@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.
Files changed (263) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/core/$type.d.ts +2 -2
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js.map +1 -1
  5. package/dist/core/record-key.d.ts +1 -1
  6. package/dist/core/record-key.d.ts.map +1 -1
  7. package/dist/core/record-key.js.map +1 -1
  8. package/dist/core/schema.d.ts +3 -2
  9. package/dist/core/schema.d.ts.map +1 -1
  10. package/dist/core/schema.js +1 -1
  11. package/dist/core/schema.js.map +1 -1
  12. package/dist/core/standard-schema.d.ts +2 -2
  13. package/dist/core/standard-schema.d.ts.map +1 -1
  14. package/dist/core/standard-schema.js.map +1 -1
  15. package/dist/core/string-format.d.ts +2 -2
  16. package/dist/core/string-format.d.ts.map +1 -1
  17. package/dist/core/string-format.js.map +1 -1
  18. package/dist/core/validation-error.d.ts +1 -1
  19. package/dist/core/validation-error.d.ts.map +1 -1
  20. package/dist/core/validation-error.js +1 -1
  21. package/dist/core/validation-error.js.map +1 -1
  22. package/dist/core/validator.d.ts +1 -1
  23. package/dist/core/validator.d.ts.map +1 -1
  24. package/dist/core/validator.js +1 -1
  25. package/dist/core/validator.js.map +1 -1
  26. package/dist/helpers.d.ts +2 -2
  27. package/dist/helpers.d.ts.map +1 -1
  28. package/dist/helpers.js +2 -2
  29. package/dist/helpers.js.map +1 -1
  30. package/dist/schema/array.d.ts +1 -1
  31. package/dist/schema/array.d.ts.map +1 -1
  32. package/dist/schema/array.js +1 -1
  33. package/dist/schema/array.js.map +1 -1
  34. package/dist/schema/blob.d.ts +1 -1
  35. package/dist/schema/blob.d.ts.map +1 -1
  36. package/dist/schema/blob.js +2 -2
  37. package/dist/schema/blob.js.map +1 -1
  38. package/dist/schema/boolean.js +1 -1
  39. package/dist/schema/boolean.js.map +1 -1
  40. package/dist/schema/bytes.js +1 -1
  41. package/dist/schema/bytes.js.map +1 -1
  42. package/dist/schema/cid.d.ts +1 -1
  43. package/dist/schema/cid.d.ts.map +1 -1
  44. package/dist/schema/cid.js +3 -3
  45. package/dist/schema/cid.js.map +1 -1
  46. package/dist/schema/custom.js +1 -1
  47. package/dist/schema/custom.js.map +1 -1
  48. package/dist/schema/dict.d.ts +1 -1
  49. package/dist/schema/dict.d.ts.map +1 -1
  50. package/dist/schema/dict.js +1 -1
  51. package/dist/schema/dict.js.map +1 -1
  52. package/dist/schema/discriminated-union.d.ts +1 -1
  53. package/dist/schema/discriminated-union.d.ts.map +1 -1
  54. package/dist/schema/discriminated-union.js +2 -1
  55. package/dist/schema/discriminated-union.js.map +1 -1
  56. package/dist/schema/enum.js +1 -1
  57. package/dist/schema/enum.js.map +1 -1
  58. package/dist/schema/integer.js +1 -1
  59. package/dist/schema/integer.js.map +1 -1
  60. package/dist/schema/intersection.d.ts +1 -1
  61. package/dist/schema/intersection.d.ts.map +1 -1
  62. package/dist/schema/intersection.js +3 -1
  63. package/dist/schema/intersection.js.map +1 -1
  64. package/dist/schema/lex-map.d.ts +1 -1
  65. package/dist/schema/lex-map.d.ts.map +1 -1
  66. package/dist/schema/lex-map.js +1 -1
  67. package/dist/schema/lex-map.js.map +1 -1
  68. package/dist/schema/lex-value.d.ts +1 -1
  69. package/dist/schema/lex-value.d.ts.map +1 -1
  70. package/dist/schema/lex-value.js +1 -1
  71. package/dist/schema/lex-value.js.map +1 -1
  72. package/dist/schema/literal.js +1 -1
  73. package/dist/schema/literal.js.map +1 -1
  74. package/dist/schema/never.js +1 -1
  75. package/dist/schema/never.js.map +1 -1
  76. package/dist/schema/null.js +1 -1
  77. package/dist/schema/null.js.map +1 -1
  78. package/dist/schema/nullable.d.ts +1 -1
  79. package/dist/schema/nullable.d.ts.map +1 -1
  80. package/dist/schema/nullable.js +1 -1
  81. package/dist/schema/nullable.js.map +1 -1
  82. package/dist/schema/object.d.ts +2 -1
  83. package/dist/schema/object.d.ts.map +1 -1
  84. package/dist/schema/object.js +1 -1
  85. package/dist/schema/object.js.map +1 -1
  86. package/dist/schema/optional.d.ts +2 -1
  87. package/dist/schema/optional.d.ts.map +1 -1
  88. package/dist/schema/optional.js +2 -1
  89. package/dist/schema/optional.js.map +1 -1
  90. package/dist/schema/params.d.ts +1 -1
  91. package/dist/schema/params.d.ts.map +1 -1
  92. package/dist/schema/params.js +1 -1
  93. package/dist/schema/params.js.map +1 -1
  94. package/dist/schema/payload.d.ts +3 -2
  95. package/dist/schema/payload.d.ts.map +1 -1
  96. package/dist/schema/payload.js +2 -1
  97. package/dist/schema/payload.js.map +1 -1
  98. package/dist/schema/permission-set.d.ts +1 -1
  99. package/dist/schema/permission-set.d.ts.map +1 -1
  100. package/dist/schema/permission-set.js +1 -0
  101. package/dist/schema/permission-set.js.map +1 -1
  102. package/dist/schema/permission.d.ts +1 -1
  103. package/dist/schema/permission.d.ts.map +1 -1
  104. package/dist/schema/permission.js.map +1 -1
  105. package/dist/schema/procedure.d.ts +1 -1
  106. package/dist/schema/procedure.d.ts.map +1 -1
  107. package/dist/schema/procedure.js +2 -0
  108. package/dist/schema/procedure.js.map +1 -1
  109. package/dist/schema/query.d.ts +1 -1
  110. package/dist/schema/query.d.ts.map +1 -1
  111. package/dist/schema/query.js +2 -0
  112. package/dist/schema/query.js.map +1 -1
  113. package/dist/schema/record.d.ts +2 -2
  114. package/dist/schema/record.d.ts.map +1 -1
  115. package/dist/schema/record.js +1 -1
  116. package/dist/schema/record.js.map +1 -1
  117. package/dist/schema/ref.d.ts +1 -1
  118. package/dist/schema/ref.d.ts.map +1 -1
  119. package/dist/schema/ref.js +1 -1
  120. package/dist/schema/ref.js.map +1 -1
  121. package/dist/schema/refine.d.ts +2 -2
  122. package/dist/schema/refine.d.ts.map +1 -1
  123. package/dist/schema/refine.js +1 -1
  124. package/dist/schema/refine.js.map +1 -1
  125. package/dist/schema/regexp.js +1 -1
  126. package/dist/schema/regexp.js.map +1 -1
  127. package/dist/schema/string.d.ts +2 -2
  128. package/dist/schema/string.d.ts.map +1 -1
  129. package/dist/schema/string.js +1 -1
  130. package/dist/schema/string.js.map +1 -1
  131. package/dist/schema/subscription.d.ts +3 -2
  132. package/dist/schema/subscription.d.ts.map +1 -1
  133. package/dist/schema/subscription.js +2 -0
  134. package/dist/schema/subscription.js.map +1 -1
  135. package/dist/schema/token.d.ts +1 -1
  136. package/dist/schema/token.d.ts.map +1 -1
  137. package/dist/schema/token.js +1 -1
  138. package/dist/schema/token.js.map +1 -1
  139. package/dist/schema/typed-object.d.ts +2 -2
  140. package/dist/schema/typed-object.d.ts.map +1 -1
  141. package/dist/schema/typed-object.js +1 -1
  142. package/dist/schema/typed-object.js.map +1 -1
  143. package/dist/schema/typed-ref.d.ts +1 -1
  144. package/dist/schema/typed-ref.d.ts.map +1 -1
  145. package/dist/schema/typed-ref.js +1 -1
  146. package/dist/schema/typed-ref.js.map +1 -1
  147. package/dist/schema/typed-union.d.ts +1 -1
  148. package/dist/schema/typed-union.d.ts.map +1 -1
  149. package/dist/schema/typed-union.js +3 -1
  150. package/dist/schema/typed-union.js.map +1 -1
  151. package/dist/schema/union.d.ts +1 -1
  152. package/dist/schema/union.d.ts.map +1 -1
  153. package/dist/schema/union.js +1 -1
  154. package/dist/schema/union.js.map +1 -1
  155. package/dist/schema/unknown.js +1 -1
  156. package/dist/schema/unknown.js.map +1 -1
  157. package/dist/schema/with-default.d.ts +1 -1
  158. package/dist/schema/with-default.d.ts.map +1 -1
  159. package/dist/schema/with-default.js +1 -1
  160. package/dist/schema/with-default.js.map +1 -1
  161. package/package.json +6 -10
  162. package/src/core/$type.test.ts +0 -24
  163. package/src/core/$type.ts +0 -199
  164. package/src/core/record-key.ts +0 -85
  165. package/src/core/result.ts +0 -15
  166. package/src/core/schema.ts +0 -412
  167. package/src/core/standard-schema.test.ts +0 -124
  168. package/src/core/standard-schema.ts +0 -31
  169. package/src/core/string-format.ts +0 -411
  170. package/src/core/types.ts +0 -120
  171. package/src/core/validation-error.ts +0 -134
  172. package/src/core/validation-issue.ts +0 -340
  173. package/src/core/validator.ts +0 -636
  174. package/src/core.ts +0 -9
  175. package/src/external.ts +0 -3
  176. package/src/helpers.test.ts +0 -694
  177. package/src/helpers.ts +0 -222
  178. package/src/index.ts +0 -3
  179. package/src/schema/array.test.ts +0 -251
  180. package/src/schema/array.ts +0 -126
  181. package/src/schema/blob.test.ts +0 -733
  182. package/src/schema/blob.ts +0 -150
  183. package/src/schema/boolean.test.ts +0 -118
  184. package/src/schema/boolean.ts +0 -46
  185. package/src/schema/bytes.test.ts +0 -227
  186. package/src/schema/bytes.ts +0 -81
  187. package/src/schema/cid.test.ts +0 -125
  188. package/src/schema/cid.ts +0 -69
  189. package/src/schema/custom.test.ts +0 -414
  190. package/src/schema/custom.ts +0 -106
  191. package/src/schema/dict.test.ts +0 -181
  192. package/src/schema/dict.ts +0 -122
  193. package/src/schema/discriminated-union.test.ts +0 -676
  194. package/src/schema/discriminated-union.ts +0 -196
  195. package/src/schema/enum.test.ts +0 -398
  196. package/src/schema/enum.ts +0 -77
  197. package/src/schema/integer.test.ts +0 -314
  198. package/src/schema/integer.ts +0 -86
  199. package/src/schema/intersection.test.ts +0 -33
  200. package/src/schema/intersection.ts +0 -113
  201. package/src/schema/lex-map.test.ts +0 -593
  202. package/src/schema/lex-map.ts +0 -63
  203. package/src/schema/lex-value.test.ts +0 -81
  204. package/src/schema/lex-value.ts +0 -86
  205. package/src/schema/literal.test.ts +0 -533
  206. package/src/schema/literal.ts +0 -70
  207. package/src/schema/never.test.ts +0 -175
  208. package/src/schema/never.ts +0 -56
  209. package/src/schema/null.test.ts +0 -80
  210. package/src/schema/null.ts +0 -49
  211. package/src/schema/nullable.test.ts +0 -470
  212. package/src/schema/nullable.ts +0 -74
  213. package/src/schema/object.test.ts +0 -69
  214. package/src/schema/object.ts +0 -136
  215. package/src/schema/optional.test.ts +0 -479
  216. package/src/schema/optional.ts +0 -92
  217. package/src/schema/params.test.ts +0 -1118
  218. package/src/schema/params.ts +0 -371
  219. package/src/schema/payload.test.ts +0 -340
  220. package/src/schema/payload.ts +0 -204
  221. package/src/schema/permission-set.test.ts +0 -613
  222. package/src/schema/permission-set.ts +0 -86
  223. package/src/schema/permission.test.ts +0 -537
  224. package/src/schema/permission.ts +0 -63
  225. package/src/schema/procedure.test.ts +0 -324
  226. package/src/schema/procedure.ts +0 -98
  227. package/src/schema/query.test.ts +0 -348
  228. package/src/schema/query.ts +0 -86
  229. package/src/schema/record.test.ts +0 -812
  230. package/src/schema/record.ts +0 -217
  231. package/src/schema/ref.test.ts +0 -349
  232. package/src/schema/ref.ts +0 -103
  233. package/src/schema/refine.test.ts +0 -579
  234. package/src/schema/refine.ts +0 -153
  235. package/src/schema/regexp.test.ts +0 -577
  236. package/src/schema/regexp.ts +0 -82
  237. package/src/schema/string.test.ts +0 -773
  238. package/src/schema/string.ts +0 -229
  239. package/src/schema/subscription.test.ts +0 -499
  240. package/src/schema/subscription.ts +0 -108
  241. package/src/schema/token.test.ts +0 -152
  242. package/src/schema/token.ts +0 -103
  243. package/src/schema/typed-object.test.ts +0 -745
  244. package/src/schema/typed-object.ts +0 -181
  245. package/src/schema/typed-ref.test.ts +0 -796
  246. package/src/schema/typed-ref.ts +0 -126
  247. package/src/schema/typed-union.test.ts +0 -355
  248. package/src/schema/typed-union.ts +0 -130
  249. package/src/schema/union.test.ts +0 -191
  250. package/src/schema/union.ts +0 -89
  251. package/src/schema/unknown.test.ts +0 -313
  252. package/src/schema/unknown.ts +0 -47
  253. package/src/schema/with-default.ts +0 -81
  254. package/src/schema.ts +0 -43
  255. package/src/util/array-agg.test.ts +0 -42
  256. package/src/util/array-agg.ts +0 -44
  257. package/src/util/assertion-util.ts +0 -1
  258. package/src/util/if-any.ts +0 -3
  259. package/src/util/lazy-property.ts +0 -14
  260. package/src/util/memoize.ts +0 -37
  261. package/tsconfig.build.json +0 -12
  262. package/tsconfig.json +0 -7
  263. 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
- })
@@ -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
- })