@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,577 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { regexp } from './regexp.js'
3
-
4
- describe('RegexpSchema', () => {
5
- describe('basic validation', () => {
6
- const schema = regexp(/^[a-z]+$/)
7
-
8
- it('validates strings matching the pattern', () => {
9
- const result = schema.safeParse('hello')
10
- expect(result.success).toBe(true)
11
- })
12
-
13
- it('validates strings with different matching values', () => {
14
- const result = schema.safeParse('world')
15
- expect(result.success).toBe(true)
16
- })
17
-
18
- it('rejects strings not matching the pattern', () => {
19
- const result = schema.safeParse('Hello')
20
- expect(result.success).toBe(false)
21
- })
22
-
23
- it('rejects strings with numbers when pattern requires letters', () => {
24
- const result = schema.safeParse('hello123')
25
- expect(result.success).toBe(false)
26
- })
27
-
28
- it('rejects non-strings', () => {
29
- const result = schema.safeParse(123)
30
- expect(result.success).toBe(false)
31
- })
32
-
33
- it('rejects null', () => {
34
- const result = schema.safeParse(null)
35
- expect(result.success).toBe(false)
36
- })
37
-
38
- it('rejects undefined', () => {
39
- const result = schema.safeParse(undefined)
40
- expect(result.success).toBe(false)
41
- })
42
-
43
- it('rejects booleans', () => {
44
- const result = schema.safeParse(true)
45
- expect(result.success).toBe(false)
46
- })
47
-
48
- it('rejects arrays', () => {
49
- const result = schema.safeParse(['hello'])
50
- expect(result.success).toBe(false)
51
- })
52
-
53
- it('rejects plain objects', () => {
54
- const result = schema.safeParse({ value: 'hello' })
55
- expect(result.success).toBe(false)
56
- })
57
- })
58
-
59
- describe('numeric patterns', () => {
60
- const schema = regexp(/^\d+$/)
61
-
62
- it('validates numeric strings', () => {
63
- const result = schema.safeParse('12345')
64
- expect(result.success).toBe(true)
65
- })
66
-
67
- it('validates single digit strings', () => {
68
- const result = schema.safeParse('0')
69
- expect(result.success).toBe(true)
70
- })
71
-
72
- it('rejects strings with letters', () => {
73
- const result = schema.safeParse('123abc')
74
- expect(result.success).toBe(false)
75
- })
76
-
77
- it('rejects empty strings', () => {
78
- const result = schema.safeParse('')
79
- expect(result.success).toBe(false)
80
- })
81
- })
82
-
83
- describe('email pattern', () => {
84
- const schema = regexp(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/)
85
-
86
- it('validates simple email addresses', () => {
87
- const result = schema.safeParse('user@example.com')
88
- expect(result.success).toBe(true)
89
- })
90
-
91
- it('validates email with subdomain', () => {
92
- const result = schema.safeParse('user@mail.example.com')
93
- expect(result.success).toBe(true)
94
- })
95
-
96
- it('validates email with numbers and special characters', () => {
97
- const result = schema.safeParse('user.name+tag@example.com')
98
- expect(result.success).toBe(true)
99
- })
100
-
101
- it('rejects email without @', () => {
102
- const result = schema.safeParse('userexample.com')
103
- expect(result.success).toBe(false)
104
- })
105
-
106
- it('rejects email without domain', () => {
107
- const result = schema.safeParse('user@')
108
- expect(result.success).toBe(false)
109
- })
110
-
111
- it('rejects email without TLD', () => {
112
- const result = schema.safeParse('user@example')
113
- expect(result.success).toBe(false)
114
- })
115
- })
116
-
117
- describe('URL pattern', () => {
118
- const schema = regexp(/^https?:\/\/[^\s/$.?#].[^\s]*$/)
119
-
120
- it('validates HTTP URLs', () => {
121
- const result = schema.safeParse('http://example.com')
122
- expect(result.success).toBe(true)
123
- })
124
-
125
- it('validates HTTPS URLs', () => {
126
- const result = schema.safeParse('https://example.com')
127
- expect(result.success).toBe(true)
128
- })
129
-
130
- it('validates URLs with paths', () => {
131
- const result = schema.safeParse('https://example.com/path/to/resource')
132
- expect(result.success).toBe(true)
133
- })
134
-
135
- it('validates URLs with query parameters', () => {
136
- const result = schema.safeParse('https://example.com?param=value')
137
- expect(result.success).toBe(true)
138
- })
139
-
140
- it('rejects URLs without protocol', () => {
141
- const result = schema.safeParse('example.com')
142
- expect(result.success).toBe(false)
143
- })
144
-
145
- it('rejects URLs with spaces', () => {
146
- const result = schema.safeParse('https://example.com/path with spaces')
147
- expect(result.success).toBe(false)
148
- })
149
- })
150
-
151
- describe('phone number pattern', () => {
152
- const schema = regexp(/^\+?[1-9]\d{1,14}$/)
153
-
154
- it('validates simple phone numbers', () => {
155
- const result = schema.safeParse('1234567890')
156
- expect(result.success).toBe(true)
157
- })
158
-
159
- it('validates phone numbers with plus prefix', () => {
160
- const result = schema.safeParse('+1234567890')
161
- expect(result.success).toBe(true)
162
- })
163
-
164
- it('validates international phone numbers', () => {
165
- const result = schema.safeParse('+441234567890')
166
- expect(result.success).toBe(true)
167
- })
168
-
169
- it('rejects phone numbers starting with zero', () => {
170
- const result = schema.safeParse('0123456789')
171
- expect(result.success).toBe(false)
172
- })
173
-
174
- it('rejects phone numbers with letters', () => {
175
- const result = schema.safeParse('123-456-ABCD')
176
- expect(result.success).toBe(false)
177
- })
178
-
179
- it('rejects phone numbers with special characters', () => {
180
- const result = schema.safeParse('123-456-7890')
181
- expect(result.success).toBe(false)
182
- })
183
- })
184
-
185
- describe('hex color pattern', () => {
186
- const schema = regexp(/^#[0-9A-Fa-f]{6}$/)
187
-
188
- it('validates 6-digit hex colors', () => {
189
- const result = schema.safeParse('#FF5733')
190
- expect(result.success).toBe(true)
191
- })
192
-
193
- it('validates lowercase hex colors', () => {
194
- const result = schema.safeParse('#ff5733')
195
- expect(result.success).toBe(true)
196
- })
197
-
198
- it('validates mixed case hex colors', () => {
199
- const result = schema.safeParse('#Ff5733')
200
- expect(result.success).toBe(true)
201
- })
202
-
203
- it('rejects hex colors without hash', () => {
204
- const result = schema.safeParse('FF5733')
205
- expect(result.success).toBe(false)
206
- })
207
-
208
- it('rejects 3-digit hex colors', () => {
209
- const result = schema.safeParse('#FFF')
210
- expect(result.success).toBe(false)
211
- })
212
-
213
- it('rejects hex colors with invalid characters', () => {
214
- const result = schema.safeParse('#GG5733')
215
- expect(result.success).toBe(false)
216
- })
217
- })
218
-
219
- describe('alphanumeric pattern', () => {
220
- const schema = regexp(/^[a-zA-Z0-9]+$/)
221
-
222
- it('validates alphanumeric strings', () => {
223
- const result = schema.safeParse('abc123')
224
- expect(result.success).toBe(true)
225
- })
226
-
227
- it('validates only letters', () => {
228
- const result = schema.safeParse('abcdef')
229
- expect(result.success).toBe(true)
230
- })
231
-
232
- it('validates only numbers', () => {
233
- const result = schema.safeParse('123456')
234
- expect(result.success).toBe(true)
235
- })
236
-
237
- it('rejects strings with spaces', () => {
238
- const result = schema.safeParse('abc 123')
239
- expect(result.success).toBe(false)
240
- })
241
-
242
- it('rejects strings with special characters', () => {
243
- const result = schema.safeParse('abc_123')
244
- expect(result.success).toBe(false)
245
- })
246
-
247
- it('rejects empty strings', () => {
248
- const result = schema.safeParse('')
249
- expect(result.success).toBe(false)
250
- })
251
- })
252
-
253
- describe('case-insensitive pattern', () => {
254
- const schema = regexp(/^hello$/i)
255
-
256
- it('validates lowercase match', () => {
257
- const result = schema.safeParse('hello')
258
- expect(result.success).toBe(true)
259
- })
260
-
261
- it('validates uppercase match', () => {
262
- const result = schema.safeParse('HELLO')
263
- expect(result.success).toBe(true)
264
- })
265
-
266
- it('validates mixed case match', () => {
267
- const result = schema.safeParse('HeLLo')
268
- expect(result.success).toBe(true)
269
- })
270
-
271
- it('rejects non-matching strings', () => {
272
- const result = schema.safeParse('world')
273
- expect(result.success).toBe(false)
274
- })
275
- })
276
-
277
- describe('multiline pattern', () => {
278
- const schema = regexp(/^line\d+$/m)
279
-
280
- it('validates single line matching pattern', () => {
281
- const result = schema.safeParse('line1')
282
- expect(result.success).toBe(true)
283
- })
284
-
285
- it('validates multiline string with matching line', () => {
286
- const result = schema.safeParse('line1\nline2')
287
- expect(result.success).toBe(true)
288
- })
289
-
290
- it('rejects strings without matching lines', () => {
291
- const result = schema.safeParse('hello\nworld')
292
- expect(result.success).toBe(false)
293
- })
294
- })
295
-
296
- describe('optional character pattern', () => {
297
- const schema = regexp(/^colou?r$/)
298
-
299
- it('validates with optional character present', () => {
300
- const result = schema.safeParse('colour')
301
- expect(result.success).toBe(true)
302
- })
303
-
304
- it('validates with optional character absent', () => {
305
- const result = schema.safeParse('color')
306
- expect(result.success).toBe(true)
307
- })
308
-
309
- it('rejects strings not matching pattern', () => {
310
- const result = schema.safeParse('colouur')
311
- expect(result.success).toBe(false)
312
- })
313
- })
314
-
315
- describe('character range pattern', () => {
316
- const schema = regexp(/^[0-5]+$/)
317
-
318
- it('validates strings within range', () => {
319
- const result = schema.safeParse('012345')
320
- expect(result.success).toBe(true)
321
- })
322
-
323
- it('validates single character in range', () => {
324
- const result = schema.safeParse('3')
325
- expect(result.success).toBe(true)
326
- })
327
-
328
- it('rejects strings with characters outside range', () => {
329
- const result = schema.safeParse('0123456')
330
- expect(result.success).toBe(false)
331
- })
332
- })
333
-
334
- describe('quantifier pattern', () => {
335
- const schema = regexp(/^a{3}$/)
336
-
337
- it('validates exact repetition count', () => {
338
- const result = schema.safeParse('aaa')
339
- expect(result.success).toBe(true)
340
- })
341
-
342
- it('rejects fewer repetitions', () => {
343
- const result = schema.safeParse('aa')
344
- expect(result.success).toBe(false)
345
- })
346
-
347
- it('rejects more repetitions', () => {
348
- const result = schema.safeParse('aaaa')
349
- expect(result.success).toBe(false)
350
- })
351
- })
352
-
353
- describe('range quantifier pattern', () => {
354
- const schema = regexp(/^a{2,4}$/)
355
-
356
- it('validates minimum repetition count', () => {
357
- const result = schema.safeParse('aa')
358
- expect(result.success).toBe(true)
359
- })
360
-
361
- it('validates middle repetition count', () => {
362
- const result = schema.safeParse('aaa')
363
- expect(result.success).toBe(true)
364
- })
365
-
366
- it('validates maximum repetition count', () => {
367
- const result = schema.safeParse('aaaa')
368
- expect(result.success).toBe(true)
369
- })
370
-
371
- it('rejects fewer than minimum repetitions', () => {
372
- const result = schema.safeParse('a')
373
- expect(result.success).toBe(false)
374
- })
375
-
376
- it('rejects more than maximum repetitions', () => {
377
- const result = schema.safeParse('aaaaa')
378
- expect(result.success).toBe(false)
379
- })
380
- })
381
-
382
- describe('alternation pattern', () => {
383
- const schema = regexp(/^(cat|dog|bird)$/)
384
-
385
- it('validates first alternative', () => {
386
- const result = schema.safeParse('cat')
387
- expect(result.success).toBe(true)
388
- })
389
-
390
- it('validates second alternative', () => {
391
- const result = schema.safeParse('dog')
392
- expect(result.success).toBe(true)
393
- })
394
-
395
- it('validates third alternative', () => {
396
- const result = schema.safeParse('bird')
397
- expect(result.success).toBe(true)
398
- })
399
-
400
- it('rejects strings not matching any alternative', () => {
401
- const result = schema.safeParse('fish')
402
- expect(result.success).toBe(false)
403
- })
404
- })
405
-
406
- describe('word boundary pattern', () => {
407
- const schema = regexp(/\bword\b/)
408
-
409
- it('validates word with boundaries', () => {
410
- const result = schema.safeParse('word')
411
- expect(result.success).toBe(true)
412
- })
413
-
414
- it('validates word within sentence', () => {
415
- const result = schema.safeParse('this is a word')
416
- expect(result.success).toBe(true)
417
- })
418
-
419
- it('rejects word as part of larger word', () => {
420
- const result = schema.safeParse('wording')
421
- expect(result.success).toBe(false)
422
- })
423
- })
424
-
425
- describe('lookahead pattern', () => {
426
- const schema = regexp(/^(?=.*[A-Z])(?=.*[0-9]).{8,}$/)
427
-
428
- it('validates string meeting all lookahead conditions', () => {
429
- const result = schema.safeParse('Password1')
430
- expect(result.success).toBe(true)
431
- })
432
-
433
- it('validates string with multiple uppercase and numbers', () => {
434
- const result = schema.safeParse('ABC12345')
435
- expect(result.success).toBe(true)
436
- })
437
-
438
- it('rejects string without uppercase', () => {
439
- const result = schema.safeParse('password1')
440
- expect(result.success).toBe(false)
441
- })
442
-
443
- it('rejects string without number', () => {
444
- const result = schema.safeParse('Password')
445
- expect(result.success).toBe(false)
446
- })
447
-
448
- it('rejects string too short', () => {
449
- const result = schema.safeParse('Pass1')
450
- expect(result.success).toBe(false)
451
- })
452
- })
453
-
454
- describe('unicode pattern', () => {
455
- const schema = regexp(/^[\u4e00-\u9fa5]+$/)
456
-
457
- it('validates Chinese characters', () => {
458
- const result = schema.safeParse('你好')
459
- expect(result.success).toBe(true)
460
- })
461
-
462
- it('validates multiple Chinese characters', () => {
463
- const result = schema.safeParse('世界')
464
- expect(result.success).toBe(true)
465
- })
466
-
467
- it('rejects non-Chinese characters', () => {
468
- const result = schema.safeParse('hello')
469
- expect(result.success).toBe(false)
470
- })
471
-
472
- it('rejects mixed Chinese and English', () => {
473
- const result = schema.safeParse('你好hello')
474
- expect(result.success).toBe(false)
475
- })
476
- })
477
-
478
- describe('empty string pattern', () => {
479
- const schema = regexp(/^$/)
480
-
481
- it('validates empty strings', () => {
482
- const result = schema.safeParse('')
483
- expect(result.success).toBe(true)
484
- })
485
-
486
- it('rejects non-empty strings', () => {
487
- const result = schema.safeParse('hello')
488
- expect(result.success).toBe(false)
489
- })
490
-
491
- it('rejects whitespace strings', () => {
492
- const result = schema.safeParse(' ')
493
- expect(result.success).toBe(false)
494
- })
495
- })
496
-
497
- describe('wildcard pattern', () => {
498
- const schema = regexp(/^.*$/)
499
-
500
- it('validates empty strings', () => {
501
- const result = schema.safeParse('')
502
- expect(result.success).toBe(true)
503
- })
504
-
505
- it('validates any string', () => {
506
- const result = schema.safeParse('anything goes here 123 !@#')
507
- expect(result.success).toBe(true)
508
- })
509
-
510
- it('validates strings with special characters', () => {
511
- const result = schema.safeParse('!@#$%^&*()')
512
- expect(result.success).toBe(true)
513
- })
514
-
515
- it('validates strings with unicode', () => {
516
- const result = schema.safeParse('Hello 世界 🌍')
517
- expect(result.success).toBe(true)
518
- })
519
- })
520
-
521
- describe('edge cases', () => {
522
- it('handles pattern with escape sequences', () => {
523
- const schema = regexp(/^\d{3}\.\d{3}\.\d{3}\.\d{3}$/)
524
- const result = schema.safeParse('192.168.001.001')
525
- expect(result.success).toBe(true)
526
- })
527
-
528
- it('handles pattern with special regex characters', () => {
529
- const schema = regexp(/^\$\d+\.\d{2}$/)
530
- const result = schema.safeParse('$99.99')
531
- expect(result.success).toBe(true)
532
- })
533
-
534
- it('handles very long strings', () => {
535
- const schema = regexp(/^[a-z]+$/)
536
- const longString = 'a'.repeat(10000)
537
- const result = schema.safeParse(longString)
538
- expect(result.success).toBe(true)
539
- })
540
-
541
- it('handles strings with newlines', () => {
542
- const schema = regexp(/^hello\nworld$/)
543
- const result = schema.safeParse('hello\nworld')
544
- expect(result.success).toBe(true)
545
- })
546
-
547
- it('handles strings with tabs', () => {
548
- const schema = regexp(/^hello\tworld$/)
549
- const result = schema.safeParse('hello\tworld')
550
- expect(result.success).toBe(true)
551
- })
552
-
553
- it('handles emoji patterns', () => {
554
- const schema = regexp(/^[\u{1F600}-\u{1F64F}]+$/u)
555
- const result = schema.safeParse('😀😃😄')
556
- expect(result.success).toBe(true)
557
- })
558
-
559
- it('handles global flag in pattern', () => {
560
- const schema = regexp(/test/g)
561
- const result = schema.safeParse('test')
562
- expect(result.success).toBe(true)
563
- })
564
-
565
- it('handles pattern matching anywhere in string', () => {
566
- const schema = regexp(/test/)
567
- const result = schema.safeParse('this is a test string')
568
- expect(result.success).toBe(true)
569
- })
570
-
571
- it('handles complex nested groups', () => {
572
- const schema = regexp(/^((https?|ftp):\/\/)?([a-z0-9]+\.)+[a-z]{2,}$/)
573
- const result = schema.safeParse('https://example.com')
574
- expect(result.success).toBe(true)
575
- })
576
- })
577
- })
@@ -1,82 +0,0 @@
1
- import { Schema, ValidationContext } from '../core.js'
2
-
3
- /**
4
- * Schema for validating strings against a regular expression pattern.
5
- *
6
- * Validates that the input is a string and matches the provided pattern.
7
- * The pattern is tested using RegExp.test().
8
- *
9
- * @template TValue - The string type (can be narrowed with branded types)
10
- *
11
- * @example
12
- * ```ts
13
- * const schema = new RegexpSchema(/^[a-z]+$/)
14
- * schema.validate('hello') // success
15
- * schema.validate('Hello') // fails - uppercase not allowed
16
- * ```
17
- */
18
- export class RegexpSchema<
19
- TValue extends string = string,
20
- > extends Schema<TValue> {
21
- readonly type = 'regexp' as const
22
-
23
- constructor(
24
- public readonly pattern: RegExp,
25
- public readonly message?: string,
26
- ) {
27
- super()
28
- }
29
-
30
- validateInContext(input: unknown, ctx: ValidationContext) {
31
- if (typeof input !== 'string') {
32
- return ctx.issueUnexpectedType(input, 'string')
33
- }
34
-
35
- if (!this.pattern.test(input)) {
36
- return ctx.issueInvalidFormat(
37
- input,
38
- this.pattern.toString(),
39
- this.message,
40
- )
41
- }
42
-
43
- return ctx.success(input as TValue)
44
- }
45
- }
46
-
47
- /**
48
- * Creates a regexp schema that validates strings against a pattern.
49
- *
50
- * Useful for custom string formats not covered by the built-in format
51
- * validators.
52
- *
53
- * @param pattern - Regular expression pattern to match against
54
- * @returns A new {@link RegexpSchema} instance
55
- *
56
- * @example
57
- * ```ts
58
- * // Simple pattern
59
- * const slugSchema = l.regexp(/^[a-z0-9-]+$/)
60
- *
61
- * // With anchors for exact match
62
- * const uuidSchema = l.regexp(
63
- * /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
64
- * )
65
- *
66
- * // Semantic versioning
67
- * const semverSchema = l.regexp(/^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/)
68
- *
69
- * // Use in object
70
- * const configSchema = l.object({
71
- * name: l.regexp(/^[a-z][a-z0-9-]*$/), // kebab-case identifier
72
- * version: semverSchema,
73
- * })
74
- * ```
75
- */
76
- /*@__NO_SIDE_EFFECTS__*/
77
- export function regexp<TInput extends string = string>(
78
- pattern: RegExp,
79
- message?: string,
80
- ): RegexpSchema<TInput> {
81
- return new RegexpSchema<TInput>(pattern, message)
82
- }