@esmj/schema 0.2.0 → 0.2.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.
package/README.md CHANGED
@@ -24,7 +24,7 @@ When choosing a schema validation library, bundle size can be an important facto
24
24
 
25
25
  | Library | Bundle Size (minified + gzipped) |
26
26
  |------------------|---------------------------------|
27
- | `@esmj/schema` | ~1 KB |
27
+ | `@esmj/schema` | `~1 KB` |
28
28
  | Superstruct | ~3.2 KB |
29
29
  | Yup | ~12.2 KB |
30
30
  | Zod@3 | ~13 KB |
@@ -36,22 +36,22 @@ When choosing a schema validation library, bundle size can be an important facto
36
36
 
37
37
  #### Schema Creation Performance
38
38
 
39
- | Library | 1 Iteration | 1,000 Iterations | 1,000,000 Iterations |
39
+ | Library | 1 Schema | 1,000 Schema | 1,000,000 Schema |
40
40
  |-----------------|-------------|------------------|----------------------|
41
- | `@esmj/schema` | 0.02 ms | 4.93 ms | 399.62 ms |
41
+ | `@esmj/schema` | `0.02 ms` | 4.93 ms | `399.62 ms` |
42
42
  | zod@3 | 0.08 ms | 9.68 ms | 8.53 s |
43
43
  | @zod/mini | 0.22 ms | 39.77 ms | 34.51 s |
44
44
  | Yup | 0.54 ms | 14.03 ms | 12.34 s |
45
- | Superstruct | 0.13 ms | 1.04 ms | 487.94 ms |
45
+ | Superstruct | 0.13 ms | `1.04 ms` | 487.94 ms |
46
46
  | Joi | 0.62 ms | 31.60 ms | 23.06 s |
47
47
 
48
48
  #### Parsing Performance
49
49
 
50
50
  | Library | 1 Iteration | 1,000 Iterations | 1,000,000 Iterations |
51
51
  |-----------------|-------------|------------------|----------------------|
52
- | `@esmj/schema` | 0.05 ms | 0.46 ms | 267.93 ms |
52
+ | `@esmj/schema` | `0.05 ms` | 0.46 ms | 267.93 ms |
53
53
  | zod@3 | 0.14 ms | 1.44 ms | 897.89 ms |
54
- | @zod/mini | 0.23 ms | 0.42 ms | 199.08 ms |
54
+ | @zod/mini | 0.23 ms | `0.42 ms` | `199.08 ms` |
55
55
  | Yup | 0.30 ms | 9.49 ms | 8.69 s |
56
56
  | Superstruct | 0.08 ms | 4.18 ms | 3.71 s |
57
57
  | Joi | 0.33 ms | 3.35 ms | 2.69 s |
@@ -60,13 +60,15 @@ When choosing a schema validation library, bundle size can be an important facto
60
60
 
61
61
  | Library | 1 Iteration | 1,000 Iterations | 1,000,000 Iterations |
62
62
  |-----------------|-------------|------------------|----------------------|
63
- | `@esmj/schema` | 0.03 ms | 0.59 ms | 365.32 ms |
63
+ | `@esmj/schema` | `0.03 ms` | `0.59 ms` | `365.32 ms` |
64
64
  | zod3 | 0.05 ms | 2.09 ms | 1.26 s |
65
65
  | @zod/mini | 0.07 ms | 0.99 ms | 545.12 ms |
66
66
  | Yup | 0.27 ms | 19.28 ms | 18.87 s |
67
67
  | Superstruct | 0.04 ms | 8.62 ms | 6.24 s |
68
68
  | Joi | 0.15 ms | 4.13 ms | 2.57 s |
69
69
 
70
+ **Note:** During the performance tests, `@zod/mini` was observed to consume 200% CPU, while other libraries used only 100% CPU. This may affect the interpretation of the results, especially in multi-threaded environments.
71
+
70
72
  ## Usage
71
73
 
