@atproto/lex-schema 0.0.9 → 0.0.11

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 (280) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE.txt +1 -1
  3. package/dist/core/$type.d.ts +11 -0
  4. package/dist/core/$type.d.ts.map +1 -1
  5. package/dist/core/$type.js +4 -0
  6. package/dist/core/$type.js.map +1 -1
  7. package/dist/core/schema.d.ts +31 -24
  8. package/dist/core/schema.d.ts.map +1 -1
  9. package/dist/core/schema.js +38 -8
  10. package/dist/core/schema.js.map +1 -1
  11. package/dist/core/string-format.d.ts +35 -35
  12. package/dist/core/string-format.d.ts.map +1 -1
  13. package/dist/core/string-format.js +49 -91
  14. package/dist/core/string-format.js.map +1 -1
  15. package/dist/core/validation-error.d.ts +1 -1
  16. package/dist/core/validation-issue.js +1 -1
  17. package/dist/core/validation-issue.js.map +1 -1
  18. package/dist/core/validator.d.ts +53 -32
  19. package/dist/core/validator.d.ts.map +1 -1
  20. package/dist/core/validator.js +18 -22
  21. package/dist/core/validator.js.map +1 -1
  22. package/dist/external.d.ts +0 -85
  23. package/dist/external.d.ts.map +1 -1
  24. package/dist/external.js +0 -164
  25. package/dist/external.js.map +1 -1
  26. package/dist/helpers.d.ts +13 -5
  27. package/dist/helpers.d.ts.map +1 -1
  28. package/dist/helpers.js +4 -4
  29. package/dist/helpers.js.map +1 -1
  30. package/dist/schema/array.d.ts +9 -5
  31. package/dist/schema/array.d.ts.map +1 -1
  32. package/dist/schema/array.js +14 -5
  33. package/dist/schema/array.js.map +1 -1
  34. package/dist/schema/blob.d.ts +9 -7
  35. package/dist/schema/blob.d.ts.map +1 -1
  36. package/dist/schema/blob.js +9 -5
  37. package/dist/schema/blob.js.map +1 -1
  38. package/dist/schema/boolean.d.ts +3 -7
  39. package/dist/schema/boolean.d.ts.map +1 -1
  40. package/dist/schema/boolean.js +6 -7
  41. package/dist/schema/boolean.js.map +1 -1
  42. package/dist/schema/bytes.d.ts +3 -2
  43. package/dist/schema/bytes.d.ts.map +1 -1
  44. package/dist/schema/bytes.js +7 -3
  45. package/dist/schema/bytes.js.map +1 -1
  46. package/dist/schema/cid.d.ts +7 -7
  47. package/dist/schema/cid.d.ts.map +1 -1
  48. package/dist/schema/cid.js +5 -1
  49. package/dist/schema/cid.js.map +1 -1
  50. package/dist/schema/custom.d.ts +6 -5
  51. package/dist/schema/custom.d.ts.map +1 -1
  52. package/dist/schema/custom.js +10 -4
  53. package/dist/schema/custom.js.map +1 -1
  54. package/dist/schema/dict.d.ts +8 -8
  55. package/dist/schema/dict.d.ts.map +1 -1
  56. package/dist/schema/dict.js +11 -2
  57. package/dist/schema/dict.js.map +1 -1
  58. package/dist/schema/discriminated-union.d.ts +21 -14
  59. package/dist/schema/discriminated-union.d.ts.map +1 -1
  60. package/dist/schema/discriminated-union.js +7 -0
  61. package/dist/schema/discriminated-union.js.map +1 -1
  62. package/dist/schema/enum.d.ts +7 -9
  63. package/dist/schema/enum.d.ts.map +1 -1
  64. package/dist/schema/enum.js +8 -4
  65. package/dist/schema/enum.js.map +1 -1
  66. package/dist/schema/integer.d.ts +5 -5
  67. package/dist/schema/integer.d.ts.map +1 -1
  68. package/dist/schema/integer.js +9 -5
  69. package/dist/schema/integer.js.map +1 -1
  70. package/dist/schema/intersection.d.ts +4 -4
  71. package/dist/schema/intersection.d.ts.map +1 -1
  72. package/dist/schema/intersection.js +5 -0
  73. package/dist/schema/intersection.js.map +1 -1
  74. package/dist/schema/literal.d.ts +6 -9
  75. package/dist/schema/literal.d.ts.map +1 -1
  76. package/dist/schema/literal.js +7 -4
  77. package/dist/schema/literal.js.map +1 -1
  78. package/dist/schema/never.d.ts +3 -2
  79. package/dist/schema/never.d.ts.map +1 -1
  80. package/dist/schema/never.js +5 -1
  81. package/dist/schema/never.js.map +1 -1
  82. package/dist/schema/null.d.ts +4 -3
  83. package/dist/schema/null.d.ts.map +1 -1
  84. package/dist/schema/null.js +6 -4
  85. package/dist/schema/null.js.map +1 -1
  86. package/dist/schema/nullable.d.ts +6 -5
  87. package/dist/schema/nullable.d.ts.map +1 -1
  88. package/dist/schema/nullable.js +9 -5
  89. package/dist/schema/nullable.js.map +1 -1
  90. package/dist/schema/object.d.ts +10 -8
  91. package/dist/schema/object.d.ts.map +1 -1
  92. package/dist/schema/object.js +11 -3
  93. package/dist/schema/object.js.map +1 -1
  94. package/dist/schema/optional.d.ts +7 -5
  95. package/dist/schema/optional.d.ts.map +1 -1
  96. package/dist/schema/optional.js +14 -6
  97. package/dist/schema/optional.js.map +1 -1
  98. package/dist/schema/params.d.ts +26 -13
  99. package/dist/schema/params.d.ts.map +1 -1
  100. package/dist/schema/params.js +47 -25
  101. package/dist/schema/params.js.map +1 -1
  102. package/dist/schema/payload.d.ts +12 -9
  103. package/dist/schema/payload.d.ts.map +1 -1
  104. package/dist/schema/payload.js +11 -0
  105. package/dist/schema/payload.js.map +1 -1
  106. package/dist/schema/permission-set.d.ts +1 -0
  107. package/dist/schema/permission-set.d.ts.map +1 -1
  108. package/dist/schema/permission-set.js +5 -0
  109. package/dist/schema/permission-set.js.map +1 -1
  110. package/dist/schema/permission.d.ts +6 -5
  111. package/dist/schema/permission.d.ts.map +1 -1
  112. package/dist/schema/permission.js +5 -0
  113. package/dist/schema/permission.js.map +1 -1
  114. package/dist/schema/procedure.d.ts +2 -1
  115. package/dist/schema/procedure.d.ts.map +1 -1
  116. package/dist/schema/procedure.js +5 -0
  117. package/dist/schema/procedure.js.map +1 -1
  118. package/dist/schema/query.d.ts +2 -1
  119. package/dist/schema/query.d.ts.map +1 -1
  120. package/dist/schema/query.js +5 -0
  121. package/dist/schema/query.js.map +1 -1
  122. package/dist/schema/record.d.ts +48 -30
  123. package/dist/schema/record.d.ts.map +1 -1
  124. package/dist/schema/record.js +12 -9
  125. package/dist/schema/record.js.map +1 -1
  126. package/dist/schema/ref.d.ts +9 -6
  127. package/dist/schema/ref.d.ts.map +1 -1
  128. package/dist/schema/ref.js +9 -16
  129. package/dist/schema/ref.js.map +1 -1
  130. package/dist/schema/refine.d.ts +4 -4
  131. package/dist/schema/refine.d.ts.map +1 -1
  132. package/dist/schema/refine.js.map +1 -1
  133. package/dist/schema/regexp.d.ts +4 -3
  134. package/dist/schema/regexp.d.ts.map +1 -1
  135. package/dist/schema/regexp.js +5 -0
  136. package/dist/schema/regexp.js.map +1 -1
  137. package/dist/schema/string.d.ts +7 -8
  138. package/dist/schema/string.d.ts.map +1 -1
  139. package/dist/schema/string.js +13 -19
  140. package/dist/schema/string.js.map +1 -1
  141. package/dist/schema/subscription.d.ts +2 -1
  142. package/dist/schema/subscription.d.ts.map +1 -1
  143. package/dist/schema/subscription.js +5 -0
  144. package/dist/schema/subscription.js.map +1 -1
  145. package/dist/schema/token.d.ts +6 -5
  146. package/dist/schema/token.d.ts.map +1 -1
  147. package/dist/schema/token.js +5 -0
  148. package/dist/schema/token.js.map +1 -1
  149. package/dist/schema/typed-object.d.ts +43 -26
  150. package/dist/schema/typed-object.d.ts.map +1 -1
  151. package/dist/schema/typed-object.js +6 -3
  152. package/dist/schema/typed-object.js.map +1 -1
  153. package/dist/schema/typed-ref.d.ts +16 -25
  154. package/dist/schema/typed-ref.d.ts.map +1 -1
  155. package/dist/schema/typed-ref.js +7 -17
  156. package/dist/schema/typed-ref.js.map +1 -1
  157. package/dist/schema/typed-union.d.ts +9 -21
  158. package/dist/schema/typed-union.d.ts.map +1 -1
  159. package/dist/schema/typed-union.js +15 -11
  160. package/dist/schema/typed-union.js.map +1 -1
  161. package/dist/schema/union.d.ts +6 -6
  162. package/dist/schema/union.d.ts.map +1 -1
  163. package/dist/schema/union.js +7 -5
  164. package/dist/schema/union.js.map +1 -1
  165. package/dist/schema/unknown-object.d.ts +5 -4
  166. package/dist/schema/unknown-object.d.ts.map +1 -1
  167. package/dist/schema/unknown-object.js +5 -1
  168. package/dist/schema/unknown-object.js.map +1 -1
  169. package/dist/schema/unknown.d.ts +3 -2
  170. package/dist/schema/unknown.d.ts.map +1 -1
  171. package/dist/schema/unknown.js +5 -1
  172. package/dist/schema/unknown.js.map +1 -1
  173. package/dist/schema/with-default.d.ts +9 -0
  174. package/dist/schema/with-default.d.ts.map +1 -0
  175. package/dist/schema/with-default.js +27 -0
  176. package/dist/schema/with-default.js.map +1 -0
  177. package/dist/schema.d.ts +2 -2
  178. package/dist/schema.d.ts.map +1 -1
  179. package/dist/schema.js +2 -4
  180. package/dist/schema.js.map +1 -1
  181. package/dist/util/assertion-util.d.ts +0 -6
  182. package/dist/util/assertion-util.d.ts.map +1 -1
  183. package/dist/util/assertion-util.js +0 -28
  184. package/dist/util/assertion-util.js.map +1 -1
  185. package/dist/util/memoize.d.ts +2 -2
  186. package/dist/util/memoize.d.ts.map +1 -1
  187. package/dist/util/memoize.js +23 -39
  188. package/dist/util/memoize.js.map +1 -1
  189. package/package.json +3 -3
  190. package/src/core/$type.test.ts +20 -0
  191. package/src/core/$type.ts +30 -0
  192. package/src/core/schema.ts +86 -38
  193. package/src/core/string-format.ts +119 -158
  194. package/src/core/validation-issue.ts +1 -1
  195. package/src/core/validator.ts +93 -53
  196. package/src/external.ts +0 -404
  197. package/src/helpers.test.ts +22 -21
  198. package/src/helpers.ts +19 -14
  199. package/src/schema/array.test.ts +38 -40
  200. package/src/schema/array.ts +35 -13
  201. package/src/schema/blob.test.ts +21 -21
  202. package/src/schema/blob.ts +19 -17
  203. package/src/schema/boolean.test.ts +9 -8
  204. package/src/schema/boolean.ts +7 -13
  205. package/src/schema/bytes.test.ts +13 -13
  206. package/src/schema/bytes.ts +13 -8
  207. package/src/schema/cid.test.ts +3 -3
  208. package/src/schema/cid.ts +13 -12
  209. package/src/schema/custom.test.ts +26 -26
  210. package/src/schema/custom.ts +20 -13
  211. package/src/schema/dict.test.ts +21 -39
  212. package/src/schema/dict.ts +28 -19
  213. package/src/schema/discriminated-union.test.ts +128 -128
  214. package/src/schema/discriminated-union.ts +45 -26
  215. package/src/schema/enum.test.ts +17 -16
  216. package/src/schema/enum.ts +16 -16
  217. package/src/schema/integer.test.ts +22 -21
  218. package/src/schema/integer.ts +12 -9
  219. package/src/schema/intersection.test.ts +10 -10
  220. package/src/schema/intersection.ts +17 -14
  221. package/src/schema/literal.test.ts +35 -34
  222. package/src/schema/literal.ts +12 -15
  223. package/src/schema/never.test.ts +5 -5
  224. package/src/schema/never.ts +7 -2
  225. package/src/schema/null.test.ts +3 -3
  226. package/src/schema/null.ts +9 -9
  227. package/src/schema/nullable.test.ts +31 -42
  228. package/src/schema/nullable.ts +17 -9
  229. package/src/schema/object.test.ts +10 -12
  230. package/src/schema/object.ts +27 -18
  231. package/src/schema/optional.test.ts +21 -28
  232. package/src/schema/optional.ts +27 -10
  233. package/src/schema/params.test.ts +471 -47
  234. package/src/schema/params.ts +74 -38
  235. package/src/schema/payload.test.ts +150 -156
  236. package/src/schema/payload.ts +35 -19
  237. package/src/schema/permission-set.test.ts +206 -273
  238. package/src/schema/permission-set.ts +8 -0
  239. package/src/schema/permission.test.ts +177 -177
  240. package/src/schema/permission.ts +13 -5
  241. package/src/schema/procedure.test.ts +183 -242
  242. package/src/schema/procedure.ts +18 -5
  243. package/src/schema/query.test.ts +186 -200
  244. package/src/schema/query.ts +16 -4
  245. package/src/schema/record.test.ts +121 -101
  246. package/src/schema/record.ts +74 -40
  247. package/src/schema/ref.test.ts +101 -118
  248. package/src/schema/ref.ts +33 -28
  249. package/src/schema/refine.test.ts +28 -28
  250. package/src/schema/refine.ts +23 -20
  251. package/src/schema/regexp.test.ts +29 -33
  252. package/src/schema/regexp.ts +11 -7
  253. package/src/schema/string.test.ts +35 -35
  254. package/src/schema/string.ts +24 -33
  255. package/src/schema/subscription.test.ts +259 -387
  256. package/src/schema/subscription.ts +16 -4
  257. package/src/schema/token.test.ts +47 -324
  258. package/src/schema/token.ts +14 -7
  259. package/src/schema/typed-object.test.ts +98 -81
  260. package/src/schema/typed-object.ts +68 -33
  261. package/src/schema/typed-ref.test.ts +206 -234
  262. package/src/schema/typed-ref.ts +40 -42
  263. package/src/schema/typed-union.test.ts +40 -64
  264. package/src/schema/typed-union.ts +36 -58
  265. package/src/schema/union.test.ts +17 -27
  266. package/src/schema/union.ts +20 -16
  267. package/src/schema/unknown-object.test.ts +8 -8
  268. package/src/schema/unknown-object.ts +9 -7
  269. package/src/schema/unknown.test.ts +4 -4
  270. package/src/schema/unknown.ts +7 -5
  271. package/src/schema/with-default.ts +35 -0
  272. package/src/schema.ts +2 -6
  273. package/src/util/assertion-util.ts +0 -39
  274. package/src/util/memoize.ts +26 -46
  275. package/dist/schema/_parameters.d.ts +0 -17
  276. package/dist/schema/_parameters.d.ts.map +0 -1
  277. package/dist/schema/_parameters.js +0 -20
  278. package/dist/schema/_parameters.js.map +0 -1
  279. package/src/schema/_parameters.test.ts +0 -417
  280. package/src/schema/_parameters.ts +0 -26
