@atproto/lex-schema 0.1.1 → 0.1.3

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/core/record-key.d.ts +10 -0
  3. package/dist/core/record-key.d.ts.map +1 -1
  4. package/dist/core/record-key.js.map +1 -1
  5. package/dist/core/result.d.ts +1 -125
  6. package/dist/core/result.d.ts.map +1 -1
  7. package/dist/core/result.js +1 -128
  8. package/dist/core/result.js.map +1 -1
  9. package/dist/core/validation-error.d.ts +0 -18
  10. package/dist/core/validation-error.d.ts.map +1 -1
  11. package/dist/core/validation-error.js +0 -30
  12. package/dist/core/validation-error.js.map +1 -1
  13. package/dist/core/validator.d.ts +8 -15
  14. package/dist/core/validator.d.ts.map +1 -1
  15. package/dist/core/validator.js +3 -14
  16. package/dist/core/validator.js.map +1 -1
  17. package/dist/helpers.d.ts +35 -2
  18. package/dist/helpers.d.ts.map +1 -1
  19. package/dist/helpers.js +33 -0
  20. package/dist/helpers.js.map +1 -1
  21. package/dist/schema/array.d.ts +1 -1
  22. package/dist/schema/blob.d.ts +1 -1
  23. package/dist/schema/boolean.d.ts +1 -1
  24. package/dist/schema/bytes.d.ts +1 -1
  25. package/dist/schema/cid.d.ts +1 -1
  26. package/dist/schema/custom.d.ts +1 -1
  27. package/dist/schema/dict.d.ts +1 -1
  28. package/dist/schema/enum.d.ts +1 -1
  29. package/dist/schema/integer.d.ts +1 -1
  30. package/dist/schema/intersection.d.ts +1 -1
  31. package/dist/schema/lex-map.d.ts +1 -1
  32. package/dist/schema/lex-value.d.ts +1 -1
  33. package/dist/schema/literal.d.ts +1 -1
  34. package/dist/schema/null.d.ts +1 -1
  35. package/dist/schema/nullable.d.ts +1 -1
  36. package/dist/schema/object.d.ts +1 -1
  37. package/dist/schema/optional.d.ts +1 -1
  38. package/dist/schema/params.d.ts +2 -2
  39. package/dist/schema/params.d.ts.map +1 -1
  40. package/dist/schema/record.d.ts +4 -4
  41. package/dist/schema/record.d.ts.map +1 -1
  42. package/dist/schema/record.js +4 -3
  43. package/dist/schema/record.js.map +1 -1
  44. package/dist/schema/regexp.d.ts +1 -1
  45. package/dist/schema/string.d.ts +1 -1
  46. package/dist/schema/token.d.ts +2 -1
  47. package/dist/schema/token.d.ts.map +1 -1
  48. package/dist/schema/token.js +6 -1
  49. package/dist/schema/token.js.map +1 -1
  50. package/dist/schema/typed-union.d.ts +1 -1
  51. package/dist/schema/union.d.ts.map +1 -1
  52. package/dist/schema/union.js +3 -3
  53. package/dist/schema/union.js.map +1 -1
  54. package/dist/schema/unknown.d.ts +1 -1
  55. package/package.json +2 -2
  56. package/src/core/record-key.ts +20 -1
  57. package/src/core/result.ts +8 -155
  58. package/src/core/validation-error.ts +1 -33
  59. package/src/core/validator.ts +10 -21
  60. package/src/helpers.test.ts +126 -1
  61. package/src/helpers.ts +108 -1
  62. package/src/schema/record.test.ts +9 -30
  63. package/src/schema/record.ts +9 -16
  64. package/src/schema/token.ts +9 -1
  65. package/src/schema/union.ts +4 -4
