@atproto/lex-schema 0.0.10 → 0.0.12
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 +26 -0
- package/dist/core/$type.d.ts +149 -0
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +44 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +44 -0
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js +30 -0
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.d.ts +85 -4
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +60 -4
- package/dist/core/result.js.map +1 -1
- package/dist/core/schema.d.ts +229 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +197 -4
- package/dist/core/schema.js.map +1 -1
- package/dist/core/string-format.d.ts +244 -11
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +150 -0
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.d.ts +90 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/validation-error.d.ts +61 -1
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +60 -0
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validation-issue.d.ts +61 -0
- package/dist/core/validation-issue.d.ts.map +1 -1
- package/dist/core/validation-issue.js +51 -0
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +347 -10
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +184 -3
- package/dist/core/validator.js.map +1 -1
- package/dist/helpers.d.ts +13 -25
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +45 -0
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +14 -0
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +46 -0
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +39 -0
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +28 -0
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +28 -0
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +38 -0
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +32 -0
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +38 -0
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +33 -0
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +66 -1
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +54 -0
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +44 -0
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +44 -0
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +58 -0
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +45 -0
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +48 -0
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +48 -0
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +42 -0
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +36 -0
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +54 -0
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +49 -0
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +44 -0
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +44 -0
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +42 -0
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +42 -0
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +29 -0
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +29 -0
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +41 -0
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +41 -0
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +56 -0
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +51 -0
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +42 -0
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +42 -0
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +89 -7
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +84 -10
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +111 -15
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +70 -0
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +58 -0
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +50 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +42 -0
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +39 -0
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +64 -0
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +64 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +55 -0
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +55 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +63 -8
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +20 -0
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +50 -0
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +17 -0
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +58 -9
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.d.ts +44 -0
- package/dist/schema/regexp.d.ts.map +1 -1
- package/dist/schema/regexp.js +44 -0
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +50 -0
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +41 -0
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +72 -2
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +59 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +47 -0
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +47 -0
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +62 -8
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +18 -0
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +53 -0
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +15 -0
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +50 -1
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +50 -1
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +45 -0
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +40 -0
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +34 -0
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +31 -0
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +33 -0
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +33 -0
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +44 -0
- package/dist/schema/with-default.d.ts.map +1 -1
- package/dist/schema/with-default.js +44 -0
- package/dist/schema/with-default.js.map +1 -1
- package/package.json +4 -4
- package/src/core/$type.ts +150 -18
- package/src/core/record-key.ts +44 -0
- package/src/core/result.ts +86 -4
- package/src/core/schema.ts +236 -7
- package/src/core/string-format.ts +259 -13
- package/src/core/types.ts +91 -3
- package/src/core/validation-error.ts +60 -0
- package/src/core/validation-issue.ts +65 -0
- package/src/core/validator.ts +351 -10
- package/src/helpers.test.ts +110 -29
- package/src/helpers.ts +14 -14
- package/src/schema/array.test.ts +94 -79
- package/src/schema/array.ts +45 -0
- package/src/schema/blob.ts +46 -0
- package/src/schema/boolean.ts +28 -0
- package/src/schema/bytes.ts +38 -0
- package/src/schema/cid.ts +38 -0
- package/src/schema/custom.ts +66 -1
- package/src/schema/dict.ts +44 -0
- package/src/schema/discriminated-union.ts +58 -0
- package/src/schema/enum.ts +48 -0
- package/src/schema/integer.ts +42 -0
- package/src/schema/intersection.ts +54 -0
- package/src/schema/literal.ts +44 -0
- package/src/schema/never.ts +42 -0
- package/src/schema/null.ts +29 -0
- package/src/schema/nullable.ts +41 -0
- package/src/schema/object.ts +56 -0
- package/src/schema/optional.ts +42 -0
- package/src/schema/params.test.ts +58 -2
- package/src/schema/params.ts +124 -16
- package/src/schema/payload.test.ts +3 -3
- package/src/schema/payload.ts +142 -38
- package/src/schema/permission-set.ts +58 -0
- package/src/schema/permission.ts +42 -0
- package/src/schema/procedure.ts +64 -0
- package/src/schema/query.ts +55 -0
- package/src/schema/record.ts +63 -8
- package/src/schema/ref.ts +50 -0
- package/src/schema/refine.ts +58 -9
- package/src/schema/regexp.ts +44 -0
- package/src/schema/string.ts +50 -0
- package/src/schema/subscription.ts +72 -2
- package/src/schema/token.ts +47 -0
- package/src/schema/typed-object.ts +62 -8
- package/src/schema/typed-ref.ts +53 -0
- package/src/schema/typed-union.ts +55 -2
- package/src/schema/union.ts +45 -0
- package/src/schema/unknown-object.ts +34 -0
- package/src/schema/unknown.ts +33 -0
- package/src/schema/with-default.ts +44 -0
package/dist/schema/token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/schema/token.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/schema/token.ts"],"names":[],"mappings":";;;AAuFA,sBAKC;AA5FD,wCAAyE;AAEzE;;;;;;;;;;;;;;GAcG;AACH,MAAa,WAEX,SAAQ,gBAAc;IACD;IAArB,YAAqB,KAAa;QAChC,KAAK,EAAE,CAAA;QADY,UAAK,GAAL,KAAK,CAAQ;IAElC,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACzB,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;QAED,0EAA0E;QAC1E,eAAe;QACf,IAAI,KAAK,YAAY,WAAW,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/D,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAC7C,CAAC;QAED,OAAO,GAAG,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;IACnD,CAAC;IAED,yEAAyE;IACzE,cAAc;IAEd,MAAM;QACJ,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;CACF;AAnCD,kCAmCC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAwB;AACxB,SAAgB,KAAK,CAGnB,IAAO,EAAE,OAAU,MAAW;IAC9B,OAAO,IAAI,WAAW,CAAC,IAAA,eAAK,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAC3C,CAAC","sourcesContent":["import { $type, NsidString, Schema, ValidationContext } from '../core.js'\n\n/**\n * Schema for Lexicon token values.\n *\n * Tokens are named constants in Lexicon, identified by their NSID and hash.\n * They validate to their string value (e.g., 'app.bsky.feed.defs#requestLess').\n * TokenSchema instances can also be used as values themselves.\n *\n * @template TValue - The token string literal type\n *\n * @example\n * ```ts\n * const schema = new TokenSchema('app.bsky.feed.defs#requestLess')\n * schema.validate('app.bsky.feed.defs#requestLess') // success\n * ```\n */\nexport class TokenSchema<\n const TValue extends string = string,\n> extends Schema<TValue> {\n constructor(readonly value: TValue) {\n super()\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (input === this.value) {\n return ctx.success(this.value)\n }\n\n // @NOTE: allow using the token instance itself (but convert to the actual\n // token value)\n if (input instanceof TokenSchema && input.value === this.value) {\n return ctx.success(this.value)\n }\n\n if (typeof input !== 'string') {\n return ctx.issueInvalidType(input, 'token')\n }\n\n return ctx.issueInvalidValue(input, [this.value])\n }\n\n // When using the TokenSchema instance as data, let's serialize it to the\n // token value\n\n toJSON(): string {\n return this.value\n }\n\n toString(): string {\n return this.value\n }\n}\n\n/**\n * Creates a token schema for Lexicon named constants.\n *\n * Tokens are used in Lexicon as named constants or enum-like values.\n * The token instance can be used both as a schema validator and as\n * the token value itself (it serializes to its string value).\n *\n * @param nsid - The NSID part of the token\n * @param hash - The hash part of the token (defaults to 'main')\n * @returns A new {@link TokenSchema} instance\n *\n * @example\n * ```ts\n * // Define tokens\n * const requestLess = l.token('app.bsky.feed.defs', 'requestLess')\n * const requestMore = l.token('app.bsky.feed.defs', 'requestMore')\n *\n * // Use as a value\n * console.log(requestLess.toString()) // 'app.bsky.feed.defs#requestLess'\n *\n * // Use in union for validation\n * const feedbackSchema = l.union([requestLess, requestMore])\n *\n * // Validate\n * feedbackSchema.parse('app.bsky.feed.defs#requestLess') // success\n *\n * // Token instances can be used as values in other schemas\n * const feedbackRequest = l.object({\n * feedback: requestLess, // Accepts the token value\n * })\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function token<\n const N extends NsidString,\n const H extends string = 'main',\n>(nsid: N, hash: H = 'main' as H) {\n return new TokenSchema($type(nsid, hash))\n}\n"]}
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import { $Type, $TypeOf, $Typed, $TypedMaybe, InferInput, InferOutput, NsidString, Schema, Unknown$TypedObject, ValidationContext, Validator } from '../core.js';
|
|
2
|
+
/**
|
|
3
|
+
* Schema for typed objects in Lexicon unions.
|
|
4
|
+
*
|
|
5
|
+
* Typed objects have a `$type` field that identifies which variant they are
|
|
6
|
+
* in a union. The `$type` can be omitted in input (it's implicit), but if
|
|
7
|
+
* present, it must match the expected value.
|
|
8
|
+
*
|
|
9
|
+
* @template TType - The $type string literal type
|
|
10
|
+
* @template TShape - The validator type for the object's shape
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* const schema = new TypedObjectSchema(
|
|
15
|
+
* 'app.bsky.embed.images#view',
|
|
16
|
+
* l.object({ images: l.array(imageSchema) })
|
|
17
|
+
* )
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
2
20
|
export declare class TypedObjectSchema<const TType extends $Type = $Type, const TShape extends Validator<{
|
|
3
21
|
[k: string]: unknown;
|
|
4
22
|
}> = any> extends Schema<$TypedMaybe<InferInput<TShape>, TType>, $TypedMaybe<InferOutput<TShape>, TType>> {
|
|
@@ -24,15 +42,51 @@ export declare class TypedObjectSchema<const TType extends $Type = $Type, const
|
|
|
24
42
|
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<InferInput<TShape>>;
|
|
25
43
|
}
|
|
26
44
|
/**
|
|
45
|
+
* Creates a typed object schema for use in Lexicon unions.
|
|
46
|
+
*
|
|
47
|
+
* Typed objects are identified by their `$type` field, which combines an NSID
|
|
48
|
+
* and a hash (e.g., 'app.bsky.embed.images#view'). Used for union variants.
|
|
49
|
+
*
|
|
27
50
|
* This function offers two overloads:
|
|
28
|
-
* - One that
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
51
|
+
* - One that infers the type from arguments (no circular reference support)
|
|
52
|
+
* - One with explicit interface for codegen with circular references
|
|
53
|
+
*
|
|
54
|
+
* @param nsid - The NSID part of the type (e.g., 'app.bsky.embed.images')
|
|
55
|
+
* @param hash - The hash part of the type (e.g., 'view'), defaults to 'main'
|
|
56
|
+
* @param validator - Schema for validating the object properties
|
|
57
|
+
* @returns A new {@link TypedObjectSchema} instance
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* // Image embed view
|
|
62
|
+
* const imageViewSchema = l.typedObject(
|
|
63
|
+
* 'app.bsky.embed.images',
|
|
64
|
+
* 'view',
|
|
65
|
+
* l.object({
|
|
66
|
+
* images: l.array(l.object({
|
|
67
|
+
* thumb: l.string(),
|
|
68
|
+
* fullsize: l.string(),
|
|
69
|
+
* alt: l.string(),
|
|
70
|
+
* })),
|
|
71
|
+
* })
|
|
72
|
+
* )
|
|
73
|
+
*
|
|
74
|
+
* // Main type (hash defaults to 'main')
|
|
75
|
+
* const postViewSchema = l.typedObject(
|
|
76
|
+
* 'app.bsky.feed.defs',
|
|
77
|
+
* 'postView',
|
|
78
|
+
* l.object({ uri: l.string(), cid: l.string(), author: authorSchema })
|
|
79
|
+
* )
|
|
80
|
+
*
|
|
81
|
+
* // Use $isTypeOf to narrow union types
|
|
82
|
+
* if (imageViewSchema.$isTypeOf(embed)) {
|
|
83
|
+
* // embed is narrowed to image view type
|
|
84
|
+
* }
|
|
85
|
+
*
|
|
86
|
+
* // Use $build to construct typed objects
|
|
87
|
+
* const view = imageViewSchema.$build({ images: [...] })
|
|
88
|
+
* // view.$type === 'app.bsky.embed.images#view'
|
|
89
|
+
* ```
|
|
36
90
|
*/
|
|
37
91
|
export declare function typedObject<const N extends NsidString, const H extends string, const S extends Validator<{
|
|
38
92
|
[k: string]: unknown;
|
|
@@ -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;AAEnB,qBAAa,iBAAiB,CAC5B,KAAK,CAAC,KAAK,SAAS,KAAK,GAAG,KAAK,EACjC,KAAK,CAAC,MAAM,SAAS,SAAS,CAAC;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,GAAG,GAAG,CAC9D,SAAQ,MAAM,CACd,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,EACtC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CACxC;IAEG,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM;IAKzB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,SAAS;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GACnC,CAAC,GACD,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,mBAAmB,CAAC,EAAE,KAAK,CAAC;IAIvD,KAAK,CACH,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,GACrC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IAOnC,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;gBAfrB,KAAK;;;;;;IAmBrC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;;;;;IAI7C,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAezD;AAED
|
|
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;AAEnB;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,iBAAiB,CAC5B,KAAK,CAAC,KAAK,SAAS,KAAK,GAAG,KAAK,EACjC,KAAK,CAAC,MAAM,SAAS,SAAS,CAAC;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,GAAG,GAAG,CAC9D,SAAQ,MAAM,CACd,WAAW,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,EACtC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CACxC;IAEG,QAAQ,CAAC,KAAK,EAAE,KAAK;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADd,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM;IAKzB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,SAAS;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,GACnC,CAAC,GACD,WAAW,CAAC,OAAO,CAAC,CAAC,EAAE,mBAAmB,CAAC,EAAE,KAAK,CAAC;IAIvD,KAAK,CACH,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,GACrC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IAOnC,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;gBAfrB,KAAK;;;;;;IAmBrC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;;;;;IAI7C,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAezD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,wBAAgB,WAAW,CACzB,KAAK,CAAC,CAAC,SAAS,UAAU,EAC1B,KAAK,CAAC,CAAC,SAAS,MAAM,EACtB,KAAK,CAAC,CAAC,SAAS,SAAS,CAAC;IAAE,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC,EACnD,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACpE,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,EACrD,IAAI,EAAE,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;CAAE,GAC9C,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,MAAM,EAAE,GAC9B,CAAC,GACD,CAAC,GACH,KAAK,EACT,IAAI,EAAE,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC,SAAS,MAAM,CAAA;CAAE,GAC9C,CAAC,SAAS,GAAG,MAAM,IAAI,MAAM,CAAC,EAAE,GAC9B,CAAC,GACD,MAAM,GACR,KAAK,EACT,SAAS,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GACrC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA"}
|
|
@@ -4,6 +4,24 @@ 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
|
+
/**
|
|
8
|
+
* Schema for typed objects in Lexicon unions.
|
|
9
|
+
*
|
|
10
|
+
* Typed objects have a `$type` field that identifies which variant they are
|
|
11
|
+
* in a union. The `$type` can be omitted in input (it's implicit), but if
|
|
12
|
+
* present, it must match the expected value.
|
|
13
|
+
*
|
|
14
|
+
* @template TType - The $type string literal type
|
|
15
|
+
* @template TShape - The validator type for the object's shape
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* const schema = new TypedObjectSchema(
|
|
20
|
+
* 'app.bsky.embed.images#view',
|
|
21
|
+
* l.object({ images: l.array(imageSchema) })
|
|
22
|
+
* )
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
7
25
|
class TypedObjectSchema extends core_js_1.Schema {
|
|
8
26
|
$type;
|
|
9
27
|
schema;
|
|
@@ -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":";;;AA6JA,kCAMC;AAnKD,gDAAiD;AACjD,wCAcmB;AAEnB;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,iBAGX,SAAQ,gBAGT;IAEY;IACA;IAFX,YACW,KAAY,EACZ,MAAc;QAEvB,KAAK,EAAE,CAAA;QAHE,UAAK,GAAL,KAAK,CAAO;QACZ,WAAM,GAAN,MAAM,CAAQ;IAGzB,CAAC;IAED,QAAQ,CACN,KAAQ;QAIR,OAAO,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,CAAA;IAChE,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,SAAS,CAAoC,KAAQ;QACnD,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;IAED,MAAM,CAAC,KAAsC;QAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC1B,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,IAAI,CAAC,IAAA,wBAAa,EAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC9C,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;CACF;AAtDD,8CAsDC;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'\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 constructor(\n readonly $type: TType,\n readonly schema: TShape,\n ) {\n super()\n }\n\n isTypeOf<X extends Record<string, unknown>>(\n value: X,\n ): value is X extends { $type?: TType }\n ? X\n : $TypedMaybe<Exclude<X, Unknown$TypedObject>, TType> {\n return value.$type === undefined || value.$type === this.$type\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<X extends Record<string, unknown>>(value: X) {\n return this.isTypeOf(value)\n }\n\n $build(input: Omit<InferInput<this>, '$type'>) {\n return this.build(input)\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input)) {\n return ctx.issueInvalidType(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\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"]}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { $Typed, InferInput, InferOutput, Schema, ValidationContext, Validator } from '../core.js';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for validators that have a $type property.
|
|
4
|
+
*
|
|
5
|
+
* Used by typed objects and records to identify their type in unions.
|
|
6
|
+
*
|
|
7
|
+
* @template TInput - The input type (with optional $type)
|
|
8
|
+
* @template TOutput - The output type (with non-optional $type)
|
|
9
|
+
*/
|
|
2
10
|
export interface TypedObjectValidator<TInput extends {
|
|
3
11
|
$type?: string;
|
|
4
12
|
} = {
|
|
@@ -6,7 +14,27 @@ export interface TypedObjectValidator<TInput extends {
|
|
|
6
14
|
}, TOutput extends TInput = TInput> extends Validator<TInput, TOutput> {
|
|
7
15
|
$type: NonNullable<TOutput['$type']>;
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Function type that returns a typed object validator, used for lazy resolution.
|
|
19
|
+
*
|
|
20
|
+
* @template TValidator - The typed object validator type
|
|
21
|
+
*/
|
|
9
22
|
export type TypedRefGetter<out TValidator extends TypedObjectValidator> = () => TValidator;
|
|
23
|
+
/**
|
|
24
|
+
* Schema for referencing typed objects with lazy resolution.
|
|
25
|
+
*
|
|
26
|
+
* Used in typed unions to reference typed object schemas. Requires the
|
|
27
|
+
* `$type` field to be present and match the referenced schema's type.
|
|
28
|
+
* The referenced schema is resolved lazily to support circular references.
|
|
29
|
+
*
|
|
30
|
+
* @template TValidator - The referenced typed object validator type
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const ref = new TypedRefSchema(() => imageViewSchema)
|
|
35
|
+
* // ref.$type === 'app.bsky.embed.images#view'
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
10
38
|
export declare class TypedRefSchema<const TValidator extends TypedObjectValidator = TypedObjectValidator> extends Schema<$Typed<InferInput<TValidator>>, $Typed<InferOutput<TValidator>>> {
|
|
11
39
|
#private;
|
|
12
40
|
constructor(getter: TypedRefGetter<TValidator>);
|
|
@@ -14,6 +42,31 @@ export declare class TypedRefSchema<const TValidator extends TypedObjectValidato
|
|
|
14
42
|
get $type(): TValidator['$type'];
|
|
15
43
|
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationFailure | import("../core.js").ValidationSuccess<InferInput<TValidator>>;
|
|
16
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates a reference to a typed object schema for use in typed unions.
|
|
47
|
+
*
|
|
48
|
+
* Unlike regular `ref()`, this requires the referenced schema to have a
|
|
49
|
+
* `$type` property, and validates that the input's `$type` matches.
|
|
50
|
+
*
|
|
51
|
+
* @param get - Function that returns the typed object validator
|
|
52
|
+
* @returns A new {@link TypedRefSchema} instance
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* // Reference to image embed view
|
|
57
|
+
* const imageRef = l.typedRef(() => imageViewSchema)
|
|
58
|
+
*
|
|
59
|
+
* // Use in a typed union
|
|
60
|
+
* const embedUnion = l.typedUnion([
|
|
61
|
+
* l.typedRef(() => imageViewSchema),
|
|
62
|
+
* l.typedRef(() => videoViewSchema),
|
|
63
|
+
* l.typedRef(() => externalViewSchema),
|
|
64
|
+
* ], true) // closed union
|
|
65
|
+
*
|
|
66
|
+
* // The $type is accessible on the ref
|
|
67
|
+
* console.log(imageRef.$type) // 'app.bsky.embed.images#view'
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
17
70
|
export declare function typedRef<const TValidator extends TypedObjectValidator>(get: TypedRefGetter<TValidator>): TypedRefSchema<TValidator>;
|
|
18
71
|
export declare function typedRef<TInput extends {
|
|
19
72
|
$type?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-ref.d.ts","sourceRoot":"","sources":["../../src/schema/typed-ref.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;AAEnB,MAAM,WAAW,oBAAoB,CACnC,MAAM,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACtD,OAAO,SAAS,MAAM,GAAG,MAAM,CAC/B,SAAQ,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAClC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;CACrC;AAED,MAAM,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,SAAS,oBAAoB,IACpE,MAAM,UAAU,CAAA;AAElB,qBAAa,cAAc,CACzB,KAAK,CAAC,UAAU,SAAS,oBAAoB,GAAG,oBAAoB,CACpE,SAAQ,MAAM,CACd,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAC9B,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAChC;;gBAGa,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC;IAS9C,IAAI,SAAS,IAAI,UAAU,CAE1B;IAED,IAAI,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,CAE/B;IAED,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAUzD;
|
|
1
|
+
{"version":3,"file":"typed-ref.d.ts","sourceRoot":"","sources":["../../src/schema/typed-ref.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,MAAM,EACN,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;AAEnB;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB,CACnC,MAAM,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACtD,OAAO,SAAS,MAAM,GAAG,MAAM,CAC/B,SAAQ,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC;IAClC,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;CACrC;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,CAAC,GAAG,CAAC,UAAU,SAAS,oBAAoB,IACpE,MAAM,UAAU,CAAA;AAElB;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc,CACzB,KAAK,CAAC,UAAU,SAAS,oBAAoB,GAAG,oBAAoB,CACpE,SAAQ,MAAM,CACd,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,EAC9B,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAChC;;gBAGa,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC;IAS9C,IAAI,SAAS,IAAI,UAAU,CAE1B;IAED,IAAI,KAAK,IAAI,UAAU,CAAC,OAAO,CAAC,CAE/B;IAED,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAUzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,wBAAgB,QAAQ,CAAC,KAAK,CAAC,UAAU,SAAS,oBAAoB,EACpE,GAAG,EAAE,cAAc,CAAC,UAAU,CAAC,GAC9B,cAAc,CAAC,UAAU,CAAC,CAAA;AAC7B,wBAAgB,QAAQ,CACtB,MAAM,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACjC,OAAO,SAAS,MAAM,GAAG,MAAM,EAE/B,GAAG,EAAE,cAAc,CAAC,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACzD,cAAc,CAAC,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA"}
|
package/dist/schema/typed-ref.js
CHANGED
|
@@ -3,6 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TypedRefSchema = void 0;
|
|
4
4
|
exports.typedRef = typedRef;
|
|
5
5
|
const core_js_1 = require("../core.js");
|
|
6
|
+
/**
|
|
7
|
+
* Schema for referencing typed objects with lazy resolution.
|
|
8
|
+
*
|
|
9
|
+
* Used in typed unions to reference typed object schemas. Requires the
|
|
10
|
+
* `$type` field to be present and match the referenced schema's type.
|
|
11
|
+
* The referenced schema is resolved lazily to support circular references.
|
|
12
|
+
*
|
|
13
|
+
* @template TValidator - The referenced typed object validator type
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const ref = new TypedRefSchema(() => imageViewSchema)
|
|
18
|
+
* // ref.$type === 'app.bsky.embed.images#view'
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
6
21
|
class TypedRefSchema extends core_js_1.Schema {
|
|
7
22
|
#getter;
|
|
8
23
|
constructor(getter) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-ref.js","sourceRoot":"","sources":["../../src/schema/typed-ref.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"typed-ref.js","sourceRoot":"","sources":["../../src/schema/typed-ref.ts"],"names":[],"mappings":";;;AAuHA,4BAIC;AA3HD,wCAOmB;AAyBnB;;;;;;;;;;;;;;GAcG;AACH,MAAa,cAEX,SAAQ,gBAGT;IACC,OAAO,CAA4B;IAEnC,YAAY,MAAkC;QAC5C,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,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;IAC7B,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QAClD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAA;QAElC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,OAAO,GAAG,CAAC,yBAAyB,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;QAC3E,CAAC;QAED,OAAO,MAAM,CAAA;IACf,CAAC;CACF;AAnCD,wCAmCC;AAqCD,SAAgB,QAAQ,CACtB,GAA+B;IAE/B,OAAO,IAAI,cAAc,CAAa,GAAG,CAAC,CAAA;AAC5C,CAAC","sourcesContent":["import {\n $Typed,\n InferInput,\n InferOutput,\n Schema,\n ValidationContext,\n Validator,\n} from '../core.js'\n\n/**\n * Interface for validators that have a $type property.\n *\n * Used by typed objects and records to identify their type in unions.\n *\n * @template TInput - The input type (with optional $type)\n * @template TOutput - The output type (with non-optional $type)\n */\nexport interface TypedObjectValidator<\n TInput extends { $type?: string } = { $type?: string },\n TOutput extends TInput = TInput,\n> extends Validator<TInput, TOutput> {\n $type: NonNullable<TOutput['$type']>\n}\n\n/**\n * Function type that returns a typed object validator, used for lazy resolution.\n *\n * @template TValidator - The typed object validator type\n */\nexport type TypedRefGetter<out TValidator extends TypedObjectValidator> =\n () => TValidator\n\n/**\n * Schema for referencing typed objects with lazy resolution.\n *\n * Used in typed unions to reference typed object schemas. Requires the\n * `$type` field to be present and match the referenced schema's type.\n * The referenced schema is resolved lazily to support circular references.\n *\n * @template TValidator - The referenced typed object validator type\n *\n * @example\n * ```ts\n * const ref = new TypedRefSchema(() => imageViewSchema)\n * // ref.$type === 'app.bsky.embed.images#view'\n * ```\n */\nexport class TypedRefSchema<\n const TValidator extends TypedObjectValidator = TypedObjectValidator,\n> extends Schema<\n $Typed<InferInput<TValidator>>,\n $Typed<InferOutput<TValidator>>\n> {\n #getter: TypedRefGetter<TValidator>\n\n constructor(getter: TypedRefGetter<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 get $type(): TValidator['$type'] {\n return this.validator.$type\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n const result = ctx.validate(input, this.validator)\n if (!result.success) return result\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\n/**\n * Creates a reference to a typed object schema for use in typed unions.\n *\n * Unlike regular `ref()`, this requires the referenced schema to have a\n * `$type` property, and validates that the input's `$type` matches.\n *\n * @param get - Function that returns the typed object validator\n * @returns A new {@link TypedRefSchema} instance\n *\n * @example\n * ```ts\n * // Reference to image embed view\n * const imageRef = l.typedRef(() => imageViewSchema)\n *\n * // Use in a typed union\n * const embedUnion = l.typedUnion([\n * l.typedRef(() => imageViewSchema),\n * l.typedRef(() => videoViewSchema),\n * l.typedRef(() => externalViewSchema),\n * ], true) // closed union\n *\n * // The $type is accessible on the ref\n * console.log(imageRef.$type) // 'app.bsky.embed.images#view'\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function typedRef<const TValidator extends TypedObjectValidator>(\n get: TypedRefGetter<TValidator>,\n): TypedRefSchema<TValidator>\nexport function typedRef<\n TInput extends { $type?: string },\n TOutput extends TInput = TInput,\n>(\n get: TypedRefGetter<TypedObjectValidator<TInput, TOutput>>,\n): TypedRefSchema<TypedObjectValidator<TInput, TOutput>>\nexport function typedRef<const TValidator extends TypedObjectValidator>(\n get: TypedRefGetter<TValidator>,\n): TypedRefSchema<TValidator> {\n return new TypedRefSchema<TValidator>(get)\n}\n"]}
|
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import { InferInput, InferOutput, Schema, Unknown$TypedObject, ValidationContext } from '../core.js';
|
|
2
|
+
import { TypedObjectSchema } from './typed-object.js';
|
|
2
3
|
import { TypedRefSchema } from './typed-ref.js';
|
|
3
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Schema for Lexicon typed unions (unions discriminated by $type).
|
|
6
|
+
*
|
|
7
|
+
* Typed unions are collections of typed objects identified by their `$type`
|
|
8
|
+
* field. Can be "open" (accept unknown types) or "closed" (only accept
|
|
9
|
+
* known types).
|
|
10
|
+
*
|
|
11
|
+
* @template TValidators - Tuple of {@link TypedRefSchema} or {@link TypedObjectSchema} instances
|
|
12
|
+
* @template TClosed - Whether the union is closed (rejects unknown $types)
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const embedUnion = new TypedUnionSchema([
|
|
17
|
+
* l.typedRef(() => imageSchema),
|
|
18
|
+
* l.typedRef(() => videoSchema),
|
|
19
|
+
* ], true) // closed - only accepts images and videos
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare class TypedUnionSchema<const TValidators extends readonly (TypedRefSchema | TypedObjectSchema)[] = [], const TClosed extends boolean = boolean> extends Schema<TClosed extends true ? InferInput<TValidators[number]> : InferInput<TValidators[number]> | Unknown$TypedObject, TClosed extends true ? InferOutput<TValidators[number]> : InferOutput<TValidators[number]> | Unknown$TypedObject> {
|
|
4
23
|
protected readonly validators: TValidators;
|
|
5
24
|
readonly closed: TClosed;
|
|
6
25
|
constructor(validators: TValidators, closed: TClosed);
|
|
@@ -8,5 +27,35 @@ export declare class TypedUnionSchema<const TValidators extends readonly TypedRe
|
|
|
8
27
|
get $types(): unknown[];
|
|
9
28
|
validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationFailure | import("../core.js").ValidationSuccess<Record<string, unknown>> | import("../core.js").ValidationSuccess<InferInput<TValidators[number]>>;
|
|
10
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a typed union schema for Lexicon unions.
|
|
32
|
+
*
|
|
33
|
+
* Typed unions discriminate variants by their `$type` field. Can be open
|
|
34
|
+
* (accepts unknown types, useful for extensibility) or closed (strict).
|
|
35
|
+
*
|
|
36
|
+
* @param refs - Array of typed refs for the union variants
|
|
37
|
+
* @param closed - Whether to reject unknown $type values
|
|
38
|
+
* @returns A new {@link TypedUnionSchema} instance
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* // Closed union - only accepts known types
|
|
43
|
+
* const embedSchema = l.typedUnion([
|
|
44
|
+
* l.typedRef(() => imageViewSchema),
|
|
45
|
+
* l.typedRef(() => videoViewSchema),
|
|
46
|
+
* l.typedRef(() => externalViewSchema),
|
|
47
|
+
* ], true)
|
|
48
|
+
*
|
|
49
|
+
* // Open union - accepts unknown types for forward compatibility
|
|
50
|
+
* const feedItemSchema = l.typedUnion([
|
|
51
|
+
* l.typedRef(() => postSchema),
|
|
52
|
+
* l.typedRef(() => repostSchema),
|
|
53
|
+
* ], false) // unknown types pass through
|
|
54
|
+
*
|
|
55
|
+
* // Get all known $types
|
|
56
|
+
* console.log(embedSchema.$types)
|
|
57
|
+
* // ['app.bsky.embed.images#view', 'app.bsky.embed.video#view', ...]
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
11
60
|
export declare function typedUnion<const R extends readonly TypedRefSchema[], const C extends boolean>(refs: R, closed: C): TypedUnionSchema<R, C>;
|
|
12
61
|
//# sourceMappingURL=typed-union.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-union.d.ts","sourceRoot":"","sources":["../../src/schema/typed-union.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C,qBAAa,gBAAgB,CAC3B,KAAK,CAAC,WAAW,SAAS,SAAS,cAAc,EAAE,GAAG,EAAE,
|
|
1
|
+
{"version":3,"file":"typed-union.d.ts","sourceRoot":"","sources":["../../src/schema/typed-union.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,mBAAmB,EACnB,iBAAiB,EAClB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,gBAAgB,CAC3B,KAAK,CAAC,WAAW,SAAS,SAAS,CAC/B,cAAc,GACd,iBAAiB,CACpB,EAAE,GAAG,EAAE,EACR,KAAK,CAAC,OAAO,SAAS,OAAO,GAAG,OAAO,CACvC,SAAQ,MAAM,CACd,OAAO,SAAS,IAAI,GAChB,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAC/B,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,mBAAmB,EACzD,OAAO,SAAS,IAAI,GAChB,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAChC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,mBAAmB,CAC3D;IAEG,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,WAAW;aAC1B,MAAM,EAAE,OAAO;gBADZ,UAAU,EAAE,WAAW,EAC1B,MAAM,EAAE,OAAO;IAUjC,IAAI,aAAa,IAAI,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAKrD;IAED,IAAI,MAAM,cAET;IAED,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAsBzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,wBAAgB,UAAU,CACxB,KAAK,CAAC,CAAC,SAAS,SAAS,cAAc,EAAE,EACzC,KAAK,CAAC,CAAC,SAAS,OAAO,EACvB,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,0BAEnB"}
|
|
@@ -5,13 +5,32 @@ exports.typedUnion = typedUnion;
|
|
|
5
5
|
const lex_data_1 = require("@atproto/lex-data");
|
|
6
6
|
const core_js_1 = require("../core.js");
|
|
7
7
|
const lazy_property_js_1 = require("../util/lazy-property.js");
|
|
8
|
+
/**
|
|
9
|
+
* Schema for Lexicon typed unions (unions discriminated by $type).
|
|
10
|
+
*
|
|
11
|
+
* Typed unions are collections of typed objects identified by their `$type`
|
|
12
|
+
* field. Can be "open" (accept unknown types) or "closed" (only accept
|
|
13
|
+
* known types).
|
|
14
|
+
*
|
|
15
|
+
* @template TValidators - Tuple of {@link TypedRefSchema} or {@link TypedObjectSchema} instances
|
|
16
|
+
* @template TClosed - Whether the union is closed (rejects unknown $types)
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const embedUnion = new TypedUnionSchema([
|
|
21
|
+
* l.typedRef(() => imageSchema),
|
|
22
|
+
* l.typedRef(() => videoSchema),
|
|
23
|
+
* ], true) // closed - only accepts images and videos
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
8
26
|
class TypedUnionSchema extends core_js_1.Schema {
|
|
9
27
|
validators;
|
|
10
28
|
closed;
|
|
11
29
|
constructor(validators, closed) {
|
|
12
30
|
// @NOTE In order to avoid circular dependency issues, we don't access the
|
|
13
31
|
// refs's schema (or $type) here. Instead, we access them lazily when first
|
|
14
|
-
// needed.
|
|
32
|
+
// needed. The biggest issue with this strategy is that we can't throw
|
|
33
|
+
// early if the refs contain multiple refs with the same $type.
|
|
15
34
|
super();
|
|
16
35
|
this.validators = validators;
|
|
17
36
|
this.closed = closed;
|
|
@@ -44,6 +63,36 @@ class TypedUnionSchema extends core_js_1.Schema {
|
|
|
44
63
|
}
|
|
45
64
|
}
|
|
46
65
|
exports.TypedUnionSchema = TypedUnionSchema;
|
|
66
|
+
/**
|
|
67
|
+
* Creates a typed union schema for Lexicon unions.
|
|
68
|
+
*
|
|
69
|
+
* Typed unions discriminate variants by their `$type` field. Can be open
|
|
70
|
+
* (accepts unknown types, useful for extensibility) or closed (strict).
|
|
71
|
+
*
|
|
72
|
+
* @param refs - Array of typed refs for the union variants
|
|
73
|
+
* @param closed - Whether to reject unknown $type values
|
|
74
|
+
* @returns A new {@link TypedUnionSchema} instance
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```ts
|
|
78
|
+
* // Closed union - only accepts known types
|
|
79
|
+
* const embedSchema = l.typedUnion([
|
|
80
|
+
* l.typedRef(() => imageViewSchema),
|
|
81
|
+
* l.typedRef(() => videoViewSchema),
|
|
82
|
+
* l.typedRef(() => externalViewSchema),
|
|
83
|
+
* ], true)
|
|
84
|
+
*
|
|
85
|
+
* // Open union - accepts unknown types for forward compatibility
|
|
86
|
+
* const feedItemSchema = l.typedUnion([
|
|
87
|
+
* l.typedRef(() => postSchema),
|
|
88
|
+
* l.typedRef(() => repostSchema),
|
|
89
|
+
* ], false) // unknown types pass through
|
|
90
|
+
*
|
|
91
|
+
* // Get all known $types
|
|
92
|
+
* console.log(embedSchema.$types)
|
|
93
|
+
* // ['app.bsky.embed.images#view', 'app.bsky.embed.video#view', ...]
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
47
96
|
/*@__NO_SIDE_EFFECTS__*/
|
|
48
97
|
function typedUnion(refs, closed) {
|
|
49
98
|
return new TypedUnionSchema(refs, closed);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typed-union.js","sourceRoot":"","sources":["../../src/schema/typed-union.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"typed-union.js","sourceRoot":"","sources":["../../src/schema/typed-union.ts"],"names":[],"mappings":";;;AA0HA,gCAKC;AA/HD,gDAAiD;AACjD,wCAMmB;AACnB,+DAAuD;AAIvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAa,gBAMX,SAAQ,gBAOT;IAEsB;IACH;IAFlB,YACqB,UAAuB,EAC1B,MAAe;QAE/B,0EAA0E;QAC1E,2EAA2E;QAC3E,sEAAsE;QACtE,+DAA+D;QAE/D,KAAK,EAAE,CAAA;QARY,eAAU,GAAV,UAAU,CAAa;QAC1B,WAAM,GAAN,MAAM,CAAS;IAQjC,CAAC;IAED,IAAI,aAAa;QACf,MAAM,GAAG,GAAG,IAAI,GAAG,EAAgC,CAAA;QACnD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QAE1D,OAAO,IAAA,+BAAY,EAAC,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC,CAAA;IACjD,CAAC;IAED,IAAI,MAAM;QACR,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAA;IAC9C,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,IAAI,CAAC,IAAA,wBAAa,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO,GAAG,CAAC,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;QAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;QAC/C,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QACvC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO,GAAG,CAAC,yBAAyB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACnE,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,OAAO,GAAG,CAAC,wBAAwB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC/D,CAAC;QAED,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;CACF;AA3DD,4CA2DC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAwB;AACxB,SAAgB,UAAU,CAGxB,IAAO,EAAE,MAAS;IAClB,OAAO,IAAI,gBAAgB,CAAO,IAAI,EAAE,MAAM,CAAC,CAAA;AACjD,CAAC","sourcesContent":["import { isPlainObject } from '@atproto/lex-data'\nimport {\n InferInput,\n InferOutput,\n Schema,\n Unknown$TypedObject,\n ValidationContext,\n} from '../core.js'\nimport { lazyProperty } from '../util/lazy-property.js'\nimport { TypedObjectSchema } from './typed-object.js'\nimport { TypedRefSchema } from './typed-ref.js'\n\n/**\n * Schema for Lexicon typed unions (unions discriminated by $type).\n *\n * Typed unions are collections of typed objects identified by their `$type`\n * field. Can be \"open\" (accept unknown types) or \"closed\" (only accept\n * known types).\n *\n * @template TValidators - Tuple of {@link TypedRefSchema} or {@link TypedObjectSchema} instances\n * @template TClosed - Whether the union is closed (rejects unknown $types)\n *\n * @example\n * ```ts\n * const embedUnion = new TypedUnionSchema([\n * l.typedRef(() => imageSchema),\n * l.typedRef(() => videoSchema),\n * ], true) // closed - only accepts images and videos\n * ```\n */\nexport class TypedUnionSchema<\n const TValidators extends readonly (\n | TypedRefSchema\n | TypedObjectSchema\n )[] = [],\n const TClosed extends boolean = boolean,\n> extends Schema<\n TClosed extends true\n ? InferInput<TValidators[number]>\n : InferInput<TValidators[number]> | Unknown$TypedObject,\n TClosed extends true\n ? InferOutput<TValidators[number]>\n : InferOutput<TValidators[number]> | Unknown$TypedObject\n> {\n constructor(\n protected readonly validators: TValidators,\n public readonly closed: TClosed,\n ) {\n // @NOTE In order to avoid circular dependency issues, we don't access the\n // refs's schema (or $type) here. Instead, we access them lazily when first\n // needed. The biggest issue with this strategy is that we can't throw\n // early if the refs contain multiple refs with the same $type.\n\n super()\n }\n\n get validatorsMap(): Map<unknown, TValidators[number]> {\n const map = new Map<unknown, TValidators[number]>()\n for (const ref of this.validators) map.set(ref.$type, ref)\n\n return lazyProperty(this, 'validatorsMap', map)\n }\n\n get $types() {\n return Array.from(this.validatorsMap.keys())\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (!isPlainObject(input) || !('$type' in input)) {\n return ctx.issueInvalidType(input, '$typed')\n }\n\n const { $type } = input\n\n const validator = this.validatorsMap.get($type)\n if (validator) {\n return ctx.validate(input, validator)\n }\n\n if (this.closed) {\n return ctx.issueInvalidPropertyValue(input, '$type', this.$types)\n }\n\n if (typeof $type !== 'string') {\n return ctx.issueInvalidPropertyType(input, '$type', 'string')\n }\n\n return ctx.success(input)\n }\n}\n\n/**\n * Creates a typed union schema for Lexicon unions.\n *\n * Typed unions discriminate variants by their `$type` field. Can be open\n * (accepts unknown types, useful for extensibility) or closed (strict).\n *\n * @param refs - Array of typed refs for the union variants\n * @param closed - Whether to reject unknown $type values\n * @returns A new {@link TypedUnionSchema} instance\n *\n * @example\n * ```ts\n * // Closed union - only accepts known types\n * const embedSchema = l.typedUnion([\n * l.typedRef(() => imageViewSchema),\n * l.typedRef(() => videoViewSchema),\n * l.typedRef(() => externalViewSchema),\n * ], true)\n *\n * // Open union - accepts unknown types for forward compatibility\n * const feedItemSchema = l.typedUnion([\n * l.typedRef(() => postSchema),\n * l.typedRef(() => repostSchema),\n * ], false) // unknown types pass through\n *\n * // Get all known $types\n * console.log(embedSchema.$types)\n * // ['app.bsky.embed.images#view', 'app.bsky.embed.video#view', ...]\n * ```\n */\n/*@__NO_SIDE_EFFECTS__*/\nexport function typedUnion<\n const R extends readonly TypedRefSchema[],\n const C extends boolean,\n>(refs: R, closed: C) {\n return new TypedUnionSchema<R, C>(refs, closed)\n}\n"]}
|
package/dist/schema/union.d.ts
CHANGED
|
@@ -1,9 +1,54 @@
|
|
|
1
1
|
import { InferInput, InferOutput, Schema, ValidationContext, ValidationFailure, Validator } from '../core.js';
|
|
2
|
+
/**
|
|
3
|
+
* Type representing a non-empty tuple of validators for union schemas.
|
|
4
|
+
*
|
|
5
|
+
* Requires at least one validator in the tuple.
|
|
6
|
+
*/
|
|
2
7
|
export type UnionSchemaValidators = readonly [Validator, ...Validator[]];
|
|
8
|
+
/**
|
|
9
|
+
* Schema for validating values that match one of several possible schemas.
|
|
10
|
+
*
|
|
11
|
+
* Tries each validator in order until one succeeds. If all validators fail,
|
|
12
|
+
* returns a combined error from all attempts.
|
|
13
|
+
*
|
|
14
|
+
* @template TValidators - Tuple type of the validators in the union
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const schema = new UnionSchema([l.string(), l.integer()])
|
|
19
|
+
* schema.validate('hello') // success
|
|
20
|
+
* schema.validate(42) // success
|
|
21
|
+
* schema.validate(true) // fails
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
3
24
|
export declare class UnionSchema<const TValidators extends UnionSchemaValidators = any> extends Schema<InferInput<TValidators[number]>, InferOutput<TValidators[number]>> {
|
|
4
25
|
protected readonly validators: TValidators;
|
|
5
26
|
constructor(validators: TValidators);
|
|
6
27
|
validateInContext(input: unknown, ctx: ValidationContext): ValidationFailure | import("../core.js").ValidationSuccess<unknown>;
|
|
7
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Creates a union schema that accepts values matching any of the provided schemas.
|
|
31
|
+
*
|
|
32
|
+
* Validators are tried in order. Use `discriminatedUnion()` for better
|
|
33
|
+
* performance when discriminating on a known property.
|
|
34
|
+
*
|
|
35
|
+
* @param validators - Non-empty array of validators to try
|
|
36
|
+
* @returns A new {@link UnionSchema} instance
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* // String or number
|
|
41
|
+
* const stringOrNumber = l.union([l.string(), l.integer()])
|
|
42
|
+
*
|
|
43
|
+
* // Nullable value
|
|
44
|
+
* const nullableString = l.union([l.string(), l.null()])
|
|
45
|
+
*
|
|
46
|
+
* // Multiple object types
|
|
47
|
+
* const mediaSchema = l.union([
|
|
48
|
+
* l.object({ type: l.literal('image'), url: l.string() }),
|
|
49
|
+
* l.object({ type: l.literal('video'), url: l.string(), duration: l.integer() }),
|
|
50
|
+
* ])
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
8
53
|
export declare function union<const TValidators extends UnionSchemaValidators>(validators: TValidators): UnionSchema<TValidators>;
|
|
9
54
|
//# sourceMappingURL=union.d.ts.map
|
|
@@ -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,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;AAEnB,MAAM,MAAM,qBAAqB,GAAG,SAAS,CAAC,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC,CAAA;AAExE,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;IACa,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,WAAW;gBAAvB,UAAU,EAAE,WAAW;IAItD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAYzD;
|
|
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,iBAAiB,EACjB,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;IACa,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,WAAW;gBAAvB,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
|
@@ -3,6 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UnionSchema = void 0;
|
|
4
4
|
exports.union = union;
|
|
5
5
|
const core_js_1 = require("../core.js");
|
|
6
|
+
/**
|
|
7
|
+
* Schema for validating values that match one of several possible schemas.
|
|
8
|
+
*
|
|
9
|
+
* Tries each validator in order until one succeeds. If all validators fail,
|
|
10
|
+
* returns a combined error from all attempts.
|
|
11
|
+
*
|
|
12
|
+
* @template TValidators - Tuple type of the validators in the union
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const schema = new UnionSchema([l.string(), l.integer()])
|
|
17
|
+
* schema.validate('hello') // success
|
|
18
|
+
* schema.validate(42) // success
|
|
19
|
+
* schema.validate(true) // fails
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
6
22
|
class UnionSchema extends core_js_1.Schema {
|
|
7
23
|
validators;
|
|
8
24
|
constructor(validators) {
|
|
@@ -21,6 +37,30 @@ class UnionSchema extends core_js_1.Schema {
|
|
|
21
37
|
}
|
|
22
38
|
}
|
|
23
39
|
exports.UnionSchema = UnionSchema;
|
|
40
|
+
/**
|
|
41
|
+
* Creates a union schema that accepts values matching any of the provided schemas.
|
|
42
|
+
*
|
|
43
|
+
* Validators are tried in order. Use `discriminatedUnion()` for better
|
|
44
|
+
* performance when discriminating on a known property.
|
|
45
|
+
*
|
|
46
|
+
* @param validators - Non-empty array of validators to try
|
|
47
|
+
* @returns A new {@link UnionSchema} instance
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // String or number
|
|
52
|
+
* const stringOrNumber = l.union([l.string(), l.integer()])
|
|
53
|
+
*
|
|
54
|
+
* // Nullable value
|
|
55
|
+
* const nullableString = l.union([l.string(), l.null()])
|
|
56
|
+
*
|
|
57
|
+
* // Multiple object types
|
|
58
|
+
* const mediaSchema = l.union([
|
|
59
|
+
* l.object({ type: l.literal('image'), url: l.string() }),
|
|
60
|
+
* l.object({ type: l.literal('video'), url: l.string(), duration: l.integer() }),
|
|
61
|
+
* ])
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
24
64
|
/*@__NO_SIDE_EFFECTS__*/
|
|
25
65
|
function union(validators) {
|
|
26
66
|
return new UnionSchema(validators);
|
package/dist/schema/union.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"union.js","sourceRoot":"","sources":["../../src/schema/union.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"union.js","sourceRoot":"","sources":["../../src/schema/union.ts"],"names":[],"mappings":";;;AAkFA,sBAIC;AAtFD,wCAQmB;AASnB;;;;;;;;;;;;;;;GAeG;AACH,MAAa,WAEX,SAAQ,gBAGT;IACgC;IAA/B,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,yBAAe,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC5D,CAAC;CACF;AAtBD,kCAsBC;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 Schema,\n ValidationContext,\n ValidationError,\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 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(ValidationError.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"]}
|