@@ -1,12 +1,12 @@
1
1
  import { describe, expect, it } from 'vitest'
2
- import { IntegerSchema } from './integer.js'
3
- import { ObjectSchema } from './object.js'
2
+ import { integer } from './integer.js'
3
+ import { object } from './object.js'
4
4
  import { refine } from './refine.js'
5
- import { StringSchema } from './string.js'
5
+ import { string } from './string.js'
6
6
 
7
7
  describe('refine', () => {
8
8
  describe('basic refinement checks', () => {
9
- const schema = refine(new IntegerSchema({}), {
9
+ const schema = refine(integer(), {
10
10
  check: (value) => value > 0,
11
11
  message: 'Value must be positive',
12
12
  })
@@ -33,7 +33,7 @@ describe('refine', () => {
33
33
  })
34
34
 
35
35
  describe('refinement with type assertions', () => {
36
- const schema = refine(new IntegerSchema({}), {
36
+ const schema = refine(integer(), {
37
37
  check: (value): value is 42 => value === 42,
38
38
  message: 'Value must be 42',
39
39
  })
@@ -50,7 +50,7 @@ describe('refine', () => {
50
50
  })
51
51
 
52
52
  describe('refinement with string schema', () => {
53
- const schema = refine(new StringSchema({}), {
53
+ const schema = refine(string(), {
54
54
  check: (value) => value.includes('@'),
55
55
  message: 'String must contain @ symbol',
56
56
  })
@@ -72,7 +72,7 @@ describe('refine', () => {
72
72
  })
73
73
 
74
74
  describe('refinement with base schema constraints', () => {
75
- const schema = refine(new IntegerSchema({ minimum: 0, maximum: 100 }), {
75
+ const schema = refine(integer({ minimum: 0, maximum: 100 }), {
76
76
  check: (value) => value % 2 === 0,
77
77
  message: 'Value must be even',
78
78
  })
@@ -100,7 +100,7 @@ describe('refine', () => {
100
100
 
101
101
  describe('multiple refinements chained', () => {
102
102
  const schema = refine(
103
- refine(new IntegerSchema({}), {
103
+ refine(integer(), {
104
104
  check: (value) => value > 0,
105
105
  message: 'Value must be positive',
106
106
  }),
@@ -135,7 +135,7 @@ describe('refine', () => {
135
135
  })
136
136
 
137
137
  describe('refinement with custom path', () => {
138
- const schema = refine(new IntegerSchema({}), {
138
+ const schema = refine(integer(), {
139
139
  check: (value) => value > 0,
140
140
  message: 'Value must be positive',
141
141
  path: 'customField',
@@ -153,7 +153,7 @@ describe('refine', () => {
153
153
  })
154
154
 
155
155
  describe('refinement with array path', () => {
156
- const schema = refine(new IntegerSchema({}), {
156
+ const schema = refine(integer(), {
157
157
  check: (value) => value > 0,
158
158
  message: 'Value must be positive',
159
159
  path: ['nested', 'field'],
@@ -171,12 +171,12 @@ describe('refine', () => {
171
171
  })
172
172
 
173
173
  describe('refinement on object properties', () => {
174
- const schema = new ObjectSchema({
175
- age: refine(new IntegerSchema({}), {
174
+ const schema = object({
175
+ age: refine(integer(), {
176
176
  check: (value) => value >= 18,
177
177
  message: 'Age must be at least 18',
178
178
  }),
179
- email: refine(new StringSchema({}), {
179
+ email: refine(string(), {
180
180
  check: (value) => value.includes('@'),
181
181
  message: 'Email must contain @ symbol',
182
182
  }),
@@ -216,7 +216,7 @@ describe('refine', () => {
216
216
  })
217
217
 
218
218
  describe('complex refinement logic', () => {
219
- const schema = refine(new StringSchema({}), {
219
+ const schema = refine(string(), {
220
220
  check: (value) => {
221
221
  const hasLowerCase = /[a-z]/.test(value)
222
222
  const hasUpperCase = /[A-Z]/.test(value)
@@ -253,7 +253,7 @@ describe('refine', () => {
253
253
  })
254
254
 
255
255
  describe('refinement with comparison logic', () => {
256
- const schema = refine(new IntegerSchema({}), {
256
+ const schema = refine(integer(), {
257
257
  check: (value) => {
258
258
  // Check if value is a prime number
259
259
  if (value <= 1) return false
@@ -285,7 +285,7 @@ describe('refine', () => {
285
285
  })
286
286
 
287
287
  describe('refinement with string length logic', () => {
288
- const schema = refine(new StringSchema({ minLength: 1, maxLength: 50 }), {
288
+ const schema = refine(string({ minLength: 1, maxLength: 50 }), {
289
289
  check: (value) => value.trim().length > 0,
290
290
  message: 'String must not be only whitespace',
291
291
  })
@@ -317,7 +317,7 @@ describe('refine', () => {
317
317
  })
318
318
 
319
319
  describe('refinement preserves original schema', () => {
320
- const originalSchema = new IntegerSchema({ minimum: 0 })
320
+ const originalSchema = integer({ minimum: 0 })
321
321
  const refinedSchema = refine(originalSchema, {
322
322
  check: (value) => value % 2 === 0,
323
323
  message: 'Value must be even',
@@ -343,7 +343,7 @@ describe('refine', () => {
343
343
  })
344
344
 
345
345
  describe('refinement with boundary conditions', () => {
346
- const schema = refine(new IntegerSchema({ minimum: 0, maximum: 100 }), {
346
+ const schema = refine(integer({ minimum: 0, maximum: 100 }), {
347
347
  check: (value) => value !== 50,
348
348
  message: 'Value must not be 50',
349
349
  })
@@ -373,7 +373,7 @@ describe('refine', () => {
373
373
  })
374
374
 
375
375
  describe('refinement with regex patterns', () => {
376
- const schema = refine(new StringSchema({}), {
376
+ const schema = refine(string(), {
377
377
  check: (value) => /^[A-Z][a-zA-Z0-9]*$/.test(value),
378
378
  message: 'Must start with uppercase letter',
379
379
  })
@@ -405,7 +405,7 @@ describe('refine', () => {
405
405
  })
406
406
 
407
407
  describe('refinement with custom error messages', () => {
408
- const schema = refine(new IntegerSchema({}), {
408
+ const schema = refine(integer(), {
409
409
  check: (value) => value >= 1 && value <= 10,
410
410
  message: 'Value must be between 1 and 10 (inclusive)',
411
411
  })
@@ -428,7 +428,7 @@ describe('refine', () => {
428
428
 
429
429
  describe('edge cases', () => {
430
430
  it('handles refinement that always returns true', () => {
431
- const schema = refine(new IntegerSchema({}), {
431
+ const schema = refine(integer(), {
432
432
  check: () => true,
433
433
  message: 'This should never fail',
434
434
  })
@@ -437,7 +437,7 @@ describe('refine', () => {
437
437
  })
438
438
 
439
439
  it('handles refinement that always returns false', () => {
440
- const schema = refine(new IntegerSchema({}), {
440
+ const schema = refine(integer(), {
441
441
  check: () => false,
442
442
  message: 'This always fails',
443
443
  })
@@ -446,7 +446,7 @@ describe('refine', () => {
446
446
  })
447
447
 
448
448
  it('handles empty string refinement', () => {
449
- const schema = refine(new StringSchema({}), {
449
+ const schema = refine(string(), {
450
450
  check: (value) => value === '',
451
451
  message: 'Value must be empty string',
452
452
  })
@@ -458,7 +458,7 @@ describe('refine', () => {
458
458
  })
459
459
 
460
460
  it('handles zero value refinement', () => {
461
- const schema = refine(new IntegerSchema({}), {
461
+ const schema = refine(integer(), {
462
462
  check: (value) => value === 0,
463
463
  message: 'Value must be zero',
464
464
  })
@@ -470,7 +470,7 @@ describe('refine', () => {
470
470
  })
471
471
 
472
472
  it('handles negative value refinement', () => {
473
- const schema = refine(new IntegerSchema({}), {
473
+ const schema = refine(integer(), {
474
474
  check: (value) => value < 0,
475
475
  message: 'Value must be negative',
476
476
  })
@@ -483,7 +483,7 @@ describe('refine', () => {
483
483
  })
484
484
 
485
485
  describe('refinement with combined string constraints', () => {
486
- const schema = refine(new StringSchema({ minLength: 8, maxLength: 20 }), {
486
+ const schema = refine(string({ minLength: 8, maxLength: 20 }), {
487
487
  check: (value) => {
488
488
  const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value)
489
489
  const hasLetter = /[a-zA-Z]/.test(value)
@@ -519,7 +519,7 @@ describe('refine', () => {
519
519
  })
520
520
 
521
521
  describe('refinement inheritance', () => {
522
- const baseSchema = new IntegerSchema({ minimum: 0, maximum: 1000 })
522
+ const baseSchema = integer({ minimum: 0, maximum: 1000 })
523
523
  const refinedOnce = refine(baseSchema, {
524
524
  check: (value) => value % 10 === 0,
525
525
  message: 'Must be divisible by 10',
@@ -551,7 +551,7 @@ describe('refine', () => {
551
551
  })
552
552
 
553
553
  describe('refinement with string format validation', () => {
554
- const schema = refine(new StringSchema({ format: 'uri' }), {
554
+ const schema = refine(string({ format: 'uri' }), {
555
555
  check: (value) => value.startsWith('https://'),
556
556
  message: 'Must be HTTPS URI',
557
557
  })
@@ -1,10 +1,10 @@
1
1
  import {
2
- Infer,
2
+ InferInput,
3
3
  IssueCustom,
4
4
  PropertyKey,
5
+ ValidationContext,
5
6
  ValidationResult,
6
7
  Validator,
7
- ValidatorContext,
8
8
  } from '../core.js'
9
9
  import { CustomAssertionContext } from './custom.js'
10
10
 
@@ -48,23 +48,26 @@ export type Refinement<T = any, Out extends T = T> =
48
48
  * // result.success === false
49
49
  * ```
50
50
  */
51
- export function refine<S extends Validator, Out extends Infer<S>>(
52
- schema: S,
53
- refinement: RefinementAssertion<Infer<S>, Out>,
54
- ): S & Validator<Out>
55
- export function refine<S extends Validator>(
56
- schema: S,
57
- refinement: RefinementCheck<Infer<S>>,
58
- ): S
59
51
  export function refine<
60
- R extends Refinement,
61
- S extends Validator<InferRefinement<R>>,
62
- >(schema: S, refinement: R): S
52
+ const TValidator extends Validator,
53
+ TInput extends InferInput<TValidator>,
54
+ >(
55
+ schema: TValidator,
56
+ refinement: RefinementAssertion<InferInput<TValidator>, TInput>,
57
+ ): TValidator & Validator<TInput>
58
+ export function refine<const TValidator extends Validator>(
59
+ schema: TValidator,
60
+ refinement: RefinementCheck<InferInput<TValidator>>,
61
+ ): TValidator
62
+ export function refine<
63
+ TRefinement extends Refinement,
64
+ const TValidator extends Validator<InferRefinement<TRefinement>>,
65
+ >(schema: TValidator, refinement: TRefinement): TValidator
63
66
  /*@__NO_SIDE_EFFECTS__*/
64
- export function refine<S extends Validator>(
65
- schema: S,
66
- refinement: Refinement<Infer<S>>,
67
- ): S {
67
+ export function refine<const TValidator extends Validator>(
68
+ schema: TValidator,
69
+ refinement: Refinement<unknown>,
70
+ ): TValidator {
68
71
  // This is basically the same as monkey patching the "validateInContext"
69
72
  // method to the schema, but done in a way that does not mutate the original
70
73
  // schema. This is safe to do because Validators don't update their internal
@@ -84,11 +87,11 @@ export function refine<S extends Validator>(
84
87
  function validateInContextUnbound<S extends Validator>(
85
88
  this: {
86
89
  schema: S
87
- refinement: Refinement<Infer<S>>
90
+ refinement: Refinement<InferInput<S>>
88
91
  },
89
92
  input: unknown,
90
- ctx: ValidatorContext,
91
- ): ValidationResult<Infer<S>> {
93
+ ctx: ValidationContext,
94
+ ): ValidationResult<InferInput<S>> {
92
95
  const result = ctx.validate(input, this.schema)
93
96
  if (!result.success) return result
94
97
 
@@ -1,9 +1,9 @@
1
1
  import { describe, expect, it } from 'vitest'
2
- import { RegexpSchema } from './regexp.js'
2
+ import { regexp } from './regexp.js'
3
3
 
4
4
  describe('RegexpSchema', () => {
5
5
  describe('basic validation', () => {
6
- const schema = new RegexpSchema(/^[a-z]+$/)
6
+ const schema = regexp(/^[a-z]+$/)
7
7
 
8
8
  it('validates strings matching the pattern', () => {
9
9
  const result = schema.safeParse('hello')
@@ -57,7 +57,7 @@ describe('RegexpSchema', () => {
57
57
  })
58
58
 
59
59
  describe('numeric patterns', () => {
60
- const schema = new RegexpSchema(/^\d+$/)
60
+ const schema = regexp(/^\d+$/)
61
61
 
62
62
  it('validates numeric strings', () => {
63
63
  const result = schema.safeParse('12345')
@@ -81,9 +81,7 @@ describe('RegexpSchema', () => {
81
81
  })
82
82
 
83
83
  describe('email pattern', () => {
84
- const schema = new RegexpSchema(
85
- /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
86
- )
84
+ const schema = regexp(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)
87
85
 
88
86
  it('validates simple email addresses', () => {
89
87
  const result = schema.safeParse('user@example.com')
@@ -117,7 +115,7 @@ describe('RegexpSchema', () => {
117
115
  })
118
116
 
119
117
  describe('URL pattern', () => {
120
- const schema = new RegexpSchema(/^https?:\/\/[^\s/$.?#].[^\s]*$/)
118
+ const schema = regexp(/^https?:\/\/[^\s/$.?#].[^\s]*$/)
121
119
 
122
120
  it('validates HTTP URLs', () => {
123
121
  const result = schema.safeParse('http://example.com')
@@ -151,7 +149,7 @@ describe('RegexpSchema', () => {
151
149
  })
152
150
 
153
151
  describe('phone number pattern', () => {
154
- const schema = new RegexpSchema(/^\+?[1-9]\d{1,14}$/)
152
+ const schema = regexp(/^\+?[1-9]\d{1,14}$/)
155
153
 
156
154
  it('validates simple phone numbers', () => {
157
155
  const result = schema.safeParse('1234567890')
@@ -185,7 +183,7 @@ describe('RegexpSchema', () => {
185
183
  })
186
184
 
187
185
  describe('hex color pattern', () => {
188
- const schema = new RegexpSchema(/^#[0-9A-Fa-f]{6}$/)
186
+ const schema = regexp(/^#[0-9A-Fa-f]{6}$/)
189
187
 
190
188
  it('validates 6-digit hex colors', () => {
191
189
  const result = schema.safeParse('#FF5733')
@@ -219,7 +217,7 @@ describe('RegexpSchema', () => {
219
217
  })
220
218
 
221
219
  describe('alphanumeric pattern', () => {
222
- const schema = new RegexpSchema(/^[a-zA-Z0-9]+$/)
220
+ const schema = regexp(/^[a-zA-Z0-9]+$/)
223
221
 
224
222
  it('validates alphanumeric strings', () => {
225
223
  const result = schema.safeParse('abc123')
@@ -253,7 +251,7 @@ describe('RegexpSchema', () => {
253
251
  })
254
252
 
255
253
  describe('case-insensitive pattern', () => {
256
- const schema = new RegexpSchema(/^hello$/i)
254
+ const schema = regexp(/^hello$/i)
257
255
 
258
256
  it('validates lowercase match', () => {
259
257
  const result = schema.safeParse('hello')
@@ -277,7 +275,7 @@ describe('RegexpSchema', () => {
277
275
  })
278
276
 
279
277
  describe('multiline pattern', () => {
280
- const schema = new RegexpSchema(/^line\d+$/m)
278
+ const schema = regexp(/^line\d+$/m)
281
279
 
282
280
  it('validates single line matching pattern', () => {
283
281
  const result = schema.safeParse('line1')
@@ -296,7 +294,7 @@ describe('RegexpSchema', () => {
296
294
  })
297
295
 
298
296
  describe('optional character pattern', () => {
299
- const schema = new RegexpSchema(/^colou?r$/)
297
+ const schema = regexp(/^colou?r$/)
300
298
 
301
299
  it('validates with optional character present', () => {
302
300
  const result = schema.safeParse('colour')
@@ -315,7 +313,7 @@ describe('RegexpSchema', () => {
315
313
  })
316
314
 
317
315
  describe('character range pattern', () => {
318
- const schema = new RegexpSchema(/^[0-5]+$/)
316
+ const schema = regexp(/^[0-5]+$/)
319
317
 
320
318
  it('validates strings within range', () => {
321
319
  const result = schema.safeParse('012345')
@@ -334,7 +332,7 @@ describe('RegexpSchema', () => {
334
332
  })
335
333
 
336
334
  describe('quantifier pattern', () => {
337
- const schema = new RegexpSchema(/^a{3}$/)
335
+ const schema = regexp(/^a{3}$/)
338
336
 
339
337
  it('validates exact repetition count', () => {
340
338
  const result = schema.safeParse('aaa')
@@ -353,7 +351,7 @@ describe('RegexpSchema', () => {
353
351
  })
354
352
 
355
353
  describe('range quantifier pattern', () => {
356
- const schema = new RegexpSchema(/^a{2,4}$/)
354
+ const schema = regexp(/^a{2,4}$/)
357
355
 
358
356
  it('validates minimum repetition count', () => {
359
357
  const result = schema.safeParse('aa')
@@ -382,7 +380,7 @@ describe('RegexpSchema', () => {
382
380
  })
383
381
 
384
382
  describe('alternation pattern', () => {
385
- const schema = new RegexpSchema(/^(cat|dog|bird)$/)
383
+ const schema = regexp(/^(cat|dog|bird)$/)
386
384
 
387
385
  it('validates first alternative', () => {
388
386
  const result = schema.safeParse('cat')
@@ -406,7 +404,7 @@ describe('RegexpSchema', () => {
406
404
  })
407
405
 
408
406
  describe('word boundary pattern', () => {
409
- const schema = new RegexpSchema(/\bword\b/)
407
+ const schema = regexp(/\bword\b/)
410
408
 
411
409
  it('validates word with boundaries', () => {
412
410
  const result = schema.safeParse('word')
@@ -425,7 +423,7 @@ describe('RegexpSchema', () => {
425
423
  })
426
424
 
427
425
  describe('lookahead pattern', () => {
428
- const schema = new RegexpSchema(/^(?=.*[A-Z])(?=.*[0-9]).{8,}$/)
426
+ const schema = regexp(/^(?=.*[A-Z])(?=.*[0-9]).{8,}$/)
429
427
 
430
428
  it('validates string meeting all lookahead conditions', () => {
431
429
  const result = schema.safeParse('Password1')
@@ -454,7 +452,7 @@ describe('RegexpSchema', () => {
454
452
  })
455
453
 
456
454
  describe('unicode pattern', () => {
457
- const schema = new RegexpSchema(/^[\u4e00-\u9fa5]+$/)
455
+ const schema = regexp(/^[\u4e00-\u9fa5]+$/)
458
456
 
459
457
  it('validates Chinese characters', () => {
460
458
  const result = schema.safeParse('你好')
@@ -478,7 +476,7 @@ describe('RegexpSchema', () => {
478
476
  })
479
477
 
480
478
  describe('empty string pattern', () => {
481
- const schema = new RegexpSchema(/^$/)
479
+ const schema = regexp(/^$/)
482
480
 
483
481
  it('validates empty strings', () => {
484
482
  const result = schema.safeParse('')
@@ -497,7 +495,7 @@ describe('RegexpSchema', () => {
497
495
  })
498
496
 
499
497
  describe('wildcard pattern', () => {
500
- const schema = new RegexpSchema(/^.*$/)
498
+ const schema = regexp(/^.*$/)
501
499
 
502
500
  it('validates empty strings', () => {
503
501
  const result = schema.safeParse('')
@@ -522,58 +520,56 @@ describe('RegexpSchema', () => {
522
520
 
523
521
  describe('edge cases', () => {
524
522
  it('handles pattern with escape sequences', () => {
525
- const schema = new RegexpSchema(/^\d{3}\.\d{3}\.\d{3}\.\d{3}$/)
523
+ const schema = regexp(/^\d{3}\.\d{3}\.\d{3}\.\d{3}$/)
526
524
  const result = schema.safeParse('192.168.001.001')
527
525
  expect(result.success).toBe(true)
528
526
  })
529
527
 
530
528
  it('handles pattern with special regex characters', () => {
531
- const schema = new RegexpSchema(/^\$\d+\.\d{2}$/)
529
+ const schema = regexp(/^\$\d+\.\d{2}$/)
532
530
  const result = schema.safeParse('$99.99')
533
531
  expect(result.success).toBe(true)
534
532
  })
535
533
 
536
534
  it('handles very long strings', () => {
537
- const schema = new RegexpSchema(/^[a-z]+$/)
535
+ const schema = regexp(/^[a-z]+$/)
538
536
  const longString = 'a'.repeat(10000)
539
537
  const result = schema.safeParse(longString)
540
538
  expect(result.success).toBe(true)
541
539
  })
542
540
 
543
541
  it('handles strings with newlines', () => {
544
- const schema = new RegexpSchema(/^hello\nworld$/)
542
+ const schema = regexp(/^hello\nworld$/)
545
543
  const result = schema.safeParse('hello\nworld')
546
544
  expect(result.success).toBe(true)
547
545
  })
548
546
 
549
547
  it('handles strings with tabs', () => {
550
- const schema = new RegexpSchema(/^hello\tworld$/)
548
+ const schema = regexp(/^hello\tworld$/)
551
549
  const result = schema.safeParse('hello\tworld')
552
550
  expect(result.success).toBe(true)
553
551
  })
554
552
 
555
553
  it('handles emoji patterns', () => {
556
- const schema = new RegexpSchema(/^[\u{1F600}-\u{1F64F}]+$/u)
554
+ const schema = regexp(/^[\u{1F600}-\u{1F64F}]+$/u)
557
555
  const result = schema.safeParse('😀😃😄')
558
556
  expect(result.success).toBe(true)
559
557
  })
560
558
 
561
559
  it('handles global flag in pattern', () => {
562
- const schema = new RegexpSchema(/test/g)
560
+ const schema = regexp(/test/g)
563
561
  const result = schema.safeParse('test')
564
562
  expect(result.success).toBe(true)
565
563
  })
566
564
 
567
565
  it('handles pattern matching anywhere in string', () => {
568
- const schema = new RegexpSchema(/test/)
566
+ const schema = regexp(/test/)
569
567
  const result = schema.safeParse('this is a test string')
570
568
  expect(result.success).toBe(true)
571
569
  })
572
570
 
573
571
  it('handles complex nested groups', () => {
574
- const schema = new RegexpSchema(
575
- /^((https?|ftp):\/\/)?([a-z0-9]+\.)+[a-z]{2,}$/,
576
- )
572
+ const schema = regexp(/^((https?|ftp):\/\/)?([a-z0-9]+\.)+[a-z]{2,}$/)
577
573
  const result = schema.safeParse('https://example.com')
578
574
  expect(result.success).toBe(true)
579
575
  })
@@ -1,14 +1,13 @@
1
- import { Schema, ValidationResult, ValidatorContext } from '../core.js'
1
+ import { Schema, ValidationContext } from '../core.js'
2
2
 
3
- export class RegexpSchema<T extends string> extends Schema<T> {
3
+ export class RegexpSchema<
4
+ TValue extends string = string,
5
+ > extends Schema<TValue> {
4
6
  constructor(public readonly pattern: RegExp) {
5
7
  super()
6
8
  }
7
9
 
8
- validateInContext(
9
- input: unknown,
10
- ctx: ValidatorContext,
11
- ): ValidationResult<T> {
10
+ validateInContext(input: unknown, ctx: ValidationContext) {
12
11
  if (typeof input !== 'string') {
13
12
  return ctx.issueInvalidType(input, 'string')
14
13
  }
@@ -17,6 +16,11 @@ export class RegexpSchema<T extends string> extends Schema<T> {
17
16
  return ctx.issueInvalidFormat(input, this.pattern.toString())
18
17
  }
19
18
 
20
- return ctx.success(input as T)
19
+ return ctx.success(input as TValue)
21
20
  }
22
21
  }
22
+
23
+ /*@__NO_SIDE_EFFECTS__*/
24
+ export function regexp<TInput extends string = string>(pattern: RegExp) {
25
+ return new RegexpSchema<TInput>(pattern)
26
+ }