@@ -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\"`: 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"]}
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"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","sourcesContent":["import type * as Result 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 TValue - The type of the validated value\n * @extends Result.ResultSuccess<TValue>\n */\nexport type ValidationSuccess<TValue = unknown> = Result.ResultSuccess<TValue>\n\n/**\n * Represents a failed validation result containing a {@link LexValidationError}.\n *\n * @see {@link LexValidationError}\n * @extends Result.ResultFailure<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 * Helper method to create a successful validation result.\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): ValidationSuccess<V> {\n return { success: true, value }\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): ValidationFailure {\n return 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"]}
package/dist/helpers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { InferOutput, Restricted } from './core.js';
2
- import { InferPayload, InferPayloadBody, InferPayloadEncoding, Procedure, Query, Subscription } from './schema.js';
1
+ import { AtIdentifierString, InferOutput, NsidString, RecordKeyValue, Restricted } from './core.js';
2
+ import { InferPayload, InferPayloadBody, InferPayloadEncoding, InferRecordKey, Procedure, Query, RecordSchema, Subscription } from './schema.js';
3
3
  export type Main<T> = T | {
4
4
  main: T;
5
5
  };
@@ -31,4 +31,37 @@ export declare const lexErrorDataSchema: import("./schema.js").ObjectSchema<{
31
31
  readonly error: import("./schema.js").RegexpSchema<string>;
32
32
  readonly message: import("./schema.js").OptionalSchema<import("./schema.js").StringSchema<{}>>;
33
33
  }>;
34
+ /**
35
+ * Helper function to construct AT Protocol URIs with compile-time & runtime
36
+ * validation of their components. This function supports different use cases,
37
+ * including constructing URIs from raw strings or from RecordSchema instances,
38
+ * ensuring that the resulting URI adheres to the expected format.
39
+ *
40
+ * @throws {TypeError} If the arguments do not match the interface
41
+ * @throws {Error} If AT-URI components are invalid
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * import { atUri } from '@atproto/lex'
46
+ * import { app } from '#/lexicons/index.js'
47
+ *
48
+ * // Constructing a URI from raw components
49
+ * const uri1 = atUri('did:example:123', 'app.bsky.feed.post', 'my-post')
50
+ *
51
+ * // Constructing a URI from a RecordSchema instance
52
+ * const uri2 = atUri('did:example:123', app.bsky.feed.post, 'my-post')
53
+ *
54
+ * // Literal rkey can be omitted
55
+ * const uri3 = atUri('did:example:123', app.bsky.actor.profile) // rkey 'self' is implied
56
+ *
57
+ * // Invalid URIs will throw errors
58
+ * atUri('invalid authority', 'app.bsky.feed.post', 'my-post') // throws
59
+ * atUri('did:example:123', 'invalid collection', 'my-post') // throws
60
+ * atUri('did:example:123', 'app.bsky.feed.post', '..') // throws
61
+ * ```
62
+ */
63
+ export declare function atUri<const TAuthority extends AtIdentifierString>(authority: TAuthority): `at://${TAuthority}`;
64
+ export declare function atUri<const TAuthority extends AtIdentifierString, const TCollection extends NsidString, const TRecordKey extends RecordKeyValue>(authority: TAuthority, nsid: TCollection, rkey: TRecordKey extends '..' | '.' ? never : TRecordKey): `at://${TAuthority}/${TCollection}/${TRecordKey}`;
65
+ export declare function atUri<const TAuthority extends AtIdentifierString, const TRecord extends RecordSchema>(authority: TAuthority, record: TRecord['key'] extends `literal:${string}` ? Main<TRecord> : never): `at://${TAuthority}/${TRecord['$type']}/${InferRecordKey<TRecord>}`;
66
+ export declare function atUri<const TAuthority extends AtIdentifierString, const TRecord extends RecordSchema, const TRecordKey extends InferRecordKey<TRecord>>(authority: TAuthority, record: Main<TRecord>, rkey: TRecordKey extends '..' | '.' ? never : TRecordKey): `at://${TAuthority}/${TRecord['$type']}/${TRecordKey}`;
34
67
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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"}
package/dist/helpers.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { assertAtIdentifierString, assertStringFormat, } from './core.js';
1
2
  import { object, optional, regexp, string, } from './schema.js';