72
74
  ### Basic Usage
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@esmj/schema",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Tiny extendable package for schema validation.",
5
5
  "keywords": [
6
6
  "schema",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "lint": "biome check --no-errors-on-unmatched",
24
24
  "lint:fix": "npm run lint -- --fix --unsafe",
25
- "benchmark": "node benchmark/index.ts",
25
+ "benchmark": "node benchmark/benchmark.ts",
26
26
  "dev": "node_modules/.bin/tsup --dts --watch --onSuccess 'node ./dist/index.mjs'",
27
27
  "test": "node --test --experimental-strip-types",
28
28
  "test:watch": "npm run test -- --watch",
@@ -1,585 +0,0 @@
1
- import { performance } from 'node:perf_hooks';
2
- import { z as zodMini } from '@zod/mini'; // Import Zod Mini
3
- import Joi from 'joi'; // Import Joi
4
- import superStruct from 'superstruct'; // Import Superstruct
5
- import * as yup from 'yup'; // Import Yup
6
- import { z } from 'zod'; // Import Zod
7
- import { s } from '../src/index.ts'; // Import @esmj/schema
8
-
9
- function formatTime(time: number) {
10
- // Convert time to milliseconds
11
- if (time < 1000) {
12
- return `${time.toFixed(2)} ms`;
13
- }
14
- // Convert to seconds
15
- const seconds = time / 1000;
16
- return `${seconds.toFixed(2)} s`;
17
- }
18
-
19
- function benchmark(label: string, fn: () => void) {
20
- const REPEAT = 10;
21
- let sum = 0;
22
- let min = Number.POSITIVE_INFINITY;
23
- let max = Number.NEGATIVE_INFINITY;
24
- for (let i = 0; i < REPEAT; i++) {
25
- const start = performance.now();
26
- fn();
27
- const end = performance.now();
28
-
29
- const time = end - start;
30
-
31
- min = Math.min(min, time);
32
- max = Math.max(max, time);
33
- sum += time;
34
- }
35
-
36
- const average = sum / REPEAT;
37
-
38
- console.log(
39
- `${label} took an average of ${formatTime(average)} over ${REPEAT} iterations. Min: ${formatTime(min)}, Max: ${formatTime(max)}`,
40
- );
41
-
42
- return formatTime(average);
43
- }
44
-
45
- function scenarioParseSchema(testData) {
46
- // Define a schema using @esmj/schema
47
- const esmjSchema = s.object({
48
- username: s.string(),
49
- password: s.string(),
50
- age: s.number().optional(),
51
- address: s.object({
52
- street: s.string().nullish(),
53
- city: s.string().nullable(),
54
- date: s.date().optional(), // Optional date field
55
- }),
56
- tags: s.array(s.string()),
57
- });
58
-
59
- // Define a schema using Zod
60
- const zodSchema = z.object({
61
- username: z.string(),
62
- password: z.string(),
63
- age: z.number().optional(),
64
- address: z.object({
65
- street: z.string().nullish(),
66
- city: z.string().nullable(),
67
- date: z.date().optional(), // Optional date field
68
- }),
69
- tags: z.array(z.string()),
70
- });
71
-
72
- // Define a schema using Zod Mini
73
- const zodMiniSchema = zodMini.object({
74
- username: zodMini.string(),
75
- password: zodMini.string(),
76
- age: zodMini.optional(zodMini.number()),
77
- address: zodMini.object({
78
- street: zodMini.nullish(zodMini.string()),
79
- city: zodMini.nullable(zodMini.string()),
80
- date: zodMini.optional(zodMini.date()), // Optional date field
81
- }),
82
- tags: zodMini.array(zodMini.string()),
83
- });
84
-
85
- // Define a schema using Yup
86
- const yupSchema = yup.object({
87
- username: yup.string().required(),
88
- password: yup.string().required(),
89
- age: yup.number().optional(),
90
- address: yup.object({
91
- street: yup.string().nullable(),
92
- city: yup.string().nullable(),
93
- date: yup.date().optional(), // Optional date field
94
- }),
95
- tags: yup.array().of(yup.string().required()).required(),
96
- });
97
-
98
- // Define a schema using Superstruct
99
- const superStructSchema = superStruct.object({
100
- username: superStruct.string(),
101
- password: superStruct.string(),
102
- age: superStruct.number(),
103
- address: superStruct.object({
104
- street: superStruct.optional(superStruct.string()),
105
- city: superStruct.optional(superStruct.string()),
106
- date: superStruct.optional(superStruct.date()), // Optional date field
107
- }),
108
- tags: superStruct.array(superStruct.string()),
109
- });
110
-
111
- // Define a schema using Joi
112
- const joiSchema = Joi.object({
113
- username: Joi.string().required(),
114
- password: Joi.string().required(),
115
- age: Joi.number().required(),
116
- address: Joi.object({
117
- street: Joi.string().optional(), // Allow null for street
118
- city: Joi.string().optional(),
119
- date: Joi.date().optional(), // Optional date field
120
- }),
121
- tags: Joi.array().items(Joi.string().required()).required(),
122
- });
123
-
124
- const result = {} as Record<string, object>;
125
-
126
- const esmjSchemaResult = {};
127
- esmjSchemaResult['1'] = benchmark('@esmj/schema 1', () => {
128
- for (let i = 0; i < 1; i++) {
129
- esmjSchema.safeParse(testData);
130
- }
131
- });
132
-
133
- esmjSchemaResult['1_000'] = benchmark('@esmj/schema 1_000', () => {
134
- for (let i = 0; i < 1_000; i++) {
135
- esmjSchema.safeParse(testData);
136
- }
137
- });
138
-
139
- esmjSchemaResult['1_000_000'] = benchmark('@esmj/schema 1_000_000', () => {
140
- for (let i = 0; i < 1_000_000; i++) {
141
- esmjSchema.safeParse(testData);
142
- }
143
- });
144
- result.esmjSchema = esmjSchemaResult;
145
-
146
- const zod = {};
147
- zod['1'] = benchmark('zod 1', () => {
148
- for (let i = 0; i < 1; i++) {
149
- zodSchema.safeParse(testData);
150
- }
151
- });
152
-
153
- zod['1_000'] = benchmark('zod 1_000', () => {
154
- for (let i = 0; i < 1_000; i++) {
155
- zodSchema.safeParse(testData);
156
- }
157
- });
158
-
159
- zod['1_000_000'] = benchmark('zod 1_000_000', () => {
160
- for (let i = 0; i < 1_000_000; i++) {
161
- zodSchema.safeParse(testData);
162
- }
163
- });
164
- result.zod = zod;
165
-
166
- const zodMiniResult = {};
167
- zodMiniResult['1'] = benchmark('@zod/mini 1', () => {
168
- for (let i = 0; i < 1; i++) {
169
- zodMiniSchema.safeParse(testData);
170
- }
171
- });
172
-
173
- zodMiniResult['1_000'] = benchmark('@zod/mini 1_000', () => {
174
- for (let i = 0; i < 1_000; i++) {
175
- zodMiniSchema.safeParse(testData);
176
- }
177
- });
178
-
179
- zodMiniResult['1_000_000'] = benchmark('@zod/mini 1_000_000', () => {
180
- for (let i = 0; i < 1_000_000; i++) {
181
- zodMiniSchema.safeParse(testData);
182
- }
183
- });
184
- result.zodMini = zodMiniResult;
185
-
186
- const yupResult = {};
187
- yupResult['1'] = benchmark('yup 1', () => {
188
- for (let i = 0; i < 1; i++) {
189
- yupSchema.isValidSync(testData);
190
- }
191
- });
192
-
193
- yupResult['1_000'] = benchmark('yup 1_000', () => {
194
- for (let i = 0; i < 1_000; i++) {
195
- yupSchema.isValidSync(testData);
196
- }
197
- });
198
-
199
- yupResult['1_000_000'] = benchmark('yup 1_000_000', () => {
200
- for (let i = 0; i < 1_000_000; i++) {
201
- yupSchema.isValidSync(testData);
202
- }
203
- });
204
- result.yup = yupResult;
205
-
206
- const superStructResult = {};
207
- superStructResult['1'] = benchmark('superStruct 1', () => {
208
- for (let i = 0; i < 1; i++) {
209
- superStruct.is(testData, superStructSchema);
210
- }
211
- });
212
-
213
- superStructResult['1_000'] = benchmark('superStruct 1_000', () => {
214
- for (let i = 0; i < 1_000; i++) {
215
- superStruct.is(testData, superStructSchema);
216
- }
217
- });
218
-
219
- superStructResult['1_000_000'] = benchmark('superStruct 1_000_000', () => {
220
- for (let i = 0; i < 1_000_000; i++) {
221
- superStruct.is(testData, superStructSchema);
222
- }
223
- });
224
- result.superStruct = superStructResult;
225
-
226
- const joiResult = {};
227
- joiResult['1'] = benchmark('joi 1', () => {
228
- for (let i = 0; i < 1; i++) {
229
- try {
230
- joiSchema.validate(testData);
231
- } catch (e) {}
232
- }
233
- });
234
-
235
- joiResult['1_000'] = benchmark('joi 1_000', () => {
236
- for (let i = 0; i < 1_000; i++) {
237
- try {
238
- joiSchema.validate(testData);
239
- } catch (e) {}
240
- }
241
- });
242
-
243
- joiResult['1_000_000'] = benchmark('joi 1_000_000', () => {
244
- for (let i = 0; i < 1_000_000; i++) {
245
- try {
246
- joiSchema.validate(testData);
247
- } catch (e) {}
248
- }
249
- });
250
- result.joi = joiResult;
251
-
252
- return result;
253
- }
254
-
255
- function scenarioCreatingSchema() {
256
- const result = {} as Record<string, object>;
257
- const esmjSchemaResult = {};
258
- esmjSchemaResult['1'] = benchmark('@esmj/schema 1', () => {
259
- for (let i = 0; i < 1; i++) {
260
- const esmjSchema = s.object({
261
- username: s.string(),
262
- password: s.string(),
263
- age: s.number().optional(),
264
- address: s.object({
265
- street: s.string().nullish(),
266
- city: s.string().nullable(),
267
- date: s.date().optional(), // Optional date field
268
- }),
269
- tags: s.array(s.string()),
270
- });
271
- }
272
- });
273
-
274
- esmjSchemaResult['1_000'] = benchmark('@esmj/schema 1_000', () => {
275
- for (let i = 0; i < 1_000; i++) {
276
- const esmjSchema = s.object({
277
- username: s.string(),
278
- password: s.string(),
279
- age: s.number().optional(),
280
- address: s.object({
281
- street: s.string().nullish(),
282
- city: s.string().nullable(),
283
- date: s.date().optional(), // Optional date field
284
- }),
285
- tags: s.array(s.string()),
286
- });
287
- }
288
- });
289
-
290
- esmjSchemaResult['1_000_000'] = benchmark('@esmj/schema 1_000_000', () => {
291
- for (let i = 0; i < 1_000_000; i++) {
292
- const esmjSchema = s.object({
293
- username: s.string(),
294
- password: s.string(),
295
- age: s.number().optional(),
296
- address: s.object({
297
- street: s.string().nullish(),
298
- city: s.string().nullable(),
299
- date: s.date().optional(), // Optional date field
300
- }),
301
- tags: s.array(s.string()),
302
- });
303
- }
304
- });
305
- result.esmjSchema = esmjSchemaResult;
306
-
307
- const zod = {};
308
- zod['1'] = benchmark('zod 1', () => {
309
- for (let i = 0; i < 1; i++) {
310
- const zodSchema = z.object({
311
- username: z.string(),
312
- password: z.string(),
313
- age: z.number().optional(),
314
- address: z.object({
315
- street: z.string().nullish(),
316
- city: z.string().nullable(),
317
- date: z.date().optional(), // Optional date field
318
- }),
319
- tags: z.array(z.string()),
320
- });
321
- }
322
- });
323
-
324
- zod['1_000'] = benchmark('zod 1_000', () => {
325
- for (let i = 0; i < 1_000; i++) {
326
- const zodSchema = z.object({
327
- username: z.string(),
328
- password: z.string(),
329
- age: z.number().optional(),
330
- address: z.object({
331
- street: z.string().nullish(),
332
- city: z.string().nullable(),
333
- date: z.date().optional(), // Optional date field
334
- }),
335
- tags: z.array(z.string()),
336
- });
337
- }
338
- });
339
-
340
- zod['1_000_000'] = benchmark('zod 1_000_000', () => {
341
- for (let i = 0; i < 1_000_000; i++) {
342
- const zodSchema = z.object({
343
- username: z.string(),
344
- password: z.string(),
345
- age: z.number().optional(),
346
- address: z.object({
347
- street: z.string().nullish(),
348
- city: z.string().nullable(),
349
- date: z.date().optional(), // Optional date field
350
- }),
351
- tags: z.array(z.string()),
352
- });
353
- }
354
- });
355
- result.zod = zod;
356
-
357
- const zodMiniResult = {};
358
- zodMiniResult['1'] = benchmark('@zod/mini 1', () => {
359
- for (let i = 0; i < 1; i++) {
360
- const zodMiniSchema = zodMini.object({
361
- username: zodMini.string(),
362
- password: zodMini.string(),
363
- age: zodMini.optional(zodMini.number()),
364
- address: zodMini.object({
365
- street: zodMini.nullish(zodMini.string()),
366
- city: zodMini.nullable(zodMini.string()),
367
- date: zodMini.optional(zodMini.date()), // Optional date field
368
- }),
369
- tags: zodMini.array(zodMini.string()),
370
- });
371
- }
372
- });
373
-
374
- zodMiniResult['1_000'] = benchmark('@zod/mini 1_000', () => {
375
- for (let i = 0; i < 1_000; i++) {
376
- const zodMiniSchema = zodMini.object({
377
- username: zodMini.string(),
378
- password: zodMini.string(),
379
- age: zodMini.optional(zodMini.number()),
380
- address: zodMini.object({
381
- street: zodMini.nullish(zodMini.string()),
382
- city: zodMini.nullable(zodMini.string()),
383
- date: zodMini.optional(zodMini.date()), // Optional date field
384
- }),
385
- tags: zodMini.array(zodMini.string()),
386
- });
387
- }
388
- });
389
-
390
- zodMiniResult['1_000_000'] = benchmark('@zod/mini 1_000_000', () => {
391
- for (let i = 0; i < 1_000_000; i++) {
392
- const zodMiniSchema = zodMini.object({
393
- username: zodMini.string(),
394
- password: zodMini.string(),
395
- age: zodMini.optional(zodMini.number()),
396
- address: zodMini.object({
397
- street: zodMini.nullish(zodMini.string()),
398
- city: zodMini.nullable(zodMini.string()),
399
- date: zodMini.optional(zodMini.date()), // Optional date field
400
- }),
401
- tags: zodMini.array(zodMini.string()),
402
- });
403
- }
404
- });
405
- result.zodMini = zodMiniResult;
406
-
407
- const yupResult = {};
408
- yupResult['1'] = benchmark('yup 1', () => {
409
- for (let i = 0; i < 1; i++) {
410
- const yupSchema = yup.object({
411
- username: yup.string().required(),
412
- password: yup.string().required(),
413
- age: yup.number().optional(),
414
- address: yup.object({
415
- street: yup.string().nullable(),
416
- city: yup.string().nullable(),
417
- date: yup.date().optional(), // Optional date field
418
- }),
419
- tags: yup.array().of(yup.string().required()).required(),
420
- });
421
- }
422
- });
423
-
424
- yupResult['1_000'] = benchmark('yup 1_000', () => {
425
- for (let i = 0; i < 1_000; i++) {
426
- const yupSchema = yup.object({
427
- username: yup.string().required(),
428
- password: yup.string().required(),
429
- age: yup.number().optional(),
430
- address: yup.object({
431
- street: yup.string().nullable(),
432
- city: yup.string().nullable(),
433
- date: yup.date().optional(), // Optional date field
434
- }),
435
- tags: yup.array().of(yup.string().required()).required(),
436
- });
437
- }
438
- });
439
-
440
- yupResult['1_000_000'] = benchmark('yup 1_000_000', () => {
441
- for (let i = 0; i < 1_000_000; i++) {
442
- const yupSchema = yup.object({
443
- username: yup.string().required(),
444
- password: yup.string().required(),
445
- age: yup.number().optional(),
446
- address: yup.object({
447
- street: yup.string().nullable(),
448
- city: yup.string().nullable(),
449
- date: yup.date().optional(), // Optional date field
450
- }),
451
- tags: yup.array().of(yup.string().required()).required(),
452
- });
453
- }
454
- });
455
- result.yup = yupResult;
456
-
457
- const superStructResult = {};
458
- superStructResult['1'] = benchmark('superStruct 1', () => {
459
- for (let i = 0; i < 1; i++) {
460
- const superStructSchema = superStruct.object({
461
- username: superStruct.string(),
462
- password: superStruct.string(),
463
- age: superStruct.number(),
464
- address: superStruct.object({
465
- street: superStruct.optional(superStruct.string()),
466
- city: superStruct.optional(superStruct.string()),
467
- date: superStruct.optional(superStruct.date()), // Optional date field
468
- }),
469
- tags: superStruct.array(superStruct.string()),
470
- });
471
- }
472
- });
473
-
474
- superStructResult['1_000'] = benchmark('superStruct 1_000', () => {
475
- for (let i = 0; i < 1_000; i++) {
476
- const superStructSchema = superStruct.object({
477
- username: superStruct.string(),
478
- password: superStruct.string(),
479
- age: superStruct.number(),
480
- address: superStruct.object({
481
- street: superStruct.optional(superStruct.string()),
482
- city: superStruct.optional(superStruct.string()),
483
- date: superStruct.optional(superStruct.date()), // Optional date field
484
- }),
485
- tags: superStruct.array(superStruct.string()),
486
- });
487
- }
488
- });
489
-
490
- superStructResult['1_000_000'] = benchmark('superStruct 1_000_000', () => {
491
- for (let i = 0; i < 1_000_000; i++) {
492
- const superStructSchema = superStruct.object({
493
- username: superStruct.string(),
494
- password: superStruct.string(),
495
- age: superStruct.number(),
496
- address: superStruct.object({
497
- street: superStruct.optional(superStruct.string()),
498
- city: superStruct.optional(superStruct.string()),
499
- date: superStruct.optional(superStruct.date()), // Optional date field
500
- }),
501
- tags: superStruct.array(superStruct.string()),
502
- });
503
- }
504
- });
505
- result.superStruct = superStructResult;
506
-
507
- const joiResult = {};
508
- joiResult['1'] = benchmark('joi 1', () => {
509
- for (let i = 0; i < 1; i++) {
510
- const joiSchema = Joi.object({
511
- username: Joi.string().required(),
512
- password: Joi.string().required(),
513
- age: Joi.number().required(),
514
- address: Joi.object({
515
- street: Joi.string().optional(), // Allow null for street
516
- city: Joi.string().optional(),
517
- date: Joi.date().optional(), // Optional date field
518
- }),
519
- tags: Joi.array().items(Joi.string().required()).required(),
520
- });
521
- }
522
- });
523
-
524
- joiResult['1_000'] = benchmark('joi 1_000', () => {
525
- for (let i = 0; i < 1_000; i++) {
526
- const joiSchema = Joi.object({
527
- username: Joi.string().required(),
528
- password: Joi.string().required(),
529
- age: Joi.number().required(),
530
- address: Joi.object({
531
- street: Joi.string().optional(), // Allow null for street
532
- city: Joi.string().optional(),
533
- date: Joi.date().optional(), // Optional date field
534
- }),
535
- tags: Joi.array().items(Joi.string().required()).required(),
536
- });
537
- }
538
- });
539
-
540
- joiResult['1_000_000'] = benchmark('joi 1_000_000', () => {
541
- for (let i = 0; i < 1_000_000; i++) {
542
- const joiSchema = Joi.object({
543
- username: Joi.string().required(),
544
- password: Joi.string().required(),
545
- age: Joi.number().required(),
546
- address: Joi.object({
547
- street: Joi.string().optional(), // Allow null for street
548
- city: Joi.string().optional(),
549
- date: Joi.date().optional(), // Optional date field
550
- }),
551
- tags: Joi.array().items(Joi.string().required()).required(),
552
- });
553
- }
554
- });
555
- result.joi = joiResult;
556
-
557
- return result;
558
- }
559
-
560
- const testDataGood = {
561
- username: 'john_doe',
562
- password: 'securepassword',
563
- age: 30,
564
- address: {
565
- street: '123 Main St',
566
- city: 'New York',
567
- date: new Date(),
568
- },
569
- tags: ['developer', 'typescript'],
570
- };
571
-
572
- const testDataBad = {
573
- username: 'john_doe',
574
- password: 'securepassword',
575
- age: 30,
576
- address: {
577
- street: '123 Main St',
578
- city: 'New York',
579
- date: new Date(),
580
- },
581
- };
582
-
583
- console.table(scenarioCreatingSchema());
584
- console.table(scenarioParseSchema(testDataGood));
585
- console.table(scenarioParseSchema(testDataBad));