@atproto/lex-schema 0.0.1 → 0.0.3
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 +68 -0
- package/dist/core/$type.d.ts +6 -3
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +1 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +3 -3
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js +12 -6
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/result.d.ts.map +1 -1
- package/dist/core/result.js +6 -0
- package/dist/core/result.js.map +1 -1
- package/dist/core/string-format.d.ts +30 -27
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +56 -42
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/types.d.ts +9 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/external.d.ts +31 -28
- package/dist/external.d.ts.map +1 -1
- package/dist/external.js +33 -17
- package/dist/external.js.map +1 -1
- package/dist/schema/_parameters.d.ts +2 -2
- package/dist/schema/_parameters.d.ts.map +1 -1
- package/dist/schema/array.d.ts +5 -6
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +5 -6
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +2 -3
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +1 -2
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +4 -5
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +2 -3
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +3 -4
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +2 -3
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +13 -6
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +2 -4
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +3 -4
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +4 -3
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +3 -3
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +1 -1
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +15 -24
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +40 -64
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +8 -4
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +5 -3
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +3 -4
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +3 -4
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +22 -14
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +12 -22
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +8 -4
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +5 -3
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +2 -2
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +1 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +2 -3
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +1 -2
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +7 -0
- package/dist/schema/nullable.d.ts.map +1 -0
- package/dist/schema/nullable.js +19 -0
- package/dist/schema/nullable.js.map +1 -0
- package/dist/schema/object.d.ts +10 -44
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +13 -56
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +7 -0
- package/dist/schema/optional.d.ts.map +1 -0
- package/dist/schema/optional.js +25 -0
- package/dist/schema/optional.js.map +1 -0
- package/dist/schema/params.d.ts +14 -19
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +10 -24
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +4 -4
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +6 -6
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +1 -2
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +0 -1
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +0 -1
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +8 -9
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +0 -1
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +7 -8
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +0 -1
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +34 -28
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +1 -2
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +2 -3
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +1 -2
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +18 -0
- package/dist/schema/refine.d.ts.map +1 -0
- package/dist/schema/refine.js +33 -0
- package/dist/schema/refine.js.map +1 -0
- package/dist/schema/regexp.d.ts +7 -0
- package/dist/schema/regexp.d.ts.map +1 -0
- package/dist/schema/regexp.js +22 -0
- package/dist/schema/regexp.js.map +1 -0
- package/dist/schema/string.d.ts +4 -8
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +6 -3
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +7 -6
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +2 -3
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +1 -2
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +29 -27
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +1 -2
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +2 -2
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +1 -1
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +3 -4
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +3 -10
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +2 -2
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +1 -1
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +2 -3
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +1 -2
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +2 -2
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +1 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema.d.ts +4 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +6 -1
- package/dist/schema.js.map +1 -1
- package/dist/util/array-agg.d.ts.map +1 -1
- package/dist/util/array-agg.js +1 -0
- package/dist/util/array-agg.js.map +1 -1
- package/dist/util/lazy-property.d.ts +2 -0
- package/dist/util/lazy-property.d.ts.map +1 -0
- package/dist/util/lazy-property.js +14 -0
- package/dist/util/lazy-property.js.map +1 -0
- package/dist/validation/schema.d.ts +24 -0
- package/dist/validation/schema.d.ts.map +1 -0
- package/dist/validation/schema.js +57 -0
- package/dist/validation/schema.js.map +1 -0
- package/dist/validation/validation-error.d.ts +3 -3
- package/dist/validation/validation-error.d.ts.map +1 -1
- package/dist/validation/validation-error.js +32 -4
- package/dist/validation/validation-error.js.map +1 -1
- package/dist/validation/validation-issue.d.ts +32 -24
- package/dist/validation/validation-issue.d.ts.map +1 -1
- package/dist/validation/validation-issue.js +136 -92
- package/dist/validation/validation-issue.js.map +1 -1
- package/dist/validation/validator.d.ts +20 -50
- package/dist/validation/validator.d.ts.map +1 -1
- package/dist/validation/validator.js +40 -134
- package/dist/validation/validator.js.map +1 -1
- package/dist/validation.d.ts +1 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +1 -0
- package/dist/validation.js.map +1 -1
- package/package.json +8 -4
- package/src/core/$type.ts +7 -4
- package/src/core/record-key.ts +12 -5
- package/src/core/result.ts +6 -0
- package/src/core/string-format.ts +97 -61
- package/src/core/types.ts +12 -6
- package/src/external.ts +92 -70
- package/src/schema/_parameters.test.ts +416 -0
- package/src/schema/array.test.ts +237 -0
- package/src/schema/array.ts +17 -11
- package/src/schema/blob.test.ts +506 -0
- package/src/schema/blob.ts +3 -5
- package/src/schema/boolean.test.ts +116 -0
- package/src/schema/boolean.ts +5 -7
- package/src/schema/bytes.test.ts +226 -0
- package/src/schema/bytes.ts +4 -6
- package/src/schema/cid.test.ts +155 -0
- package/src/schema/cid.ts +14 -8
- package/src/schema/custom.test.ts +413 -0
- package/src/schema/custom.ts +10 -8
- package/src/schema/dict.test.ts +198 -0
- package/src/schema/dict.ts +6 -8
- package/src/schema/discriminated-union.test.ts +675 -0
- package/src/schema/discriminated-union.ts +68 -95
- package/src/schema/enum.test.ts +396 -0
- package/src/schema/enum.ts +12 -5
- package/src/schema/integer.test.ts +312 -0
- package/src/schema/integer.ts +5 -7
- package/src/schema/intersection.test.ts +32 -0
- package/src/schema/intersection.ts +37 -40
- package/src/schema/literal.test.ts +531 -0
- package/src/schema/literal.ts +12 -5
- package/src/schema/never.test.ts +174 -0
- package/src/schema/never.ts +3 -10
- package/src/schema/null.test.ts +79 -0
- package/src/schema/null.ts +3 -5
- package/src/schema/nullable.test.ts +480 -0
- package/src/schema/nullable.ts +23 -0
- package/src/schema/object.test.ts +47 -115
- package/src/schema/object.ts +23 -134
- package/src/schema/optional.test.ts +485 -0
- package/src/schema/optional.ts +31 -0
- package/src/schema/params.test.ts +582 -0
- package/src/schema/params.ts +37 -55
- package/src/schema/payload.test.ts +345 -0
- package/src/schema/payload.ts +5 -5
- package/src/schema/permission-set.test.ts +679 -0
- package/src/schema/permission-set.ts +6 -8
- package/src/schema/permission.test.ts +536 -0
- package/src/schema/permission.ts +0 -2
- package/src/schema/procedure.test.ts +443 -0
- package/src/schema/procedure.ts +11 -13
- package/src/schema/query.test.ts +408 -0
- package/src/schema/query.ts +9 -11
- package/src/schema/record.test.ts +694 -0
- package/src/schema/record.ts +38 -36
- package/src/schema/ref.test.ts +365 -0
- package/src/schema/ref.ts +8 -5
- package/src/schema/refine.test.ts +578 -0
- package/src/schema/refine.ts +85 -0
- package/src/schema/regexp.test.ts +580 -0
- package/src/schema/regexp.ts +22 -0
- package/src/schema/string.test.ts +612 -0
- package/src/schema/string.ts +11 -17
- package/src/schema/subscription.test.ts +689 -0
- package/src/schema/subscription.ts +13 -8
- package/src/schema/token.test.ts +428 -0
- package/src/schema/token.ts +3 -5
- package/src/schema/typed-object.test.ts +612 -0
- package/src/schema/typed-object.ts +23 -20
- package/src/schema/typed-ref.test.ts +823 -0
- package/src/schema/typed-ref.ts +10 -5
- package/src/schema/typed-union.test.ts +378 -0
- package/src/schema/typed-union.ts +6 -15
- package/src/schema/union.test.ts +200 -0
- package/src/schema/union.ts +5 -4
- package/src/schema/unknown-object.test.ts +592 -0
- package/src/schema/unknown-object.ts +3 -5
- package/src/schema/unknown.test.ts +312 -0
- package/src/schema/unknown.ts +3 -3
- package/src/schema.ts +7 -1
- package/src/util/array-agg.ts +1 -0
- package/src/util/lazy-property.ts +14 -0
- package/src/validation/schema.ts +92 -0
- package/src/validation/validation-error.ts +60 -9
- package/src/validation/validation-issue.ts +141 -144
- package/src/validation/validator.ts +67 -206
- package/src/validation.ts +1 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +7 -0
- package/tsconfig.tests.json +9 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { IntegerSchema } from './integer.js'
|
|
2
|
+
|
|
3
|
+
describe('IntegerSchema', () => {
|
|
4
|
+
describe('basic validation', () => {
|
|
5
|
+
const schema = new IntegerSchema({})
|
|
6
|
+
|
|
7
|
+
it('validates integers', () => {
|
|
8
|
+
const result = schema.safeParse(42)
|
|
9
|
+
expect(result.success).toBe(true)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
it('validates zero', () => {
|
|
13
|
+
const result = schema.safeParse(0)
|
|
14
|
+
expect(result.success).toBe(true)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('validates negative integers', () => {
|
|
18
|
+
const result = schema.safeParse(-42)
|
|
19
|
+
expect(result.success).toBe(true)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('validates large integers', () => {
|
|
23
|
+
const result = schema.safeParse(Number.MAX_SAFE_INTEGER)
|
|
24
|
+
expect(result.success).toBe(true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('validates small integers', () => {
|
|
28
|
+
const result = schema.safeParse(Number.MIN_SAFE_INTEGER)
|
|
29
|
+
expect(result.success).toBe(true)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('rejects floats', () => {
|
|
33
|
+
const result = schema.safeParse(3.14)
|
|
34
|
+
expect(result.success).toBe(false)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('rejects strings', () => {
|
|
38
|
+
const result = schema.safeParse('42')
|
|
39
|
+
expect(result.success).toBe(false)
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('rejects booleans', () => {
|
|
43
|
+
const result = schema.safeParse(true)
|
|
44
|
+
expect(result.success).toBe(false)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('rejects null', () => {
|
|
48
|
+
const result = schema.safeParse(null)
|
|
49
|
+
expect(result.success).toBe(false)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('rejects undefined', () => {
|
|
53
|
+
const result = schema.safeParse(undefined)
|
|
54
|
+
expect(result.success).toBe(false)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('rejects objects', () => {
|
|
58
|
+
const result = schema.safeParse({})
|
|
59
|
+
expect(result.success).toBe(false)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('rejects arrays', () => {
|
|
63
|
+
const result = schema.safeParse([42])
|
|
64
|
+
expect(result.success).toBe(false)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('rejects NaN', () => {
|
|
68
|
+
const result = schema.safeParse(NaN)
|
|
69
|
+
expect(result.success).toBe(false)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
it('rejects Infinity', () => {
|
|
73
|
+
const result = schema.safeParse(Infinity)
|
|
74
|
+
expect(result.success).toBe(false)
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('rejects -Infinity', () => {
|
|
78
|
+
const result = schema.safeParse(-Infinity)
|
|
79
|
+
expect(result.success).toBe(false)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
describe('default value', () => {
|
|
84
|
+
const schema = new IntegerSchema({ default: 10 })
|
|
85
|
+
|
|
86
|
+
it('uses default when undefined is provided', () => {
|
|
87
|
+
const result = schema.safeParse(undefined)
|
|
88
|
+
expect(result.success).toBe(true)
|
|
89
|
+
if (result.success) {
|
|
90
|
+
expect(result.value).toBe(10)
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('does not use default when explicit value is provided', () => {
|
|
95
|
+
const result = schema.safeParse(20)
|
|
96
|
+
expect(result.success).toBe(true)
|
|
97
|
+
if (result.success) {
|
|
98
|
+
expect(result.value).toBe(20)
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('does not use default when zero is provided', () => {
|
|
103
|
+
const result = schema.safeParse(0)
|
|
104
|
+
expect(result.success).toBe(true)
|
|
105
|
+
if (result.success) {
|
|
106
|
+
expect(result.value).toBe(0)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
describe('minimum constraint', () => {
|
|
112
|
+
const schema = new IntegerSchema({ minimum: 10 })
|
|
113
|
+
|
|
114
|
+
it('accepts values equal to minimum', () => {
|
|
115
|
+
const result = schema.safeParse(10)
|
|
116
|
+
expect(result.success).toBe(true)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('accepts values greater than minimum', () => {
|
|
120
|
+
const result = schema.safeParse(20)
|
|
121
|
+
expect(result.success).toBe(true)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('rejects values less than minimum', () => {
|
|
125
|
+
const result = schema.safeParse(5)
|
|
126
|
+
expect(result.success).toBe(false)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('rejects zero when minimum is positive', () => {
|
|
130
|
+
const result = schema.safeParse(0)
|
|
131
|
+
expect(result.success).toBe(false)
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it('rejects negative values when minimum is positive', () => {
|
|
135
|
+
const result = schema.safeParse(-10)
|
|
136
|
+
expect(result.success).toBe(false)
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
describe('maximum constraint', () => {
|
|
141
|
+
const schema = new IntegerSchema({ maximum: 100 })
|
|
142
|
+
|
|
143
|
+
it('accepts values equal to maximum', () => {
|
|
144
|
+
const result = schema.safeParse(100)
|
|
145
|
+
expect(result.success).toBe(true)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('accepts values less than maximum', () => {
|
|
149
|
+
const result = schema.safeParse(50)
|
|
150
|
+
expect(result.success).toBe(true)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('rejects values greater than maximum', () => {
|
|
154
|
+
const result = schema.safeParse(150)
|
|
155
|
+
expect(result.success).toBe(false)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
it('accepts zero when maximum is positive', () => {
|
|
159
|
+
const result = schema.safeParse(0)
|
|
160
|
+
expect(result.success).toBe(true)
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
it('accepts negative values when maximum is positive', () => {
|
|
164
|
+
const result = schema.safeParse(-10)
|
|
165
|
+
expect(result.success).toBe(true)
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
describe('minimum and maximum constraints', () => {
|
|
170
|
+
const schema = new IntegerSchema({ minimum: 10, maximum: 100 })
|
|
171
|
+
|
|
172
|
+
it('accepts values within range', () => {
|
|
173
|
+
const result = schema.safeParse(50)
|
|
174
|
+
expect(result.success).toBe(true)
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('accepts minimum value', () => {
|
|
178
|
+
const result = schema.safeParse(10)
|
|
179
|
+
expect(result.success).toBe(true)
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
it('accepts maximum value', () => {
|
|
183
|
+
const result = schema.safeParse(100)
|
|
184
|
+
expect(result.success).toBe(true)
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('rejects values below minimum', () => {
|
|
188
|
+
const result = schema.safeParse(5)
|
|
189
|
+
expect(result.success).toBe(false)
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
it('rejects values above maximum', () => {
|
|
193
|
+
const result = schema.safeParse(150)
|
|
194
|
+
expect(result.success).toBe(false)
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('negative range constraints', () => {
|
|
199
|
+
const schema = new IntegerSchema({ minimum: -100, maximum: -10 })
|
|
200
|
+
|
|
201
|
+
it('accepts negative values within range', () => {
|
|
202
|
+
const result = schema.safeParse(-50)
|
|
203
|
+
expect(result.success).toBe(true)
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
it('accepts minimum negative value', () => {
|
|
207
|
+
const result = schema.safeParse(-100)
|
|
208
|
+
expect(result.success).toBe(true)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('accepts maximum negative value', () => {
|
|
212
|
+
const result = schema.safeParse(-10)
|
|
213
|
+
expect(result.success).toBe(true)
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('rejects values below minimum', () => {
|
|
217
|
+
const result = schema.safeParse(-150)
|
|
218
|
+
expect(result.success).toBe(false)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('rejects values above maximum', () => {
|
|
222
|
+
const result = schema.safeParse(-5)
|
|
223
|
+
expect(result.success).toBe(false)
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
it('rejects zero', () => {
|
|
227
|
+
const result = schema.safeParse(0)
|
|
228
|
+
expect(result.success).toBe(false)
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
it('rejects positive values', () => {
|
|
232
|
+
const result = schema.safeParse(10)
|
|
233
|
+
expect(result.success).toBe(false)
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
describe('zero constraints', () => {
|
|
238
|
+
const schema = new IntegerSchema({ minimum: 0, maximum: 0 })
|
|
239
|
+
|
|
240
|
+
it('accepts zero', () => {
|
|
241
|
+
const result = schema.safeParse(0)
|
|
242
|
+
expect(result.success).toBe(true)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
it('rejects positive values', () => {
|
|
246
|
+
const result = schema.safeParse(1)
|
|
247
|
+
expect(result.success).toBe(false)
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('rejects negative values', () => {
|
|
251
|
+
const result = schema.safeParse(-1)
|
|
252
|
+
expect(result.success).toBe(false)
|
|
253
|
+
})
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
describe('combined with default value', () => {
|
|
257
|
+
const schema = new IntegerSchema({ default: 50, minimum: 10, maximum: 100 })
|
|
258
|
+
|
|
259
|
+
it('uses default when undefined is provided', () => {
|
|
260
|
+
const result = schema.safeParse(undefined)
|
|
261
|
+
expect(result.success).toBe(true)
|
|
262
|
+
if (result.success) {
|
|
263
|
+
expect(result.value).toBe(50)
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('validates explicit values with constraints', () => {
|
|
268
|
+
const result = schema.safeParse(75)
|
|
269
|
+
expect(result.success).toBe(true)
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
it('rejects explicit values outside constraints', () => {
|
|
273
|
+
const result = schema.safeParse(5)
|
|
274
|
+
expect(result.success).toBe(false)
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
describe('edge cases', () => {
|
|
279
|
+
it('handles minimum of 0', () => {
|
|
280
|
+
const schema = new IntegerSchema({ minimum: 0 })
|
|
281
|
+
expect(schema.safeParse(0).success).toBe(true)
|
|
282
|
+
expect(schema.safeParse(-1).success).toBe(false)
|
|
283
|
+
expect(schema.safeParse(1).success).toBe(true)
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
it('handles maximum of 0', () => {
|
|
287
|
+
const schema = new IntegerSchema({ maximum: 0 })
|
|
288
|
+
expect(schema.safeParse(0).success).toBe(true)
|
|
289
|
+
expect(schema.safeParse(1).success).toBe(false)
|
|
290
|
+
expect(schema.safeParse(-1).success).toBe(true)
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
it('handles very large ranges', () => {
|
|
294
|
+
const schema = new IntegerSchema({
|
|
295
|
+
minimum: Number.MIN_SAFE_INTEGER,
|
|
296
|
+
maximum: Number.MAX_SAFE_INTEGER,
|
|
297
|
+
})
|
|
298
|
+
expect(schema.safeParse(Number.MIN_SAFE_INTEGER).success).toBe(true)
|
|
299
|
+
expect(schema.safeParse(Number.MAX_SAFE_INTEGER).success).toBe(true)
|
|
300
|
+
expect(schema.safeParse(0).success).toBe(true)
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
it('allows unconstrained schema', () => {
|
|
304
|
+
const schema = new IntegerSchema({})
|
|
305
|
+
expect(schema.safeParse(Number.MIN_SAFE_INTEGER).success).toBe(true)
|
|
306
|
+
expect(schema.safeParse(Number.MAX_SAFE_INTEGER).success).toBe(true)
|
|
307
|
+
expect(schema.safeParse(0).success).toBe(true)
|
|
308
|
+
expect(schema.safeParse(-999999).success).toBe(true)
|
|
309
|
+
expect(schema.safeParse(999999).success).toBe(true)
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
})
|
package/src/schema/integer.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Schema, ValidationResult, ValidatorContext } from '../validation.js'
|
|
2
2
|
|
|
3
3
|
export type IntegerSchemaOptions = {
|
|
4
4
|
default?: number
|
|
@@ -6,15 +6,13 @@ export type IntegerSchemaOptions = {
|
|
|
6
6
|
maximum?: number
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export class IntegerSchema extends
|
|
10
|
-
readonly
|
|
11
|
-
|
|
12
|
-
constructor(readonly options: IntegerSchemaOptions) {
|
|
9
|
+
export class IntegerSchema extends Schema<number> {
|
|
10
|
+
constructor(readonly options: IntegerSchemaOptions = {}) {
|
|
13
11
|
super()
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
input: unknown = this.options
|
|
14
|
+
validateInContext(
|
|
15
|
+
input: unknown = this.options?.default,
|
|
18
16
|
ctx: ValidatorContext,
|
|
19
17
|
): ValidationResult<number> {
|
|
20
18
|
if (!isInteger(input)) {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BooleanSchema } from './boolean.js'
|
|
2
|
+
import { DictSchema } from './dict.js'
|
|
3
|
+
import { EnumSchema } from './enum.js'
|
|
4
|
+
import { IntersectionSchema } from './intersection.js'
|
|
5
|
+
import { ObjectSchema } from './object.js'
|
|
6
|
+
import { StringSchema } from './string.js'
|
|
7
|
+
|
|
8
|
+
describe('IntersectionSchema', () => {
|
|
9
|
+
const schema = new IntersectionSchema(
|
|
10
|
+
new ObjectSchema({
|
|
11
|
+
title: new StringSchema({}),
|
|
12
|
+
}),
|
|
13
|
+
new DictSchema(new EnumSchema(['tag1', 'tag2']), new BooleanSchema({})),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
it('validates extra properties with the provided validator', () => {
|
|
17
|
+
const result = schema.safeParse({
|
|
18
|
+
title: 'My Post',
|
|
19
|
+
tag1: true,
|
|
20
|
+
tag2: false,
|
|
21
|
+
})
|
|
22
|
+
expect(result.success).toBe(true)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('rejects extra properties that fail the provided validator', () => {
|
|
26
|
+
const result = schema.safeParse({
|
|
27
|
+
title: 'My Post',
|
|
28
|
+
tag1: 'not a boolean',
|
|
29
|
+
})
|
|
30
|
+
expect(result.success).toBe(false)
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -1,57 +1,54 @@
|
|
|
1
|
+
import { Simplify } from '../core.js'
|
|
1
2
|
import {
|
|
2
3
|
Infer,
|
|
4
|
+
Schema,
|
|
3
5
|
ValidationResult,
|
|
4
|
-
Validator,
|
|
5
6
|
ValidatorContext,
|
|
6
7
|
} from '../validation.js'
|
|
8
|
+
import { DictSchema } from './dict.js'
|
|
9
|
+
import { ObjectSchema } from './object.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Allows to more accurately represent the intersection of two object types
|
|
13
|
+
* where both types may share some keys, and one of them uses an index
|
|
14
|
+
* signature.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://www.typescriptlang.org/play/?#code/C4TwDgpgBAglC8UDeUBmB7dAuKByARgIYBOuUAvlAGTJQDaA+lAJYB2UAzsMWwOYC6OVgFcAtvgjEKAKGkATCAGMANiWiL0rLlEI4YsjVuBQA1hBA4uPVrwRQARBnT2Dm7QDdCy4dESE6ZiD8UAD0IVAi4pJQABQcABbowspyUBIORMT2AJSyEAAeYOjExqCQUACSrMCSHErAzJoAPNJQsFAFNaxyHFAASkrFck1WfAA0UMKsJqzoAO6sAHxjrVAAQh35XT39g8TDozYTUzPzSyuLdqtwVKttMYHoqO00j88bnRDdvawQ7pJ3NpQAD860BbRwSHBQLadAA0ix2G91oJ1vDggAfWABcxPF5QOH8aFtci5aRlaAwVDMfIQVKIKo1Yh1RQNZq0Jw4AgkMjkCYoRiIzjcPioyISKTkRayBQqNRQQzaQgAMRpdL01NpclcRignm8EFVWrsKrVchxQVC4XF0SxmSAA Playground link}
|
|
17
|
+
*/
|
|
18
|
+
export type Intersect<A, B> = B[keyof B] extends never
|
|
19
|
+
? A
|
|
20
|
+
: keyof A & keyof B extends never
|
|
21
|
+
? // If A and B don't overlap, just return A & B
|
|
22
|
+
A & B
|
|
23
|
+
: // Otherwise, properly represent the fact that accessing using an
|
|
24
|
+
// index signature could return a value from either A or B
|
|
25
|
+
A & { [K in keyof B]: B[K] | A[keyof A & K] }
|
|
7
26
|
|
|
8
|
-
export type IntersectionSchemaValidators = readonly [
|
|
9
|
-
Validator,
|
|
10
|
-
Validator,
|
|
11
|
-
...Validator[],
|
|
12
|
-
]
|
|
13
27
|
export type IntersectionSchemaOutput<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
> =
|
|
17
|
-
infer First extends Validator,
|
|
18
|
-
...infer Rest extends Validator[],
|
|
19
|
-
]
|
|
20
|
-
? IntersectionSchemaOutput<Rest, Base & Infer<First>>
|
|
21
|
-
: Base
|
|
28
|
+
Left extends ObjectSchema,
|
|
29
|
+
Right extends DictSchema,
|
|
30
|
+
> = Simplify<Intersect<Infer<Left>, Infer<Right>>>
|
|
22
31
|
|
|
23
32
|
export class IntersectionSchema<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
const Left extends ObjectSchema = any,
|
|
34
|
+
const Right extends DictSchema = any,
|
|
35
|
+
> extends Schema<IntersectionSchemaOutput<Left, Right>> {
|
|
36
|
+
constructor(
|
|
37
|
+
protected readonly left: Left,
|
|
38
|
+
protected readonly right: Right,
|
|
39
|
+
) {
|
|
27
40
|
super()
|
|
28
41
|
}
|
|
29
42
|
|
|
30
|
-
|
|
43
|
+
validateInContext(
|
|
31
44
|
input: unknown,
|
|
32
45
|
ctx: ValidatorContext,
|
|
33
|
-
): ValidationResult<IntersectionSchemaOutput<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!result.success) {
|
|
38
|
-
return result
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// @NOTE because transforming the value could make it invalid for previous
|
|
42
|
-
// validators, we need to ensure the input remains unchanged only gets
|
|
43
|
-
// transformed by the first validator.
|
|
44
|
-
if (i !== 0 && input !== result.value) {
|
|
45
|
-
// The alternative would be to allow transforms on a first pass
|
|
46
|
-
// (ignoring errors) and then re-validate the final value against all
|
|
47
|
-
// validators (without allowing further transforms). This would be way
|
|
48
|
-
// less efficient (we could make this optional).
|
|
49
|
-
return ctx.issueInvalidValue(input, [result.value])
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
input = result.value
|
|
53
|
-
}
|
|
46
|
+
): ValidationResult<IntersectionSchemaOutput<Left, Right>> {
|
|
47
|
+
const leftResult = ctx.validate(input, this.left)
|
|
48
|
+
if (!leftResult.success) return leftResult
|
|
54
49
|
|
|
55
|
-
return
|
|
50
|
+
return this.right.validateInContext(leftResult.value, ctx, {
|
|
51
|
+
ignoredKeys: this.left.validatorsMap,
|
|
52
|
+
}) as ValidationResult<IntersectionSchemaOutput<Left, Right>>
|
|
56
53
|
}
|
|
57
54
|
}
|