2
3
  export function getMain(ns) {
3
4
  return 'main' in ns ? ns.main : ns;
@@ -11,4 +12,36 @@ export const lexErrorDataSchema = object({
11
12
  // description of the error, appropriate for display to humans
12
13
  message: optional(string()),
13
14
  });
15
+ export function atUri(authority, record, rkey) {
16
+ /**
17
+ * @NOTE because we are encoding potentially untrusted input into a URI, we
18
+ * validate the input against the AT Protocol constraints, ensuring that no
19
+ * invalid URIs can be generated.
20
+ */
21
+ switch (typeof record) {
22
+ case 'undefined': {
23
+ assertAtIdentifierString(authority);
24
+ return `at://${authority}`;
25
+ }
26
+ case 'string': {
27
+ if (!rkey) {
28
+ throw new TypeError('Record key is required when record is a string');
29
+ }
30
+ assertAtIdentifierString(authority);
31
+ assertStringFormat(record, 'nsid');
32
+ assertStringFormat(rkey, 'record-key');
33
+ return `at://${authority}/${record}/${rkey}`;
34
+ }
35
+ default: {
36
+ // @NOTE The use of a schema assumes that the collection ($type) is a
37
+ // valid NSID that can safely be included in the URI without additional
38
+ // checks.
39
+ assertAtIdentifierString(authority);
40
+ const schema = getMain(record);
41
+ // @NOTE parsing will apply defaults, so that literal keys will be
42
+ // properly validated and included in the URI.
43
+ return `at://${authority}/${schema.$type}/${schema.keySchema.parse(rkey)}`;
44
+ }
45
+ }
46
+ }
14
47
  //# sourceMappingURL=helpers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,GACP,MAAM,aAAa,CAAA;AAIpB,MAAM,UAAU,OAAO,CAAmB,EAAW;IACnD,OAAO,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;AACpC,CAAC;AAuFD;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;IACvC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,4CAA4C,CAAC;IACxE,8DAA8D;IAC9D,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;CAC5B,CAAgC,CAAA","sourcesContent":["import { LexErrorData } from '@atproto/lex-data'\nimport { InferOutput, Restricted, Schema } from './core.js'\nimport {\n InferPayload,\n InferPayloadBody,\n InferPayloadEncoding,\n Procedure,\n Query,\n Subscription,\n object,\n optional,\n regexp,\n string,\n} from './schema.js'\n\nexport type Main<T> = T | { main: T }\n\nexport function getMain<T extends object>(ns: Main<T>): T {\n return 'main' in ns ? ns.main : ns\n}\n\n/**\n * Every XRPC implementation should translate `application/json` and `text/*`\n * payloads into their native equivalent ({@link LexValue} or string). Binary\n * data payloads, however, can be represented differently depending on the\n * environment and use case (e.g. `Uint8Array`, `Blob`, `Buffer`,\n * `ReadableStream`, etc.). This type is a placeholder to represent binary data\n * when not explicitly provided.\n */\nexport type BinaryData = Restricted<'Binary data'>\n\nexport type InferMethodParams<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Procedure<any, infer TParams, any, any, any>\n ? InferOutput<TParams>\n : M extends Query<any, infer TParams, any, any>\n ? InferOutput<TParams>\n : M extends Subscription<any, infer TParams, any, any>\n ? InferOutput<TParams>\n : never\n\nexport type InferMethodInput<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, infer TInput, any, any>\n ? InferPayload<TInput, B>\n : undefined\n\nexport type InferMethodInputBody<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, infer TInput, any, any>\n ? InferPayloadBody<TInput, B>\n : undefined\n\nexport type InferMethodInputEncoding<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Procedure<any, any, infer TInput, any, any>\n ? InferPayloadEncoding<TInput>\n : undefined\n\nexport type InferMethodOutput<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, any, infer TOutput, any>\n ? InferPayload<TOutput, B>\n : M extends Query<any, any, infer TOutput, any>\n ? InferPayload<TOutput, B>\n : undefined\n\nexport type InferMethodOutputBody<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, any, infer TOutput, any>\n ? InferPayloadBody<TOutput, B>\n : M extends Query<any, any, infer TOutput, any>\n ? InferPayloadBody<TOutput, B>\n : undefined\n\nexport type InferMethodOutputEncoding<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Procedure<any, any, any, infer TOutput, any>\n ? InferPayloadEncoding<TOutput>\n : M extends Query<any, any, infer TOutput, any>\n ? InferPayloadEncoding<TOutput>\n : undefined\n\nexport type InferMethodMessage<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Subscription<any, any, infer TMessage, any>\n ? InferOutput<TMessage>\n : undefined\n\nexport type InferMethodError<\n //\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> = M extends { errors: readonly (infer E extends string)[] } ? E : never\n\n/**\n * @see {@link https://atproto.com/specs/xrpc#error-responses}\n */\nexport const lexErrorDataSchema = object({\n // type name of the error (generic ASCII constant, no whitespace)\n error: regexp(/^[\\w_-]+$/, 'Expected ASCII constant with no whitespace'),\n // description of the error, appropriate for display to humans\n message: optional(string()),\n}) satisfies Schema<LexErrorData>\n"]}
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,WAAW,CAAA;AAClB,OAAO,EASL,MAAM,EACN,QAAQ,EACR,MAAM,EACN,MAAM,GACP,MAAM,aAAa,CAAA;AAIpB,MAAM,UAAU,OAAO,CAAmB,EAAW;IACnD,OAAO,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;AACpC,CAAC;AAuFD;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;IACvC,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE,4CAA4C,CAAC;IACxE,8DAA8D;IAC9D,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;CAC5B,CAAgC,CAAA;AA2DjC,MAAM,UAAU,KAAK,CACnB,SAA6B,EAC7B,MAAoC,EACpC,IAAa;IAEb;;;;OAIG;IACH,QAAQ,OAAO,MAAM,EAAE,CAAC;QACtB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,wBAAwB,CAAC,SAAS,CAAC,CAAA;YACnC,OAAO,QAAQ,SAAS,EAAE,CAAA;QAC5B,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAA;YACvE,CAAC;YACD,wBAAwB,CAAC,SAAS,CAAC,CAAA;YACnC,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAClC,kBAAkB,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;YACtC,OAAO,QAAQ,SAAS,IAAI,MAAM,IAAI,IAAI,EAAE,CAAA;QAC9C,CAAC;QAED,OAAO,CAAC,CAAC,CAAC;YACR,qEAAqE;YACrE,uEAAuE;YACvE,UAAU;YACV,wBAAwB,CAAC,SAAS,CAAC,CAAA;YACnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;YAC9B,kEAAkE;YAClE,8CAA8C;YAC9C,OAAO,QAAQ,SAAS,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAA;QAC5E,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { LexErrorData } from '@atproto/lex-data'\nimport {\n AtIdentifierString,\n InferOutput,\n NsidString,\n RecordKeyValue,\n Restricted,\n Schema,\n assertAtIdentifierString,\n assertStringFormat,\n} from './core.js'\nimport {\n InferPayload,\n InferPayloadBody,\n InferPayloadEncoding,\n InferRecordKey,\n Procedure,\n Query,\n RecordSchema,\n Subscription,\n object,\n optional,\n regexp,\n string,\n} from './schema.js'\n\nexport type Main<T> = T | { main: T }\n\nexport function getMain<T extends object>(ns: Main<T>): T {\n return 'main' in ns ? ns.main : ns\n}\n\n/**\n * Every XRPC implementation should translate `application/json` and `text/*`\n * payloads into their native equivalent ({@link LexValue} or string). Binary\n * data payloads, however, can be represented differently depending on the\n * environment and use case (e.g. `Uint8Array`, `Blob`, `Buffer`,\n * `ReadableStream`, etc.). This type is a placeholder to represent binary data\n * when not explicitly provided.\n */\nexport type BinaryData = Restricted<'Binary data'>\n\nexport type InferMethodParams<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Procedure<any, infer TParams, any, any, any>\n ? InferOutput<TParams>\n : M extends Query<any, infer TParams, any, any>\n ? InferOutput<TParams>\n : M extends Subscription<any, infer TParams, any, any>\n ? InferOutput<TParams>\n : never\n\nexport type InferMethodInput<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, infer TInput, any, any>\n ? InferPayload<TInput, B>\n : undefined\n\nexport type InferMethodInputBody<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, infer TInput, any, any>\n ? InferPayloadBody<TInput, B>\n : undefined\n\nexport type InferMethodInputEncoding<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Procedure<any, any, infer TInput, any, any>\n ? InferPayloadEncoding<TInput>\n : undefined\n\nexport type InferMethodOutput<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, any, infer TOutput, any>\n ? InferPayload<TOutput, B>\n : M extends Query<any, any, infer TOutput, any>\n ? InferPayload<TOutput, B>\n : undefined\n\nexport type InferMethodOutputBody<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n B = BinaryData,\n> =\n M extends Procedure<any, any, any, infer TOutput, any>\n ? InferPayloadBody<TOutput, B>\n : M extends Query<any, any, infer TOutput, any>\n ? InferPayloadBody<TOutput, B>\n : undefined\n\nexport type InferMethodOutputEncoding<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Procedure<any, any, any, infer TOutput, any>\n ? InferPayloadEncoding<TOutput>\n : M extends Query<any, any, infer TOutput, any>\n ? InferPayloadEncoding<TOutput>\n : undefined\n\nexport type InferMethodMessage<\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> =\n M extends Subscription<any, any, infer TMessage, any>\n ? InferOutput<TMessage>\n : undefined\n\nexport type InferMethodError<\n //\n M extends Procedure | Query | Subscription = Procedure | Query | Subscription,\n> = M extends { errors: readonly (infer E extends string)[] } ? E : never\n\n/**\n * @see {@link https://atproto.com/specs/xrpc#error-responses}\n */\nexport const lexErrorDataSchema = object({\n // type name of the error (generic ASCII constant, no whitespace)\n error: regexp(/^[\\w_-]+$/, 'Expected ASCII constant with no whitespace'),\n // description of the error, appropriate for display to humans\n message: optional(string()),\n}) satisfies Schema<LexErrorData>\n\n/**\n * Helper function to construct AT Protocol URIs with compile-time & runtime\n * validation of their components. This function supports different use cases,\n * including constructing URIs from raw strings or from RecordSchema instances,\n * ensuring that the resulting URI adheres to the expected format.\n *\n * @throws {TypeError} If the arguments do not match the interface\n * @throws {Error} If AT-URI components are invalid\n *\n * @example\n * ```typescript\n * import { atUri } from '@atproto/lex'\n * import { app } from '#/lexicons/index.js'\n *\n * // Constructing a URI from raw components\n * const uri1 = atUri('did:example:123', 'app.bsky.feed.post', 'my-post')\n *\n * // Constructing a URI from a RecordSchema instance\n * const uri2 = atUri('did:example:123', app.bsky.feed.post, 'my-post')\n *\n * // Literal rkey can be omitted\n * const uri3 = atUri('did:example:123', app.bsky.actor.profile) // rkey 'self' is implied\n *\n * // Invalid URIs will throw errors\n * atUri('invalid authority', 'app.bsky.feed.post', 'my-post') // throws\n * atUri('did:example:123', 'invalid collection', 'my-post') // throws\n * atUri('did:example:123', 'app.bsky.feed.post', '..') // throws\n * ```\n */\nexport function atUri<const TAuthority extends AtIdentifierString>(\n authority: TAuthority,\n): `at://${TAuthority}`\nexport function atUri<\n const TAuthority extends AtIdentifierString,\n const TCollection extends NsidString,\n const TRecordKey extends RecordKeyValue,\n>(\n authority: TAuthority,\n nsid: TCollection,\n rkey: TRecordKey extends '..' | '.' ? never : TRecordKey,\n): `at://${TAuthority}/${TCollection}/${TRecordKey}`\nexport function atUri<\n const TAuthority extends AtIdentifierString,\n const TRecord extends RecordSchema,\n>(\n authority: TAuthority,\n record: TRecord['key'] extends `literal:${string}` ? Main<TRecord> : never,\n): `at://${TAuthority}/${TRecord['$type']}/${InferRecordKey<TRecord>}`\nexport function atUri<\n const TAuthority extends AtIdentifierString,\n const TRecord extends RecordSchema,\n const TRecordKey extends InferRecordKey<TRecord>,\n>(\n authority: TAuthority,\n record: Main<TRecord>,\n rkey: TRecordKey extends '..' | '.' ? never : TRecordKey,\n): `at://${TAuthority}/${TRecord['$type']}/${TRecordKey}`\nexport function atUri(\n authority: AtIdentifierString,\n record?: string | Main<RecordSchema>,\n rkey?: string,\n) {\n /**\n * @NOTE because we are encoding potentially untrusted input into a URI, we\n * validate the input against the AT Protocol constraints, ensuring that no\n * invalid URIs can be generated.\n */\n switch (typeof record) {\n case 'undefined': {\n assertAtIdentifierString(authority)\n return `at://${authority}`\n }\n\n case 'string': {\n if (!rkey) {\n throw new TypeError('Record key is required when record is a string')\n }\n assertAtIdentifierString(authority)\n assertStringFormat(record, 'nsid')\n assertStringFormat(rkey, 'record-key')\n return `at://${authority}/${record}/${rkey}`\n }\n\n default: {\n // @NOTE The use of a schema assumes that the collection ($type) is a\n // valid NSID that can safely be included in the URI without additional\n // checks.\n assertAtIdentifierString(authority)\n const schema = getMain(record)\n // @NOTE parsing will apply defaults, so that literal keys will be\n // properly validated and included in the URI.\n return `at://${authority}/${schema.$type}/${schema.keySchema.parse(rkey)}`\n }\n }\n}\n"]}
@@ -28,7 +28,7 @@ export declare class ArraySchema<const TItem extends Validator> extends Schema<A
28
28
  readonly options: ArraySchemaOptions;
29
29
  readonly type: "array";
30
30
  constructor(validator: TItem, options?: ArraySchemaOptions);
31
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<any[]>;
31
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<any[]>;
32
32
  }
