@atproto/lex-schema 0.0.0
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/dist/core/$type.d.ts +4 -0
- package/dist/core/$type.d.ts.map +1 -0
- package/dist/core/$type.js +7 -0
- package/dist/core/$type.js.map +1 -0
- package/dist/core/record-key.d.ts +4 -0
- package/dist/core/record-key.d.ts.map +1 -0
- package/dist/core/record-key.js +16 -0
- package/dist/core/record-key.js.map +1 -0
- package/dist/core/result.d.ts +57 -0
- package/dist/core/result.d.ts.map +1 -0
- package/dist/core/result.js +74 -0
- package/dist/core/result.js.map +1 -0
- package/dist/core/string-format.d.ts +31 -0
- package/dist/core/string-format.d.ts.map +1 -0
- package/dist/core/string-format.js +81 -0
- package/dist/core/string-format.js.map +1 -0
- package/dist/core/types.d.ts +19 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core.d.ts +6 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +9 -0
- package/dist/core.js.map +1 -0
- package/dist/external.d.ts +86 -0
- package/dist/external.d.ts.map +1 -0
- package/dist/external.js +171 -0
- package/dist/external.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/schema/_parameters.d.ts +17 -0
- package/dist/schema/_parameters.d.ts.map +1 -0
- package/dist/schema/_parameters.js +20 -0
- package/dist/schema/_parameters.js.map +1 -0
- package/dist/schema/array.d.ts +13 -0
- package/dist/schema/array.d.ts.map +1 -0
- package/dist/schema/array.js +40 -0
- package/dist/schema/array.js.map +1 -0
- package/dist/schema/blob.d.ts +32 -0
- package/dist/schema/blob.d.ts.map +1 -0
- package/dist/schema/blob.js +40 -0
- package/dist/schema/blob.js.map +1 -0
- package/dist/schema/boolean.d.ts +11 -0
- package/dist/schema/boolean.d.ts.map +1 -0
- package/dist/schema/boolean.js +20 -0
- package/dist/schema/boolean.js.map +1 -0
- package/dist/schema/bytes.d.ts +12 -0
- package/dist/schema/bytes.d.ts.map +1 -0
- package/dist/schema/bytes.js +31 -0
- package/dist/schema/bytes.js.map +1 -0
- package/dist/schema/cid.d.ts +13 -0
- package/dist/schema/cid.d.ts.map +1 -0
- package/dist/schema/cid.js +22 -0
- package/dist/schema/cid.js.map +1 -0
- package/dist/schema/custom.d.ts +15 -0
- package/dist/schema/custom.d.ts.map +1 -0
- package/dist/schema/custom.js +22 -0
- package/dist/schema/custom.js.map +1 -0
- package/dist/schema/dict.d.ts +18 -0
- package/dist/schema/dict.d.ts.map +1 -0
- package/dist/schema/dict.js +48 -0
- package/dist/schema/dict.js.map +1 -0
- package/dist/schema/discriminated-union.d.ts +34 -0
- package/dist/schema/discriminated-union.d.ts.map +1 -0
- package/dist/schema/discriminated-union.js +93 -0
- package/dist/schema/discriminated-union.js.map +1 -0
- package/dist/schema/enum.d.ts +7 -0
- package/dist/schema/enum.d.ts.map +1 -0
- package/dist/schema/enum.js +19 -0
- package/dist/schema/enum.js.map +1 -0
- package/dist/schema/integer.d.ts +13 -0
- package/dist/schema/integer.d.ts.map +1 -0
- package/dist/schema/integer.js +32 -0
- package/dist/schema/integer.js.map +1 -0
- package/dist/schema/intersection.d.ts +16 -0
- package/dist/schema/intersection.d.ts.map +1 -0
- package/dist/schema/intersection.js +33 -0
- package/dist/schema/intersection.js.map +1 -0
- package/dist/schema/literal.d.ts +7 -0
- package/dist/schema/literal.d.ts.map +1 -0
- package/dist/schema/literal.js +19 -0
- package/dist/schema/literal.js.map +1 -0
- package/dist/schema/never.d.ts +5 -0
- package/dist/schema/never.d.ts.map +1 -0
- package/dist/schema/never.js +11 -0
- package/dist/schema/never.js.map +1 -0
- package/dist/schema/null.d.ts +7 -0
- package/dist/schema/null.d.ts.map +1 -0
- package/dist/schema/null.js +18 -0
- package/dist/schema/null.js.map +1 -0
- package/dist/schema/object.d.ts +47 -0
- package/dist/schema/object.d.ts.map +1 -0
- package/dist/schema/object.js +89 -0
- package/dist/schema/object.js.map +1 -0
- package/dist/schema/params.d.ts +22 -0
- package/dist/schema/params.d.ts.map +1 -0
- package/dist/schema/params.js +115 -0
- package/dist/schema/params.js.map +1 -0
- package/dist/schema/payload.d.ts +19 -0
- package/dist/schema/payload.d.ts.map +1 -0
- package/dist/schema/payload.js +16 -0
- package/dist/schema/payload.js.map +1 -0
- package/dist/schema/permission-set.d.ts +15 -0
- package/dist/schema/permission-set.d.ts.map +1 -0
- package/dist/schema/permission-set.js +16 -0
- package/dist/schema/permission-set.js.map +1 -0
- package/dist/schema/permission.d.ts +9 -0
- package/dist/schema/permission.d.ts.map +1 -0
- package/dist/schema/permission.js +14 -0
- package/dist/schema/permission.js.map +1 -0
- package/dist/schema/procedure.d.ts +17 -0
- package/dist/schema/procedure.d.ts.map +1 -0
- package/dist/schema/procedure.js +20 -0
- package/dist/schema/procedure.js.map +1 -0
- package/dist/schema/query.d.ts +15 -0
- package/dist/schema/query.d.ts.map +1 -0
- package/dist/schema/query.js +18 -0
- package/dist/schema/query.js.map +1 -0
- package/dist/schema/record.d.ts +37 -0
- package/dist/schema/record.d.ts.map +1 -0
- package/dist/schema/record.js +64 -0
- package/dist/schema/record.js.map +1 -0
- package/dist/schema/ref.d.ts +10 -0
- package/dist/schema/ref.d.ts.map +1 -0
- package/dist/schema/ref.js +36 -0
- package/dist/schema/ref.js.map +1 -0
- package/dist/schema/string.d.ts +24 -0
- package/dist/schema/string.d.ts.map +1 -0
- package/dist/schema/string.js +107 -0
- package/dist/schema/string.js.map +1 -0
- package/dist/schema/subscription.d.ts +16 -0
- package/dist/schema/subscription.d.ts.map +1 -0
- package/dist/schema/subscription.js +18 -0
- package/dist/schema/subscription.js.map +1 -0
- package/dist/schema/token.d.ts +10 -0
- package/dist/schema/token.d.ts.map +1 -0
- package/dist/schema/token.js +36 -0
- package/dist/schema/token.js.map +1 -0
- package/dist/schema/typed-object.d.ts +32 -0
- package/dist/schema/typed-object.d.ts.map +1 -0
- package/dist/schema/typed-object.js +40 -0
- package/dist/schema/typed-object.js.map +1 -0
- package/dist/schema/typed-ref.d.ts +30 -0
- package/dist/schema/typed-ref.d.ts.map +1 -0
- package/dist/schema/typed-ref.js +44 -0
- package/dist/schema/typed-ref.js.map +1 -0
- package/dist/schema/typed-union.d.ts +26 -0
- package/dist/schema/typed-union.d.ts.map +1 -0
- package/dist/schema/typed-union.js +54 -0
- package/dist/schema/typed-union.js.map +1 -0
- package/dist/schema/union.d.ts +9 -0
- package/dist/schema/union.d.ts.map +1 -0
- package/dist/schema/union.js +29 -0
- package/dist/schema/union.js.map +1 -0
- package/dist/schema/unknown-object.d.ts +9 -0
- package/dist/schema/unknown-object.d.ts.map +1 -0
- package/dist/schema/unknown-object.js +16 -0
- package/dist/schema/unknown-object.js.map +1 -0
- package/dist/schema/unknown.d.ts +5 -0
- package/dist/schema/unknown.d.ts.map +1 -0
- package/dist/schema/unknown.js +11 -0
- package/dist/schema/unknown.js.map +1 -0
- package/dist/schema.d.ts +34 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +41 -0
- package/dist/schema.js.map +1 -0
- package/dist/util/array-agg.d.ts +20 -0
- package/dist/util/array-agg.d.ts.map +1 -0
- package/dist/util/array-agg.js +42 -0
- package/dist/util/array-agg.js.map +1 -0
- package/dist/validation/property-key.d.ts +2 -0
- package/dist/validation/property-key.d.ts.map +1 -0
- package/dist/validation/property-key.js +3 -0
- package/dist/validation/property-key.js.map +1 -0
- package/dist/validation/validation-error.d.ts +9 -0
- package/dist/validation/validation-error.d.ts.map +1 -0
- package/dist/validation/validation-error.js +27 -0
- package/dist/validation/validation-error.js.map +1 -0
- package/dist/validation/validation-issue.d.ts +45 -0
- package/dist/validation/validation-issue.d.ts.map +1 -0
- package/dist/validation/validation-issue.js +167 -0
- package/dist/validation/validation-issue.js.map +1 -0
- package/dist/validation/validator.d.ts +113 -0
- package/dist/validation/validator.d.ts.map +1 -0
- package/dist/validation/validator.js +209 -0
- package/dist/validation/validator.js.map +1 -0
- package/dist/validation.d.ts +5 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +8 -0
- package/dist/validation.js.map +1 -0
- package/package.json +45 -0
- package/src/core/$type.ts +19 -0
- package/src/core/record-key.ts +15 -0
- package/src/core/result.ts +73 -0
- package/src/core/string-format.ts +124 -0
- package/src/core/types.ts +22 -0
- package/src/core.ts +5 -0
- package/src/external.ts +365 -0
- package/src/index.ts +3 -0
- package/src/schema/_parameters.ts +26 -0
- package/src/schema/array.ts +51 -0
- package/src/schema/blob.ts +82 -0
- package/src/schema/boolean.ts +24 -0
- package/src/schema/bytes.ts +38 -0
- package/src/schema/cid.ts +27 -0
- package/src/schema/custom.ts +36 -0
- package/src/schema/dict.ts +69 -0
- package/src/schema/discriminated-union.ts +144 -0
- package/src/schema/enum.ts +20 -0
- package/src/schema/integer.ts +41 -0
- package/src/schema/intersection.ts +57 -0
- package/src/schema/literal.ts +20 -0
- package/src/schema/never.ts +14 -0
- package/src/schema/null.ts +20 -0
- package/src/schema/object.test.ts +138 -0
- package/src/schema/object.ts +180 -0
- package/src/schema/params.ts +157 -0
- package/src/schema/payload.ts +53 -0
- package/src/schema/permission-set.ts +22 -0
- package/src/schema/permission.ts +15 -0
- package/src/schema/procedure.ts +35 -0
- package/src/schema/query.ts +28 -0
- package/src/schema/record.ts +106 -0
- package/src/schema/ref.ts +47 -0
- package/src/schema/string.ts +139 -0
- package/src/schema/subscription.ts +35 -0
- package/src/schema/token.ts +41 -0
- package/src/schema/typed-object.ts +64 -0
- package/src/schema/typed-ref.ts +68 -0
- package/src/schema/typed-union.ts +106 -0
- package/src/schema/union.ts +40 -0
- package/src/schema/unknown-object.ts +20 -0
- package/src/schema/unknown.ts +10 -0
- package/src/schema.ts +40 -0
- package/src/util/array-agg.test.ts +41 -0
- package/src/util/array-agg.ts +43 -0
- package/src/validation/property-key.ts +1 -0
- package/src/validation/validation-error.ts +32 -0
- package/src/validation/validation-issue.ts +231 -0
- package/src/validation/validator.ts +361 -0
- package/src/validation.ts +4 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ensureValidCidString, isLanguage } from '@atproto/lex-data'
|
|
2
|
+
import {
|
|
3
|
+
ensureValidAtUri,
|
|
4
|
+
ensureValidDatetime,
|
|
5
|
+
ensureValidDid,
|
|
6
|
+
ensureValidHandle,
|
|
7
|
+
ensureValidNsid,
|
|
8
|
+
ensureValidRecordKey,
|
|
9
|
+
ensureValidTid,
|
|
10
|
+
} from '@atproto/syntax'
|
|
11
|
+
|
|
12
|
+
// Allow (date as Date).toISOString() to be used where datetime format is expected
|
|
13
|
+
declare global {
|
|
14
|
+
interface Date {
|
|
15
|
+
toISOString(): `${string}T${string}Z`
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const STRING_FORMATS = Object.freeze([
|
|
20
|
+
'datetime',
|
|
21
|
+
'uri',
|
|
22
|
+
'at-uri',
|
|
23
|
+
'did',
|
|
24
|
+
'handle',
|
|
25
|
+
'at-identifier',
|
|
26
|
+
'nsid',
|
|
27
|
+
'cid',
|
|
28
|
+
'language',
|
|
29
|
+
'tid',
|
|
30
|
+
'record-key',
|
|
31
|
+
] as const)
|
|
32
|
+
|
|
33
|
+
export type StringFormat = (typeof STRING_FORMATS)[number]
|
|
34
|
+
|
|
35
|
+
export type Did<M extends string = string> = `did:${M}:${string}`
|
|
36
|
+
export type Uri = `${string}:${string}`
|
|
37
|
+
export type Nsid = `${string}.${string}.${string}`
|
|
38
|
+
/** An ISO 8601 formatted datetime string (YYYY-MM-DDTHH:mm:ss.sssZ) */
|
|
39
|
+
export type Datetime = `${string}T${string}`
|
|
40
|
+
export type Handle = `${string}.${string}`
|
|
41
|
+
export type AtIdentifier = Did | Handle
|
|
42
|
+
export type AtUri = `at://${AtIdentifier}/${Nsid}/${string}`
|
|
43
|
+
|
|
44
|
+
export type InferStringFormat<F> =
|
|
45
|
+
//
|
|
46
|
+
F extends 'datetime'
|
|
47
|
+
? Datetime
|
|
48
|
+
: F extends 'uri'
|
|
49
|
+
? Uri
|
|
50
|
+
: F extends 'at-uri'
|
|
51
|
+
? AtUri
|
|
52
|
+
: F extends 'did'
|
|
53
|
+
? Did
|
|
54
|
+
: F extends 'handle'
|
|
55
|
+
? Handle
|
|
56
|
+
: F extends 'at-identifier'
|
|
57
|
+
? AtIdentifier
|
|
58
|
+
: F extends 'nsid'
|
|
59
|
+
? Nsid
|
|
60
|
+
: string
|
|
61
|
+
|
|
62
|
+
type AssertFn<T> = <I extends string>(input: I) => asserts input is I & T
|
|
63
|
+
|
|
64
|
+
// Re-export utility typed as assertion functions so that TypeScript can
|
|
65
|
+
// infer the narrowed type after calling them.
|
|
66
|
+
|
|
67
|
+
export const assertDid: AssertFn<Did> = ensureValidDid
|
|
68
|
+
export const assertAtUri: AssertFn<AtUri> = ensureValidAtUri
|
|
69
|
+
export const assertNsid: AssertFn<Nsid> = ensureValidNsid
|
|
70
|
+
export const assertTid: AssertFn<string> = ensureValidTid
|
|
71
|
+
export const assertRecordKey: AssertFn<string> = ensureValidRecordKey
|
|
72
|
+
export const assertDatetime: AssertFn<Datetime> = ensureValidDatetime
|
|
73
|
+
export const assertCidString: AssertFn<string> = ensureValidCidString
|
|
74
|
+
export const assertHandle: AssertFn<Handle> = ensureValidHandle
|
|
75
|
+
|
|
76
|
+
// Export utilities for formats missing from @atproto/syntax
|
|
77
|
+
|
|
78
|
+
export const assertUri: AssertFn<Uri> = (input) => {
|
|
79
|
+
if (!/^\w+:(?:\/\/)?[^\s/][^\s]*$/.test(input)) {
|
|
80
|
+
throw new Error('Invalid URI')
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export const assertLanguage: AssertFn<string> = (input) => {
|
|
84
|
+
if (!isLanguage(input)) {
|
|
85
|
+
throw new Error('Invalid BCP 47 string')
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export const assertAtIdentifier: AssertFn<AtIdentifier> = (input) => {
|
|
89
|
+
if (input.startsWith('did:web:') || input.startsWith('did:plc:')) {
|
|
90
|
+
assertDid(input)
|
|
91
|
+
} else if (input.startsWith('did:')) {
|
|
92
|
+
throw new Error('Invalid DID method')
|
|
93
|
+
} else {
|
|
94
|
+
try {
|
|
95
|
+
assertHandle(input)
|
|
96
|
+
} catch (cause) {
|
|
97
|
+
throw new Error('Invalid DID or handle', { cause })
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const formatters = /*#__PURE__*/ new Map<StringFormat, (str: string) => void>([
|
|
103
|
+
['datetime', assertDatetime],
|
|
104
|
+
['uri', assertUri],
|
|
105
|
+
['at-uri', assertAtUri],
|
|
106
|
+
['did', assertDid],
|
|
107
|
+
['handle', assertHandle],
|
|
108
|
+
['at-identifier', assertAtIdentifier],
|
|
109
|
+
['nsid', assertNsid],
|
|
110
|
+
['cid', assertCidString],
|
|
111
|
+
['language', assertLanguage],
|
|
112
|
+
['tid', assertTid],
|
|
113
|
+
['record-key', assertRecordKey],
|
|
114
|
+
] as const)
|
|
115
|
+
|
|
116
|
+
export function assertStringFormat<F extends StringFormat>(
|
|
117
|
+
input: string,
|
|
118
|
+
format: F,
|
|
119
|
+
): asserts input is InferStringFormat<F> {
|
|
120
|
+
const assertFn = formatters.get(format)
|
|
121
|
+
if (assertFn) assertFn(input)
|
|
122
|
+
// Fool-proof
|
|
123
|
+
else throw new Error(`Unknown string format: ${format}`)
|
|
124
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Same as {@link string} but prevents TypeScript allowing union types to
|
|
3
|
+
* be widened to `string` in IDEs.
|
|
4
|
+
*/
|
|
5
|
+
export type UnknownString = string & NonNullable<unknown>
|
|
6
|
+
|
|
7
|
+
export type Simplify<T> = { [K in keyof T]: T[K] } & NonNullable<unknown>
|
|
8
|
+
|
|
9
|
+
// @NOTE there is no way to express "array containing at least one P", so we use
|
|
10
|
+
// "array that contains P at first or last position" as a workaround.
|
|
11
|
+
export type ArrayContaining<T, Items = unknown> =
|
|
12
|
+
| readonly [T, ...Items[]]
|
|
13
|
+
| readonly [...Items[], T]
|
|
14
|
+
|
|
15
|
+
declare const __restricted: unique symbol
|
|
16
|
+
/**
|
|
17
|
+
* A type that represents a value that cannot be used, with a custom
|
|
18
|
+
* message explaining the restriction.
|
|
19
|
+
*/
|
|
20
|
+
export type Restricted<Message extends string> = typeof __restricted & {
|
|
21
|
+
[__restricted]: Message
|
|
22
|
+
}
|
package/src/core.ts
ADDED
package/src/external.ts
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
import { $Type, $type, Nsid, RecordKey } from './core.js'
|
|
2
|
+
import {
|
|
3
|
+
ArraySchema,
|
|
4
|
+
ArraySchemaOptions,
|
|
5
|
+
BlobSchema,
|
|
6
|
+
BlobSchemaOptions,
|
|
7
|
+
BooleanSchema,
|
|
8
|
+
BooleanSchemaOptions,
|
|
9
|
+
BytesSchema,
|
|
10
|
+
BytesSchemaOptions,
|
|
11
|
+
CidSchema,
|
|
12
|
+
CustomAssertion,
|
|
13
|
+
CustomSchema,
|
|
14
|
+
DictSchema,
|
|
15
|
+
DiscriminatedUnionSchema,
|
|
16
|
+
DiscriminatedUnionSchemaVariants,
|
|
17
|
+
EnumSchema,
|
|
18
|
+
IntegerSchema,
|
|
19
|
+
IntegerSchemaOptions,
|
|
20
|
+
IntersectionSchema,
|
|
21
|
+
IntersectionSchemaValidators,
|
|
22
|
+
LiteralSchema,
|
|
23
|
+
NeverSchema,
|
|
24
|
+
NullSchema,
|
|
25
|
+
ObjectSchema,
|
|
26
|
+
ObjectSchemaOptions,
|
|
27
|
+
ObjectSchemaProperties,
|
|
28
|
+
ParamsSchema,
|
|
29
|
+
ParamsSchemaOptions,
|
|
30
|
+
ParamsSchemaProperties,
|
|
31
|
+
Payload,
|
|
32
|
+
PayloadBody,
|
|
33
|
+
Permission,
|
|
34
|
+
PermissionOptions,
|
|
35
|
+
PermissionSet,
|
|
36
|
+
PermissionSetOptions,
|
|
37
|
+
Procedure,
|
|
38
|
+
Query,
|
|
39
|
+
RecordSchema,
|
|
40
|
+
RefSchema,
|
|
41
|
+
RefSchemaGetter,
|
|
42
|
+
StringSchema,
|
|
43
|
+
StringSchemaOptions,
|
|
44
|
+
Subscription,
|
|
45
|
+
TokenSchema,
|
|
46
|
+
TypedObjectSchema,
|
|
47
|
+
TypedRefGetter,
|
|
48
|
+
TypedRefSchema,
|
|
49
|
+
TypedUnionSchema,
|
|
50
|
+
UnionSchema,
|
|
51
|
+
UnionSchemaValidators,
|
|
52
|
+
UnknownObjectOutput,
|
|
53
|
+
UnknownObjectSchema,
|
|
54
|
+
UnknownSchema,
|
|
55
|
+
} from './schema.js'
|
|
56
|
+
import { Infer, PropertyKey, Validator } from './validation.js'
|
|
57
|
+
|
|
58
|
+
export * from './core.js'
|
|
59
|
+
export * from './schema.js'
|
|
60
|
+
export * from './validation.js'
|
|
61
|
+
|
|
62
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
63
|
+
export function never() {
|
|
64
|
+
return new NeverSchema()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
68
|
+
export function unknown() {
|
|
69
|
+
return new UnknownSchema()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
73
|
+
export function _null() {
|
|
74
|
+
return new NullSchema()
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { _null as null }
|
|
78
|
+
|
|
79
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
80
|
+
export function literal<const V extends null | string | number | boolean>(
|
|
81
|
+
value: V,
|
|
82
|
+
) {
|
|
83
|
+
return new LiteralSchema<V>(value)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
87
|
+
export function _enum<const V extends null | string | number | boolean>(
|
|
88
|
+
value: readonly V[],
|
|
89
|
+
) {
|
|
90
|
+
return new EnumSchema<V>(value)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// @NOTE "enum" is a reserved keyword in JS/TS
|
|
94
|
+
export { _enum as enum }
|
|
95
|
+
|
|
96
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
97
|
+
export function boolean(options: BooleanSchemaOptions = {}) {
|
|
98
|
+
return new BooleanSchema(options)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
102
|
+
export function integer(options: IntegerSchemaOptions = {}) {
|
|
103
|
+
return new IntegerSchema(options)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
107
|
+
export function cidLink() {
|
|
108
|
+
return new CidSchema()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
112
|
+
export function bytes(options: BytesSchemaOptions = {}) {
|
|
113
|
+
return new BytesSchema(options)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
117
|
+
export function blob(options: BlobSchemaOptions = {}) {
|
|
118
|
+
return new BlobSchema(options)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
122
|
+
export function string<
|
|
123
|
+
const O extends StringSchemaOptions = NonNullable<unknown>,
|
|
124
|
+
>(options: StringSchemaOptions & O = {} as O) {
|
|
125
|
+
return new StringSchema<O>(options)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
129
|
+
export function array<const T>(
|
|
130
|
+
items: Validator<T>,
|
|
131
|
+
options: ArraySchemaOptions = {},
|
|
132
|
+
) {
|
|
133
|
+
return new ArraySchema(items, options)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
137
|
+
export function object<
|
|
138
|
+
const P extends ObjectSchemaProperties,
|
|
139
|
+
const O extends ObjectSchemaOptions = NonNullable<unknown>,
|
|
140
|
+
>(
|
|
141
|
+
properties: ObjectSchemaProperties & P,
|
|
142
|
+
options: ObjectSchemaOptions & O = {} as O,
|
|
143
|
+
) {
|
|
144
|
+
return new ObjectSchema<P, O>(properties, options)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
148
|
+
export function dict<const K extends Validator, const V extends Validator>(
|
|
149
|
+
key: K,
|
|
150
|
+
value: V,
|
|
151
|
+
) {
|
|
152
|
+
return new DictSchema<K, V>(key, value)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Utility
|
|
156
|
+
export type { UnknownObjectOutput as UnknownObject }
|
|
157
|
+
|
|
158
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
159
|
+
export function unknownObject() {
|
|
160
|
+
return new UnknownObjectSchema()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
164
|
+
export function ref<T>(get: RefSchemaGetter<T>) {
|
|
165
|
+
return new RefSchema<T>(get)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
169
|
+
export function custom<T>(
|
|
170
|
+
assertion: CustomAssertion<T>,
|
|
171
|
+
message: string,
|
|
172
|
+
path?: PropertyKey | readonly PropertyKey[],
|
|
173
|
+
) {
|
|
174
|
+
return new CustomSchema<T>(assertion, message, path)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
178
|
+
export function union<const V extends UnionSchemaValidators>(validators: V) {
|
|
179
|
+
return new UnionSchema<V>(validators)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
183
|
+
export function intersection<const V extends IntersectionSchemaValidators>(
|
|
184
|
+
validators: V,
|
|
185
|
+
) {
|
|
186
|
+
return new IntersectionSchema<V>(validators)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
190
|
+
export function discriminatedUnion<
|
|
191
|
+
const Discriminator extends string,
|
|
192
|
+
const Options extends DiscriminatedUnionSchemaVariants<Discriminator>,
|
|
193
|
+
>(discriminator: Discriminator, variants: Options) {
|
|
194
|
+
return new DiscriminatedUnionSchema<Discriminator, Options>(
|
|
195
|
+
discriminator,
|
|
196
|
+
variants,
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
201
|
+
export function token<const N extends Nsid, const H extends string>(
|
|
202
|
+
nsid: N,
|
|
203
|
+
hash: H,
|
|
204
|
+
) {
|
|
205
|
+
return new TokenSchema($type(nsid, hash))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
209
|
+
export function typedRef<const V extends { $type?: string }>(
|
|
210
|
+
get: TypedRefGetter<V>,
|
|
211
|
+
) {
|
|
212
|
+
return new TypedRefSchema<V>(get)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
216
|
+
export function typedUnion<
|
|
217
|
+
const R extends readonly TypedRefSchema[],
|
|
218
|
+
const C extends boolean,
|
|
219
|
+
>(refs: R, closed: C) {
|
|
220
|
+
return new TypedUnionSchema<R, C>(refs, closed)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* This function offers two overloads:
|
|
225
|
+
* - One that allows creating a {@link TypedObjectSchema}, and infer the output
|
|
226
|
+
* type from the provided arguments, without requiring to specify any of the
|
|
227
|
+
* generics. This is useful when you want to define a record without
|
|
228
|
+
* explicitly defining its interface. This version does not support circular
|
|
229
|
+
* references, as TypeScript cannot infer types in such cases.
|
|
230
|
+
* - One allows creating a {@link TypedObjectSchema} with an explicitly defined
|
|
231
|
+
* interface. This will typically be used by codegen (`lex build`) to generate
|
|
232
|
+
* schemas that work even if they contain circular references.
|
|
233
|
+
*/
|
|
234
|
+
export function typedObject<
|
|
235
|
+
const N extends Nsid,
|
|
236
|
+
const H extends string,
|
|
237
|
+
const Schema extends Validator<{ [_ in string]?: unknown }>,
|
|
238
|
+
>(nsid: N, hash: H, schema: Schema): TypedObjectSchema<$Type<N, H>, Schema>
|
|
239
|
+
export function typedObject<const V extends { $type?: $Type }>(
|
|
240
|
+
nsid: V extends { $type?: infer T extends string }
|
|
241
|
+
? T extends `${infer N}#${string}`
|
|
242
|
+
? N
|
|
243
|
+
: T // (T is a "main" type, so already an NSID)
|
|
244
|
+
: never,
|
|
245
|
+
hash: V extends { $type?: infer T extends string }
|
|
246
|
+
? T extends `${string}#${infer H}`
|
|
247
|
+
? H
|
|
248
|
+
: 'main'
|
|
249
|
+
: never,
|
|
250
|
+
schema: Validator<Omit<V, '$type'>>,
|
|
251
|
+
): TypedObjectSchema<NonNullable<V['$type']>, typeof schema, V>
|
|
252
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
253
|
+
export function typedObject<
|
|
254
|
+
const N extends Nsid,
|
|
255
|
+
const H extends string,
|
|
256
|
+
const Schema extends Validator<{ [_ in string]?: unknown }>,
|
|
257
|
+
>(nsid: N, hash: H, schema: Schema) {
|
|
258
|
+
return new TypedObjectSchema<$Type<N, H>, Schema>($type(nsid, hash), schema)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Ensures that a `$type` used in a record is a valid NSID (i.e. no fragment).
|
|
263
|
+
*/
|
|
264
|
+
type AsNsid<T> = T extends `${string}#${string}` ? never : T
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* This function offers two overloads:
|
|
268
|
+
* - One that allows creating a {@link RecordSchema}, and infer the output type
|
|
269
|
+
* from the provided arguments, without requiring to specify any of the
|
|
270
|
+
* generics. This is useful when you want to define a record without
|
|
271
|
+
* explicitly defining its interface. This version does not support circular
|
|
272
|
+
* references, as TypeScript cannot infer types in such cases.
|
|
273
|
+
* - One allows creating a {@link RecordSchema} with an explicitly defined
|
|
274
|
+
* interface. This will typically be used by codegen (`lex build`) to generate
|
|
275
|
+
* schemas that work even if they contain circular references.
|
|
276
|
+
*/
|
|
277
|
+
export function record<
|
|
278
|
+
const K extends RecordKey,
|
|
279
|
+
const T extends Nsid,
|
|
280
|
+
const S extends Validator<{ [_ in string]?: unknown }>,
|
|
281
|
+
>(
|
|
282
|
+
key: K,
|
|
283
|
+
type: AsNsid<T>,
|
|
284
|
+
schema: S,
|
|
285
|
+
): RecordSchema<K, T, S, Infer<S> & { $type: T }>
|
|
286
|
+
export function record<
|
|
287
|
+
const K extends RecordKey,
|
|
288
|
+
const V extends { $type: Nsid },
|
|
289
|
+
>(
|
|
290
|
+
key: K,
|
|
291
|
+
type: AsNsid<V['$type']>,
|
|
292
|
+
schema: Validator<Omit<V, '$type'>>,
|
|
293
|
+
): RecordSchema<K, V['$type'], typeof schema, V>
|
|
294
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
295
|
+
export function record<
|
|
296
|
+
const K extends RecordKey,
|
|
297
|
+
const T extends Nsid,
|
|
298
|
+
const S extends Validator<{ [_ in string]?: unknown }>,
|
|
299
|
+
>(key: K, type: T, schema: S) {
|
|
300
|
+
return new RecordSchema<K, T, S, Infer<S> & { $type: T }>(key, type, schema)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
304
|
+
export function params<
|
|
305
|
+
const P extends ParamsSchemaProperties = NonNullable<unknown>,
|
|
306
|
+
const O extends ParamsSchemaOptions = ParamsSchemaOptions,
|
|
307
|
+
>(properties: P = {} as P, options: ParamsSchemaOptions & O = {} as O) {
|
|
308
|
+
return new ParamsSchema<P, O>(properties, options)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
312
|
+
export function payload<
|
|
313
|
+
const E extends string | undefined = undefined,
|
|
314
|
+
const S extends PayloadBody<E> = undefined,
|
|
315
|
+
>(encoding: E = undefined as E, schema: S = undefined as S) {
|
|
316
|
+
return new Payload<E, S>(encoding, schema)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
320
|
+
export function query<
|
|
321
|
+
const N extends Nsid,
|
|
322
|
+
const P extends ParamsSchema,
|
|
323
|
+
const O extends Payload,
|
|
324
|
+
const E extends undefined | readonly string[] = undefined,
|
|
325
|
+
>(nsid: N, parameters: P, output: O, errors: E = undefined as E) {
|
|
326
|
+
return new Query<N, P, O, E>(nsid, parameters, output, errors)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
330
|
+
export function procedure<
|
|
331
|
+
const N extends Nsid,
|
|
332
|
+
const P extends ParamsSchema,
|
|
333
|
+
const I extends Payload,
|
|
334
|
+
const O extends Payload,
|
|
335
|
+
const E extends undefined | readonly string[] = undefined,
|
|
336
|
+
>(nsid: N, parameters: P, input: I, output: O, errors: E = undefined as E) {
|
|
337
|
+
return new Procedure<N, P, I, O, E>(nsid, parameters, input, output, errors)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
341
|
+
export function subscription<
|
|
342
|
+
const N extends string,
|
|
343
|
+
const P extends ParamsSchema,
|
|
344
|
+
const M extends undefined | RefSchema | TypedUnionSchema | ObjectSchema,
|
|
345
|
+
const E extends undefined | readonly string[] = undefined,
|
|
346
|
+
>(nsid: N, parameters: P, message: M, errors: E = undefined as E) {
|
|
347
|
+
return new Subscription<N, P, M, E>(nsid, parameters, message, errors)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
351
|
+
export function permission<
|
|
352
|
+
const R extends string,
|
|
353
|
+
const O extends PermissionOptions,
|
|
354
|
+
>(resource: R, options: PermissionOptions & O = {} as O) {
|
|
355
|
+
return new Permission<R, O>(resource, options)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
359
|
+
export function permissionSet<
|
|
360
|
+
const N extends string,
|
|
361
|
+
const P extends readonly Permission[],
|
|
362
|
+
const O extends PermissionSetOptions,
|
|
363
|
+
>(nsid: N, permissions: P, options: PermissionSetOptions & O = {} as O) {
|
|
364
|
+
return new PermissionSet<N, P, O>(nsid, permissions, options)
|
|
365
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Infer, Validator } from '../validation.js'
|
|
2
|
+
import { ArraySchema } from './array.js'
|
|
3
|
+
import { BooleanSchema } from './boolean.js'
|
|
4
|
+
import { DictSchema } from './dict.js'
|
|
5
|
+
import { IntegerSchema } from './integer.js'
|
|
6
|
+
import { StringSchema } from './string.js'
|
|
7
|
+
import { UnionSchema } from './union.js'
|
|
8
|
+
|
|
9
|
+
export type ParamScalar = Infer<typeof paramScalarSchema>
|
|
10
|
+
const paramScalarSchema = new UnionSchema([
|
|
11
|
+
new BooleanSchema({}),
|
|
12
|
+
new IntegerSchema({}),
|
|
13
|
+
new StringSchema({}),
|
|
14
|
+
])
|
|
15
|
+
|
|
16
|
+
export type Param = Infer<typeof paramSchema>
|
|
17
|
+
export const paramSchema = new UnionSchema([
|
|
18
|
+
paramScalarSchema,
|
|
19
|
+
new ArraySchema(paramScalarSchema, {}),
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
export type Params = { [_: string]: undefined | Param }
|
|
23
|
+
export const paramsSchema = new DictSchema(
|
|
24
|
+
new StringSchema({}),
|
|
25
|
+
paramSchema,
|
|
26
|
+
) satisfies Validator<Params>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ValidationResult, Validator, ValidatorContext } from '../validation.js'
|
|
2
|
+
|
|
3
|
+
export type ArraySchemaOptions = {
|
|
4
|
+
minLength?: number
|
|
5
|
+
maxLength?: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class ArraySchema<Item = any> extends Validator<Array<Item>> {
|
|
9
|
+
readonly lexiconType = 'array' as const
|
|
10
|
+
|
|
11
|
+
constructor(
|
|
12
|
+
readonly items: Validator<Item>,
|
|
13
|
+
readonly options: ArraySchemaOptions,
|
|
14
|
+
) {
|
|
15
|
+
super()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override validateInContext(
|
|
19
|
+
input: unknown,
|
|
20
|
+
ctx: ValidatorContext,
|
|
21
|
+
): ValidationResult<Array<Item>> {
|
|
22
|
+
if (!Array.isArray(input)) {
|
|
23
|
+
return ctx.issueInvalidType(input, 'array')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const { minLength, maxLength } = this.options
|
|
27
|
+
|
|
28
|
+
if (minLength != null && input.length < minLength) {
|
|
29
|
+
return ctx.issueTooSmall(input, 'array', minLength, input.length)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (maxLength != null && input.length > maxLength) {
|
|
33
|
+
return ctx.issueTooBig(input, 'array', maxLength, input.length)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let copy: undefined | Array<Item>
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < input.length; i++) {
|
|
39
|
+
const result = ctx.validateChild(input, i, this.items)
|
|
40
|
+
if (!result.success) return result
|
|
41
|
+
|
|
42
|
+
if (result.value !== input[i]) {
|
|
43
|
+
// Copy on write (but only if we did not already make a copy)
|
|
44
|
+
copy ??= Array.from(input)
|
|
45
|
+
copy[i] = result.value
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return ctx.success(copy ?? input) as ValidationResult<Array<Item>>
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BlobRef,
|
|
3
|
+
LegacyBlobRef,
|
|
4
|
+
isBlobRef,
|
|
5
|
+
isLegacyBlobRef,
|
|
6
|
+
} from '@atproto/lex-data'
|
|
7
|
+
import { ValidationResult, Validator, ValidatorContext } from '../validation.js'
|
|
8
|
+
|
|
9
|
+
export type BlobSchemaOptions = {
|
|
10
|
+
/**
|
|
11
|
+
* Whether to allow legacy blob references format
|
|
12
|
+
* @see {@link LegacyBlobRef}
|
|
13
|
+
*/
|
|
14
|
+
allowLegacy?: boolean
|
|
15
|
+
/**
|
|
16
|
+
* Whether to enforce strict validation on the blob reference (CID version, codec, hash function)
|
|
17
|
+
*/
|
|
18
|
+
strict?: boolean
|
|
19
|
+
/**
|
|
20
|
+
* List of accepted mime types
|
|
21
|
+
*/
|
|
22
|
+
accept?: string[]
|
|
23
|
+
/**
|
|
24
|
+
* Maximum size in bytes
|
|
25
|
+
*/
|
|
26
|
+
maxSize?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type { BlobRef, LegacyBlobRef }
|
|
30
|
+
|
|
31
|
+
export type BlobSchemaOutput<Options> = Options extends { allowLegacy: true }
|
|
32
|
+
? BlobRef | LegacyBlobRef
|
|
33
|
+
: BlobRef
|
|
34
|
+
|
|
35
|
+
export class BlobSchema<O extends BlobSchemaOptions> extends Validator<
|
|
36
|
+
BlobSchemaOutput<O>
|
|
37
|
+
> {
|
|
38
|
+
readonly lexiconType = 'blob' as const
|
|
39
|
+
|
|
40
|
+
constructor(readonly options: O) {
|
|
41
|
+
super()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
override validateInContext(
|
|
45
|
+
input: unknown,
|
|
46
|
+
ctx: ValidatorContext,
|
|
47
|
+
): ValidationResult<BlobSchemaOutput<O>> {
|
|
48
|
+
if (!isBlob(input, this.options)) {
|
|
49
|
+
return ctx.issueInvalidType(input, 'blob')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// @NOTE Historically, we did not enforce constraints on blob references
|
|
53
|
+
// https://github.com/bluesky-social/atproto/blob/4c15fb47cec26060bff2e710e95869a90c9d7fdd/packages/lexicon/src/validators/blob.ts#L5-L19
|
|
54
|
+
|
|
55
|
+
// const { accept } = this.options
|
|
56
|
+
// if (accept && !accept.includes(input.mimeType)) {
|
|
57
|
+
// return ctx.issueInvalidValue(input, accept)
|
|
58
|
+
// }
|
|
59
|
+
|
|
60
|
+
// const { maxSize } = this.options
|
|
61
|
+
// if (maxSize != null && input.size != -1 && input.size > maxSize) {
|
|
62
|
+
// return ctx.issueTooBig(input, 'blob', maxSize, input.size)
|
|
63
|
+
// }
|
|
64
|
+
|
|
65
|
+
return ctx.success(input)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isBlob<O extends BlobSchemaOptions>(
|
|
70
|
+
input: unknown,
|
|
71
|
+
options: O,
|
|
72
|
+
): input is BlobSchemaOutput<O> {
|
|
73
|
+
if ((input as any)?.$type !== undefined) {
|
|
74
|
+
return isBlobRef(input, options)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (options.allowLegacy === true) {
|
|
78
|
+
return isLegacyBlobRef(input)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ValidationResult, Validator, ValidatorContext } from '../validation.js'
|
|
2
|
+
|
|
3
|
+
export type BooleanSchemaOptions = {
|
|
4
|
+
default?: boolean
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class BooleanSchema extends Validator<boolean> {
|
|
8
|
+
readonly lexiconType = 'boolean' as const
|
|
9
|
+
|
|
10
|
+
constructor(readonly options: BooleanSchemaOptions) {
|
|
11
|
+
super()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override validateInContext(
|
|
15
|
+
input: unknown = this.options.default,
|
|
16
|
+
ctx: ValidatorContext,
|
|
17
|
+
): ValidationResult<boolean> {
|
|
18
|
+
if (typeof input === 'boolean') {
|
|
19
|
+
return ctx.success(input)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return ctx.issueInvalidType(input, 'boolean')
|
|
23
|
+
}
|
|
24
|
+
}
|