@atproto/lex-schema 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/core/$type.d.ts +2 -2
- package/dist/core/$type.d.ts.map +1 -1
- package/dist/core/$type.js.map +1 -1
- package/dist/core/record-key.d.ts +1 -1
- package/dist/core/record-key.d.ts.map +1 -1
- package/dist/core/record-key.js.map +1 -1
- package/dist/core/schema.d.ts +3 -2
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +1 -1
- package/dist/core/schema.js.map +1 -1
- package/dist/core/standard-schema.d.ts +2 -2
- package/dist/core/standard-schema.d.ts.map +1 -1
- package/dist/core/standard-schema.js.map +1 -1
- package/dist/core/string-format.d.ts +2 -2
- package/dist/core/string-format.d.ts.map +1 -1
- package/dist/core/string-format.js.map +1 -1
- package/dist/core/validation-error.d.ts +1 -1
- package/dist/core/validation-error.d.ts.map +1 -1
- package/dist/core/validation-error.js +1 -1
- package/dist/core/validation-error.js.map +1 -1
- package/dist/core/validator.d.ts +1 -1
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +1 -1
- package/dist/core/validator.js.map +1 -1
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +2 -2
- package/dist/helpers.js.map +1 -1
- package/dist/schema/array.d.ts +1 -1
- package/dist/schema/array.d.ts.map +1 -1
- package/dist/schema/array.js +1 -1
- package/dist/schema/array.js.map +1 -1
- package/dist/schema/blob.d.ts +1 -1
- package/dist/schema/blob.d.ts.map +1 -1
- package/dist/schema/blob.js +2 -2
- package/dist/schema/blob.js.map +1 -1
- package/dist/schema/boolean.js +1 -1
- package/dist/schema/boolean.js.map +1 -1
- package/dist/schema/bytes.js +1 -1
- package/dist/schema/bytes.js.map +1 -1
- package/dist/schema/cid.d.ts +1 -1
- package/dist/schema/cid.d.ts.map +1 -1
- package/dist/schema/cid.js +3 -3
- package/dist/schema/cid.js.map +1 -1
- package/dist/schema/custom.js +1 -1
- package/dist/schema/custom.js.map +1 -1
- package/dist/schema/dict.d.ts +1 -1
- package/dist/schema/dict.d.ts.map +1 -1
- package/dist/schema/dict.js +1 -1
- package/dist/schema/dict.js.map +1 -1
- package/dist/schema/discriminated-union.d.ts +1 -1
- package/dist/schema/discriminated-union.d.ts.map +1 -1
- package/dist/schema/discriminated-union.js +2 -1
- package/dist/schema/discriminated-union.js.map +1 -1
- package/dist/schema/enum.js +1 -1
- package/dist/schema/enum.js.map +1 -1
- package/dist/schema/integer.js +1 -1
- package/dist/schema/integer.js.map +1 -1
- package/dist/schema/intersection.d.ts +1 -1
- package/dist/schema/intersection.d.ts.map +1 -1
- package/dist/schema/intersection.js +3 -1
- package/dist/schema/intersection.js.map +1 -1
- package/dist/schema/lex-map.d.ts +1 -1
- package/dist/schema/lex-map.d.ts.map +1 -1
- package/dist/schema/lex-map.js +1 -1
- package/dist/schema/lex-map.js.map +1 -1
- package/dist/schema/lex-value.d.ts +1 -1
- package/dist/schema/lex-value.d.ts.map +1 -1
- package/dist/schema/lex-value.js +1 -1
- package/dist/schema/lex-value.js.map +1 -1
- package/dist/schema/literal.js +1 -1
- package/dist/schema/literal.js.map +1 -1
- package/dist/schema/never.js +1 -1
- package/dist/schema/never.js.map +1 -1
- package/dist/schema/null.js +1 -1
- package/dist/schema/null.js.map +1 -1
- package/dist/schema/nullable.d.ts +1 -1
- package/dist/schema/nullable.d.ts.map +1 -1
- package/dist/schema/nullable.js +1 -1
- package/dist/schema/nullable.js.map +1 -1
- package/dist/schema/object.d.ts +2 -1
- package/dist/schema/object.d.ts.map +1 -1
- package/dist/schema/object.js +1 -1
- package/dist/schema/object.js.map +1 -1
- package/dist/schema/optional.d.ts +2 -1
- package/dist/schema/optional.d.ts.map +1 -1
- package/dist/schema/optional.js +2 -1
- package/dist/schema/optional.js.map +1 -1
- package/dist/schema/params.d.ts +1 -1
- package/dist/schema/params.d.ts.map +1 -1
- package/dist/schema/params.js +1 -1
- package/dist/schema/params.js.map +1 -1
- package/dist/schema/payload.d.ts +3 -2
- package/dist/schema/payload.d.ts.map +1 -1
- package/dist/schema/payload.js +2 -1
- package/dist/schema/payload.js.map +1 -1
- package/dist/schema/permission-set.d.ts +1 -1
- package/dist/schema/permission-set.d.ts.map +1 -1
- package/dist/schema/permission-set.js +1 -0
- package/dist/schema/permission-set.js.map +1 -1
- package/dist/schema/permission.d.ts +1 -1
- package/dist/schema/permission.d.ts.map +1 -1
- package/dist/schema/permission.js.map +1 -1
- package/dist/schema/procedure.d.ts +1 -1
- package/dist/schema/procedure.d.ts.map +1 -1
- package/dist/schema/procedure.js +2 -0
- package/dist/schema/procedure.js.map +1 -1
- package/dist/schema/query.d.ts +1 -1
- package/dist/schema/query.d.ts.map +1 -1
- package/dist/schema/query.js +2 -0
- package/dist/schema/query.js.map +1 -1
- package/dist/schema/record.d.ts +2 -2
- package/dist/schema/record.d.ts.map +1 -1
- package/dist/schema/record.js +1 -1
- package/dist/schema/record.js.map +1 -1
- package/dist/schema/ref.d.ts +1 -1
- package/dist/schema/ref.d.ts.map +1 -1
- package/dist/schema/ref.js +1 -1
- package/dist/schema/ref.js.map +1 -1
- package/dist/schema/refine.d.ts +2 -2
- package/dist/schema/refine.d.ts.map +1 -1
- package/dist/schema/refine.js +1 -1
- package/dist/schema/refine.js.map +1 -1
- package/dist/schema/regexp.js +1 -1
- package/dist/schema/regexp.js.map +1 -1
- package/dist/schema/string.d.ts +2 -2
- package/dist/schema/string.d.ts.map +1 -1
- package/dist/schema/string.js +1 -1
- package/dist/schema/string.js.map +1 -1
- package/dist/schema/subscription.d.ts +3 -2
- package/dist/schema/subscription.d.ts.map +1 -1
- package/dist/schema/subscription.js +2 -0
- package/dist/schema/subscription.js.map +1 -1
- package/dist/schema/token.d.ts +1 -1
- package/dist/schema/token.d.ts.map +1 -1
- package/dist/schema/token.js +1 -1
- package/dist/schema/token.js.map +1 -1
- package/dist/schema/typed-object.d.ts +2 -2
- package/dist/schema/typed-object.d.ts.map +1 -1
- package/dist/schema/typed-object.js +1 -1
- package/dist/schema/typed-object.js.map +1 -1
- package/dist/schema/typed-ref.d.ts +1 -1
- package/dist/schema/typed-ref.d.ts.map +1 -1
- package/dist/schema/typed-ref.js +1 -1
- package/dist/schema/typed-ref.js.map +1 -1
- package/dist/schema/typed-union.d.ts +1 -1
- package/dist/schema/typed-union.d.ts.map +1 -1
- package/dist/schema/typed-union.js +3 -1
- package/dist/schema/typed-union.js.map +1 -1
- package/dist/schema/union.d.ts +1 -1
- package/dist/schema/union.d.ts.map +1 -1
- package/dist/schema/union.js +1 -1
- package/dist/schema/union.js.map +1 -1
- package/dist/schema/unknown.js +1 -1
- package/dist/schema/unknown.js.map +1 -1
- package/dist/schema/with-default.d.ts +1 -1
- package/dist/schema/with-default.d.ts.map +1 -1
- package/dist/schema/with-default.js +1 -1
- package/dist/schema/with-default.js.map +1 -1
- package/package.json +6 -10
- package/src/core/$type.test.ts +0 -24
- package/src/core/$type.ts +0 -199
- package/src/core/record-key.ts +0 -85
- package/src/core/result.ts +0 -15
- package/src/core/schema.ts +0 -412
- package/src/core/standard-schema.test.ts +0 -124
- package/src/core/standard-schema.ts +0 -31
- package/src/core/string-format.ts +0 -411
- package/src/core/types.ts +0 -120
- package/src/core/validation-error.ts +0 -134
- package/src/core/validation-issue.ts +0 -340
- package/src/core/validator.ts +0 -636
- package/src/core.ts +0 -9
- package/src/external.ts +0 -3
- package/src/helpers.test.ts +0 -694
- package/src/helpers.ts +0 -222
- package/src/index.ts +0 -3
- package/src/schema/array.test.ts +0 -251
- package/src/schema/array.ts +0 -126
- package/src/schema/blob.test.ts +0 -733
- package/src/schema/blob.ts +0 -150
- package/src/schema/boolean.test.ts +0 -118
- package/src/schema/boolean.ts +0 -46
- package/src/schema/bytes.test.ts +0 -227
- package/src/schema/bytes.ts +0 -81
- package/src/schema/cid.test.ts +0 -125
- package/src/schema/cid.ts +0 -69
- package/src/schema/custom.test.ts +0 -414
- package/src/schema/custom.ts +0 -106
- package/src/schema/dict.test.ts +0 -181
- package/src/schema/dict.ts +0 -122
- package/src/schema/discriminated-union.test.ts +0 -676
- package/src/schema/discriminated-union.ts +0 -196
- package/src/schema/enum.test.ts +0 -398
- package/src/schema/enum.ts +0 -77
- package/src/schema/integer.test.ts +0 -314
- package/src/schema/integer.ts +0 -86
- package/src/schema/intersection.test.ts +0 -33
- package/src/schema/intersection.ts +0 -113
- package/src/schema/lex-map.test.ts +0 -593
- package/src/schema/lex-map.ts +0 -63
- package/src/schema/lex-value.test.ts +0 -81
- package/src/schema/lex-value.ts +0 -86
- package/src/schema/literal.test.ts +0 -533
- package/src/schema/literal.ts +0 -70
- package/src/schema/never.test.ts +0 -175
- package/src/schema/never.ts +0 -56
- package/src/schema/null.test.ts +0 -80
- package/src/schema/null.ts +0 -49
- package/src/schema/nullable.test.ts +0 -470
- package/src/schema/nullable.ts +0 -74
- package/src/schema/object.test.ts +0 -69
- package/src/schema/object.ts +0 -136
- package/src/schema/optional.test.ts +0 -479
- package/src/schema/optional.ts +0 -92
- package/src/schema/params.test.ts +0 -1118
- package/src/schema/params.ts +0 -371
- package/src/schema/payload.test.ts +0 -340
- package/src/schema/payload.ts +0 -204
- package/src/schema/permission-set.test.ts +0 -613
- package/src/schema/permission-set.ts +0 -86
- package/src/schema/permission.test.ts +0 -537
- package/src/schema/permission.ts +0 -63
- package/src/schema/procedure.test.ts +0 -324
- package/src/schema/procedure.ts +0 -98
- package/src/schema/query.test.ts +0 -348
- package/src/schema/query.ts +0 -86
- package/src/schema/record.test.ts +0 -812
- package/src/schema/record.ts +0 -217
- package/src/schema/ref.test.ts +0 -349
- package/src/schema/ref.ts +0 -103
- package/src/schema/refine.test.ts +0 -579
- package/src/schema/refine.ts +0 -153
- package/src/schema/regexp.test.ts +0 -577
- package/src/schema/regexp.ts +0 -82
- package/src/schema/string.test.ts +0 -773
- package/src/schema/string.ts +0 -229
- package/src/schema/subscription.test.ts +0 -499
- package/src/schema/subscription.ts +0 -108
- package/src/schema/token.test.ts +0 -152
- package/src/schema/token.ts +0 -103
- package/src/schema/typed-object.test.ts +0 -745
- package/src/schema/typed-object.ts +0 -181
- package/src/schema/typed-ref.test.ts +0 -796
- package/src/schema/typed-ref.ts +0 -126
- package/src/schema/typed-union.test.ts +0 -355
- package/src/schema/typed-union.ts +0 -130
- package/src/schema/union.test.ts +0 -191
- package/src/schema/union.ts +0 -89
- package/src/schema/unknown.test.ts +0 -313
- package/src/schema/unknown.ts +0 -47
- package/src/schema/with-default.ts +0 -81
- package/src/schema.ts +0 -43
- package/src/util/array-agg.test.ts +0 -42
- package/src/util/array-agg.ts +0 -44
- package/src/util/assertion-util.ts +0 -1
- package/src/util/if-any.ts +0 -3
- package/src/util/lazy-property.ts +0 -14
- package/src/util/memoize.ts +0 -37
- package/tsconfig.build.json +0 -12
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest'
|
|
2
|
-
import { parseCid } from '@atproto/lex-data'
|
|
3
|
-
import { lexValue } from './lex-value.js'
|
|
4
|
-
|
|
5
|
-
const schema = lexValue()
|
|
6
|
-
|
|
7
|
-
describe(lexValue, () => {
|
|
8
|
-
describe('valid values', () => {
|
|
9
|
-
for (const { note, value } of [
|
|
10
|
-
{ note: 'string', value: 'hello' },
|
|
11
|
-
{ note: 'boolean true', value: true },
|
|
12
|
-
{ note: 'boolean false', value: false },
|
|
13
|
-
{ note: 'null', value: null },
|
|
14
|
-
{ note: 'integer', value: 42 },
|
|
15
|
-
{ note: 'negative integer', value: -1 },
|
|
16
|
-
{ note: 'zero', value: 0 },
|
|
17
|
-
{ note: 'Uint8Array', value: new Uint8Array([1, 2, 3]) },
|
|
18
|
-
{
|
|
19
|
-
note: 'Cid',
|
|
20
|
-
value: parseCid(
|
|
21
|
-
'bafyreidfayvfuwqa7qlnopdjiqrxzs6blmoeu4rujcjtnci5beludirz2a',
|
|
22
|
-
),
|
|
23
|
-
},
|
|
24
|
-
{ note: 'empty plain object', value: {} },
|
|
25
|
-
{
|
|
26
|
-
note: 'object with Lex values',
|
|
27
|
-
value: {
|
|
28
|
-
a: 123,
|
|
29
|
-
b: 'blah',
|
|
30
|
-
c: true,
|
|
31
|
-
d: null,
|
|
32
|
-
e: new Uint8Array([1, 2, 3]),
|
|
33
|
-
f: { nested: 'value' },
|
|
34
|
-
g: [1, 2, 3],
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
{ note: 'empty array', value: [] },
|
|
38
|
-
{
|
|
39
|
-
note: 'array with Lex values',
|
|
40
|
-
value: [
|
|
41
|
-
123,
|
|
42
|
-
'blah',
|
|
43
|
-
true,
|
|
44
|
-
null,
|
|
45
|
-
new Uint8Array([1, 2, 3]),
|
|
46
|
-
{ nested: 'value' },
|
|
47
|
-
[1, 2, 3],
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
]) {
|
|
51
|
-
test(note, () => {
|
|
52
|
-
const result = schema.safeParse(value)
|
|
53
|
-
expect(result.success).toBe(true)
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
describe('invalid values', () => {
|
|
59
|
-
for (const { note, value } of [
|
|
60
|
-
{ note: 'float', value: 42.5 },
|
|
61
|
-
{ note: 'undefined', value: undefined },
|
|
62
|
-
{ note: 'function', value: () => {} },
|
|
63
|
-
{ note: 'Date object', value: new Date() },
|
|
64
|
-
{ note: 'Map object', value: new Map() },
|
|
65
|
-
{ note: 'Set object', value: new Set() },
|
|
66
|
-
{ note: 'class instance', value: new (class A {})() },
|
|
67
|
-
{ note: 'object with function value', value: { a: 123, b: () => {} } },
|
|
68
|
-
{
|
|
69
|
-
note: 'object with undefined value',
|
|
70
|
-
value: { a: 123, b: undefined },
|
|
71
|
-
},
|
|
72
|
-
{ note: 'array with function', value: [123, 'blah', () => {}] },
|
|
73
|
-
{ note: 'array with undefined', value: [123, 'blah', undefined] },
|
|
74
|
-
]) {
|
|
75
|
-
test(note, () => {
|
|
76
|
-
const result = schema.safeParse(value)
|
|
77
|
-
expect(result.success).toBe(false)
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
})
|
|
81
|
-
})
|
package/src/schema/lex-value.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { LexValue, isLexScalar, isPlainObject } from '@atproto/lex-data'
|
|
2
|
-
import { Schema, ValidationContext } from '../core.js'
|
|
3
|
-
import { memoizedOptions } from '../util/memoize.js'
|
|
4
|
-
|
|
5
|
-
export type { LexValue }
|
|
6
|
-
|
|
7
|
-
const EXPECTED_TYPES = Object.freeze([
|
|
8
|
-
// Scalar types
|
|
9
|
-
'null',
|
|
10
|
-
'boolean',
|
|
11
|
-
'integer',
|
|
12
|
-
'string',
|
|
13
|
-
'cid',
|
|
14
|
-
'bytes',
|
|
15
|
-
// Recursive types
|
|
16
|
-
'array',
|
|
17
|
-
'object',
|
|
18
|
-
] as const)
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* AT Protocol lexicon values are any valid AT Protocol data types: string,
|
|
22
|
-
* integer, boolean, null, bytes, cid, array, or object.
|
|
23
|
-
*/
|
|
24
|
-
export class LexValueSchema extends Schema<LexValue> {
|
|
25
|
-
readonly type = 'lexValue' as const
|
|
26
|
-
|
|
27
|
-
validateInContext(input: unknown, ctx: ValidationContext) {
|
|
28
|
-
// @NOTE We are *not* using "isLexValue" here to allow for more specific
|
|
29
|
-
// error messages about the path and type of the invalid value. The
|
|
30
|
-
// "isLexValue" check is effectively performed by the recursive validation
|
|
31
|
-
// of child properties below.
|
|
32
|
-
|
|
33
|
-
// @NOTE There are two limitations to the fact that we are not using
|
|
34
|
-
// "isLexValue" here:
|
|
35
|
-
// 1. We cannot detect circular references in objects or arrays, which would
|
|
36
|
-
// cause infinite recursion. However, circular references are not valid
|
|
37
|
-
// AT Protocol data types, so this is not a concern for valid input. This
|
|
38
|
-
// could easily be addressed in the "validateChild" method by keeping
|
|
39
|
-
// track of "parent" objects.
|
|
40
|
-
// 2. We are limited in the recursion depth we can validate due to potential
|
|
41
|
-
// recursion depth limits in JavaScript. However, this is also not a
|
|
42
|
-
// concern for most valid input, as extremely deep nesting is unlikely in
|
|
43
|
-
// typical use cases.
|
|
44
|
-
if (isPlainObject(input)) {
|
|
45
|
-
for (const key of Object.keys(input)) {
|
|
46
|
-
const r = ctx.validateChild(input, key, this) // recursively validate all properties
|
|
47
|
-
if (!r.success) return r
|
|
48
|
-
}
|
|
49
|
-
} else if (Array.isArray(input)) {
|
|
50
|
-
for (let i = 0; i < input.length; i++) {
|
|
51
|
-
const r = ctx.validateChild(input, i, this) // recursively validate all array items
|
|
52
|
-
if (!r.success) return r
|
|
53
|
-
}
|
|
54
|
-
} else if (!isLexScalar(input)) {
|
|
55
|
-
return ctx.issueInvalidType(input, EXPECTED_TYPES)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return ctx.success(input)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Creates a schema that accepts any valid AT Protocol data type: string,
|
|
64
|
-
* integer, boolean, null, bytes, cid, array, or plain object. Arrays and
|
|
65
|
-
* objects are recursively validated to ensure all nested values are also valid
|
|
66
|
-
* AT Protocol data types.
|
|
67
|
-
*
|
|
68
|
-
* @see {@link LexValue} from `@atproto/lex-data` for the type definition of valid AT Protocol data types
|
|
69
|
-
* @returns A new {@link LexValueSchema} instance
|
|
70
|
-
*
|
|
71
|
-
* @example
|
|
72
|
-
* ```ts
|
|
73
|
-
* const schema = l.lexValue()
|
|
74
|
-
*
|
|
75
|
-
* schema.validate('hello') // success
|
|
76
|
-
* schema.validate(42) // success
|
|
77
|
-
* schema.validate(null) // success
|
|
78
|
-
* schema.validate([1, 'two', null]) // success
|
|
79
|
-
* schema.validate({ any: 'props' }) // success
|
|
80
|
-
* schema.validate(new Date()) // fails - Date is not a valid LexValue
|
|
81
|
-
* schema.validate({ foo: 1.2 }) // fails - 1.2 is not a valid LexValue (not an integer)
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
export const lexValue = /*#__PURE__*/ memoizedOptions(function () {
|
|
85
|
-
return new LexValueSchema()
|
|
86
|
-
})
|
|
@@ -1,533 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { literal } from './literal.js'
|
|
3
|
-
import { withDefault } from './with-default.js'
|
|
4
|
-
|
|
5
|
-
describe('LiteralSchema', () => {
|
|
6
|
-
describe('string literals', () => {
|
|
7
|
-
const schema = literal('hello')
|
|
8
|
-
|
|
9
|
-
it('validates exact string match', () => {
|
|
10
|
-
const result = schema.safeParse('hello')
|
|
11
|
-
expect(result.success).toBe(true)
|
|
12
|
-
if (result.success) {
|
|
13
|
-
expect(result.value).toBe('hello')
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('rejects different strings', () => {
|
|
18
|
-
const result = schema.safeParse('world')
|
|
19
|
-
expect(result.success).toBe(false)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('rejects similar strings with different case', () => {
|
|
23
|
-
const result = schema.safeParse('Hello')
|
|
24
|
-
expect(result.success).toBe(false)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('rejects empty string when literal is non-empty', () => {
|
|
28
|
-
const result = schema.safeParse('')
|
|
29
|
-
expect(result.success).toBe(false)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('rejects numbers', () => {
|
|
33
|
-
const result = schema.safeParse(42)
|
|
34
|
-
expect(result.success).toBe(false)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('rejects booleans', () => {
|
|
38
|
-
const result = schema.safeParse(true)
|
|
39
|
-
expect(result.success).toBe(false)
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('rejects null', () => {
|
|
43
|
-
const result = schema.safeParse(null)
|
|
44
|
-
expect(result.success).toBe(false)
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('rejects undefined', () => {
|
|
48
|
-
const result = schema.safeParse(undefined)
|
|
49
|
-
expect(result.success).toBe(false)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('rejects objects', () => {
|
|
53
|
-
const result = schema.safeParse({})
|
|
54
|
-
expect(result.success).toBe(false)
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('rejects arrays', () => {
|
|
58
|
-
const result = schema.safeParse(['hello'])
|
|
59
|
-
expect(result.success).toBe(false)
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
describe('empty string literal', () => {
|
|
64
|
-
const schema = literal('')
|
|
65
|
-
|
|
66
|
-
it('validates empty string', () => {
|
|
67
|
-
const result = schema.safeParse('')
|
|
68
|
-
expect(result.success).toBe(true)
|
|
69
|
-
if (result.success) {
|
|
70
|
-
expect(result.value).toBe('')
|
|
71
|
-
}
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
it('rejects non-empty strings', () => {
|
|
75
|
-
const result = schema.safeParse('hello')
|
|
76
|
-
expect(result.success).toBe(false)
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('rejects null', () => {
|
|
80
|
-
const result = schema.safeParse(null)
|
|
81
|
-
expect(result.success).toBe(false)
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('rejects undefined', () => {
|
|
85
|
-
const result = schema.safeParse(undefined)
|
|
86
|
-
expect(result.success).toBe(false)
|
|
87
|
-
})
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
describe('number literals', () => {
|
|
91
|
-
const schema = literal(42)
|
|
92
|
-
|
|
93
|
-
it('validates exact number match', () => {
|
|
94
|
-
const result = schema.safeParse(42)
|
|
95
|
-
expect(result.success).toBe(true)
|
|
96
|
-
if (result.success) {
|
|
97
|
-
expect(result.value).toBe(42)
|
|
98
|
-
}
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it('rejects different numbers', () => {
|
|
102
|
-
const result = schema.safeParse(43)
|
|
103
|
-
expect(result.success).toBe(false)
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
it('rejects string representation of number', () => {
|
|
107
|
-
const result = schema.safeParse('42')
|
|
108
|
-
expect(result.success).toBe(false)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
it('rejects booleans', () => {
|
|
112
|
-
const result = schema.safeParse(true)
|
|
113
|
-
expect(result.success).toBe(false)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it('rejects null', () => {
|
|
117
|
-
const result = schema.safeParse(null)
|
|
118
|
-
expect(result.success).toBe(false)
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
it('rejects undefined', () => {
|
|
122
|
-
const result = schema.safeParse(undefined)
|
|
123
|
-
expect(result.success).toBe(false)
|
|
124
|
-
})
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
describe('zero literal', () => {
|
|
128
|
-
const schema = literal(0)
|
|
129
|
-
|
|
130
|
-
it('validates zero', () => {
|
|
131
|
-
const result = schema.safeParse(0)
|
|
132
|
-
expect(result.success).toBe(true)
|
|
133
|
-
if (result.success) {
|
|
134
|
-
expect(result.value).toBe(0)
|
|
135
|
-
}
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
it('rejects false', () => {
|
|
139
|
-
const result = schema.safeParse(false)
|
|
140
|
-
expect(result.success).toBe(false)
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
it('rejects null', () => {
|
|
144
|
-
const result = schema.safeParse(null)
|
|
145
|
-
expect(result.success).toBe(false)
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
it('rejects empty string', () => {
|
|
149
|
-
const result = schema.safeParse('')
|
|
150
|
-
expect(result.success).toBe(false)
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
it('rejects other numbers', () => {
|
|
154
|
-
const result = schema.safeParse(1)
|
|
155
|
-
expect(result.success).toBe(false)
|
|
156
|
-
})
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
describe('negative number literals', () => {
|
|
160
|
-
const schema = literal(-42)
|
|
161
|
-
|
|
162
|
-
it('validates exact negative number match', () => {
|
|
163
|
-
const result = schema.safeParse(-42)
|
|
164
|
-
expect(result.success).toBe(true)
|
|
165
|
-
if (result.success) {
|
|
166
|
-
expect(result.value).toBe(-42)
|
|
167
|
-
}
|
|
168
|
-
})
|
|
169
|
-
|
|
170
|
-
it('rejects positive equivalent', () => {
|
|
171
|
-
const result = schema.safeParse(42)
|
|
172
|
-
expect(result.success).toBe(false)
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
it('rejects different negative numbers', () => {
|
|
176
|
-
const result = schema.safeParse(-43)
|
|
177
|
-
expect(result.success).toBe(false)
|
|
178
|
-
})
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
describe('decimal number literals', () => {
|
|
182
|
-
const schema = literal(3.14)
|
|
183
|
-
|
|
184
|
-
it('validates exact decimal match', () => {
|
|
185
|
-
const result = schema.safeParse(3.14)
|
|
186
|
-
expect(result.success).toBe(true)
|
|
187
|
-
if (result.success) {
|
|
188
|
-
expect(result.value).toBe(3.14)
|
|
189
|
-
}
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('rejects different decimals', () => {
|
|
193
|
-
const result = schema.safeParse(3.15)
|
|
194
|
-
expect(result.success).toBe(false)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('rejects integer equivalent', () => {
|
|
198
|
-
const result = schema.safeParse(3)
|
|
199
|
-
expect(result.success).toBe(false)
|
|
200
|
-
})
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
describe('boolean literals', () => {
|
|
204
|
-
describe('true literal', () => {
|
|
205
|
-
const schema = literal(true)
|
|
206
|
-
|
|
207
|
-
it('validates true', () => {
|
|
208
|
-
const result = schema.safeParse(true)
|
|
209
|
-
expect(result.success).toBe(true)
|
|
210
|
-
if (result.success) {
|
|
211
|
-
expect(result.value).toBe(true)
|
|
212
|
-
}
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
it('rejects false', () => {
|
|
216
|
-
const result = schema.safeParse(false)
|
|
217
|
-
expect(result.success).toBe(false)
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
it('rejects truthy values', () => {
|
|
221
|
-
const result = schema.safeParse(1)
|
|
222
|
-
expect(result.success).toBe(false)
|
|
223
|
-
})
|
|
224
|
-
|
|
225
|
-
it('rejects string representation', () => {
|
|
226
|
-
const result = schema.safeParse('true')
|
|
227
|
-
expect(result.success).toBe(false)
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
it('rejects null', () => {
|
|
231
|
-
const result = schema.safeParse(null)
|
|
232
|
-
expect(result.success).toBe(false)
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
it('rejects undefined', () => {
|
|
236
|
-
const result = schema.safeParse(undefined)
|
|
237
|
-
expect(result.success).toBe(false)
|
|
238
|
-
})
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
describe('false literal', () => {
|
|
242
|
-
const schema = literal(false)
|
|
243
|
-
|
|
244
|
-
it('validates false', () => {
|
|
245
|
-
const result = schema.safeParse(false)
|
|
246
|
-
expect(result.success).toBe(true)
|
|
247
|
-
if (result.success) {
|
|
248
|
-
expect(result.value).toBe(false)
|
|
249
|
-
}
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
it('rejects true', () => {
|
|
253
|
-
const result = schema.safeParse(true)
|
|
254
|
-
expect(result.success).toBe(false)
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
it('rejects falsy values', () => {
|
|
258
|
-
const result = schema.safeParse(0)
|
|
259
|
-
expect(result.success).toBe(false)
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
it('rejects empty string', () => {
|
|
263
|
-
const result = schema.safeParse('')
|
|
264
|
-
expect(result.success).toBe(false)
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
it('rejects null', () => {
|
|
268
|
-
const result = schema.safeParse(null)
|
|
269
|
-
expect(result.success).toBe(false)
|
|
270
|
-
})
|
|
271
|
-
})
|
|
272
|
-
})
|
|
273
|
-
|
|
274
|
-
describe('null literal', () => {
|
|
275
|
-
const schema = literal(null)
|
|
276
|
-
|
|
277
|
-
it('validates null', () => {
|
|
278
|
-
const result = schema.safeParse(null)
|
|
279
|
-
expect(result.success).toBe(true)
|
|
280
|
-
if (result.success) {
|
|
281
|
-
expect(result.value).toBe(null)
|
|
282
|
-
}
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
it('rejects undefined', () => {
|
|
286
|
-
const result = schema.safeParse(undefined)
|
|
287
|
-
expect(result.success).toBe(false)
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('rejects false', () => {
|
|
291
|
-
const result = schema.safeParse(false)
|
|
292
|
-
expect(result.success).toBe(false)
|
|
293
|
-
})
|
|
294
|
-
|
|
295
|
-
it('rejects zero', () => {
|
|
296
|
-
const result = schema.safeParse(0)
|
|
297
|
-
expect(result.success).toBe(false)
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
it('rejects empty string', () => {
|
|
301
|
-
const result = schema.safeParse('')
|
|
302
|
-
expect(result.success).toBe(false)
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
it('rejects string "null"', () => {
|
|
306
|
-
const result = schema.safeParse('null')
|
|
307
|
-
expect(result.success).toBe(false)
|
|
308
|
-
})
|
|
309
|
-
})
|
|
310
|
-
|
|
311
|
-
describe('default values', () => {
|
|
312
|
-
describe('string literal with default', () => {
|
|
313
|
-
const schema = withDefault(literal('hello'), 'hello')
|
|
314
|
-
|
|
315
|
-
it('uses default value when undefined is provided', () => {
|
|
316
|
-
const result = schema.safeParse(undefined)
|
|
317
|
-
expect(result.success).toBe(true)
|
|
318
|
-
if (result.success) {
|
|
319
|
-
expect(result.value).toBe('hello')
|
|
320
|
-
}
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
it('uses explicit value over default', () => {
|
|
324
|
-
const result = schema.safeParse('hello')
|
|
325
|
-
expect(result.success).toBe(true)
|
|
326
|
-
if (result.success) {
|
|
327
|
-
expect(result.value).toBe('hello')
|
|
328
|
-
}
|
|
329
|
-
})
|
|
330
|
-
|
|
331
|
-
it('rejects non-matching value even with default', () => {
|
|
332
|
-
const result = schema.safeParse('world')
|
|
333
|
-
expect(result.success).toBe(false)
|
|
334
|
-
})
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
describe('number literal with default', () => {
|
|
338
|
-
const schema = withDefault(literal(42), 42)
|
|
339
|
-
|
|
340
|
-
it('uses default value when undefined is provided', () => {
|
|
341
|
-
const result = schema.safeParse(undefined)
|
|
342
|
-
expect(result.success).toBe(true)
|
|
343
|
-
if (result.success) {
|
|
344
|
-
expect(result.value).toBe(42)
|
|
345
|
-
}
|
|
346
|
-
})
|
|
347
|
-
|
|
348
|
-
it('uses explicit value over default', () => {
|
|
349
|
-
const result = schema.safeParse(42)
|
|
350
|
-
expect(result.success).toBe(true)
|
|
351
|
-
})
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
describe('boolean literal with default', () => {
|
|
355
|
-
const schema = withDefault(literal(true), true)
|
|
356
|
-
|
|
357
|
-
it('uses default value when undefined is provided', () => {
|
|
358
|
-
const result = schema.safeParse(undefined)
|
|
359
|
-
expect(result.success).toBe(true)
|
|
360
|
-
if (result.success) {
|
|
361
|
-
expect(result.value).toBe(true)
|
|
362
|
-
}
|
|
363
|
-
})
|
|
364
|
-
|
|
365
|
-
it('uses explicit value over default', () => {
|
|
366
|
-
const result = schema.safeParse(true)
|
|
367
|
-
expect(result.success).toBe(true)
|
|
368
|
-
})
|
|
369
|
-
})
|
|
370
|
-
|
|
371
|
-
describe('null literal with default', () => {
|
|
372
|
-
const schema = withDefault(literal(null), null)
|
|
373
|
-
|
|
374
|
-
it('uses default value when undefined is provided', () => {
|
|
375
|
-
const result = schema.safeParse(undefined)
|
|
376
|
-
expect(result.success).toBe(true)
|
|
377
|
-
if (result.success) {
|
|
378
|
-
expect(result.value).toBe(null)
|
|
379
|
-
}
|
|
380
|
-
})
|
|
381
|
-
|
|
382
|
-
it('uses explicit value over default', () => {
|
|
383
|
-
const result = schema.safeParse(null)
|
|
384
|
-
expect(result.success).toBe(true)
|
|
385
|
-
})
|
|
386
|
-
})
|
|
387
|
-
|
|
388
|
-
describe('false literal with default', () => {
|
|
389
|
-
const schema = withDefault(literal(false), false)
|
|
390
|
-
|
|
391
|
-
it('uses default value when undefined is provided', () => {
|
|
392
|
-
const result = schema.safeParse(undefined)
|
|
393
|
-
expect(result.success).toBe(true)
|
|
394
|
-
if (result.success) {
|
|
395
|
-
expect(result.value).toBe(false)
|
|
396
|
-
}
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
it('does not confuse explicit false with undefined', () => {
|
|
400
|
-
const result = schema.safeParse(false)
|
|
401
|
-
expect(result.success).toBe(true)
|
|
402
|
-
})
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
describe('zero literal with default', () => {
|
|
406
|
-
const schema = withDefault(literal(0), 0)
|
|
407
|
-
|
|
408
|
-
it('uses default value when undefined is provided', () => {
|
|
409
|
-
const result = schema.safeParse(undefined)
|
|
410
|
-
expect(result.success).toBe(true)
|
|
411
|
-
if (result.success) {
|
|
412
|
-
expect(result.value).toBe(0)
|
|
413
|
-
}
|
|
414
|
-
})
|
|
415
|
-
|
|
416
|
-
it('does not confuse explicit zero with undefined', () => {
|
|
417
|
-
const result = schema.safeParse(0)
|
|
418
|
-
expect(result.success).toBe(true)
|
|
419
|
-
})
|
|
420
|
-
})
|
|
421
|
-
})
|
|
422
|
-
|
|
423
|
-
describe('edge cases', () => {
|
|
424
|
-
it('handles special string characters', () => {
|
|
425
|
-
const schema = literal('hello\nworld')
|
|
426
|
-
expect(schema.safeParse('hello\nworld').success).toBe(true)
|
|
427
|
-
expect(schema.safeParse('hello world').success).toBe(false)
|
|
428
|
-
})
|
|
429
|
-
|
|
430
|
-
it('handles unicode characters in strings', () => {
|
|
431
|
-
const schema = literal('Hello 世界 🌍')
|
|
432
|
-
expect(schema.safeParse('Hello 世界 🌍').success).toBe(true)
|
|
433
|
-
expect(schema.safeParse('Hello world').success).toBe(false)
|
|
434
|
-
})
|
|
435
|
-
|
|
436
|
-
it('handles emoji literals', () => {
|
|
437
|
-
const schema = literal('🚀')
|
|
438
|
-
expect(schema.safeParse('🚀').success).toBe(true)
|
|
439
|
-
expect(schema.safeParse('🌟').success).toBe(false)
|
|
440
|
-
})
|
|
441
|
-
|
|
442
|
-
it('handles very long string literals', () => {
|
|
443
|
-
const longString = 'a'.repeat(1000)
|
|
444
|
-
const schema = literal(longString)
|
|
445
|
-
expect(schema.safeParse(longString).success).toBe(true)
|
|
446
|
-
expect(schema.safeParse(longString + 'b').success).toBe(false)
|
|
447
|
-
})
|
|
448
|
-
|
|
449
|
-
it('handles string with whitespace', () => {
|
|
450
|
-
const schema = literal(' hello ')
|
|
451
|
-
expect(schema.safeParse(' hello ').success).toBe(true)
|
|
452
|
-
expect(schema.safeParse('hello').success).toBe(false)
|
|
453
|
-
expect(schema.safeParse(' hello').success).toBe(false)
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
it('handles Number.MAX_SAFE_INTEGER', () => {
|
|
457
|
-
const schema = literal(Number.MAX_SAFE_INTEGER)
|
|
458
|
-
expect(schema.safeParse(Number.MAX_SAFE_INTEGER).success).toBe(true)
|
|
459
|
-
expect(schema.safeParse(Number.MAX_SAFE_INTEGER - 1).success).toBe(false)
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
it('handles Number.MIN_SAFE_INTEGER', () => {
|
|
463
|
-
const schema = literal(Number.MIN_SAFE_INTEGER)
|
|
464
|
-
expect(schema.safeParse(Number.MIN_SAFE_INTEGER).success).toBe(true)
|
|
465
|
-
expect(schema.safeParse(Number.MIN_SAFE_INTEGER + 1).success).toBe(false)
|
|
466
|
-
})
|
|
467
|
-
|
|
468
|
-
it('rejects NaN', () => {
|
|
469
|
-
const schema = literal(42)
|
|
470
|
-
expect(schema.safeParse(NaN).success).toBe(false)
|
|
471
|
-
})
|
|
472
|
-
|
|
473
|
-
it('rejects Infinity', () => {
|
|
474
|
-
const schema = literal(42)
|
|
475
|
-
expect(schema.safeParse(Infinity).success).toBe(false)
|
|
476
|
-
})
|
|
477
|
-
|
|
478
|
-
it('rejects -Infinity', () => {
|
|
479
|
-
const schema = literal(42)
|
|
480
|
-
expect(schema.safeParse(-Infinity).success).toBe(false)
|
|
481
|
-
})
|
|
482
|
-
|
|
483
|
-
it('rejects Boolean objects', () => {
|
|
484
|
-
const schema = literal(true)
|
|
485
|
-
expect(schema.safeParse(new Boolean(true)).success).toBe(false)
|
|
486
|
-
})
|
|
487
|
-
|
|
488
|
-
it('rejects String objects', () => {
|
|
489
|
-
const schema = literal('hello')
|
|
490
|
-
expect(schema.safeParse(new String('hello')).success).toBe(false)
|
|
491
|
-
})
|
|
492
|
-
|
|
493
|
-
it('rejects Number objects', () => {
|
|
494
|
-
const schema = literal(42)
|
|
495
|
-
expect(schema.safeParse(new Number(42)).success).toBe(false)
|
|
496
|
-
})
|
|
497
|
-
|
|
498
|
-
it('distinguishes between -0 and +0', () => {
|
|
499
|
-
const schemaPositive = literal(0)
|
|
500
|
-
const schemaNegative = literal(-0)
|
|
501
|
-
// In JavaScript, 0 === -0, so both should validate for both schemas
|
|
502
|
-
expect(schemaPositive.safeParse(0).success).toBe(true)
|
|
503
|
-
expect(schemaPositive.safeParse(-0).success).toBe(true)
|
|
504
|
-
expect(schemaNegative.safeParse(0).success).toBe(true)
|
|
505
|
-
expect(schemaNegative.safeParse(-0).success).toBe(true)
|
|
506
|
-
})
|
|
507
|
-
|
|
508
|
-
it('handles very small decimal differences', () => {
|
|
509
|
-
const schema = literal(0.1 + 0.2)
|
|
510
|
-
// Note: 0.1 + 0.2 !== 0.3 in JavaScript due to floating point precision
|
|
511
|
-
expect(schema.safeParse(0.1 + 0.2).success).toBe(true)
|
|
512
|
-
expect(schema.safeParse(0.3).success).toBe(false)
|
|
513
|
-
})
|
|
514
|
-
})
|
|
515
|
-
|
|
516
|
-
describe('type safety', () => {
|
|
517
|
-
it('accepts exact literal types in TypeScript', () => {
|
|
518
|
-
const schema = literal('specific' as const)
|
|
519
|
-
const result = schema.safeParse('specific')
|
|
520
|
-
expect(result.success).toBe(true)
|
|
521
|
-
})
|
|
522
|
-
|
|
523
|
-
it('preserves literal type in success result', () => {
|
|
524
|
-
const schema = literal(42)
|
|
525
|
-
const result = schema.safeParse(42)
|
|
526
|
-
expect(result.success).toBe(true)
|
|
527
|
-
if (result.success) {
|
|
528
|
-
// TypeScript should infer result.value as the literal type 42
|
|
529
|
-
expect(result.value).toBe(42)
|
|
530
|
-
}
|
|
531
|
-
})
|
|
532
|
-
})
|
|
533
|
-
})
|