33
33
  /**
34
34
  * Creates an array schema that validates each item against the provided schema.
@@ -38,7 +38,7 @@ export declare class BlobSchema<const TOptions extends BlobSchemaOptions = NonNu
38
38
  readonly options?: TOptions | undefined;
39
39
  readonly type: "blob";
40
40
  constructor(options?: TOptions | undefined);
41
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<BlobRef>;
41
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<BlobRef>;
42
42
  matchesMime(mime: string): boolean;
43
43
  }
44
44
  /**
@@ -15,7 +15,7 @@ import { Schema, ValidationContext } from '../core.js';
15
15
  */
16
16
  export declare class BooleanSchema extends Schema<boolean> {
17
17
  readonly type: "boolean";
18
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<boolean>;
18
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<boolean>;
19
19
  }
20
20
  /**
21
21
  * Creates a boolean schema that validates true/false values.
@@ -25,7 +25,7 @@ export declare class BytesSchema extends Schema<Uint8Array> {
25
25
  readonly options: BytesSchemaOptions;
26
26
  readonly type: "bytes";
27
27
  constructor(options?: BytesSchemaOptions);
28
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<Uint8Array<ArrayBufferLike>>;
28
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Uint8Array<ArrayBufferLike>>;
29
29
  }
30
30
  /**
31
31
  * Creates a bytes schema for validating binary data with optional length constraints.
@@ -28,7 +28,7 @@ export declare class CidSchema<const TOptions extends CidSchemaOptions = {
28
28
  readonly options?: TOptions | undefined;
29
29
  readonly type: "cid";
30
30
  constructor(options?: TOptions | undefined);
31
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<Cid<0 | 1, number, number>>;
31
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Cid<0 | 1, number, number>>;
32
32
  }
33
33
  /**
34
34
  * Creates a CID schema for validating Content Identifiers.
@@ -38,7 +38,7 @@ export declare class CustomSchema<out TValue = unknown> extends Schema<TValue> {
38
38
  private readonly path?;
39
39
  readonly type: "custom";
40
40
  constructor(assertion: CustomAssertion<TValue>, message: string, path?: (PropertyKey | readonly PropertyKey[]) | undefined);
41
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<TValue>;
41
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<TValue>;
42
42
  }
43
43
  /**
44
44
  * Creates a custom schema with a user-defined validation function.
@@ -28,7 +28,7 @@ export declare class DictSchema<const TKey extends Validator<string> = any, cons
28
28
  ignoredKeys?: {
29
29
  has(k: string): boolean;
30
30
  };
31
- }): import("../core.js").ValidationResult<Record<string, unknown>>;
31
+ }): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Record<string, unknown>>;
32
32
  }
33
33
  /**
34
34
  * Creates a dictionary schema for validating map-like objects.
@@ -18,7 +18,7 @@ export declare class EnumSchema<const TValue extends null | string | number | bo
18
18
  readonly values: readonly TValue[];
19
19
  readonly type: "enum";
20
20
  constructor(values: readonly TValue[]);
21
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<TValue>;
21
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<TValue>;
22
22
  }
23
23
  /**
24
24
  * Creates an enum schema that accepts one of the specified values.
@@ -25,7 +25,7 @@ export declare class IntegerSchema extends Schema<number> {
25
25
  readonly options?: IntegerSchemaOptions | undefined;
26
26
  readonly type: "integer";
27
27
  constructor(options?: IntegerSchemaOptions | undefined);
28
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<number>;
28
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<number>;
29
29
  }
30
30
  /**
31
31
  * Creates an integer schema with optional minimum and maximum constraints.
@@ -43,7 +43,7 @@ export declare class IntersectionSchema<const Left extends ObjectSchema = any, c
43
43
  protected readonly right: Right;
44
44
  readonly type: "intersection";
45
45
  constructor(left: Left, right: Right);
46
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<Record<string, unknown>>;
46
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Record<string, unknown>>;
47
47
  }
48
48
  /**
49
49
  * Creates an intersection schema combining fixed object properties with dynamic dictionary properties.
@@ -10,7 +10,7 @@ export type { LexMap };
10
10
  */
