@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,579 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { integer } from './integer.js'
3
- import { object } from './object.js'
4
- import { refine } from './refine.js'
5
- import { string } from './string.js'
6
-
7
- describe('refine', () => {
8
- describe('basic refinement checks', () => {
9
- const schema = refine(integer(), {
10
- check: (value) => value > 0,
11
- message: 'Value must be positive',
12
- })
13
-
14
- it('validates values that pass the refinement check', () => {
15
- const result = schema.safeParse(42)
16
- expect(result.success).toBe(true)
17
- })
18
-
19
- it('rejects values that fail the refinement check', () => {
20
- const result = schema.safeParse(-5)
21
- expect(result.success).toBe(false)
22
- })
23
-
24
- it('rejects zero when check requires positive', () => {
25
- const result = schema.safeParse(0)
26
- expect(result.success).toBe(false)
27
- })
28
-
29
- it('still validates base schema constraints', () => {
30
- const result = schema.safeParse('not a number')
31
- expect(result.success).toBe(false)
32
- })
33
- })
34
-
35
- describe('refinement with type assertions', () => {
36
- const schema = refine(integer(), {
37
- check: (value): value is 42 => value === 42,
38
- message: 'Value must be 42',
39
- })
40
-
41
- it('validates values that pass the type assertion', () => {
42
- const result = schema.safeParse(42)
43
- expect(result.success).toBe(true)
44
- })
45
-
46
- it('rejects values that fail the type assertion', () => {
47
- const result = schema.safeParse(43)
48
- expect(result.success).toBe(false)
49
- })
50
- })
51
-
52
- describe('refinement with string schema', () => {
53
- const schema = refine(string(), {
54
- check: (value) => value.includes('@'),
55
- message: 'String must contain @ symbol',
56
- })
57
-
58
- it('validates strings that pass the refinement check', () => {
59
- const result = schema.safeParse('user@example.com')
60
- expect(result.success).toBe(true)
61
- })
62
-
63
- it('rejects strings that fail the refinement check', () => {
64
- const result = schema.safeParse('userexample.com')
65
- expect(result.success).toBe(false)
66
- })
67
-
68
- it('rejects non-strings before refinement check', () => {
69
- const result = schema.safeParse(123)
70
- expect(result.success).toBe(false)
71
- })
72
- })
73
-
74
- describe('refinement with base schema constraints', () => {
75
- const schema = refine(integer({ minimum: 0, maximum: 100 }), {
76
- check: (value) => value % 2 === 0,
77
- message: 'Value must be even',
78
- })
79
-
80
- it('validates values that pass both base constraints and refinement', () => {
81
- const result = schema.safeParse(42)
82
- expect(result.success).toBe(true)
83
- })
84
-
85
- it('rejects values that fail base constraints', () => {
86
- const result = schema.safeParse(150)
87
- expect(result.success).toBe(false)
88
- })
89
-
90
- it('rejects values that pass base constraints but fail refinement', () => {
91
- const result = schema.safeParse(43)
92
- expect(result.success).toBe(false)
93
- })
94
-
95
- it('rejects values that fail both base constraints and refinement', () => {
96
- const result = schema.safeParse(-5)
97
- expect(result.success).toBe(false)
98
- })
99
- })
100
-
101
- describe('multiple refinements chained', () => {
102
- const schema = refine(
103
- refine(integer(), {
104
- check: (value) => value > 0,
105
- message: 'Value must be positive',
106
- }),
107
- {
108
- check: (value) => value < 100,
109
- message: 'Value must be less than 100',
110
- },
111
- )
112
-
113
- it('validates values that pass all refinements', () => {
114
- const result = schema.safeParse(42)
115
- expect(result.success).toBe(true)
116
- })
117
-
118
- it('rejects values that fail first refinement', () => {
119
- const result = schema.safeParse(-5)
120
- expect(result.success).toBe(false)
121
- })
122
-
123
- it('rejects values that fail second refinement', () => {
124
- const result = schema.safeParse(150)
125
- expect(result.success).toBe(false)
126
- })
127
-
128
- it('accepts values at the boundary of both refinements', () => {
129
- const result1 = schema.safeParse(1)
130
- expect(result1.success).toBe(true)
131
-
132
- const result2 = schema.safeParse(99)
133
- expect(result2.success).toBe(true)
134
- })
135
- })
136
-
137
- describe('refinement with custom path', () => {
138
- const schema = refine(integer(), {
139
- check: (value) => value > 0,
140
- message: 'Value must be positive',
141
- path: 'customField',
142
- })
143
-
144
- it('validates values that pass the refinement', () => {
145
- const result = schema.safeParse(42)
146
- expect(result.success).toBe(true)
147
- })
148
-
149
- it('rejects values that fail the refinement', () => {
150
- const result = schema.safeParse(-5)
151
- expect(result.success).toBe(false)
152
- })
153
- })
154
-
155
- describe('refinement with array path', () => {
156
- const schema = refine(integer(), {
157
- check: (value) => value > 0,
158
- message: 'Value must be positive',
159
- path: ['nested', 'field'],
160
- })
161
-
162
- it('validates values that pass the refinement', () => {
163
- const result = schema.safeParse(42)
164
- expect(result.success).toBe(true)
165
- })
166
-
167
- it('rejects values that fail the refinement', () => {
168
- const result = schema.safeParse(-5)
169
- expect(result.success).toBe(false)
170
- })
171
- })
172
-
173
- describe('refinement on object properties', () => {
174
- const schema = object({
175
- age: refine(integer(), {
176
- check: (value) => value >= 18,
177
- message: 'Age must be at least 18',
178
- }),
179
- email: refine(string(), {
180
- check: (value) => value.includes('@'),
181
- message: 'Email must contain @ symbol',
182
- }),
183
- })
184
-
185
- it('validates objects with properties that pass refinements', () => {
186
- const result = schema.safeParse({
187
- age: 25,
188
- email: 'user@example.com',
189
- })
190
- expect(result.success).toBe(true)
191
- })
192
-
193
- it('rejects objects with age below minimum', () => {
194
- const result = schema.safeParse({
195
- age: 16,
196
- email: 'user@example.com',
197
- })
198
- expect(result.success).toBe(false)
199
- })
200
-
201
- it('rejects objects with invalid email', () => {
202
- const result = schema.safeParse({
203
- age: 25,
204
- email: 'userexample.com',
205
- })
206
- expect(result.success).toBe(false)
207
- })
208
-
209
- it('rejects objects with both properties failing refinements', () => {
210
- const result = schema.safeParse({
211
- age: 16,
212
- email: 'userexample.com',
213
- })
214
- expect(result.success).toBe(false)
215
- })
216
- })
217
-
218
- describe('complex refinement logic', () => {
219
- const schema = refine(string(), {
220
- check: (value) => {
221
- const hasLowerCase = /[a-z]/.test(value)
222
- const hasUpperCase = /[A-Z]/.test(value)
223
- const hasNumber = /[0-9]/.test(value)
224
- return hasLowerCase && hasUpperCase && hasNumber
225
- },
226
- message: 'Password must contain lowercase, uppercase, and numbers',
227
- })
228
-
229
- it('validates strings that meet all password requirements', () => {
230
- const result = schema.safeParse('Password123')
231
- expect(result.success).toBe(true)
232
- })
233
-
234
- it('rejects strings without lowercase', () => {
235
- const result = schema.safeParse('PASSWORD123')
236
- expect(result.success).toBe(false)
237
- })
238
-
239
- it('rejects strings without uppercase', () => {
240
- const result = schema.safeParse('password123')
241
- expect(result.success).toBe(false)
242
- })
243
-
244
- it('rejects strings without numbers', () => {
245
- const result = schema.safeParse('Password')
246
- expect(result.success).toBe(false)
247
- })
248
-
249
- it('rejects empty strings', () => {
250
- const result = schema.safeParse('')
251
- expect(result.success).toBe(false)
252
- })
253
- })
254
-
255
- describe('refinement with comparison logic', () => {
256
- const schema = refine(integer(), {
257
- check: (value) => {
258
- // Check if value is a prime number
259
- if (value <= 1) return false
260
- if (value <= 3) return true
261
- if (value % 2 === 0 || value % 3 === 0) return false
262
- for (let i = 5; i * i <= value; i += 6) {
263
- if (value % i === 0 || value % (i + 2) === 0) return false
264
- }
265
- return true
266
- },
267
- message: 'Value must be a prime number',
268
- })
269
-
270
- it('validates prime numbers', () => {
271
- const primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]
272
- primes.forEach((prime) => {
273
- const result = schema.safeParse(prime)
274
- expect(result.success).toBe(true)
275
- })
276
- })
277
-
278
- it('rejects non-prime numbers', () => {
279
- const nonPrimes = [0, 1, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]
280
- nonPrimes.forEach((nonPrime) => {
281
- const result = schema.safeParse(nonPrime)
282
- expect(result.success).toBe(false)
283
- })
284
- })
285
- })
286
-
287
- describe('refinement with string length logic', () => {
288
- const schema = refine(string({ minLength: 1, maxLength: 50 }), {
289
- check: (value) => value.trim().length > 0,
290
- message: 'String must not be only whitespace',
291
- })
292
-
293
- it('validates non-empty trimmed strings', () => {
294
- const result = schema.safeParse('hello world')
295
- expect(result.success).toBe(true)
296
- })
297
-
298
- it('validates strings with leading/trailing whitespace', () => {
299
- const result = schema.safeParse(' hello ')
300
- expect(result.success).toBe(true)
301
- })
302
-
303
- it('rejects strings with only whitespace', () => {
304
- const result = schema.safeParse(' ')
305
- expect(result.success).toBe(false)
306
- })
307
-
308
- it('rejects single space', () => {
309
- const result = schema.safeParse(' ')
310
- expect(result.success).toBe(false)
311
- })
312
-
313
- it('rejects tabs and newlines only', () => {
314
- const result = schema.safeParse('\t\n ')
315
- expect(result.success).toBe(false)
316
- })
317
- })
318
-
319
- describe('refinement preserves original schema', () => {
320
- const originalSchema = integer({ minimum: 0 })
321
- const refinedSchema = refine(originalSchema, {
322
- check: (value) => value % 2 === 0,
323
- message: 'Value must be even',
324
- })
325
-
326
- it('original schema still works independently', () => {
327
- const result = originalSchema.safeParse(5)
328
- expect(result.success).toBe(true)
329
- })
330
-
331
- it('refined schema has additional constraint', () => {
332
- const result = refinedSchema.safeParse(5)
333
- expect(result.success).toBe(false)
334
- })
335
-
336
- it('refined schema inherits base constraints', () => {
337
- const result1 = refinedSchema.safeParse(-2)
338
- expect(result1.success).toBe(false)
339
-
340
- const result2 = refinedSchema.safeParse(4)
341
- expect(result2.success).toBe(true)
342
- })
343
- })
344
-
345
- describe('refinement with boundary conditions', () => {
346
- const schema = refine(integer({ minimum: 0, maximum: 100 }), {
347
- check: (value) => value !== 50,
348
- message: 'Value must not be 50',
349
- })
350
-
351
- it('validates values at lower boundary', () => {
352
- const result = schema.safeParse(0)
353
- expect(result.success).toBe(true)
354
- })
355
-
356
- it('validates values at upper boundary', () => {
357
- const result = schema.safeParse(100)
358
- expect(result.success).toBe(true)
359
- })
360
-
361
- it('rejects the specific excluded value', () => {
362
- const result = schema.safeParse(50)
363
- expect(result.success).toBe(false)
364
- })
365
-
366
- it('validates values around the excluded value', () => {
367
- const result1 = schema.safeParse(49)
368
- expect(result1.success).toBe(true)
369
-
370
- const result2 = schema.safeParse(51)
371
- expect(result2.success).toBe(true)
372
- })
373
- })
374
-
375
- describe('refinement with regex patterns', () => {
376
- const schema = refine(string(), {
377
- check: (value) => /^[A-Z][a-zA-Z0-9]*$/.test(value),
378
- message: 'Must start with uppercase letter',
379
- })
380
-
381
- it('validates strings starting with uppercase', () => {
382
- const result = schema.safeParse('Hello123')
383
- expect(result.success).toBe(true)
384
- })
385
-
386
- it('rejects strings starting with lowercase', () => {
387
- const result = schema.safeParse('hello123')
388
- expect(result.success).toBe(false)
389
- })
390
-
391
- it('rejects strings starting with number', () => {
392
- const result = schema.safeParse('123Hello')
393
- expect(result.success).toBe(false)
394
- })
395
-
396
- it('rejects strings starting with special character', () => {
397
- const result = schema.safeParse('_Hello')
398
- expect(result.success).toBe(false)
399
- })
400
-
401
- it('validates single uppercase letter', () => {
402
- const result = schema.safeParse('A')
403
- expect(result.success).toBe(true)
404
- })
405
- })
406
-
407
- describe('refinement with custom error messages', () => {
408
- const schema = refine(integer(), {
409
- check: (value) => value >= 1 && value <= 10,
410
- message: 'Value must be between 1 and 10 (inclusive)',
411
- })
412
-
413
- it('validates values within range', () => {
414
- const result = schema.safeParse(5)
415
- expect(result.success).toBe(true)
416
- })
417
-
418
- it('rejects values outside range', () => {
419
- const result = schema.safeParse(11)
420
- expect(result.success).toBe(false)
421
- })
422
-
423
- it('rejects zero', () => {
424
- const result = schema.safeParse(0)
425
- expect(result.success).toBe(false)
426
- })
427
- })
428
-
429
- describe('edge cases', () => {
430
- it('handles refinement that always returns true', () => {
431
- const schema = refine(integer(), {
432
- check: () => true,
433
- message: 'This should never fail',
434
- })
435
- const result = schema.safeParse(42)
436
- expect(result.success).toBe(true)
437
- })
438
-
439
- it('handles refinement that always returns false', () => {
440
- const schema = refine(integer(), {
441
- check: () => false,
442
- message: 'This always fails',
443
- })
444
- const result = schema.safeParse(42)
445
- expect(result.success).toBe(false)
446
- })
447
-
448
- it('handles empty string refinement', () => {
449
- const schema = refine(string(), {
450
- check: (value) => value === '',
451
- message: 'Value must be empty string',
452
- })
453
- const result1 = schema.safeParse('')
454
- expect(result1.success).toBe(true)
455
-
456
- const result2 = schema.safeParse('hello')
457
- expect(result2.success).toBe(false)
458
- })
459
-
460
- it('handles zero value refinement', () => {
461
- const schema = refine(integer(), {
462
- check: (value) => value === 0,
463
- message: 'Value must be zero',
464
- })
465
- const result1 = schema.safeParse(0)
466
- expect(result1.success).toBe(true)
467
-
468
- const result2 = schema.safeParse(1)
469
- expect(result2.success).toBe(false)
470
- })
471
-
472
- it('handles negative value refinement', () => {
473
- const schema = refine(integer(), {
474
- check: (value) => value < 0,
475
- message: 'Value must be negative',
476
- })
477
- const result1 = schema.safeParse(-5)
478
- expect(result1.success).toBe(true)
479
-
480
- const result2 = schema.safeParse(5)
481
- expect(result2.success).toBe(false)
482
- })
483
- })
484
-
485
- describe('refinement with combined string constraints', () => {
486
- const schema = refine(string({ minLength: 8, maxLength: 20 }), {
487
- check: (value) => {
488
- const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value)
489
- const hasLetter = /[a-zA-Z]/.test(value)
490
- return hasSpecialChar && hasLetter
491
- },
492
- message: 'Must contain letters and special characters',
493
- })
494
-
495
- it('validates strings meeting all requirements', () => {
496
- const result = schema.safeParse('Hello@World!')
497
- expect(result.success).toBe(true)
498
- })
499
-
500
- it('rejects strings too short', () => {
501
- const result = schema.safeParse('Hi@!')
502
- expect(result.success).toBe(false)
503
- })
504
-
505
- it('rejects strings without special characters', () => {
506
- const result = schema.safeParse('HelloWorld')
507
- expect(result.success).toBe(false)
508
- })
509
-
510
- it('rejects strings without letters', () => {
511
- const result = schema.safeParse('12345!@#$%')
512
- expect(result.success).toBe(false)
513
- })
514
-
515
- it('validates strings at minimum length with requirements', () => {
516
- const result = schema.safeParse('Hello@12')
517
- expect(result.success).toBe(true)
518
- })
519
- })
520
-
521
- describe('refinement inheritance', () => {
522
- const baseSchema = integer({ minimum: 0, maximum: 1000 })
523
- const refinedOnce = refine(baseSchema, {
524
- check: (value) => value % 10 === 0,
525
- message: 'Must be divisible by 10',
526
- })
527
- const refinedTwice = refine(refinedOnce, {
528
- check: (value) => value % 100 === 0,
529
- message: 'Must be divisible by 100',
530
- })
531
-
532
- it('validates with all inherited constraints', () => {
533
- const result = refinedTwice.safeParse(500)
534
- expect(result.success).toBe(true)
535
- })
536
-
537
- it('rejects when failing base constraint', () => {
538
- const result = refinedTwice.safeParse(1500)
539
- expect(result.success).toBe(false)
540
- })
541
-
542
- it('rejects when failing first refinement', () => {
543
- const result = refinedTwice.safeParse(505)
544
- expect(result.success).toBe(false)
545
- })
546
-
547
- it('rejects when failing second refinement', () => {
548
- const result = refinedTwice.safeParse(50)
549
- expect(result.success).toBe(false)
550
- })
551
- })
552
-
553
- describe('refinement with string format validation', () => {
554
- const schema = refine(string({ format: 'uri' }), {
555
- check: (value) => value.startsWith('https://'),
556
- message: 'Must be HTTPS URI',
557
- })
558
-
559
- it('validates HTTPS URIs', () => {
560
- const result = schema.safeParse('https://example.com')
561
- expect(result.success).toBe(true)
562
- })
563
-
564
- it('rejects HTTP URIs', () => {
565
- const result = schema.safeParse('http://example.com')
566
- expect(result.success).toBe(false)
567
- })
568
-
569
- it('rejects other valid URIs', () => {
570
- const result = schema.safeParse('ftp://example.com')
571
- expect(result.success).toBe(false)
572
- })
573
-
574
- it('rejects invalid URIs', () => {
575
- const result = schema.safeParse('not a uri')
576
- expect(result.success).toBe(false)
577
- })
578
- })
579
- })