@livon/schema 0.27.0-rc.1

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 (169) hide show
  1. package/PROMPT.md +21 -0
  2. package/README.md +13 -0
  3. package/SCHEMA.md +13 -0
  4. package/dist/SchemaValidationError.cjs +41 -0
  5. package/dist/SchemaValidationError.d.ts +20 -0
  6. package/dist/SchemaValidationError.js +7 -0
  7. package/dist/SchemaValidationError.spec.cjs +65 -0
  8. package/dist/SchemaValidationError.spec.d.ts +1 -0
  9. package/dist/SchemaValidationError.spec.js +59 -0
  10. package/dist/after.cjs +36 -0
  11. package/dist/after.d.ts +30 -0
  12. package/dist/after.js +2 -0
  13. package/dist/after.spec.cjs +54 -0
  14. package/dist/after.spec.d.ts +1 -0
  15. package/dist/after.spec.js +48 -0
  16. package/dist/and.cjs +36 -0
  17. package/dist/and.d.ts +26 -0
  18. package/dist/and.js +2 -0
  19. package/dist/and.spec.cjs +57 -0
  20. package/dist/and.spec.d.ts +1 -0
  21. package/dist/and.spec.js +51 -0
  22. package/dist/api.cjs +317 -0
  23. package/dist/api.d.ts +107 -0
  24. package/dist/api.js +277 -0
  25. package/dist/api.spec.cjs +512 -0
  26. package/dist/api.spec.d.ts +1 -0
  27. package/dist/api.spec.js +506 -0
  28. package/dist/array.cjs +74 -0
  29. package/dist/array.d.ts +25 -0
  30. package/dist/array.js +40 -0
  31. package/dist/array.spec.cjs +167 -0
  32. package/dist/array.spec.d.ts +1 -0
  33. package/dist/array.spec.js +161 -0
  34. package/dist/before.cjs +36 -0
  35. package/dist/before.d.ts +30 -0
  36. package/dist/before.js +2 -0
  37. package/dist/before.spec.cjs +54 -0
  38. package/dist/before.spec.d.ts +1 -0
  39. package/dist/before.spec.js +48 -0
  40. package/dist/binary.cjs +53 -0
  41. package/dist/binary.d.ts +24 -0
  42. package/dist/binary.js +19 -0
  43. package/dist/binary.spec.cjs +107 -0
  44. package/dist/binary.spec.d.ts +1 -0
  45. package/dist/binary.spec.js +101 -0
  46. package/dist/boolean.cjs +53 -0
  47. package/dist/boolean.d.ts +24 -0
  48. package/dist/boolean.js +19 -0
  49. package/dist/boolean.spec.cjs +96 -0
  50. package/dist/boolean.spec.d.ts +1 -0
  51. package/dist/boolean.spec.js +90 -0
  52. package/dist/context.cjs +125 -0
  53. package/dist/context.d.ts +101 -0
  54. package/dist/context.js +76 -0
  55. package/dist/context.spec.cjs +244 -0
  56. package/dist/context.spec.d.ts +1 -0
  57. package/dist/context.spec.js +238 -0
  58. package/dist/date.cjs +53 -0
  59. package/dist/date.d.ts +24 -0
  60. package/dist/date.js +19 -0
  61. package/dist/date.spec.cjs +97 -0
  62. package/dist/date.spec.d.ts +1 -0
  63. package/dist/date.spec.js +91 -0
  64. package/dist/doc.cjs +54 -0
  65. package/dist/doc.d.ts +25 -0
  66. package/dist/doc.js +17 -0
  67. package/dist/doc.spec.cjs +99 -0
  68. package/dist/doc.spec.d.ts +1 -0
  69. package/dist/doc.spec.js +93 -0
  70. package/dist/enumeration.cjs +74 -0
  71. package/dist/enumeration.d.ts +50 -0
  72. package/dist/enumeration.js +40 -0
  73. package/dist/enumeration.spec.cjs +110 -0
  74. package/dist/enumeration.spec.d.ts +1 -0
  75. package/dist/enumeration.spec.js +104 -0
  76. package/dist/hydrate.cjs +18 -0
  77. package/dist/hydrate.d.ts +1 -0
  78. package/dist/hydrate.js +0 -0
  79. package/dist/index.cjs +145 -0
  80. package/dist/index.d.ts +34 -0
  81. package/dist/index.js +24 -0
  82. package/dist/index.spec.cjs +43 -0
  83. package/dist/index.spec.d.ts +1 -0
  84. package/dist/index.spec.js +37 -0
  85. package/dist/literal.cjs +55 -0
  86. package/dist/literal.d.ts +25 -0
  87. package/dist/literal.js +21 -0
  88. package/dist/literal.spec.cjs +93 -0
  89. package/dist/literal.spec.d.ts +1 -0
  90. package/dist/literal.spec.js +87 -0
  91. package/dist/number.cjs +89 -0
  92. package/dist/number.d.ts +84 -0
  93. package/dist/number.js +55 -0
  94. package/dist/number.spec.cjs +155 -0
  95. package/dist/number.spec.d.ts +1 -0
  96. package/dist/number.spec.js +149 -0
  97. package/dist/object.cjs +66 -0
  98. package/dist/object.d.ts +37 -0
  99. package/dist/object.js +32 -0
  100. package/dist/object.spec.cjs +171 -0
  101. package/dist/object.spec.d.ts +1 -0
  102. package/dist/object.spec.js +165 -0
  103. package/dist/operation.cjs +182 -0
  104. package/dist/operation.d.ts +197 -0
  105. package/dist/operation.js +133 -0
  106. package/dist/operation.spec.cjs +454 -0
  107. package/dist/operation.spec.d.ts +1 -0
  108. package/dist/operation.spec.js +448 -0
  109. package/dist/or.cjs +85 -0
  110. package/dist/or.d.ts +37 -0
  111. package/dist/or.js +51 -0
  112. package/dist/or.spec.cjs +204 -0
  113. package/dist/or.spec.d.ts +1 -0
  114. package/dist/or.spec.js +198 -0
  115. package/dist/schema.cjs +285 -0
  116. package/dist/schema.d.ts +132 -0
  117. package/dist/schema.js +233 -0
  118. package/dist/schema.spec.cjs +587 -0
  119. package/dist/schema.spec.d.ts +1 -0
  120. package/dist/schema.spec.js +581 -0
  121. package/dist/schemaFactory.cjs +125 -0
  122. package/dist/schemaFactory.d.ts +97 -0
  123. package/dist/schemaFactory.js +88 -0
  124. package/dist/schemaFactory.spec.cjs +197 -0
  125. package/dist/schemaFactory.spec.d.ts +1 -0
  126. package/dist/schemaFactory.spec.js +191 -0
  127. package/dist/schemaModule.cjs +280 -0
  128. package/dist/schemaModule.d.ts +97 -0
  129. package/dist/schemaModule.js +243 -0
  130. package/dist/schemaModule.spec.cjs +355 -0
  131. package/dist/schemaModule.spec.d.ts +1 -0
  132. package/dist/schemaModule.spec.js +349 -0
  133. package/dist/string.cjs +93 -0
  134. package/dist/string.d.ts +85 -0
  135. package/dist/string.js +59 -0
  136. package/dist/string.spec.cjs +158 -0
  137. package/dist/string.spec.d.ts +1 -0
  138. package/dist/string.spec.js +152 -0
  139. package/dist/testing/mocks/assertions.mock.cjs +48 -0
  140. package/dist/testing/mocks/assertions.mock.d.ts +5 -0
  141. package/dist/testing/mocks/assertions.mock.js +14 -0
  142. package/dist/testing/mocks/index.cjs +52 -0
  143. package/dist/testing/mocks/index.d.ts +4 -0
  144. package/dist/testing/mocks/index.js +3 -0
  145. package/dist/testing/mocks/schema.mock.cjs +120 -0
  146. package/dist/testing/mocks/schema.mock.d.ts +37 -0
  147. package/dist/testing/mocks/schema.mock.js +74 -0
  148. package/dist/tuple.cjs +58 -0
  149. package/dist/tuple.d.ts +33 -0
  150. package/dist/tuple.js +24 -0
  151. package/dist/tuple.spec.cjs +162 -0
  152. package/dist/tuple.spec.d.ts +1 -0
  153. package/dist/tuple.spec.js +156 -0
  154. package/dist/typeGuards.cjs +60 -0
  155. package/dist/typeGuards.d.ts +93 -0
  156. package/dist/typeGuards.js +8 -0
  157. package/dist/typeGuards.spec.cjs +101 -0
  158. package/dist/typeGuards.spec.d.ts +1 -0
  159. package/dist/typeGuards.spec.js +95 -0
  160. package/dist/types.cjs +18 -0
  161. package/dist/types.d.ts +289 -0
  162. package/dist/types.js +0 -0
  163. package/dist/union.cjs +74 -0
  164. package/dist/union.d.ts +33 -0
  165. package/dist/union.js +40 -0
  166. package/dist/union.spec.cjs +159 -0
  167. package/dist/union.spec.d.ts +1 -0
  168. package/dist/union.spec.js +153 -0
  169. package/package.json +47 -0