11
11
  export declare class LexMapSchema extends Schema<LexMap> {
12
12
  readonly type: "lexMap";
13
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<Record<string, unknown>>;
13
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Record<string, unknown>>;
14
14
  }
15
15
  /**
16
16
  * Creates a schema that accepts any plain object with string keys and values
@@ -7,7 +7,7 @@ export type { LexValue };
7
7
  */
8
8
  export declare class LexValueSchema extends Schema<LexValue> {
9
9
  readonly type: "lexValue";
10
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<any[] | Record<string, unknown> | import("@atproto/lex-data").LexScalar>;
10
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<any[] | Record<string, unknown> | import("@atproto/lex-data").LexScalar>;
11
11
  }
12
12
  /**
13
13
  * Creates a schema that accepts any valid AT Protocol data type: string,
@@ -18,7 +18,7 @@ export declare class LiteralSchema<const TValue extends null | string | number |
18
18
  readonly value: TValue;
19
19
  readonly type: "literal";
20
20
  constructor(value: TValue);
21
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<TValue>;
21
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<TValue>;
22
22
  }
23
23
  /**
24
24
  * Creates a literal schema that only accepts the exact specified value.
@@ -14,7 +14,7 @@ import { Schema, ValidationContext } from '../core.js';
14
14
  */
