@atproto/lex-schema 0.0.15 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # @atproto/lex-schema
2
2
 
3
+ ## 0.0.16
4
+
5
+ ### Patch Changes
6
+
7
+ - [#4761](https://github.com/bluesky-social/atproto/pull/4761) [`6a88461`](https://github.com/bluesky-social/atproto/commit/6a88461c5aa9486269f0769b7a3d52f384581786) Thanks [@matthieusieben](https://github.com/matthieusieben)! - Allow using a dynamic non-strict validation mode
8
+
9
+ - Updated dependencies [[`6a88461`](https://github.com/bluesky-social/atproto/commit/6a88461c5aa9486269f0769b7a3d52f384581786)]:
10
+ - @atproto/lex-data@0.0.14
11
+
3
12
  ## 0.0.15
4
13
 
5
14
  ### Patch Changes
@@ -34,7 +34,7 @@ export interface SchemaInternals<out TInput = unknown, out TOutput = TInput> {
34
34
  * - **Assertion methods**: `assert()`, `check()` - throw on invalid input
35
35
  * - **Type guard methods**: `matches()`, `ifMatches()` - return boolean or optional value
36
36
  * - **Parse methods**: `parse()`, `safeParse()` - allow value transformation/coercion
37
- * - **Validate methods**: `validate()`, `safeValidate()` - strict validation without coercion
37
+ * - **Validate methods**: `validate()`, `safeValidate()` - validation without coercion
38
38
  *
39
39
  * All methods are also available with a `$` prefix (e.g., `$parse()`, `$validate()`)
40
40
  * for consistent access in generated lexicon namespaces.
@@ -13,7 +13,7 @@ const validator_js_1 = require("./validator.js");
13
13
  * - **Assertion methods**: `assert()`, `check()` - throw on invalid input
14
14
  * - **Type guard methods**: `matches()`, `ifMatches()` - return boolean or optional value
15
15
  * - **Parse methods**: `parse()`, `safeParse()` - allow value transformation/coercion
16
- * - **Validate methods**: `validate()`, `safeValidate()` - strict validation without coercion
16
+ * - **Validate methods**: `validate()`, `safeValidate()` - validation without coercion
17
17
  *
18
18
  * All methods are also available with a `$` prefix (e.g., `$parse()`, `$validate()`)
19
19
  * for consistent access in generated lexicon namespaces.
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":";;;AACA,+DAAuD;AACvD,6DAA4D;AAC5D,iDAOuB;AA8BvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAsB,MAAM;IAW1B,IAAI,WAAW;QACb,wEAAwE;QACxE,YAAY;QACZ,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,WAAW,EAAE,IAAI,0CAAqB,CAAC,IAAI,CAAC,CAAC,CAAA;IACzE,CAAC;IA0BD;;;;;OAKG;IACH,MAAM,CAAC,KAAc;QACnB,MAAM,MAAM,GAAG,gCAAiB,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACtD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,MAAM,MAAM,CAAC,MAAM,CAAA;IAC1C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,KAAc;QAClB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAI,KAAQ;QACd,MAAM,MAAM,GAAG,gCAAiB,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACtD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,KAAK,CAAA;QACvC,MAAM,MAAM,CAAC,MAAM,CAAA;IACrB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAI,KAAQ;QACjB,MAAM,MAAM,GAAG,gCAAiB,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QACtD,OAAO,MAAM,CAAC,OAAO,CAAA;IACvB,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,SAAS,CAAI,KAAQ;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAA;IAChD,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,KAAc,EAAE,OAAsB;QAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAC7C,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,KAAK,CAAA;QACvC,MAAM,MAAM,CAAC,MAAM,CAAA;IACrB,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CACP,KAAc,EACd,OAAsB;QAEtB,OAAO,gCAAiB,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE;YAC7C,GAAG,OAAO;YACV,IAAI,EAAE,OAAO;SACd,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,QAAQ,CAAI,KAAQ,EAAE,OAAyB;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAChD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC,KAAK,CAAA;QACvC,MAAM,MAAM,CAAC,MAAM,CAAA;IACrB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,YAAY,CACV,KAAQ,EACR,OAAyB;QAEzB,OAAO,gCAAiB,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE;YAC7C,GAAG,OAAO;YACV,IAAI,EAAE,UAAU;SACjB,CAAC,CAAA;IACJ,CAAC;IAED,gCAAgC;IAChC,EAAE;IACF,0EAA0E;IAC1E,0EAA0E;IAC1E,4EAA4E;IAC5E,gEAAgE;IAChE,yCAAyC;IACzC,EAAE;IACF,8EAA8E;IAC9E,8EAA8E;IAC9E,uCAAuC;IACvC,EAAE;IACF,2EAA2E;IAC3E,4EAA4E;IAC5E,8EAA8E;IAC9E,yDAAyD;IACzD,EAAE;IACF,4EAA4E;IAC5E,8EAA8E;IAC9E,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,EAAE;IACF,0EAA0E;IAC1E,0EAA0E;IAC1E,qBAAqB;IACrB,EAAE;IACF,oEAAoE;IACpE,8EAA8E;IAC9E,qCAAqC;IACrC,6EAA6E;IAC7E,0CAA0C;IAC1C,EAAE;IACF,8EAA8E;IAC9E,yEAAyE;IACzE,uEAAuE;IACvE,oDAAoD;IAEpD;;;OAGG;IACH,IAAI,OAAO;QACT,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC9D,CAAC;IAED;;;OAGG;IACH,IAAI,MAAM;QACR,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5D,CAAC;IAED;;;OAGG;IACH,IAAI,KAAK;QACP,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1D,CAAC;IAED;;;OAGG;IACH,IAAI,QAAQ;QACV,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAChE,CAAC;IAED;;;OAGG;IACH,IAAI,UAAU;QACZ,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpE,CAAC;IAED;;;OAGG;IACH,IAAI,MAAM;QACR,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC5D,CAAC;IAED;;;OAGG;IACH,IAAI,UAAU;QACZ,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACpE,CAAC;IAED;;;OAGG;IACH,IAAI,SAAS;QACX,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAClE,CAAC;IAED;;;OAGG;IACH,IAAI,aAAa;QACf,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1E,CAAC;CACF;AA7UD,wBA6UC","sourcesContent":["import { StandardSchemaV1 } from '@standard-schema/spec'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { StandardSchemaAdapter } from './standard-schema.js'\nimport {\n InferInput,\n InferOutput,\n ValidationContext,\n ValidationOptions,\n ValidationResult,\n Validator,\n} from './validator.js'\n\n/**\n * Options for parsing operations.\n * Excludes the `mode` option as it is implicitly set to `\"parse\"`.\n */\nexport type ParseOptions = Omit<ValidationOptions, 'mode'>\n\n/**\n * Options for validation operations.\n * Excludes the `mode` option as it is implicitly set to `\"validate\"`.\n */\nexport type ValidateOptions = Omit<ValidationOptions, 'mode'>\n\n/**\n * Internal type structure for schema type inference.\n *\n * This interface defines the phantom types used for compile-time type inference\n * without affecting runtime behavior. The `input` and `output` properties\n * represent the expected input type during validation and the resulting output\n * type after parsing, respectively.\n *\n * @typeParam TInput - The type accepted as input during validation\n * @typeParam TOutput - The type returned after parsing (may differ from input due to coercion)\n */\nexport interface SchemaInternals<out TInput = unknown, out TOutput = TInput> {\n input: TInput\n output: TOutput\n}\n\n/**\n * Abstract base class for all schema validators in the lexicon system.\n *\n * This class provides the standard validation interface that all schema types\n * implement. It offers multiple methods for validating and parsing data:\n *\n * - **Assertion methods**: `assert()`, `check()` - throw on invalid input\n * - **Type guard methods**: `matches()`, `ifMatches()` - return boolean or optional value\n * - **Parse methods**: `parse()`, `safeParse()` - allow value transformation/coercion\n * - **Validate methods**: `validate()`, `safeValidate()` - strict validation without coercion\n *\n * All methods are also available with a `$` prefix (e.g., `$parse()`, `$validate()`)\n * for consistent access in generated lexicon namespaces.\n *\n * @typeParam TInput - The type accepted as valid input during validation\n * @typeParam TOutput - The type returned after parsing (may include transformations)\n *\n * @example\n * ```typescript\n * class MySchema extends Schema<string> {\n * validateInContext(input: unknown, ctx: ValidationContext): ValidationResult {\n * if (typeof input !== 'string') {\n * return ctx.issueUnexpectedType(input, 'string')\n * }\n * return ctx.success(input)\n * }\n * }\n *\n * const schema = new MySchema()\n * schema.assert('hello') // OK\n * schema.assert(123) // Throws LexValidationError\n * schema.matches('hello') // true\n * schema.matches(123) // false\n * ```\n */\nexport abstract class Schema<out TInput = unknown, out TOutput = TInput>\n implements Validator<TInput, TOutput>, StandardSchemaV1<TInput, TOutput>\n{\n /**\n * Internal phantom property for type inference.\n * This property does not exist at runtime.\n *\n * @internal\n */\n declare readonly ['__lex']: SchemaInternals<TInput, TOutput>\n\n get '~standard'(): StandardSchemaV1.Props<TInput, TOutput> {\n // Lazily create, and cache, the Standard Schema adapter for this schema\n // instance.\n return lazyProperty(this, '~standard', new StandardSchemaAdapter(this))\n }\n\n // Needed to discriminate multiple schema types when used in unions. Without\n // this, Typescript could allow an EnumSchema<\"foo\" | \"bar\"> to be used where\n // a StringSchema is expected, since they would both be structurally\n // compatible.\n abstract readonly type: string\n\n /**\n * Performs validation of the input value within a validation context.\n *\n * This method must be implemented by subclasses to define the actual\n * validation logic. It should not be called directly; use\n * {@link ValidationContext.validate} instead to ensure proper mode enforcement.\n *\n * @param input - The value to validate\n * @param ctx - The validation context providing path tracking and issue reporting\n * @returns A validation result indicating success with the validated value or failure with issues\n *\n * @internal\n */\n abstract validateInContext(\n input: unknown,\n ctx: ValidationContext,\n ): ValidationResult\n\n /**\n * @note use {@link check}() instead of {@link assert}() if you encounter a\n * `ts(2775)` error and you are not able to fully type the validator. This\n * will typically arise in generic contexts, where the narrowed type is not\n * needed.\n */\n assert(input: unknown): asserts input is InferInput<this> {\n const result = ValidationContext.validate(input, this)\n if (!result.success) throw result.reason\n }\n\n /**\n * Alias for {@link assert}(). Most useful in generic contexts where the\n * validator is not exactly typed, allowing to avoid \"_Assertions require\n * every name in the call target to be declared with an explicit type\n * annotation. ts(2775)_\" errors.\n */\n check(input: unknown): void {\n this.assert(input)\n }\n\n /**\n * Casts the input (by validating it) to the output type if it matches the\n * schema, otherwise throws. This is the same as calling {@link parse}() with\n * `mode: \"validate\"`.\n */\n cast<I>(input: I): I & InferInput<this> {\n const result = ValidationContext.validate(input, this)\n if (result.success) return result.value\n throw result.reason\n }\n\n /**\n * Type guard that checks if the input matches this schema.\n *\n * @param input - The value to check\n * @returns `true` if the input is valid according to this schema\n *\n * @example\n * ```typescript\n * if (schema.matches(data)) {\n * // data is narrowed to the schema's input type\n * console.log(data)\n * }\n * ```\n */\n matches<I>(input: I): input is I & InferInput<this> {\n const result = ValidationContext.validate(input, this)\n return result.success\n }\n\n /**\n * Returns the input if it matches this schema, otherwise returns `undefined`.\n *\n * This is useful for optional filtering operations where you want to\n * conditionally extract values that match a schema.\n *\n * @param input - The value to check\n * @returns The input value with narrowed type if valid, otherwise `undefined`\n *\n * @example\n * ```typescript\n * const validData = schema.ifMatches(data)\n * if (validData !== undefined) {\n * // validData is the schema's input type\n * console.log(validData)\n * }\n * ```\n */\n ifMatches<I>(input: I): (I & InferInput<this>) | undefined {\n return this.matches(input) ? input : undefined\n }\n\n /**\n * Parses the input, allowing value transformations and coercion.\n *\n * Unlike {@link validate}, this method allows the schema to transform\n * the input value (e.g., applying default values, type coercion).\n * Throws a {@link LexValidationError} if the input is invalid.\n *\n * @param input - The value to parse\n * @param options - Optional parsing configuration\n * @returns The parsed and potentially transformed value\n * @throws {LexValidationError} If the input fails validation\n *\n * @example\n * ```typescript\n * const result = schema.parse(rawData)\n * // result has defaults applied and is fully typed\n * ```\n */\n parse(input: unknown, options?: ParseOptions): InferOutput<this> {\n const result = this.safeParse(input, options)\n if (result.success) return result.value\n throw result.reason\n }\n\n /**\n * Safely parses the input without throwing, returning a result object.\n *\n * This method allows value transformations like {@link parse}, but\n * returns a discriminated union result instead of throwing on error.\n *\n * @param input - The value to parse\n * @param options - Optional parsing configuration\n * @returns A {@link ValidationResult} with either the parsed value or validation errors\n *\n * @example\n * ```typescript\n * const result = schema.safeParse(data)\n * if (result.success) {\n * console.log(result.value)\n * } else {\n * console.error(result.reason.issues)\n * }\n * ```\n */\n safeParse(\n input: unknown,\n options?: ParseOptions,\n ): ValidationResult<InferOutput<this>> {\n return ValidationContext.validate(input, this, {\n ...options,\n mode: 'parse',\n })\n }\n\n /**\n * Validates the input strictly without allowing transformations.\n *\n * Unlike {@link parse}, this method requires the input to exactly match\n * the schema without any transformations (no defaults applied, no coercion).\n * Throws a {@link LexValidationError} if the input is invalid or would require transformation.\n *\n * @typeParam I - The input type (preserved in the return type)\n * @param input - The value to validate\n * @param options - Optional validation configuration\n * @returns The validated input with narrowed type\n * @throws {LexValidationError} If the input fails validation or requires transformation\n *\n * @example\n * ```typescript\n * const validated = schema.validate(data)\n * // validated is typed as the intersection of input type and schema type\n * ```\n */\n validate<I>(input: I, options?: ValidateOptions): I & InferInput<this> {\n const result = this.safeValidate(input, options)\n if (result.success) return result.value\n throw result.reason\n }\n\n /**\n * Safely validates the input without throwing, returning a result object.\n *\n * This method performs strict validation like {@link validate}, but\n * returns a discriminated union result instead of throwing on error.\n *\n * @typeParam I - The input type (preserved in the result value type)\n * @param input - The value to validate\n * @param options - Optional validation configuration\n * @returns A {@link ValidationResult} with either the validated value or validation errors\n *\n * @example\n * ```typescript\n * const result = schema.safeValidate(data)\n * if (result.success) {\n * console.log(result.value)\n * } else {\n * console.error(result.reason.issues)\n * }\n * ```\n */\n safeValidate<I>(\n input: I,\n options?: ValidateOptions,\n ): ValidationResult<I & InferInput<this>> {\n return ValidationContext.validate(input, this, {\n ...options,\n mode: 'validate',\n })\n }\n\n // @NOTE Dollar-prefixed aliases\n //\n // The `lex-builder` lib generates namespaced utility functions that allow\n // accessing the schema's methods without the need to specify the \".main.\"\n // part of the namespace. This allows utilities for a particular record type\n // to be called like \"app.bsky.feed.post.<utility>()\" instead of\n // \"app.bsky.feed.post.main.<utility>()\".\n //\n // Because those utilities could conflict with other schemas (e.g. if there is\n // a lexicon definition with the same name as the \"<utility>\"), those exported\n // utilities will be prefixed with \"$\".\n //\n // Similarly, since those utilities are defined as simple \"const\", they are\n // also bound (using JS's .bind) to the schema instance, so that they can be\n // used without worrying about the context (e.g. \"app.bsky.feed.post.$parse()\"\n // will work regardless of how it is imported or called).\n //\n // In order to provide the same functionalities for non-main definitions, we\n // also define those aliases directly on the schema instance, so that they can\n // be used in the same way as the utilities generated by \"lex-builder\". For\n // example, if there is a non-main definition \"app.bsky.feed.defs.postView\",\n // it will also be possible to call \"app.bsky.feed.defs.postView.$parse()\".\n //\n // These methods are also \"bound\" to the instance so that they can be used\n // exactly like the utilities generated by \"lex-builder\", without worrying\n // about the context.\n //\n // There are two ways we could \"bind\" those methods to the instance:\n // 1. Define them as getters that return the bound method (e.g. get $parse() {\n // return this.parse.bind(this) })\n // 2. Define them as properties that are initialized in the constructor (e.g.\n // this.$parse = this.parse.bind(this))\n //\n // Since a **lot** of those methods would end-up being created in systems that\n // contains many schemas (e.g. the appview), we choose the first approach\n // (getters) in order to avoid the overhead of creating all those bound\n // functions upfront when instantiating the schemas.\n\n /**\n * Bound alias for {@link assert} for compatibility with generated utilities.\n * @see {@link assert}\n */\n get $assert(): typeof this.assert {\n return lazyProperty(this, '$assert', this.assert.bind(this))\n }\n\n /**\n * Bound alias for {@link check} for compatibility with generated utilities.\n * @see {@link check}\n */\n get $check(): typeof this.check {\n return lazyProperty(this, '$check', this.check.bind(this))\n }\n\n /**\n * Bound alias for {@link cast} for compatibility with generated utilities.\n * @see {@link cast}\n */\n get $cast(): typeof this.cast {\n return lazyProperty(this, '$cast', this.cast.bind(this))\n }\n\n /**\n * Bound alias for {@link matches} for compatibility with generated utilities.\n * @see {@link matches}\n */\n get $matches(): typeof this.matches {\n return lazyProperty(this, '$matches', this.matches.bind(this))\n }\n\n /**\n * Bound alias for {@link ifMatches} for compatibility with generated utilities.\n * @see {@link ifMatches}\n */\n get $ifMatches(): typeof this.ifMatches {\n return lazyProperty(this, '$ifMatches', this.ifMatches.bind(this))\n }\n\n /**\n * Bound alias for {@link parse} for compatibility with generated utilities.\n * @see {@link parse}\n */\n get $parse(): typeof this.parse {\n return lazyProperty(this, '$parse', this.parse.bind(this))\n }\n\n /**\n * Bound alias for {@link safeParse} for compatibility with generated utilities.\n * @see {@link safeParse}\n */\n get $safeParse(): typeof this.safeParse {\n return lazyProperty(this, '$safeParse', this.safeParse.bind(this))\n }\n\n /**\n * Bound alias for {@link validate} for compatibility with generated utilities.\n * @see {@link validate}\n */\n get $validate(): typeof this.validate {\n return lazyProperty(this, '$validate', this.validate.bind(this))\n }\n\n /**\n * Bound alias for {@link safeValidate} for compatibility with generated utilities.\n * @see {@link safeValidate}\n */\n get $safeValidate(): typeof this.safeValidate {\n return lazyProperty(this, '$safeValidate', this.safeValidate.bind(this))\n }\n}\n"]}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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","sourcesContent":["import { StandardSchemaV1 } from '@standard-schema/spec'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { StandardSchemaAdapter } from './standard-schema.js'\nimport {\n InferInput,\n InferOutput,\n ValidationContext,\n ValidationOptions,\n ValidationResult,\n Validator,\n} from './validator.js'\n\n/**\n * Options for parsing operations.\n * Excludes the `mode` option as it is implicitly set to `\"parse\"`.\n */\nexport type ParseOptions = Omit<ValidationOptions, 'mode'>\n\n/**\n * Options for validation operations.\n * Excludes the `mode` option as it is implicitly set to `\"validate\"`.\n */\nexport type ValidateOptions = Omit<ValidationOptions, 'mode'>\n\n/**\n * Internal type structure for schema type inference.\n *\n * This interface defines the phantom types used for compile-time type inference\n * without affecting runtime behavior. The `input` and `output` properties\n * represent the expected input type during validation and the resulting output\n * type after parsing, respectively.\n *\n * @typeParam TInput - The type accepted as input during validation\n * @typeParam TOutput - The type returned after parsing (may differ from input due to coercion)\n */\nexport interface SchemaInternals<out TInput = unknown, out TOutput = TInput> {\n input: TInput\n output: TOutput\n}\n\n/**\n * Abstract base class for all schema validators in the lexicon system.\n *\n * This class provides the standard validation interface that all schema types\n * implement. It offers multiple methods for validating and parsing data:\n *\n * - **Assertion methods**: `assert()`, `check()` - throw on invalid input\n * - **Type guard methods**: `matches()`, `ifMatches()` - return boolean or optional value\n * - **Parse methods**: `parse()`, `safeParse()` - allow value transformation/coercion\n * - **Validate methods**: `validate()`, `safeValidate()` - validation without coercion\n *\n * All methods are also available with a `$` prefix (e.g., `$parse()`, `$validate()`)\n * for consistent access in generated lexicon namespaces.\n *\n * @typeParam TInput - The type accepted as valid input during validation\n * @typeParam TOutput - The type returned after parsing (may include transformations)\n *\n * @example\n * ```typescript\n * class MySchema extends Schema<string> {\n * validateInContext(input: unknown, ctx: ValidationContext): ValidationResult {\n * if (typeof input !== 'string') {\n * return ctx.issueUnexpectedType(input, 'string')\n * }\n * return ctx.success(input)\n * }\n * }\n *\n * const schema = new MySchema()\n * schema.assert('hello') // OK\n * schema.assert(123) // Throws LexValidationError\n * schema.matches('hello') // true\n * schema.matches(123) // false\n * ```\n */\nexport abstract class Schema<out TInput = unknown, out TOutput = TInput>\n implements Validator<TInput, TOutput>, StandardSchemaV1<TInput, TOutput>\n{\n /**\n * Internal phantom property for type inference.\n * This property does not exist at runtime.\n *\n * @internal\n */\n declare readonly ['__lex']: SchemaInternals<TInput, TOutput>\n\n get '~standard'(): StandardSchemaV1.Props<TInput, TOutput> {\n // Lazily create, and cache, the Standard Schema adapter for this schema\n // instance.\n return lazyProperty(this, '~standard', new StandardSchemaAdapter(this))\n }\n\n // Needed to discriminate multiple schema types when used in unions. Without\n // this, Typescript could allow an EnumSchema<\"foo\" | \"bar\"> to be used where\n // a StringSchema is expected, since they would both be structurally\n // compatible.\n abstract readonly type: string\n\n /**\n * Performs validation of the input value within a validation context.\n *\n * This method must be implemented by subclasses to define the actual\n * validation logic. It should not be called directly; use\n * {@link ValidationContext.validate} instead to ensure proper mode enforcement.\n *\n * @param input - The value to validate\n * @param ctx - The validation context providing path tracking and issue reporting\n * @returns A validation result indicating success with the validated value or failure with issues\n *\n * @internal\n */\n abstract validateInContext(\n input: unknown,\n ctx: ValidationContext,\n ): ValidationResult\n\n /**\n * @note use {@link check}() instead of {@link assert}() if you encounter a\n * `ts(2775)` error and you are not able to fully type the validator. This\n * will typically arise in generic contexts, where the narrowed type is not\n * needed.\n */\n assert(input: unknown): asserts input is InferInput<this> {\n const result = ValidationContext.validate(input, this)\n if (!result.success) throw result.reason\n }\n\n /**\n * Alias for {@link assert}(). Most useful in generic contexts where the\n * validator is not exactly typed, allowing to avoid \"_Assertions require\n * every name in the call target to be declared with an explicit type\n * annotation. ts(2775)_\" errors.\n */\n check(input: unknown): void {\n this.assert(input)\n }\n\n /**\n * Casts the input (by validating it) to the output type if it matches the\n * schema, otherwise throws. This is the same as calling {@link parse}() with\n * `mode: \"validate\"`.\n */\n cast<I>(input: I): I & InferInput<this> {\n const result = ValidationContext.validate(input, this)\n if (result.success) return result.value\n throw result.reason\n }\n\n /**\n * Type guard that checks if the input matches this schema.\n *\n * @param input - The value to check\n * @returns `true` if the input is valid according to this schema\n *\n * @example\n * ```typescript\n * if (schema.matches(data)) {\n * // data is narrowed to the schema's input type\n * console.log(data)\n * }\n * ```\n */\n matches<I>(input: I): input is I & InferInput<this> {\n const result = ValidationContext.validate(input, this)\n return result.success\n }\n\n /**\n * Returns the input if it matches this schema, otherwise returns `undefined`.\n *\n * This is useful for optional filtering operations where you want to\n * conditionally extract values that match a schema.\n *\n * @param input - The value to check\n * @returns The input value with narrowed type if valid, otherwise `undefined`\n *\n * @example\n * ```typescript\n * const validData = schema.ifMatches(data)\n * if (validData !== undefined) {\n * // validData is the schema's input type\n * console.log(validData)\n * }\n * ```\n */\n ifMatches<I>(input: I): (I & InferInput<this>) | undefined {\n return this.matches(input) ? input : undefined\n }\n\n /**\n * Parses the input, allowing value transformations and coercion.\n *\n * Unlike {@link validate}, this method allows the schema to transform\n * the input value (e.g., applying default values, type coercion).\n * Throws a {@link LexValidationError} if the input is invalid.\n *\n * @param input - The value to parse\n * @param options - Optional parsing configuration\n * @returns The parsed and potentially transformed value\n * @throws {LexValidationError} If the input fails validation\n *\n * @example\n * ```typescript\n * const result = schema.parse(rawData)\n * // result has defaults applied and is fully typed\n * ```\n */\n parse(input: unknown, options?: ParseOptions): InferOutput<this> {\n const result = this.safeParse(input, options)\n if (result.success) return result.value\n throw result.reason\n }\n\n /**\n * Safely parses the input without throwing, returning a result object.\n *\n * This method allows value transformations like {@link parse}, but\n * returns a discriminated union result instead of throwing on error.\n *\n * @param input - The value to parse\n * @param options - Optional parsing configuration\n * @returns A {@link ValidationResult} with either the parsed value or validation errors\n *\n * @example\n * ```typescript\n * const result = schema.safeParse(data)\n * if (result.success) {\n * console.log(result.value)\n * } else {\n * console.error(result.reason.issues)\n * }\n * ```\n */\n safeParse(\n input: unknown,\n options?: ParseOptions,\n ): ValidationResult<InferOutput<this>> {\n return ValidationContext.validate(input, this, {\n ...options,\n mode: 'parse',\n })\n }\n\n /**\n * Validates the input strictly without allowing transformations.\n *\n * Unlike {@link parse}, this method requires the input to exactly match\n * the schema without any transformations (no defaults applied, no coercion).\n * Throws a {@link LexValidationError} if the input is invalid or would require transformation.\n *\n * @typeParam I - The input type (preserved in the return type)\n * @param input - The value to validate\n * @param options - Optional validation configuration\n * @returns The validated input with narrowed type\n * @throws {LexValidationError} If the input fails validation or requires transformation\n *\n * @example\n * ```typescript\n * const validated = schema.validate(data)\n * // validated is typed as the intersection of input type and schema type\n * ```\n */\n validate<I>(input: I, options?: ValidateOptions): I & InferInput<this> {\n const result = this.safeValidate(input, options)\n if (result.success) return result.value\n throw result.reason\n }\n\n /**\n * Safely validates the input without throwing, returning a result object.\n *\n * This method performs strict validation like {@link validate}, but\n * returns a discriminated union result instead of throwing on error.\n *\n * @typeParam I - The input type (preserved in the result value type)\n * @param input - The value to validate\n * @param options - Optional validation configuration\n * @returns A {@link ValidationResult} with either the validated value or validation errors\n *\n * @example\n * ```typescript\n * const result = schema.safeValidate(data)\n * if (result.success) {\n * console.log(result.value)\n * } else {\n * console.error(result.reason.issues)\n * }\n * ```\n */\n safeValidate<I>(\n input: I,\n options?: ValidateOptions,\n ): ValidationResult<I & InferInput<this>> {\n return ValidationContext.validate(input, this, {\n ...options,\n mode: 'validate',\n })\n }\n\n // @NOTE Dollar-prefixed aliases\n //\n // The `lex-builder` lib generates namespaced utility functions that allow\n // accessing the schema's methods without the need to specify the \".main.\"\n // part of the namespace. This allows utilities for a particular record type\n // to be called like \"app.bsky.feed.post.<utility>()\" instead of\n // \"app.bsky.feed.post.main.<utility>()\".\n //\n // Because those utilities could conflict with other schemas (e.g. if there is\n // a lexicon definition with the same name as the \"<utility>\"), those exported\n // utilities will be prefixed with \"$\".\n //\n // Similarly, since those utilities are defined as simple \"const\", they are\n // also bound (using JS's .bind) to the schema instance, so that they can be\n // used without worrying about the context (e.g. \"app.bsky.feed.post.$parse()\"\n // will work regardless of how it is imported or called).\n //\n // In order to provide the same functionalities for non-main definitions, we\n // also define those aliases directly on the schema instance, so that they can\n // be used in the same way as the utilities generated by \"lex-builder\". For\n // example, if there is a non-main definition \"app.bsky.feed.defs.postView\",\n // it will also be possible to call \"app.bsky.feed.defs.postView.$parse()\".\n //\n // These methods are also \"bound\" to the instance so that they can be used\n // exactly like the utilities generated by \"lex-builder\", without worrying\n // about the context.\n //\n // There are two ways we could \"bind\" those methods to the instance:\n // 1. Define them as getters that return the bound method (e.g. get $parse() {\n // return this.parse.bind(this) })\n // 2. Define them as properties that are initialized in the constructor (e.g.\n // this.$parse = this.parse.bind(this))\n //\n // Since a **lot** of those methods would end-up being created in systems that\n // contains many schemas (e.g. the appview), we choose the first approach\n // (getters) in order to avoid the overhead of creating all those bound\n // functions upfront when instantiating the schemas.\n\n /**\n * Bound alias for {@link assert} for compatibility with generated utilities.\n * @see {@link assert}\n */\n get $assert(): typeof this.assert {\n return lazyProperty(this, '$assert', this.assert.bind(this))\n }\n\n /**\n * Bound alias for {@link check} for compatibility with generated utilities.\n * @see {@link check}\n */\n get $check(): typeof this.check {\n return lazyProperty(this, '$check', this.check.bind(this))\n }\n\n /**\n * Bound alias for {@link cast} for compatibility with generated utilities.\n * @see {@link cast}\n */\n get $cast(): typeof this.cast {\n return lazyProperty(this, '$cast', this.cast.bind(this))\n }\n\n /**\n * Bound alias for {@link matches} for compatibility with generated utilities.\n * @see {@link matches}\n */\n get $matches(): typeof this.matches {\n return lazyProperty(this, '$matches', this.matches.bind(this))\n }\n\n /**\n * Bound alias for {@link ifMatches} for compatibility with generated utilities.\n * @see {@link ifMatches}\n */\n get $ifMatches(): typeof this.ifMatches {\n return lazyProperty(this, '$ifMatches', this.ifMatches.bind(this))\n }\n\n /**\n * Bound alias for {@link parse} for compatibility with generated utilities.\n * @see {@link parse}\n */\n get $parse(): typeof this.parse {\n return lazyProperty(this, '$parse', this.parse.bind(this))\n }\n\n /**\n * Bound alias for {@link safeParse} for compatibility with generated utilities.\n * @see {@link safeParse}\n */\n get $safeParse(): typeof this.safeParse {\n return lazyProperty(this, '$safeParse', this.safeParse.bind(this))\n }\n\n /**\n * Bound alias for {@link validate} for compatibility with generated utilities.\n * @see {@link validate}\n */\n get $validate(): typeof this.validate {\n return lazyProperty(this, '$validate', this.validate.bind(this))\n }\n\n /**\n * Bound alias for {@link safeValidate} for compatibility with generated utilities.\n * @see {@link safeValidate}\n */\n get $safeValidate(): typeof this.safeValidate {\n return lazyProperty(this, '$safeValidate', this.safeValidate.bind(this))\n }\n}\n"]}
@@ -3,6 +3,12 @@ import { CheckFn } from '../util/assertion-util.js';
3
3
  export { type AtIdentifierString, asAtIdentifierString, ifAtIdentifierString, isAtIdentifierString, } from '@atproto/syntax';
4
4
  export { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax';
5
5
  export { type DatetimeString, asDatetimeString, ifDatetimeString, isDatetimeString, } from '@atproto/syntax';
6
+ /**
7
+ * Matches any ISO-ish datetime string. This is a more lenient check than
8
+ * the strict {@link isDatetimeString} guard, which only allows datetimes that
9
+ * fully conform to the AT Protocol specification (e.g. must include timezone).
10
+ */
11
+ export declare function isDatetimeStringLoose<I>(input: I): input is I & DatetimeString;
6
12
  export { currentDatetimeString, toDatetimeString } from '@atproto/syntax';
7
13
  /**
8
14
  * Type guard that checks if a value is a valid AT URI.
@@ -153,6 +159,18 @@ type StringFormats = {
153
159
  * Union type of all valid string format names.
154
160
  */
155
161
  export type StringFormat = Extract<keyof StringFormats, string>;
162
+ export type StringFormatValidationOptions = {
163
+ /**
164
+ * Allows to be more lenient in validation by using a "loose" verification
165
+ * function, if available. The behavior of the loose verifier depends on the
166
+ * specific format, but generally it may allow for a wider range of valid
167
+ * inputs, including values that are not compliant with the AT Protocol
168
+ * specification.
169
+ *
170
+ * @default true
171
+ */
172
+ strict?: boolean;
173
+ };
156
174
  /**
157
175
  * Infers the string type for a given format name.
158
176
  *
@@ -183,7 +201,7 @@ export type InferStringFormat<F extends StringFormat> = F extends StringFormat ?
183
201
  * }
184
202
  * ```
185
203
  */
186
- export declare function isStringFormat<I extends string, F extends StringFormat>(input: I, format: F): input is I & StringFormats[F];
204
+ export declare function isStringFormat<I extends string, F extends StringFormat>(input: I, format: F, options?: StringFormatValidationOptions): input is I & StringFormats[F];
187
205
  /**
188
206
  * Asserts that a string matches a specific format, throwing if invalid.
189
207
  *
@@ -199,7 +217,7 @@ export declare function isStringFormat<I extends string, F extends StringFormat>
199
217
  * // value is now typed as HandleString
200
218
  * ```
201
219
  */
202
- export declare function assertStringFormat<I extends string, F extends StringFormat>(input: I, format: F): asserts input is I & StringFormats[F];
220
+ export declare function assertStringFormat<I extends string, F extends StringFormat>(input: I, format: F, options?: StringFormatValidationOptions): asserts input is I & StringFormats[F];
203
221
  /**
204
222
  * Validates and returns a string as the specified format type, throwing if invalid.
205
223
  *
@@ -218,7 +236,7 @@ export declare function assertStringFormat<I extends string, F extends StringFor
218
236
  * // did is typed as DidString
219
237
  * ```
220
238
  */
221
- export declare function asStringFormat<I extends string, F extends StringFormat>(input: I, format: F): I & StringFormats[F];
239
+ export declare function asStringFormat<I extends string, F extends StringFormat>(input: I, format: F, options?: StringFormatValidationOptions): I & StringFormats[F];
222
240
  /**
223
241
  * Returns the string as the format type if valid, otherwise returns `undefined`.
224
242
  *
@@ -239,7 +257,7 @@ export declare function asStringFormat<I extends string, F extends StringFormat>
239
257
  * }
240
258
  * ```
241
259
  */
242
- export declare function ifStringFormat<I extends string, F extends StringFormat>(input: I, format: F): undefined | (I & StringFormats[F]);
260
+ export declare function ifStringFormat<I extends string, F extends StringFormat>(input: I, format: F, options?: StringFormatValidationOptions): undefined | (I & StringFormats[F]);
243
261
  /**
244
262
  * Array of all valid string format names.
245
263
  *
@@ -1 +1 @@
1
- {"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"string-format.d.ts","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.STRING_FORMATS = exports.isUriString = exports.isTidString = exports.isRecordKeyString = exports.isNsidString = exports.isLanguageString = exports.isHandleString = exports.isDidString = exports.isCidString = exports.isAtUriString = exports.toDatetimeString = exports.currentDatetimeString = exports.isDatetimeString = exports.ifDatetimeString = exports.asDatetimeString = exports.isHandleIdentifier = exports.isDidIdentifier = exports.isAtIdentifierString = exports.ifAtIdentifierString = exports.asAtIdentifierString = void 0;
4
+ exports.isDatetimeStringLoose = isDatetimeStringLoose;
4
5
  exports.isStringFormat = isStringFormat;
5
6
  exports.assertStringFormat = assertStringFormat;
6
7
  exports.asStringFormat = asStringFormat;
7
8
  exports.ifStringFormat = ifStringFormat;
9
+ const iso_datestring_validator_1 = require("iso-datestring-validator");
8
10
  const lex_data_1 = require("@atproto/lex-data");
9
11
  const syntax_1 = require("@atproto/syntax");
10
12
  // -----------------------------------------------------------------------------
@@ -26,6 +28,25 @@ var syntax_4 = require("@atproto/syntax");
26
28
  Object.defineProperty(exports, "asDatetimeString", { enumerable: true, get: function () { return syntax_4.asDatetimeString; } });
27
29
  Object.defineProperty(exports, "ifDatetimeString", { enumerable: true, get: function () { return syntax_4.ifDatetimeString; } });
28
30
  Object.defineProperty(exports, "isDatetimeString", { enumerable: true, get: function () { return syntax_4.isDatetimeString; } });
31
+ /**
32
+ * Matches any ISO-ish datetime string. This is a more lenient check than
33
+ * the strict {@link isDatetimeString} guard, which only allows datetimes that
34
+ * fully conform to the AT Protocol specification (e.g. must include timezone).
35
+ */
36
+ function isDatetimeStringLoose(input) {
37
+ // @NOTE the returned type assertion is inaccurate wrt. the DatetimeString
38
+ // type definition. A more accurate solution would be to use a branded type
39
+ // instead of a template literal for the "datetime" format
40
+ if (typeof input !== 'string')
41
+ return false;
42
+ try {
43
+ return (0, iso_datestring_validator_1.isValidISODateString)(input);
44
+ }
45
+ catch {
46
+ // @NOTE isValidISODateString throws on some inputs
47
+ return false;
48
+ }
49
+ }
29
50
  // DatetimeString utilities
30
51
  var syntax_5 = require("@atproto/syntax");
31
52
  Object.defineProperty(exports, "currentDatetimeString", { enumerable: true, get: function () { return syntax_5.currentDatetimeString; } });
@@ -95,17 +116,17 @@ exports.isTidString = syntax_1.isValidTid;
95
116
  exports.isUriString = syntax_1.isValidUri;
96
117
  const stringFormatVerifiers = /*#__PURE__*/ Object.freeze({
97
118
  __proto__: null,
98
- 'at-identifier': syntax_1.isAtIdentifierString,
99
- 'at-uri': exports.isAtUriString,
100
- cid: exports.isCidString,
101
- datetime: syntax_1.isDatetimeString,
102
- did: exports.isDidString,
103
- handle: exports.isHandleString,
104
- language: exports.isLanguageString,
105
- nsid: exports.isNsidString,
106
- 'record-key': exports.isRecordKeyString,
107
- tid: exports.isTidString,
108
- uri: exports.isUriString,
119
+ 'at-identifier': [syntax_1.isAtIdentifierString],
120
+ 'at-uri': [exports.isAtUriString],
121
+ cid: [exports.isCidString],
122
+ datetime: [syntax_1.isDatetimeString, isDatetimeStringLoose],
123
+ did: [exports.isDidString],
124
+ handle: [exports.isHandleString],
125
+ language: [exports.isLanguageString],
126
+ nsid: [exports.isNsidString],
127
+ 'record-key': [exports.isRecordKeyString],
128
+ tid: [exports.isTidString],
129
+ uri: [exports.isUriString],
109
130
  });
110
131
  /**
111
132
  * Type guard that checks if a string matches a specific format.
@@ -126,12 +147,15 @@ const stringFormatVerifiers = /*#__PURE__*/ Object.freeze({
126
147
  * ```
127
148
  */
128
149
  /*@__NO_SIDE_EFFECTS__*/
129
- function isStringFormat(input, format) {
150
+ function isStringFormat(input, format, options) {
130
151
  const formatVerifier = stringFormatVerifiers[format];
131
152
  // Fool-proof
132
153
  if (!formatVerifier)
133
154
  throw new TypeError(`Unknown string format: ${format}`);
134
- return formatVerifier(input);
155
+ const check = options?.strict === false
156
+ ? formatVerifier[1] ?? formatVerifier[0]
157
+ : formatVerifier[0];
158
+ return check(input);
135
159
  }
136
160
  /**
137
161
  * Asserts that a string matches a specific format, throwing if invalid.
@@ -149,8 +173,8 @@ function isStringFormat(input, format) {
149
173
  * ```
150
174
  */
151
175
  /*@__NO_SIDE_EFFECTS__*/
152
- function assertStringFormat(input, format) {
153
- if (!isStringFormat(input, format)) {
176
+ function assertStringFormat(input, format, options) {
177
+ if (!isStringFormat(input, format, options)) {
154
178
  throw new TypeError(`Invalid string format (${format}): ${input}`);
155
179
  }
156
180
  }
@@ -173,8 +197,8 @@ function assertStringFormat(input, format) {
173
197
  * ```
174
198
  */
175
199
  /*@__NO_SIDE_EFFECTS__*/
176
- function asStringFormat(input, format) {
177
- assertStringFormat(input, format);
200
+ function asStringFormat(input, format, options) {
201
+ assertStringFormat(input, format, options);
178
202
  return input;
179
203
  }
180
204
  /**
@@ -198,8 +222,8 @@ function asStringFormat(input, format) {
198
222
  * ```
199
223
  */
200
224
  /*@__NO_SIDE_EFFECTS__*/
201
- function ifStringFormat(input, format) {
202
- return isStringFormat(input, format) ? input : undefined;
225
+ function ifStringFormat(input, format, options) {
226
+ return isStringFormat(input, format, options) ? input : undefined;
203
227
  }
204
228
  /**
205
229
  * Array of all valid string format names.
@@ -1 +1 @@
1
- {"version":3,"file":"string-format.js","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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","sourcesContent":["import { validateCidString } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n AtUriString,\n DatetimeString,\n DidString,\n HandleString,\n NsidString,\n RecordKeyString,\n TidString,\n UriString,\n isAtIdentifierString,\n isDatetimeString,\n isValidAtUri,\n isValidDid,\n isValidHandle,\n isValidLanguage,\n isValidNsid,\n isValidRecordKey,\n isValidTid,\n isValidUri,\n} from '@atproto/syntax'\nimport { CheckFn } from '../util/assertion-util.js'\n\n// -----------------------------------------------------------------------------\n// Individual string format types and type guards\n// -----------------------------------------------------------------------------\n\n// Re-exporting from @atproto/syntax without modification to preserve types and\n// documentation for types and utilities that are already well-defined there.\n// @TODO rework other string formats in @atproto/syntax to follow this pattern\n// and re-export here, e.g. language tags, NSIDs, record keys, etc.\n\nexport {\n type AtIdentifierString,\n asAtIdentifierString,\n ifAtIdentifierString,\n isAtIdentifierString,\n} from '@atproto/syntax'\n\n// AtIdentifierString utilities\nexport { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax'\n\nexport {\n type DatetimeString,\n asDatetimeString,\n ifDatetimeString,\n isDatetimeString,\n} from '@atproto/syntax'\n\n// DatetimeString utilities\nexport { currentDatetimeString, toDatetimeString } from '@atproto/syntax'\n\n/**\n * Type guard that checks if a value is a valid AT URI.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid AT URI\n */\nexport const isAtUriString: CheckFn<AtUriString> = isValidAtUri\nexport type {\n /**\n * An AT URI string pointing to a resource in the AT Protocol network.\n *\n * @example `\"at://did:plc:1234.../app.bsky.feed.post/3k2...\"`\n */\n AtUriString,\n}\n\n/**\n * Type guard that checks if a value is a valid CID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid CID string\n */\nexport const isCidString = ((v) => validateCidString(v)) as CheckFn<CidString>\n/**\n * A Content Identifier (CID) string.\n *\n * CIDs are self-describing content addresses used to identify data by its hash.\n *\n * @example `\"bafyreig...\"`\n */\nexport type CidString = string\n\n/**\n * Type guard that checks if a value is a valid DID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid DID string\n */\nexport const isDidString: CheckFn<DidString> = isValidDid\nexport type {\n /**\n * A Decentralized Identifier (DID) string.\n *\n * DIDs are globally unique identifiers that don't require a central authority.\n *\n * @example `\"did:plc:1234abcd...\"` or `\"did:web:example.com\"`\n */\n DidString,\n}\n\n/**\n * Type guard that checks if a value is a valid handle string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid handle string\n */\nexport const isHandleString: CheckFn<HandleString> = isValidHandle\nexport type {\n /**\n * A handle string - a human-readable identifier for users.\n *\n * @example `\"alice.bsky.social\"` or `\"bob.example.com\"`\n */\n HandleString,\n}\n\n/**\n * Type guard that checks if a value is a valid BCP-47 language tag.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid language string\n */\nexport const isLanguageString = isValidLanguage as CheckFn<LanguageString>\n/**\n * A BCP-47 language tag string.\n *\n * @example `\"en\"`, `\"en-US\"`, `\"zh-Hans\"`\n */\nexport type LanguageString = string\n\n/**\n * Type guard that checks if a value is a valid NSID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid NSID string\n */\nexport const isNsidString: CheckFn<NsidString> = isValidNsid\nexport type {\n /**\n * A Namespaced Identifier (NSID) string identifying a lexicon.\n *\n * NSIDs use reverse-domain notation to identify schemas.\n *\n * @example `\"app.bsky.feed.post\"`, `\"com.atproto.repo.createRecord\"`\n */\n NsidString,\n}\n\n/**\n * Type guard that checks if a value is a valid record key string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid record key string\n */\nexport const isRecordKeyString: CheckFn<RecordKeyString> = isValidRecordKey\nexport type {\n /**\n * A record key string identifying a record within a collection.\n *\n * @example `\"3k2...\"` (TID format) or `\"self\"` (literal key)\n */\n RecordKeyString,\n}\n\n/**\n * Type guard that checks if a value is a valid TID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid TID string\n */\nexport const isTidString: CheckFn<TidString> = isValidTid\nexport type {\n /**\n * A Timestamp Identifier (TID) string.\n *\n * TIDs are time-based identifiers used for record keys.\n *\n * @example `\"3k2...\"`\n */\n TidString,\n}\n\n/**\n * Type guard that checks if a value is a valid URI string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid URI string\n */\nexport const isUriString: CheckFn<UriString> = isValidUri\nexport type {\n /**\n * A standard URI string.\n *\n * @example `\"https://example.com/path\"`\n */\n UriString,\n}\n\n// -----------------------------------------------------------------------------\n// String format registry\n// -----------------------------------------------------------------------------\n\ntype StringFormats = {\n 'at-identifier': AtIdentifierString\n 'at-uri': AtUriString\n cid: CidString\n datetime: DatetimeString\n did: DidString\n handle: HandleString\n language: LanguageString\n nsid: NsidString\n 'record-key': RecordKeyString\n tid: TidString\n uri: UriString\n}\n\n/**\n * Union type of all valid string format names.\n */\nexport type StringFormat = Extract<keyof StringFormats, string>\n\nconst stringFormatVerifiers: {\n readonly [K in StringFormat]: CheckFn<StringFormats[K]>\n} = /*#__PURE__*/ Object.freeze({\n __proto__: null,\n\n 'at-identifier': isAtIdentifierString,\n 'at-uri': isAtUriString,\n cid: isCidString,\n datetime: isDatetimeString,\n did: isDidString,\n handle: isHandleString,\n language: isLanguageString,\n nsid: isNsidString,\n 'record-key': isRecordKeyString,\n tid: isTidString,\n uri: isUriString,\n})\n\n/**\n * Infers the string type for a given format name.\n *\n * @typeParam F - The format name\n *\n * @example\n * ```typescript\n * type Did = InferStringFormat<'did'>\n * // Result: DidString\n * ```\n */\nexport type InferStringFormat<F extends StringFormat> = F extends StringFormat\n ? StringFormats[F]\n : never\n\n/**\n * Type guard that checks if a string matches a specific format.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns `true` if the string matches the format\n *\n * @example\n * ```typescript\n * const value: string = 'did:plc:1234...'\n * if (isStringFormat(value, 'did')) {\n * // value is typed as DidString\n * console.log('Valid DID:', value)\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n): input is I & StringFormats[F] {\n const formatVerifier = stringFormatVerifiers[format]\n // Fool-proof\n if (!formatVerifier) throw new TypeError(`Unknown string format: ${format}`)\n\n return formatVerifier(input)\n}\n\n/**\n * Asserts that a string matches a specific format, throwing if invalid.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * assertStringFormat(value, 'handle')\n * // value is now typed as HandleString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function assertStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n): asserts input is I & StringFormats[F] {\n if (!isStringFormat(input, format)) {\n throw new TypeError(`Invalid string format (${format}): ${input}`)\n }\n}\n\n/**\n * Validates and returns a string as the specified format type, throwing if invalid.\n *\n * This is useful when you need to convert a string to a format type in an expression.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The input typed as the format type\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * const did = asStringFormat(userInput, 'did')\n * // did is typed as DidString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function asStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n): I & StringFormats[F] {\n assertStringFormat(input, format)\n return input\n}\n\n/**\n * Returns the string as the format type if valid, otherwise returns `undefined`.\n *\n * This is useful for optional validation where you want to handle invalid values\n * without throwing.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The typed string if valid, otherwise `undefined`\n *\n * @example\n * ```typescript\n * const did = ifStringFormat(maybeInvalid, 'did')\n * if (did) {\n * // did is typed as DidString\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function ifStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n): undefined | (I & StringFormats[F]) {\n return isStringFormat(input, format) ? input : undefined\n}\n\n/**\n * Array of all valid string format names.\n *\n * @example\n * ```typescript\n * for (const format of STRING_FORMATS) {\n * console.log(format) // 'at-identifier', 'at-uri', 'cid', ...\n * }\n * ```\n */\nexport const STRING_FORMATS = /*#__PURE__*/ Object.freeze(\n /*#__PURE__*/ Object.keys(stringFormatVerifiers),\n) as readonly StringFormat[]\n"]}
1
+ {"version":3,"file":"string-format.js","sourceRoot":"","sources":["../../src/core/string-format.ts"],"names":[],"mappings":"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","sourcesContent":["import { isValidISODateString } from 'iso-datestring-validator'\nimport { validateCidString } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n AtUriString,\n DatetimeString,\n DidString,\n HandleString,\n NsidString,\n RecordKeyString,\n TidString,\n UriString,\n isAtIdentifierString,\n isDatetimeString,\n isValidAtUri,\n isValidDid,\n isValidHandle,\n isValidLanguage,\n isValidNsid,\n isValidRecordKey,\n isValidTid,\n isValidUri,\n} from '@atproto/syntax'\nimport { CheckFn } from '../util/assertion-util.js'\n\n// -----------------------------------------------------------------------------\n// Individual string format types and type guards\n// -----------------------------------------------------------------------------\n\n// Re-exporting from @atproto/syntax without modification to preserve types and\n// documentation for types and utilities that are already well-defined there.\n// @TODO rework other string formats in @atproto/syntax to follow this pattern\n// and re-export here, e.g. language tags, NSIDs, record keys, etc.\n\nexport {\n type AtIdentifierString,\n asAtIdentifierString,\n ifAtIdentifierString,\n isAtIdentifierString,\n} from '@atproto/syntax'\n\n// AtIdentifierString utilities\nexport { isDidIdentifier, isHandleIdentifier } from '@atproto/syntax'\n\nexport {\n type DatetimeString,\n asDatetimeString,\n ifDatetimeString,\n isDatetimeString,\n} from '@atproto/syntax'\n\n/**\n * Matches any ISO-ish datetime string. This is a more lenient check than\n * the strict {@link isDatetimeString} guard, which only allows datetimes that\n * fully conform to the AT Protocol specification (e.g. must include timezone).\n */\nexport function isDatetimeStringLoose<I>(\n input: I,\n): input is I & DatetimeString {\n // @NOTE the returned type assertion is inaccurate wrt. the DatetimeString\n // type definition. A more accurate solution would be to use a branded type\n // instead of a template literal for the \"datetime\" format\n if (typeof input !== 'string') return false\n try {\n return isValidISODateString(input)\n } catch {\n // @NOTE isValidISODateString throws on some inputs\n return false\n }\n}\n\n// DatetimeString utilities\nexport { currentDatetimeString, toDatetimeString } from '@atproto/syntax'\n\n/**\n * Type guard that checks if a value is a valid AT URI.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid AT URI\n */\nexport const isAtUriString: CheckFn<AtUriString> = isValidAtUri\nexport type {\n /**\n * An AT URI string pointing to a resource in the AT Protocol network.\n *\n * @example `\"at://did:plc:1234.../app.bsky.feed.post/3k2...\"`\n */\n AtUriString,\n}\n\n/**\n * Type guard that checks if a value is a valid CID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid CID string\n */\nexport const isCidString = ((v) => validateCidString(v)) as CheckFn<CidString>\n/**\n * A Content Identifier (CID) string.\n *\n * CIDs are self-describing content addresses used to identify data by its hash.\n *\n * @example `\"bafyreig...\"`\n */\nexport type CidString = string\n\n/**\n * Type guard that checks if a value is a valid DID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid DID string\n */\nexport const isDidString: CheckFn<DidString> = isValidDid\nexport type {\n /**\n * A Decentralized Identifier (DID) string.\n *\n * DIDs are globally unique identifiers that don't require a central authority.\n *\n * @example `\"did:plc:1234abcd...\"` or `\"did:web:example.com\"`\n */\n DidString,\n}\n\n/**\n * Type guard that checks if a value is a valid handle string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid handle string\n */\nexport const isHandleString: CheckFn<HandleString> = isValidHandle\nexport type {\n /**\n * A handle string - a human-readable identifier for users.\n *\n * @example `\"alice.bsky.social\"` or `\"bob.example.com\"`\n */\n HandleString,\n}\n\n/**\n * Type guard that checks if a value is a valid BCP-47 language tag.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid language string\n */\nexport const isLanguageString = isValidLanguage as CheckFn<LanguageString>\n/**\n * A BCP-47 language tag string.\n *\n * @example `\"en\"`, `\"en-US\"`, `\"zh-Hans\"`\n */\nexport type LanguageString = string\n\n/**\n * Type guard that checks if a value is a valid NSID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid NSID string\n */\nexport const isNsidString: CheckFn<NsidString> = isValidNsid\nexport type {\n /**\n * A Namespaced Identifier (NSID) string identifying a lexicon.\n *\n * NSIDs use reverse-domain notation to identify schemas.\n *\n * @example `\"app.bsky.feed.post\"`, `\"com.atproto.repo.createRecord\"`\n */\n NsidString,\n}\n\n/**\n * Type guard that checks if a value is a valid record key string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid record key string\n */\nexport const isRecordKeyString: CheckFn<RecordKeyString> = isValidRecordKey\nexport type {\n /**\n * A record key string identifying a record within a collection.\n *\n * @example `\"3k2...\"` (TID format) or `\"self\"` (literal key)\n */\n RecordKeyString,\n}\n\n/**\n * Type guard that checks if a value is a valid TID string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid TID string\n */\nexport const isTidString: CheckFn<TidString> = isValidTid\nexport type {\n /**\n * A Timestamp Identifier (TID) string.\n *\n * TIDs are time-based identifiers used for record keys.\n *\n * @example `\"3k2...\"`\n */\n TidString,\n}\n\n/**\n * Type guard that checks if a value is a valid URI string.\n *\n * @param value - The value to check\n * @returns `true` if the value is a valid URI string\n */\nexport const isUriString: CheckFn<UriString> = isValidUri\nexport type {\n /**\n * A standard URI string.\n *\n * @example `\"https://example.com/path\"`\n */\n UriString,\n}\n\n// -----------------------------------------------------------------------------\n// String format registry\n// -----------------------------------------------------------------------------\n\ntype StringFormats = {\n 'at-identifier': AtIdentifierString\n 'at-uri': AtUriString\n cid: CidString\n datetime: DatetimeString\n did: DidString\n handle: HandleString\n language: LanguageString\n nsid: NsidString\n 'record-key': RecordKeyString\n tid: TidString\n uri: UriString\n}\n\n/**\n * Union type of all valid string format names.\n */\nexport type StringFormat = Extract<keyof StringFormats, string>\n\nconst stringFormatVerifiers: {\n readonly [K in StringFormat]: readonly [\n strict: CheckFn<StringFormats[K]>,\n loose?: CheckFn<StringFormats[K]>,\n ]\n} = /*#__PURE__*/ Object.freeze({\n __proto__: null,\n\n 'at-identifier': [isAtIdentifierString],\n 'at-uri': [isAtUriString],\n cid: [isCidString],\n datetime: [isDatetimeString, isDatetimeStringLoose],\n did: [isDidString],\n handle: [isHandleString],\n language: [isLanguageString],\n nsid: [isNsidString],\n 'record-key': [isRecordKeyString],\n tid: [isTidString],\n uri: [isUriString],\n})\n\nexport type StringFormatValidationOptions = {\n /**\n * Allows to be more lenient in validation by using a \"loose\" verification\n * function, if available. The behavior of the loose verifier depends on the\n * specific format, but generally it may allow for a wider range of valid\n * inputs, including values that are not compliant with the AT Protocol\n * specification.\n *\n * @default true\n */\n strict?: boolean\n}\n\n/**\n * Infers the string type for a given format name.\n *\n * @typeParam F - The format name\n *\n * @example\n * ```typescript\n * type Did = InferStringFormat<'did'>\n * // Result: DidString\n * ```\n */\nexport type InferStringFormat<F extends StringFormat> = F extends StringFormat\n ? StringFormats[F]\n : never\n\n/**\n * Type guard that checks if a string matches a specific format.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns `true` if the string matches the format\n *\n * @example\n * ```typescript\n * const value: string = 'did:plc:1234...'\n * if (isStringFormat(value, 'did')) {\n * // value is typed as DidString\n * console.log('Valid DID:', value)\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function isStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): input is I & StringFormats[F] {\n const formatVerifier = stringFormatVerifiers[format]\n // Fool-proof\n if (!formatVerifier) throw new TypeError(`Unknown string format: ${format}`)\n\n const check: CheckFn<StringFormats[F]> =\n options?.strict === false\n ? formatVerifier[1] ?? formatVerifier[0]\n : formatVerifier[0]\n\n return check(input)\n}\n\n/**\n * Asserts that a string matches a specific format, throwing if invalid.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to check\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * assertStringFormat(value, 'handle')\n * // value is now typed as HandleString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function assertStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): asserts input is I & StringFormats[F] {\n if (!isStringFormat(input, format, options)) {\n throw new TypeError(`Invalid string format (${format}): ${input}`)\n }\n}\n\n/**\n * Validates and returns a string as the specified format type, throwing if invalid.\n *\n * This is useful when you need to convert a string to a format type in an expression.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The input typed as the format type\n * @throws {TypeError} If the string doesn't match the format\n *\n * @example\n * ```typescript\n * const did = asStringFormat(userInput, 'did')\n * // did is typed as DidString\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function asStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): I & StringFormats[F] {\n assertStringFormat(input, format, options)\n return input\n}\n\n/**\n * Returns the string as the format type if valid, otherwise returns `undefined`.\n *\n * This is useful for optional validation where you want to handle invalid values\n * without throwing.\n *\n * @typeParam I - The input string type\n * @typeParam F - The format to validate against\n * @param input - The string to validate\n * @param format - The format name to validate against\n * @returns The typed string if valid, otherwise `undefined`\n *\n * @example\n * ```typescript\n * const did = ifStringFormat(maybeInvalid, 'did')\n * if (did) {\n * // did is typed as DidString\n * }\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function ifStringFormat<I extends string, F extends StringFormat>(\n input: I,\n format: F,\n options?: StringFormatValidationOptions,\n): undefined | (I & StringFormats[F]) {\n return isStringFormat(input, format, options) ? input : undefined\n}\n\n/**\n * Array of all valid string format names.\n *\n * @example\n * ```typescript\n * for (const format of STRING_FORMATS) {\n * console.log(format) // 'at-identifier', 'at-uri', 'cid', ...\n * }\n * ```\n */\nexport const STRING_FORMATS = /*#__PURE__*/ Object.freeze(\n /*#__PURE__*/ Object.keys(stringFormatVerifiers),\n) as readonly StringFormat[]\n"]}
@@ -131,11 +131,13 @@ export type ValidationOptions = {
131
131
  /**
132
132
  * The validation mode determining how transformations are handled.
133
133
  *
134
- * - `"validate"` (default): Strict validation where the result must be
134
+ * - `"validate"`: Strict validation where the result must be
135
135
  * strictly equal to the input value. No transformations such as applying
136
136
  * default values are allowed.
137
137
  * - `"parse"`: Allows the schema to transform the input value, such as
138
138
  * applying default values or performing type coercion.
139
+ *
140
+ * @default "validate"
139
141
  */
140
142
  mode?: 'validate' | 'parse';
141
143
  /**
@@ -151,6 +153,16 @@ export type ValidationOptions = {
151
153
  * ```
152
154
  */
153
155
  path?: readonly PropertyKey[];
156
+ /**
157
+ * Whether to enforce strict validation rules (e.g., MIME type matching, size
158
+ * limits, datetime format).
159
+ *
160
+ * This is typically useful to allow more lax validation when parsing server
161
+ * responses, while enforcing strict validation for user input.
162
+ *
163
+ * @default true
164
+ */
165
+ strict?: boolean;
154
166
  };
155
167
  /**
156
168
  * Manages the state and context for validation operations.
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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"}
@@ -39,6 +39,7 @@ class ValidationContext {
39
39
  const context = new ValidationContext({
40
40
  path: options?.path ?? [],
41
41
  mode: options?.mode ?? 'validate',
42
+ strict: options?.strict ?? true,
42
43
  });
43
44
  return context.validate(input, validator);
44
45
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { ResultFailure, ResultSuccess, success } from './result.js'\nimport { LexValidationError } from './validation-error.js'\nimport {\n Issue,\n IssueInvalidFormat,\n IssueInvalidType,\n IssueInvalidValue,\n IssueRequiredKey,\n IssueTooBig,\n IssueTooSmall,\n MeasurableType,\n} from './validation-issue.js'\n\n/**\n * Represents a successful validation result.\n *\n * @typeParam Value - The type of the validated value\n */\nexport type ValidationSuccess<Value = unknown> = ResultSuccess<Value>\n\n/**\n * Represents a failed validation result containing a {@link LexValidationError}.\n *\n * @extends ResultFailure<LexValidationError>\n * @see {@link ResultFailure}\n * @see {@link LexValidationError}\n */\nexport type ValidationFailure = LexValidationError\n\n/**\n * Discriminated union representing the outcome of a validation operation.\n *\n * Check the `success` property to determine if validation passed or failed:\n * - If `success` is `true`, the `value` property contains the validated data\n * - If `success` is `false`, the `reason` property contains the {@link LexValidationError}\n *\n * @typeParam Value - The type of the validated value on success\n *\n * @example\n * ```typescript\n * const result: ValidationResult<string> = schema.safeParse(data)\n * if (result.success) {\n * // result.value is string\n * } else {\n * // result.reason is LexValidationError\n * }\n * ```\n */\nexport type ValidationResult<Value = unknown> =\n | ValidationSuccess<Value>\n | ValidationFailure\n\n/**\n * Extracts the input type that a validator accepts.\n *\n * Use this utility type to infer what type a schema will accept during validation.\n *\n * @typeParam V - A validator type\n *\n * @example\n * ```typescript\n * const userSchema = new ObjectSchema({ name: stringSchema, age: numberSchema })\n * type UserInput = InferInput<typeof userSchema>\n * // { name: string; age: number }\n * ```\n */\nexport type InferInput<V extends Validator> = V['__lex']['input']\n\n/**\n * Extracts the output type that a validator produces after parsing.\n *\n * The output type may differ from the input type when the schema applies\n * transformations such as default values or type coercion during parsing.\n *\n * @typeParam V - A validator type\n *\n * @example\n * ```typescript\n * const schema = new StringSchema().default('hello')\n * type Input = InferInput<typeof schema> // string | undefined\n * type Output = InferOutput<typeof schema> // string\n * ```\n */\nexport type InferOutput<V extends Validator> = V['__lex']['output']\n\n/**\n * Alias for {@link InferInput} for convenient type inference.\n *\n * @typeParam V - A validator type\n */\nexport type { InferInput as Infer }\n\nexport interface Validator<TInput = unknown, TOutput = TInput> {\n /**\n * This property is used for type inference purposes and does not actually\n * exist at runtime.\n *\n * @internal\n * @deprecated **INTERNAL API, DO NOT USE**.\n */\n readonly ['__lex']: {\n input: TInput\n output: TOutput\n }\n\n /**\n * @internal **INTERNAL API**: use {@link ValidationContext.validate} instead\n *\n * This method is implemented by subclasses to perform transformation and\n * validation of the input value. Do not call this method directly; as the\n * {@link ValidationContext.options.mode} option will **not** be enforced. See\n * {@link ValidationContext.validate} for details. When delegating validation\n * from one validator sub-class implementation to another schema,\n * {@link ValidationContext.validate} must be used instead of calling\n * {@link Validator.validateInContext}. This will allow to stop the validation\n * process if the value was transformed (by the other schema) but\n * transformations are not allowed.\n *\n * By convention, the {@link ValidationResult} must return the original input\n * value if validation was successful and no transformation was applied (i.e.\n * the input already conformed to the schema). If a default value, or any\n * other transformation was applied, the returned value can be different from\n * the input.\n *\n * This convention allows the {@link Validator.check check} and\n * {@link Validator.assert assert} methods to check whether the input value\n * exactly matches the schema (without defaults or transformations), by\n * checking if the returned value is strictly equal to the input.\n *\n * @see {@link ValidationContext.validate}\n */\n validateInContext(input: unknown, ctx: ValidationContext): ValidationResult\n}\n\n/**\n * Configuration options for validation and parsing operations.\n *\n * @example\n * ```typescript\n * // Validate mode (strict, no transformations)\n * ValidationContext.validate(data, schema, { mode: 'validate' })\n *\n * // Parse mode (allows transformations like defaults)\n * ValidationContext.validate(data, schema, { mode: 'parse' })\n *\n * // With initial path for nested validation\n * ValidationContext.validate(data, schema, { path: ['user', 'profile'] })\n * ```\n */\nexport type ValidationOptions = {\n /**\n * The validation mode determining how transformations are handled.\n *\n * - `\"validate\"` (default): Strict validation where the result must be\n * strictly equal to the input value. No transformations such as applying\n * default values are allowed.\n * - `\"parse\"`: Allows the schema to transform the input value, such as\n * applying default values or performing type coercion.\n */\n mode?: 'validate' | 'parse'\n\n /**\n * The initial path to the value being validated.\n *\n * This is used to provide context in validation issues when validating\n * nested structures. The path is prepended to all issue paths.\n *\n * @example\n * ```typescript\n * // Issues will be reported at paths like \"user.name\" instead of just \"name\"\n * ValidationContext.validate(data, schema, { path: ['user'] })\n * ```\n */\n path?: readonly PropertyKey[]\n}\n\n/**\n * Manages the state and context for validation operations.\n *\n * The `ValidationContext` class is responsible for:\n * - Tracking the current path in nested structures for error reporting\n * - Collecting validation issues during traversal\n * - Enforcing validation mode (validate vs parse)\n * - Providing factory methods for creating validation results\n *\n * Use the static {@link ValidationContext.validate} method as the primary entry point\n * for validation. This ensures proper mode enforcement and issue aggregation.\n *\n * @example\n * ```typescript\n * // Primary usage via static method\n * const result = ValidationContext.validate(data, schema, { mode: 'parse' })\n *\n * // Within a custom validator implementation\n * class MyValidator implements Validator {\n * validateInContext(input: unknown, ctx: ValidationContext): ValidationResult {\n * if (typeof input !== 'string') {\n * return ctx.issueUnexpectedType(input, 'string')\n * }\n * return ctx.success(input)\n * }\n * }\n * ```\n */\nexport class ValidationContext {\n /**\n * Validates input against a validator in parse mode.\n *\n * In parse mode, the schema may transform the input (e.g., apply defaults).\n *\n * @param input - The value to validate\n * @param validator - The validator to use\n * @param options - Validation options with mode set to 'parse'\n * @returns A validation result with the parsed output type\n */\n static validate<V extends Validator>(\n input: unknown,\n validator: V,\n options: ValidationOptions & {\n mode: 'parse'\n },\n ): ValidationResult<InferOutput<V>>\n /**\n * Validates input against a validator in validate mode (default).\n *\n * In validate mode, the result must be strictly equal to the input.\n * No transformations are allowed.\n *\n * @typeParam V - The validator type\n * @typeParam I - The input type\n * @param input - The value to validate\n * @param validator - The validator to use\n * @param options - Optional validation options (defaults to validate mode)\n * @returns A validation result preserving the input type intersected with the schema type\n */\n static validate<V extends Validator, I = unknown>(\n input: I,\n validator: V,\n options?: ValidationOptions & {\n mode?: 'validate'\n },\n ): ValidationResult<I & InferInput<V>>\n /**\n * Validates input against a validator with configurable options.\n *\n * @param input - The value to validate\n * @param validator - The validator to use\n * @param options - Optional validation options\n * @returns A validation result with either the input or output type\n */\n static validate<V extends Validator>(\n input: unknown,\n validator: V,\n options?: ValidationOptions,\n ): ValidationResult<InferOutput<V> | InferInput<V>>\n static validate<V extends Validator>(\n input: unknown,\n validator: V,\n options?: ValidationOptions,\n ): ValidationResult<InferOutput<V> | InferInput<V>> {\n const context = new ValidationContext({\n path: options?.path ?? [],\n mode: options?.mode ?? 'validate',\n })\n return context.validate(input, validator)\n }\n\n /**\n * The current path being validated, used for error reporting.\n */\n protected readonly currentPath: PropertyKey[]\n\n /**\n * Accumulated validation issues collected during traversal.\n */\n protected readonly issues: Issue[] = []\n\n /**\n * Creates a new validation context with the specified options.\n *\n * @param options - The validation options (path and mode are required)\n */\n constructor(readonly options: Required<ValidationOptions>) {\n // Create a copy because we will be mutating the array during validation.\n this.currentPath = Array.from(options.path)\n }\n\n /**\n * Returns a copy of the current validation path.\n *\n * The path represents the location in the data structure being validated,\n * used for constructing meaningful error messages.\n */\n get path() {\n return Array.from(this.currentPath)\n }\n\n /**\n * Creates a new path by appending segments to the current path.\n *\n * @param path - Optional path segment(s) to append\n * @returns A new path array with the segment(s) appended\n */\n concatPath(path?: PropertyKey | readonly PropertyKey[]) {\n if (path == null) return this.path\n return this.currentPath.concat(path)\n }\n\n /**\n * Validates input against a validator within this context.\n *\n * This is the primary entry point for validation within a context. Always use\n * this method instead of calling {@link Validator.validateInContext} directly,\n * as this method enforces validation mode rules and handles transformation detection.\n *\n * @typeParam V - The validator type\n * @param input - The value to validate\n * @param validator - The validator to use\n * @returns A validation result with the validated value or error\n */\n validate<V extends Validator>(\n input: unknown,\n validator: V,\n ): ValidationResult<InferInput<V>> {\n // This is the only place where validateInContext should be called.\n const result = validator.validateInContext(input, this)\n\n if (result.success) {\n if (this.issues.length > 0) {\n // Validator returned a success but issues were added via the context.\n // This means the overall validation failed.\n return new LexValidationError(Array.from(this.issues))\n }\n\n if (this.options.mode !== 'parse' && !Object.is(result.value, input)) {\n // If the value changed, it means that a default (or some other\n // transformation) was applied, meaning that the original value did\n // *not* match the (output) schema. When not in \"parse\" mode, we\n // consider this a failure.\n\n // This check is the reason why Validator.validateInContext should not\n // be used directly, and ValidatorContext.validate should be used\n // instead, even when delegating validation from one validator to\n // another.\n\n // This if block comes before the next one because 'this.issues' will\n // end-up being appended to the returned LexValidationError (see the\n // \"failure\" method below), resulting in a more complete error report.\n return this.issueInvalidValue(input, [result.value])\n }\n }\n\n return result as ValidationResult<InferInput<V>>\n }\n\n /**\n * Validates a child property of an object within this context.\n *\n * This method automatically manages the path stack, pushing the property key\n * before validation and popping it afterward. Use this for validating object\n * properties to ensure proper path tracking in error messages.\n *\n * @typeParam I - The input object type\n * @typeParam K - The property key type\n * @typeParam V - The validator type\n * @param input - The parent object containing the property\n * @param key - The property key to validate\n * @param validator - The validator to use for the property value\n * @returns A validation result for the property value\n *\n * @example\n * ```typescript\n * // In a custom object validator\n * const result = ctx.validateChild(input, 'name', stringSchema)\n * // If validation fails, error path will include 'name'\n * ```\n */\n validateChild<\n I extends object,\n K extends PropertyKey & keyof I,\n V extends Validator,\n >(input: I, key: K, validator: V): ValidationResult<InferInput<V>> {\n // @NOTE we could add support for recursive schemas by keeping track of\n // \"parent\" objects in the context and checking for circular references\n // here. This would allow us to validate recursive structures without\n // hitting maximum call stack errors, and would also allow us to provide\n // better error messages for circular reference issues. However, this is not\n // a priority at the moment as recursive structures are not supported in\n // the context of AT Protocol lexicons, and we can always add this in the\n // future if needed.\n\n // Instead of creating a new context, we just push/pop the path segment.\n this.currentPath.push(key)\n try {\n return this.validate(input[key], validator)\n } finally {\n this.currentPath.length--\n }\n }\n\n /**\n * Adds a validation issue to the context without immediately failing.\n *\n * Use this method to collect multiple issues during validation before\n * determining the final result. Issues added this way will be included\n * in the final error if validation fails.\n *\n * @param issue - The validation issue to add\n */\n addIssue(issue: Issue): void {\n this.issues.push(issue)\n }\n\n /**\n * Creates a successful validation result with the given value.\n *\n * @typeParam V - The value type\n * @param value - The validated value\n * @returns A successful validation result\n */\n success<V>(value: V): ValidationResult<V> {\n return success(value)\n }\n\n /**\n * Creates a failed validation result with the given error.\n *\n * @param reason - The validation error\n * @returns A failed validation result\n */\n failure(reason: LexValidationError): ValidationFailure {\n return reason\n }\n\n /**\n * Creates a failed validation result from a single issue.\n *\n * Any previously accumulated issues in the context are included in the error.\n *\n * @param issue - The validation issue that caused the failure\n * @returns A failed validation result\n */\n issue(issue: Issue) {\n return this.failure(new LexValidationError([...this.issues, issue]))\n }\n\n /**\n * Creates a failure for an invalid value that doesn't match expected values.\n *\n * @param input - The actual value that was received\n * @param values - The expected valid values\n * @returns A failed validation result with an invalid value issue\n */\n issueInvalidValue(input: unknown, values: readonly unknown[]) {\n return this.issue(new IssueInvalidValue(this.path, input, values))\n }\n\n /**\n * Creates a failure for an invalid type.\n *\n * @param input - The actual value that was received\n * @param expected - An array of expected type names\n * @returns A failed validation result with an invalid type issue\n */\n issueInvalidType(input: unknown, expected: readonly string[]) {\n return this.issue(new IssueInvalidType(this.path, input, expected))\n }\n\n /**\n * Creates a failure for an invalid type.\n *\n * @param input - The actual value that was received\n * @param expected - The expected type name\n * @returns A failed validation result with an invalid type issue\n */\n issueUnexpectedType(input: unknown, expected: string) {\n return this.issueInvalidType(input, [expected])\n }\n\n /**\n * Creates a failure for a missing required key in an object.\n *\n * @param input - The object missing the required key\n * @param key - The name of the required key\n * @returns A failed validation result with a required key issue\n */\n issueRequiredKey(input: object, key: PropertyKey) {\n return this.issue(new IssueRequiredKey(this.path, input, key))\n }\n\n /**\n * Creates a failure for an invalid string format.\n *\n * @param input - The actual value that was received\n * @param format - The expected format name (e.g., 'did', 'handle', 'uri')\n * @param msg - Optional additional message describing the format error\n * @returns A failed validation result with an invalid format issue\n */\n issueInvalidFormat(input: unknown, format: string, msg?: string) {\n return this.issue(new IssueInvalidFormat(this.path, input, format, msg))\n }\n\n /**\n * Creates a failure for a value that exceeds a maximum constraint.\n *\n * @param input - The actual value that was received\n * @param type - The type of measurement (e.g., 'string', 'array', 'bytes')\n * @param max - The maximum allowed value\n * @param actual - The actual measured value\n * @returns A failed validation result with a too big issue\n */\n issueTooBig(\n input: unknown,\n type: MeasurableType,\n max: number,\n actual: number,\n ) {\n return this.issue(new IssueTooBig(this.path, input, max, type, actual))\n }\n\n /**\n * Creates a failure for a value that is below a minimum constraint.\n *\n * @param input - The actual value that was received\n * @param type - The type of measurement (e.g., 'string', 'array', 'bytes')\n * @param min - The minimum required value\n * @param actual - The actual measured value\n * @returns A failed validation result with a too small issue\n */\n issueTooSmall(\n input: unknown,\n type: MeasurableType,\n min: number,\n actual: number,\n ) {\n return this.issue(new IssueTooSmall(this.path, input, min, type, actual))\n }\n\n /**\n * Creates a failure for an invalid property value within an object.\n *\n * This is a convenience method that automatically extracts the property value\n * and constructs the appropriate path.\n *\n * @typeParam I - The input object type\n * @param input - The object containing the invalid property\n * @param property - The property key with the invalid value\n * @param values - The expected valid values\n * @returns A failed validation result with an invalid value issue at the property path\n */\n issueInvalidPropertyValue<I>(\n input: I,\n property: keyof I & PropertyKey,\n values: readonly unknown[],\n ) {\n const value = input[property]\n const path = this.concatPath(property)\n return this.issue(new IssueInvalidValue(path, value, values))\n }\n\n /**\n * Creates a failure for an invalid property type within an object.\n *\n * This is a convenience method that automatically extracts the property value\n * and constructs the appropriate path.\n *\n * @typeParam I - The input object type\n * @param input - The object containing the invalid property\n * @param property - The property key with the invalid type\n * @param expected - The expected type name\n * @returns A failed validation result with an invalid type issue at the property path\n */\n issueInvalidPropertyType<I>(\n input: I,\n property: keyof I & PropertyKey,\n expected: string,\n ) {\n const value = input[property]\n const path = this.concatPath(property)\n return this.issue(new IssueInvalidType(path, value, [expected]))\n }\n}\n\n/**\n * Recursively unwraps a wrapped validator to its innermost validator type.\n *\n * Some validators wrap other validators (e.g., optional, nullable). This type\n * utility recursively unwraps such wrappers to reveal the core validator.\n *\n * @typeParam T - A validator type, possibly wrapped\n *\n * @example\n * ```typescript\n * type Inner = UnwrapValidator<OptionalValidator<NullableValidator<StringSchema>>>\n * // Result: StringSchema\n * ```\n */\nexport type UnwrapValidator<T extends Validator> = T extends {\n unwrap(): infer U extends Validator\n}\n ? UnwrapValidator<U>\n : T\n\n/**\n * Interface for validators that wrap another validator.\n *\n * Implement this interface when creating validators that wrap or modify\n * the behavior of another validator (e.g., optional, nullable, transform).\n *\n * @typeParam Validator - The type of the wrapped validator\n *\n * @example\n * ```typescript\n * class OptionalSchema<V extends Validator> implements WrappedValidator<V> {\n * constructor(private inner: V) {}\n *\n * unwrap(): V {\n * return this.inner\n * }\n * }\n * ```\n */\nexport interface WrappedValidator<out Validator> {\n /**\n * Returns the inner wrapped validator.\n *\n * @returns The wrapped validator\n */\n unwrap(): Validator\n}\n"]}
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":";;;AAAA,6DAA6D;AAC7D,2CAAmE;AACnE,+DAA0D;AAC1D,+DAS8B;AAkL9B;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAa,iBAAiB;IAiFP;IA5BrB,MAAM,CAAC,QAAQ,CACb,KAAc,EACd,SAAY,EACZ,OAA2B;QAE3B,MAAM,OAAO,GAAG,IAAI,iBAAiB,CAAC;YACpC,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE;YACzB,IAAI,EAAE,OAAO,EAAE,IAAI,IAAI,UAAU;YACjC,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;SAChC,CAAC,CAAA;QACF,OAAO,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IAC3C,CAAC;IAED;;OAEG;IACgB,WAAW,CAAe;IAE7C;;OAEG;IACgB,MAAM,GAAY,EAAE,CAAA;IAEvC;;;;OAIG;IACH,YAAqB,OAAoC;QAApC,YAAO,GAAP,OAAO,CAA6B;QACvD,yEAAyE;QACzE,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,CAAC;IAED;;;;;OAKG;IACH,IAAI,IAAI;QACN,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACrC,CAAC;IAED;;;;;OAKG;IACH,UAAU,CAAC,IAA2C;QACpD,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,IAAI,CAAA;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACtC,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CACN,KAAc,EACd,SAAY;QAEZ,mEAAmE;QACnE,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAEvD,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,sEAAsE;gBACtE,4CAA4C;gBAC5C,OAAO,IAAI,wCAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;YACxD,CAAC;YAED,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;gBACrE,+DAA+D;gBAC/D,mEAAmE;gBACnE,gEAAgE;gBAChE,2BAA2B;gBAE3B,sEAAsE;gBACtE,iEAAiE;gBACjE,iEAAiE;gBACjE,WAAW;gBAEX,qEAAqE;gBACrE,oEAAoE;gBACpE,sEAAsE;gBACtE,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;YACtD,CAAC;QACH,CAAC;QAED,OAAO,MAAyC,CAAA;IAClD,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,aAAa,CAIX,KAAQ,EAAE,GAAM,EAAE,SAAY;QAC9B,uEAAuE;QACvE,uEAAuE;QACvE,qEAAqE;QACrE,wEAAwE;QACxE,4EAA4E;QAC5E,wEAAwE;QACxE,yEAAyE;QACzE,oBAAoB;QAEpB,wEAAwE;QACxE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC1B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAA;QAC7C,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAA;QAC3B,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACH,QAAQ,CAAC,KAAY;QACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAED;;;;;;OAMG;IACH,OAAO,CAAI,KAAQ;QACjB,OAAO,IAAA,mBAAO,EAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED;;;;;OAKG;IACH,OAAO,CAAC,MAA0B;QAChC,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,KAAY;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,wCAAkB,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IACtE,CAAC;IAED;;;;;;OAMG;IACH,iBAAiB,CAAC,KAAc,EAAE,MAA0B;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,uCAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IACpE,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAc,EAAE,QAA2B;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,sCAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAA;IACrE,CAAC;IAED;;;;;;OAMG;IACH,mBAAmB,CAAC,KAAc,EAAE,QAAgB;QAClD,OAAO,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IACjD,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,KAAa,EAAE,GAAgB;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,sCAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAA;IAChE,CAAC;IAED;;;;;;;OAOG;IACH,kBAAkB,CAAC,KAAc,EAAE,MAAc,EAAE,GAAY;QAC7D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,wCAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAA;IAC1E,CAAC;IAED;;;;;;;;OAQG;IACH,WAAW,CACT,KAAc,EACd,IAAoB,EACpB,GAAW,EACX,MAAc;QAEd,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,iCAAW,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IACzE,CAAC;IAED;;;;;;;;OAQG;IACH,aAAa,CACX,KAAc,EACd,IAAoB,EACpB,GAAW,EACX,MAAc;QAEd,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,mCAAa,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IAC3E,CAAC;IAED;;;;;;;;;;;OAWG;IACH,yBAAyB,CACvB,KAAQ,EACR,QAA+B,EAC/B,MAA0B;QAE1B,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,uCAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED;;;;;;;;;;;OAWG;IACH,wBAAwB,CACtB,KAAQ,EACR,QAA+B,EAC/B,QAAgB;QAEhB,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAA;QACtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,sCAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAClE,CAAC;CACF;AA5XD,8CA4XC","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { ResultFailure, ResultSuccess, success } from './result.js'\nimport { LexValidationError } from './validation-error.js'\nimport {\n Issue,\n IssueInvalidFormat,\n IssueInvalidType,\n IssueInvalidValue,\n IssueRequiredKey,\n IssueTooBig,\n IssueTooSmall,\n MeasurableType,\n} from './validation-issue.js'\n\n/**\n * Represents a successful validation result.\n *\n * @typeParam Value - The type of the validated value\n */\nexport type ValidationSuccess<Value = unknown> = ResultSuccess<Value>\n\n/**\n * Represents a failed validation result containing a {@link LexValidationError}.\n *\n * @extends ResultFailure<LexValidationError>\n * @see {@link ResultFailure}\n * @see {@link LexValidationError}\n */\nexport type ValidationFailure = LexValidationError\n\n/**\n * Discriminated union representing the outcome of a validation operation.\n *\n * Check the `success` property to determine if validation passed or failed:\n * - If `success` is `true`, the `value` property contains the validated data\n * - If `success` is `false`, the `reason` property contains the {@link LexValidationError}\n *\n * @typeParam Value - The type of the validated value on success\n *\n * @example\n * ```typescript\n * const result: ValidationResult<string> = schema.safeParse(data)\n * if (result.success) {\n * // result.value is string\n * } else {\n * // result.reason is LexValidationError\n * }\n * ```\n */\nexport type ValidationResult<Value = unknown> =\n | ValidationSuccess<Value>\n | ValidationFailure\n\n/**\n * Extracts the input type that a validator accepts.\n *\n * Use this utility type to infer what type a schema will accept during validation.\n *\n * @typeParam V - A validator type\n *\n * @example\n * ```typescript\n * const userSchema = new ObjectSchema({ name: stringSchema, age: numberSchema })\n * type UserInput = InferInput<typeof userSchema>\n * // { name: string; age: number }\n * ```\n */\nexport type InferInput<V extends Validator> = V['__lex']['input']\n\n/**\n * Extracts the output type that a validator produces after parsing.\n *\n * The output type may differ from the input type when the schema applies\n * transformations such as default values or type coercion during parsing.\n *\n * @typeParam V - A validator type\n *\n * @example\n * ```typescript\n * const schema = new StringSchema().default('hello')\n * type Input = InferInput<typeof schema> // string | undefined\n * type Output = InferOutput<typeof schema> // string\n * ```\n */\nexport type InferOutput<V extends Validator> = V['__lex']['output']\n\n/**\n * Alias for {@link InferInput} for convenient type inference.\n *\n * @typeParam V - A validator type\n */\nexport type { InferInput as Infer }\n\nexport interface Validator<TInput = unknown, TOutput = TInput> {\n /**\n * This property is used for type inference purposes and does not actually\n * exist at runtime.\n *\n * @internal\n * @deprecated **INTERNAL API, DO NOT USE**.\n */\n readonly ['__lex']: {\n input: TInput\n output: TOutput\n }\n\n /**\n * @internal **INTERNAL API**: use {@link ValidationContext.validate} instead\n *\n * This method is implemented by subclasses to perform transformation and\n * validation of the input value. Do not call this method directly; as the\n * {@link ValidationContext.options.mode} option will **not** be enforced. See\n * {@link ValidationContext.validate} for details. When delegating validation\n * from one validator sub-class implementation to another schema,\n * {@link ValidationContext.validate} must be used instead of calling\n * {@link Validator.validateInContext}. This will allow to stop the validation\n * process if the value was transformed (by the other schema) but\n * transformations are not allowed.\n *\n * By convention, the {@link ValidationResult} must return the original input\n * value if validation was successful and no transformation was applied (i.e.\n * the input already conformed to the schema). If a default value, or any\n * other transformation was applied, the returned value can be different from\n * the input.\n *\n * This convention allows the {@link Validator.check check} and\n * {@link Validator.assert assert} methods to check whether the input value\n * exactly matches the schema (without defaults or transformations), by\n * checking if the returned value is strictly equal to the input.\n *\n * @see {@link ValidationContext.validate}\n */\n validateInContext(input: unknown, ctx: ValidationContext): ValidationResult\n}\n\n/**\n * Configuration options for validation and parsing operations.\n *\n * @example\n * ```typescript\n * // Validate mode (strict, no transformations)\n * ValidationContext.validate(data, schema, { mode: 'validate' })\n *\n * // Parse mode (allows transformations like defaults)\n * ValidationContext.validate(data, schema, { mode: 'parse' })\n *\n * // With initial path for nested validation\n * ValidationContext.validate(data, schema, { path: ['user', 'profile'] })\n * ```\n */\nexport type ValidationOptions = {\n /**\n * The validation mode determining how transformations are handled.\n *\n * - `\"validate\"`: Strict validation where the result must be\n * strictly equal to the input value. No transformations such as applying\n * default values are allowed.\n * - `\"parse\"`: Allows the schema to transform the input value, such as\n * applying default values or performing type coercion.\n *\n * @default \"validate\"\n */\n mode?: 'validate' | 'parse'\n\n /**\n * The initial path to the value being validated.\n *\n * This is used to provide context in validation issues when validating\n * nested structures. The path is prepended to all issue paths.\n *\n * @example\n * ```typescript\n * // Issues will be reported at paths like \"user.name\" instead of just \"name\"\n * ValidationContext.validate(data, schema, { path: ['user'] })\n * ```\n */\n path?: readonly PropertyKey[]\n\n /**\n * Whether to enforce strict validation rules (e.g., MIME type matching, size\n * limits, datetime format).\n *\n * This is typically useful to allow more lax validation when parsing server\n * responses, while enforcing strict validation for user input.\n *\n * @default true\n */\n strict?: boolean\n}\n\n/**\n * Manages the state and context for validation operations.\n *\n * The `ValidationContext` class is responsible for:\n * - Tracking the current path in nested structures for error reporting\n * - Collecting validation issues during traversal\n * - Enforcing validation mode (validate vs parse)\n * - Providing factory methods for creating validation results\n *\n * Use the static {@link ValidationContext.validate} method as the primary entry point\n * for validation. This ensures proper mode enforcement and issue aggregation.\n *\n * @example\n * ```typescript\n * // Primary usage via static method\n * const result = ValidationContext.validate(data, schema, { mode: 'parse' })\n *\n * // Within a custom validator implementation\n * class MyValidator implements Validator {\n * validateInContext(input: unknown, ctx: ValidationContext): ValidationResult {\n * if (typeof input !== 'string') {\n * return ctx.issueUnexpectedType(input, 'string')\n * }\n * return ctx.success(input)\n * }\n * }\n * ```\n */\nexport class ValidationContext {\n /**\n * Validates input against a validator in parse mode.\n *\n * In parse mode, the schema may transform the input (e.g., apply defaults).\n *\n * @param input - The value to validate\n * @param validator - The validator to use\n * @param options - Validation options with mode set to 'parse'\n * @returns A validation result with the parsed output type\n */\n static validate<V extends Validator>(\n input: unknown,\n validator: V,\n options: ValidationOptions & {\n mode: 'parse'\n },\n ): ValidationResult<InferOutput<V>>\n\n /**\n * Validates input against a validator in validate mode (default).\n *\n * In validate mode, the result must be strictly equal to the input.\n * No transformations are allowed.\n *\n * @typeParam V - The validator type\n * @typeParam I - The input type\n * @param input - The value to validate\n * @param validator - The validator to use\n * @param options - Optional validation options (defaults to validate mode)\n * @returns A validation result preserving the input type intersected with the schema type\n */\n static validate<V extends Validator, I = unknown>(\n input: I,\n validator: V,\n options?: ValidationOptions & {\n mode?: 'validate'\n },\n ): ValidationResult<I & InferInput<V>>\n\n /**\n * Validates input against a validator with configurable options.\n *\n * @param input - The value to validate\n * @param validator - The validator to use\n * @param options - Optional validation options\n * @returns A validation result with either the input or output type\n */\n static validate<V extends Validator>(\n input: unknown,\n validator: V,\n options?: ValidationOptions,\n ): ValidationResult<InferOutput<V> | InferInput<V>>\n static validate<V extends Validator>(\n input: unknown,\n validator: V,\n options?: ValidationOptions,\n ): ValidationResult<InferOutput<V> | InferInput<V>> {\n const context = new ValidationContext({\n path: options?.path ?? [],\n mode: options?.mode ?? 'validate',\n strict: options?.strict ?? true,\n })\n return context.validate(input, validator)\n }\n\n /**\n * The current path being validated, used for error reporting.\n */\n protected readonly currentPath: PropertyKey[]\n\n /**\n * Accumulated validation issues collected during traversal.\n */\n protected readonly issues: Issue[] = []\n\n /**\n * Creates a new validation context with the specified options.\n *\n * @param options - The validation options (path and mode are required)\n */\n constructor(readonly options: Required<ValidationOptions>) {\n // Create a copy because we will be mutating the array during validation.\n this.currentPath = Array.from(options.path)\n }\n\n /**\n * Returns a copy of the current validation path.\n *\n * The path represents the location in the data structure being validated,\n * used for constructing meaningful error messages.\n */\n get path() {\n return Array.from(this.currentPath)\n }\n\n /**\n * Creates a new path by appending segments to the current path.\n *\n * @param path - Optional path segment(s) to append\n * @returns A new path array with the segment(s) appended\n */\n concatPath(path?: PropertyKey | readonly PropertyKey[]) {\n if (path == null) return this.path\n return this.currentPath.concat(path)\n }\n\n /**\n * Validates input against a validator within this context.\n *\n * This is the primary entry point for validation within a context. Always use\n * this method instead of calling {@link Validator.validateInContext} directly,\n * as this method enforces validation mode rules and handles transformation detection.\n *\n * @typeParam V - The validator type\n * @param input - The value to validate\n * @param validator - The validator to use\n * @returns A validation result with the validated value or error\n */\n validate<V extends Validator>(\n input: unknown,\n validator: V,\n ): ValidationResult<InferInput<V>> {\n // This is the only place where validateInContext should be called.\n const result = validator.validateInContext(input, this)\n\n if (result.success) {\n if (this.issues.length > 0) {\n // Validator returned a success but issues were added via the context.\n // This means the overall validation failed.\n return new LexValidationError(Array.from(this.issues))\n }\n\n if (this.options.mode !== 'parse' && !Object.is(result.value, input)) {\n // If the value changed, it means that a default (or some other\n // transformation) was applied, meaning that the original value did\n // *not* match the (output) schema. When not in \"parse\" mode, we\n // consider this a failure.\n\n // This check is the reason why Validator.validateInContext should not\n // be used directly, and ValidatorContext.validate should be used\n // instead, even when delegating validation from one validator to\n // another.\n\n // This if block comes before the next one because 'this.issues' will\n // end-up being appended to the returned LexValidationError (see the\n // \"failure\" method below), resulting in a more complete error report.\n return this.issueInvalidValue(input, [result.value])\n }\n }\n\n return result as ValidationResult<InferInput<V>>\n }\n\n /**\n * Validates a child property of an object within this context.\n *\n * This method automatically manages the path stack, pushing the property key\n * before validation and popping it afterward. Use this for validating object\n * properties to ensure proper path tracking in error messages.\n *\n * @typeParam I - The input object type\n * @typeParam K - The property key type\n * @typeParam V - The validator type\n * @param input - The parent object containing the property\n * @param key - The property key to validate\n * @param validator - The validator to use for the property value\n * @returns A validation result for the property value\n *\n * @example\n * ```typescript\n * // In a custom object validator\n * const result = ctx.validateChild(input, 'name', stringSchema)\n * // If validation fails, error path will include 'name'\n * ```\n */\n validateChild<\n I extends object,\n K extends PropertyKey & keyof I,\n V extends Validator,\n >(input: I, key: K, validator: V): ValidationResult<InferInput<V>> {\n // @NOTE we could add support for recursive schemas by keeping track of\n // \"parent\" objects in the context and checking for circular references\n // here. This would allow us to validate recursive structures without\n // hitting maximum call stack errors, and would also allow us to provide\n // better error messages for circular reference issues. However, this is not\n // a priority at the moment as recursive structures are not supported in\n // the context of AT Protocol lexicons, and we can always add this in the\n // future if needed.\n\n // Instead of creating a new context, we just push/pop the path segment.\n this.currentPath.push(key)\n try {\n return this.validate(input[key], validator)\n } finally {\n this.currentPath.length--\n }\n }\n\n /**\n * Adds a validation issue to the context without immediately failing.\n *\n * Use this method to collect multiple issues during validation before\n * determining the final result. Issues added this way will be included\n * in the final error if validation fails.\n *\n * @param issue - The validation issue to add\n */\n addIssue(issue: Issue): void {\n this.issues.push(issue)\n }\n\n /**\n * Creates a successful validation result with the given value.\n *\n * @typeParam V - The value type\n * @param value - The validated value\n * @returns A successful validation result\n */\n success<V>(value: V): ValidationResult<V> {\n return success(value)\n }\n\n /**\n * Creates a failed validation result with the given error.\n *\n * @param reason - The validation error\n * @returns A failed validation result\n */\n failure(reason: LexValidationError): ValidationFailure {\n return reason\n }\n\n /**\n * Creates a failed validation result from a single issue.\n *\n * Any previously accumulated issues in the context are included in the error.\n *\n * @param issue - The validation issue that caused the failure\n * @returns A failed validation result\n */\n issue(issue: Issue) {\n return this.failure(new LexValidationError([...this.issues, issue]))\n }\n\n /**\n * Creates a failure for an invalid value that doesn't match expected values.\n *\n * @param input - The actual value that was received\n * @param values - The expected valid values\n * @returns A failed validation result with an invalid value issue\n */\n issueInvalidValue(input: unknown, values: readonly unknown[]) {\n return this.issue(new IssueInvalidValue(this.path, input, values))\n }\n\n /**\n * Creates a failure for an invalid type.\n *\n * @param input - The actual value that was received\n * @param expected - An array of expected type names\n * @returns A failed validation result with an invalid type issue\n */\n issueInvalidType(input: unknown, expected: readonly string[]) {\n return this.issue(new IssueInvalidType(this.path, input, expected))\n }\n\n /**\n * Creates a failure for an invalid type.\n *\n * @param input - The actual value that was received\n * @param expected - The expected type name\n * @returns A failed validation result with an invalid type issue\n */\n issueUnexpectedType(input: unknown, expected: string) {\n return this.issueInvalidType(input, [expected])\n }\n\n /**\n * Creates a failure for a missing required key in an object.\n *\n * @param input - The object missing the required key\n * @param key - The name of the required key\n * @returns A failed validation result with a required key issue\n */\n issueRequiredKey(input: object, key: PropertyKey) {\n return this.issue(new IssueRequiredKey(this.path, input, key))\n }\n\n /**\n * Creates a failure for an invalid string format.\n *\n * @param input - The actual value that was received\n * @param format - The expected format name (e.g., 'did', 'handle', 'uri')\n * @param msg - Optional additional message describing the format error\n * @returns A failed validation result with an invalid format issue\n */\n issueInvalidFormat(input: unknown, format: string, msg?: string) {\n return this.issue(new IssueInvalidFormat(this.path, input, format, msg))\n }\n\n /**\n * Creates a failure for a value that exceeds a maximum constraint.\n *\n * @param input - The actual value that was received\n * @param type - The type of measurement (e.g., 'string', 'array', 'bytes')\n * @param max - The maximum allowed value\n * @param actual - The actual measured value\n * @returns A failed validation result with a too big issue\n */\n issueTooBig(\n input: unknown,\n type: MeasurableType,\n max: number,\n actual: number,\n ) {\n return this.issue(new IssueTooBig(this.path, input, max, type, actual))\n }\n\n /**\n * Creates a failure for a value that is below a minimum constraint.\n *\n * @param input - The actual value that was received\n * @param type - The type of measurement (e.g., 'string', 'array', 'bytes')\n * @param min - The minimum required value\n * @param actual - The actual measured value\n * @returns A failed validation result with a too small issue\n */\n issueTooSmall(\n input: unknown,\n type: MeasurableType,\n min: number,\n actual: number,\n ) {\n return this.issue(new IssueTooSmall(this.path, input, min, type, actual))\n }\n\n /**\n * Creates a failure for an invalid property value within an object.\n *\n * This is a convenience method that automatically extracts the property value\n * and constructs the appropriate path.\n *\n * @typeParam I - The input object type\n * @param input - The object containing the invalid property\n * @param property - The property key with the invalid value\n * @param values - The expected valid values\n * @returns A failed validation result with an invalid value issue at the property path\n */\n issueInvalidPropertyValue<I>(\n input: I,\n property: keyof I & PropertyKey,\n values: readonly unknown[],\n ) {\n const value = input[property]\n const path = this.concatPath(property)\n return this.issue(new IssueInvalidValue(path, value, values))\n }\n\n /**\n * Creates a failure for an invalid property type within an object.\n *\n * This is a convenience method that automatically extracts the property value\n * and constructs the appropriate path.\n *\n * @typeParam I - The input object type\n * @param input - The object containing the invalid property\n * @param property - The property key with the invalid type\n * @param expected - The expected type name\n * @returns A failed validation result with an invalid type issue at the property path\n */\n issueInvalidPropertyType<I>(\n input: I,\n property: keyof I & PropertyKey,\n expected: string,\n ) {\n const value = input[property]\n const path = this.concatPath(property)\n return this.issue(new IssueInvalidType(path, value, [expected]))\n }\n}\n\n/**\n * Recursively unwraps a wrapped validator to its innermost validator type.\n *\n * Some validators wrap other validators (e.g., optional, nullable). This type\n * utility recursively unwraps such wrappers to reveal the core validator.\n *\n * @typeParam T - A validator type, possibly wrapped\n *\n * @example\n * ```typescript\n * type Inner = UnwrapValidator<OptionalValidator<NullableValidator<StringSchema>>>\n * // Result: StringSchema\n * ```\n */\nexport type UnwrapValidator<T extends Validator> = T extends {\n unwrap(): infer U extends Validator\n}\n ? UnwrapValidator<U>\n : T\n\n/**\n * Interface for validators that wrap another validator.\n *\n * Implement this interface when creating validators that wrap or modify\n * the behavior of another validator (e.g., optional, nullable, transform).\n *\n * @typeParam Validator - The type of the wrapped validator\n *\n * @example\n * ```typescript\n * class OptionalSchema<V extends Validator> implements WrappedValidator<V> {\n * constructor(private inner: V) {}\n *\n * unwrap(): V {\n * return this.inner\n * }\n * }\n * ```\n */\nexport interface WrappedValidator<out Validator> {\n /**\n * Returns the inner wrapped validator.\n *\n * @returns The wrapped validator\n */\n unwrap(): Validator\n}\n"]}