@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
|
@@ -10,10 +10,12 @@ export type InferSubscriptionMessage<S extends Subscription> = Infer<
|
|
|
10
10
|
>
|
|
11
11
|
|
|
12
12
|
export class Subscription<
|
|
13
|
-
TNsid extends NsidString = NsidString,
|
|
14
|
-
TParameters extends ParamsSchema = ParamsSchema,
|
|
15
|
-
TMessage extends Schema = Schema,
|
|
16
|
-
TErrors extends undefined | readonly string[] =
|
|
13
|
+
const TNsid extends NsidString = NsidString,
|
|
14
|
+
const TParameters extends ParamsSchema = ParamsSchema,
|
|
15
|
+
const TMessage extends Schema = Schema,
|
|
16
|
+
const TErrors extends undefined | readonly string[] =
|
|
17
|
+
| undefined
|
|
18
|
+
| readonly string[],
|
|
17
19
|
> {
|
|
18
20
|
readonly type = 'subscription' as const
|
|
19
21
|
|
|
@@ -24,3 +26,13 @@ export class Subscription<
|
|
|
24
26
|
readonly errors: TErrors,
|
|
25
27
|
) {}
|
|
26
28
|
}
|
|
29
|
+
|
|
30
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
31
|
+
export function subscription<
|
|
32
|
+
const N extends NsidString,
|
|
33
|
+
const P extends ParamsSchema,
|
|
34
|
+
const M extends Schema,
|
|
35
|
+
const E extends undefined | readonly string[] = undefined,
|
|
36
|
+
>(nsid: N, parameters: P, message: M, errors: E = undefined as E) {
|
|
37
|
+
return new Subscription<N, P, M, E>(nsid, parameters, message, errors)
|
|
38
|
+
}
|
package/src/schema/token.test.ts
CHANGED
|
@@ -1,30 +1,29 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import {
|
|
2
|
+
import { token } from './token.js'
|
|
3
3
|
|
|
4
4
|
describe('TokenSchema', () => {
|
|
5
5
|
describe('basic validation', () => {
|
|
6
|
-
const schema =
|
|
6
|
+
const schema = token('my.to.ken')
|
|
7
7
|
|
|
8
8
|
it('validates exact token match', () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
9
|
+
expect(schema.safeParse('my.to.ken')).toMatchObject({
|
|
10
|
+
success: true,
|
|
11
|
+
value: 'my.to.ken',
|
|
12
|
+
})
|
|
14
13
|
})
|
|
15
14
|
|
|
16
15
|
it('rejects different strings', () => {
|
|
17
|
-
const result = schema.safeParse('
|
|
16
|
+
const result = schema.safeParse('other.to.ken')
|
|
18
17
|
expect(result.success).toBe(false)
|
|
19
18
|
})
|
|
20
19
|
|
|
21
20
|
it('rejects similar strings with different case', () => {
|
|
22
|
-
const result = schema.safeParse('
|
|
21
|
+
const result = schema.safeParse('My.To.Ken')
|
|
23
22
|
expect(result.success).toBe(false)
|
|
24
23
|
})
|
|
25
24
|
|
|
26
25
|
it('rejects partial matches', () => {
|
|
27
|
-
const result = schema.safeParse('my')
|
|
26
|
+
const result = schema.safeParse('my.to')
|
|
28
27
|
expect(result.success).toBe(false)
|
|
29
28
|
})
|
|
30
29
|
|
|
@@ -32,37 +31,56 @@ describe('TokenSchema', () => {
|
|
|
32
31
|
const result = schema.safeParse('')
|
|
33
32
|
expect(result.success).toBe(false)
|
|
34
33
|
})
|
|
34
|
+
|
|
35
|
+
it('rejects symbols', () => {
|
|
36
|
+
const result = schema.safeParse(Symbol.for(schema.toString()))
|
|
37
|
+
expect(result.success).toBe(false)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('rejects functions', () => {
|
|
41
|
+
const result = schema.safeParse(() => schema)
|
|
42
|
+
expect(result.success).toBe(false)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('rejects dates', () => {
|
|
46
|
+
const result = schema.safeParse(new Date())
|
|
47
|
+
expect(result.success).toBe(false)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('rejects regular expressions', () => {
|
|
51
|
+
const result = schema.safeParse(/mytoken/)
|
|
52
|
+
expect(result.success).toBe(false)
|
|
53
|
+
})
|
|
35
54
|
})
|
|
36
55
|
|
|
37
56
|
describe('TokenSchema instance validation', () => {
|
|
38
|
-
const schema =
|
|
57
|
+
const schema = token('my.to.ken')
|
|
39
58
|
|
|
40
59
|
it('accepts TokenSchema instance with same value', () => {
|
|
41
|
-
const otherInstance =
|
|
60
|
+
const otherInstance = token('my.to.ken')
|
|
42
61
|
const result = schema.safeParse(otherInstance)
|
|
43
62
|
expect(result.success).toBe(true)
|
|
44
63
|
if (result.success) {
|
|
45
|
-
expect(result.value).toBe('
|
|
64
|
+
expect(result.value).toBe('my.to.ken')
|
|
46
65
|
}
|
|
47
66
|
})
|
|
48
67
|
|
|
49
68
|
it('rejects TokenSchema instance with different value', () => {
|
|
50
|
-
const otherInstance =
|
|
69
|
+
const otherInstance = token('other.to.ken')
|
|
51
70
|
const result = schema.safeParse(otherInstance)
|
|
52
71
|
expect(result.success).toBe(false)
|
|
53
72
|
})
|
|
54
73
|
|
|
55
74
|
it('accepts itself as input', () => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
75
|
+
expect(schema.safeParse(schema)).toMatchObject({
|
|
76
|
+
success: true,
|
|
77
|
+
value: 'my.to.ken',
|
|
78
|
+
})
|
|
61
79
|
})
|
|
62
80
|
})
|
|
63
81
|
|
|
64
82
|
describe('type validation', () => {
|
|
65
|
-
const schema =
|
|
83
|
+
const schema = token('my.to.ken')
|
|
66
84
|
|
|
67
85
|
it('rejects null', () => {
|
|
68
86
|
const result = schema.safeParse(null)
|
|
@@ -100,330 +118,35 @@ describe('TokenSchema', () => {
|
|
|
100
118
|
})
|
|
101
119
|
})
|
|
102
120
|
|
|
103
|
-
describe('special token values', () => {
|
|
104
|
-
it('validates token with spaces', () => {
|
|
105
|
-
const schema = new TokenSchema('my token')
|
|
106
|
-
expect(schema.safeParse('my token').success).toBe(true)
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
it('validates token with special characters', () => {
|
|
110
|
-
const schema = new TokenSchema('token-with-dashes')
|
|
111
|
-
expect(schema.safeParse('token-with-dashes').success).toBe(true)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
it('validates token with underscores', () => {
|
|
115
|
-
const schema = new TokenSchema('token_with_underscores')
|
|
116
|
-
expect(schema.safeParse('token_with_underscores').success).toBe(true)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('validates token with dots', () => {
|
|
120
|
-
const schema = new TokenSchema('token.with.dots')
|
|
121
|
-
expect(schema.safeParse('token.with.dots').success).toBe(true)
|
|
122
|
-
})
|
|
123
|
-
|
|
124
|
-
it('validates token with numbers', () => {
|
|
125
|
-
const schema = new TokenSchema('token123')
|
|
126
|
-
expect(schema.safeParse('token123').success).toBe(true)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
it('validates token with unicode characters', () => {
|
|
130
|
-
const schema = new TokenSchema('token世界')
|
|
131
|
-
expect(schema.safeParse('token世界').success).toBe(true)
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
it('validates token with emoji', () => {
|
|
135
|
-
const schema = new TokenSchema('token🚀')
|
|
136
|
-
expect(schema.safeParse('token🚀').success).toBe(true)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
it('validates token with newlines', () => {
|
|
140
|
-
const schema = new TokenSchema('token\nwith\nnewlines')
|
|
141
|
-
expect(schema.safeParse('token\nwith\nnewlines').success).toBe(true)
|
|
142
|
-
expect(schema.safeParse('token with newlines').success).toBe(false)
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
it('validates token with tabs', () => {
|
|
146
|
-
const schema = new TokenSchema('token\twith\ttabs')
|
|
147
|
-
expect(schema.safeParse('token\twith\ttabs').success).toBe(true)
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
it('validates very long token', () => {
|
|
151
|
-
const longToken = 'token'.repeat(200)
|
|
152
|
-
const schema = new TokenSchema(longToken)
|
|
153
|
-
expect(schema.safeParse(longToken).success).toBe(true)
|
|
154
|
-
expect(schema.safeParse(longToken + 'x').success).toBe(false)
|
|
155
|
-
})
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
describe('empty token', () => {
|
|
159
|
-
const schema = new TokenSchema('')
|
|
160
|
-
|
|
161
|
-
it('validates empty string', () => {
|
|
162
|
-
const result = schema.safeParse('')
|
|
163
|
-
expect(result.success).toBe(true)
|
|
164
|
-
if (result.success) {
|
|
165
|
-
expect(result.value).toBe('')
|
|
166
|
-
}
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
it('rejects non-empty strings', () => {
|
|
170
|
-
const result = schema.safeParse('anything')
|
|
171
|
-
expect(result.success).toBe(false)
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
it('rejects null', () => {
|
|
175
|
-
const result = schema.safeParse(null)
|
|
176
|
-
expect(result.success).toBe(false)
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
it('rejects undefined', () => {
|
|
180
|
-
const result = schema.safeParse(undefined)
|
|
181
|
-
expect(result.success).toBe(false)
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
it('accepts TokenSchema instance with empty value', () => {
|
|
185
|
-
const otherInstance = new TokenSchema('')
|
|
186
|
-
const result = schema.safeParse(otherInstance)
|
|
187
|
-
expect(result.success).toBe(true)
|
|
188
|
-
if (result.success) {
|
|
189
|
-
expect(result.value).toBe('')
|
|
190
|
-
}
|
|
191
|
-
})
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
describe('whitespace handling', () => {
|
|
195
|
-
it('treats whitespace as significant', () => {
|
|
196
|
-
const schema = new TokenSchema(' token ')
|
|
197
|
-
expect(schema.safeParse(' token ').success).toBe(true)
|
|
198
|
-
expect(schema.safeParse('token').success).toBe(false)
|
|
199
|
-
expect(schema.safeParse(' token').success).toBe(false)
|
|
200
|
-
expect(schema.safeParse('token ').success).toBe(false)
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
it('distinguishes between different whitespace', () => {
|
|
204
|
-
const schema = new TokenSchema('token ')
|
|
205
|
-
expect(schema.safeParse('token ').success).toBe(true)
|
|
206
|
-
expect(schema.safeParse('token').success).toBe(false)
|
|
207
|
-
expect(schema.safeParse('token ').success).toBe(false)
|
|
208
|
-
})
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
describe('case sensitivity', () => {
|
|
212
|
-
const schema = new TokenSchema('Token')
|
|
213
|
-
|
|
214
|
-
it('is case sensitive', () => {
|
|
215
|
-
expect(schema.safeParse('Token').success).toBe(true)
|
|
216
|
-
expect(schema.safeParse('token').success).toBe(false)
|
|
217
|
-
expect(schema.safeParse('TOKEN').success).toBe(false)
|
|
218
|
-
expect(schema.safeParse('ToKeN').success).toBe(false)
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('handles case-sensitive TokenSchema instances', () => {
|
|
222
|
-
expect(schema.safeParse(new TokenSchema('Token')).success).toBe(true)
|
|
223
|
-
expect(schema.safeParse(new TokenSchema('token')).success).toBe(false)
|
|
224
|
-
})
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
describe('common token patterns', () => {
|
|
228
|
-
it('validates namespace-style tokens', () => {
|
|
229
|
-
const schema = new TokenSchema('com.example.record')
|
|
230
|
-
expect(schema.safeParse('com.example.record').success).toBe(true)
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
it('validates URL-like tokens', () => {
|
|
234
|
-
const schema = new TokenSchema('https://example.com/path')
|
|
235
|
-
expect(schema.safeParse('https://example.com/path').success).toBe(true)
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
it('validates version-like tokens', () => {
|
|
239
|
-
const schema = new TokenSchema('v1.0.0')
|
|
240
|
-
expect(schema.safeParse('v1.0.0').success).toBe(true)
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
it('validates hash-like tokens', () => {
|
|
244
|
-
const schema = new TokenSchema('#token')
|
|
245
|
-
expect(schema.safeParse('#token').success).toBe(true)
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
it('validates type discriminator tokens', () => {
|
|
249
|
-
const schema = new TokenSchema('#post')
|
|
250
|
-
expect(schema.safeParse('#post').success).toBe(true)
|
|
251
|
-
expect(schema.safeParse('#comment').success).toBe(false)
|
|
252
|
-
})
|
|
253
|
-
})
|
|
254
|
-
|
|
255
121
|
describe('serialization methods', () => {
|
|
256
|
-
const schema =
|
|
122
|
+
const schema = token('my.to.ken', 'foo')
|
|
257
123
|
|
|
258
124
|
it('toJSON returns the token value', () => {
|
|
259
|
-
expect(schema.toJSON()).toBe('
|
|
125
|
+
expect(schema.toJSON()).toBe('my.to.ken#foo')
|
|
260
126
|
})
|
|
261
127
|
|
|
262
128
|
it('toString returns the token value', () => {
|
|
263
|
-
expect(schema.toString()).toBe('
|
|
129
|
+
expect(schema.toString()).toBe('my.to.ken#foo')
|
|
264
130
|
})
|
|
265
131
|
|
|
266
132
|
it('toJSON and toString return the same value', () => {
|
|
267
133
|
expect(schema.toJSON()).toBe(schema.toString())
|
|
268
134
|
})
|
|
269
135
|
|
|
270
|
-
it('handles empty token serialization', () => {
|
|
271
|
-
const emptySchema = new TokenSchema('')
|
|
272
|
-
expect(emptySchema.toJSON()).toBe('')
|
|
273
|
-
expect(emptySchema.toString()).toBe('')
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
it('handles special characters in serialization', () => {
|
|
277
|
-
const specialSchema = new TokenSchema('token\nwith\tspecial')
|
|
278
|
-
expect(specialSchema.toJSON()).toBe('token\nwith\tspecial')
|
|
279
|
-
expect(specialSchema.toString()).toBe('token\nwith\tspecial')
|
|
280
|
-
})
|
|
281
|
-
|
|
282
136
|
it('serializes to primitive string in JSON', () => {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
137
|
+
expect(JSON.stringify({ token: schema })).toBe(
|
|
138
|
+
'{"token":"my.to.ken#foo"}',
|
|
139
|
+
)
|
|
286
140
|
})
|
|
287
141
|
})
|
|
288
142
|
|
|
289
143
|
describe('value property', () => {
|
|
290
|
-
const schema =
|
|
144
|
+
const schema = token('my.to.ken')
|
|
291
145
|
|
|
292
146
|
it('exposes the token value through serialization', () => {
|
|
293
147
|
// value is protected, so we verify it through toString/toJSON
|
|
294
|
-
expect(schema.toString()).toBe('
|
|
295
|
-
expect(schema.toJSON()).toBe('
|
|
296
|
-
})
|
|
297
|
-
})
|
|
298
|
-
|
|
299
|
-
describe('multiple token instances', () => {
|
|
300
|
-
const schema1 = new TokenSchema('token1')
|
|
301
|
-
const schema2 = new TokenSchema('token2')
|
|
302
|
-
const schema3 = new TokenSchema('token1')
|
|
303
|
-
|
|
304
|
-
it('different instances with same value validate each other', () => {
|
|
305
|
-
expect(schema1.safeParse(schema3).success).toBe(true)
|
|
306
|
-
expect(schema3.safeParse(schema1).success).toBe(true)
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
it('different instances with different values reject each other', () => {
|
|
310
|
-
expect(schema1.safeParse(schema2).success).toBe(false)
|
|
311
|
-
expect(schema2.safeParse(schema1).success).toBe(false)
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
it('validates string values correctly', () => {
|
|
315
|
-
expect(schema1.safeParse('token1').success).toBe(true)
|
|
316
|
-
expect(schema1.safeParse('token2').success).toBe(false)
|
|
317
|
-
expect(schema2.safeParse('token2').success).toBe(true)
|
|
318
|
-
expect(schema2.safeParse('token1').success).toBe(false)
|
|
319
|
-
})
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
describe('type safety', () => {
|
|
323
|
-
it('preserves token type in TypeScript', () => {
|
|
324
|
-
const schema = new TokenSchema('specific' as const)
|
|
325
|
-
const result = schema.safeParse('specific')
|
|
326
|
-
expect(result.success).toBe(true)
|
|
327
|
-
if (result.success) {
|
|
328
|
-
// TypeScript should infer result.value as the literal type 'specific'
|
|
329
|
-
expect(result.value).toBe('specific')
|
|
330
|
-
}
|
|
331
|
-
})
|
|
332
|
-
|
|
333
|
-
it('handles generic token types', () => {
|
|
334
|
-
const schema: TokenSchema<'a' | 'b'> = new TokenSchema('a')
|
|
335
|
-
expect(schema.safeParse('a').success).toBe(true)
|
|
336
|
-
})
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
describe('edge cases', () => {
|
|
340
|
-
it('handles tokens that look like numbers', () => {
|
|
341
|
-
const schema = new TokenSchema('123')
|
|
342
|
-
expect(schema.safeParse('123').success).toBe(true)
|
|
343
|
-
expect(schema.safeParse(123).success).toBe(false)
|
|
344
|
-
})
|
|
345
|
-
|
|
346
|
-
it('handles tokens that look like booleans', () => {
|
|
347
|
-
const schema = new TokenSchema('true')
|
|
348
|
-
expect(schema.safeParse('true').success).toBe(true)
|
|
349
|
-
expect(schema.safeParse(true).success).toBe(false)
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
it('handles tokens that look like null', () => {
|
|
353
|
-
const schema = new TokenSchema('null')
|
|
354
|
-
expect(schema.safeParse('null').success).toBe(true)
|
|
355
|
-
expect(schema.safeParse(null).success).toBe(false)
|
|
356
|
-
})
|
|
357
|
-
|
|
358
|
-
it('handles tokens that look like undefined', () => {
|
|
359
|
-
const schema = new TokenSchema('undefined')
|
|
360
|
-
expect(schema.safeParse('undefined').success).toBe(true)
|
|
361
|
-
expect(schema.safeParse(undefined).success).toBe(false)
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
it('handles tokens with only whitespace', () => {
|
|
365
|
-
const schema = new TokenSchema(' ')
|
|
366
|
-
expect(schema.safeParse(' ').success).toBe(true)
|
|
367
|
-
expect(schema.safeParse(' ').success).toBe(false)
|
|
368
|
-
expect(schema.safeParse(' ').success).toBe(false)
|
|
369
|
-
})
|
|
370
|
-
|
|
371
|
-
it('handles single character tokens', () => {
|
|
372
|
-
const schema = new TokenSchema('x')
|
|
373
|
-
expect(schema.safeParse('x').success).toBe(true)
|
|
374
|
-
expect(schema.safeParse('X').success).toBe(false)
|
|
375
|
-
expect(schema.safeParse('').success).toBe(false)
|
|
376
|
-
})
|
|
377
|
-
|
|
378
|
-
it('rejects symbols', () => {
|
|
379
|
-
const schema = new TokenSchema('mytoken')
|
|
380
|
-
const result = schema.safeParse(Symbol('mytoken'))
|
|
381
|
-
expect(result.success).toBe(false)
|
|
382
|
-
})
|
|
383
|
-
|
|
384
|
-
it('rejects functions', () => {
|
|
385
|
-
const schema = new TokenSchema('mytoken')
|
|
386
|
-
const result = schema.safeParse(() => 'mytoken')
|
|
387
|
-
expect(result.success).toBe(false)
|
|
388
|
-
})
|
|
389
|
-
|
|
390
|
-
it('rejects dates', () => {
|
|
391
|
-
const schema = new TokenSchema('mytoken')
|
|
392
|
-
const result = schema.safeParse(new Date())
|
|
393
|
-
expect(result.success).toBe(false)
|
|
394
|
-
})
|
|
395
|
-
|
|
396
|
-
it('rejects regular expressions', () => {
|
|
397
|
-
const schema = new TokenSchema('mytoken')
|
|
398
|
-
const result = schema.safeParse(/mytoken/)
|
|
399
|
-
expect(result.success).toBe(false)
|
|
400
|
-
})
|
|
401
|
-
})
|
|
402
|
-
|
|
403
|
-
describe('comparison with similar schemas', () => {
|
|
404
|
-
it('behaves like a string literal validator', () => {
|
|
405
|
-
const schema = new TokenSchema('literal')
|
|
406
|
-
|
|
407
|
-
// Should only accept the exact string
|
|
408
|
-
expect(schema.safeParse('literal').success).toBe(true)
|
|
409
|
-
expect(schema.safeParse('other').success).toBe(false)
|
|
410
|
-
expect(schema.safeParse('').success).toBe(false)
|
|
411
|
-
})
|
|
412
|
-
|
|
413
|
-
it('differs from enum by accepting only one value', () => {
|
|
414
|
-
const schema = new TokenSchema('option1')
|
|
415
|
-
|
|
416
|
-
// Only accepts the single token value
|
|
417
|
-
expect(schema.safeParse('option1').success).toBe(true)
|
|
418
|
-
expect(schema.safeParse('option2').success).toBe(false)
|
|
419
|
-
})
|
|
420
|
-
|
|
421
|
-
it('differs from string schema by accepting only specific value', () => {
|
|
422
|
-
const schema = new TokenSchema('specific')
|
|
423
|
-
|
|
424
|
-
// Only accepts the exact token
|
|
425
|
-
expect(schema.safeParse('specific').success).toBe(true)
|
|
426
|
-
expect(schema.safeParse('any other string').success).toBe(false)
|
|
148
|
+
expect(schema.toString()).toBe('my.to.ken')
|
|
149
|
+
expect(schema.toJSON()).toBe('my.to.ken')
|
|
427
150
|
})
|
|
428
151
|
})
|
|
429
152
|
})
|
package/src/schema/token.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { $type, NsidString, Schema, ValidationContext } from '../core.js'
|
|
2
2
|
|
|
3
|
-
export class TokenSchema<
|
|
4
|
-
|
|
3
|
+
export class TokenSchema<
|
|
4
|
+
const TValue extends string = string,
|
|
5
|
+
> extends Schema<TValue> {
|
|
6
|
+
constructor(readonly value: TValue) {
|
|
5
7
|
super()
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
validateInContext(
|
|
9
|
-
input: unknown,
|
|
10
|
-
ctx: ValidatorContext,
|
|
11
|
-
): ValidationResult<V> {
|
|
10
|
+
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
12
11
|
if (input === this.value) {
|
|
13
12
|
return ctx.success(this.value)
|
|
14
13
|
}
|
|
@@ -37,3 +36,11 @@ export class TokenSchema<V extends string = any> extends Schema<V> {
|
|
|
37
36
|
return this.value
|
|
38
37
|
}
|
|
39
38
|
}
|
|
39
|
+
|
|
40
|
+
/*@__NO_SIDE_EFFECTS__*/
|
|
41
|
+
export function token<
|
|
42
|
+
const N extends NsidString,
|
|
43
|
+
const H extends string = 'main',
|
|
44
|
+
>(nsid: N, hash: H = 'main' as H) {
|
|
45
|
+
return new TokenSchema($type(nsid, hash))
|
|
46
|
+
}
|