15
15
  export declare class NullSchema extends Schema<null> {
16
16
  readonly type: "null";
17
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<null>;
17
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<null>;
18
18
  }
19
19
  /**
20
20
  * Creates a null schema that only accepts the null value.
@@ -18,7 +18,7 @@ export declare class NullableSchema<const TValidator extends Validator> extends
18
18
  readonly validator: TValidator;
19
19
  readonly type: "nullable";
20
20
  constructor(validator: TValidator);
21
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<null> | import("../core.js").ValidationSuccess<InferInput<TValidator>>;
21
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationSuccess<null> | import("../core.js").ValidationResult<InferInput<TValidator>>;
22
22
  }
23
23
  /**
24
24
  * Creates a nullable schema that accepts null in addition to the wrapped type.
@@ -31,7 +31,7 @@ export declare class ObjectSchema<const TShape extends ObjectSchemaShape = any>
31
31
  readonly type: "object";
32
32
  constructor(shape: TShape);
33
33
  get validatorsMap(): Map<string, Validator>;
34
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<Record<string, unknown>>;
34
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Record<string, unknown>>;
35
35
  }
36
36
  /**
37
37
  * Creates an object schema with the specified property validators.
@@ -20,7 +20,7 @@ export declare class OptionalSchema<TValidator extends Validator> extends Schema
20
20
  readonly validator: TValidator;
21
21
  readonly type: "optional";
22
22
  constructor(validator: TValidator);
23
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<undefined> | import("../core.js").ValidationSuccess<InferInput<TValidator>>;
23
+ validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<undefined> | import("../core.js").ValidationSuccess<InferInput<TValidator>>;
24
24
  }
25
25
  /**
26
26
  * Creates an optional schema that allows undefined values.
@@ -1,4 +1,4 @@
1
- import { Infer, InferInput, InferOutput, ParseOptions, Schema, ValidationContext, Validator, WithOptionalProperties } from '../core.js';
1
+ import { Infer, InferInput, InferOutput, LexValidationError, ParseOptions, Schema, ValidationContext, Validator, WithOptionalProperties } from '../core.js';
2
2
  import { ArraySchema } from './array.js';
3
3
  import { BooleanSchema } from './boolean.js';
4
4
  import { EnumSchema } from './enum.js';
@@ -68,7 +68,7 @@ export declare class ParamsSchema<const TShape extends ParamsShape = ParamsShape
68
68
  readonly type: "params";
69
69
  constructor(shape: TShape);
70
70
  get shapeValidators(): Map<string, ParamValidator>;
71
- validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<Record<string, unknown>>;
71
+ validateInContext(input: unknown, ctx: ValidationContext): LexValidationError | import("../core.js").ValidationSuccess<Record<string, unknown>>;
72
72
  fromURLSearchParams(input: string | Iterable<[string, string]>, options?: ParseOptions): InferOutput<this>;
73
73
  toURLSearchParams(input: InferInput<this>): URLSearchParams;
74
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/schema/params.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/schema/params.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
1
  import { LexMap } from '@atproto/lex-data';
2
- import { $Typed, InferInput, InferOutput, LexiconRecordKey, NsidString, Schema, TidString, Unknown$TypedObject, ValidationContext, Validator } from '../core.js';
2
+ import { $Typed, InferInput, InferOutput, LexiconRecordKey, NsidString, RecordKeyValue, Schema, Unknown$TypedObject, ValidationContext, Validator } from '../core.js';
3
3
  /**
4
4
  * Infers the record key type from a RecordSchema.
5
5
  *
6
6
  * @template R - The RecordSchema type
7
7
  */
