@atproto/lex-schema 0.0.8 → 0.0.10
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 +41 -0
- package/LICENSE.txt +1 -1
- package/dist/core/$type.d.ts +11 -0
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +4 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/schema.d.ts +31 -24
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +38 -8
- package/dist/core/schema.js.map +1 -1
- package/dist/core/string-format.d.ts +35 -35
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +49 -91
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-issue.js +1 -1
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +53 -32
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +18 -22
- package/dist/core/validator.js.map +1 -1
- package/dist/external.d.ts +0 -85
- package/dist/external.d.ts.map +1 -1
- package/dist/external.js +0 -164
- package/dist/external.js.map +1 -1
- package/dist/helpers.d.ts +10 -5
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +3 -3
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +9 -5
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +14 -5
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +9 -7
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +9 -5
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +3 -7
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +6 -7
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +3 -2
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +7 -3
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +10 -8
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +5 -1
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +6 -5
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +10 -4
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +8 -8
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +11 -2
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +21 -14
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +7 -0
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +7 -9
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +8 -4
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +5 -5
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +9 -5
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +4 -4
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +5 -0
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +6 -9
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +7 -4
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +3 -2
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +5 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +4 -3
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +6 -4
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +6 -5
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +9 -5
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +10 -8
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +11 -3
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +7 -5
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +14 -6
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +24 -13
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +47 -25
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +12 -9
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +11 -0
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +1 -0
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +5 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +6 -5
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +5 -0
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +2 -1
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +5 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +2 -1
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +5 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +48 -30
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +12 -9
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +9 -6
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +9 -16
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +4 -4
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.d.ts +4 -3
- package/dist/schema/regexp.d.ts.map +1 -1
- package/dist/schema/regexp.js +5 -0
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +7 -8
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +13 -19
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +2 -1
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +5 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +6 -5
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +5 -0
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +43 -26
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +6 -3
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +16 -25
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +7 -17
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +9 -21
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +15 -11
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +6 -6
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +7 -5
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +5 -4
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +5 -1
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +3 -2
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +5 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +9 -0
- package/dist/schema/with-default.d.ts.map +1 -0
- package/dist/schema/with-default.js +27 -0
- package/dist/schema/with-default.js.map +1 -0
- package/dist/schema.d.ts +2 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +2 -4
- package/dist/schema.js.map +1 -1
- package/dist/util/assertion-util.d.ts +0 -6
- package/dist/util/assertion-util.d.ts.map +1 -1
- package/dist/util/assertion-util.js +0 -28
- package/dist/util/assertion-util.js.map +1 -1
- package/dist/util/memoize.d.ts +2 -2
- package/dist/util/memoize.d.ts.map +1 -1
- package/dist/util/memoize.js +23 -39
- package/dist/util/memoize.js.map +1 -1
- package/package.json +3 -3
- package/src/core/$type.test.ts +20 -0
- package/src/core/$type.ts +30 -0
- package/src/core/schema.ts +86 -38
- package/src/core/string-format.ts +119 -158
- package/src/core/validation-issue.ts +1 -1
- package/src/core/validator.ts +93 -53
- package/src/external.ts +0 -404
- package/src/helpers.test.ts +22 -21
- package/src/helpers.ts +14 -14
- package/src/schema/array.test.ts +38 -40
- package/src/schema/array.ts +35 -13
- package/src/schema/blob.test.ts +21 -21
- package/src/schema/blob.ts +19 -17
- package/src/schema/boolean.test.ts +9 -8
- package/src/schema/boolean.ts +7 -13
- package/src/schema/bytes.test.ts +13 -13
- package/src/schema/bytes.ts +13 -8
- package/src/schema/cid.test.ts +3 -3
- package/src/schema/cid.ts +15 -13
- package/src/schema/custom.test.ts +26 -26
- package/src/schema/custom.ts +20 -13
- package/src/schema/dict.test.ts +21 -39
- package/src/schema/dict.ts +28 -19
- package/src/schema/discriminated-union.test.ts +128 -128
- package/src/schema/discriminated-union.ts +45 -26
- package/src/schema/enum.test.ts +17 -16
- package/src/schema/enum.ts +16 -16
- package/src/schema/integer.test.ts +22 -21
- package/src/schema/integer.ts +12 -9
- package/src/schema/intersection.test.ts +10 -10
- package/src/schema/intersection.ts +17 -14
- package/src/schema/literal.test.ts +35 -34
- package/src/schema/literal.ts +12 -15
- package/src/schema/never.test.ts +5 -5
- package/src/schema/never.ts +7 -2
- package/src/schema/null.test.ts +3 -3
- package/src/schema/null.ts +9 -9
- package/src/schema/nullable.test.ts +31 -42
- package/src/schema/nullable.ts +17 -9
- package/src/schema/object.test.ts +10 -12
- package/src/schema/object.ts +27 -18
- package/src/schema/optional.test.ts +21 -28
- package/src/schema/optional.ts +27 -10
- package/src/schema/params.test.ts +471 -47
- package/src/schema/params.ts +72 -38
- package/src/schema/payload.test.ts +150 -156
- package/src/schema/payload.ts +35 -19
- package/src/schema/permission-set.test.ts +206 -273
- package/src/schema/permission-set.ts +8 -0
- package/src/schema/permission.test.ts +177 -177
- package/src/schema/permission.ts +13 -5
- package/src/schema/procedure.test.ts +183 -242
- package/src/schema/procedure.ts +18 -5
- package/src/schema/query.test.ts +186 -200
- package/src/schema/query.ts +16 -4
- package/src/schema/record.test.ts +121 -101
- package/src/schema/record.ts +74 -40
- package/src/schema/ref.test.ts +101 -118
- package/src/schema/ref.ts +33 -28
- package/src/schema/refine.test.ts +28 -28
- package/src/schema/refine.ts +23 -20
- package/src/schema/regexp.test.ts +29 -33
- package/src/schema/regexp.ts +11 -7
- package/src/schema/string.test.ts +35 -35
- package/src/schema/string.ts +24 -33
- package/src/schema/subscription.test.ts +259 -387
- package/src/schema/subscription.ts +16 -4
- package/src/schema/token.test.ts +47 -324
- package/src/schema/token.ts +14 -7
- package/src/schema/typed-object.test.ts +98 -81
- package/src/schema/typed-object.ts +68 -33
- package/src/schema/typed-ref.test.ts +206 -234
- package/src/schema/typed-ref.ts +40 -42
- package/src/schema/typed-union.test.ts +40 -64
- package/src/schema/typed-union.ts +36 -58
- package/src/schema/union.test.ts +17 -27
- package/src/schema/union.ts +20 -16
- package/src/schema/unknown-object.test.ts +8 -8
- package/src/schema/unknown-object.ts +9 -7
- package/src/schema/unknown.test.ts +4 -4
- package/src/schema/unknown.ts +7 -5
- package/src/schema/with-default.ts +35 -0
- package/src/schema.ts +2 -6
- package/src/util/assertion-util.ts +0 -39
- package/src/util/memoize.ts +26 -46
- package/dist/schema/_parameters.d.ts +0 -17
- package/dist/schema/_parameters.d.ts.map +0 -1
- package/dist/schema/_parameters.js +0 -20
- package/dist/schema/_parameters.js.map +0 -1
- package/src/schema/_parameters.test.ts +0 -417
- package/src/schema/_parameters.ts +0 -26
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { discriminatedUnion } from './discriminated-union.js'
|
|
3
|
+
import { enumSchema } from './enum.js'
|
|
4
|
+
import { integer } from './integer.js'
|
|
5
|
+
import { literal } from './literal.js'
|
|
6
|
+
import { object } from './object.js'
|
|
7
|
+
import { string } from './string.js'
|
|
8
8
|
|
|
9
9
|
describe('DiscriminatedUnionSchema', () => {
|
|
10
10
|
describe('with literal discriminators', () => {
|
|
11
|
-
const schema =
|
|
12
|
-
|
|
13
|
-
type:
|
|
14
|
-
meow:
|
|
11
|
+
const schema = discriminatedUnion('type', [
|
|
12
|
+
object({
|
|
13
|
+
type: literal('cat'),
|
|
14
|
+
meow: string(),
|
|
15
15
|
}),
|
|
16
|
-
|
|
17
|
-
type:
|
|
18
|
-
bark:
|
|
16
|
+
object({
|
|
17
|
+
type: literal('dog'),
|
|
18
|
+
bark: string(),
|
|
19
19
|
}),
|
|
20
20
|
])
|
|
21
21
|
|
|
@@ -96,14 +96,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
96
96
|
})
|
|
97
97
|
|
|
98
98
|
describe('with enum discriminators', () => {
|
|
99
|
-
const schema =
|
|
100
|
-
|
|
101
|
-
status:
|
|
102
|
-
progress:
|
|
99
|
+
const schema = discriminatedUnion('status', [
|
|
100
|
+
object({
|
|
101
|
+
status: enumSchema(['pending', 'processing']),
|
|
102
|
+
progress: integer(),
|
|
103
103
|
}),
|
|
104
|
-
|
|
105
|
-
status:
|
|
106
|
-
result:
|
|
104
|
+
object({
|
|
105
|
+
status: enumSchema(['complete', 'failed']),
|
|
106
|
+
result: string(),
|
|
107
107
|
}),
|
|
108
108
|
])
|
|
109
109
|
|
|
@@ -164,14 +164,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
164
164
|
})
|
|
165
165
|
|
|
166
166
|
describe('with mixed literal and enum discriminators', () => {
|
|
167
|
-
const schema =
|
|
168
|
-
|
|
169
|
-
kind:
|
|
170
|
-
value:
|
|
167
|
+
const schema = discriminatedUnion('kind', [
|
|
168
|
+
object({
|
|
169
|
+
kind: literal('simple'),
|
|
170
|
+
value: string(),
|
|
171
171
|
}),
|
|
172
|
-
|
|
173
|
-
kind:
|
|
174
|
-
value:
|
|
172
|
+
object({
|
|
173
|
+
kind: enumSchema(['complex', 'advanced']),
|
|
174
|
+
value: integer(),
|
|
175
175
|
}),
|
|
176
176
|
])
|
|
177
177
|
|
|
@@ -209,10 +209,10 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
209
209
|
})
|
|
210
210
|
|
|
211
211
|
describe('with single variant', () => {
|
|
212
|
-
const schema =
|
|
213
|
-
|
|
214
|
-
type:
|
|
215
|
-
value:
|
|
212
|
+
const schema = discriminatedUnion('type', [
|
|
213
|
+
object({
|
|
214
|
+
type: literal('only'),
|
|
215
|
+
value: string(),
|
|
216
216
|
}),
|
|
217
217
|
])
|
|
218
218
|
|
|
@@ -234,19 +234,19 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
234
234
|
})
|
|
235
235
|
|
|
236
236
|
describe('with three variants', () => {
|
|
237
|
-
const schema =
|
|
238
|
-
|
|
239
|
-
shape:
|
|
240
|
-
radius:
|
|
237
|
+
const schema = discriminatedUnion('shape', [
|
|
238
|
+
object({
|
|
239
|
+
shape: literal('circle'),
|
|
240
|
+
radius: integer(),
|
|
241
241
|
}),
|
|
242
|
-
|
|
243
|
-
shape:
|
|
244
|
-
side:
|
|
242
|
+
object({
|
|
243
|
+
shape: literal('square'),
|
|
244
|
+
side: integer(),
|
|
245
245
|
}),
|
|
246
|
-
|
|
247
|
-
shape:
|
|
248
|
-
width:
|
|
249
|
-
height:
|
|
246
|
+
object({
|
|
247
|
+
shape: literal('rectangle'),
|
|
248
|
+
width: integer(),
|
|
249
|
+
height: integer(),
|
|
250
250
|
}),
|
|
251
251
|
])
|
|
252
252
|
|
|
@@ -285,14 +285,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
285
285
|
})
|
|
286
286
|
|
|
287
287
|
describe('with number discriminators', () => {
|
|
288
|
-
const schema =
|
|
289
|
-
|
|
290
|
-
version:
|
|
291
|
-
oldFormat:
|
|
288
|
+
const schema = discriminatedUnion('version', [
|
|
289
|
+
object({
|
|
290
|
+
version: literal(1),
|
|
291
|
+
oldFormat: string(),
|
|
292
292
|
}),
|
|
293
|
-
|
|
294
|
-
version:
|
|
295
|
-
newFormat:
|
|
293
|
+
object({
|
|
294
|
+
version: literal(2),
|
|
295
|
+
newFormat: string(),
|
|
296
296
|
}),
|
|
297
297
|
])
|
|
298
298
|
|
|
@@ -330,14 +330,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
330
330
|
})
|
|
331
331
|
|
|
332
332
|
describe('with boolean discriminators', () => {
|
|
333
|
-
const schema =
|
|
334
|
-
|
|
335
|
-
enabled:
|
|
336
|
-
config:
|
|
333
|
+
const schema = discriminatedUnion('enabled', [
|
|
334
|
+
object({
|
|
335
|
+
enabled: literal(true),
|
|
336
|
+
config: string(),
|
|
337
337
|
}),
|
|
338
|
-
|
|
339
|
-
enabled:
|
|
340
|
-
reason:
|
|
338
|
+
object({
|
|
339
|
+
enabled: literal(false),
|
|
340
|
+
reason: string(),
|
|
341
341
|
}),
|
|
342
342
|
])
|
|
343
343
|
|
|
@@ -367,14 +367,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
367
367
|
})
|
|
368
368
|
|
|
369
369
|
describe('with null discriminator', () => {
|
|
370
|
-
const schema =
|
|
371
|
-
|
|
372
|
-
value:
|
|
373
|
-
empty:
|
|
370
|
+
const schema = discriminatedUnion('value', [
|
|
371
|
+
object({
|
|
372
|
+
value: literal(null),
|
|
373
|
+
empty: string(),
|
|
374
374
|
}),
|
|
375
|
-
|
|
376
|
-
value:
|
|
377
|
-
data:
|
|
375
|
+
object({
|
|
376
|
+
value: literal('present'),
|
|
377
|
+
data: string(),
|
|
378
378
|
}),
|
|
379
379
|
])
|
|
380
380
|
|
|
@@ -406,14 +406,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
406
406
|
describe('constructor validation', () => {
|
|
407
407
|
it('throws on overlapping literal discriminator values', () => {
|
|
408
408
|
expect(() => {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
type:
|
|
412
|
-
a:
|
|
409
|
+
discriminatedUnion('type', [
|
|
410
|
+
object({
|
|
411
|
+
type: literal('duplicate'),
|
|
412
|
+
a: string(),
|
|
413
413
|
}),
|
|
414
|
-
|
|
415
|
-
type:
|
|
416
|
-
b:
|
|
414
|
+
object({
|
|
415
|
+
type: literal('duplicate'),
|
|
416
|
+
b: string(),
|
|
417
417
|
}),
|
|
418
418
|
])
|
|
419
419
|
}).toThrow('Overlapping discriminator value: duplicate')
|
|
@@ -421,14 +421,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
421
421
|
|
|
422
422
|
it('throws on overlapping enum discriminator values', () => {
|
|
423
423
|
expect(() => {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
status:
|
|
427
|
-
a:
|
|
424
|
+
discriminatedUnion('status', [
|
|
425
|
+
object({
|
|
426
|
+
status: enumSchema(['active', 'pending']),
|
|
427
|
+
a: string(),
|
|
428
428
|
}),
|
|
429
|
-
|
|
430
|
-
status:
|
|
431
|
-
b:
|
|
429
|
+
object({
|
|
430
|
+
status: enumSchema(['pending', 'complete']),
|
|
431
|
+
b: string(),
|
|
432
432
|
}),
|
|
433
433
|
])
|
|
434
434
|
}).toThrow('Overlapping discriminator value: pending')
|
|
@@ -436,14 +436,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
436
436
|
|
|
437
437
|
it('throws on overlapping literal and enum discriminator values', () => {
|
|
438
438
|
expect(() => {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
kind:
|
|
442
|
-
a:
|
|
439
|
+
discriminatedUnion('kind', [
|
|
440
|
+
object({
|
|
441
|
+
kind: literal('test'),
|
|
442
|
+
a: string(),
|
|
443
443
|
}),
|
|
444
|
-
|
|
445
|
-
kind:
|
|
446
|
-
b:
|
|
444
|
+
object({
|
|
445
|
+
kind: enumSchema(['test', 'other']),
|
|
446
|
+
b: string(),
|
|
447
447
|
}),
|
|
448
448
|
])
|
|
449
449
|
}).toThrow('Overlapping discriminator value: test')
|
|
@@ -451,14 +451,14 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
451
451
|
})
|
|
452
452
|
|
|
453
453
|
describe('edge cases', () => {
|
|
454
|
-
const schema =
|
|
455
|
-
|
|
456
|
-
type:
|
|
457
|
-
value:
|
|
454
|
+
const schema = discriminatedUnion('type', [
|
|
455
|
+
object({
|
|
456
|
+
type: literal('a'),
|
|
457
|
+
value: string(),
|
|
458
458
|
}),
|
|
459
|
-
|
|
460
|
-
type:
|
|
461
|
-
value:
|
|
459
|
+
object({
|
|
460
|
+
type: literal('b'),
|
|
461
|
+
value: integer(),
|
|
462
462
|
}),
|
|
463
463
|
])
|
|
464
464
|
|
|
@@ -490,10 +490,10 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
490
490
|
})
|
|
491
491
|
|
|
492
492
|
it('handles empty string discriminator', () => {
|
|
493
|
-
const emptySchema =
|
|
494
|
-
|
|
495
|
-
key:
|
|
496
|
-
value:
|
|
493
|
+
const emptySchema = discriminatedUnion('key', [
|
|
494
|
+
object({
|
|
495
|
+
key: literal(''),
|
|
496
|
+
value: string(),
|
|
497
497
|
}),
|
|
498
498
|
])
|
|
499
499
|
|
|
@@ -505,10 +505,10 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
505
505
|
})
|
|
506
506
|
|
|
507
507
|
it('handles zero discriminator', () => {
|
|
508
|
-
const zeroSchema =
|
|
509
|
-
|
|
510
|
-
count:
|
|
511
|
-
value:
|
|
508
|
+
const zeroSchema = discriminatedUnion('count', [
|
|
509
|
+
object({
|
|
510
|
+
count: literal(0),
|
|
511
|
+
value: string(),
|
|
512
512
|
}),
|
|
513
513
|
])
|
|
514
514
|
|
|
@@ -520,10 +520,10 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
520
520
|
})
|
|
521
521
|
|
|
522
522
|
it('handles false discriminator', () => {
|
|
523
|
-
const falseSchema =
|
|
524
|
-
|
|
525
|
-
flag:
|
|
526
|
-
value:
|
|
523
|
+
const falseSchema = discriminatedUnion('flag', [
|
|
524
|
+
object({
|
|
525
|
+
flag: literal(false),
|
|
526
|
+
value: string(),
|
|
527
527
|
}),
|
|
528
528
|
])
|
|
529
529
|
|
|
@@ -544,10 +544,10 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
544
544
|
})
|
|
545
545
|
|
|
546
546
|
it('handles discriminator with special characters', () => {
|
|
547
|
-
const specialSchema =
|
|
548
|
-
|
|
549
|
-
$type:
|
|
550
|
-
value:
|
|
547
|
+
const specialSchema = discriminatedUnion('$type', [
|
|
548
|
+
object({
|
|
549
|
+
$type: literal('test'),
|
|
550
|
+
value: string(),
|
|
551
551
|
}),
|
|
552
552
|
])
|
|
553
553
|
|
|
@@ -576,16 +576,16 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
576
576
|
})
|
|
577
577
|
|
|
578
578
|
describe('complex nested structures', () => {
|
|
579
|
-
const schema =
|
|
580
|
-
|
|
581
|
-
type:
|
|
582
|
-
name:
|
|
583
|
-
age:
|
|
579
|
+
const schema = discriminatedUnion('type', [
|
|
580
|
+
object({
|
|
581
|
+
type: literal('user'),
|
|
582
|
+
name: string(),
|
|
583
|
+
age: integer(),
|
|
584
584
|
}),
|
|
585
|
-
|
|
586
|
-
type:
|
|
587
|
-
title:
|
|
588
|
-
content:
|
|
585
|
+
object({
|
|
586
|
+
type: literal('post'),
|
|
587
|
+
title: string(),
|
|
588
|
+
content: string(),
|
|
589
589
|
}),
|
|
590
590
|
])
|
|
591
591
|
|
|
@@ -636,17 +636,17 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
636
636
|
|
|
637
637
|
describe('discriminator key variations', () => {
|
|
638
638
|
it('works with different discriminator key names', () => {
|
|
639
|
-
const kindSchema =
|
|
640
|
-
|
|
641
|
-
kind:
|
|
642
|
-
value:
|
|
639
|
+
const kindSchema = discriminatedUnion('kind', [
|
|
640
|
+
object({
|
|
641
|
+
kind: literal('a'),
|
|
642
|
+
value: string(),
|
|
643
643
|
}),
|
|
644
644
|
])
|
|
645
645
|
|
|
646
|
-
const tagSchema =
|
|
647
|
-
|
|
648
|
-
tag:
|
|
649
|
-
value:
|
|
646
|
+
const tagSchema = discriminatedUnion('tag', [
|
|
647
|
+
object({
|
|
648
|
+
tag: literal('a'),
|
|
649
|
+
value: string(),
|
|
650
650
|
}),
|
|
651
651
|
])
|
|
652
652
|
|
|
@@ -659,10 +659,10 @@ describe('DiscriminatedUnionSchema', () => {
|
|
|
659
659
|
})
|
|
660
660
|
|
|
661
661
|
it('rejects when discriminator key does not match schema', () => {
|
|
662
|
-
const schema =
|
|
663
|
-
|
|
664
|
-
type:
|
|
665
|
-
value:
|
|
662
|
+
const schema = discriminatedUnion('type', [
|
|
663
|
+
object({
|
|
664
|
+
type: literal('a'),
|
|
665
|
+
value: string(),
|
|
666
666
|
}),
|
|
667
667
|
])
|
|
668
668
|
|
|
@@ -1,32 +1,40 @@
|
|
|
1
1
|
import { isPlainObject } from '@atproto/lex-data'
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
InferInput,
|
|
4
|
+
InferOutput,
|
|
4
5
|
Schema,
|
|
6
|
+
ValidationContext,
|
|
5
7
|
ValidationResult,
|
|
6
8
|
Validator,
|
|
7
|
-
ValidatorContext,
|
|
8
9
|
} from '../core.js'
|
|
9
10
|
import { EnumSchema } from './enum.js'
|
|
10
11
|
import { LiteralSchema } from './literal.js'
|
|
11
12
|
import { ObjectSchema } from './object.js'
|
|
12
13
|
|
|
13
|
-
export type DiscriminatedUnionVariant<Discriminator extends string> =
|
|
14
|
-
ObjectSchema<Record<Discriminator, EnumSchema | LiteralSchema
|
|
14
|
+
export type DiscriminatedUnionVariant<Discriminator extends string = string> =
|
|
15
|
+
ObjectSchema<Record<Discriminator, EnumSchema<any> | LiteralSchema<any>>>
|
|
15
16
|
|
|
16
|
-
export type DiscriminatedUnionVariants<
|
|
17
|
+
export type DiscriminatedUnionVariants<TDiscriminator extends string> =
|
|
17
18
|
readonly [
|
|
18
|
-
DiscriminatedUnionVariant<
|
|
19
|
-
...DiscriminatedUnionVariant<
|
|
19
|
+
DiscriminatedUnionVariant<TDiscriminator>,
|
|
20
|
+
...DiscriminatedUnionVariant<TDiscriminator>[],
|
|
20
21
|
]
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
type DiscriminatedUnionSchemaInput<TVariants extends readonly Validator[]> =
|
|
24
|
+
TVariants extends readonly [
|
|
25
|
+
infer TValidator extends Validator,
|
|
26
|
+
...infer TRest extends readonly Validator[],
|
|
27
|
+
]
|
|
28
|
+
? InferInput<TValidator> | DiscriminatedUnionSchemaInput<TRest>
|
|
29
|
+
: never
|
|
30
|
+
|
|
31
|
+
type DiscriminatedUnionSchemaOutput<TVariants extends readonly Validator[]> =
|
|
32
|
+
TVariants extends readonly [
|
|
33
|
+
infer TValidator extends Validator,
|
|
34
|
+
...infer TRest extends readonly Validator[],
|
|
35
|
+
]
|
|
36
|
+
? InferOutput<TValidator> | DiscriminatedUnionSchemaOutput<TRest>
|
|
37
|
+
: never
|
|
30
38
|
|
|
31
39
|
/**
|
|
32
40
|
* @note There is no discriminated union in Lexicon schemas. This is a custom
|
|
@@ -34,14 +42,17 @@ export type DiscriminatedUnionSchemaOutput<
|
|
|
34
42
|
* lex library programmatically (i.e. not code generated from a lexicon schema).
|
|
35
43
|
*/
|
|
36
44
|
export class DiscriminatedUnionSchema<
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
> extends Schema<
|
|
40
|
-
|
|
45
|
+
const TDiscriminator extends string,
|
|
46
|
+
const TVariants extends DiscriminatedUnionVariants<TDiscriminator>,
|
|
47
|
+
> extends Schema<
|
|
48
|
+
DiscriminatedUnionSchemaInput<TVariants>,
|
|
49
|
+
DiscriminatedUnionSchemaOutput<TVariants>
|
|
50
|
+
> {
|
|
51
|
+
readonly variantsMap: Map<unknown, DiscriminatedUnionVariant<TDiscriminator>>
|
|
41
52
|
|
|
42
53
|
constructor(
|
|
43
|
-
readonly discriminator:
|
|
44
|
-
variants:
|
|
54
|
+
readonly discriminator: TDiscriminator,
|
|
55
|
+
readonly variants: TVariants,
|
|
45
56
|
) {
|
|
46
57
|
super()
|
|
47
58
|
|
|
@@ -51,10 +62,7 @@ export class DiscriminatedUnionSchema<
|
|
|
51
62
|
this.variantsMap = buildVariantsMap(discriminator, variants)
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
validateInContext(
|
|
55
|
-
input: unknown,
|
|
56
|
-
ctx: ValidatorContext,
|
|
57
|
-
): ValidationResult<DiscriminatedUnionSchemaOutput<Variants>> {
|
|
65
|
+
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
58
66
|
if (!isPlainObject(input)) {
|
|
59
67
|
return ctx.issueInvalidType(input, 'object')
|
|
60
68
|
}
|
|
@@ -70,7 +78,7 @@ export class DiscriminatedUnionSchema<
|
|
|
70
78
|
const variant = this.variantsMap.get(discriminatorValue)
|
|
71
79
|
if (variant) {
|
|
72
80
|
return ctx.validate(input, variant) as ValidationResult<
|
|
73
|
-
|
|
81
|
+
DiscriminatedUnionSchemaInput<TVariants>
|
|
74
82
|
>
|
|
75
83
|
}
|
|
76
84
|
|
|
@@ -115,3 +123,14 @@ function buildVariantsMap<Discriminator extends string>(
|
|
|
115
123
|
|
|
116
124
|
return variantsMap
|
|
117
125
|
}
|
|
126
|
+
|
|
127
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
128
|
+
export function discriminatedUnion<
|
|
129
|
+
const Discriminator extends string,
|
|
130
|
+
const Options extends DiscriminatedUnionVariants<Discriminator>,
|
|
131
|
+
>(discriminator: Discriminator, variants: Options) {
|
|
132
|
+
return new DiscriminatedUnionSchema<Discriminator, Options>(
|
|
133
|
+
discriminator,
|
|
134
|
+
variants,
|
|
135
|
+
)
|
|
136
|
+
}
|
package/src/schema/enum.test.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import { enumSchema } from './enum.js'
|
|
3
|
+
import { withDefault } from './with-default.js'
|
|
3
4
|
|
|
4
5
|
describe('EnumSchema', () => {
|
|
5
6
|
describe('with string values', () => {
|
|
6
|
-
const schema =
|
|
7
|
+
const schema = enumSchema(['male', 'female', 'other'])
|
|
7
8
|
|
|
8
9
|
it('validates matching string values', () => {
|
|
9
10
|
const result = schema.safeParse('male')
|
|
@@ -58,7 +59,7 @@ describe('EnumSchema', () => {
|
|
|
58
59
|
})
|
|
59
60
|
|
|
60
61
|
describe('with number values', () => {
|
|
61
|
-
const schema =
|
|
62
|
+
const schema = enumSchema([1, 2, 3])
|
|
62
63
|
|
|
63
64
|
it('validates matching number values', () => {
|
|
64
65
|
const result = schema.safeParse(1)
|
|
@@ -93,7 +94,7 @@ describe('EnumSchema', () => {
|
|
|
93
94
|
})
|
|
94
95
|
|
|
95
96
|
describe('with boolean values', () => {
|
|
96
|
-
const schema =
|
|
97
|
+
const schema = enumSchema([true, false])
|
|
97
98
|
|
|
98
99
|
it('validates true', () => {
|
|
99
100
|
const result = schema.safeParse(true)
|
|
@@ -117,7 +118,7 @@ describe('EnumSchema', () => {
|
|
|
117
118
|
})
|
|
118
119
|
|
|
119
120
|
describe('with single boolean value', () => {
|
|
120
|
-
const schema =
|
|
121
|
+
const schema = enumSchema([true])
|
|
121
122
|
|
|
122
123
|
it('validates true', () => {
|
|
123
124
|
const result = schema.safeParse(true)
|
|
@@ -131,7 +132,7 @@ describe('EnumSchema', () => {
|
|
|
131
132
|
})
|
|
132
133
|
|
|
133
134
|
describe('with null value', () => {
|
|
134
|
-
const schema =
|
|
135
|
+
const schema = enumSchema([null, 'value'])
|
|
135
136
|
|
|
136
137
|
it('validates null', () => {
|
|
137
138
|
const result = schema.safeParse(null)
|
|
@@ -150,7 +151,7 @@ describe('EnumSchema', () => {
|
|
|
150
151
|
})
|
|
151
152
|
|
|
152
153
|
describe('with mixed type values', () => {
|
|
153
|
-
const schema =
|
|
154
|
+
const schema = enumSchema(['string', 123, true, null])
|
|
154
155
|
|
|
155
156
|
it('validates string value', () => {
|
|
156
157
|
const result = schema.safeParse('string')
|
|
@@ -181,7 +182,7 @@ describe('EnumSchema', () => {
|
|
|
181
182
|
})
|
|
182
183
|
|
|
183
184
|
describe('with default option', () => {
|
|
184
|
-
const schema =
|
|
185
|
+
const schema = withDefault(enumSchema(['red', 'green', 'blue']), 'red')
|
|
185
186
|
|
|
186
187
|
it('validates matching values', () => {
|
|
187
188
|
const result = schema.safeParse('green')
|
|
@@ -221,7 +222,7 @@ describe('EnumSchema', () => {
|
|
|
221
222
|
})
|
|
222
223
|
|
|
223
224
|
describe('with default option as number', () => {
|
|
224
|
-
const schema =
|
|
225
|
+
const schema = withDefault(enumSchema([1, 2, 3]), 1)
|
|
225
226
|
|
|
226
227
|
it('uses default when input is undefined', () => {
|
|
227
228
|
const result = schema.safeParse(undefined)
|
|
@@ -238,7 +239,7 @@ describe('EnumSchema', () => {
|
|
|
238
239
|
})
|
|
239
240
|
|
|
240
241
|
describe('with default option as boolean', () => {
|
|
241
|
-
const schema =
|
|
242
|
+
const schema = withDefault(enumSchema([true, false]), false)
|
|
242
243
|
|
|
243
244
|
it('uses default when input is undefined', () => {
|
|
244
245
|
const result = schema.safeParse(undefined)
|
|
@@ -258,7 +259,7 @@ describe('EnumSchema', () => {
|
|
|
258
259
|
})
|
|
259
260
|
|
|
260
261
|
describe('with default option as null', () => {
|
|
261
|
-
const schema =
|
|
262
|
+
const schema = withDefault(enumSchema([null, 'value']), null)
|
|
262
263
|
|
|
263
264
|
it('uses default when input is undefined', () => {
|
|
264
265
|
const result = schema.safeParse(undefined)
|
|
@@ -278,7 +279,7 @@ describe('EnumSchema', () => {
|
|
|
278
279
|
})
|
|
279
280
|
|
|
280
281
|
describe('with single value', () => {
|
|
281
|
-
const schema =
|
|
282
|
+
const schema = enumSchema(['only'])
|
|
282
283
|
|
|
283
284
|
it('validates the single value', () => {
|
|
284
285
|
const result = schema.safeParse('only')
|
|
@@ -294,7 +295,7 @@ describe('EnumSchema', () => {
|
|
|
294
295
|
})
|
|
295
296
|
|
|
296
297
|
describe('with empty string value', () => {
|
|
297
|
-
const schema =
|
|
298
|
+
const schema = enumSchema(['', 'value'])
|
|
298
299
|
|
|
299
300
|
it('validates empty string', () => {
|
|
300
301
|
const result = schema.safeParse('')
|
|
@@ -313,7 +314,7 @@ describe('EnumSchema', () => {
|
|
|
313
314
|
})
|
|
314
315
|
|
|
315
316
|
describe('with zero value', () => {
|
|
316
|
-
const schema =
|
|
317
|
+
const schema = enumSchema([0, 1, 2])
|
|
317
318
|
|
|
318
319
|
it('validates zero', () => {
|
|
319
320
|
const result = schema.safeParse(0)
|
|
@@ -332,7 +333,7 @@ describe('EnumSchema', () => {
|
|
|
332
333
|
})
|
|
333
334
|
|
|
334
335
|
describe('case sensitivity', () => {
|
|
335
|
-
const schema =
|
|
336
|
+
const schema = enumSchema(['Value', 'VALUE', 'value'])
|
|
336
337
|
|
|
337
338
|
it('validates exact case matches', () => {
|
|
338
339
|
expect(schema.safeParse('Value').success).toBe(true)
|
|
@@ -347,7 +348,7 @@ describe('EnumSchema', () => {
|
|
|
347
348
|
})
|
|
348
349
|
|
|
349
350
|
describe('with special string values', () => {
|
|
350
|
-
const schema =
|
|
351
|
+
const schema = enumSchema([
|
|
351
352
|
'with space',
|
|
352
353
|
'with\ttab',
|
|
353
354
|
'with\nnewline',
|