@atproto/lex-schema 0.0.11 → 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 +19 -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 +60 -0
- 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 +9 -24
- package/dist/helpers.d.ts.map +1 -1
- 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 +90 -10
- 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 +3 -3
- 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 +9 -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 +125 -19
- 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
|
@@ -15,6 +15,24 @@ import {
|
|
|
15
15
|
Validator,
|
|
16
16
|
} from '../core.js'
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Schema for typed objects in Lexicon unions.
|
|
20
|
+
*
|
|
21
|
+
* Typed objects have a `$type` field that identifies which variant they are
|
|
22
|
+
* in a union. The `$type` can be omitted in input (it's implicit), but if
|
|
23
|
+
* present, it must match the expected value.
|
|
24
|
+
*
|
|
25
|
+
* @template TType - The $type string literal type
|
|
26
|
+
* @template TShape - The validator type for the object's shape
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const schema = new TypedObjectSchema(
|
|
31
|
+
* 'app.bsky.embed.images#view',
|
|
32
|
+
* l.object({ images: l.array(imageSchema) })
|
|
33
|
+
* )
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
18
36
|
export class TypedObjectSchema<
|
|
19
37
|
const TType extends $Type = $Type,
|
|
20
38
|
const TShape extends Validator<{ [k: string]: unknown }> = any,
|
|
@@ -72,15 +90,51 @@ export class TypedObjectSchema<
|
|
|
72
90
|
}
|
|
73
91
|
|
|
74
92
|
/**
|
|
93
|
+
* Creates a typed object schema for use in Lexicon unions.
|
|
94
|
+
*
|
|
95
|
+
* Typed objects are identified by their `$type` field, which combines an NSID
|
|
96
|
+
* and a hash (e.g., 'app.bsky.embed.images#view'). Used for union variants.
|
|
97
|
+
*
|
|
75
98
|
* This function offers two overloads:
|
|
76
|
-
* - One that
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
99
|
+
* - One that infers the type from arguments (no circular reference support)
|
|
100
|
+
* - One with explicit interface for codegen with circular references
|
|
101
|
+
*
|
|
102
|
+
* @param nsid - The NSID part of the type (e.g., 'app.bsky.embed.images')
|
|
103
|
+
* @param hash - The hash part of the type (e.g., 'view'), defaults to 'main'
|
|
104
|
+
* @param validator - Schema for validating the object properties
|
|
105
|
+
* @returns A new {@link TypedObjectSchema} instance
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```ts
|
|
109
|
+
* // Image embed view
|
|
110
|
+
* const imageViewSchema = l.typedObject(
|
|
111
|
+
* 'app.bsky.embed.images',
|
|
112
|
+
* 'view',
|
|
113
|
+
* l.object({
|
|
114
|
+
* images: l.array(l.object({
|
|
115
|
+
* thumb: l.string(),
|
|
116
|
+
* fullsize: l.string(),
|
|
117
|
+
* alt: l.string(),
|
|
118
|
+
* })),
|
|
119
|
+
* })
|
|
120
|
+
* )
|
|
121
|
+
*
|
|
122
|
+
* // Main type (hash defaults to 'main')
|
|
123
|
+
* const postViewSchema = l.typedObject(
|
|
124
|
+
* 'app.bsky.feed.defs',
|
|
125
|
+
* 'postView',
|
|
126
|
+
* l.object({ uri: l.string(), cid: l.string(), author: authorSchema })
|
|
127
|
+
* )
|
|
128
|
+
*
|
|
129
|
+
* // Use $isTypeOf to narrow union types
|
|
130
|
+
* if (imageViewSchema.$isTypeOf(embed)) {
|
|
131
|
+
* // embed is narrowed to image view type
|
|
132
|
+
* }
|
|
133
|
+
*
|
|
134
|
+
* // Use $build to construct typed objects
|
|
135
|
+
* const view = imageViewSchema.$build({ images: [...] })
|
|
136
|
+
* // view.$type === 'app.bsky.embed.images#view'
|
|
137
|
+
* ```
|
|
84
138
|
*/
|
|
85
139
|
export function typedObject<
|
|
86
140
|
const N extends NsidString,
|
package/src/schema/typed-ref.ts
CHANGED
|
@@ -7,6 +7,14 @@ import {
|
|
|
7
7
|
Validator,
|
|
8
8
|
} from '../core.js'
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Interface for validators that have a $type property.
|
|
12
|
+
*
|
|
13
|
+
* Used by typed objects and records to identify their type in unions.
|
|
14
|
+
*
|
|
15
|
+
* @template TInput - The input type (with optional $type)
|
|
16
|
+
* @template TOutput - The output type (with non-optional $type)
|
|
17
|
+
*/
|
|
10
18
|
export interface TypedObjectValidator<
|
|
11
19
|
TInput extends { $type?: string } = { $type?: string },
|
|
12
20
|
TOutput extends TInput = TInput,
|
|
@@ -14,9 +22,29 @@ export interface TypedObjectValidator<
|
|
|
14
22
|
$type: NonNullable<TOutput['$type']>
|
|
15
23
|
}
|
|
16
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Function type that returns a typed object validator, used for lazy resolution.
|
|
27
|
+
*
|
|
28
|
+
* @template TValidator - The typed object validator type
|
|
29
|
+
*/
|
|
17
30
|
export type TypedRefGetter<out TValidator extends TypedObjectValidator> =
|
|
18
31
|
() => TValidator
|
|
19
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Schema for referencing typed objects with lazy resolution.
|
|
35
|
+
*
|
|
36
|
+
* Used in typed unions to reference typed object schemas. Requires the
|
|
37
|
+
* `$type` field to be present and match the referenced schema's type.
|
|
38
|
+
* The referenced schema is resolved lazily to support circular references.
|
|
39
|
+
*
|
|
40
|
+
* @template TValidator - The referenced typed object validator type
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const ref = new TypedRefSchema(() => imageViewSchema)
|
|
45
|
+
* // ref.$type === 'app.bsky.embed.images#view'
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
20
48
|
export class TypedRefSchema<
|
|
21
49
|
const TValidator extends TypedObjectValidator = TypedObjectValidator,
|
|
22
50
|
> extends Schema<
|
|
@@ -54,6 +82,31 @@ export class TypedRefSchema<
|
|
|
54
82
|
}
|
|
55
83
|
}
|
|
56
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Creates a reference to a typed object schema for use in typed unions.
|
|
87
|
+
*
|
|
88
|
+
* Unlike regular `ref()`, this requires the referenced schema to have a
|
|
89
|
+
* `$type` property, and validates that the input's `$type` matches.
|
|
90
|
+
*
|
|
91
|
+
* @param get - Function that returns the typed object validator
|
|
92
|
+
* @returns A new {@link TypedRefSchema} instance
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* // Reference to image embed view
|
|
97
|
+
* const imageRef = l.typedRef(() => imageViewSchema)
|
|
98
|
+
*
|
|
99
|
+
* // Use in a typed union
|
|
100
|
+
* const embedUnion = l.typedUnion([
|
|
101
|
+
* l.typedRef(() => imageViewSchema),
|
|
102
|
+
* l.typedRef(() => videoViewSchema),
|
|
103
|
+
* l.typedRef(() => externalViewSchema),
|
|
104
|
+
* ], true) // closed union
|
|
105
|
+
*
|
|
106
|
+
* // The $type is accessible on the ref
|
|
107
|
+
* console.log(imageRef.$type) // 'app.bsky.embed.images#view'
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
57
110
|
/*@__NO_SIDE_EFFECTS__*/
|
|
58
111
|
export function typedRef<const TValidator extends TypedObjectValidator>(
|
|
59
112
|
get: TypedRefGetter<TValidator>,
|
|
@@ -7,10 +7,32 @@ import {
|
|
|
7
7
|
ValidationContext,
|
|
8
8
|
} from '../core.js'
|
|
9
9
|
import { lazyProperty } from '../util/lazy-property.js'
|
|
10
|
+
import { TypedObjectSchema } from './typed-object.js'
|
|
10
11
|
import { TypedRefSchema } from './typed-ref.js'
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Schema for Lexicon typed unions (unions discriminated by $type).
|
|
15
|
+
*
|
|
16
|
+
* Typed unions are collections of typed objects identified by their `$type`
|
|
17
|
+
* field. Can be "open" (accept unknown types) or "closed" (only accept
|
|
18
|
+
* known types).
|
|
19
|
+
*
|
|
20
|
+
* @template TValidators - Tuple of {@link TypedRefSchema} or {@link TypedObjectSchema} instances
|
|
21
|
+
* @template TClosed - Whether the union is closed (rejects unknown $types)
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const embedUnion = new TypedUnionSchema([
|
|
26
|
+
* l.typedRef(() => imageSchema),
|
|
27
|
+
* l.typedRef(() => videoSchema),
|
|
28
|
+
* ], true) // closed - only accepts images and videos
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
12
31
|
export class TypedUnionSchema<
|
|
13
|
-
const TValidators extends readonly
|
|
32
|
+
const TValidators extends readonly (
|
|
33
|
+
| TypedRefSchema
|
|
34
|
+
| TypedObjectSchema
|
|
35
|
+
)[] = [],
|
|
14
36
|
const TClosed extends boolean = boolean,
|
|
15
37
|
> extends Schema<
|
|
16
38
|
TClosed extends true
|
|
@@ -26,7 +48,8 @@ export class TypedUnionSchema<
|
|
|
26
48
|
) {
|
|
27
49
|
// @NOTE In order to avoid circular dependency issues, we don't access the
|
|
28
50
|
// refs's schema (or $type) here. Instead, we access them lazily when first
|
|
29
|
-
// needed.
|
|
51
|
+
// needed. The biggest issue with this strategy is that we can't throw
|
|
52
|
+
// early if the refs contain multiple refs with the same $type.
|
|
30
53
|
|
|
31
54
|
super()
|
|
32
55
|
}
|
|
@@ -66,6 +89,36 @@ export class TypedUnionSchema<
|
|
|
66
89
|
}
|
|
67
90
|
}
|
|
68
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Creates a typed union schema for Lexicon unions.
|
|
94
|
+
*
|
|
95
|
+
* Typed unions discriminate variants by their `$type` field. Can be open
|
|
96
|
+
* (accepts unknown types, useful for extensibility) or closed (strict).
|
|
97
|
+
*
|
|
98
|
+
* @param refs - Array of typed refs for the union variants
|
|
99
|
+
* @param closed - Whether to reject unknown $type values
|
|
100
|
+
* @returns A new {@link TypedUnionSchema} instance
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* // Closed union - only accepts known types
|
|
105
|
+
* const embedSchema = l.typedUnion([
|
|
106
|
+
* l.typedRef(() => imageViewSchema),
|
|
107
|
+
* l.typedRef(() => videoViewSchema),
|
|
108
|
+
* l.typedRef(() => externalViewSchema),
|
|
109
|
+
* ], true)
|
|
110
|
+
*
|
|
111
|
+
* // Open union - accepts unknown types for forward compatibility
|
|
112
|
+
* const feedItemSchema = l.typedUnion([
|
|
113
|
+
* l.typedRef(() => postSchema),
|
|
114
|
+
* l.typedRef(() => repostSchema),
|
|
115
|
+
* ], false) // unknown types pass through
|
|
116
|
+
*
|
|
117
|
+
* // Get all known $types
|
|
118
|
+
* console.log(embedSchema.$types)
|
|
119
|
+
* // ['app.bsky.embed.images#view', 'app.bsky.embed.video#view', ...]
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
69
122
|
/*@__NO_SIDE_EFFECTS__*/
|
|
70
123
|
export function typedUnion<
|
|
71
124
|
const R extends readonly TypedRefSchema[],
|
package/src/schema/union.ts
CHANGED
|
@@ -8,8 +8,29 @@ import {
|
|
|
8
8
|
Validator,
|
|
9
9
|
} from '../core.js'
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Type representing a non-empty tuple of validators for union schemas.
|
|
13
|
+
*
|
|
14
|
+
* Requires at least one validator in the tuple.
|
|
15
|
+
*/
|
|
11
16
|
export type UnionSchemaValidators = readonly [Validator, ...Validator[]]
|
|
12
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Schema for validating values that match one of several possible schemas.
|
|
20
|
+
*
|
|
21
|
+
* Tries each validator in order until one succeeds. If all validators fail,
|
|
22
|
+
* returns a combined error from all attempts.
|
|
23
|
+
*
|
|
24
|
+
* @template TValidators - Tuple type of the validators in the union
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* const schema = new UnionSchema([l.string(), l.integer()])
|
|
29
|
+
* schema.validate('hello') // success
|
|
30
|
+
* schema.validate(42) // success
|
|
31
|
+
* schema.validate(true) // fails
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
13
34
|
export class UnionSchema<
|
|
14
35
|
const TValidators extends UnionSchemaValidators = any,
|
|
15
36
|
> extends Schema<
|
|
@@ -34,6 +55,30 @@ export class UnionSchema<
|
|
|
34
55
|
}
|
|
35
56
|
}
|
|
36
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Creates a union schema that accepts values matching any of the provided schemas.
|
|
60
|
+
*
|
|
61
|
+
* Validators are tried in order. Use `discriminatedUnion()` for better
|
|
62
|
+
* performance when discriminating on a known property.
|
|
63
|
+
*
|
|
64
|
+
* @param validators - Non-empty array of validators to try
|
|
65
|
+
* @returns A new {@link UnionSchema} instance
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* // String or number
|
|
70
|
+
* const stringOrNumber = l.union([l.string(), l.integer()])
|
|
71
|
+
*
|
|
72
|
+
* // Nullable value
|
|
73
|
+
* const nullableString = l.union([l.string(), l.null()])
|
|
74
|
+
*
|
|
75
|
+
* // Multiple object types
|
|
76
|
+
* const mediaSchema = l.union([
|
|
77
|
+
* l.object({ type: l.literal('image'), url: l.string() }),
|
|
78
|
+
* l.object({ type: l.literal('video'), url: l.string(), duration: l.integer() }),
|
|
79
|
+
* ])
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
37
82
|
/*@__NO_SIDE_EFFECTS__*/
|
|
38
83
|
export function union<const TValidators extends UnionSchemaValidators>(
|
|
39
84
|
validators: TValidators,
|
|
@@ -2,8 +2,24 @@ import { LexMap, isLexMap } from '@atproto/lex-data'
|
|
|
2
2
|
import { Schema, ValidationContext } from '../core.js'
|
|
3
3
|
import { memoizedOptions } from '../util/memoize.js'
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Type alias for a plain object with unknown values.
|
|
7
|
+
*/
|
|
5
8
|
export type UnknownObject = LexMap
|
|
6
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Schema that accepts any plain object without validating its properties.
|
|
12
|
+
*
|
|
13
|
+
* Validates that the input is a plain object (not an array, Date, or other
|
|
14
|
+
* special object type), but does not validate the object's properties.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const schema = new UnknownObjectSchema()
|
|
19
|
+
* schema.validate({ any: 'props' }) // success
|
|
20
|
+
* schema.validate([1, 2, 3]) // fails - arrays not accepted
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
7
23
|
export class UnknownObjectSchema extends Schema<UnknownObject> {
|
|
8
24
|
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
9
25
|
if (isLexMap(input)) {
|
|
@@ -14,6 +30,24 @@ export class UnknownObjectSchema extends Schema<UnknownObject> {
|
|
|
14
30
|
}
|
|
15
31
|
}
|
|
16
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Creates a schema that accepts any plain object.
|
|
35
|
+
*
|
|
36
|
+
* Unlike `l.unknown()` which accepts any value, this validates that the input
|
|
37
|
+
* is specifically a plain object (not an array, null, or primitive).
|
|
38
|
+
*
|
|
39
|
+
* @returns A new {@link UnknownObjectSchema} instance
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* // Accept any object shape
|
|
44
|
+
* const metadataSchema = l.unknownObject()
|
|
45
|
+
*
|
|
46
|
+
* metadataSchema.parse({ foo: 1, bar: 'baz' }) // success
|
|
47
|
+
* metadataSchema.parse([1, 2, 3]) // throws - not a plain object
|
|
48
|
+
* metadataSchema.parse(null) // throws
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
17
51
|
export const unknownObject = /*#__PURE__*/ memoizedOptions(function () {
|
|
18
52
|
return new UnknownObjectSchema()
|
|
19
53
|
})
|
package/src/schema/unknown.ts
CHANGED
|
@@ -1,12 +1,45 @@
|
|
|
1
1
|
import { Schema, ValidationContext } from '../core.js'
|
|
2
2
|
import { memoizedOptions } from '../util/memoize.js'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Schema that accepts any value without validation.
|
|
6
|
+
*
|
|
7
|
+
* Passes through any input unchanged. Use sparingly as it bypasses
|
|
8
|
+
* type safety. Useful for dynamic data or when the schema is not
|
|
9
|
+
* known at compile time.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const schema = new UnknownSchema()
|
|
14
|
+
* schema.validate(anything) // always succeeds
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
4
17
|
export class UnknownSchema extends Schema<unknown> {
|
|
5
18
|
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
6
19
|
return ctx.success(input)
|
|
7
20
|
}
|
|
8
21
|
}
|
|
9
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Creates an unknown schema that accepts any value.
|
|
25
|
+
*
|
|
26
|
+
* The value passes through without any validation or transformation.
|
|
27
|
+
* Use this when you need to accept arbitrary data.
|
|
28
|
+
*
|
|
29
|
+
* @returns A new {@link UnknownSchema} instance
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* // Accept any value
|
|
34
|
+
* const anyDataSchema = l.unknown()
|
|
35
|
+
*
|
|
36
|
+
* // In an object with a dynamic field
|
|
37
|
+
* const flexibleSchema = l.object({
|
|
38
|
+
* type: l.string(),
|
|
39
|
+
* data: l.unknown(),
|
|
40
|
+
* })
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
10
43
|
export const unknown = /*#__PURE__*/ memoizedOptions(function () {
|
|
11
44
|
return new UnknownSchema()
|
|
12
45
|
})
|
|
@@ -6,6 +6,22 @@ import {
|
|
|
6
6
|
Validator,
|
|
7
7
|
} from '../core.js'
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Schema wrapper that provides a default value when the input is undefined.
|
|
11
|
+
*
|
|
12
|
+
* In parse mode, when the input is `undefined`, the default value is used
|
|
13
|
+
* instead. In validate mode, undefined values pass through unchanged (the
|
|
14
|
+
* default is not applied).
|
|
15
|
+
*
|
|
16
|
+
* @template TValidator - The wrapped validator type
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const schema = new WithDefaultSchema(l.integer(), 0)
|
|
21
|
+
* schema.parse(undefined) // 0
|
|
22
|
+
* schema.parse(42) // 42
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
9
25
|
export class WithDefaultSchema<
|
|
10
26
|
const TValidator extends Validator,
|
|
11
27
|
> extends Schema<InferInput<TValidator>, InferOutput<TValidator>> {
|
|
@@ -27,6 +43,34 @@ export class WithDefaultSchema<
|
|
|
27
43
|
}
|
|
28
44
|
}
|
|
29
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Creates a schema that applies a default value when the input is undefined.
|
|
48
|
+
*
|
|
49
|
+
* Commonly used with `optional()` to provide fallback values for missing
|
|
50
|
+
* properties. The default value is validated against the schema.
|
|
51
|
+
*
|
|
52
|
+
* @param validator - The validator for the value
|
|
53
|
+
* @param defaultValue - The default value to use when input is undefined
|
|
54
|
+
* @returns A new {@link WithDefaultSchema} instance
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* // Integer with default
|
|
59
|
+
* const countSchema = l.withDefault(l.integer(), 0)
|
|
60
|
+
* countSchema.parse(undefined) // 0
|
|
61
|
+
* countSchema.parse(5) // 5
|
|
62
|
+
*
|
|
63
|
+
* // Commonly combined with optional in objects
|
|
64
|
+
* const settingsSchema = l.object({
|
|
65
|
+
* theme: l.optional(l.withDefault(l.string(), 'light')),
|
|
66
|
+
* pageSize: l.optional(l.withDefault(l.integer(), 25)),
|
|
67
|
+
* })
|
|
68
|
+
* settingsSchema.parse({}) // { theme: 'light', pageSize: 25 }
|
|
69
|
+
*
|
|
70
|
+
* // Boolean with default
|
|
71
|
+
* const enabledSchema = l.withDefault(l.boolean(), false)
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
30
74
|
export function withDefault<const TValidator extends Validator>(
|
|
31
75
|
validator: TValidator,
|
|
32
76
|
defaultValue: InferInput<TValidator>,
|