8
- export type InferRecordKey<R extends RecordSchema> = R extends RecordSchema<infer TKey> ? RecordKeySchemaOutput<TKey> : never;
8
+ export type InferRecordKey<R extends RecordSchema> = R extends RecordSchema<infer TKey> ? RecordKeyValue<TKey> : never;
9
9
  export type TypedRecord<TType extends NsidString, TValue extends {
10
10
  $type?: unknown;
11
11
  } = {
@@ -57,8 +57,8 @@ export declare class RecordSchema<const TKey extends LexiconRecordKey = LexiconR
57
57
  */
58
58
  get $isTypeOf(): typeof this.isTypeOf;
59
59
  }
60
- export type RecordKeySchemaOutput<Key extends LexiconRecordKey> = Key extends 'any' ? string : Key extends 'tid' ? TidString : Key extends 'nsid' ? NsidString : Key extends `literal:${infer L extends string}` ? L : never;
61
- export type RecordKeySchema<Key extends LexiconRecordKey> = Schema<RecordKeySchemaOutput<Key>>;
60
+ export type RecordKeySchemaOutput<Key extends LexiconRecordKey> = RecordKeyValue<Key>;
61
+ export type RecordKeySchema<Key extends LexiconRecordKey> = Schema<RecordKeyValue<Key>>;
62
62
  /**
63
63
  * Ensures that a `$type` used in a record is a valid NSID (i.e. no fragment).
64
64
  */
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/schema/record.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/schema/record.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { $typed, Schema, } from '../core.js';
2
2
  import { lazyProperty } from '../util/lazy-property.js';
