@atproto/lex-schema 0.0.9 → 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 +34 -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 +7 -7
- 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 +13 -12
- 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,12 +1,12 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { integer } from './integer.js'
|
|
3
|
+
import { object } from './object.js'
|
|
4
4
|
import { refine } from './refine.js'
|
|
5
|
-
import {
|
|
5
|
+
import { string } from './string.js'
|
|
6
6
|
|
|
7
7
|
describe('refine', () => {
|
|
8
8
|
describe('basic refinement checks', () => {
|
|
9
|
-
const schema = refine(
|
|
9
|
+
const schema = refine(integer(), {
|
|
10
10
|
check: (value) => value > 0,
|
|
11
11
|
message: 'Value must be positive',
|
|
12
12
|
})
|
|
@@ -33,7 +33,7 @@ describe('refine', () => {
|
|
|
33
33
|
})
|
|
34
34
|
|
|
35
35
|
describe('refinement with type assertions', () => {
|
|
36
|
-
const schema = refine(
|
|
36
|
+
const schema = refine(integer(), {
|
|
37
37
|
check: (value): value is 42 => value === 42,
|
|
38
38
|
message: 'Value must be 42',
|
|
39
39
|
})
|
|
@@ -50,7 +50,7 @@ describe('refine', () => {
|
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
describe('refinement with string schema', () => {
|
|
53
|
-
const schema = refine(
|
|
53
|
+
const schema = refine(string(), {
|
|
54
54
|
check: (value) => value.includes('@'),
|
|
55
55
|
message: 'String must contain @ symbol',
|
|
56
56
|
})
|
|
@@ -72,7 +72,7 @@ describe('refine', () => {
|
|
|
72
72
|
})
|
|
73
73
|
|
|
74
74
|
describe('refinement with base schema constraints', () => {
|
|
75
|
-
const schema = refine(
|
|
75
|
+
const schema = refine(integer({ minimum: 0, maximum: 100 }), {
|
|
76
76
|
check: (value) => value % 2 === 0,
|
|
77
77
|
message: 'Value must be even',
|
|
78
78
|
})
|
|
@@ -100,7 +100,7 @@ describe('refine', () => {
|
|
|
100
100
|
|
|
101
101
|
describe('multiple refinements chained', () => {
|
|
102
102
|
const schema = refine(
|
|
103
|
-
refine(
|
|
103
|
+
refine(integer(), {
|
|
104
104
|
check: (value) => value > 0,
|
|
105
105
|
message: 'Value must be positive',
|
|
106
106
|
}),
|
|
@@ -135,7 +135,7 @@ describe('refine', () => {
|
|
|
135
135
|
})
|
|
136
136
|
|
|
137
137
|
describe('refinement with custom path', () => {
|
|
138
|
-
const schema = refine(
|
|
138
|
+
const schema = refine(integer(), {
|
|
139
139
|
check: (value) => value > 0,
|
|
140
140
|
message: 'Value must be positive',
|
|
141
141
|
path: 'customField',
|
|
@@ -153,7 +153,7 @@ describe('refine', () => {
|
|
|
153
153
|
})
|
|
154
154
|
|
|
155
155
|
describe('refinement with array path', () => {
|
|
156
|
-
const schema = refine(
|
|
156
|
+
const schema = refine(integer(), {
|
|
157
157
|
check: (value) => value > 0,
|
|
158
158
|
message: 'Value must be positive',
|
|
159
159
|
path: ['nested', 'field'],
|
|
@@ -171,12 +171,12 @@ describe('refine', () => {
|
|
|
171
171
|
})
|
|
172
172
|
|
|
173
173
|
describe('refinement on object properties', () => {
|
|
174
|
-
const schema =
|
|
175
|
-
age: refine(
|
|
174
|
+
const schema = object({
|
|
175
|
+
age: refine(integer(), {
|
|
176
176
|
check: (value) => value >= 18,
|
|
177
177
|
message: 'Age must be at least 18',
|
|
178
178
|
}),
|
|
179
|
-
email: refine(
|
|
179
|
+
email: refine(string(), {
|
|
180
180
|
check: (value) => value.includes('@'),
|
|
181
181
|
message: 'Email must contain @ symbol',
|
|
182
182
|
}),
|
|
@@ -216,7 +216,7 @@ describe('refine', () => {
|
|
|
216
216
|
})
|
|
217
217
|
|
|
218
218
|
describe('complex refinement logic', () => {
|
|
219
|
-
const schema = refine(
|
|
219
|
+
const schema = refine(string(), {
|
|
220
220
|
check: (value) => {
|
|
221
221
|
const hasLowerCase = /[a-z]/.test(value)
|
|
222
222
|
const hasUpperCase = /[A-Z]/.test(value)
|
|
@@ -253,7 +253,7 @@ describe('refine', () => {
|
|
|
253
253
|
})
|
|
254
254
|
|
|
255
255
|
describe('refinement with comparison logic', () => {
|
|
256
|
-
const schema = refine(
|
|
256
|
+
const schema = refine(integer(), {
|
|
257
257
|
check: (value) => {
|
|
258
258
|
// Check if value is a prime number
|
|
259
259
|
if (value <= 1) return false
|
|
@@ -285,7 +285,7 @@ describe('refine', () => {
|
|
|
285
285
|
})
|
|
286
286
|
|
|
287
287
|
describe('refinement with string length logic', () => {
|
|
288
|
-
const schema = refine(
|
|
288
|
+
const schema = refine(string({ minLength: 1, maxLength: 50 }), {
|
|
289
289
|
check: (value) => value.trim().length > 0,
|
|
290
290
|
message: 'String must not be only whitespace',
|
|
291
291
|
})
|
|
@@ -317,7 +317,7 @@ describe('refine', () => {
|
|
|
317
317
|
})
|
|
318
318
|
|
|
319
319
|
describe('refinement preserves original schema', () => {
|
|
320
|
-
const originalSchema =
|
|
320
|
+
const originalSchema = integer({ minimum: 0 })
|
|
321
321
|
const refinedSchema = refine(originalSchema, {
|
|
322
322
|
check: (value) => value % 2 === 0,
|
|
323
323
|
message: 'Value must be even',
|
|
@@ -343,7 +343,7 @@ describe('refine', () => {
|
|
|
343
343
|
})
|
|
344
344
|
|
|
345
345
|
describe('refinement with boundary conditions', () => {
|
|
346
|
-
const schema = refine(
|
|
346
|
+
const schema = refine(integer({ minimum: 0, maximum: 100 }), {
|
|
347
347
|
check: (value) => value !== 50,
|
|
348
348
|
message: 'Value must not be 50',
|
|
349
349
|
})
|
|
@@ -373,7 +373,7 @@ describe('refine', () => {
|
|
|
373
373
|
})
|
|
374
374
|
|
|
375
375
|
describe('refinement with regex patterns', () => {
|
|
376
|
-
const schema = refine(
|
|
376
|
+
const schema = refine(string(), {
|
|
377
377
|
check: (value) => /^[A-Z][a-zA-Z0-9]*$/.test(value),
|
|
378
378
|
message: 'Must start with uppercase letter',
|
|
379
379
|
})
|
|
@@ -405,7 +405,7 @@ describe('refine', () => {
|
|
|
405
405
|
})
|
|
406
406
|
|
|
407
407
|
describe('refinement with custom error messages', () => {
|
|
408
|
-
const schema = refine(
|
|
408
|
+
const schema = refine(integer(), {
|
|
409
409
|
check: (value) => value >= 1 && value <= 10,
|
|
410
410
|
message: 'Value must be between 1 and 10 (inclusive)',
|
|
411
411
|
})
|
|
@@ -428,7 +428,7 @@ describe('refine', () => {
|
|
|
428
428
|
|
|
429
429
|
describe('edge cases', () => {
|
|
430
430
|
it('handles refinement that always returns true', () => {
|
|
431
|
-
const schema = refine(
|
|
431
|
+
const schema = refine(integer(), {
|
|
432
432
|
check: () => true,
|
|
433
433
|
message: 'This should never fail',
|
|
434
434
|
})
|
|
@@ -437,7 +437,7 @@ describe('refine', () => {
|
|
|
437
437
|
})
|
|
438
438
|
|
|
439
439
|
it('handles refinement that always returns false', () => {
|
|
440
|
-
const schema = refine(
|
|
440
|
+
const schema = refine(integer(), {
|
|
441
441
|
check: () => false,
|
|
442
442
|
message: 'This always fails',
|
|
443
443
|
})
|
|
@@ -446,7 +446,7 @@ describe('refine', () => {
|
|
|
446
446
|
})
|
|
447
447
|
|
|
448
448
|
it('handles empty string refinement', () => {
|
|
449
|
-
const schema = refine(
|
|
449
|
+
const schema = refine(string(), {
|
|
450
450
|
check: (value) => value === '',
|
|
451
451
|
message: 'Value must be empty string',
|
|
452
452
|
})
|
|
@@ -458,7 +458,7 @@ describe('refine', () => {
|
|
|
458
458
|
})
|
|
459
459
|
|
|
460
460
|
it('handles zero value refinement', () => {
|
|
461
|
-
const schema = refine(
|
|
461
|
+
const schema = refine(integer(), {
|
|
462
462
|
check: (value) => value === 0,
|
|
463
463
|
message: 'Value must be zero',
|
|
464
464
|
})
|
|
@@ -470,7 +470,7 @@ describe('refine', () => {
|
|
|
470
470
|
})
|
|
471
471
|
|
|
472
472
|
it('handles negative value refinement', () => {
|
|
473
|
-
const schema = refine(
|
|
473
|
+
const schema = refine(integer(), {
|
|
474
474
|
check: (value) => value < 0,
|
|
475
475
|
message: 'Value must be negative',
|
|
476
476
|
})
|
|
@@ -483,7 +483,7 @@ describe('refine', () => {
|
|
|
483
483
|
})
|
|
484
484
|
|
|
485
485
|
describe('refinement with combined string constraints', () => {
|
|
486
|
-
const schema = refine(
|
|
486
|
+
const schema = refine(string({ minLength: 8, maxLength: 20 }), {
|
|
487
487
|
check: (value) => {
|
|
488
488
|
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value)
|
|
489
489
|
const hasLetter = /[a-zA-Z]/.test(value)
|
|
@@ -519,7 +519,7 @@ describe('refine', () => {
|
|
|
519
519
|
})
|
|
520
520
|
|
|
521
521
|
describe('refinement inheritance', () => {
|
|
522
|
-
const baseSchema =
|
|
522
|
+
const baseSchema = integer({ minimum: 0, maximum: 1000 })
|
|
523
523
|
const refinedOnce = refine(baseSchema, {
|
|
524
524
|
check: (value) => value % 10 === 0,
|
|
525
525
|
message: 'Must be divisible by 10',
|
|
@@ -551,7 +551,7 @@ describe('refine', () => {
|
|
|
551
551
|
})
|
|
552
552
|
|
|
553
553
|
describe('refinement with string format validation', () => {
|
|
554
|
-
const schema = refine(
|
|
554
|
+
const schema = refine(string({ format: 'uri' }), {
|
|
555
555
|
check: (value) => value.startsWith('https://'),
|
|
556
556
|
message: 'Must be HTTPS URI',
|
|
557
557
|
})
|
package/src/schema/refine.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
InferInput,
|
|
3
3
|
IssueCustom,
|
|
4
4
|
PropertyKey,
|
|
5
|
+
ValidationContext,
|
|
5
6
|
ValidationResult,
|
|
6
7
|
Validator,
|
|
7
|
-
ValidatorContext,
|
|
8
8
|
} from '../core.js'
|
|
9
9
|
import { CustomAssertionContext } from './custom.js'
|
|
10
10
|
|
|
@@ -48,23 +48,26 @@ export type Refinement<T = any, Out extends T = T> =
|
|
|
48
48
|
* // result.success === false
|
|
49
49
|
* ```
|
|
50
50
|
*/
|
|
51
|
-
export function refine<S extends Validator, Out extends Infer<S>>(
|
|
52
|
-
schema: S,
|
|
53
|
-
refinement: RefinementAssertion<Infer<S>, Out>,
|
|
54
|
-
): S & Validator<Out>
|
|
55
|
-
export function refine<S extends Validator>(
|
|
56
|
-
schema: S,
|
|
57
|
-
refinement: RefinementCheck<Infer<S>>,
|
|
58
|
-
): S
|
|
59
51
|
export function refine<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
>(
|
|
52
|
+
const TValidator extends Validator,
|
|
53
|
+
TInput extends InferInput<TValidator>,
|
|
54
|
+
>(
|
|
55
|
+
schema: TValidator,
|
|
56
|
+
refinement: RefinementAssertion<InferInput<TValidator>, TInput>,
|
|
57
|
+
): TValidator & Validator<TInput>
|
|
58
|
+
export function refine<const TValidator extends Validator>(
|
|
59
|
+
schema: TValidator,
|
|
60
|
+
refinement: RefinementCheck<InferInput<TValidator>>,
|
|
61
|
+
): TValidator
|
|
62
|
+
export function refine<
|
|
63
|
+
TRefinement extends Refinement,
|
|
64
|
+
const TValidator extends Validator<InferRefinement<TRefinement>>,
|
|
65
|
+
>(schema: TValidator, refinement: TRefinement): TValidator
|
|
63
66
|
/*@__NO_SIDE_EFFECTS__*/
|
|
64
|
-
export function refine<
|
|
65
|
-
schema:
|
|
66
|
-
refinement: Refinement<
|
|
67
|
-
):
|
|
67
|
+
export function refine<const TValidator extends Validator>(
|
|
68
|
+
schema: TValidator,
|
|
69
|
+
refinement: Refinement<unknown>,
|
|
70
|
+
): TValidator {
|
|
68
71
|
// This is basically the same as monkey patching the "validateInContext"
|
|
69
72
|
// method to the schema, but done in a way that does not mutate the original
|
|
70
73
|
// schema. This is safe to do because Validators don't update their internal
|
|
@@ -84,11 +87,11 @@ export function refine<S extends Validator>(
|
|
|
84
87
|
function validateInContextUnbound<S extends Validator>(
|
|
85
88
|
this: {
|
|
86
89
|
schema: S
|
|
87
|
-
refinement: Refinement<
|
|
90
|
+
refinement: Refinement<InferInput<S>>
|
|
88
91
|
},
|
|
89
92
|
input: unknown,
|
|
90
|
-
ctx:
|
|
91
|
-
): ValidationResult<
|
|
93
|
+
ctx: ValidationContext,
|
|
94
|
+
): ValidationResult<InferInput<S>> {
|
|
92
95
|
const result = ctx.validate(input, this.schema)
|
|
93
96
|
if (!result.success) return result
|
|
94
97
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import { regexp } from './regexp.js'
|
|
3
3
|
|
|
4
4
|
describe('RegexpSchema', () => {
|
|
5
5
|
describe('basic validation', () => {
|
|
6
|
-
const schema =
|
|
6
|
+
const schema = regexp(/^[a-z]+$/)
|
|
7
7
|
|
|
8
8
|
it('validates strings matching the pattern', () => {
|
|
9
9
|
const result = schema.safeParse('hello')
|
|
@@ -57,7 +57,7 @@ describe('RegexpSchema', () => {
|
|
|
57
57
|
})
|
|
58
58
|
|
|
59
59
|
describe('numeric patterns', () => {
|
|
60
|
-
const schema =
|
|
60
|
+
const schema = regexp(/^\d+$/)
|
|
61
61
|
|
|
62
62
|
it('validates numeric strings', () => {
|
|
63
63
|
const result = schema.safeParse('12345')
|
|
@@ -81,9 +81,7 @@ describe('RegexpSchema', () => {
|
|
|
81
81
|
})
|
|
82
82
|
|
|
83
83
|
describe('email pattern', () => {
|
|
84
|
-
const schema =
|
|
85
|
-
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
86
|
-
)
|
|
84
|
+
const schema = regexp(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)
|
|
87
85
|
|
|
88
86
|
it('validates simple email addresses', () => {
|
|
89
87
|
const result = schema.safeParse('user@example.com')
|
|
@@ -117,7 +115,7 @@ describe('RegexpSchema', () => {
|
|
|
117
115
|
})
|
|
118
116
|
|
|
119
117
|
describe('URL pattern', () => {
|
|
120
|
-
const schema =
|
|
118
|
+
const schema = regexp(/^https?:\/\/[^\s/$.?#].[^\s]*$/)
|
|
121
119
|
|
|
122
120
|
it('validates HTTP URLs', () => {
|
|
123
121
|
const result = schema.safeParse('http://example.com')
|
|
@@ -151,7 +149,7 @@ describe('RegexpSchema', () => {
|
|
|
151
149
|
})
|
|
152
150
|
|
|
153
151
|
describe('phone number pattern', () => {
|
|
154
|
-
const schema =
|
|
152
|
+
const schema = regexp(/^\+?[1-9]\d{1,14}$/)
|
|
155
153
|
|
|
156
154
|
it('validates simple phone numbers', () => {
|
|
157
155
|
const result = schema.safeParse('1234567890')
|
|
@@ -185,7 +183,7 @@ describe('RegexpSchema', () => {
|
|
|
185
183
|
})
|
|
186
184
|
|
|
187
185
|
describe('hex color pattern', () => {
|
|
188
|
-
const schema =
|
|
186
|
+
const schema = regexp(/^#[0-9A-Fa-f]{6}$/)
|
|
189
187
|
|
|
190
188
|
it('validates 6-digit hex colors', () => {
|
|
191
189
|
const result = schema.safeParse('#FF5733')
|
|
@@ -219,7 +217,7 @@ describe('RegexpSchema', () => {
|
|
|
219
217
|
})
|
|
220
218
|
|
|
221
219
|
describe('alphanumeric pattern', () => {
|
|
222
|
-
const schema =
|
|
220
|
+
const schema = regexp(/^[a-zA-Z0-9]+$/)
|
|
223
221
|
|
|
224
222
|
it('validates alphanumeric strings', () => {
|
|
225
223
|
const result = schema.safeParse('abc123')
|
|
@@ -253,7 +251,7 @@ describe('RegexpSchema', () => {
|
|
|
253
251
|
})
|
|
254
252
|
|
|
255
253
|
describe('case-insensitive pattern', () => {
|
|
256
|
-
const schema =
|
|
254
|
+
const schema = regexp(/^hello$/i)
|
|
257
255
|
|
|
258
256
|
it('validates lowercase match', () => {
|
|
259
257
|
const result = schema.safeParse('hello')
|
|
@@ -277,7 +275,7 @@ describe('RegexpSchema', () => {
|
|
|
277
275
|
})
|
|
278
276
|
|
|
279
277
|
describe('multiline pattern', () => {
|
|
280
|
-
const schema =
|
|
278
|
+
const schema = regexp(/^line\d+$/m)
|
|
281
279
|
|
|
282
280
|
it('validates single line matching pattern', () => {
|
|
283
281
|
const result = schema.safeParse('line1')
|
|
@@ -296,7 +294,7 @@ describe('RegexpSchema', () => {
|
|
|
296
294
|
})
|
|
297
295
|
|
|
298
296
|
describe('optional character pattern', () => {
|
|
299
|
-
const schema =
|
|
297
|
+
const schema = regexp(/^colou?r$/)
|
|
300
298
|
|
|
301
299
|
it('validates with optional character present', () => {
|
|
302
300
|
const result = schema.safeParse('colour')
|
|
@@ -315,7 +313,7 @@ describe('RegexpSchema', () => {
|
|
|
315
313
|
})
|
|
316
314
|
|
|
317
315
|
describe('character range pattern', () => {
|
|
318
|
-
const schema =
|
|
316
|
+
const schema = regexp(/^[0-5]+$/)
|
|
319
317
|
|
|
320
318
|
it('validates strings within range', () => {
|
|
321
319
|
const result = schema.safeParse('012345')
|
|
@@ -334,7 +332,7 @@ describe('RegexpSchema', () => {
|
|
|
334
332
|
})
|
|
335
333
|
|
|
336
334
|
describe('quantifier pattern', () => {
|
|
337
|
-
const schema =
|
|
335
|
+
const schema = regexp(/^a{3}$/)
|
|
338
336
|
|
|
339
337
|
it('validates exact repetition count', () => {
|
|
340
338
|
const result = schema.safeParse('aaa')
|
|
@@ -353,7 +351,7 @@ describe('RegexpSchema', () => {
|
|
|
353
351
|
})
|
|
354
352
|
|
|
355
353
|
describe('range quantifier pattern', () => {
|
|
356
|
-
const schema =
|
|
354
|
+
const schema = regexp(/^a{2,4}$/)
|
|
357
355
|
|
|
358
356
|
it('validates minimum repetition count', () => {
|
|
359
357
|
const result = schema.safeParse('aa')
|
|
@@ -382,7 +380,7 @@ describe('RegexpSchema', () => {
|
|
|
382
380
|
})
|
|
383
381
|
|
|
384
382
|
describe('alternation pattern', () => {
|
|
385
|
-
const schema =
|
|
383
|
+
const schema = regexp(/^(cat|dog|bird)$/)
|
|
386
384
|
|
|
387
385
|
it('validates first alternative', () => {
|
|
388
386
|
const result = schema.safeParse('cat')
|
|
@@ -406,7 +404,7 @@ describe('RegexpSchema', () => {
|
|
|
406
404
|
})
|
|
407
405
|
|
|
408
406
|
describe('word boundary pattern', () => {
|
|
409
|
-
const schema =
|
|
407
|
+
const schema = regexp(/\bword\b/)
|
|
410
408
|
|
|
411
409
|
it('validates word with boundaries', () => {
|
|
412
410
|
const result = schema.safeParse('word')
|
|
@@ -425,7 +423,7 @@ describe('RegexpSchema', () => {
|
|
|
425
423
|
})
|
|
426
424
|
|
|
427
425
|
describe('lookahead pattern', () => {
|
|
428
|
-
const schema =
|
|
426
|
+
const schema = regexp(/^(?=.*[A-Z])(?=.*[0-9]).{8,}$/)
|
|
429
427
|
|
|
430
428
|
it('validates string meeting all lookahead conditions', () => {
|
|
431
429
|
const result = schema.safeParse('Password1')
|
|
@@ -454,7 +452,7 @@ describe('RegexpSchema', () => {
|
|
|
454
452
|
})
|
|
455
453
|
|
|
456
454
|
describe('unicode pattern', () => {
|
|
457
|
-
const schema =
|
|
455
|
+
const schema = regexp(/^[\u4e00-\u9fa5]+$/)
|
|
458
456
|
|
|
459
457
|
it('validates Chinese characters', () => {
|
|
460
458
|
const result = schema.safeParse('你好')
|
|
@@ -478,7 +476,7 @@ describe('RegexpSchema', () => {
|
|
|
478
476
|
})
|
|
479
477
|
|
|
480
478
|
describe('empty string pattern', () => {
|
|
481
|
-
const schema =
|
|
479
|
+
const schema = regexp(/^$/)
|
|
482
480
|
|
|
483
481
|
it('validates empty strings', () => {
|
|
484
482
|
const result = schema.safeParse('')
|
|
@@ -497,7 +495,7 @@ describe('RegexpSchema', () => {
|
|
|
497
495
|
})
|
|
498
496
|
|
|
499
497
|
describe('wildcard pattern', () => {
|
|
500
|
-
const schema =
|
|
498
|
+
const schema = regexp(/^.*$/)
|
|
501
499
|
|
|
502
500
|
it('validates empty strings', () => {
|
|
503
501
|
const result = schema.safeParse('')
|
|
@@ -522,58 +520,56 @@ describe('RegexpSchema', () => {
|
|
|
522
520
|
|
|
523
521
|
describe('edge cases', () => {
|
|
524
522
|
it('handles pattern with escape sequences', () => {
|
|
525
|
-
const schema =
|
|
523
|
+
const schema = regexp(/^\d{3}\.\d{3}\.\d{3}\.\d{3}$/)
|
|
526
524
|
const result = schema.safeParse('192.168.001.001')
|
|
527
525
|
expect(result.success).toBe(true)
|
|
528
526
|
})
|
|
529
527
|
|
|
530
528
|
it('handles pattern with special regex characters', () => {
|
|
531
|
-
const schema =
|
|
529
|
+
const schema = regexp(/^\$\d+\.\d{2}$/)
|
|
532
530
|
const result = schema.safeParse('$99.99')
|
|
533
531
|
expect(result.success).toBe(true)
|
|
534
532
|
})
|
|
535
533
|
|
|
536
534
|
it('handles very long strings', () => {
|
|
537
|
-
const schema =
|
|
535
|
+
const schema = regexp(/^[a-z]+$/)
|
|
538
536
|
const longString = 'a'.repeat(10000)
|
|
539
537
|
const result = schema.safeParse(longString)
|
|
540
538
|
expect(result.success).toBe(true)
|
|
541
539
|
})
|
|
542
540
|
|
|
543
541
|
it('handles strings with newlines', () => {
|
|
544
|
-
const schema =
|
|
542
|
+
const schema = regexp(/^hello\nworld$/)
|
|
545
543
|
const result = schema.safeParse('hello\nworld')
|
|
546
544
|
expect(result.success).toBe(true)
|
|
547
545
|
})
|
|
548
546
|
|
|
549
547
|
it('handles strings with tabs', () => {
|
|
550
|
-
const schema =
|
|
548
|
+
const schema = regexp(/^hello\tworld$/)
|
|
551
549
|
const result = schema.safeParse('hello\tworld')
|
|
552
550
|
expect(result.success).toBe(true)
|
|
553
551
|
})
|
|
554
552
|
|
|
555
553
|
it('handles emoji patterns', () => {
|
|
556
|
-
const schema =
|
|
554
|
+
const schema = regexp(/^[\u{1F600}-\u{1F64F}]+$/u)
|
|
557
555
|
const result = schema.safeParse('😀😃😄')
|
|
558
556
|
expect(result.success).toBe(true)
|
|
559
557
|
})
|
|
560
558
|
|
|
561
559
|
it('handles global flag in pattern', () => {
|
|
562
|
-
const schema =
|
|
560
|
+
const schema = regexp(/test/g)
|
|
563
561
|
const result = schema.safeParse('test')
|
|
564
562
|
expect(result.success).toBe(true)
|
|
565
563
|
})
|
|
566
564
|
|
|
567
565
|
it('handles pattern matching anywhere in string', () => {
|
|
568
|
-
const schema =
|
|
566
|
+
const schema = regexp(/test/)
|
|
569
567
|
const result = schema.safeParse('this is a test string')
|
|
570
568
|
expect(result.success).toBe(true)
|
|
571
569
|
})
|
|
572
570
|
|
|
573
571
|
it('handles complex nested groups', () => {
|
|
574
|
-
const schema =
|
|
575
|
-
/^((https?|ftp):\/\/)?([a-z0-9]+\.)+[a-z]{2,}$/,
|
|
576
|
-
)
|
|
572
|
+
const schema = regexp(/^((https?|ftp):\/\/)?([a-z0-9]+\.)+[a-z]{2,}$/)
|
|
577
573
|
const result = schema.safeParse('https://example.com')
|
|
578
574
|
expect(result.success).toBe(true)
|
|
579
575
|
})
|
package/src/schema/regexp.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { Schema,
|
|
1
|
+
import { Schema, ValidationContext } from '../core.js'
|
|
2
2
|
|
|
3
|
-
export class RegexpSchema<
|
|
3
|
+
export class RegexpSchema<
|
|
4
|
+
TValue extends string = string,
|
|
5
|
+
> extends Schema<TValue> {
|
|
4
6
|
constructor(public readonly pattern: RegExp) {
|
|
5
7
|
super()
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
validateInContext(
|
|
9
|
-
input: unknown,
|
|
10
|
-
ctx: ValidatorContext,
|
|
11
|
-
): ValidationResult<T> {
|
|
10
|
+
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
12
11
|
if (typeof input !== 'string') {
|
|
13
12
|
return ctx.issueInvalidType(input, 'string')
|
|
14
13
|
}
|
|
@@ -17,6 +16,11 @@ export class RegexpSchema<T extends string> extends Schema<T> {
|
|
|
17
16
|
return ctx.issueInvalidFormat(input, this.pattern.toString())
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
return ctx.success(input as
|
|
19
|
+
return ctx.success(input as TValue)
|
|
21
20
|
}
|
|
22
21
|
}
|
|
22
|
+
|
|
23
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
24
|
+
export function regexp<TInput extends string = string>(pattern: RegExp) {
|
|
25
|
+
return new RegexpSchema<TInput>(pattern)
|
|
26
|
+
}
|