An ATProto Lexicon validator for Gleam.

format

+2 -2
src/honk.gleam
··· 1 1 // Main public API for the ATProtocol lexicon validator 2 2 3 - import honk/errors as errors 4 3 import gleam/dict.{type Dict} 5 4 import gleam/json.{type Json} 6 5 import gleam/option.{None, Some} 7 6 import gleam/result 7 + import honk/errors 8 8 import honk/internal/json_helpers 9 - import honk/types as types 9 + import honk/types 10 10 import honk/validation/context 11 11 import honk/validation/formats 12 12
+1 -1
src/honk/internal/constraints.gleam
··· 1 1 // Reusable constraint validation functions 2 2 3 - import honk/errors as errors 4 3 import gleam/int 5 4 import gleam/list 6 5 import gleam/option.{type Option, Some} 7 6 import gleam/result 8 7 import gleam/string 8 + import honk/errors 9 9 10 10 /// Validates length constraints (minLength/maxLength) 11 11 pub fn validate_length_constraints(
+2 -4
src/honk/internal/json_helpers.gleam
··· 1 1 // JSON helper utilities for extracting and validating fields 2 2 3 - import honk/errors.{type ValidationError, data_validation, invalid_schema} 4 3 import gleam/dict.{type Dict} 5 4 import gleam/dynamic.{type Dynamic} 6 5 import gleam/dynamic/decode ··· 8 7 import gleam/list 9 8 import gleam/option.{type Option, None, Some} 10 9 import gleam/result 10 + import honk/errors.{type ValidationError, data_validation, invalid_schema} 11 11 12 12 /// Parse JSON string to dynamic for decoding 13 13 fn json_to_dynamic(json_value: Json) -> Result(Dynamic, String) { ··· 293 293 } 294 294 } 295 295 Error(_) -> 296 - Error(data_validation( 297 - "Failed to convert dynamic to Json", 298 - )) 296 + Error(data_validation("Failed to convert dynamic to Json")) 299 297 } 300 298 } 301 299 }
+1 -1
src/honk/internal/resolution.gleam
··· 1 1 // Reference resolution utilities 2 2 3 - import honk/errors as errors 4 3 import gleam/dict.{type Dict} 5 4 import gleam/json.{type Json} 6 5 import gleam/list ··· 8 7 import gleam/result 9 8 import gleam/set.{type Set} 10 9 import gleam/string 10 + import honk/errors 11 11 import honk/internal/json_helpers 12 12 import honk/validation/context.{type ValidationContext} 13 13
+3 -4
src/honk/validation/context.gleam
··· 1 1 // Validation context and builder 2 2 3 - import honk/errors as errors 4 3 import gleam/dict.{type Dict} 5 4 import gleam/json.{type Json} 6 5 import gleam/list ··· 8 7 import gleam/result 9 8 import gleam/set.{type Set} 10 9 import gleam/string 10 + import honk/errors 11 11 import honk/internal/json_helpers 12 - import honk/types as types 12 + import honk/types 13 13 import honk/validation/formats 14 14 15 15 /// Validation context that tracks state during validation ··· 36 36 lexicons: Dict(String, types.LexiconDoc), 37 37 // Parameters: data (Json), schema (Json), ctx (ValidationContext) 38 38 validator: Option( 39 - fn(Json, Json, ValidationContext) -> 40 - Result(Nil, errors.ValidationError), 39 + fn(Json, Json, ValidationContext) -> Result(Nil, errors.ValidationError), 41 40 ), 42 41 ) 43 42 }
+1 -1
src/honk/validation/field.gleam
··· 1 1 // Field type validators (object and array) 2 2 3 - import honk/errors as errors 4 3 import gleam/dict 5 4 import gleam/dynamic.{type Dynamic} 6 5 import gleam/dynamic/decode ··· 9 8 import gleam/list 10 9 import gleam/option.{None, Some} 11 10 import gleam/result 11 + import honk/errors 12 12 import honk/internal/constraints 13 13 import honk/internal/json_helpers 14 14 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/field/reference.gleam
··· 1 1 // Reference type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/json.{type Json} 5 4 import gleam/option.{None, Some} 6 5 import gleam/result 7 6 import gleam/string 7 + import honk/errors 8 8 import honk/internal/constraints 9 9 import honk/internal/json_helpers 10 10 import honk/internal/resolution
+1 -1
src/honk/validation/field/union.gleam
··· 1 1 // Union type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/dynamic/decode 5 4 import gleam/json.{type Json} 6 5 import gleam/list 7 6 import gleam/option.{None, Some} 8 7 import gleam/result 9 8 import gleam/string 9 + import honk/errors 10 10 import honk/internal/constraints 11 11 import honk/internal/json_helpers 12 12 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/formats.gleam
··· 4 4 import gleam/regexp 5 5 import gleam/string 6 6 import gleam/time/timestamp 7 - import honk/types as types 7 + import honk/types 8 8 9 9 /// Validates RFC3339 datetime format 10 10 pub fn is_valid_rfc3339_datetime(value: String) -> Bool {
+1 -1
src/honk/validation/meta/token.gleam
··· 1 1 // Token type validator 2 2 // Tokens are unit types used for discrimination in unions 3 3 4 - import honk/errors as errors 5 4 import gleam/json.{type Json} 6 5 import gleam/string 6 + import honk/errors 7 7 import honk/internal/constraints 8 8 import honk/internal/json_helpers 9 9 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/meta/unknown.gleam
··· 1 1 // Unknown type validator 2 2 // Unknown allows flexible data with AT Protocol data model rules 3 3 4 - import honk/errors as errors 5 4 import gleam/json.{type Json} 6 5 import gleam/option.{None, Some} 6 + import honk/errors 7 7 import honk/internal/constraints 8 8 import honk/internal/json_helpers 9 9 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primary/params.gleam
··· 2 2 // Mirrors the Go implementation's validation/primary/params 3 3 // Params define query/procedure/subscription parameters (XRPC endpoint arguments) 4 4 5 - import honk/errors as errors 6 5 import gleam/dynamic/decode 7 6 import gleam/json.{type Json} 8 7 import gleam/list 9 8 import gleam/option.{None, Some} 10 9 import gleam/result 10 + import honk/errors 11 11 import honk/internal/constraints 12 12 import honk/internal/json_helpers 13 13 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primary/procedure.gleam
··· 1 1 // Procedure type validator 2 2 // Procedures are XRPC Procedure (HTTP POST) endpoints for modifying data 3 3 4 - import honk/errors as errors 5 4 import gleam/json.{type Json} 6 5 import gleam/option.{None, Some} 7 6 import gleam/result 7 + import honk/errors 8 8 import honk/internal/constraints 9 9 import honk/internal/json_helpers 10 10 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primary/query.gleam
··· 1 1 // Query type validator 2 2 // Queries are XRPC Query (HTTP GET) endpoints for retrieving data 3 3 4 - import honk/errors as errors 5 4 import gleam/dynamic/decode 6 5 import gleam/json.{type Json} 7 6 import gleam/list 8 7 import gleam/option.{None, Some} 9 8 import gleam/result 9 + import honk/errors 10 10 import honk/internal/constraints 11 11 import honk/internal/json_helpers 12 12 import honk/validation/context.{type ValidationContext}
+5 -2
src/honk/validation/primary/record.gleam
··· 1 1 // Record type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/json.{type Json} 5 4 import gleam/option.{None, Some} 6 5 import gleam/result 7 6 import gleam/string 7 + import honk/errors 8 8 import honk/internal/constraints 9 9 import honk/internal/json_helpers 10 10 import honk/validation/context.{type ValidationContext} ··· 101 101 /// - `any`: Record key can be any valid record key format 102 102 /// - `nsid`: Record key must be a valid NSID 103 103 /// - `literal:*`: Record key must match the literal value after the colon 104 - fn validate_key(def_name: String, key: String) -> Result(Nil, errors.ValidationError) { 104 + fn validate_key( 105 + def_name: String, 106 + key: String, 107 + ) -> Result(Nil, errors.ValidationError) { 105 108 case key { 106 109 "tid" -> Ok(Nil) 107 110 "any" -> Ok(Nil)
+1 -1
src/honk/validation/primary/subscription.gleam
··· 1 1 // Subscription type validator 2 2 // Subscriptions are XRPC Subscription (WebSocket) endpoints for real-time data 3 3 4 - import honk/errors as errors 5 4 import gleam/dynamic/decode 6 5 import gleam/json.{type Json} 7 6 import gleam/list 8 7 import gleam/option.{None, Some} 9 8 import gleam/result 9 + import honk/errors 10 10 import honk/internal/constraints 11 11 import honk/internal/json_helpers 12 12 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primitive/blob.gleam
··· 1 1 // Blob type validator 2 2 // Blobs are binary objects with MIME types and size constraints 3 3 4 - import honk/errors as errors 5 4 import gleam/dynamic.{type Dynamic} 6 5 import gleam/dynamic/decode 7 6 import gleam/int ··· 10 9 import gleam/option.{None, Some} 11 10 import gleam/result 12 11 import gleam/string 12 + import honk/errors 13 13 import honk/internal/constraints 14 14 import honk/internal/json_helpers 15 15 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primitive/boolean.gleam
··· 1 1 // Boolean type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/json.{type Json} 5 4 import gleam/option.{None, Some} 6 5 import gleam/result 6 + import honk/errors 7 7 import honk/internal/constraints 8 8 import honk/internal/json_helpers 9 9 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primitive/bytes.gleam
··· 1 1 // Bytes type validator 2 2 // Bytes are base64-encoded strings 3 3 4 - import honk/errors as errors 5 4 import gleam/bit_array 6 5 import gleam/json.{type Json} 7 6 import gleam/list 8 7 import gleam/option.{None, Some} 9 8 import gleam/result 10 9 import gleam/string 10 + import honk/errors 11 11 import honk/internal/constraints 12 12 import honk/internal/json_helpers 13 13 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primitive/cid_link.gleam
··· 1 1 // CID Link type validator 2 2 // CID links are IPFS content identifiers 3 3 4 - import honk/errors as errors 5 4 import gleam/json.{type Json} 6 5 import gleam/option 6 + import honk/errors 7 7 import honk/internal/constraints 8 8 import honk/internal/json_helpers 9 9 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primitive/integer.gleam
··· 1 1 // Integer type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/dynamic/decode 5 4 import gleam/int 6 5 import gleam/json.{type Json} 7 6 import gleam/list 8 7 import gleam/option.{None, Some} 9 8 import gleam/result 9 + import honk/errors 10 10 import honk/internal/constraints 11 11 import honk/internal/json_helpers 12 12 import honk/validation/context.{type ValidationContext}
+1 -1
src/honk/validation/primitive/null.gleam
··· 1 1 // Null type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/json.{type Json} 4 + import honk/errors 5 5 import honk/internal/constraints 6 6 import honk/internal/json_helpers 7 7 import honk/validation/context.{type ValidationContext}
+2 -2
src/honk/validation/primitive/string.gleam
··· 1 1 // String type validator 2 2 3 - import honk/errors as errors 4 3 import gleam/dynamic/decode 5 4 import gleam/json.{type Json} 6 5 import gleam/list 7 6 import gleam/option.{type Option, None, Some} 8 7 import gleam/result 9 8 import gleam/string 9 + import honk/errors 10 10 import honk/internal/constraints 11 11 import honk/internal/json_helpers 12 - import honk/types as types 12 + import honk/types 13 13 import honk/validation/context.{type ValidationContext} 14 14 import honk/validation/formats 15 15