@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,796 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import { integer } from './integer.js'
3
- import { object } from './object.js'
4
- import { string } from './string.js'
5
- import { typedObject } from './typed-object.js'
6
- import { typedRef } from './typed-ref.js'
7
-
8
- describe('TypedRefSchema', () => {
9
- describe('basic validation', () => {
10
- it('validates through a typed object reference with explicit $type', () => {
11
- const typedObjectSchema = typedObject(
12
- 'com.example.user',
13
- 'main',
14
- object({
15
- name: string(),
16
- age: integer(),
17
- }),
18
- )
19
-
20
- const schema = typedRef(() => typedObjectSchema)
21
-
22
- const result = schema.safeParse({
23
- $type: 'com.example.user',
24
- name: 'Alice',
25
- age: 30,
26
- })
27
-
28
- expect(result.success).toBe(true)
29
- if (result.success) {
30
- expect(result.value.$type).toBe('com.example.user')
31
- }
32
- })
33
-
34
- it('validates through a typed object with explicit $type', () => {
35
- const typedObjectSchema = typedObject(
36
- 'com.example.user',
37
- 'main',
38
- object({
39
- name: string(),
40
- age: integer(),
41
- }),
42
- )
43
-
44
- const schema = typedRef(() => typedObjectSchema)
45
-
46
- const result = schema.safeParse({
47
- $type: 'com.example.user',
48
- name: 'Alice',
49
- age: 30,
50
- })
51
-
52
- expect(result.success).toBe(true)
53
- if (result.success) {
54
- expect(result.value.$type).toBe('com.example.user')
55
- }
56
- })
57
-
58
- it('rejects input with wrong $type', () => {
59
- const typedObjectSchema = typedObject(
60
- 'com.example.user',
61
- 'main',
62
- object({
63
- name: string(),
64
- }),
65
- )
66
-
67
- const schema = typedRef(() => typedObjectSchema)
68
-
69
- const result = schema.safeParse({
70
- $type: 'com.example.wrong',
71
- name: 'Alice',
72
- })
73
-
74
- expect(result.success).toBe(false)
75
- })
76
-
77
- it('rejects invalid input through reference', () => {
78
- const typedObjectSchema = typedObject(
79
- 'com.example.user',
80
- 'main',
81
- object({
82
- name: string(),
83
- age: integer(),
84
- }),
85
- )
86
-
87
- const schema = typedRef(() => typedObjectSchema)
88
-
89
- const result = schema.safeParse({
90
- $type: 'com.example.user',
91
- name: 'Alice',
92
- age: 'thirty',
93
- })
94
-
95
- expect(result.success).toBe(false)
96
- })
97
-
98
- it('rejects non-objects through reference', () => {
99
- const typedObjectSchema = typedObject(
100
- 'com.example.value',
101
- 'main',
102
- object({
103
- value: string(),
104
- }),
105
- )
106
-
107
- const schema = typedRef(() => typedObjectSchema)
108
-
109
- const result = schema.safeParse('not an object')
110
- expect(result.success).toBe(false)
111
- })
112
-
113
- it('rejects null through reference', () => {
114
- const typedObjectSchema = typedObject(
115
- 'com.example.user',
116
- 'main',
117
- object({
118
- name: string(),
119
- }),
120
- )
121
-
122
- const schema = typedRef(() => typedObjectSchema)
123
-
124
- const result = schema.safeParse(null)
125
- expect(result.success).toBe(false)
126
- })
127
-
128
- it('rejects undefined through reference', () => {
129
- const typedObjectSchema = typedObject(
130
- 'com.example.user',
131
- 'main',
132
- object({
133
- name: string(),
134
- }),
135
- )
136
-
137
- const schema = typedRef(() => typedObjectSchema)
138
-
139
- const result = schema.safeParse(undefined)
140
- expect(result.success).toBe(false)
141
- })
142
- })
143
-
144
- describe('$type property', () => {
145
- it('exposes the $type from the referenced schema', () => {
146
- const typedObjectSchema = typedObject(
147
- 'com.example.post',
148
- 'main',
149
- object({
150
- text: string(),
151
- }),
152
- )
153
-
154
- const schema = typedRef(() => typedObjectSchema)
155
-
156
- expect(schema.$type).toBe('com.example.post')
157
- })
158
-
159
- it('validates that output has correct $type', () => {
160
- const typedObjectSchema = typedObject(
161
- 'com.example.like',
162
- 'main',
163
- object({
164
- subject: string(),
165
- }),
166
- )
167
-
168
- const schema = typedRef(() => typedObjectSchema)
169
-
170
- const result = schema.safeParse({
171
- $type: 'com.example.like',
172
- subject: 'at://did:plc:abc/app.bsky.feed.post/123',
173
- })
174
-
175
- expect(result.success).toBe(true)
176
- if (result.success) {
177
- expect(result.value.$type).toBe('com.example.like')
178
- }
179
- })
180
-
181
- it('ensures $type matches expected value', () => {
182
- const typedObjectSchema = typedObject(
183
- 'com.example.follow',
184
- 'main',
185
- object({
186
- subject: string(),
187
- }),
188
- )
189
-
190
- const schema = typedRef(() => typedObjectSchema)
191
-
192
- // Try to pass wrong $type
193
- const result = schema.safeParse({
194
- $type: 'com.example.block',
195
- subject: 'did:plc:abc',
196
- })
197
-
198
- expect(result.success).toBe(false)
199
- })
200
- })
201
-
202
- describe('lazy schema resolution', () => {
203
- it('does not call getter until first validation', () => {
204
- let getterCalled = false
205
-
206
- const schema = typedRef(() => {
207
- getterCalled = true
208
- return typedObject(
209
- 'com.example.test',
210
- 'main',
211
- object({
212
- value: string(),
213
- }),
214
- )
215
- })
216
-
217
- expect(getterCalled).toBe(false)
218
-
219
- schema.safeParse({ value: 'test' })
220
- expect(getterCalled).toBe(true)
221
- })
222
-
223
- it('does not call getter until $type is accessed', () => {
224
- let getterCalled = false
225
-
226
- const schema = typedRef(() => {
227
- getterCalled = true
228
- return typedObject(
229
- 'com.example.test',
230
- 'main',
231
- object({
232
- value: string(),
233
- }),
234
- )
235
- })
236
-
237
- expect(getterCalled).toBe(false)
238
-
239
- // Access $type should trigger getter
240
- const type = schema.$type
241
- expect(getterCalled).toBe(true)
242
- expect(type).toBe('com.example.test')
243
- })
244
-
245
- it('throws error if getter is called recursively', () => {
246
- // @ts-expect-error
247
- const schema = typedRef(() => {
248
- // This would cause infinite recursion if not protected
249
- return schema.validator
250
- })
251
-
252
- expect(() => {
253
- schema.safeParse({ value: 'test' })
254
- }).toThrow()
255
- })
256
- })
257
-
258
- describe('with constrained schemas', () => {
259
- it('validates typed object with string constraints', () => {
260
- const typedObjectSchema = typedObject(
261
- 'com.example.post',
262
- 'main',
263
- object({
264
- text: string({ minLength: 1, maxLength: 300 }),
265
- }),
266
- )
267
-
268
- const schema = typedRef(() => typedObjectSchema)
269
-
270
- const result = schema.safeParse({
271
- $type: 'com.example.post',
272
- text: 'This is a valid post',
273
- })
274
-
275
- expect(result.success).toBe(true)
276
- })
277
-
278
- it('rejects typed object violating string constraints', () => {
279
- const typedObjectSchema = typedObject(
280
- 'com.example.post',
281
- 'main',
282
- object({
283
- text: string({ minLength: 1, maxLength: 300 }),
284
- }),
285
- )
286
-
287
- const schema = typedRef(() => typedObjectSchema)
288
-
289
- const result = schema.safeParse({
290
- $type: 'com.example.post',
291
- text: '',
292
- })
293
-
294
- expect(result.success).toBe(false)
295
- })
296
-
297
- it('validates typed object with integer constraints', () => {
298
- const typedObjectSchema = typedObject(
299
- 'com.example.rating',
300
- 'main',
301
- object({
302
- score: integer({ minimum: 1, maximum: 5 }),
303
- }),
304
- )
305
-
306
- const schema = typedRef(() => typedObjectSchema)
307
-
308
- const result = schema.safeParse({
309
- $type: 'com.example.rating',
310
- score: 4,
311
- })
312
-
313
- expect(result.success).toBe(true)
314
- })
315
-
316
- it('rejects typed object violating integer constraints', () => {
317
- const typedObjectSchema = typedObject(
318
- 'com.example.rating',
319
- 'main',
320
- object({
321
- score: integer({ minimum: 1, maximum: 5 }),
322
- }),
323
- )
324
-
325
- const schema = typedRef(() => typedObjectSchema)
326
-
327
- const result = schema.safeParse({
328
- $type: 'com.example.rating',
329
- score: 10,
330
- })
331
-
332
- expect(result.success).toBe(false)
333
- })
334
- })
335
-
336
- describe('multiple validations', () => {
337
- it('validates multiple inputs correctly', () => {
338
- const typedObjectSchema = typedObject(
339
- 'com.example.user',
340
- 'main',
341
- object({
342
- name: string({ minLength: 2 }),
343
- }),
344
- )
345
-
346
- const schema = typedRef(() => typedObjectSchema)
347
-
348
- const result1 = schema.safeParse({
349
- $type: 'com.example.user',
350
- name: 'Alice',
351
- })
352
- expect(result1.success).toBe(true)
353
-
354
- const result2 = schema.safeParse({ $type: 'com.example.user', name: 'A' })
355
- expect(result2.success).toBe(false)
356
-
357
- const result3 = schema.safeParse({
358
- $type: 'com.example.user',
359
- name: 'Bob',
360
- })
361
- expect(result3.success).toBe(true)
362
-
363
- const result4 = schema.safeParse({ $type: 'com.example.user', name: '' })
364
- expect(result4.success).toBe(false)
365
- })
366
-
367
- it('handles different types of validation failures', () => {
368
- const typedObjectSchema = typedObject(
369
- 'com.example.user',
370
- 'main',
371
- object({
372
- name: string({ minLength: 2 }),
373
- age: integer({ minimum: 0, maximum: 150 }),
374
- }),
375
- )
376
-
377
- const schema = typedRef(() => typedObjectSchema)
378
-
379
- const result1 = schema.safeParse({
380
- $type: 'com.example.user',
381
- name: 'A',
382
- age: 25,
383
- })
384
- expect(result1.success).toBe(false)
385
-
386
- const result2 = schema.safeParse({
387
- $type: 'com.example.user',
388
- name: 'Alice',
389
- age: 200,
390
- })
391
- expect(result2.success).toBe(false)
392
-
393
- const result3 = schema.safeParse({
394
- $type: 'com.example.user',
395
- name: 'Alice',
396
- age: 25,
397
- })
398
- expect(result3.success).toBe(true)
399
-
400
- const result4 = schema.safeParse({
401
- $type: 'com.example.user',
402
- name: 'Alice',
403
- })
404
- expect(result4.success).toBe(false)
405
- })
406
-
407
- it('validates same input multiple times consistently', () => {
408
- const typedObjectSchema = typedObject(
409
- 'com.example.post',
410
- 'main',
411
- object({
412
- text: string(),
413
- }),
414
- )
415
-
416
- const schema = typedRef(() => typedObjectSchema)
417
-
418
- const input = { $type: 'com.example.post', text: 'Hello world' }
419
-
420
- const result1 = schema.safeParse(input)
421
- const result2 = schema.safeParse(input)
422
- const result3 = schema.safeParse(input)
423
-
424
- expect(result1.success).toBe(true)
425
- expect(result2.success).toBe(true)
426
- expect(result3.success).toBe(true)
427
- })
428
- })
429
-
430
- describe('edge cases', () => {
431
- it('handles empty object validation', () => {
432
- const typedObjectSchema = typedObject(
433
- 'com.example.empty',
434
- 'main',
435
- object({}),
436
- )
437
-
438
- const schema = typedRef(() => typedObjectSchema)
439
-
440
- const result = schema.safeParse({ $type: 'com.example.empty' })
441
- expect(result.success).toBe(true)
442
- if (result.success) {
443
- expect(result.value.$type).toBe('com.example.empty')
444
- }
445
- })
446
-
447
- it('rejects arrays', () => {
448
- const typedObjectSchema = typedObject(
449
- 'com.example.test',
450
- 'main',
451
- object({
452
- value: string(),
453
- }),
454
- )
455
-
456
- const schema = typedRef(() => typedObjectSchema)
457
-
458
- const result = schema.safeParse([{ value: 'test' }])
459
- expect(result.success).toBe(false)
460
- })
461
-
462
- it('rejects primitive values', () => {
463
- const typedObjectSchema = typedObject(
464
- 'com.example.test',
465
- 'main',
466
- object({
467
- value: string(),
468
- }),
469
- )
470
-
471
- const schema = typedRef(() => typedObjectSchema)
472
-
473
- const result1 = schema.safeParse('string')
474
- expect(result1.success).toBe(false)
475
-
476
- const result2 = schema.safeParse(123)
477
- expect(result2.success).toBe(false)
478
-
479
- const result3 = schema.safeParse(true)
480
- expect(result3.success).toBe(false)
481
- })
482
-
483
- it('handles objects with extra properties', () => {
484
- const typedObjectSchema = typedObject(
485
- 'com.example.user',
486
- 'main',
487
- object({
488
- name: string(),
489
- }),
490
- )
491
-
492
- const schema = typedRef(() => typedObjectSchema)
493
-
494
- const result = schema.safeParse({
495
- $type: 'com.example.user',
496
- name: 'Alice',
497
- extra: 'property',
498
- another: 'value',
499
- })
500
-
501
- expect(result.success).toBe(true)
502
- })
503
-
504
- it('validates with zero values', () => {
505
- const typedObjectSchema = typedObject(
506
- 'com.example.counter',
507
- 'main',
508
- object({
509
- count: integer(),
510
- }),
511
- )
512
-
513
- const schema = typedRef(() => typedObjectSchema)
514
-
515
- const result = schema.safeParse({
516
- $type: 'com.example.counter',
517
- count: 0,
518
- })
519
- expect(result.success).toBe(true)
520
- })
521
-
522
- it('validates with empty strings', () => {
523
- const typedObjectSchema = typedObject(
524
- 'com.example.text',
525
- 'main',
526
- object({
527
- content: string(),
528
- }),
529
- )
530
-
531
- const schema = typedRef(() => typedObjectSchema)
532
-
533
- const result = schema.safeParse({
534
- $type: 'com.example.text',
535
- content: '',
536
- })
537
- expect(result.success).toBe(true)
538
- })
539
-
540
- it('rejects NaN in integer fields', () => {
541
- const typedObjectSchema = typedObject(
542
- 'com.example.number',
543
- 'main',
544
- object({
545
- value: integer(),
546
- }),
547
- )
548
-
549
- const schema = typedRef(() => typedObjectSchema)
550
-
551
- const result = schema.safeParse({
552
- $type: 'com.example.number',
553
- value: NaN,
554
- })
555
- expect(result.success).toBe(false)
556
- })
557
-
558
- it('rejects Infinity in integer fields', () => {
559
- const typedObjectSchema = typedObject(
560
- 'com.example.number',
561
- 'main',
562
- object({
563
- value: integer(),
564
- }),
565
- )
566
-
567
- const schema = typedRef(() => typedObjectSchema)
568
-
569
- const result = schema.safeParse({
570
- $type: 'com.example.number',
571
- value: Infinity,
572
- })
573
- expect(result.success).toBe(false)
574
- })
575
- })
576
-
577
- describe('nested references', () => {
578
- it('validates through nested TypedRefSchema', () => {
579
- const typedObjectSchema = typedObject(
580
- 'com.example.user',
581
- 'main',
582
- object({
583
- name: string({ minLength: 2 }),
584
- }),
585
- )
586
-
587
- const innerRef = typedRef(() => typedObjectSchema)
588
- const outerRef = typedRef(() => innerRef.validator)
589
-
590
- const result = outerRef.safeParse({
591
- $type: 'com.example.user',
592
- name: 'Alice',
593
- })
594
- expect(result.success).toBe(true)
595
- if (result.success) {
596
- expect(result.value.$type).toBe('com.example.user')
597
- }
598
- })
599
-
600
- it('validates with objects containing TypedRef fields', () => {
601
- const innerTyped = typedObject(
602
- 'com.example.profile',
603
- 'main',
604
- object({
605
- bio: string(),
606
- }),
607
- )
608
-
609
- const outerTyped = typedObject(
610
- 'com.example.user',
611
- 'main',
612
- object({
613
- name: string(),
614
- profile: typedRef(() => innerTyped),
615
- }),
616
- )
617
-
618
- const schema = typedRef(() => outerTyped)
619
-
620
- const result = schema.safeParse({
621
- $type: 'com.example.user',
622
- name: 'Alice',
623
- profile: {
624
- $type: 'com.example.profile',
625
- bio: 'Software developer',
626
- },
627
- })
628
-
629
- expect(result.success).toBe(true)
630
- if (result.success) {
631
- expect(result.value.$type).toBe('com.example.user')
632
- expect(result.value.profile.$type).toBe('com.example.profile')
633
- }
634
- })
635
-
636
- it('rejects nested objects with wrong $type', () => {
637
- const innerTyped = typedObject(
638
- 'com.example.profile',
639
- 'main',
640
- object({
641
- bio: string(),
642
- }),
643
- )
644
-
645
- const outerTyped = typedObject(
646
- 'com.example.user',
647
- 'main',
648
- object({
649
- name: string(),
650
- profile: typedRef(() => innerTyped),
651
- }),
652
- )
653
-
654
- const schema = typedRef(() => outerTyped)
655
-
656
- const result = schema.safeParse({
657
- $type: 'com.example.user',
658
- name: 'Alice',
659
- profile: {
660
- $type: 'com.example.wrongtype',
661
- bio: 'Software developer',
662
- },
663
- })
664
-
665
- expect(result.success).toBe(false)
666
- })
667
- })
668
-
669
- describe('schema property access', () => {
670
- it('allows direct access to resolved schema', () => {
671
- const typedObjectSchema = typedObject(
672
- 'com.example.test',
673
- 'main',
674
- object({
675
- value: string(),
676
- }),
677
- )
678
-
679
- const refSchema = typedRef(() => typedObjectSchema)
680
-
681
- const resolved = refSchema.validator
682
- expect(resolved).toBe(typedObjectSchema)
683
- expect(resolved.$type).toBe('com.example.test')
684
- })
685
-
686
- it('returns same instance on multiple schema property accesses', () => {
687
- const typedObjectSchema = typedObject(
688
- 'com.example.test',
689
- 'main',
690
- object({
691
- value: string(),
692
- }),
693
- )
694
-
695
- const refSchema = typedRef(() => typedObjectSchema)
696
-
697
- const first = refSchema.validator
698
- const second = refSchema.validator
699
- const third = refSchema.validator
700
-
701
- expect(first).toBe(second)
702
- expect(second).toBe(third)
703
- expect(first.$type).toBe('com.example.test')
704
- })
705
- })
706
-
707
- describe('complex object structures', () => {
708
- it('validates complex nested structure', () => {
709
- const typedObjectSchema = typedObject(
710
- 'com.example.post',
711
- 'main',
712
- object({
713
- text: string({ minLength: 1, maxLength: 300 }),
714
- createdAt: string({ format: 'datetime' }),
715
- likeCount: integer({ minimum: 0 }),
716
- }),
717
- )
718
-
719
- const schema = typedRef(() => typedObjectSchema)
720
-
721
- const result = schema.safeParse({
722
- $type: 'com.example.post',
723
- text: 'Hello world!',
724
- createdAt: '2023-01-01T00:00:00Z',
725
- likeCount: 42,
726
- })
727
-
728
- expect(result.success).toBe(true)
729
- if (result.success) {
730
- expect(result.value.$type).toBe('com.example.post')
731
- expect(result.value.text).toBe('Hello world!')
732
- expect(result.value.likeCount).toBe(42)
733
- }
734
- })
735
-
736
- it('validates structure with multiple property types', () => {
737
- const typedObjectSchema = typedObject(
738
- 'com.example.record',
739
- 'main',
740
- object({
741
- id: string({ format: 'nsid' }),
742
- count: integer({ minimum: 0 }),
743
- flag: string(),
744
- }),
745
- )
746
-
747
- const schema = typedRef(() => typedObjectSchema)
748
-
749
- const result = schema.safeParse({
750
- $type: 'com.example.record',
751
- id: 'com.example.feed.post',
752
- count: 100,
753
- flag: 'active',
754
- })
755
-
756
- expect(result.success).toBe(true)
757
- })
758
-
759
- it('rejects structure with any invalid property', () => {
760
- const typedObjectSchema = typedObject(
761
- 'com.example.record',
762
- 'main',
763
- object({
764
- name: string({ minLength: 1 }),
765
- count: integer({ minimum: 0 }),
766
- }),
767
- )
768
-
769
- const schema = typedRef(() => typedObjectSchema)
770
-
771
- // Valid name, invalid count
772
- const result1 = schema.safeParse({
773
- $type: 'com.example.record',
774
- name: 'test',
775
- count: -5,
776
- })
777
- expect(result1.success).toBe(false)
778
-
779
- // Invalid name, valid count
780
- const result2 = schema.safeParse({
781
- $type: 'com.example.record',
782
- name: '',
783
- count: 5,
784
- })
785
- expect(result2.success).toBe(false)
786
-
787
- // Both invalid
788
- const result3 = schema.safeParse({
789
- $type: 'com.example.record',
790
- name: '',
791
- count: -5,
792
- })
793
- expect(result3.success).toBe(false)
794
- })
795
- })
796
- })