@@ -0,0 +1,506 @@
1
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { api, composeApi, subscription } from "./api.js";
3
+ import { fieldOperation, operation } from "./operation.js";
4
+ import { createBaseSchemaMock } from "./testing/mocks/index.js";
5
+ describe('api utilities', ()=>{
6
+ beforeAll(()=>{
7
+ vi.useRealTimers();
8
+ });
9
+ beforeEach(()=>{
10
+ vi.clearAllMocks();
11
+ });
12
+ afterEach(()=>{
13
+ vi.clearAllMocks();
14
+ });
15
+ afterAll(()=>{
16
+ vi.restoreAllMocks();
17
+ });
18
+ describe("subscription()", ()=>{
19
+ describe('happy', ()=>{
20
+ it('should include optional fields when optional values are provided', ()=>{
21
+ const payload = createBaseSchemaMock({
22
+ name: 'Payload',
23
+ type: 'payload'
24
+ });
25
+ const input = createBaseSchemaMock({
26
+ name: 'Input',
27
+ type: 'input'
28
+ });
29
+ const output = createBaseSchemaMock({
30
+ name: 'Output',
31
+ type: 'output'
32
+ });
33
+ const filter = vi.fn(()=>true);
34
+ const exec = vi.fn(()=>({
35
+ event: 'created'
36
+ }));
37
+ const result = subscription({
38
+ name: 'userCreated',
39
+ input,
40
+ payload,
41
+ output,
42
+ filter,
43
+ exec,
44
+ doc: {
45
+ summary: "subscription doc"
46
+ }
47
+ });
48
+ expect(result.type).toBe("subscription");
49
+ expect(result.name).toBe('userCreated');
50
+ expect(result.input).toBe(input);
51
+ expect(result.payload).toBe(payload);
52
+ expect(result.output).toBe(output);
53
+ expect(result.filter).toBe(filter);
54
+ expect(result.exec).toBe(exec);
55
+ expect(result.doc).toEqual({
56
+ summary: "subscription doc"
57
+ });
58
+ });
59
+ });
60
+ describe('sad', ()=>{
61
+ it('should only include mandatory payload when optional values are omitted', ()=>{
62
+ const payload = createBaseSchemaMock({
63
+ name: 'Payload',
64
+ type: 'payload'
65
+ });
66
+ const result = subscription({
67
+ payload
68
+ });
69
+ expect(result.type).toBe("subscription");
70
+ expect(result.payload).toBe(payload);
71
+ expect(result.input).toBeUndefined();
72
+ expect(result.output).toBeUndefined();
73
+ expect(result.filter).toBeUndefined();
74
+ expect(result.exec).toBeUndefined();
75
+ });
76
+ });
77
+ });
78
+ describe('api()', ()=>{
79
+ describe('happy', ()=>{
80
+ it('should merge explicit and inline operations when both are provided', ()=>{
81
+ const inputSchema = createBaseSchemaMock({
82
+ name: 'Input',
83
+ type: 'input',
84
+ outputValue: 'x'
85
+ });
86
+ const explicitOperation = operation({
87
+ input: inputSchema,
88
+ exec: async ()=>'explicit'
89
+ });
90
+ const inlineOperation = operation({
91
+ input: inputSchema,
92
+ exec: async ()=>'inline'
93
+ });
94
+ const result = api({
95
+ operations: {
96
+ explicit: explicitOperation
97
+ },
98
+ inline: inlineOperation
99
+ });
100
+ const operations = result.operations;
101
+ expect(operations.explicit?.name).toBe('explicit');
102
+ expect(operations.explicit?.exec).toBe(explicitOperation.exec);
103
+ expect(operations.inline?.name).toBe('inline');
104
+ expect(operations.inline?.exec).toBe(inlineOperation.exec);
105
+ });
106
+ it("should assign missing names to operations field operations and subscriptions", ()=>{
107
+ const entity = createBaseSchemaMock({
108
+ name: 'User',
109
+ type: 'object',
110
+ astNode: {
111
+ type: 'object',
112
+ name: 'User'
113
+ },
114
+ outputValue: {
115
+ id: 'u-1'
116
+ }
117
+ });
118
+ const inputSchema = createBaseSchemaMock({
119
+ name: 'Input',
120
+ type: 'input',
121
+ outputValue: 'x'
122
+ });
123
+ const payloadSchema = createBaseSchemaMock({
124
+ name: 'Payload',
125
+ type: 'payload'
126
+ });
127
+ const op = operation({
128
+ input: inputSchema,
129
+ exec: async ()=>'ok'
130
+ });
131
+ const fieldOp = fieldOperation({
132
+ dependsOn: entity,
133
+ exec: async ()=>'field'
134
+ });
135
+ const sub = subscription({
136
+ payload: payloadSchema
137
+ });
138
+ const result = api({
139
+ type: entity,
140
+ operations: {
141
+ createUser: op
142
+ },
143
+ fieldOperations: {
144
+ displayName: fieldOp
145
+ },
146
+ subscriptions: {
147
+ userCreated: sub
148
+ }
149
+ });
150
+ expect(result.operations.createUser.name).toBe('createUser');
151
+ expect(result.fieldOperations.displayName.name).toBe('displayName');
152
+ expect(result.subscriptions.userCreated?.name).toBe('userCreated');
153
+ });
154
+ it("should build ast with operation subscription and field nodes when ast is requested", ()=>{
155
+ const entity = createBaseSchemaMock({
156
+ name: 'User',
157
+ type: 'object',
158
+ astNode: {
159
+ type: 'object',
160
+ name: 'User'
161
+ },
162
+ outputValue: {
163
+ id: 'u-1'
164
+ }
165
+ });
166
+ const operationInput = createBaseSchemaMock({
167
+ name: 'OperationInput',
168
+ type: 'operation-input',
169
+ astNode: {
170
+ type: 'object',
171
+ name: 'OperationInput'
172
+ },
173
+ outputValue: {
174
+ name: 'Alice'
175
+ }
176
+ });
177
+ const operationOutput = createBaseSchemaMock({
178
+ name: 'OperationOutput',
179
+ type: 'operation-output',
180
+ astNode: {
181
+ type: 'object',
182
+ name: 'OperationOutput'
183
+ },
184
+ outputValue: {
185
+ id: 'u-1'
186
+ }
187
+ });
188
+ const subscriptionPayload = createBaseSchemaMock({
189
+ name: "SubscriptionPayload",
190
+ type: "subscription-payload",
191
+ astNode: {
192
+ type: 'object',
193
+ name: "SubscriptionPayload"
194
+ }
195
+ });
196
+ const fieldInput = createBaseSchemaMock({
197
+ name: 'FieldInput',
198
+ type: 'field-input',
199
+ astNode: {
200
+ type: 'object',
201
+ name: 'FieldInput'
202
+ },
203
+ outputValue: {
204
+ locale: 'en'
205
+ }
206
+ });
207
+ const fieldOutput = createBaseSchemaMock({
208
+ name: 'FieldOutput',
209
+ type: 'field-output',
210
+ astNode: {
211
+ type: 'object',
212
+ name: 'FieldOutput'
213
+ },
214
+ outputValue: {
215
+ value: 'Alice'
216
+ }
217
+ });
218
+ const createUser = operation({
219
+ input: operationInput,
220
+ output: operationOutput,
221
+ exec: async ()=>({
222
+ id: 'u-1'
223
+ }),
224
+ publish: {
225
+ userCreated: ()=>({
226
+ id: 'u-1'
227
+ })
228
+ },
229
+ ack: {
230
+ required: true,
231
+ mode: 'handled'
232
+ },
233
+ doc: {
234
+ summary: 'create user'
235
+ }
236
+ });
237
+ const displayName = fieldOperation({
238
+ dependsOn: entity,
239
+ input: fieldInput,
240
+ output: fieldOutput,
241
+ exec: async ()=>({
242
+ value: 'Alice'
243
+ }),
244
+ doc: {
245
+ summary: 'field doc'
246
+ }
247
+ });
248
+ const userCreated = subscription({
249
+ payload: subscriptionPayload,
250
+ doc: {
251
+ summary: 'sub doc'
252
+ }
253
+ });
254
+ const result = api({
255
+ doc: {
256
+ summary: 'api doc'
257
+ },
258
+ type: entity,
259
+ operations: {
260
+ createUser
261
+ },
262
+ fieldOperations: {
263
+ displayName
264
+ },
265
+ subscriptions: {
266
+ userCreated
267
+ }
268
+ });
269
+ const ast = result.ast();
270
+ const operationNode = ast.children?.find((node)=>'operation' === node.type);
271
+ const subscriptionNode = ast.children?.find((node)=>"subscription" === node.type);
272
+ const fieldNode = ast.children?.find((node)=>'field' === node.type);
273
+ expect(ast.type).toBe('api');
274
+ expect(ast.doc).toEqual({
275
+ summary: 'api doc'
276
+ });
277
+ expect(operationNode).toMatchObject({
278
+ name: 'createUser',
279
+ constraints: {
280
+ publish: [
281
+ 'userCreated'
282
+ ],
283
+ ack: {
284
+ required: true,
285
+ mode: 'handled'
286
+ },
287
+ request: 'OperationInput',
288
+ response: 'OperationOutput'
289
+ }
290
+ });
291
+ expect(subscriptionNode).toMatchObject({
292
+ name: 'userCreated',
293
+ constraints: {
294
+ payload: "SubscriptionPayload",
295
+ output: "SubscriptionPayload"
296
+ }
297
+ });
298
+ expect(fieldNode).toMatchObject({
299
+ name: 'User.displayName',
300
+ constraints: {
301
+ owner: 'User',
302
+ field: 'displayName',
303
+ request: 'FieldInput',
304
+ response: 'FieldOutput',
305
+ dependsOn: 'User'
306
+ }
307
+ });
308
+ });
309
+ });
310
+ describe('sad', ()=>{
311
+ it('should throw when field operations are provided without entity type', ()=>{
312
+ const fieldOp = fieldOperation({
313
+ dependsOn: createBaseSchemaMock({
314
+ outputValue: {
315
+ id: 'u-1'
316
+ }
317
+ }),
318
+ exec: async ()=>'field'
319
+ });
320
+ expect(()=>api({
321
+ fieldOperations: {
322
+ displayName: fieldOp
323
+ }
324
+ })).toThrowError('api.type is required when fieldOperations are provided.');
325
+ });
326
+ it("should throw when operation publishes topic without matching subscription", ()=>{
327
+ const inputSchema = createBaseSchemaMock({
328
+ outputValue: 'x'
329
+ });
330
+ const publishingOperation = operation({
331
+ input: inputSchema,
332
+ exec: async ()=>'ok',
333
+ publish: {
334
+ missingTopic: ()=>({
335
+ payload: true
336
+ })
337
+ }
338
+ });
339
+ expect(()=>api({
340
+ operations: {
341
+ createUser: publishingOperation
342
+ }
343
+ })).toThrowError('api: operation "createUser" publishes "missingTopic" but no subscription with that name exists.');
344
+ });
345
+ });
346
+ });
347
+ describe('composeApi()', ()=>{
348
+ describe('happy', ()=>{
349
+ it("should compose operations field operations and subscriptions from multiple apis", ()=>{
350
+ const userSchema = createBaseSchemaMock({
351
+ name: 'User',
352
+ type: 'object',
353
+ astNode: {
354
+ type: 'object',
355
+ name: 'User'
356
+ },
357
+ outputValue: {
358
+ id: 'u-1'
359
+ }
360
+ });
361
+ const inputSchema = createBaseSchemaMock({
362
+ outputValue: 'x'
363
+ });
364
+ const payloadSchema = createBaseSchemaMock({
365
+ name: 'Payload',
366
+ type: 'payload'
367
+ });
368
+ const usersApi = api({
369
+ type: userSchema,
370
+ operations: {
371
+ createUser: operation({
372
+ input: inputSchema,
373
+ exec: async ()=>'ok'
374
+ })
375
+ },
376
+ fieldOperations: {
377
+ displayName: fieldOperation({
378
+ dependsOn: userSchema,
379
+ exec: async ()=>'name'
380
+ })
381
+ },
382
+ subscriptions: {
383
+ userCreated: subscription({
384
+ payload: payloadSchema
385
+ })
386
+ }
387
+ });
388
+ const systemApi = api({
389
+ operations: {
390
+ health: operation({
391
+ input: inputSchema,
392
+ exec: async ()=>'ok'
393
+ })
394
+ }
395
+ });
396
+ const composed = composeApi({
397
+ users: usersApi,
398
+ system: systemApi
399
+ });
400
+ const ast = composed.ast();
401
+ expect(composed.type).toBe('api-composed');
402
+ expect(Object.keys(composed.operations)).toEqual([
403
+ 'createUser',
404
+ 'health'
405
+ ]);
406
+ expect(Object.keys(composed.fieldOperations)).toEqual([
407
+ 'User.displayName'
408
+ ]);
409
+ expect(Object.keys(composed.subscriptions)).toEqual([
410
+ 'userCreated'
411
+ ]);
412
+ expect(ast.type).toBe('api-composed');
413
+ expect(ast.children?.map((node)=>node.name)).toEqual([
414
+ 'users',
415
+ 'system'
416
+ ]);
417
+ });
418
+ });
419
+ describe('sad', ()=>{
420
+ it('should throw when two apis contain duplicate operation names', ()=>{
421
+ const inputSchema = createBaseSchemaMock({
422
+ outputValue: 'x'
423
+ });
424
+ const left = api({
425
+ operations: {
426
+ ping: operation({
427
+ input: inputSchema,
428
+ exec: async ()=>'left'
429
+ })
430
+ }
431
+ });
432
+ const right = api({
433
+ operations: {
434
+ ping: operation({
435
+ input: inputSchema,
436
+ exec: async ()=>'right'
437
+ })
438
+ }
439
+ });
440
+ expect(()=>composeApi({
441
+ left,
442
+ right
443
+ })).toThrowError('composeApi: duplicate operation name "ping"');
444
+ });
445
+ it('should throw when two apis contain duplicate field operation names', ()=>{
446
+ const owner = createBaseSchemaMock({
447
+ name: 'User',
448
+ type: 'object',
449
+ astNode: {
450
+ type: 'object',
451
+ name: 'User'
452
+ },
453
+ outputValue: {
454
+ id: 'u-1'
455
+ }
456
+ });
457
+ const left = api({
458
+ type: owner,
459
+ fieldOperations: {
460
+ displayName: fieldOperation({
461
+ dependsOn: owner,
462
+ exec: async ()=>'left'
463
+ })
464
+ }
465
+ });
466
+ const right = api({
467
+ type: owner,
468
+ fieldOperations: {
469
+ displayName: fieldOperation({
470
+ dependsOn: owner,
471
+ exec: async ()=>'right'
472
+ })
473
+ }
474
+ });
475
+ expect(()=>composeApi({
476
+ left,
477
+ right
478
+ })).toThrowError('composeApi: duplicate field operation name "User.displayName"');
479
+ });
480
+ it("should throw when two apis contain duplicate subscription names", ()=>{
481
+ const payload = createBaseSchemaMock({
482
+ name: 'Payload',
483
+ type: 'payload'
484
+ });
485
+ const left = api({
486
+ subscriptions: {
487
+ userCreated: subscription({
488
+ payload
489
+ })
490
+ }
491
+ });
492
+ const right = api({
493
+ subscriptions: {
494
+ userCreated: subscription({
495
+ payload
496
+ })
497
+ }
498
+ });
499
+ expect(()=>composeApi({
500
+ left,
501
+ right
502
+ })).toThrowError('composeApi: duplicate subscription name "userCreated"');
503
+ });
504
+ });
505
+ });
506
+ });
package/dist/array.cjs ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ array: ()=>array
28
+ });
29
+ const external_schemaFactory_cjs_namespaceObject = require("./schemaFactory.cjs");
30
+ const external_typeGuards_cjs_namespaceObject = require("./typeGuards.cjs");
31
+ const array = ({ name, item, doc })=>(0, external_schemaFactory_cjs_namespaceObject.schemaFactory)({
32
+ name,
33
+ type: `array<${item.name}>`,
34
+ doc,
35
+ ast: (ctx)=>{
36
+ const build = ctx.getBuildContext();
37
+ return {
38
+ type: 'array',
39
+ name,
40
+ children: [
41
+ item.ast(build ?? void 0)
42
+ ]
43
+ };
44
+ },
45
+ validate: (input, ctx)=>{
46
+ if (!(0, external_typeGuards_cjs_namespaceObject.isArray)()(input)) throw {
47
+ message: 'Expected array',
48
+ code: 'array.type'
49
+ };
50
+ const values = [];
51
+ input.forEach((value, index)=>{
52
+ try {
53
+ values.push(item.parse(value, ctx));
54
+ } catch (error) {
55
+ throw {
56
+ message: `Invalid item at index ${index}`,
57
+ code: 'array.item',
58
+ context: {
59
+ index,
60
+ error
61
+ }
62
+ };
63
+ }
64
+ });
65
+ return values;
66
+ }
67
+ });
68
+ exports.array = __webpack_exports__.array;
69
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
70
+ "array"
71
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
72
+ Object.defineProperty(exports, '__esModule', {
73
+ value: true
74
+ });
@@ -0,0 +1,25 @@
1
+ import { Schema, SchemaDoc } from './types.js';
2
+ export interface ArraySchemaInput<T> {
3
+ name: string;
4
+ item: Schema<T>;
5
+ doc?: SchemaDoc;
6
+ }
7
+ /**
8
+ * array is part of the public LIVON API.
9
+ *
10
+ * @remarks
11
+ * Parameter and return types are defined in the TypeScript signature.
12
+ *
13
+ * @see https://live-input-vector-output-node.github.io/livon-ts/docs/schema/array
14
+ *
15
+ * @example
16
+ * // Creates an array schema that validates string items.
17
+ * const Tags = array({ name: 'tags', item: string() });
18
+ * Tags.parse(['typescript', 'schema']);
19
+ *
20
+ * @example
21
+ * // Extends the array schema to also allow undefined.
22
+ * const OptionalTags = array({ name: 'tags', item: string() }).optional();
23
+ * OptionalTags.parse(undefined);
24
+ */
25
+ export declare const array: <T>({ name, item, doc }: ArraySchemaInput<T>) => import("./schemaFactory.js").SchemaWithChain<T[], import("./schemaFactory.js").SchemaFactoryChainDefinition<T[]>>;
package/dist/array.js ADDED
@@ -0,0 +1,40 @@
1
+ import { schemaFactory } from "./schemaFactory.js";
2
+ import { isArray } from "./typeGuards.js";
3
+ const array = ({ name, item, doc })=>schemaFactory({
4
+ name,
5
+ type: `array<${item.name}>`,
6
+ doc,
7
+ ast: (ctx)=>{
8
+ const build = ctx.getBuildContext();
9
+ return {
10
+ type: 'array',
11
+ name,
12
+ children: [
13
+ item.ast(build ?? void 0)
14
+ ]
15
+ };
16
+ },
17
+ validate: (input, ctx)=>{
18
+ if (!isArray()(input)) throw {
19
+ message: 'Expected array',
20
+ code: 'array.type'
21
+ };
22
+ const values = [];
23
+ input.forEach((value, index)=>{
24
+ try {
25
+ values.push(item.parse(value, ctx));
26
+ } catch (error) {
27
+ throw {
28
+ message: `Invalid item at index ${index}`,
29
+ code: 'array.item',
30
+ context: {
31
+ index,
32
+ error
33
+ }
34
+ };
35
+ }
36
+ });
37
+ return values;
38
+ }
39
+ });
40
+ export { array };