@atproto/lex-schema 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/LICENSE.txt +1 -1
- package/dist/core/$type.d.ts +11 -0
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js +4 -0
- package/dist/core/$type.js.map +1 -1
- package/dist/core/schema.d.ts +31 -24
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +38 -8
- package/dist/core/schema.js.map +1 -1
- package/dist/core/string-format.d.ts +35 -35
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js +49 -91
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-issue.js +1 -1
- package/dist/core/validation-issue.js.map +1 -1
- package/dist/core/validator.d.ts +53 -32
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +18 -22
- package/dist/core/validator.js.map +1 -1
- package/dist/external.d.ts +0 -85
- package/dist/external.d.ts.map +1 -1
- package/dist/external.js +0 -164
- package/dist/external.js.map +1 -1
- package/dist/helpers.d.ts +10 -5
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +3 -3
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +9 -5
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +14 -5
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +9 -7
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +9 -5
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.d.ts +3 -7
- package/dist/schema/boolean.d.ts.map +1 -1
- package/dist/schema/boolean.js +6 -7
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.d.ts +3 -2
- package/dist/schema/bytes.d.ts.map +1 -1
- package/dist/schema/bytes.js +7 -3
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +10 -8
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +5 -1
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.d.ts +6 -5
- package/dist/schema/custom.d.ts.map +1 -1
- package/dist/schema/custom.js +10 -4
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +8 -8
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +11 -2
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +21 -14
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +7 -0
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.d.ts +7 -9
- package/dist/schema/enum.d.ts.map +1 -1
- package/dist/schema/enum.js +8 -4
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.d.ts +5 -5
- package/dist/schema/integer.d.ts.map +1 -1
- package/dist/schema/integer.js +9 -5
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +4 -4
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +5 -0
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/literal.d.ts +6 -9
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +7 -4
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.d.ts +3 -2
- package/dist/schema/never.d.ts.map +1 -1
- package/dist/schema/never.js +5 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.d.ts +4 -3
- package/dist/schema/null.d.ts.map +1 -1
- package/dist/schema/null.js +6 -4
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +6 -5
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +9 -5
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +10 -8
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +11 -3
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +7 -5
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +14 -6
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +24 -13
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +47 -25
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +12 -9
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +11 -0
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +1 -0
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +5 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +6 -5
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js +5 -0
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +2 -1
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +5 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +2 -1
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +5 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +48 -30
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +12 -9
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +9 -6
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +9 -16
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +4 -4
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.d.ts +4 -3
- package/dist/schema/regexp.d.ts.map +1 -1
- package/dist/schema/regexp.js +5 -0
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +7 -8
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +13 -19
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +2 -1
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +5 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +6 -5
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +5 -0
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +43 -26
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +6 -3
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +16 -25
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +7 -17
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +9 -21
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +15 -11
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +6 -6
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +7 -5
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown-object.d.ts +5 -4
- package/dist/schema/unknown-object.d.ts.map +1 -1
- package/dist/schema/unknown-object.js +5 -1
- package/dist/schema/unknown-object.js.map +1 -1
- package/dist/schema/unknown.d.ts +3 -2
- package/dist/schema/unknown.d.ts.map +1 -1
- package/dist/schema/unknown.js +5 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +9 -0
- package/dist/schema/with-default.d.ts.map +1 -0
- package/dist/schema/with-default.js +27 -0
- package/dist/schema/with-default.js.map +1 -0
- package/dist/schema.d.ts +2 -2
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +2 -4
- package/dist/schema.js.map +1 -1
- package/dist/util/assertion-util.d.ts +0 -6
- package/dist/util/assertion-util.d.ts.map +1 -1
- package/dist/util/assertion-util.js +0 -28
- package/dist/util/assertion-util.js.map +1 -1
- package/dist/util/memoize.d.ts +2 -2
- package/dist/util/memoize.d.ts.map +1 -1
- package/dist/util/memoize.js +23 -39
- package/dist/util/memoize.js.map +1 -1
- package/package.json +3 -3
- package/src/core/$type.test.ts +20 -0
- package/src/core/$type.ts +30 -0
- package/src/core/schema.ts +86 -38
- package/src/core/string-format.ts +119 -158
- package/src/core/validation-issue.ts +1 -1
- package/src/core/validator.ts +93 -53
- package/src/external.ts +0 -404
- package/src/helpers.test.ts +22 -21
- package/src/helpers.ts +14 -14
- package/src/schema/array.test.ts +38 -40
- package/src/schema/array.ts +35 -13
- package/src/schema/blob.test.ts +21 -21
- package/src/schema/blob.ts +19 -17
- package/src/schema/boolean.test.ts +9 -8
- package/src/schema/boolean.ts +7 -13
- package/src/schema/bytes.test.ts +13 -13
- package/src/schema/bytes.ts +13 -8
- package/src/schema/cid.test.ts +3 -3
- package/src/schema/cid.ts +15 -13
- package/src/schema/custom.test.ts +26 -26
- package/src/schema/custom.ts +20 -13
- package/src/schema/dict.test.ts +21 -39
- package/src/schema/dict.ts +28 -19
- package/src/schema/discriminated-union.test.ts +128 -128
- package/src/schema/discriminated-union.ts +45 -26
- package/src/schema/enum.test.ts +17 -16
- package/src/schema/enum.ts +16 -16
- package/src/schema/integer.test.ts +22 -21
- package/src/schema/integer.ts +12 -9
- package/src/schema/intersection.test.ts +10 -10
- package/src/schema/intersection.ts +17 -14
- package/src/schema/literal.test.ts +35 -34
- package/src/schema/literal.ts +12 -15
- package/src/schema/never.test.ts +5 -5
- package/src/schema/never.ts +7 -2
- package/src/schema/null.test.ts +3 -3
- package/src/schema/null.ts +9 -9
- package/src/schema/nullable.test.ts +31 -42
- package/src/schema/nullable.ts +17 -9
- package/src/schema/object.test.ts +10 -12
- package/src/schema/object.ts +27 -18
- package/src/schema/optional.test.ts +21 -28
- package/src/schema/optional.ts +27 -10
- package/src/schema/params.test.ts +471 -47
- package/src/schema/params.ts +72 -38
- package/src/schema/payload.test.ts +150 -156
- package/src/schema/payload.ts +35 -19
- package/src/schema/permission-set.test.ts +206 -273
- package/src/schema/permission-set.ts +8 -0
- package/src/schema/permission.test.ts +177 -177
- package/src/schema/permission.ts +13 -5
- package/src/schema/procedure.test.ts +183 -242
- package/src/schema/procedure.ts +18 -5
- package/src/schema/query.test.ts +186 -200
- package/src/schema/query.ts +16 -4
- package/src/schema/record.test.ts +121 -101
- package/src/schema/record.ts +74 -40
- package/src/schema/ref.test.ts +101 -118
- package/src/schema/ref.ts +33 -28
- package/src/schema/refine.test.ts +28 -28
- package/src/schema/refine.ts +23 -20
- package/src/schema/regexp.test.ts +29 -33
- package/src/schema/regexp.ts +11 -7
- package/src/schema/string.test.ts +35 -35
- package/src/schema/string.ts +24 -33
- package/src/schema/subscription.test.ts +259 -387
- package/src/schema/subscription.ts +16 -4
- package/src/schema/token.test.ts +47 -324
- package/src/schema/token.ts +14 -7
- package/src/schema/typed-object.test.ts +98 -81
- package/src/schema/typed-object.ts +68 -33
- package/src/schema/typed-ref.test.ts +206 -234
- package/src/schema/typed-ref.ts +40 -42
- package/src/schema/typed-union.test.ts +40 -64
- package/src/schema/typed-union.ts +36 -58
- package/src/schema/union.test.ts +17 -27
- package/src/schema/union.ts +20 -16
- package/src/schema/unknown-object.test.ts +8 -8
- package/src/schema/unknown-object.ts +9 -7
- package/src/schema/unknown.test.ts +4 -4
- package/src/schema/unknown.ts +7 -5
- package/src/schema/with-default.ts +35 -0
- package/src/schema.ts +2 -6
- package/src/util/assertion-util.ts +0 -39
- package/src/util/memoize.ts +26 -46
- package/dist/schema/_parameters.d.ts +0 -17
- package/dist/schema/_parameters.d.ts.map +0 -1
- package/dist/schema/_parameters.js +0 -20
- package/dist/schema/_parameters.js.map +0 -1
- package/src/schema/_parameters.test.ts +0 -417
- package/src/schema/_parameters.ts +0 -26
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { string } from './string.js'
|
|
3
|
+
import { token } from './token.js'
|
|
4
|
+
import { withDefault } from './with-default.js'
|
|
4
5
|
|
|
5
6
|
describe('StringSchema', () => {
|
|
6
7
|
describe('basic validation', () => {
|
|
7
|
-
const schema =
|
|
8
|
+
const schema = string()
|
|
8
9
|
|
|
9
10
|
it('validates plain strings', () => {
|
|
10
11
|
const result = schema.safeParse('hello world')
|
|
@@ -49,7 +50,7 @@ describe('StringSchema', () => {
|
|
|
49
50
|
|
|
50
51
|
describe('default values', () => {
|
|
51
52
|
it('uses default value when no input provided', () => {
|
|
52
|
-
const schema =
|
|
53
|
+
const schema = withDefault(string(), 'default value')
|
|
53
54
|
const result = schema.safeParse(undefined)
|
|
54
55
|
expect(result.success).toBe(true)
|
|
55
56
|
if (result.success) {
|
|
@@ -58,14 +59,14 @@ describe('StringSchema', () => {
|
|
|
58
59
|
})
|
|
59
60
|
|
|
60
61
|
it('validates default value against constraints', () => {
|
|
61
|
-
const schema =
|
|
62
|
+
const schema = string({ default: 'hi', minLength: 5 })
|
|
62
63
|
const result = schema.safeParse(undefined)
|
|
63
64
|
expect(result.success).toBe(false)
|
|
64
65
|
})
|
|
65
66
|
})
|
|
66
67
|
|
|
67
68
|
describe('minLength constraint', () => {
|
|
68
|
-
const schema =
|
|
69
|
+
const schema = string({ minLength: 5 })
|
|
69
70
|
|
|
70
71
|
it('accepts strings meeting minimum length', () => {
|
|
71
72
|
const result = schema.safeParse('hello')
|
|
@@ -89,7 +90,7 @@ describe('StringSchema', () => {
|
|
|
89
90
|
})
|
|
90
91
|
|
|
91
92
|
describe('maxLength constraint', () => {
|
|
92
|
-
const schema =
|
|
93
|
+
const schema = string({ maxLength: 10 })
|
|
93
94
|
|
|
94
95
|
it('accepts strings meeting maximum length', () => {
|
|
95
96
|
const result = schema.safeParse('1234567890')
|
|
@@ -113,20 +114,20 @@ describe('StringSchema', () => {
|
|
|
113
114
|
|
|
114
115
|
it('correctly handles UTF-8 multi-byte characters', () => {
|
|
115
116
|
// Emoji takes 4 bytes in UTF-8
|
|
116
|
-
const schema =
|
|
117
|
+
const schema = string({ maxLength: 4 })
|
|
117
118
|
const result = schema.safeParse('😀')
|
|
118
119
|
expect(result.success).toBe(true)
|
|
119
120
|
})
|
|
120
121
|
|
|
121
122
|
it('rejects when multi-byte characters exceed maxLength', () => {
|
|
122
|
-
const schema =
|
|
123
|
+
const schema = string({ maxLength: 3 })
|
|
123
124
|
const result = schema.safeParse('😀')
|
|
124
125
|
expect(result.success).toBe(false)
|
|
125
126
|
})
|
|
126
127
|
})
|
|
127
128
|
|
|
128
129
|
describe('combined min and max length', () => {
|
|
129
|
-
const schema =
|
|
130
|
+
const schema = string({ minLength: 3, maxLength: 10 })
|
|
130
131
|
|
|
131
132
|
it('accepts strings within range', () => {
|
|
132
133
|
const result = schema.safeParse('hello')
|
|
@@ -155,7 +156,7 @@ describe('StringSchema', () => {
|
|
|
155
156
|
})
|
|
156
157
|
|
|
157
158
|
describe('minGraphemes constraint', () => {
|
|
158
|
-
const schema =
|
|
159
|
+
const schema = string({ minGraphemes: 3 })
|
|
159
160
|
|
|
160
161
|
it('accepts strings meeting minimum graphemes', () => {
|
|
161
162
|
const result = schema.safeParse('abc')
|
|
@@ -184,7 +185,7 @@ describe('StringSchema', () => {
|
|
|
184
185
|
})
|
|
185
186
|
|
|
186
187
|
describe('maxGraphemes constraint', () => {
|
|
187
|
-
const schema =
|
|
188
|
+
const schema = string({ maxGraphemes: 5 })
|
|
188
189
|
|
|
189
190
|
it('accepts strings meeting maximum graphemes', () => {
|
|
190
191
|
const result = schema.safeParse('hello')
|
|
@@ -213,7 +214,7 @@ describe('StringSchema', () => {
|
|
|
213
214
|
})
|
|
214
215
|
|
|
215
216
|
describe('combined grapheme constraints', () => {
|
|
216
|
-
const schema =
|
|
217
|
+
const schema = string({ minGraphemes: 2, maxGraphemes: 5 })
|
|
217
218
|
|
|
218
219
|
it('accepts strings within grapheme range', () => {
|
|
219
220
|
const result = schema.safeParse('hello')
|
|
@@ -242,7 +243,7 @@ describe('StringSchema', () => {
|
|
|
242
243
|
})
|
|
243
244
|
|
|
244
245
|
describe('format: datetime', () => {
|
|
245
|
-
const schema =
|
|
246
|
+
const schema = string({ format: 'datetime' })
|
|
246
247
|
|
|
247
248
|
it('accepts valid ISO datetime strings', () => {
|
|
248
249
|
const result = schema.safeParse('2023-12-25T12:00:00Z')
|
|
@@ -266,7 +267,7 @@ describe('StringSchema', () => {
|
|
|
266
267
|
})
|
|
267
268
|
|
|
268
269
|
describe('format: uri', () => {
|
|
269
|
-
const schema =
|
|
270
|
+
const schema = string({ format: 'uri' })
|
|
270
271
|
|
|
271
272
|
it('accepts valid HTTP URIs', () => {
|
|
272
273
|
const result = schema.safeParse('https://example.com')
|
|
@@ -295,7 +296,7 @@ describe('StringSchema', () => {
|
|
|
295
296
|
})
|
|
296
297
|
|
|
297
298
|
describe('format: at-uri', () => {
|
|
298
|
-
const schema =
|
|
299
|
+
const schema = string({ format: 'at-uri' })
|
|
299
300
|
|
|
300
301
|
it('accepts valid AT URI', () => {
|
|
301
302
|
const result = schema.safeParse(
|
|
@@ -316,7 +317,7 @@ describe('StringSchema', () => {
|
|
|
316
317
|
})
|
|
317
318
|
|
|
318
319
|
describe('format: did', () => {
|
|
319
|
-
const schema =
|
|
320
|
+
const schema = string({ format: 'did' })
|
|
320
321
|
|
|
321
322
|
it('accepts valid DID with plc method', () => {
|
|
322
323
|
const result = schema.safeParse('did:plc:abc123')
|
|
@@ -340,7 +341,7 @@ describe('StringSchema', () => {
|
|
|
340
341
|
})
|
|
341
342
|
|
|
342
343
|
describe('format: handle', () => {
|
|
343
|
-
const schema =
|
|
344
|
+
const schema = string({ format: 'handle' })
|
|
344
345
|
|
|
345
346
|
it('accepts valid handle', () => {
|
|
346
347
|
const result = schema.safeParse('user.bsky.social')
|
|
@@ -364,7 +365,7 @@ describe('StringSchema', () => {
|
|
|
364
365
|
})
|
|
365
366
|
|
|
366
367
|
describe('format: at-identifier', () => {
|
|
367
|
-
const schema =
|
|
368
|
+
const schema = string({ format: 'at-identifier' })
|
|
368
369
|
|
|
369
370
|
it('accepts valid DID as at-identifier', () => {
|
|
370
371
|
const result = schema.safeParse('did:plc:abc123')
|
|
@@ -383,7 +384,7 @@ describe('StringSchema', () => {
|
|
|
383
384
|
})
|
|
384
385
|
|
|
385
386
|
describe('format: nsid', () => {
|
|
386
|
-
const schema =
|
|
387
|
+
const schema = string({ format: 'nsid' })
|
|
387
388
|
|
|
388
389
|
it('accepts valid NSID', () => {
|
|
389
390
|
const result = schema.safeParse('app.bsky.feed.post')
|
|
@@ -407,7 +408,7 @@ describe('StringSchema', () => {
|
|
|
407
408
|
})
|
|
408
409
|
|
|
409
410
|
describe('format: cid', () => {
|
|
410
|
-
const schema =
|
|
411
|
+
const schema = string({ format: 'cid' })
|
|
411
412
|
|
|
412
413
|
it('accepts valid CID v1', () => {
|
|
413
414
|
const result = schema.safeParse(
|
|
@@ -428,7 +429,7 @@ describe('StringSchema', () => {
|
|
|
428
429
|
})
|
|
429
430
|
|
|
430
431
|
describe('format: language', () => {
|
|
431
|
-
const schema =
|
|
432
|
+
const schema = string({ format: 'language' })
|
|
432
433
|
|
|
433
434
|
it('accepts valid BCP 47 language code', () => {
|
|
434
435
|
const result = schema.safeParse('en')
|
|
@@ -452,7 +453,7 @@ describe('StringSchema', () => {
|
|
|
452
453
|
})
|
|
453
454
|
|
|
454
455
|
describe('format: tid', () => {
|
|
455
|
-
const schema =
|
|
456
|
+
const schema = string({ format: 'tid' })
|
|
456
457
|
|
|
457
458
|
it('accepts valid TID', () => {
|
|
458
459
|
const result = schema.safeParse('3jzfcijpj2z2a')
|
|
@@ -471,7 +472,7 @@ describe('StringSchema', () => {
|
|
|
471
472
|
})
|
|
472
473
|
|
|
473
474
|
describe('format: record-key', () => {
|
|
474
|
-
const schema =
|
|
475
|
+
const schema = string({ format: 'record-key' })
|
|
475
476
|
|
|
476
477
|
it('accepts valid record key', () => {
|
|
477
478
|
const result = schema.safeParse('3jzfcijpj2z2a')
|
|
@@ -495,7 +496,7 @@ describe('StringSchema', () => {
|
|
|
495
496
|
})
|
|
496
497
|
|
|
497
498
|
describe('type coercion', () => {
|
|
498
|
-
const schema =
|
|
499
|
+
const schema = string()
|
|
499
500
|
|
|
500
501
|
it('coerces Date objects to ISO strings', () => {
|
|
501
502
|
const date = new Date('2023-12-25T12:00:00Z')
|
|
@@ -531,17 +532,16 @@ describe('StringSchema', () => {
|
|
|
531
532
|
})
|
|
532
533
|
|
|
533
534
|
it('coerces TokenSchema instances to strings', () => {
|
|
534
|
-
const
|
|
535
|
-
const result = schema.safeParse(token)
|
|
535
|
+
const result = schema.safeParse(token('my.to.ken', 'main'))
|
|
536
536
|
expect(result.success).toBe(true)
|
|
537
537
|
if (result.success) {
|
|
538
|
-
expect(result.value).toBe('
|
|
538
|
+
expect(result.value).toBe('my.to.ken')
|
|
539
539
|
}
|
|
540
540
|
})
|
|
541
541
|
})
|
|
542
542
|
|
|
543
543
|
describe('combined constraints and format', () => {
|
|
544
|
-
const schema =
|
|
544
|
+
const schema = string({
|
|
545
545
|
format: 'handle',
|
|
546
546
|
minLength: 5,
|
|
547
547
|
maxLength: 50,
|
|
@@ -572,39 +572,39 @@ describe('StringSchema', () => {
|
|
|
572
572
|
|
|
573
573
|
describe('edge cases', () => {
|
|
574
574
|
it('handles strings with special characters', () => {
|
|
575
|
-
const schema =
|
|
575
|
+
const schema = string()
|
|
576
576
|
const result = schema.safeParse('hello\nworld\ttab')
|
|
577
577
|
expect(result.success).toBe(true)
|
|
578
578
|
})
|
|
579
579
|
|
|
580
580
|
it('handles strings with unicode characters', () => {
|
|
581
|
-
const schema =
|
|
581
|
+
const schema = string()
|
|
582
582
|
const result = schema.safeParse('Hello 世界 🌍')
|
|
583
583
|
expect(result.success).toBe(true)
|
|
584
584
|
})
|
|
585
585
|
|
|
586
586
|
it('handles very long strings', () => {
|
|
587
|
-
const schema =
|
|
587
|
+
const schema = string({ maxLength: 10000 })
|
|
588
588
|
const longString = 'a'.repeat(10000)
|
|
589
589
|
const result = schema.safeParse(longString)
|
|
590
590
|
expect(result.success).toBe(true)
|
|
591
591
|
})
|
|
592
592
|
|
|
593
593
|
it('rejects very long strings exceeding maxLength', () => {
|
|
594
|
-
const schema =
|
|
594
|
+
const schema = string({ maxLength: 100 })
|
|
595
595
|
const longString = 'a'.repeat(101)
|
|
596
596
|
const result = schema.safeParse(longString)
|
|
597
597
|
expect(result.success).toBe(false)
|
|
598
598
|
})
|
|
599
599
|
|
|
600
600
|
it('handles zero as minLength', () => {
|
|
601
|
-
const schema =
|
|
601
|
+
const schema = string({ minLength: 0 })
|
|
602
602
|
const result = schema.safeParse('')
|
|
603
603
|
expect(result.success).toBe(true)
|
|
604
604
|
})
|
|
605
605
|
|
|
606
606
|
it('handles complex emoji sequences', () => {
|
|
607
|
-
const schema =
|
|
607
|
+
const schema = string({ maxGraphemes: 5 })
|
|
608
608
|
// Family emoji is a single grapheme cluster
|
|
609
609
|
const result = schema.safeParse('👨👩👧👦')
|
|
610
610
|
expect(result.success).toBe(true)
|
package/src/schema/string.ts
CHANGED
|
@@ -3,14 +3,13 @@ import {
|
|
|
3
3
|
InferStringFormat,
|
|
4
4
|
Schema,
|
|
5
5
|
StringFormat,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
assertStringFormat,
|
|
6
|
+
ValidationContext,
|
|
7
|
+
isStringFormat,
|
|
9
8
|
} from '../core.js'
|
|
9
|
+
import { memoizedOptions } from '../util/memoize.js'
|
|
10
10
|
import { TokenSchema } from './token.js'
|
|
11
11
|
|
|
12
12
|
export type StringSchemaOptions = {
|
|
13
|
-
default?: string
|
|
14
13
|
format?: StringFormat
|
|
15
14
|
minLength?: number
|
|
16
15
|
maxLength?: number
|
|
@@ -18,26 +17,18 @@ export type StringSchemaOptions = {
|
|
|
18
17
|
maxGraphemes?: number
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
export class StringSchema<
|
|
21
|
+
const TOptions extends StringSchemaOptions = StringSchemaOptions,
|
|
22
|
+
> extends Schema<
|
|
23
|
+
TOptions extends { format: infer F extends StringFormat }
|
|
24
24
|
? InferStringFormat<F>
|
|
25
25
|
: string
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const Options extends StringSchemaOptions = any,
|
|
29
|
-
> extends Schema<StringSchemaOutput<Options>> {
|
|
30
|
-
constructor(readonly options: Options) {
|
|
26
|
+
> {
|
|
27
|
+
constructor(readonly options?: TOptions) {
|
|
31
28
|
super()
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
validateInContext(
|
|
35
|
-
// @NOTE validation will be applied on the default value as well
|
|
36
|
-
input: unknown = this.options.default,
|
|
37
|
-
ctx: ValidatorContext,
|
|
38
|
-
): ValidationResult<StringSchemaOutput<Options>> {
|
|
39
|
-
const { options } = this
|
|
40
|
-
|
|
31
|
+
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
41
32
|
const str = coerceToString(input)
|
|
42
33
|
if (str == null) {
|
|
43
34
|
return ctx.issueInvalidType(input, 'string')
|
|
@@ -45,14 +36,14 @@ export class StringSchema<
|
|
|
45
36
|
|
|
46
37
|
let lazyUtf8Len: number
|
|
47
38
|
|
|
48
|
-
const
|
|
39
|
+
const minLength = this.options?.minLength
|
|
49
40
|
if (minLength != null) {
|
|
50
41
|
if ((lazyUtf8Len ??= utf8Len(str)) < minLength) {
|
|
51
42
|
return ctx.issueTooSmall(str, 'string', minLength, lazyUtf8Len)
|
|
52
43
|
}
|
|
53
44
|
}
|
|
54
45
|
|
|
55
|
-
const
|
|
46
|
+
const maxLength = this.options?.maxLength
|
|
56
47
|
if (maxLength != null) {
|
|
57
48
|
// Optimization: we can avoid computing the UTF-8 length if the maximum
|
|
58
49
|
// possible length, in bytes, of the input JS string is smaller than the
|
|
@@ -66,7 +57,7 @@ export class StringSchema<
|
|
|
66
57
|
|
|
67
58
|
let lazyGraphLen: number
|
|
68
59
|
|
|
69
|
-
const
|
|
60
|
+
const minGraphemes = this.options?.minGraphemes
|
|
70
61
|
if (minGraphemes != null) {
|
|
71
62
|
// Optimization: avoid counting graphemes if the length check already fails
|
|
72
63
|
if (str.length < minGraphemes) {
|
|
@@ -76,25 +67,19 @@ export class StringSchema<
|
|
|
76
67
|
}
|
|
77
68
|
}
|
|
78
69
|
|
|
79
|
-
const
|
|
70
|
+
const maxGraphemes = this.options?.maxGraphemes
|
|
80
71
|
if (maxGraphemes != null) {
|
|
81
72
|
if ((lazyGraphLen ??= graphemeLen(str)) > maxGraphemes) {
|
|
82
73
|
return ctx.issueTooBig(str, 'grapheme', maxGraphemes, lazyGraphLen)
|
|
83
74
|
}
|
|
84
75
|
}
|
|
85
76
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
// from @atproto/syntax)
|
|
90
|
-
assertStringFormat(str, options.format)
|
|
91
|
-
} catch (err) {
|
|
92
|
-
const message = err instanceof Error ? err.message : undefined
|
|
93
|
-
return ctx.issueInvalidFormat(str, options.format, message)
|
|
94
|
-
}
|
|
77
|
+
const format = this.options?.format
|
|
78
|
+
if (format != null && !isStringFormat(str, format)) {
|
|
79
|
+
return ctx.issueInvalidFormat(str, format)
|
|
95
80
|
}
|
|
96
81
|
|
|
97
|
-
return ctx.success(str
|
|
82
|
+
return ctx.success(str)
|
|
98
83
|
}
|
|
99
84
|
}
|
|
100
85
|
|
|
@@ -137,3 +122,9 @@ export function coerceToString(input: unknown): string | null {
|
|
|
137
122
|
return null
|
|
138
123
|
}
|
|
139
124
|
}
|
|
125
|
+
|
|
126
|
+
export const string = /*#__PURE__*/ memoizedOptions(function <
|
|
127
|
+
const O extends StringSchemaOptions = NonNullable<unknown>,
|
|
128
|
+
>(options?: StringSchemaOptions & O) {
|
|
129
|
+
return new StringSchema<O>(options)
|
|
130
|
+
})
|