@atproto/lex-schema 0.0.13 → 0.0.15
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 +39 -0
- package/dist/core/schema.d.ts +27 -35
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +73 -54
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.d.ts +14 -0
- package/dist/core/standard-schema.d.ts.map +1 -0
- package/dist/core/standard-schema.js +27 -0
- package/dist/core/standard-schema.js.map +1 -0
- package/dist/core/string-format.d.ts +4 -28
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +23 -17
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-error.d.ts +14 -6
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +18 -8
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.d.ts +15 -15
- package/dist/core/validation-issue.d.ts.map +1 -1
- package/dist/core/validation-issue.js +33 -29
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +21 -18
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +5 -4
- package/dist/core/validator.js.map +1 -1
- package/dist/core.d.ts +0 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +0 -1
- package/dist/core.js.map +1 -1
- package/dist/schema/custom.d.ts +1 -1
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/never.d.ts +1 -1
- package/dist/schema/nullable.d.ts +1 -1
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +4 -1
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/record.d.ts +12 -6
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +21 -12
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +1 -1
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +1 -1
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/typed-object.d.ts +12 -4
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +21 -12
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +1 -1
- package/dist/schema/typed-union.d.ts +1 -1
- package/dist/schema/union.d.ts +2 -2
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +1 -1
- package/dist/schema/union.js.map +1 -1
- package/package.json +4 -3
- package/src/core/schema.ts +78 -69
- package/src/core/standard-schema.test.ts +124 -0
- package/src/core/standard-schema.ts +31 -0
- package/src/core/string-format.ts +26 -33
- package/src/core/validation-error.ts +25 -10
- package/src/core/validation-issue.ts +32 -32
- package/src/core/validator.ts +16 -12
- package/src/core.ts +0 -1
- package/src/schema/array.test.ts +2 -2
- package/src/schema/custom.ts +1 -7
- package/src/schema/params.test.ts +18 -2
- package/src/schema/params.ts +5 -2
- package/src/schema/record.ts +27 -22
- package/src/schema/ref.ts +1 -5
- package/src/schema/refine.ts +0 -1
- package/src/schema/typed-object.test.ts +38 -0
- package/src/schema/typed-object.ts +29 -24
- package/src/schema/union.ts +2 -2
- package/dist/core/property-key.d.ts +0 -2
- package/dist/core/property-key.d.ts.map +0 -1
- package/dist/core/property-key.js +0 -3
- package/dist/core/property-key.js.map +0 -1
- package/src/core/property-key.ts +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/schema/params.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPlainObject } from '@atproto/lex-data'\nimport {\n Infer,\n InferInput,\n InferOutput,\n Issue,\n IssueInvalidType,\n IssueInvalidValue,\n ParseOptions,\n Schema,\n ValidationContext,\n ValidationError,\n Validator,\n WithOptionalProperties,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { memoizedOptions } from '../util/memoize.js'\nimport { ArraySchema, array } from './array.js'\nimport { BooleanSchema, boolean } from './boolean.js'\nimport { dict } from './dict.js'\nimport { EnumSchema } from './enum.js'\nimport { IntegerSchema, integer } from './integer.js'\nimport { LiteralSchema } from './literal.js'\nimport { OptionalSchema, optional } from './optional.js'\nimport { StringSchema, string } from './string.js'\nimport { union } from './union.js'\nimport { WithDefaultSchema } from './with-default.js'\n\n/**\n * Scalar types allowed in URL parameters: boolean, integer, or string.\n */\nexport type ParamScalar = Infer<typeof paramScalarSchema>\nconst paramScalarSchema = union([boolean(), integer(), string()])\n\n/**\n * A single parameter value: scalar or array of scalars.\n */\nexport type Param = Infer<typeof paramSchema>\n\n/**\n * Schema for validating individual parameter values.\n */\nexport const paramSchema = union([\n paramScalarSchema,\n array(boolean()),\n array(integer()),\n array(string()),\n])\n\n/**\n * Type for a params object with string keys and optional param values.\n */\nexport type Params = Infer<typeof paramsSchema>\n\n/**\n * Schema for validating arbitrary params objects.\n */\nexport const paramsSchema = dict(string(), optional(paramSchema))\n\nexport type ParamScalarValidator =\n // @NOTE In order to properly coerce URLSearchParams, we need to distinguish\n // between scalar and array validators, requiring to be able to detect which\n // schema types are being used, restricting the allowed param validators here.\n | LiteralSchema<string>\n | LiteralSchema<number>\n | LiteralSchema<boolean>\n | EnumSchema<string>\n | EnumSchema<number>\n // | EnumSchema<boolean> // Boolean lexicon definitions don't allow \"enum\"\n | StringSchema<any>\n | BooleanSchema\n | IntegerSchema\n\ntype AsArrayParamSchema<TSchema extends Validator> =\n // This allows to \"distribute\" any union of scalar validators into a union of\n // arrays of those validators, instead of an array of union. If TSchema is\n // BooleanSchema | IntegerSchema, we want the result to be\n // ArraySchema<BooleanSchema> | ArraySchema<IntegerSchema>, not\n // ArraySchema<BooleanSchema | IntegerSchema>, since the latter would allow\n // arrays with mixed types (e.g. [true, 42]), which we don't want.\n TSchema extends any ? ArraySchema<TSchema> : never\n\nexport type ParamValueValidator =\n | ParamScalarValidator\n | AsArrayParamSchema<ParamScalarValidator>\n\nexport type ParamValidator =\n | ParamValueValidator\n | OptionalSchema<ParamValueValidator>\n | OptionalSchema<WithDefaultSchema<ParamValueValidator>>\n | WithDefaultSchema<ParamValueValidator>\n\n/**\n * Type representing the shape of a params schema definition.\n *\n * Maps parameter names to their validators (must be Param or undefined).\n */\nexport type ParamsShape = {\n [x: string]: ParamValidator\n}\n\n/**\n * Schema for validating URL query parameters in Lexicon endpoints.\n *\n * Params are the query string parameters passed to queries, procedures,\n * and subscriptions. Values must be scalars (boolean, integer, string)\n * or arrays of scalars, as they need to be serializable to URL format.\n *\n * Provides methods for converting to/from URLSearchParams.\n *\n * @template TShape - The params shape type mapping names to validators\n *\n * @example\n * ```ts\n * const schema = new ParamsSchema({\n * limit: l.optional(l.integer({ minimum: 1, maximum: 100 })),\n * cursor: l.optional(l.string()),\n * })\n * ```\n */\nexport class ParamsSchema<\n const TShape extends ParamsShape = ParamsShape,\n> extends Schema<\n WithOptionalProperties<{\n [K in keyof TShape]: InferInput<TShape[K]>\n }>,\n WithOptionalProperties<{\n [K in keyof TShape]: InferOutput<TShape[K]>\n }>\n> {\n readonly type = 'params' as const\n\n constructor(readonly shape: TShape) {\n super()\n }\n\n get shapeValidators(): Map<string, ParamValidator> {\n const map = new Map(Object.entries(this.shape))\n\n return lazyProperty(this, 'shapeValidators', map)\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input)) {\n return ctx.issueUnexpectedType(input, 'object')\n }\n\n // Lazily copy value\n let copy: undefined | Record<string, unknown>\n\n // Ensure that non-specified params conform to param schema\n for (const key in input) {\n if (this.shapeValidators.has(key)) continue\n\n const result = ctx.validateChild(input, key, paramSchema)\n if (!result.success) return result\n\n if (result.value !== input[key]) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n for (const [key, propDef] of this.shapeValidators) {\n const result = ctx.validateChild(input, key, propDef)\n if (!result.success) {\n if (!(key in input)) {\n // Transform into \"required key\" issue\n return ctx.issueRequiredKey(input, key)\n }\n\n return result\n }\n\n // Skip copying if key is not present in input (and value is undefined)\n if (result.value === undefined && !(key in input)) {\n continue\n }\n\n if (!Object.is(result.value, input[key])) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n // Copy on write\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n return ctx.success(copy ?? input)\n }\n\n fromURLSearchParams(\n input: string | Iterable<[string, string]>,\n options?: ParseOptions,\n ): InferOutput<this> {\n const params: Record<string, unknown> = {}\n\n const iterable =\n typeof input === 'string' ? new URLSearchParams(input) : input\n const entries =\n iterable instanceof URLSearchParams ? iterable.entries() : iterable\n\n for (const [name, value] of entries) {\n const validator = this.shapeValidators.get(name)\n const innerValidator = validator ? unwrapSchema(validator) : undefined\n const expectsArray = innerValidator instanceof ArraySchema\n const scalarValidator = expectsArray\n ? unwrapSchema(innerValidator.validator)\n : innerValidator\n\n const coerced = coerceParam(name, value, scalarValidator, options)\n\n const currentParam = params[name]\n if (currentParam === undefined) {\n params[name] = expectsArray ? [coerced] : coerced\n } else if (Array.isArray(currentParam)) {\n currentParam.push(coerced)\n } else {\n params[name] = [currentParam, coerced]\n }\n }\n\n return this.parse(params, options)\n }\n\n toURLSearchParams(input: InferInput<this>): URLSearchParams {\n const urlSearchParams = new URLSearchParams()\n\n // @NOTE We apply defaults here to ensure that server with different\n // defaults still receive all expected parameters.\n const params = this.parse(input)\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n urlSearchParams.append(key, String(v))\n }\n } else if (value !== undefined) {\n urlSearchParams.append(key, String(value))\n }\n }\n\n return urlSearchParams\n }\n}\n\nfunction coerceParam(\n name: string,\n param: string,\n schema?: ParamScalarValidator,\n options?: ParseOptions,\n): ParamScalar {\n let issue: Issue\n\n if (!schema) {\n // The param is unknown (not defined in schema), so we don't apply any\n // coercion and just return the string value.\n return param\n } else if (schema instanceof StringSchema) {\n return param\n } else if (schema instanceof IntegerSchema) {\n if (/^-?\\d+$/.test(param)) return Number(param)\n issue = new IssueInvalidType(paramPath(name, options), param, ['integer'])\n } else if (schema instanceof BooleanSchema) {\n if (param === 'true') return true\n if (param === 'false') return false\n issue = new IssueInvalidType(paramPath(name, options), param, ['boolean'])\n } else if (schema instanceof LiteralSchema) {\n const { value } = schema\n if (String(value) === param) return value\n issue = new IssueInvalidValue(paramPath(name, options), param, [value])\n } else if (schema instanceof EnumSchema) {\n const { values } = schema\n for (const value of values) {\n if (String(value) === param) return value\n }\n issue = new IssueInvalidValue(paramPath(name, options), param, values)\n } else {\n // This should never happen. If it *does*, it means that the user of\n // lex-schema is mixing different versions of the lib, which is not\n // supported. Throwing an error here is better than silently accepting\n // invalid params and causing unexpected behavior down the line (ie. error\n // message returning the string value instead of the expected\n // boolean/number/string value).\n throw new Error(`Unsupported schema type for param coercion: ${schema}`)\n }\n\n // We were not able to coerce the param to the expected type. There is no\n // point in returning the original string value since it doesn't conform to\n // the expected schema, so we throw a validation error instead. We could\n // return the \"param\" here, which would cause the validation to fail later on\n // (see fromURLSearchParams()'s return statement). The main benefit of\n // returning the original \"param\" value is that the error path would include\n // the index of the param in case of array params (e.g. \"tags[1]\"), which\n // could be helpful for debugging. The cost overhead is not worth it though\n // (IMO).\n throw new ValidationError([issue])\n}\n\nfunction paramPath(key: string, options?: ParseOptions) {\n return options?.path ? [...options.path, key] : [key]\n}\n\n/**\n * Creates a params schema for URL query parameters.\n *\n * Params schemas validate query string parameters for Lexicon endpoints.\n * Values must be boolean, integer, string, or arrays of those types.\n *\n * @param properties - Object mapping parameter names to their validators\n * @returns A new {@link ParamsSchema} instance\n *\n * @example\n * ```ts\n * // Simple pagination params\n * const paginationParams = l.params({\n * limit: l.optional(l.withDefault(l.integer({ minimum: 1, maximum: 100 }), 50)),\n * cursor: l.optional(l.string()),\n * })\n *\n * // Required parameter\n * const actorParams = l.params({\n * actor: l.string({ format: 'at-identifier' }),\n * })\n *\n * // Array parameter (multiple values)\n * const filterParams = l.params({\n * tags: l.optional(l.array(l.string())),\n * })\n *\n * // Convert from URL\n * const urlParams = new URLSearchParams('limit=25&cursor=abc')\n * const validated = paginationParams.fromURLSearchParams(urlParams)\n *\n * // Convert to URL\n * const searchParams = paginationParams.toURLSearchParams({ limit: 25 })\n * ```\n */\nexport const params = /*#__PURE__*/ memoizedOptions(function params<\n const TShape extends ParamsShape = NonNullable<unknown>,\n>(properties: TShape = {} as TShape) {\n return new ParamsSchema<TShape>(properties)\n})\n\ntype UnwrapSchema<S extends Validator> =\n S extends OptionalSchema<infer U>\n ? UnwrapSchema<U>\n : S extends WithDefaultSchema<infer U>\n ? UnwrapSchema<U>\n : S\n\nfunction unwrapSchema<S extends Validator>(schema: S): UnwrapSchema<S> {\n while (\n schema instanceof OptionalSchema ||\n schema instanceof WithDefaultSchema\n ) {\n return unwrapSchema(schema.validator)\n }\n return schema as UnwrapSchema<S>\n}\n"]}
|
|
1
|
+
{"version":3,"file":"params.js","sourceRoot":"","sources":["../../src/schema/params.ts"],"names":[],"mappings":"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","sourcesContent":["import { isPlainObject } from '@atproto/lex-data'\nimport {\n Infer,\n InferInput,\n InferOutput,\n Issue,\n IssueInvalidType,\n IssueInvalidValue,\n LexValidationError,\n ParseOptions,\n Schema,\n ValidationContext,\n Validator,\n WithOptionalProperties,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { memoizedOptions } from '../util/memoize.js'\nimport { ArraySchema, array } from './array.js'\nimport { BooleanSchema, boolean } from './boolean.js'\nimport { dict } from './dict.js'\nimport { EnumSchema } from './enum.js'\nimport { IntegerSchema, integer } from './integer.js'\nimport { LiteralSchema } from './literal.js'\nimport { OptionalSchema, optional } from './optional.js'\nimport { StringSchema, string } from './string.js'\nimport { union } from './union.js'\nimport { WithDefaultSchema } from './with-default.js'\n\n/**\n * Scalar types allowed in URL parameters: boolean, integer, or string.\n */\nexport type ParamScalar = Infer<typeof paramScalarSchema>\nconst paramScalarSchema = union([boolean(), integer(), string()])\n\n/**\n * A single parameter value: scalar or array of scalars.\n */\nexport type Param = Infer<typeof paramSchema>\n\n/**\n * Schema for validating individual parameter values.\n */\nexport const paramSchema = union([\n paramScalarSchema,\n array(boolean()),\n array(integer()),\n array(string()),\n])\n\n/**\n * Type for a params object with string keys and optional param values.\n */\nexport type Params = Infer<typeof paramsSchema>\n\n/**\n * Schema for validating arbitrary params objects.\n */\nexport const paramsSchema = dict(string(), optional(paramSchema))\n\nexport type ParamScalarValidator =\n // @NOTE In order to properly coerce URLSearchParams, we need to distinguish\n // between scalar and array validators, requiring to be able to detect which\n // schema types are being used, restricting the allowed param validators here.\n | LiteralSchema<string>\n | LiteralSchema<number>\n | LiteralSchema<boolean>\n | EnumSchema<string>\n | EnumSchema<number>\n // | EnumSchema<boolean> // Boolean lexicon definitions don't allow \"enum\"\n | StringSchema<any>\n | BooleanSchema\n | IntegerSchema\n\ntype AsArrayParamSchema<TSchema extends Validator> =\n // This allows to \"distribute\" any union of scalar validators into a union of\n // arrays of those validators, instead of an array of union. If TSchema is\n // BooleanSchema | IntegerSchema, we want the result to be\n // ArraySchema<BooleanSchema> | ArraySchema<IntegerSchema>, not\n // ArraySchema<BooleanSchema | IntegerSchema>, since the latter would allow\n // arrays with mixed types (e.g. [true, 42]), which we don't want.\n TSchema extends any ? ArraySchema<TSchema> : never\n\nexport type ParamValueValidator =\n | ParamScalarValidator\n | AsArrayParamSchema<ParamScalarValidator>\n\nexport type ParamValidator =\n | ParamValueValidator\n | OptionalSchema<ParamValueValidator>\n | OptionalSchema<WithDefaultSchema<ParamValueValidator>>\n | WithDefaultSchema<ParamValueValidator>\n\n/**\n * Type representing the shape of a params schema definition.\n *\n * Maps parameter names to their validators (must be Param or undefined).\n */\nexport type ParamsShape = {\n [x: string]: ParamValidator\n}\n\n/**\n * Schema for validating URL query parameters in Lexicon endpoints.\n *\n * Params are the query string parameters passed to queries, procedures,\n * and subscriptions. Values must be scalars (boolean, integer, string)\n * or arrays of scalars, as they need to be serializable to URL format.\n *\n * Provides methods for converting to/from URLSearchParams.\n *\n * @template TShape - The params shape type mapping names to validators\n *\n * @example\n * ```ts\n * const schema = new ParamsSchema({\n * limit: l.optional(l.integer({ minimum: 1, maximum: 100 })),\n * cursor: l.optional(l.string()),\n * })\n * ```\n */\nexport class ParamsSchema<\n const TShape extends ParamsShape = ParamsShape,\n> extends Schema<\n WithOptionalProperties<{\n [K in keyof TShape]: InferInput<TShape[K]>\n }>,\n WithOptionalProperties<{\n [K in keyof TShape]: InferOutput<TShape[K]>\n }>\n> {\n readonly type = 'params' as const\n\n constructor(readonly shape: TShape) {\n super()\n }\n\n get shapeValidators(): Map<string, ParamValidator> {\n const map = new Map(Object.entries(this.shape))\n\n return lazyProperty(this, 'shapeValidators', map)\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input)) {\n return ctx.issueUnexpectedType(input, 'object')\n }\n\n // Lazily copy value\n let copy: undefined | Record<string, unknown>\n\n // Ensure that non-specified params conform to param schema\n for (const key in input) {\n if (this.shapeValidators.has(key)) continue\n\n const result = ctx.validateChild(input, key, paramSchema)\n if (!result.success) return result\n\n if (result.value !== input[key]) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n for (const [key, propDef] of this.shapeValidators) {\n const result = ctx.validateChild(input, key, propDef)\n if (!result.success) {\n if (!(key in input)) {\n // Transform into \"required key\" issue\n return ctx.issueRequiredKey(input, key)\n }\n\n return result\n }\n\n // Skip copying if key is not present in input (and value is undefined)\n if (result.value === undefined && !(key in input)) {\n continue\n }\n\n if (!Object.is(result.value, input[key])) {\n if (ctx.options.mode === 'validate') {\n // In \"validate\" mode, we can't modify the input, so we issue an error\n return ctx.issueInvalidPropertyValue(input, key, [result.value])\n }\n\n // Copy on write\n copy ??= { ...input }\n copy[key] = result.value\n }\n }\n\n return ctx.success(copy ?? input)\n }\n\n fromURLSearchParams(\n input: string | Iterable<[string, string]>,\n options?: ParseOptions,\n ): InferOutput<this> {\n const params: Record<string, unknown> = {}\n\n const iterable =\n typeof input === 'string' ? new URLSearchParams(input) : input\n const entries =\n iterable instanceof URLSearchParams ? iterable.entries() : iterable\n\n for (const [name, value] of entries) {\n // Ignore empty strings\n if (!value) continue\n\n const validator = this.shapeValidators.get(name)\n const innerValidator = validator ? unwrapSchema(validator) : undefined\n const expectsArray = innerValidator instanceof ArraySchema\n const scalarValidator = expectsArray\n ? unwrapSchema(innerValidator.validator)\n : innerValidator\n\n const coerced = coerceParam(name, value, scalarValidator, options)\n\n const currentParam = params[name]\n if (currentParam === undefined) {\n params[name] = expectsArray ? [coerced] : coerced\n } else if (Array.isArray(currentParam)) {\n currentParam.push(coerced)\n } else {\n params[name] = [currentParam, coerced]\n }\n }\n\n return this.parse(params, options)\n }\n\n toURLSearchParams(input: InferInput<this>): URLSearchParams {\n const urlSearchParams = new URLSearchParams()\n\n // @NOTE We apply defaults here to ensure that server with different\n // defaults still receive all expected parameters.\n const params = this.parse(input)\n\n for (const [key, value] of Object.entries(params)) {\n if (Array.isArray(value)) {\n for (const v of value) {\n urlSearchParams.append(key, String(v))\n }\n } else if (value !== undefined) {\n urlSearchParams.append(key, String(value))\n }\n }\n\n return urlSearchParams\n }\n}\n\nfunction coerceParam(\n name: string,\n param: string,\n schema?: ParamScalarValidator,\n options?: ParseOptions,\n): ParamScalar {\n let issue: Issue\n\n if (!schema) {\n // The param is unknown (not defined in schema), so we don't apply any\n // coercion and just return the string value.\n return param\n } else if (schema instanceof StringSchema) {\n return param\n } else if (schema instanceof IntegerSchema) {\n if (/^-?\\d+$/.test(param)) return Number(param)\n issue = new IssueInvalidType(paramPath(name, options), param, ['integer'])\n } else if (schema instanceof BooleanSchema) {\n if (param === 'true') return true\n if (param === 'false') return false\n issue = new IssueInvalidType(paramPath(name, options), param, ['boolean'])\n } else if (schema instanceof LiteralSchema) {\n const { value } = schema\n if (String(value) === param) return value\n issue = new IssueInvalidValue(paramPath(name, options), param, [value])\n } else if (schema instanceof EnumSchema) {\n const { values } = schema\n for (const value of values) {\n if (String(value) === param) return value\n }\n issue = new IssueInvalidValue(paramPath(name, options), param, values)\n } else {\n // This should never happen. If it *does*, it means that the user of\n // lex-schema is mixing different versions of the lib, which is not\n // supported. Throwing an error here is better than silently accepting\n // invalid params and causing unexpected behavior down the line (ie. error\n // message returning the string value instead of the expected\n // boolean/number/string value).\n throw new Error(`Unsupported schema type for param coercion: ${schema}`)\n }\n\n // We were not able to coerce the param to the expected type. There is no\n // point in returning the original string value since it doesn't conform to\n // the expected schema, so we throw a validation error instead. We could\n // return the \"param\" here, which would cause the validation to fail later on\n // (see fromURLSearchParams()'s return statement). The main benefit of\n // returning the original \"param\" value is that the error path would include\n // the index of the param in case of array params (e.g. \"tags[1]\"), which\n // could be helpful for debugging. The cost overhead is not worth it though\n // (IMO).\n throw new LexValidationError([issue])\n}\n\nfunction paramPath(key: string, options?: ParseOptions) {\n return options?.path ? [...options.path, key] : [key]\n}\n\n/**\n * Creates a params schema for URL query parameters.\n *\n * Params schemas validate query string parameters for Lexicon endpoints.\n * Values must be boolean, integer, string, or arrays of those types.\n *\n * @param properties - Object mapping parameter names to their validators\n * @returns A new {@link ParamsSchema} instance\n *\n * @example\n * ```ts\n * // Simple pagination params\n * const paginationParams = l.params({\n * limit: l.optional(l.withDefault(l.integer({ minimum: 1, maximum: 100 }), 50)),\n * cursor: l.optional(l.string()),\n * })\n *\n * // Required parameter\n * const actorParams = l.params({\n * actor: l.string({ format: 'at-identifier' }),\n * })\n *\n * // Array parameter (multiple values)\n * const filterParams = l.params({\n * tags: l.optional(l.array(l.string())),\n * })\n *\n * // Convert from URL\n * const urlParams = new URLSearchParams('limit=25&cursor=abc')\n * const validated = paginationParams.fromURLSearchParams(urlParams)\n *\n * // Convert to URL\n * const searchParams = paginationParams.toURLSearchParams({ limit: 25 })\n * ```\n */\nexport const params = /*#__PURE__*/ memoizedOptions(function params<\n const TShape extends ParamsShape = NonNullable<unknown>,\n>(properties: TShape = {} as TShape) {\n return new ParamsSchema<TShape>(properties)\n})\n\ntype UnwrapSchema<S extends Validator> =\n S extends OptionalSchema<infer U>\n ? UnwrapSchema<U>\n : S extends WithDefaultSchema<infer U>\n ? UnwrapSchema<U>\n : S\n\nfunction unwrapSchema<S extends Validator>(schema: S): UnwrapSchema<S> {\n while (\n schema instanceof OptionalSchema ||\n schema instanceof WithDefaultSchema\n ) {\n return unwrapSchema(schema.validator)\n }\n return schema as UnwrapSchema<S>\n}\n"]}
|
package/dist/schema/record.d.ts
CHANGED
|
@@ -41,15 +41,21 @@ export declare class RecordSchema<const TKey extends LexiconRecordKey = any, con
|
|
|
41
41
|
readonly type: "record";
|
|
42
42
|
keySchema: RecordKeySchema<TKey>;
|
|
43
43
|
constructor(key: TKey, $type: TType, schema: TShape);
|
|
44
|
-
|
|
45
|
-
$type?: unknown;
|
|
46
|
-
}>(value: TValue): value is TypedRecord<TType, TValue>;
|
|
44
|
+
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<InferInput<TShape>>;
|
|
47
45
|
build(input: Omit<InferInput<this>, '$type'>): $Typed<InferOutput<this>, TType>;
|
|
48
|
-
|
|
46
|
+
isTypeOf<TValue extends {
|
|
49
47
|
$type?: unknown;
|
|
50
48
|
}>(value: TValue): value is TypedRecord<TType, TValue>;
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Bound alias for {@link build} for compatibility with generated utilities.
|
|
51
|
+
* @see {@link build}
|
|
52
|
+
*/
|
|
53
|
+
get $build(): typeof this.build;
|
|
54
|
+
/**
|
|
55
|
+
* Bound alias for {@link isTypeOf} for compatibility with generated utilities.
|
|
56
|
+
* @see {@link isTypeOf}
|
|
57
|
+
*/
|
|
58
|
+
get $isTypeOf(): typeof this.isTypeOf;
|
|
53
59
|
}
|
|
54
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;
|
|
55
61
|
export type RecordKeySchema<Key extends LexiconRecordKey> = Schema<RecordKeySchemaOutput<Key>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/schema/record.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EAEN,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,MAAM,EACN,SAAS,EACT,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/schema/record.ts"],"names":[],"mappings":"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"}
|
package/dist/schema/record.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.RecordSchema = void 0;
|
|
4
4
|
exports.record = record;
|
|
5
5
|
const core_js_1 = require("../core.js");
|
|
6
|
+
const lazy_property_js_1 = require("../util/lazy-property.js");
|
|
6
7
|
const literal_js_1 = require("./literal.js");
|
|
7
8
|
const string_js_1 = require("./string.js");
|
|
8
9
|
/**
|
|
@@ -38,18 +39,6 @@ class RecordSchema extends core_js_1.Schema {
|
|
|
38
39
|
this.schema = schema;
|
|
39
40
|
this.keySchema = recordKey(key);
|
|
40
41
|
}
|
|
41
|
-
isTypeOf(value) {
|
|
42
|
-
return value.$type === this.$type;
|
|
43
|
-
}
|
|
44
|
-
build(input) {
|
|
45
|
-
return this.parse((0, core_js_1.$typed)(input, this.$type));
|
|
46
|
-
}
|
|
47
|
-
$isTypeOf(value) {
|
|
48
|
-
return this.isTypeOf(value);
|
|
49
|
-
}
|
|
50
|
-
$build(input) {
|
|
51
|
-
return this.build(input);
|
|
52
|
-
}
|
|
53
42
|
validateInContext(input, ctx) {
|
|
54
43
|
const result = ctx.validate(input, this.schema);
|
|
55
44
|
if (!result.success) {
|
|
@@ -60,6 +49,26 @@ class RecordSchema extends core_js_1.Schema {
|
|
|
60
49
|
}
|
|
61
50
|
return result;
|
|
62
51
|
}
|
|
52
|
+
build(input) {
|
|
53
|
+
return this.parse((0, core_js_1.$typed)(input, this.$type));
|
|
54
|
+
}
|
|
55
|
+
isTypeOf(value) {
|
|
56
|
+
return value.$type === this.$type;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Bound alias for {@link build} for compatibility with generated utilities.
|
|
60
|
+
* @see {@link build}
|
|
61
|
+
*/
|
|
62
|
+
get $build() {
|
|
63
|
+
return (0, lazy_property_js_1.lazyProperty)(this, '$build', this.build.bind(this));
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Bound alias for {@link isTypeOf} for compatibility with generated utilities.
|
|
67
|
+
* @see {@link isTypeOf}
|
|
68
|
+
*/
|
|
69
|
+
get $isTypeOf() {
|
|
70
|
+
return (0, lazy_property_js_1.lazyProperty)(this, '$isTypeOf', this.isTypeOf.bind(this));
|
|
71
|
+
}
|
|
63
72
|
}
|
|
64
73
|
exports.RecordSchema = RecordSchema;
|
|
65
74
|
const keySchema = (0, string_js_1.string)({ minLength: 1 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/schema/record.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/schema/record.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n $Typed,\n $typed,\n InferInput,\n InferOutput,\n LexiconRecordKey,\n NsidString,\n Schema,\n TidString,\n Unknown$TypedObject,\n ValidationContext,\n Validator,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { literal } from './literal.js'\nimport { string } from './string.js'\n\n/**\n * Infers the record key type from a RecordSchema.\n *\n * @template R - The RecordSchema type\n */\nexport type InferRecordKey<R extends RecordSchema> =\n R extends RecordSchema<infer TKey> ? RecordKeySchemaOutput<TKey> : never\n\nexport type TypedRecord<\n TType extends NsidString,\n TValue extends { $type?: unknown } = { $type?: unknown },\n> = TValue extends { $type: TType }\n ? TValue\n : $Typed<Exclude<TValue, Unknown$TypedObject>, TType>\n\n/**\n * Schema for AT Protocol records with a type identifier and key constraints.\n *\n * Records are the primary data unit in AT Protocol. Each record has a `$type`\n * field identifying its Lexicon schema, and is stored at a specific key\n * (TID, NSID, or other format) in a repository.\n *\n * @template TKey - The record key type ('tid', 'nsid', 'any', or 'literal:...')\n * @template TType - The NSID string identifying this record type\n * @template TShape - The validator type for the record's data shape\n *\n * @example\n * ```ts\n * const postSchema = new RecordSchema(\n * 'tid',\n * 'app.bsky.feed.post',\n * l.object({ text: l.string(), createdAt: l.string() })\n * )\n * ```\n */\nexport class RecordSchema<\n const TKey extends LexiconRecordKey = any,\n const TType extends NsidString = any,\n const TShape extends Validator<{ [k: string]: unknown }> = any,\n> extends Schema<\n $Typed<InferInput<TShape>, TType>,\n $Typed<InferOutput<TShape>, TType>\n> {\n readonly type = 'record' as const\n\n keySchema: RecordKeySchema<TKey>\n\n constructor(\n readonly key: TKey,\n readonly $type: TType,\n readonly schema: TShape,\n ) {\n super()\n this.keySchema = recordKey(key)\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n const result = ctx.validate(input, this.schema)\n\n if (!result.success) {\n return result\n }\n\n if (result.value.$type !== this.$type) {\n return ctx.issueInvalidPropertyValue(result.value, '$type', [this.$type])\n }\n\n return result\n }\n\n build(\n input: Omit<InferInput<this>, '$type'>,\n ): $Typed<InferOutput<this>, TType> {\n return this.parse($typed(input, this.$type))\n }\n\n isTypeOf<TValue extends { $type?: unknown }>(\n value: TValue,\n ): value is TypedRecord<TType, TValue> {\n return value.$type === this.$type\n }\n\n /**\n * Bound alias for {@link build} for compatibility with generated utilities.\n * @see {@link build}\n */\n get $build(): typeof this.build {\n return lazyProperty(this, '$build', this.build.bind(this))\n }\n\n /**\n * Bound alias for {@link isTypeOf} for compatibility with generated utilities.\n * @see {@link isTypeOf}\n */\n get $isTypeOf(): typeof this.isTypeOf {\n return lazyProperty(this, '$isTypeOf', this.isTypeOf.bind(this))\n }\n}\n\nexport type RecordKeySchemaOutput<Key extends LexiconRecordKey> =\n Key extends 'any'\n ? string\n : Key extends 'tid'\n ? TidString\n : Key extends 'nsid'\n ? NsidString\n : Key extends `literal:${infer L extends string}`\n ? L\n : never\n\nexport type RecordKeySchema<Key extends LexiconRecordKey> = Schema<\n RecordKeySchemaOutput<Key>\n>\n\nconst keySchema = string({ minLength: 1 })\nconst tidSchema = string({ format: 'tid' })\nconst nsidSchema = string({ format: 'nsid' })\nconst selfLiteralSchema = literal('self')\n\nfunction recordKey<Key extends LexiconRecordKey>(\n key: Key,\n): RecordKeySchema<Key> {\n // @NOTE Use cached instances for common schemas\n if (key === 'any') return keySchema as any\n if (key === 'tid') return tidSchema as any\n if (key === 'nsid') return nsidSchema as any\n if (key.startsWith('literal:')) {\n const value = key.slice(8) as RecordKeySchemaOutput<Key>\n if (value === 'self') return selfLiteralSchema as any\n return literal(value)\n }\n\n throw new Error(`Unsupported record key type: ${key}`)\n}\n\n/**\n * Ensures that a `$type` used in a record is a valid NSID (i.e. no fragment).\n */\ntype AsNsid<T> = T extends `${string}#${string}` ? never : T\n\n/**\n * Creates a record schema for AT Protocol records.\n *\n * Records are the primary data unit in AT Protocol repositories. They have\n * a `$type` field identifying their Lexicon schema, and are stored at keys\n * following a specific format (TID, NSID, etc.).\n *\n * This function offers two overloads:\n * - One that infers the output type from the provided arguments (does not\n * support circular references)\n * - One with an explicitly defined interface for use with codegen and\n * circular references\n *\n * @param key - The record key type: 'tid', 'nsid', 'any', or 'literal:value'\n * @param type - The NSID identifying this record type (e.g., 'app.bsky.feed.post')\n * @param validator - Schema validator for the record's properties\n * @returns A new {@link RecordSchema} instance\n *\n * @example\n * ```ts\n * // Post record with TID key\n * const postSchema = l.record('tid', 'app.bsky.feed.post', l.object({\n * text: l.string({ maxGraphemes: 300 }),\n * createdAt: l.string({ format: 'datetime' }),\n * reply: l.optional(l.object({\n * root: l.ref(() => strongRefSchema),\n * parent: l.ref(() => strongRefSchema),\n * })),\n * }))\n *\n * // Profile record with literal 'self' key\n * const profileSchema = l.record('literal:self', 'app.bsky.actor.profile', l.object({\n * displayName: l.optional(l.string({ maxGraphemes: 64 })),\n * description: l.optional(l.string({ maxGraphemes: 256 })),\n * avatar: l.optional(l.blob({ accept: ['image/*'] })),\n * }))\n *\n * // Build a record with automatic $type injection\n * const post = postSchema.build({ text: 'Hello!', createdAt: new Date().toISOString() })\n * ```\n */\nexport function record<\n const K extends LexiconRecordKey,\n const T extends NsidString,\n const S extends Validator<{ [k: string]: unknown }>,\n>(key: K, type: AsNsid<T>, validator: S): RecordSchema<K, T, S>\nexport function record<\n const K extends LexiconRecordKey,\n const V extends { $type: NsidString },\n>(\n key: K,\n type: AsNsid<V['$type']>,\n validator: Validator<Omit<V, '$type'>>,\n): RecordSchema<K, V['$type'], Validator<Omit<V, '$type'>>>\n/*@__NO_SIDE_EFFECTS__*/\nexport function record<\n const K extends LexiconRecordKey,\n const T extends NsidString,\n const S extends Validator<{ [k: string]: unknown }>,\n>(key: K, type: T, validator: S) {\n return new RecordSchema<K, T, S>(key, type, validator)\n}\n"]}
|
package/dist/schema/ref.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export type RefSchemaGetter<out TValidator extends Validator> = () => TValidator
|
|
|
22
22
|
* })
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
|
-
export declare class RefSchema<const TValidator extends Validator> extends Schema<InferInput<TValidator>, InferOutput<TValidator
|
|
25
|
+
export declare class RefSchema<const TValidator extends Validator> extends Schema<InferInput<TValidator>, InferOutput<TValidator>> implements WrappedValidator<TValidator> {
|
|
26
26
|
#private;
|
|
27
27
|
readonly type: "ref";
|
|
28
28
|
constructor(getter: RefSchemaGetter<TValidator>);
|
package/dist/schema/ref.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/schema/ref.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,GAAG,CAAC,UAAU,SAAS,SAAS,IAAI,MAAM,UAAU,CAAA;AAEhF;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,SAAS,CAAC,KAAK,CAAC,UAAU,SAAS,SAAS,CACvD,SAAQ,MAAM,
|
|
1
|
+
{"version":3,"file":"ref.d.ts","sourceRoot":"","sources":["../../src/schema/ref.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,EACT,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,GAAG,CAAC,UAAU,SAAS,SAAS,IAAI,MAAM,UAAU,CAAA;AAEhF;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,SAAS,CAAC,KAAK,CAAC,UAAU,SAAS,SAAS,CACvD,SAAQ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAC9D,YAAW,gBAAgB,CAAC,UAAU,CAAC;;IAEvC,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAS;gBAIlB,MAAM,EAAE,eAAe,CAAC,UAAU,CAAC;IAS/C,IAAI,SAAS,IAAI,UAAU,CAE1B;IAED,MAAM,IAAI,UAAU;IAIpB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAGzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,wBAAgB,GAAG,CAAC,KAAK,CAAC,UAAU,SAAS,SAAS,EACpD,GAAG,EAAE,eAAe,CAAC,UAAU,CAAC,GAC/B,SAAS,CAAC,UAAU,CAAC,CAAA;AACxB,wBAAgB,GAAG,CAAC,MAAM,EAAE,OAAO,SAAS,MAAM,GAAG,MAAM,EACzD,GAAG,EAAE,eAAe,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAC/C,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA"}
|
package/dist/schema/ref.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ref.js","sourceRoot":"","sources":["../../src/schema/ref.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ref.js","sourceRoot":"","sources":["../../src/schema/ref.ts"],"names":[],"mappings":";;;AAkGA,kBAIC;AAtGD,wCAOmB;AASnB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAa,SACX,SAAQ,gBAAuD;IAGtD,IAAI,GAAG,KAAc,CAAA;IAE9B,OAAO,CAA6B;IAEpC,YAAY,MAAmC;QAC7C,uEAAuE;QACvE,sEAAsE;QAEtE,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IAC5C,CAAC;CACF;AA5BD,8BA4BC;AAqCD,SAAgB,GAAG,CACjB,GAAgC;IAEhC,OAAO,IAAI,SAAS,CAAa,GAAG,CAAC,CAAA;AACvC,CAAC","sourcesContent":["import {\n InferInput,\n InferOutput,\n Schema,\n ValidationContext,\n Validator,\n WrappedValidator,\n} from '../core.js'\n\n/**\n * Function type that returns a validator, used for lazy schema resolution.\n *\n * @template TValidator - The validator type that will be returned\n */\nexport type RefSchemaGetter<out TValidator extends Validator> = () => TValidator\n\n/**\n * Schema for creating references to other schemas with lazy resolution.\n *\n * Useful for handling circular references or breaking module dependency cycles.\n * The referenced schema is resolved lazily when first needed for validation.\n *\n * @template TValidator - The referenced validator type\n *\n * @example\n * ```ts\n * // Self-referential schema for tree structure\n * const nodeSchema = l.object({\n * value: l.string(),\n * children: l.array(l.ref(() => nodeSchema)),\n * })\n * ```\n */\nexport class RefSchema<const TValidator extends Validator>\n extends Schema<InferInput<TValidator>, InferOutput<TValidator>>\n implements WrappedValidator<TValidator>\n{\n readonly type = 'ref' as const\n\n #getter: RefSchemaGetter<TValidator>\n\n constructor(getter: RefSchemaGetter<TValidator>) {\n // @NOTE In order to avoid circular dependency issues, we don't resolve\n // the schema here. Instead, we resolve it lazily when first accessed.\n\n super()\n\n this.#getter = getter\n }\n\n get validator(): TValidator {\n return this.#getter.call(null)\n }\n\n unwrap(): TValidator {\n return this.validator\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n return ctx.validate(input, this.validator)\n }\n}\n\n/**\n * Creates a reference schema with lazy resolution.\n *\n * Allows referencing schemas that may not be defined yet, enabling\n * circular references and breaking dependency cycles. The getter function\n * is called lazily when validation is first performed.\n *\n * @param get - Function that returns the referenced validator\n * @returns A new {@link RefSchema} instance\n *\n * @example\n * ```ts\n * // Circular reference - tree node that contains children of the same type\n * const treeNodeSchema = l.object({\n * name: l.string(),\n * children: l.optional(l.array(l.ref(() => treeNodeSchema))),\n * })\n *\n * // Cross-module reference\n * const commentSchema = l.object({\n * text: l.string(),\n * author: l.ref(() => userSchema), // userSchema defined elsewhere\n * })\n *\n * // Explicitly typed reference\n * const itemSchema = l.ref<Item>(() => complexItemSchema)\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function ref<const TValidator extends Validator>(\n get: RefSchemaGetter<TValidator>,\n): RefSchema<TValidator>\nexport function ref<TInput, TOutput extends TInput = TInput>(\n get: RefSchemaGetter<Validator<TInput, TOutput>>,\n): RefSchema<Validator<TInput, TOutput>>\nexport function ref<const TValidator extends Validator>(\n get: RefSchemaGetter<TValidator>,\n) {\n return new RefSchema<TValidator>(get)\n}\n"]}
|
package/dist/schema/refine.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refine.d.ts","sourceRoot":"","sources":["../../src/schema/refine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,
|
|
1
|
+
{"version":3,"file":"refine.d.ts","sourceRoot":"","sources":["../../src/schema/refine.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAIV,SAAS,EACV,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAA;AAEpD;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,sBAAsB,KAAK,OAAO,CAAA;IACzD,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,WAAW,EAAE,CAAA;CAC5C,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,IAAI;IAClD,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,sBAAsB,KAAK,KAAK,IAAI,GAAG,CAAA;IAC1E,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,WAAW,EAAE,CAAA;CAC5C,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,IAC3B,CAAC,SAAS,eAAe,CAAC,MAAM,CAAC,CAAC,GAC9B,CAAC,GACD,CAAC,SAAS,mBAAmB,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,GACzC,CAAC,GACD,KAAK,CAAA;AAEb;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,IAC7C,eAAe,CAAC,CAAC,CAAC,GAClB,mBAAmB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAE/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,MAAM,CACpB,KAAK,CAAC,UAAU,SAAS,SAAS,EAClC,MAAM,SAAS,UAAU,CAAC,UAAU,CAAC,EAErC,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,mBAAmB,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,GAC9D,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC,CAAA;AACjC,wBAAgB,MAAM,CAAC,KAAK,CAAC,UAAU,SAAS,SAAS,EACvD,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,eAAe,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,GAClD,UAAU,CAAA;AACb,wBAAgB,MAAM,CACpB,WAAW,SAAS,UAAU,EAC9B,KAAK,CAAC,UAAU,SAAS,SAAS,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,EAChE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,GAAG,UAAU,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refine.js","sourceRoot":"","sources":["../../src/schema/refine.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"refine.js","sourceRoot":"","sources":["../../src/schema/refine.ts"],"names":[],"mappings":";;AAkHA,wBAiBC;AAnID,wCAMmB;AA2GnB,wBAAwB;AACxB,SAAgB,MAAM,CACpB,MAAkB,EAClB,UAA+B;IAE/B,wEAAwE;IACxE,4EAA4E;IAC5E,4EAA4E;IAC5E,6BAA6B;IAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE;QAC3B,iBAAiB,EAAE;YACjB,8DAA8D;YAC9D,KAAK,EAAE,wBAAwB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YAC5D,UAAU,EAAE,KAAK;YACjB,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,IAAI;SACnB;KACF,CAAC,CAAA;AACJ,CAAC;AAED,wBAAwB;AACxB,SAAS,wBAAwB,CAK/B,KAAc,EACd,GAAsB;IAEtB,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAC/C,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,MAAM,CAAA;IAElC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IACvE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACjD,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,qBAAW,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAA;IACzE,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC","sourcesContent":["import {\n InferInput,\n IssueCustom,\n ValidationContext,\n ValidationResult,\n Validator,\n} from '../core.js'\nimport { CustomAssertionContext } from './custom.js'\n\n/**\n * Configuration for a refinement check that validates a condition.\n *\n * @template T - The type being validated\n * @property check - Function that returns true if the value passes the check\n * @property message - Error message when the check fails\n * @property path - Optional path to associate with the error\n */\nexport type RefinementCheck<T> = {\n check: (value: T, ctx: CustomAssertionContext) => boolean\n message: string\n path?: PropertyKey | readonly PropertyKey[]\n}\n\n/**\n * Configuration for a refinement assertion that narrows the type.\n *\n * @template T - The input type being validated\n * @template Out - The narrowed output type\n * @property check - Type guard function that narrows the type\n * @property message - Error message when the assertion fails\n * @property path - Optional path to associate with the error\n */\nexport type RefinementAssertion<T, Out extends T> = {\n check: (this: null, value: T, ctx: CustomAssertionContext) => value is Out\n message: string\n path?: PropertyKey | readonly PropertyKey[]\n}\n\n/**\n * Infers the input type from a refinement configuration.\n *\n * @template R - The refinement type\n */\nexport type InferRefinement<R> =\n R extends RefinementCheck<infer T>\n ? T\n : R extends RefinementAssertion<infer T, any>\n ? T\n : never\n\n/**\n * Union type of refinement check or assertion.\n *\n * @template T - The input type being validated\n * @template Out - The output type (same as T for checks, narrowed for assertions)\n */\nexport type Refinement<T = any, Out extends T = T> =\n | RefinementCheck<T>\n | RefinementAssertion<T, Out>\n\n/**\n * Creates a refined schema by adding additional validation constraints.\n *\n * Wraps an existing schema with an additional check function. The base schema\n * is validated first, then the refinement check is applied to the result.\n *\n * @param schema - The base schema to refine\n * @param refinement - The refinement check or assertion to apply\n * @returns A new schema that includes the refinement\n *\n * @example\n * ```ts\n * // Simple check refinement\n * const positiveInt = l.refine(l.integer(), {\n * check: (value) => value > 0,\n * message: 'Value must be positive',\n * })\n *\n * positiveInt.parse(5) // 5\n * positiveInt.parse(-1) // throws\n *\n * // Type-narrowing assertion\n * const nonEmptyString = l.refine(l.string(), {\n * check: (value): value is string & { length: number } => value.length > 0,\n * message: 'String must not be empty',\n * })\n *\n * // With custom path for nested errors\n * const validDateRange = l.refine(\n * l.object({ start: l.string(), end: l.string() }),\n * {\n * check: (v) => new Date(v.start) < new Date(v.end),\n * message: 'Start date must be before end date',\n * path: ['end'],\n * }\n * )\n * ```\n */\nexport function refine<\n const TValidator extends Validator,\n TInput extends InferInput<TValidator>,\n>(\n schema: TValidator,\n refinement: RefinementAssertion<InferInput<TValidator>, TInput>,\n): TValidator & Validator<TInput>\nexport function refine<const TValidator extends Validator>(\n schema: TValidator,\n refinement: RefinementCheck<InferInput<TValidator>>,\n): TValidator\nexport function refine<\n TRefinement extends Refinement,\n const TValidator extends Validator<InferRefinement<TRefinement>>,\n>(schema: TValidator, refinement: TRefinement): TValidator\n/*@__NO_SIDE_EFFECTS__*/\nexport function refine<const TValidator extends Validator>(\n schema: TValidator,\n refinement: Refinement<unknown>,\n): TValidator {\n // This is basically the same as monkey patching the \"validateInContext\"\n // method to the schema, but done in a way that does not mutate the original\n // schema. This is safe to do because Validators don't update their internal\n // state over their lifetime.\n return Object.create(schema, {\n validateInContext: {\n // We do not use an arrow function to avoid creating a closure\n value: validateInContextUnbound.bind({ schema, refinement }),\n enumerable: false,\n writable: false,\n configurable: true,\n },\n })\n}\n\n/*@__NO_SIDE_EFFECTS__*/\nfunction validateInContextUnbound<S extends Validator>(\n this: {\n schema: S\n refinement: Refinement<InferInput<S>>\n },\n input: unknown,\n ctx: ValidationContext,\n): ValidationResult<InferInput<S>> {\n const result = ctx.validate(input, this.schema)\n if (!result.success) return result\n\n const checkResult = this.refinement.check.call(null, result.value, ctx)\n if (!checkResult) {\n const path = ctx.concatPath(this.refinement.path)\n return ctx.issue(new IssueCustom(path, input, this.refinement.message))\n }\n\n return result\n}\n"]}
|
|
@@ -31,11 +31,19 @@ export declare class TypedObjectSchema<const TType extends $Type = $Type, const
|
|
|
31
31
|
readonly schema: TShape;
|
|
32
32
|
readonly type: "typedObject";
|
|
33
33
|
constructor($type: TType, schema: TShape);
|
|
34
|
-
isTypeOf<TValue extends Record<string, unknown>>(value: TValue): value is MaybeTypedObject<TType, TValue>;
|
|
35
|
-
build(input: Omit<InferInput<this>, '$type'>): $Typed<InferOutput<this>, TType>;
|
|
36
|
-
$isTypeOf<TValue extends Record<string, unknown>>(value: TValue): value is MaybeTypedObject<TType, TValue>;
|
|
37
|
-
$build(input: Omit<InferInput<this>, '$type'>): $Typed<InferOutput<this>, TType>;
|
|
38
34
|
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<InferInput<TShape>>;
|
|
35
|
+
build(input: Omit<InferInput<this>, '$type'>): $Typed<InferOutput<this>, TType>;
|
|
36
|
+
isTypeOf<TValue extends Record<string, unknown>>(value: TValue): value is MaybeTypedObject<TType, TValue>;
|
|
37
|
+
/**
|
|
38
|
+
* Bound alias for {@link build} for compatibility with generated utilities.
|
|
39
|
+
* @see {@link build}
|
|
40
|
+
*/
|
|
41
|
+
get $build(): typeof this.build;
|
|
42
|
+
/**
|
|
43
|
+
* Bound alias for {@link isTypeOf} for compatibility with generated utilities.
|
|
44
|
+
* @see {@link isTypeOf}
|
|
45
|
+
*/
|
|
46
|
+
get $isTypeOf(): typeof this.isTypeOf;
|
|
39
47
|
}
|
|
40
48
|
/**
|
|
41
49
|
* Creates a typed object schema for use in Lexicon unions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-object.d.ts","sourceRoot":"","sources":["../../src/schema/typed-object.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,EACL,OAAO,EACP,MAAM,EACN,WAAW,EAGX,UAAU,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"typed-object.d.ts","sourceRoot":"","sources":["../../src/schema/typed-object.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@ exports.TypedObjectSchema = void 0;
|
|
|
4
4
|
exports.typedObject = typedObject;
|
|
5
5
|
const lex_data_1 = require("@atproto/lex-data");
|
|
6
6
|
const core_js_1 = require("../core.js");
|
|
7
|
+
const lazy_property_js_1 = require("../util/lazy-property.js");
|
|
7
8
|
/**
|
|
8
9
|
* Schema for typed objects in Lexicon unions.
|
|
9
10
|
*
|
|
@@ -31,18 +32,6 @@ class TypedObjectSchema extends core_js_1.Schema {
|
|
|
31
32
|
this.$type = $type;
|
|
32
33
|
this.schema = schema;
|
|
33
34
|
}
|
|
34
|
-
isTypeOf(value) {
|
|
35
|
-
return value.$type === undefined || value.$type === this.$type;
|
|
36
|
-
}
|
|
37
|
-
build(input) {
|
|
38
|
-
return this.parse((0, core_js_1.$typed)(input, this.$type));
|
|
39
|
-
}
|
|
40
|
-
$isTypeOf(value) {
|
|
41
|
-
return this.isTypeOf(value);
|
|
42
|
-
}
|
|
43
|
-
$build(input) {
|
|
44
|
-
return this.build(input);
|
|
45
|
-
}
|
|
46
35
|
validateInContext(input, ctx) {
|
|
47
36
|
if (!(0, lex_data_1.isPlainObject)(input)) {
|
|
48
37
|
return ctx.issueUnexpectedType(input, 'object');
|
|
@@ -54,6 +43,26 @@ class TypedObjectSchema extends core_js_1.Schema {
|
|
|
54
43
|
}
|
|
55
44
|
return ctx.validate(input, this.schema);
|
|
56
45
|
}
|
|
46
|
+
build(input) {
|
|
47
|
+
return this.parse((0, core_js_1.$typed)(input, this.$type));
|
|
48
|
+
}
|
|
49
|
+
isTypeOf(value) {
|
|
50
|
+
return value.$type === undefined || value.$type === this.$type;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Bound alias for {@link build} for compatibility with generated utilities.
|
|
54
|
+
* @see {@link build}
|
|
55
|
+
*/
|
|
56
|
+
get $build() {
|
|
57
|
+
return (0, lazy_property_js_1.lazyProperty)(this, '$build', this.build.bind(this));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Bound alias for {@link isTypeOf} for compatibility with generated utilities.
|
|
61
|
+
* @see {@link isTypeOf}
|
|
62
|
+
*/
|
|
63
|
+
get $isTypeOf() {
|
|
64
|
+
return (0, lazy_property_js_1.lazyProperty)(this, '$isTypeOf', this.isTypeOf.bind(this));
|
|
65
|
+
}
|
|
57
66
|
}
|
|
58
67
|
exports.TypedObjectSchema = TypedObjectSchema;
|
|
59
68
|
/*@__NO_SIDE_EFFECTS__*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-object.js","sourceRoot":"","sources":["../../src/schema/typed-object.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"typed-object.js","sourceRoot":"","sources":["../../src/schema/typed-object.ts"],"names":[],"mappings":";;;AA6KA,kCAMC;AAnLD,gDAAiD;AACjD,wCAcmB;AACnB,+DAAuD;AASvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,iBAGX,SAAQ,gBAGT;IAIY;IACA;IAJF,IAAI,GAAG,aAAsB,CAAA;IAEtC,YACW,KAAY,EACZ,MAAc;QAEvB,KAAK,EAAE,CAAA;QAHE,UAAK,GAAL,KAAK,CAAO;QACZ,WAAM,GAAN,MAAM,CAAQ;IAGzB,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,IAAI,CAAC,IAAA,wBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,mBAAmB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QACjD,CAAC;QAED,IACE,OAAO,IAAI,KAAK;YAChB,KAAK,CAAC,KAAK,KAAK,SAAS;YACzB,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAC1B,CAAC;YACD,OAAO,GAAG,CAAC,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;QACpE,CAAC;QAED,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACzC,CAAC;IAED,KAAK,CACH,KAAsC;QAEtC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAA,gBAAM,EAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAG1C,CAAA;IACH,CAAC;IAED,QAAQ,CACN,KAAa;QAEb,OAAO,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAA;IAChE,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,SAAS;QACX,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAClE,CAAC;CACF;AA9DD,8CA8DC;AAmED,wBAAwB;AACxB,SAAgB,WAAW,CAIzB,IAAO,EAAE,IAAO,EAAE,SAAY;IAC9B,OAAO,IAAI,iBAAiB,CAAiB,IAAA,eAAK,EAAC,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS,CAAC,CAAA;AAC5E,CAAC","sourcesContent":["import { isPlainObject } from '@atproto/lex-data'\nimport {\n $Type,\n $TypeOf,\n $Typed,\n $TypedMaybe,\n $type,\n $typed,\n InferInput,\n InferOutput,\n NsidString,\n Schema,\n Unknown$TypedObject,\n ValidationContext,\n Validator,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\n\nexport type MaybeTypedObject<\n TType extends $Type,\n TValue extends { $type?: unknown } = { $type?: unknown },\n> = TValue extends { $type?: TType }\n ? TValue\n : $TypedMaybe<Exclude<TValue, Unknown$TypedObject>, TType>\n\n/**\n * Schema for typed objects in Lexicon unions.\n *\n * Typed objects have a `$type` field that identifies which variant they are\n * in a union. The `$type` can be omitted in input (it's implicit), but if\n * present, it must match the expected value.\n *\n * @template TType - The $type string literal type\n * @template TShape - The validator type for the object's shape\n *\n * @example\n * ```ts\n * const schema = new TypedObjectSchema(\n * 'app.bsky.embed.images#view',\n * l.object({ images: l.array(imageSchema) })\n * )\n * ```\n */\nexport class TypedObjectSchema<\n const TType extends $Type = $Type,\n const TShape extends Validator<{ [k: string]: unknown }> = any,\n> extends Schema<\n $TypedMaybe<InferInput<TShape>, TType>,\n $TypedMaybe<InferOutput<TShape>, TType>\n> {\n readonly type = 'typedObject' as const\n\n constructor(\n readonly $type: TType,\n readonly schema: TShape,\n ) {\n super()\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input)) {\n return ctx.issueUnexpectedType(input, 'object')\n }\n\n if (\n '$type' in input &&\n input.$type !== undefined &&\n input.$type !== this.$type\n ) {\n return ctx.issueInvalidPropertyValue(input, '$type', [this.$type])\n }\n\n return ctx.validate(input, this.schema)\n }\n\n build(\n input: Omit<InferInput<this>, '$type'>,\n ): $Typed<InferOutput<this>, TType> {\n return this.parse($typed(input, this.$type)) as $Typed<\n InferOutput<this>,\n TType\n >\n }\n\n isTypeOf<TValue extends Record<string, unknown>>(\n value: TValue,\n ): value is MaybeTypedObject<TType, TValue> {\n return value.$type === undefined || value.$type === this.$type\n }\n\n /**\n * Bound alias for {@link build} for compatibility with generated utilities.\n * @see {@link build}\n */\n get $build(): typeof this.build {\n return lazyProperty(this, '$build', this.build.bind(this))\n }\n\n /**\n * Bound alias for {@link isTypeOf} for compatibility with generated utilities.\n * @see {@link isTypeOf}\n */\n get $isTypeOf(): typeof this.isTypeOf {\n return lazyProperty(this, '$isTypeOf', this.isTypeOf.bind(this))\n }\n}\n\n/**\n * Creates a typed object schema for use in Lexicon unions.\n *\n * Typed objects are identified by their `$type` field, which combines an NSID\n * and a hash (e.g., 'app.bsky.embed.images#view'). Used for union variants.\n *\n * This function offers two overloads:\n * - One that infers the type from arguments (no circular reference support)\n * - One with explicit interface for codegen with circular references\n *\n * @param nsid - The NSID part of the type (e.g., 'app.bsky.embed.images')\n * @param hash - The hash part of the type (e.g., 'view'), defaults to 'main'\n * @param validator - Schema for validating the object properties\n * @returns A new {@link TypedObjectSchema} instance\n *\n * @example\n * ```ts\n * // Image embed view\n * const imageViewSchema = l.typedObject(\n * 'app.bsky.embed.images',\n * 'view',\n * l.object({\n * images: l.array(l.object({\n * thumb: l.string(),\n * fullsize: l.string(),\n * alt: l.string(),\n * })),\n * })\n * )\n *\n * // Main type (hash defaults to 'main')\n * const postViewSchema = l.typedObject(\n * 'app.bsky.feed.defs',\n * 'postView',\n * l.object({ uri: l.string(), cid: l.string(), author: authorSchema })\n * )\n *\n * // Use $isTypeOf to narrow union types\n * if (imageViewSchema.$isTypeOf(embed)) {\n * // embed is narrowed to image view type\n * }\n *\n * // Use $build to construct typed objects\n * const view = imageViewSchema.$build({ images: [...] })\n * // view.$type === 'app.bsky.embed.images#view'\n * ```\n */\nexport function typedObject<\n const N extends NsidString,\n const H extends string,\n const S extends Validator<{ [k: string]: unknown }>,\n>(nsid: N, hash: H, validator: S): TypedObjectSchema<$Type<N, H>, S>\nexport function typedObject<V extends { $type?: $Type }>(\n nsid: V extends { $type?: infer T extends string }\n ? T extends `${infer N}#${string}`\n ? N\n : T // (T is a \"main\" type, so already an NSID)\n : never,\n hash: V extends { $type?: infer T extends string }\n ? T extends `${string}#${infer H}`\n ? H\n : 'main'\n : never,\n validator: Validator<Omit<V, '$type'>>,\n): TypedObjectSchema<$TypeOf<V>, Validator<V>>\n/*@__NO_SIDE_EFFECTS__*/\nexport function typedObject<\n const N extends NsidString,\n const H extends string,\n const S extends Validator<{ [k: string]: unknown }>,\n>(nsid: N, hash: H, validator: S) {\n return new TypedObjectSchema<$Type<N, H>, S>($type(nsid, hash), validator)\n}\n"]}
|
|
@@ -41,7 +41,7 @@ export declare class TypedRefSchema<const TValidator extends TypedObjectValidato
|
|
|
41
41
|
constructor(getter: TypedRefGetter<TValidator>);
|
|
42
42
|
get validator(): TValidator;
|
|
43
43
|
get $type(): TValidator['$type'];
|
|
44
|
-
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").
|
|
44
|
+
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<InferInput<TValidator>>;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* Creates a reference to a typed object schema for use in typed unions.
|
|
@@ -26,7 +26,7 @@ export declare class TypedUnionSchema<const TValidators extends readonly (TypedR
|
|
|
26
26
|
constructor(validators: TValidators, closed: TClosed);
|
|
27
27
|
get validatorsMap(): Map<unknown, TValidators[number]>;
|
|
28
28
|
get $types(): unknown[];
|
|
29
|
-
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").
|
|
29
|
+
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").LexValidationError | import("../core.js").ValidationSuccess<Record<string, unknown>> | import("../core.js").ValidationSuccess<InferInput<TValidators[number]>>;
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
32
32
|
* Creates a typed union schema for Lexicon unions.
|
package/dist/schema/union.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InferInput, InferOutput, Schema, ValidationContext,
|
|
1
|
+
import { InferInput, InferOutput, LexValidationError, Schema, ValidationContext, Validator } from '../core.js';
|
|
2
2
|
/**
|
|
3
3
|
* Type representing a non-empty tuple of validators for union schemas.
|
|
4
4
|
*
|
|
@@ -25,7 +25,7 @@ export declare class UnionSchema<const TValidators extends UnionSchemaValidators
|
|
|
25
25
|
protected readonly validators: TValidators;
|
|
26
26
|
readonly type: "union";
|
|
27
27
|
constructor(validators: TValidators);
|
|
28
|
-
validateInContext(input: unknown, ctx: ValidationContext):
|
|
28
|
+
validateInContext(input: unknown, ctx: ValidationContext): LexValidationError | import("../core.js").ValidationSuccess<unknown>;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
31
|
* Creates a union schema that accepts values matching any of the provided schemas.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"union.d.ts","sourceRoot":"","sources":["../../src/schema/union.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EAEjB,
|
|
1
|
+
{"version":3,"file":"union.d.ts","sourceRoot":"","sources":["../../src/schema/union.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,MAAM,EACN,iBAAiB,EAEjB,SAAS,EACV,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,CAAC,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC,CAAA;AAExE;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,WAAW,CACtB,KAAK,CAAC,WAAW,SAAS,qBAAqB,GAAG,GAAG,CACrD,SAAQ,MAAM,CACd,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAC/B,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CACjC;IAGa,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,WAAW;IAFtD,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;gBAED,UAAU,EAAE,WAAW;IAItD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAYzD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,wBAAgB,KAAK,CAAC,KAAK,CAAC,WAAW,SAAS,qBAAqB,EACnE,UAAU,EAAE,WAAW,4BAGxB"}
|
package/dist/schema/union.js
CHANGED
|
@@ -34,7 +34,7 @@ class UnionSchema extends core_js_1.Schema {
|
|
|
34
34
|
return result;
|
|
35
35
|
failures.push(result);
|
|
36
36
|
}
|
|
37
|
-
return ctx.failure(core_js_1.
|
|
37
|
+
return ctx.failure(core_js_1.LexValidationError.fromFailures(failures));
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
exports.UnionSchema = UnionSchema;
|
package/dist/schema/union.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"union.js","sourceRoot":"","sources":["../../src/schema/union.ts"],"names":[],"mappings":";;;AAoFA,sBAIC;AAxFD,wCAQmB;AASnB;;;;;;;;;;;;;;;GAeG;AACH,MAAa,WAEX,SAAQ,gBAGT;IAGgC;IAFtB,IAAI,GAAG,OAAgB,CAAA;IAEhC,YAA+B,UAAuB;QACpD,KAAK,EAAE,CAAA;QADsB,eAAU,GAAV,UAAU,CAAa;IAEtD,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,MAAM,QAAQ,GAAwB,EAAE,CAAA;QAExC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;YAC7C,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO,MAAM,CAAA;YAEjC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC;QAED,OAAO,GAAG,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"union.js","sourceRoot":"","sources":["../../src/schema/union.ts"],"names":[],"mappings":";;;AAoFA,sBAIC;AAxFD,wCAQmB;AASnB;;;;;;;;;;;;;;;GAeG;AACH,MAAa,WAEX,SAAQ,gBAGT;IAGgC;IAFtB,IAAI,GAAG,OAAgB,CAAA;IAEhC,YAA+B,UAAuB;QACpD,KAAK,EAAE,CAAA;QADsB,eAAU,GAAV,UAAU,CAAa;IAEtD,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,MAAM,QAAQ,GAAwB,EAAE,CAAA;QAExC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;YAC7C,IAAI,MAAM,CAAC,OAAO;gBAAE,OAAO,MAAM,CAAA;YAEjC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC;QAED,OAAO,GAAG,CAAC,OAAO,CAAC,4BAAkB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC/D,CAAC;CACF;AAxBD,kCAwBC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAwB;AACxB,SAAgB,KAAK,CACnB,UAAuB;IAEvB,OAAO,IAAI,WAAW,CAAc,UAAU,CAAC,CAAA;AACjD,CAAC","sourcesContent":["import {\n InferInput,\n InferOutput,\n LexValidationError,\n Schema,\n ValidationContext,\n ValidationFailure,\n Validator,\n} from '../core.js'\n\n/**\n * Type representing a non-empty tuple of validators for union schemas.\n *\n * Requires at least one validator in the tuple.\n */\nexport type UnionSchemaValidators = readonly [Validator, ...Validator[]]\n\n/**\n * Schema for validating values that match one of several possible schemas.\n *\n * Tries each validator in order until one succeeds. If all validators fail,\n * returns a combined error from all attempts.\n *\n * @template TValidators - Tuple type of the validators in the union\n *\n * @example\n * ```ts\n * const schema = new UnionSchema([l.string(), l.integer()])\n * schema.validate('hello') // success\n * schema.validate(42) // success\n * schema.validate(true) // fails\n * ```\n */\nexport class UnionSchema<\n const TValidators extends UnionSchemaValidators = any,\n> extends Schema<\n InferInput<TValidators[number]>,\n InferOutput<TValidators[number]>\n> {\n readonly type = 'union' as const\n\n constructor(protected readonly validators: TValidators) {\n super()\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n const failures: ValidationFailure[] = []\n\n for (const validator of this.validators) {\n const result = ctx.validate(input, validator)\n if (result.success) return result\n\n failures.push(result)\n }\n\n return ctx.failure(LexValidationError.fromFailures(failures))\n }\n}\n\n/**\n * Creates a union schema that accepts values matching any of the provided schemas.\n *\n * Validators are tried in order. Use `discriminatedUnion()` for better\n * performance when discriminating on a known property.\n *\n * @param validators - Non-empty array of validators to try\n * @returns A new {@link UnionSchema} instance\n *\n * @example\n * ```ts\n * // String or number\n * const stringOrNumber = l.union([l.string(), l.integer()])\n *\n * // Nullable value\n * const nullableString = l.union([l.string(), l.null()])\n *\n * // Multiple object types\n * const mediaSchema = l.union([\n * l.object({ type: l.literal('image'), url: l.string() }),\n * l.object({ type: l.literal('video'), url: l.string(), duration: l.integer() }),\n * ])\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function union<const TValidators extends UnionSchemaValidators>(\n validators: TValidators,\n) {\n return new UnionSchema<TValidators>(validators)\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-schema",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.15",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Lexicon schema system for AT Lexicons",
|
|
6
6
|
"keywords": [
|
|
@@ -35,9 +35,10 @@
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"@standard-schema/spec": "^1.1.0",
|
|
38
39
|
"tslib": "^2.8.1",
|
|
39
|
-
"@atproto/syntax": "^0.
|
|
40
|
-
"@atproto/lex-data": "^0.0.
|
|
40
|
+
"@atproto/syntax": "^0.5.1",
|
|
41
|
+
"@atproto/lex-data": "^0.0.13"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
43
44
|
"vitest": "^4.0.16"
|