@atproto/lex-schema 0.1.5 → 0.1.6
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 +14 -0
- package/dist/core/$type.d.ts +2 -2
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +1 -1
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/schema.d.ts +3 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +1 -1
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.d.ts +2 -2
- package/dist/core/standard-schema.d.ts.map +1 -1
- package/dist/core/standard-schema.js.map +1 -1
- package/dist/core/string-format.d.ts +2 -2
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-error.d.ts +1 -1
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +1 -1
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validator.d.ts +1 -1
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +1 -1
- package/dist/core/validator.js.map +1 -1
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +1 -1
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +1 -1
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +1 -1
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +2 -2
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.js +1 -1
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.js +1 -1
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +1 -1
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +3 -3
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.js +1 -1
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +1 -1
- 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 +1 -1
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +2 -1
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.js +1 -1
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.js +1 -1
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +1 -1
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +3 -1
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/lex-map.d.ts +1 -1
- package/dist/schema/lex-map.d.ts.map +1 -1
- package/dist/schema/lex-map.js +1 -1
- package/dist/schema/lex-map.js.map +1 -1
- package/dist/schema/lex-value.d.ts +1 -1
- package/dist/schema/lex-value.d.ts.map +1 -1
- package/dist/schema/lex-value.js +1 -1
- package/dist/schema/lex-value.js.map +1 -1
- package/dist/schema/literal.js +1 -1
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.js +1 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.js +1 -1
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +1 -1
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +1 -1
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +2 -1
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +1 -1
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +2 -1
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +2 -1
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +1 -1
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +1 -1
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +3 -2
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +2 -1
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +1 -1
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +1 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +1 -1
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +1 -1
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +2 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +1 -1
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +2 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +2 -2
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +1 -1
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +1 -1
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +1 -1
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +2 -2
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.js +1 -1
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +2 -2
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +1 -1
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +3 -2
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +2 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +1 -1
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +1 -1
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +2 -2
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +1 -1
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +1 -1
- 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 +1 -1
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +3 -1
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +1 -1
- 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.js +1 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +1 -1
- package/dist/schema/with-default.d.ts.map +1 -1
- package/dist/schema/with-default.js +1 -1
- package/dist/schema/with-default.js.map +1 -1
- package/package.json +6 -10
- package/src/core/$type.test.ts +0 -24
- package/src/core/$type.ts +0 -199
- package/src/core/record-key.ts +0 -85
- package/src/core/result.ts +0 -15
- package/src/core/schema.ts +0 -412
- package/src/core/standard-schema.test.ts +0 -124
- package/src/core/standard-schema.ts +0 -31
- package/src/core/string-format.ts +0 -411
- package/src/core/types.ts +0 -120
- package/src/core/validation-error.ts +0 -134
- package/src/core/validation-issue.ts +0 -340
- package/src/core/validator.ts +0 -636
- package/src/core.ts +0 -9
- package/src/external.ts +0 -3
- package/src/helpers.test.ts +0 -694
- package/src/helpers.ts +0 -222
- package/src/index.ts +0 -3
- package/src/schema/array.test.ts +0 -251
- package/src/schema/array.ts +0 -126
- package/src/schema/blob.test.ts +0 -733
- package/src/schema/blob.ts +0 -150
- package/src/schema/boolean.test.ts +0 -118
- package/src/schema/boolean.ts +0 -46
- package/src/schema/bytes.test.ts +0 -227
- package/src/schema/bytes.ts +0 -81
- package/src/schema/cid.test.ts +0 -125
- package/src/schema/cid.ts +0 -69
- package/src/schema/custom.test.ts +0 -414
- package/src/schema/custom.ts +0 -106
- package/src/schema/dict.test.ts +0 -181
- package/src/schema/dict.ts +0 -122
- package/src/schema/discriminated-union.test.ts +0 -676
- package/src/schema/discriminated-union.ts +0 -196
- package/src/schema/enum.test.ts +0 -398
- package/src/schema/enum.ts +0 -77
- package/src/schema/integer.test.ts +0 -314
- package/src/schema/integer.ts +0 -86
- package/src/schema/intersection.test.ts +0 -33
- package/src/schema/intersection.ts +0 -113
- package/src/schema/lex-map.test.ts +0 -593
- package/src/schema/lex-map.ts +0 -63
- package/src/schema/lex-value.test.ts +0 -81
- package/src/schema/lex-value.ts +0 -86
- package/src/schema/literal.test.ts +0 -533
- package/src/schema/literal.ts +0 -70
- package/src/schema/never.test.ts +0 -175
- package/src/schema/never.ts +0 -56
- package/src/schema/null.test.ts +0 -80
- package/src/schema/null.ts +0 -49
- package/src/schema/nullable.test.ts +0 -470
- package/src/schema/nullable.ts +0 -74
- package/src/schema/object.test.ts +0 -69
- package/src/schema/object.ts +0 -136
- package/src/schema/optional.test.ts +0 -479
- package/src/schema/optional.ts +0 -92
- package/src/schema/params.test.ts +0 -1118
- package/src/schema/params.ts +0 -371
- package/src/schema/payload.test.ts +0 -340
- package/src/schema/payload.ts +0 -204
- package/src/schema/permission-set.test.ts +0 -613
- package/src/schema/permission-set.ts +0 -86
- package/src/schema/permission.test.ts +0 -537
- package/src/schema/permission.ts +0 -63
- package/src/schema/procedure.test.ts +0 -324
- package/src/schema/procedure.ts +0 -98
- package/src/schema/query.test.ts +0 -348
- package/src/schema/query.ts +0 -86
- package/src/schema/record.test.ts +0 -812
- package/src/schema/record.ts +0 -217
- package/src/schema/ref.test.ts +0 -349
- package/src/schema/ref.ts +0 -103
- package/src/schema/refine.test.ts +0 -579
- package/src/schema/refine.ts +0 -153
- package/src/schema/regexp.test.ts +0 -577
- package/src/schema/regexp.ts +0 -82
- package/src/schema/string.test.ts +0 -773
- package/src/schema/string.ts +0 -229
- package/src/schema/subscription.test.ts +0 -499
- package/src/schema/subscription.ts +0 -108
- package/src/schema/token.test.ts +0 -152
- package/src/schema/token.ts +0 -103
- package/src/schema/typed-object.test.ts +0 -745
- package/src/schema/typed-object.ts +0 -181
- package/src/schema/typed-ref.test.ts +0 -796
- package/src/schema/typed-ref.ts +0 -126
- package/src/schema/typed-union.test.ts +0 -355
- package/src/schema/typed-union.ts +0 -130
- package/src/schema/union.test.ts +0 -191
- package/src/schema/union.ts +0 -89
- package/src/schema/unknown.test.ts +0 -313
- package/src/schema/unknown.ts +0 -47
- package/src/schema/with-default.ts +0 -81
- package/src/schema.ts +0 -43
- package/src/util/array-agg.test.ts +0 -42
- package/src/util/array-agg.ts +0 -44
- package/src/util/assertion-util.ts +0 -1
- package/src/util/if-any.ts +0 -3
- package/src/util/lazy-property.ts +0 -14
- package/src/util/memoize.ts +0 -37
- package/tsconfig.build.json +0 -12
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
|
@@ -1,470 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { enumSchema } from './enum.js'
|
|
3
|
-
import { integer } from './integer.js'
|
|
4
|
-
import { nullable } from './nullable.js'
|
|
5
|
-
import { object } from './object.js'
|
|
6
|
-
import { string } from './string.js'
|
|
7
|
-
import { withDefault } from './with-default.js'
|
|
8
|
-
|
|
9
|
-
describe('NullableSchema', () => {
|
|
10
|
-
describe('with StringSchema', () => {
|
|
11
|
-
const schema = nullable(string())
|
|
12
|
-
|
|
13
|
-
it('validates null', () => {
|
|
14
|
-
const result = schema.safeParse(null)
|
|
15
|
-
expect(result.success).toBe(true)
|
|
16
|
-
if (result.success) {
|
|
17
|
-
expect(result.value).toBe(null)
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('validates valid string values', () => {
|
|
22
|
-
const result = schema.safeParse('hello')
|
|
23
|
-
expect(result.success).toBe(true)
|
|
24
|
-
if (result.success) {
|
|
25
|
-
expect(result.value).toBe('hello')
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('validates empty strings', () => {
|
|
30
|
-
const result = schema.safeParse('')
|
|
31
|
-
expect(result.success).toBe(true)
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('rejects undefined', () => {
|
|
35
|
-
const result = schema.safeParse(undefined)
|
|
36
|
-
expect(result.success).toBe(false)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('rejects numbers', () => {
|
|
40
|
-
const result = schema.safeParse(123)
|
|
41
|
-
expect(result.success).toBe(false)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('rejects booleans', () => {
|
|
45
|
-
const result = schema.safeParse(true)
|
|
46
|
-
expect(result.success).toBe(false)
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
it('rejects objects', () => {
|
|
50
|
-
const result = schema.safeParse({ value: 'test' })
|
|
51
|
-
expect(result.success).toBe(false)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('rejects arrays', () => {
|
|
55
|
-
const result = schema.safeParse(['hello'])
|
|
56
|
-
expect(result.success).toBe(false)
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
describe('with IntegerSchema', () => {
|
|
61
|
-
const schema = nullable(integer())
|
|
62
|
-
|
|
63
|
-
it('validates null', () => {
|
|
64
|
-
const result = schema.safeParse(null)
|
|
65
|
-
expect(result.success).toBe(true)
|
|
66
|
-
if (result.success) {
|
|
67
|
-
expect(result.value).toBe(null)
|
|
68
|
-
}
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('validates valid integer values', () => {
|
|
72
|
-
const result = schema.safeParse(42)
|
|
73
|
-
expect(result.success).toBe(true)
|
|
74
|
-
if (result.success) {
|
|
75
|
-
expect(result.value).toBe(42)
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('validates zero', () => {
|
|
80
|
-
const result = schema.safeParse(0)
|
|
81
|
-
expect(result.success).toBe(true)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('validates negative integers', () => {
|
|
85
|
-
const result = schema.safeParse(-42)
|
|
86
|
-
expect(result.success).toBe(true)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
it('rejects floats', () => {
|
|
90
|
-
const result = schema.safeParse(3.14)
|
|
91
|
-
expect(result.success).toBe(false)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('rejects strings', () => {
|
|
95
|
-
const result = schema.safeParse('42')
|
|
96
|
-
expect(result.success).toBe(false)
|
|
97
|
-
})
|
|
98
|
-
|
|
99
|
-
it('rejects undefined', () => {
|
|
100
|
-
const result = schema.safeParse(undefined)
|
|
101
|
-
expect(result.success).toBe(false)
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
describe('with EnumSchema', () => {
|
|
106
|
-
const schema = nullable(enumSchema(['red', 'green', 'blue']))
|
|
107
|
-
|
|
108
|
-
it('validates null', () => {
|
|
109
|
-
const result = schema.safeParse(null)
|
|
110
|
-
expect(result.success).toBe(true)
|
|
111
|
-
if (result.success) {
|
|
112
|
-
expect(result.value).toBe(null)
|
|
113
|
-
}
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it('validates valid enum values', () => {
|
|
117
|
-
expect(schema.safeParse('red').success).toBe(true)
|
|
118
|
-
expect(schema.safeParse('green').success).toBe(true)
|
|
119
|
-
expect(schema.safeParse('blue').success).toBe(true)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('rejects invalid enum values', () => {
|
|
123
|
-
const result = schema.safeParse('yellow')
|
|
124
|
-
expect(result.success).toBe(false)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('rejects undefined', () => {
|
|
128
|
-
const result = schema.safeParse(undefined)
|
|
129
|
-
expect(result.success).toBe(false)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('rejects empty string when not in enum', () => {
|
|
133
|
-
const result = schema.safeParse('')
|
|
134
|
-
expect(result.success).toBe(false)
|
|
135
|
-
})
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
describe('with constrained StringSchema', () => {
|
|
139
|
-
const schema = nullable(string({ minLength: 3, maxLength: 10 }))
|
|
140
|
-
|
|
141
|
-
it('validates null', () => {
|
|
142
|
-
const result = schema.safeParse(null)
|
|
143
|
-
expect(result.success).toBe(true)
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
it('validates strings within constraints', () => {
|
|
147
|
-
const result = schema.safeParse('hello')
|
|
148
|
-
expect(result.success).toBe(true)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
it('rejects strings below minimum length', () => {
|
|
152
|
-
const result = schema.safeParse('hi')
|
|
153
|
-
expect(result.success).toBe(false)
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
it('rejects strings above maximum length', () => {
|
|
157
|
-
const result = schema.safeParse('hello world!')
|
|
158
|
-
expect(result.success).toBe(false)
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
it('accepts strings at minimum boundary', () => {
|
|
162
|
-
const result = schema.safeParse('abc')
|
|
163
|
-
expect(result.success).toBe(true)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
it('accepts strings at maximum boundary', () => {
|
|
167
|
-
const result = schema.safeParse('1234567890')
|
|
168
|
-
expect(result.success).toBe(true)
|
|
169
|
-
})
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
describe('with constrained IntegerSchema', () => {
|
|
173
|
-
const schema = nullable(integer({ minimum: 0, maximum: 100 }))
|
|
174
|
-
|
|
175
|
-
it('validates null', () => {
|
|
176
|
-
const result = schema.safeParse(null)
|
|
177
|
-
expect(result.success).toBe(true)
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
it('validates integers within constraints', () => {
|
|
181
|
-
const result = schema.safeParse(50)
|
|
182
|
-
expect(result.success).toBe(true)
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
it('validates minimum value', () => {
|
|
186
|
-
const result = schema.safeParse(0)
|
|
187
|
-
expect(result.success).toBe(true)
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
it('validates maximum value', () => {
|
|
191
|
-
const result = schema.safeParse(100)
|
|
192
|
-
expect(result.success).toBe(true)
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
it('rejects values below minimum', () => {
|
|
196
|
-
const result = schema.safeParse(-1)
|
|
197
|
-
expect(result.success).toBe(false)
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
it('rejects values above maximum', () => {
|
|
201
|
-
const result = schema.safeParse(101)
|
|
202
|
-
expect(result.success).toBe(false)
|
|
203
|
-
})
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
describe('with StringSchema having default value', () => {
|
|
207
|
-
const schema = nullable(withDefault(string(), 'default'))
|
|
208
|
-
|
|
209
|
-
it('validates null explicitly', () => {
|
|
210
|
-
const result = schema.safeParse(null)
|
|
211
|
-
expect(result.success).toBe(true)
|
|
212
|
-
if (result.success) {
|
|
213
|
-
expect(result.value).toBe(null)
|
|
214
|
-
}
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
it('uses default value when undefined is provided', () => {
|
|
218
|
-
const result = schema.safeParse(undefined)
|
|
219
|
-
expect(result.success).toBe(true)
|
|
220
|
-
if (result.success) {
|
|
221
|
-
expect(result.value).toBe('default')
|
|
222
|
-
}
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
it('validates explicit string values', () => {
|
|
226
|
-
const result = schema.safeParse('custom')
|
|
227
|
-
expect(result.success).toBe(true)
|
|
228
|
-
if (result.success) {
|
|
229
|
-
expect(result.value).toBe('custom')
|
|
230
|
-
}
|
|
231
|
-
})
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
describe('with ObjectSchema', () => {
|
|
235
|
-
const schema = nullable(
|
|
236
|
-
object({
|
|
237
|
-
name: string(),
|
|
238
|
-
age: integer(),
|
|
239
|
-
}),
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
it('validates null', () => {
|
|
243
|
-
const result = schema.safeParse(null)
|
|
244
|
-
expect(result.success).toBe(true)
|
|
245
|
-
if (result.success) {
|
|
246
|
-
expect(result.value).toBe(null)
|
|
247
|
-
}
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('validates valid objects', () => {
|
|
251
|
-
const result = schema.safeParse({ name: 'Alice', age: 30 })
|
|
252
|
-
expect(result.success).toBe(true)
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
it('rejects invalid objects with missing properties', () => {
|
|
256
|
-
const result = schema.safeParse({ name: 'Alice' })
|
|
257
|
-
expect(result.success).toBe(false)
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
it('rejects invalid objects with wrong types', () => {
|
|
261
|
-
const result = schema.safeParse({ name: 'Alice', age: 'thirty' })
|
|
262
|
-
expect(result.success).toBe(false)
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
it('rejects empty objects', () => {
|
|
266
|
-
const result = schema.safeParse({})
|
|
267
|
-
expect(result.success).toBe(false)
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
it('rejects primitive values', () => {
|
|
271
|
-
const result = schema.safeParse('not an object')
|
|
272
|
-
expect(result.success).toBe(false)
|
|
273
|
-
})
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
describe('nested nullable schemas', () => {
|
|
277
|
-
const schema = nullable(nullable(string()))
|
|
278
|
-
|
|
279
|
-
it('validates null at outer level', () => {
|
|
280
|
-
const result = schema.safeParse(null)
|
|
281
|
-
expect(result.success).toBe(true)
|
|
282
|
-
if (result.success) {
|
|
283
|
-
expect(result.value).toBe(null)
|
|
284
|
-
}
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
it('validates valid string values', () => {
|
|
288
|
-
const result = schema.safeParse('hello')
|
|
289
|
-
expect(result.success).toBe(true)
|
|
290
|
-
if (result.success) {
|
|
291
|
-
expect(result.value).toBe('hello')
|
|
292
|
-
}
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
it('rejects undefined', () => {
|
|
296
|
-
const result = schema.safeParse(undefined)
|
|
297
|
-
expect(result.success).toBe(false)
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
it('rejects invalid types', () => {
|
|
301
|
-
const result = schema.safeParse(123)
|
|
302
|
-
expect(result.success).toBe(false)
|
|
303
|
-
})
|
|
304
|
-
})
|
|
305
|
-
|
|
306
|
-
describe('with StringSchema format constraints', () => {
|
|
307
|
-
const schema = nullable(string({ format: 'uri' }))
|
|
308
|
-
|
|
309
|
-
it('validates null', () => {
|
|
310
|
-
const result = schema.safeParse(null)
|
|
311
|
-
expect(result.success).toBe(true)
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
it('validates valid URIs', () => {
|
|
315
|
-
const result = schema.safeParse('https://example.com')
|
|
316
|
-
expect(result.success).toBe(true)
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
it('rejects invalid URIs', () => {
|
|
320
|
-
const result = schema.safeParse('not a uri')
|
|
321
|
-
expect(result.success).toBe(false)
|
|
322
|
-
})
|
|
323
|
-
|
|
324
|
-
it('rejects invalid format even with valid string', () => {
|
|
325
|
-
const result = schema.safeParse('just a string')
|
|
326
|
-
expect(result.success).toBe(false)
|
|
327
|
-
})
|
|
328
|
-
})
|
|
329
|
-
|
|
330
|
-
describe('edge cases', () => {
|
|
331
|
-
const stringSchema = nullable(string())
|
|
332
|
-
|
|
333
|
-
it('handles null correctly without coercion', () => {
|
|
334
|
-
const result = stringSchema.safeParse(null)
|
|
335
|
-
expect(result.success).toBe(true)
|
|
336
|
-
if (result.success) {
|
|
337
|
-
expect(result.value).toBe(null)
|
|
338
|
-
expect(result.value).not.toBe(undefined)
|
|
339
|
-
expect(result.value).not.toBe('')
|
|
340
|
-
expect(result.value).not.toBe(0)
|
|
341
|
-
expect(result.value).not.toBe(false)
|
|
342
|
-
}
|
|
343
|
-
})
|
|
344
|
-
|
|
345
|
-
it('distinguishes null from falsy values', () => {
|
|
346
|
-
expect(stringSchema.safeParse(null).success).toBe(true)
|
|
347
|
-
expect(stringSchema.safeParse(undefined).success).toBe(false)
|
|
348
|
-
expect(stringSchema.safeParse('').success).toBe(true)
|
|
349
|
-
expect(stringSchema.safeParse(0).success).toBe(false)
|
|
350
|
-
expect(stringSchema.safeParse(false).success).toBe(false)
|
|
351
|
-
})
|
|
352
|
-
|
|
353
|
-
it('handles NaN correctly', () => {
|
|
354
|
-
const result = stringSchema.safeParse(NaN)
|
|
355
|
-
expect(result.success).toBe(false)
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
it('handles Symbol correctly', () => {
|
|
359
|
-
const result = stringSchema.safeParse(Symbol('test'))
|
|
360
|
-
expect(result.success).toBe(false)
|
|
361
|
-
})
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
describe('type preservation', () => {
|
|
365
|
-
it('preserves string type for valid strings', () => {
|
|
366
|
-
const schema = nullable(string())
|
|
367
|
-
const result = schema.safeParse('test')
|
|
368
|
-
expect(result.success).toBe(true)
|
|
369
|
-
if (result.success) {
|
|
370
|
-
expect(typeof result.value).toBe('string')
|
|
371
|
-
expect(result.value).toBe('test')
|
|
372
|
-
}
|
|
373
|
-
})
|
|
374
|
-
|
|
375
|
-
it('preserves number type for valid integers', () => {
|
|
376
|
-
const schema = nullable(integer())
|
|
377
|
-
const result = schema.safeParse(42)
|
|
378
|
-
expect(result.success).toBe(true)
|
|
379
|
-
if (result.success) {
|
|
380
|
-
expect(typeof result.value).toBe('number')
|
|
381
|
-
expect(result.value).toBe(42)
|
|
382
|
-
}
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
it('preserves object type for valid objects', () => {
|
|
386
|
-
const schema = nullable(object({ key: string() }))
|
|
387
|
-
const input = { key: 'value' }
|
|
388
|
-
const result = schema.safeParse(input)
|
|
389
|
-
expect(result.success).toBe(true)
|
|
390
|
-
if (result.success) {
|
|
391
|
-
expect(typeof result.value).toBe('object')
|
|
392
|
-
expect(result.value).toEqual({ key: 'value' })
|
|
393
|
-
}
|
|
394
|
-
})
|
|
395
|
-
|
|
396
|
-
it('preserves null type exactly', () => {
|
|
397
|
-
const schema = nullable(string())
|
|
398
|
-
const result = schema.safeParse(null)
|
|
399
|
-
expect(result.success).toBe(true)
|
|
400
|
-
if (result.success) {
|
|
401
|
-
expect(result.value).toBe(null)
|
|
402
|
-
expect(result.value === null).toBe(true)
|
|
403
|
-
expect(typeof result.value).toBe('object')
|
|
404
|
-
}
|
|
405
|
-
})
|
|
406
|
-
})
|
|
407
|
-
|
|
408
|
-
describe('with complex wrapped schemas', () => {
|
|
409
|
-
it('validates nullable enum with default', () => {
|
|
410
|
-
const schema = nullable(
|
|
411
|
-
withDefault(enumSchema(['option1', 'option2']), 'option1'),
|
|
412
|
-
)
|
|
413
|
-
|
|
414
|
-
expect(schema.safeParse(null).success).toBe(true)
|
|
415
|
-
expect(schema.safeParse('option1').success).toBe(true)
|
|
416
|
-
expect(schema.safeParse('option2').success).toBe(true)
|
|
417
|
-
expect(schema.safeParse(undefined).success).toBe(true)
|
|
418
|
-
expect(schema.safeParse('invalid').success).toBe(false)
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
it('handles nullable schema with grapheme constraints', () => {
|
|
422
|
-
const schema = nullable(string({ minGraphemes: 2, maxGraphemes: 5 }))
|
|
423
|
-
|
|
424
|
-
expect(schema.safeParse(null).success).toBe(true)
|
|
425
|
-
expect(schema.safeParse('ab').success).toBe(true)
|
|
426
|
-
expect(schema.safeParse('hello').success).toBe(true)
|
|
427
|
-
expect(schema.safeParse('a').success).toBe(false)
|
|
428
|
-
expect(schema.safeParse('hello!').success).toBe(false)
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
it('handles nullable integer with negative range', () => {
|
|
432
|
-
const schema = nullable(integer({ minimum: -100, maximum: -10 }))
|
|
433
|
-
|
|
434
|
-
expect(schema.safeParse(null).success).toBe(true)
|
|
435
|
-
expect(schema.safeParse(-50).success).toBe(true)
|
|
436
|
-
expect(schema.safeParse(-100).success).toBe(true)
|
|
437
|
-
expect(schema.safeParse(-10).success).toBe(true)
|
|
438
|
-
expect(schema.safeParse(0).success).toBe(false)
|
|
439
|
-
expect(schema.safeParse(-5).success).toBe(false)
|
|
440
|
-
expect(schema.safeParse(-150).success).toBe(false)
|
|
441
|
-
})
|
|
442
|
-
})
|
|
443
|
-
|
|
444
|
-
describe('validation error behavior', () => {
|
|
445
|
-
it('returns failure for wrapped schema validation errors', () => {
|
|
446
|
-
const schema = nullable(integer({ minimum: 10 }))
|
|
447
|
-
const result = schema.safeParse(5)
|
|
448
|
-
expect(result.success).toBe(false)
|
|
449
|
-
})
|
|
450
|
-
|
|
451
|
-
it('returns failure for type mismatches', () => {
|
|
452
|
-
const schema = nullable(string())
|
|
453
|
-
const result = schema.safeParse(123)
|
|
454
|
-
expect(result.success).toBe(false)
|
|
455
|
-
})
|
|
456
|
-
|
|
457
|
-
it('returns success for null regardless of wrapped constraints', () => {
|
|
458
|
-
const schema = nullable(string({ minLength: 100, format: 'uri' }))
|
|
459
|
-
const result = schema.safeParse(null)
|
|
460
|
-
expect(result.success).toBe(true)
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
it('wrapped schema validation applies when value is not null', () => {
|
|
464
|
-
const schema = nullable(string({ minLength: 5 }))
|
|
465
|
-
expect(schema.safeParse(null).success).toBe(true)
|
|
466
|
-
expect(schema.safeParse('hello').success).toBe(true)
|
|
467
|
-
expect(schema.safeParse('hi').success).toBe(false)
|
|
468
|
-
})
|
|
469
|
-
})
|
|
470
|
-
})
|
package/src/schema/nullable.ts
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
InferInput,
|
|
3
|
-
InferOutput,
|
|
4
|
-
Schema,
|
|
5
|
-
ValidationContext,
|
|
6
|
-
Validator,
|
|
7
|
-
} from '../core.js'
|
|
8
|
-
import { memoizedTransformer } from '../util/memoize.js'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Schema wrapper that allows null values in addition to the wrapped schema.
|
|
12
|
-
*
|
|
13
|
-
* When the input is `null`, validation succeeds immediately. Otherwise,
|
|
14
|
-
* the input is validated against the wrapped schema.
|
|
15
|
-
*
|
|
16
|
-
* @template TValidator - The wrapped validator type
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```ts
|
|
20
|
-
* const schema = new NullableSchema(l.string())
|
|
21
|
-
* schema.validate(null) // success
|
|
22
|
-
* schema.validate('hello') // success
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export class NullableSchema<const TValidator extends Validator> extends Schema<
|
|
26
|
-
InferInput<TValidator> | null,
|
|
27
|
-
InferOutput<TValidator> | null
|
|
28
|
-
> {
|
|
29
|
-
readonly type = 'nullable' as const
|
|
30
|
-
|
|
31
|
-
constructor(readonly validator: TValidator) {
|
|
32
|
-
super()
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
36
|
-
if (input === null) {
|
|
37
|
-
return ctx.success(null)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return ctx.validate(input, this.validator)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Creates a nullable schema that accepts null in addition to the wrapped type.
|
|
46
|
-
*
|
|
47
|
-
* Wraps another schema to allow null values. Different from `optional()` which
|
|
48
|
-
* allows undefined.
|
|
49
|
-
*
|
|
50
|
-
* @param validator - The validator to make nullable
|
|
51
|
-
* @returns A new {@link NullableSchema} instance
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* ```ts
|
|
55
|
-
* // Nullable string
|
|
56
|
-
* const nullableString = l.nullable(l.string())
|
|
57
|
-
* nullableString.parse(null) // null
|
|
58
|
-
* nullableString.parse('hello') // 'hello'
|
|
59
|
-
*
|
|
60
|
-
* // In an object
|
|
61
|
-
* const userSchema = l.object({
|
|
62
|
-
* name: l.string(),
|
|
63
|
-
* deletedAt: l.nullable(l.string({ format: 'datetime' })),
|
|
64
|
-
* })
|
|
65
|
-
*
|
|
66
|
-
* // Combine with optional for null or undefined
|
|
67
|
-
* const maybeString = l.optional(l.nullable(l.string()))
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
export const nullable = /*#__PURE__*/ memoizedTransformer(function <
|
|
71
|
-
const TValidator extends Validator,
|
|
72
|
-
>(validator: TValidator) {
|
|
73
|
-
return new NullableSchema<TValidator>(validator)
|
|
74
|
-
})
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { enumSchema } from './enum.js'
|
|
3
|
-
import { integer } from './integer.js'
|
|
4
|
-
import { nullable } from './nullable.js'
|
|
5
|
-
import { object } from './object.js'
|
|
6
|
-
import { optional } from './optional.js'
|
|
7
|
-
import { string } from './string.js'
|
|
8
|
-
|
|
9
|
-
describe('ObjectSchema', () => {
|
|
10
|
-
const schema = object({
|
|
11
|
-
name: string(),
|
|
12
|
-
age: optional(integer()),
|
|
13
|
-
gender: optional(nullable(enumSchema(['male', 'female']))),
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('validates plain objects', () => {
|
|
17
|
-
const result = schema.safeParse({
|
|
18
|
-
name: 'Alice',
|
|
19
|
-
age: 30,
|
|
20
|
-
gender: 'female',
|
|
21
|
-
})
|
|
22
|
-
expect(result.success).toBe(true)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('rejects non-objects', () => {
|
|
26
|
-
const result = schema.safeParse('not an object')
|
|
27
|
-
expect(result.success).toBe(false)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('rejects missing properties', () => {
|
|
31
|
-
const result = schema.safeParse({
|
|
32
|
-
age: 30,
|
|
33
|
-
gender: 'female',
|
|
34
|
-
})
|
|
35
|
-
expect(result.success).toBe(false)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
it('validates optional properties', () => {
|
|
39
|
-
const result = schema.safeParse({
|
|
40
|
-
name: 'Alice',
|
|
41
|
-
})
|
|
42
|
-
expect(result.success).toBe(true)
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
it('validates nullable properties', () => {
|
|
46
|
-
const result = schema.safeParse({
|
|
47
|
-
name: 'Alice',
|
|
48
|
-
gender: null,
|
|
49
|
-
})
|
|
50
|
-
expect(result.success).toBe(true)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('rejects invalid property types', () => {
|
|
54
|
-
const result = schema.safeParse({
|
|
55
|
-
name: 'Alice',
|
|
56
|
-
age: 'thirty',
|
|
57
|
-
})
|
|
58
|
-
expect(result.success).toBe(false)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('ignores extra properties', () => {
|
|
62
|
-
const result = schema.safeParse({
|
|
63
|
-
name: 'Alice',
|
|
64
|
-
age: 30,
|
|
65
|
-
extra: 'value',
|
|
66
|
-
})
|
|
67
|
-
expect(result.success).toBe(true)
|
|
68
|
-
})
|
|
69
|
-
})
|