3
3
  import { literal } from './literal.js';
4
4
  import { string } from './string.js';
5
+ import { withDefault } from './with-default.js';
5
6
  /**
6
7
  * Schema for AT Protocol records with a type identifier and key constraints.
7
8
  *
@@ -62,10 +63,10 @@ export class RecordSchema extends Schema {
62
63
  return lazyProperty(this, '$isTypeOf', this.isTypeOf.bind(this));
63
64
  }
64
65
  }
65
- const keySchema = string({ minLength: 1 });
66
+ const keySchema = string({ format: 'record-key' });
66
67
  const tidSchema = string({ format: 'tid' });
67
68
  const nsidSchema = string({ format: 'nsid' });
68
- const selfLiteralSchema = literal('self');
69
+ const selfLiteralSchema = withDefault(literal('self'), 'self');
69
70
  function recordKey(key) {
70
71
  // @NOTE Use cached instances for common schemas
71
72
  if (key === 'any')
@@ -78,7 +79,7 @@ function recordKey(key) {
78
79
  const value = key.slice(8);
79
80
  if (value === 'self')
80
81
  return selfLiteralSchema;
81
- return literal(value);
82
+ return withDefault(literal(value), value);
82
83
  }
83
84
  throw new Error(`Unsupported record key type: ${key}`);
84
85
  }