ejv 2.1.0 → 2.1.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.
@@ -0,0 +1,1336 @@
1
+ import { EjvError } from './interfaces.js';
2
+ import { DATA_TYPE, ERROR_MESSAGE, ERROR_TYPE, NUMBER_FORMAT, STRING_FORMAT } from './constants.js';
3
+ import { arrayTester, arrayTypeOfTester, booleanTester, dateFormatTester, dateTester, dateTimeFormatTester, definedTester, emailTester, enumTester, exclusiveMaxDateTester, exclusiveMaxNumberTester, exclusiveMinDateTester, exclusiveMinNumberTester, hasPropertyTester, indexTester, integerTester, lengthTester, maxDateTester, maxLengthTester, maxNumberTester, minDateTester, minLengthTester, minNumberTester, notEnumTester, numberTester, objectTester, regExpTester, stringRegExpTester, stringTester, timeFormatTester, typeTester, uniqueItemsTester } from './tester.js';
4
+ import { clone, createErrorMsg, sift } from './util.js';
5
+ function _getEffectiveTypes(scheme) {
6
+ let result;
7
+ if (definedTester(scheme.type)) {
8
+ result = (arrayTester(scheme.type)
9
+ ? scheme.type
10
+ : [scheme.type]);
11
+ }
12
+ else if (definedTester(scheme.parent)) {
13
+ result = _getEffectiveTypes(scheme.parent);
14
+ }
15
+ return result;
16
+ }
17
+ const _ejv = (data, schemes, options) => {
18
+ // check schemes
19
+ if (!definedTester(schemes) || schemes === null) {
20
+ return new EjvError({
21
+ type: ERROR_TYPE.NO_SCHEME,
22
+ message: ERROR_MESSAGE.NO_SCHEME,
23
+ data: data,
24
+ errorScheme: schemes,
25
+ isSchemeError: true
26
+ });
27
+ }
28
+ if (!arrayTester(schemes)) {
29
+ return new EjvError({
30
+ type: ERROR_TYPE.INVALID_SCHEMES,
31
+ message: ERROR_MESSAGE.NO_ARRAY_SCHEME,
32
+ data: data,
33
+ errorScheme: schemes,
34
+ isSchemeError: true
35
+ });
36
+ }
37
+ if (!arrayTypeOfTester(schemes, DATA_TYPE.OBJECT)) {
38
+ return new EjvError({
39
+ type: ERROR_TYPE.INVALID_SCHEMES,
40
+ message: ERROR_MESSAGE.NO_OBJECT_ARRAY_SCHEME,
41
+ data: data,
42
+ errorScheme: schemes,
43
+ isSchemeError: true
44
+ });
45
+ }
46
+ if (!minLengthTester(schemes, 1)) {
47
+ return new EjvError({
48
+ type: ERROR_TYPE.INVALID_SCHEMES,
49
+ message: ERROR_MESSAGE.EMPTY_SCHEME,
50
+ data: data,
51
+ errorScheme: schemes,
52
+ isSchemeError: true
53
+ });
54
+ }
55
+ // check data by schemes
56
+ let result = null;
57
+ // use for() instead of forEach() to stop
58
+ for (const scheme of schemes) {
59
+ const key = scheme.key;
60
+ const _options = clone(options); // divide instance
61
+ let value;
62
+ if (key) {
63
+ value = data[key];
64
+ _options.path.push(key);
65
+ }
66
+ const types = _getEffectiveTypes(scheme);
67
+ if (!definedTester(types)) {
68
+ return new EjvError({
69
+ type: ERROR_TYPE.INVALID_SCHEMES,
70
+ message: ERROR_MESSAGE.SCHEMES_SHOULD_HAVE_TYPE,
71
+ data: data,
72
+ errorScheme: scheme,
73
+ isSchemeError: true
74
+ });
75
+ }
76
+ const allDataType = Object.values(DATA_TYPE);
77
+ const typeError = types.find((type) => {
78
+ return !definedTester(type)
79
+ || !stringTester(type)
80
+ || !enumTester(type, allDataType);
81
+ });
82
+ if (typeError) {
83
+ return new EjvError({
84
+ type: ERROR_TYPE.INVALID_SCHEMES,
85
+ message: createErrorMsg(ERROR_MESSAGE.SCHEMES_HAS_INVALID_TYPE, {
86
+ placeholders: [typeError]
87
+ }),
88
+ data: data,
89
+ errorScheme: scheme,
90
+ isSchemeError: true
91
+ });
92
+ }
93
+ if (!uniqueItemsTester(types)) {
94
+ const notUniqueItems = types.filter((type) => {
95
+ return types.filter((_type) => _type === type).length > 1;
96
+ });
97
+ const notUniqueItemsSifted = sift(notUniqueItems);
98
+ return new EjvError({
99
+ type: ERROR_TYPE.INVALID_SCHEMES,
100
+ message: createErrorMsg(ERROR_MESSAGE.SCHEMES_HAS_DUPLICATED_TYPE, {
101
+ placeholders: [notUniqueItemsSifted.join(', ')]
102
+ }),
103
+ data: data,
104
+ errorScheme: scheme,
105
+ isSchemeError: true
106
+ });
107
+ }
108
+ if (!definedTester(value)) {
109
+ if (scheme.optional !== true) {
110
+ result = new EjvError({
111
+ type: ERROR_TYPE.REQUIRED,
112
+ message: createErrorMsg(ERROR_MESSAGE.REQUIRED),
113
+ data,
114
+ path: _options.path,
115
+ errorScheme: scheme,
116
+ errorData: value
117
+ });
118
+ break;
119
+ }
120
+ else {
121
+ continue;
122
+ }
123
+ }
124
+ if (value === null) {
125
+ if (scheme.nullable !== true) {
126
+ result = new EjvError({
127
+ type: ERROR_TYPE.REQUIRED,
128
+ message: createErrorMsg(ERROR_MESSAGE.REQUIRED),
129
+ data,
130
+ path: _options.path,
131
+ errorScheme: scheme,
132
+ errorData: value
133
+ });
134
+ break;
135
+ }
136
+ else {
137
+ continue;
138
+ }
139
+ }
140
+ const typeResolved = types.find((type) => {
141
+ return typeTester(value, type);
142
+ });
143
+ if (typeResolved) {
144
+ if (definedTester(scheme.type)) {
145
+ if (!arrayTester(scheme.type)) {
146
+ if (scheme.type !== typeResolved) {
147
+ result = new EjvError({
148
+ type: ERROR_TYPE.TYPE_MISMATCH,
149
+ message: createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH, {
150
+ placeholders: [scheme.type]
151
+ }),
152
+ data,
153
+ path: _options.path,
154
+ errorScheme: scheme,
155
+ errorData: value
156
+ });
157
+ }
158
+ }
159
+ else {
160
+ if (!scheme.type.includes(typeResolved)) {
161
+ result = new EjvError({
162
+ type: ERROR_TYPE.TYPE_MISMATCH_ONE_OF,
163
+ message: createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH_ONE_OF, {
164
+ placeholders: [JSON.stringify(scheme.type)]
165
+ }),
166
+ data,
167
+ path: _options.path,
168
+ errorScheme: scheme,
169
+ errorData: value
170
+ });
171
+ }
172
+ }
173
+ }
174
+ // else do additional validation
175
+ }
176
+ else {
177
+ // type is not resolved
178
+ const typesForMsg = scheme.type || scheme.parent?.type;
179
+ if (!arrayTester(typesForMsg)) {
180
+ result = new EjvError({
181
+ type: ERROR_TYPE.TYPE_MISMATCH,
182
+ message: createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH, {
183
+ placeholders: [typesForMsg]
184
+ }),
185
+ data,
186
+ path: _options.path,
187
+ errorScheme: scheme,
188
+ errorData: value
189
+ });
190
+ }
191
+ else {
192
+ result = new EjvError({
193
+ type: ERROR_TYPE.TYPE_MISMATCH_ONE_OF,
194
+ message: createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH_ONE_OF, {
195
+ placeholders: [JSON.stringify(typesForMsg)]
196
+ }),
197
+ data,
198
+ path: _options.path,
199
+ errorScheme: scheme,
200
+ errorData: value
201
+ });
202
+ }
203
+ break;
204
+ }
205
+ // additional check for type resolved
206
+ switch (typeResolved) {
207
+ case DATA_TYPE.NUMBER: {
208
+ const valueAsNumber = value;
209
+ const numberScheme = scheme;
210
+ if (definedTester(numberScheme.enum)) {
211
+ if (!arrayTester(numberScheme.enum)) {
212
+ return new EjvError({
213
+ type: ERROR_TYPE.INVALID_SCHEMES,
214
+ message: createErrorMsg(ERROR_MESSAGE.ENUM_SHOULD_BE_ARRAY),
215
+ data: data,
216
+ errorScheme: numberScheme,
217
+ isSchemeError: true
218
+ });
219
+ }
220
+ const enumArr = numberScheme.enum;
221
+ if (!arrayTypeOfTester(enumArr, DATA_TYPE.NUMBER)) {
222
+ return new EjvError({
223
+ type: ERROR_TYPE.INVALID_SCHEMES,
224
+ message: createErrorMsg(ERROR_MESSAGE.ENUM_SHOULD_BE_NUMBERS),
225
+ data: data,
226
+ errorScheme: numberScheme,
227
+ isSchemeError: true
228
+ });
229
+ }
230
+ if (!enumTester(valueAsNumber, enumArr)) {
231
+ result = new EjvError({
232
+ type: ERROR_TYPE.ONE_VALUE_OF,
233
+ message: createErrorMsg(ERROR_MESSAGE.ONE_VALUE_OF, {
234
+ placeholders: [JSON.stringify(enumArr)]
235
+ }),
236
+ data,
237
+ path: _options.path,
238
+ errorScheme: numberScheme,
239
+ errorData: value
240
+ });
241
+ break;
242
+ }
243
+ }
244
+ if (definedTester(numberScheme.notEnum)) {
245
+ if (!arrayTester(numberScheme.notEnum)) {
246
+ return new EjvError({
247
+ type: ERROR_TYPE.INVALID_SCHEMES,
248
+ message: createErrorMsg(ERROR_MESSAGE.NOT_ENUM_SHOULD_BE_ARRAY),
249
+ data: data,
250
+ errorScheme: numberScheme,
251
+ isSchemeError: true
252
+ });
253
+ }
254
+ const enumArr = numberScheme.notEnum;
255
+ if (!arrayTypeOfTester(enumArr, DATA_TYPE.NUMBER)) {
256
+ return new EjvError({
257
+ type: ERROR_TYPE.INVALID_SCHEMES,
258
+ message: createErrorMsg(ERROR_MESSAGE.NOT_ENUM_SHOULD_BE_NUMBERS),
259
+ data: data,
260
+ errorScheme: numberScheme,
261
+ isSchemeError: true
262
+ });
263
+ }
264
+ if (!notEnumTester(valueAsNumber, enumArr)) {
265
+ result = new EjvError({
266
+ type: ERROR_TYPE.NOT_ONE_VALUE_OF,
267
+ message: createErrorMsg(ERROR_MESSAGE.NOT_ONE_VALUE_OF, {
268
+ placeholders: [JSON.stringify(enumArr)]
269
+ }),
270
+ data,
271
+ path: _options.path,
272
+ errorScheme: numberScheme,
273
+ errorData: value
274
+ });
275
+ break;
276
+ }
277
+ }
278
+ if (definedTester(numberScheme.min)
279
+ || definedTester(scheme.parent?.min)) {
280
+ const effectiveMin = definedTester(numberScheme.min)
281
+ ? numberScheme.min
282
+ : scheme.parent?.min;
283
+ if (!numberTester(effectiveMin)) {
284
+ return new EjvError({
285
+ type: ERROR_TYPE.INVALID_SCHEMES,
286
+ message: createErrorMsg(ERROR_MESSAGE.MIN_SHOULD_BE_NUMBER),
287
+ data: data,
288
+ errorScheme: numberScheme,
289
+ isSchemeError: true
290
+ });
291
+ }
292
+ if (definedTester(numberScheme.exclusiveMin)) {
293
+ if (!booleanTester(numberScheme.exclusiveMin)) {
294
+ return new EjvError({
295
+ type: ERROR_TYPE.INVALID_SCHEMES,
296
+ message: createErrorMsg(ERROR_MESSAGE.EXCLUSIVE_MIN_SHOULD_BE_BOOLEAN),
297
+ data: data,
298
+ errorScheme: numberScheme,
299
+ isSchemeError: true
300
+ });
301
+ }
302
+ }
303
+ if (numberScheme.exclusiveMin) {
304
+ if (!exclusiveMinNumberTester(valueAsNumber, effectiveMin)) {
305
+ result = new EjvError({
306
+ type: ERROR_TYPE.BIGGER_THAN,
307
+ message: createErrorMsg(ERROR_MESSAGE.BIGGER_THAN, {
308
+ placeholders: [effectiveMin]
309
+ }),
310
+ data,
311
+ path: _options.path,
312
+ errorScheme: numberScheme,
313
+ errorData: value
314
+ });
315
+ break;
316
+ }
317
+ }
318
+ else {
319
+ if (!minNumberTester(valueAsNumber, effectiveMin)) {
320
+ result = new EjvError({
321
+ type: ERROR_TYPE.BIGGER_THAN_OR_EQUAL,
322
+ message: createErrorMsg(ERROR_MESSAGE.BIGGER_THAN_OR_EQUAL, {
323
+ placeholders: [effectiveMin]
324
+ }),
325
+ data,
326
+ path: _options.path,
327
+ errorScheme: numberScheme,
328
+ errorData: value
329
+ });
330
+ break;
331
+ }
332
+ }
333
+ }
334
+ if (definedTester(numberScheme.max)
335
+ || definedTester(scheme.parent?.max)) {
336
+ const effectiveMax = definedTester(numberScheme.max)
337
+ ? numberScheme.max
338
+ : scheme.parent?.max;
339
+ if (!numberTester(effectiveMax)) {
340
+ return new EjvError({
341
+ type: ERROR_TYPE.INVALID_SCHEMES,
342
+ message: createErrorMsg(ERROR_MESSAGE.MAX_SHOULD_BE_NUMBER),
343
+ data: data,
344
+ errorScheme: numberScheme,
345
+ isSchemeError: true
346
+ });
347
+ }
348
+ if (definedTester(numberScheme.exclusiveMax)) {
349
+ if (!booleanTester(numberScheme.exclusiveMax)) {
350
+ return new EjvError({
351
+ type: ERROR_TYPE.INVALID_SCHEMES,
352
+ message: createErrorMsg(ERROR_MESSAGE.EXCLUSIVE_MAX_SHOULD_BE_BOOLEAN),
353
+ data: data,
354
+ errorScheme: numberScheme,
355
+ isSchemeError: true
356
+ });
357
+ }
358
+ }
359
+ if (numberScheme.exclusiveMax) {
360
+ if (!exclusiveMaxNumberTester(valueAsNumber, effectiveMax)) {
361
+ result = new EjvError({
362
+ type: ERROR_TYPE.SMALLER_THAN,
363
+ message: createErrorMsg(ERROR_MESSAGE.SMALLER_THAN, {
364
+ placeholders: [effectiveMax]
365
+ }),
366
+ data,
367
+ path: _options.path,
368
+ errorScheme: numberScheme,
369
+ errorData: value
370
+ });
371
+ break;
372
+ }
373
+ }
374
+ else {
375
+ if (!maxNumberTester(valueAsNumber, effectiveMax)) {
376
+ result = new EjvError({
377
+ type: ERROR_TYPE.SMALLER_THAN_OR_EQUAL,
378
+ message: createErrorMsg(ERROR_MESSAGE.SMALLER_THAN_OR_EQUAL, {
379
+ placeholders: [effectiveMax]
380
+ }),
381
+ data,
382
+ path: _options.path,
383
+ errorScheme: numberScheme,
384
+ errorData: value
385
+ });
386
+ break;
387
+ }
388
+ }
389
+ }
390
+ if (definedTester(numberScheme.format)) {
391
+ let formats;
392
+ const allNumberFormat = Object.values(NUMBER_FORMAT);
393
+ if (!arrayTester(numberScheme.format)) {
394
+ const formatAsString = numberScheme.format;
395
+ if (!enumTester(formatAsString, allNumberFormat)) {
396
+ return new EjvError({
397
+ type: ERROR_TYPE.INVALID_SCHEMES,
398
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_NUMBER_FORMAT, {
399
+ placeholders: [formatAsString]
400
+ }),
401
+ data: data,
402
+ errorScheme: numberScheme,
403
+ isSchemeError: true
404
+ });
405
+ }
406
+ formats = [numberScheme.format];
407
+ }
408
+ else {
409
+ const formatAsArray = numberScheme.format;
410
+ const errorFormat = formatAsArray.find((format) => {
411
+ return !enumTester(format, allNumberFormat);
412
+ });
413
+ if (errorFormat) {
414
+ return new EjvError({
415
+ type: ERROR_TYPE.INVALID_SCHEMES,
416
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_NUMBER_FORMAT, {
417
+ placeholders: [errorFormat]
418
+ }),
419
+ data: data,
420
+ errorScheme: numberScheme,
421
+ isSchemeError: true
422
+ });
423
+ }
424
+ formats = numberScheme.format;
425
+ }
426
+ const someFormatIsWrong = formats.some((format) => {
427
+ let valid = false;
428
+ switch (format) {
429
+ case NUMBER_FORMAT.INTEGER:
430
+ valid = integerTester(valueAsNumber);
431
+ break;
432
+ case NUMBER_FORMAT.INDEX:
433
+ valid = indexTester(valueAsNumber);
434
+ break;
435
+ }
436
+ return valid;
437
+ });
438
+ if (!someFormatIsWrong) {
439
+ if (!arrayTester(numberScheme.format)) {
440
+ result = new EjvError({
441
+ type: ERROR_TYPE.FORMAT,
442
+ message: createErrorMsg(ERROR_MESSAGE.FORMAT, {
443
+ placeholders: [numberScheme.format]
444
+ }),
445
+ data,
446
+ path: _options.path,
447
+ errorScheme: numberScheme,
448
+ errorData: value
449
+ });
450
+ }
451
+ else {
452
+ result = new EjvError({
453
+ type: ERROR_TYPE.FORMAT_ONE_OF,
454
+ message: createErrorMsg(ERROR_MESSAGE.FORMAT_ONE_OF, {
455
+ placeholders: [JSON.stringify(numberScheme.format)]
456
+ }),
457
+ data,
458
+ path: _options.path,
459
+ errorScheme: numberScheme,
460
+ errorData: value
461
+ });
462
+ }
463
+ break;
464
+ }
465
+ }
466
+ break;
467
+ }
468
+ case DATA_TYPE.STRING: {
469
+ const valueAsString = value;
470
+ const stringScheme = scheme;
471
+ if (definedTester(stringScheme.enum)) {
472
+ if (!arrayTester(stringScheme.enum)) {
473
+ return new EjvError({
474
+ type: ERROR_TYPE.INVALID_SCHEMES,
475
+ message: createErrorMsg(ERROR_MESSAGE.ENUM_SHOULD_BE_ARRAY),
476
+ data: data,
477
+ errorScheme: stringScheme,
478
+ isSchemeError: true
479
+ });
480
+ }
481
+ const enumArr = stringScheme.enum;
482
+ if (!arrayTypeOfTester(enumArr, DATA_TYPE.STRING)) {
483
+ return new EjvError({
484
+ type: ERROR_TYPE.INVALID_SCHEMES,
485
+ message: createErrorMsg(ERROR_MESSAGE.ENUM_SHOULD_BE_STRINGS),
486
+ data: data,
487
+ errorScheme: stringScheme,
488
+ isSchemeError: true
489
+ });
490
+ }
491
+ if (!enumTester(valueAsString, enumArr)) {
492
+ result = new EjvError({
493
+ type: ERROR_TYPE.ONE_VALUE_OF,
494
+ message: createErrorMsg(ERROR_MESSAGE.ONE_VALUE_OF, {
495
+ placeholders: [JSON.stringify(stringScheme.enum)]
496
+ }),
497
+ data,
498
+ path: _options.path,
499
+ errorScheme: stringScheme,
500
+ errorData: value
501
+ });
502
+ break;
503
+ }
504
+ }
505
+ if (definedTester(stringScheme.notEnum)) {
506
+ if (!arrayTester(stringScheme.notEnum)) {
507
+ return new EjvError({
508
+ type: ERROR_TYPE.INVALID_SCHEMES,
509
+ message: createErrorMsg(ERROR_MESSAGE.NOT_ENUM_SHOULD_BE_ARRAY),
510
+ data: data,
511
+ errorScheme: stringScheme,
512
+ isSchemeError: true
513
+ });
514
+ }
515
+ const enumArr = stringScheme.notEnum;
516
+ if (!arrayTypeOfTester(enumArr, DATA_TYPE.STRING)) {
517
+ return new EjvError({
518
+ type: ERROR_TYPE.INVALID_SCHEMES,
519
+ message: createErrorMsg(ERROR_MESSAGE.NOT_ENUM_SHOULD_BE_STRINGS),
520
+ data: data,
521
+ errorScheme: stringScheme,
522
+ isSchemeError: true
523
+ });
524
+ }
525
+ if (!notEnumTester(valueAsString, enumArr)) {
526
+ result = new EjvError({
527
+ type: ERROR_TYPE.NOT_ONE_VALUE_OF,
528
+ message: createErrorMsg(ERROR_MESSAGE.NOT_ONE_VALUE_OF, {
529
+ placeholders: [JSON.stringify(stringScheme.notEnum)]
530
+ }),
531
+ data,
532
+ path: _options.path,
533
+ errorScheme: stringScheme,
534
+ errorData: value
535
+ });
536
+ break;
537
+ }
538
+ }
539
+ if (definedTester(stringScheme.length)) {
540
+ const length = stringScheme.length;
541
+ if (!(numberTester(length) && integerTester(length))) {
542
+ return new EjvError({
543
+ type: ERROR_TYPE.INVALID_SCHEMES,
544
+ message: createErrorMsg(ERROR_MESSAGE.LENGTH_SHOULD_BE_INTEGER),
545
+ data: data,
546
+ errorScheme: stringScheme,
547
+ isSchemeError: true
548
+ });
549
+ }
550
+ if (!lengthTester(valueAsString, length)) {
551
+ result = new EjvError({
552
+ type: ERROR_TYPE.LENGTH,
553
+ message: createErrorMsg(ERROR_MESSAGE.LENGTH, {
554
+ placeholders: [length]
555
+ }),
556
+ data,
557
+ path: _options.path,
558
+ errorScheme: stringScheme,
559
+ errorData: value
560
+ });
561
+ break;
562
+ }
563
+ }
564
+ if (definedTester(stringScheme.minLength)) {
565
+ const minLength = stringScheme.minLength;
566
+ if (!(numberTester(minLength) && integerTester(minLength))) {
567
+ return new EjvError({
568
+ type: ERROR_TYPE.INVALID_SCHEMES,
569
+ message: createErrorMsg(ERROR_MESSAGE.MIN_LENGTH_SHOULD_BE_INTEGER),
570
+ data: data,
571
+ errorScheme: stringScheme,
572
+ isSchemeError: true
573
+ });
574
+ }
575
+ if (!minLengthTester(valueAsString, minLength)) {
576
+ result = new EjvError({
577
+ type: ERROR_TYPE.MIN_LENGTH,
578
+ message: createErrorMsg(ERROR_MESSAGE.MIN_LENGTH, {
579
+ placeholders: ['' + minLength]
580
+ }),
581
+ data,
582
+ path: _options.path,
583
+ errorScheme: stringScheme,
584
+ errorData: value
585
+ });
586
+ break;
587
+ }
588
+ }
589
+ if (definedTester(stringScheme.maxLength)) {
590
+ const maxLength = stringScheme.maxLength;
591
+ if (!(numberTester(maxLength) && integerTester(maxLength))) {
592
+ return new EjvError({
593
+ type: ERROR_TYPE.INVALID_SCHEMES,
594
+ message: createErrorMsg(ERROR_MESSAGE.MAX_LENGTH_SHOULD_BE_INTEGER),
595
+ data: data,
596
+ errorScheme: stringScheme,
597
+ isSchemeError: true
598
+ });
599
+ }
600
+ if (!maxLengthTester(valueAsString, maxLength)) {
601
+ result = new EjvError({
602
+ type: ERROR_TYPE.MAX_LENGTH,
603
+ message: createErrorMsg(ERROR_MESSAGE.MAX_LENGTH, {
604
+ placeholders: ['' + maxLength]
605
+ }),
606
+ data,
607
+ path: _options.path,
608
+ errorScheme: stringScheme,
609
+ errorData: value
610
+ });
611
+ break;
612
+ }
613
+ }
614
+ if (definedTester(stringScheme.format)) {
615
+ let formats;
616
+ const allStringFormat = Object.values(STRING_FORMAT);
617
+ if (!arrayTester(stringScheme.format)) {
618
+ const formatAsString = stringScheme.format;
619
+ if (!enumTester(formatAsString, allStringFormat)) {
620
+ return new EjvError({
621
+ type: ERROR_TYPE.INVALID_SCHEMES,
622
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_FORMAT, {
623
+ placeholders: [formatAsString]
624
+ }),
625
+ data: data,
626
+ errorScheme: stringScheme,
627
+ isSchemeError: true
628
+ });
629
+ }
630
+ formats = [stringScheme.format];
631
+ }
632
+ else {
633
+ const formatAsArray = stringScheme.format;
634
+ const errorFormat = formatAsArray.find((format) => {
635
+ return !enumTester(format, allStringFormat);
636
+ });
637
+ if (errorFormat) {
638
+ return new EjvError({
639
+ type: ERROR_TYPE.INVALID_SCHEMES,
640
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_FORMAT, {
641
+ placeholders: [errorFormat]
642
+ }),
643
+ data: data,
644
+ errorScheme: stringScheme,
645
+ isSchemeError: true
646
+ });
647
+ }
648
+ formats = stringScheme.format;
649
+ }
650
+ const foundFormatMatching = formats.some((format) => {
651
+ let valid = false;
652
+ switch (format) {
653
+ case STRING_FORMAT.EMAIL:
654
+ valid = emailTester(valueAsString);
655
+ break;
656
+ case STRING_FORMAT.DATE:
657
+ valid = dateFormatTester(valueAsString);
658
+ break;
659
+ case STRING_FORMAT.TIME:
660
+ valid = timeFormatTester(valueAsString);
661
+ break;
662
+ case STRING_FORMAT.DATE_TIME:
663
+ valid = dateTimeFormatTester(valueAsString);
664
+ break;
665
+ }
666
+ return valid;
667
+ });
668
+ if (!foundFormatMatching) {
669
+ if (!arrayTester(stringScheme.format)) {
670
+ result = new EjvError({
671
+ type: ERROR_TYPE.FORMAT,
672
+ message: createErrorMsg(ERROR_MESSAGE.FORMAT, {
673
+ placeholders: [stringScheme.format]
674
+ }),
675
+ data,
676
+ path: _options.path,
677
+ errorScheme: stringScheme,
678
+ errorData: value
679
+ });
680
+ }
681
+ else {
682
+ result = new EjvError({
683
+ type: ERROR_TYPE.FORMAT_ONE_OF,
684
+ message: createErrorMsg(ERROR_MESSAGE.FORMAT_ONE_OF, {
685
+ placeholders: [JSON.stringify(stringScheme.format)]
686
+ }),
687
+ data,
688
+ path: _options.path,
689
+ errorScheme: stringScheme,
690
+ errorData: value
691
+ });
692
+ }
693
+ break;
694
+ }
695
+ }
696
+ if (definedTester(stringScheme.pattern)) {
697
+ // check parameter
698
+ if (stringScheme.pattern === null) {
699
+ return new EjvError({
700
+ type: ERROR_TYPE.INVALID_SCHEMES,
701
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
702
+ placeholders: ['null']
703
+ }),
704
+ data: data,
705
+ errorScheme: stringScheme,
706
+ isSchemeError: true
707
+ });
708
+ }
709
+ const isValidPattern = (pattern) => {
710
+ return (stringTester(pattern) && minLengthTester(pattern, 1))
711
+ || (regExpTester(pattern) && pattern.toString() !== '/(?:)/' && pattern.toString() !== '/null/');
712
+ };
713
+ const patternToString = (pattern) => {
714
+ let regExpStr;
715
+ if (pattern === null) {
716
+ regExpStr = '/null/';
717
+ }
718
+ else if (stringTester(pattern)) {
719
+ if (minLengthTester(pattern, 1)) {
720
+ regExpStr = new RegExp(pattern).toString();
721
+ }
722
+ else {
723
+ regExpStr = '//';
724
+ }
725
+ }
726
+ else {
727
+ regExpStr = pattern.toString();
728
+ }
729
+ // empty regular expression
730
+ if (regExpStr === '/(?:)/') {
731
+ regExpStr = '//';
732
+ }
733
+ return regExpStr;
734
+ };
735
+ const createArrayErrorMsg = (patternsAsArray) => {
736
+ return '[' + patternsAsArray.map((onePattern) => {
737
+ return patternToString(onePattern);
738
+ }).join(', ') + ']';
739
+ };
740
+ if (arrayTester(stringScheme.pattern)) {
741
+ const patternsAsArray = stringScheme.pattern;
742
+ if (!minLengthTester(patternsAsArray, 1)) { // empty array
743
+ return new EjvError({
744
+ type: ERROR_TYPE.INVALID_SCHEMES,
745
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
746
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
747
+ }),
748
+ data: data,
749
+ errorScheme: stringScheme,
750
+ isSchemeError: true
751
+ });
752
+ }
753
+ try {
754
+ const regExpPatterns = patternsAsArray.map((pattern) => {
755
+ if (!isValidPattern(pattern)) {
756
+ throw new Error(createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
757
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
758
+ }));
759
+ }
760
+ return new RegExp(pattern);
761
+ });
762
+ // check value
763
+ const foundMatchPattern = regExpPatterns.some((regexp) => {
764
+ return stringRegExpTester(valueAsString, regexp);
765
+ });
766
+ if (!foundMatchPattern) {
767
+ result = new EjvError({
768
+ type: ERROR_TYPE.PATTERN_ONE_OF,
769
+ message: createErrorMsg(ERROR_MESSAGE.PATTERN_ONE_OF, {
770
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
771
+ }),
772
+ data,
773
+ path: _options.path,
774
+ errorScheme: stringScheme,
775
+ errorData: value
776
+ });
777
+ break;
778
+ }
779
+ }
780
+ catch (e) { // eslint-disable-line @typescript-eslint/no-unused-vars
781
+ return new EjvError({
782
+ type: ERROR_TYPE.INVALID_SCHEMES,
783
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
784
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
785
+ }),
786
+ data: data,
787
+ errorScheme: stringScheme,
788
+ isSchemeError: true
789
+ });
790
+ }
791
+ }
792
+ else {
793
+ const patternAsOne = stringScheme.pattern;
794
+ if (!isValidPattern(patternAsOne)) {
795
+ return new EjvError({
796
+ type: ERROR_TYPE.INVALID_SCHEMES,
797
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
798
+ placeholders: [patternToString(patternAsOne)]
799
+ }),
800
+ data: data,
801
+ errorScheme: stringScheme,
802
+ isSchemeError: true
803
+ });
804
+ }
805
+ // check value
806
+ const regExp = new RegExp(patternAsOne);
807
+ if (!stringRegExpTester(valueAsString, regExp)) {
808
+ result = new EjvError({
809
+ type: ERROR_TYPE.PATTERN,
810
+ message: createErrorMsg(ERROR_MESSAGE.PATTERN, {
811
+ placeholders: [patternToString(patternAsOne)]
812
+ }),
813
+ data,
814
+ path: _options.path,
815
+ errorScheme: stringScheme,
816
+ errorData: value
817
+ });
818
+ break;
819
+ }
820
+ }
821
+ }
822
+ break;
823
+ }
824
+ case DATA_TYPE.OBJECT: {
825
+ const valueAsObject = value;
826
+ const objectScheme = scheme;
827
+ if (definedTester(objectScheme.allowNoProperty)) {
828
+ if (!booleanTester(objectScheme.allowNoProperty)) {
829
+ return new EjvError({
830
+ type: ERROR_TYPE.INVALID_SCHEMES,
831
+ message: createErrorMsg(ERROR_MESSAGE.ALLOW_NO_PROPERTY_SHOULD_BE_BOOLEAN),
832
+ data: data,
833
+ errorScheme: objectScheme,
834
+ isSchemeError: true
835
+ });
836
+ }
837
+ if (!objectScheme.allowNoProperty && !hasPropertyTester(valueAsObject)) {
838
+ result = new EjvError({
839
+ type: ERROR_TYPE.PROPERTY,
840
+ message: ERROR_MESSAGE.PROPERTY,
841
+ data,
842
+ path: _options.path,
843
+ errorScheme: objectScheme,
844
+ errorData: value
845
+ });
846
+ break;
847
+ }
848
+ }
849
+ if (definedTester(objectScheme.properties)) {
850
+ if (!arrayTester(objectScheme.properties)) {
851
+ return new EjvError({
852
+ type: ERROR_TYPE.INVALID_SCHEMES,
853
+ message: createErrorMsg(ERROR_MESSAGE.PROPERTIES_SHOULD_BE_ARRAY),
854
+ data: data,
855
+ errorScheme: objectScheme,
856
+ isSchemeError: true
857
+ });
858
+ }
859
+ const properties = objectScheme.properties;
860
+ if (!minLengthTester(properties, 1)) {
861
+ return new EjvError({
862
+ type: ERROR_TYPE.INVALID_SCHEMES,
863
+ message: createErrorMsg(ERROR_MESSAGE.PROPERTIES_SHOULD_HAVE_ITEMS),
864
+ data: data,
865
+ errorScheme: objectScheme,
866
+ isSchemeError: true
867
+ });
868
+ }
869
+ if (!arrayTypeOfTester(properties, DATA_TYPE.OBJECT)) {
870
+ return new EjvError({
871
+ type: ERROR_TYPE.INVALID_SCHEMES,
872
+ message: createErrorMsg(ERROR_MESSAGE.PROPERTIES_SHOULD_BE_ARRAY_OF_OBJECT),
873
+ data: data,
874
+ errorScheme: objectScheme,
875
+ isSchemeError: true
876
+ });
877
+ }
878
+ if (!objectTester(value)) {
879
+ result = new EjvError({
880
+ type: ERROR_TYPE.TYPE_MISMATCH,
881
+ message: createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH, {
882
+ placeholders: ['object']
883
+ }),
884
+ data,
885
+ path: _options.path,
886
+ errorScheme: objectScheme,
887
+ errorData: value
888
+ });
889
+ break;
890
+ }
891
+ const partialData = data[key];
892
+ const partialScheme = objectScheme.properties;
893
+ scheme.parent = objectScheme;
894
+ // call recursively
895
+ result = _ejv(partialData, partialScheme, _options);
896
+ if (result) {
897
+ // inject original data
898
+ result.data = data;
899
+ }
900
+ }
901
+ break;
902
+ }
903
+ case DATA_TYPE.DATE: {
904
+ const valueAsDate = value;
905
+ const dateScheme = scheme;
906
+ const parentDateScheme = scheme.parent;
907
+ if (definedTester(dateScheme.min)
908
+ || definedTester(parentDateScheme?.min)) {
909
+ const minDateCandidate = dateScheme.min || parentDateScheme?.min;
910
+ if (!((stringTester(minDateCandidate)
911
+ && (dateFormatTester(minDateCandidate)
912
+ || dateTimeFormatTester(minDateCandidate)))
913
+ || dateTester(minDateCandidate))) {
914
+ return new EjvError({
915
+ type: ERROR_TYPE.INVALID_SCHEMES,
916
+ message: createErrorMsg(ERROR_MESSAGE.MIN_DATE_SHOULD_BE_DATE_OR_STRING),
917
+ data: data,
918
+ errorScheme: dateScheme,
919
+ isSchemeError: true
920
+ });
921
+ }
922
+ const effectiveMin = new Date(minDateCandidate);
923
+ if (definedTester(dateScheme.exclusiveMin)) {
924
+ if (!booleanTester(dateScheme.exclusiveMin)) {
925
+ return new EjvError({
926
+ type: ERROR_TYPE.INVALID_SCHEMES,
927
+ message: createErrorMsg(ERROR_MESSAGE.EXCLUSIVE_MIN_SHOULD_BE_BOOLEAN),
928
+ data: data,
929
+ errorScheme: dateScheme,
930
+ isSchemeError: true
931
+ });
932
+ }
933
+ if (dateScheme.exclusiveMin) {
934
+ if (!exclusiveMinDateTester(valueAsDate, effectiveMin)) {
935
+ result = new EjvError({
936
+ type: ERROR_TYPE.AFTER_DATE,
937
+ message: createErrorMsg(ERROR_MESSAGE.AFTER_DATE, {
938
+ placeholders: [effectiveMin.toISOString()]
939
+ }),
940
+ data,
941
+ path: _options.path,
942
+ errorScheme: dateScheme,
943
+ errorData: value
944
+ });
945
+ break;
946
+ }
947
+ }
948
+ else {
949
+ if (!minDateTester(valueAsDate, effectiveMin)) {
950
+ result = new EjvError({
951
+ type: ERROR_TYPE.AFTER_OR_SAME_DATE,
952
+ message: createErrorMsg(ERROR_MESSAGE.AFTER_OR_SAME_DATE, {
953
+ placeholders: [effectiveMin.toISOString()]
954
+ }),
955
+ data,
956
+ path: _options.path,
957
+ errorScheme: dateScheme,
958
+ errorData: value
959
+ });
960
+ break;
961
+ }
962
+ }
963
+ }
964
+ else {
965
+ if (!minDateTester(valueAsDate, effectiveMin)) {
966
+ result = new EjvError({
967
+ type: ERROR_TYPE.AFTER_OR_SAME_DATE,
968
+ message: createErrorMsg(ERROR_MESSAGE.AFTER_OR_SAME_DATE, {
969
+ placeholders: [effectiveMin.toISOString()]
970
+ }),
971
+ data,
972
+ path: _options.path,
973
+ errorScheme: dateScheme,
974
+ errorData: value
975
+ });
976
+ break;
977
+ }
978
+ }
979
+ }
980
+ if (definedTester(dateScheme.max)
981
+ || definedTester(parentDateScheme?.max)) {
982
+ const maxDateCandidate = dateScheme.max || parentDateScheme?.max;
983
+ if (!((stringTester(maxDateCandidate)
984
+ && (dateFormatTester(maxDateCandidate)
985
+ || dateTimeFormatTester(maxDateCandidate)))
986
+ || dateTester(maxDateCandidate))) {
987
+ return new EjvError({
988
+ type: ERROR_TYPE.INVALID_SCHEMES,
989
+ message: createErrorMsg(ERROR_MESSAGE.MAX_DATE_SHOULD_BE_DATE_OR_STRING),
990
+ data: data,
991
+ errorScheme: dateScheme,
992
+ isSchemeError: true
993
+ });
994
+ }
995
+ const effectiveMax = new Date(maxDateCandidate);
996
+ if (definedTester(dateScheme.exclusiveMax)) {
997
+ if (!booleanTester(dateScheme.exclusiveMax)) {
998
+ return new EjvError({
999
+ type: ERROR_TYPE.INVALID_SCHEMES,
1000
+ message: createErrorMsg(ERROR_MESSAGE.EXCLUSIVE_MAX_SHOULD_BE_BOOLEAN),
1001
+ data: data,
1002
+ errorScheme: dateScheme,
1003
+ isSchemeError: true
1004
+ });
1005
+ }
1006
+ }
1007
+ if (dateScheme.exclusiveMax) {
1008
+ if (!exclusiveMaxDateTester(valueAsDate, effectiveMax)) {
1009
+ result = new EjvError({
1010
+ type: ERROR_TYPE.BEFORE_DATE,
1011
+ message: createErrorMsg(ERROR_MESSAGE.BEFORE_DATE, {
1012
+ placeholders: [effectiveMax.toISOString()]
1013
+ }),
1014
+ data,
1015
+ path: _options.path,
1016
+ errorScheme: dateScheme,
1017
+ errorData: value
1018
+ });
1019
+ break;
1020
+ }
1021
+ }
1022
+ else {
1023
+ if (!maxDateTester(valueAsDate, effectiveMax)) {
1024
+ result = new EjvError({
1025
+ type: ERROR_TYPE.BEFORE_OR_SAME_DATE,
1026
+ message: createErrorMsg(ERROR_MESSAGE.BEFORE_OR_SAME_DATE, {
1027
+ placeholders: [effectiveMax.toISOString()]
1028
+ }),
1029
+ data,
1030
+ path: _options.path,
1031
+ errorScheme: dateScheme,
1032
+ errorData: value
1033
+ });
1034
+ break;
1035
+ }
1036
+ }
1037
+ }
1038
+ break;
1039
+ }
1040
+ case DATA_TYPE.ARRAY: {
1041
+ const valueAsArray = value;
1042
+ const arrayScheme = scheme;
1043
+ if (definedTester(arrayScheme.length)) {
1044
+ const length = arrayScheme.length;
1045
+ if (!(numberTester(length) && integerTester(length))) {
1046
+ return new EjvError({
1047
+ type: ERROR_TYPE.INVALID_SCHEMES,
1048
+ message: createErrorMsg(ERROR_MESSAGE.LENGTH_SHOULD_BE_INTEGER),
1049
+ data: data,
1050
+ errorScheme: arrayScheme,
1051
+ isSchemeError: true
1052
+ });
1053
+ }
1054
+ if (!lengthTester(valueAsArray, length)) {
1055
+ result = new EjvError({
1056
+ type: ERROR_TYPE.LENGTH,
1057
+ message: createErrorMsg(ERROR_MESSAGE.LENGTH, {
1058
+ placeholders: ['' + length]
1059
+ }),
1060
+ data,
1061
+ path: _options.path,
1062
+ errorScheme: arrayScheme,
1063
+ errorData: value
1064
+ });
1065
+ break;
1066
+ }
1067
+ }
1068
+ if (definedTester(arrayScheme.minLength)) {
1069
+ const minLength = arrayScheme.minLength;
1070
+ if (!(numberTester(arrayScheme.minLength) && integerTester(minLength))) {
1071
+ return new EjvError({
1072
+ type: ERROR_TYPE.INVALID_SCHEMES,
1073
+ message: createErrorMsg(ERROR_MESSAGE.MIN_LENGTH_SHOULD_BE_INTEGER),
1074
+ data: data,
1075
+ errorScheme: arrayScheme,
1076
+ isSchemeError: true
1077
+ });
1078
+ }
1079
+ if (!minLengthTester(valueAsArray, minLength)) {
1080
+ result = new EjvError({
1081
+ type: ERROR_TYPE.MIN_LENGTH,
1082
+ message: createErrorMsg(ERROR_MESSAGE.MIN_LENGTH, {
1083
+ placeholders: ['' + minLength]
1084
+ }),
1085
+ data,
1086
+ path: _options.path,
1087
+ errorScheme: arrayScheme,
1088
+ errorData: value
1089
+ });
1090
+ break;
1091
+ }
1092
+ }
1093
+ if (definedTester(arrayScheme.maxLength)) {
1094
+ const maxLength = arrayScheme.maxLength;
1095
+ if (!(numberTester(arrayScheme.maxLength) && integerTester(maxLength))) {
1096
+ return new EjvError({
1097
+ type: ERROR_TYPE.INVALID_SCHEMES,
1098
+ message: createErrorMsg(ERROR_MESSAGE.MAX_LENGTH_SHOULD_BE_INTEGER),
1099
+ data: data,
1100
+ errorScheme: arrayScheme,
1101
+ isSchemeError: true
1102
+ });
1103
+ }
1104
+ if (!maxLengthTester(valueAsArray, maxLength)) {
1105
+ result = new EjvError({
1106
+ type: ERROR_TYPE.MAX_LENGTH,
1107
+ message: createErrorMsg(ERROR_MESSAGE.MAX_LENGTH, {
1108
+ placeholders: ['' + maxLength]
1109
+ }),
1110
+ data,
1111
+ path: _options.path,
1112
+ errorScheme: arrayScheme,
1113
+ errorData: value
1114
+ });
1115
+ break;
1116
+ }
1117
+ }
1118
+ if (definedTester(arrayScheme.unique)) {
1119
+ if (!booleanTester(arrayScheme.unique)) {
1120
+ return new EjvError({
1121
+ type: ERROR_TYPE.INVALID_SCHEMES,
1122
+ message: createErrorMsg(ERROR_MESSAGE.UNIQUE_SHOULD_BE_BOOLEAN),
1123
+ data: data,
1124
+ errorScheme: arrayScheme,
1125
+ isSchemeError: true
1126
+ });
1127
+ }
1128
+ if (arrayScheme.unique && !uniqueItemsTester(valueAsArray)) {
1129
+ result = new EjvError({
1130
+ type: ERROR_TYPE.UNIQUE_ITEMS,
1131
+ message: ERROR_MESSAGE.UNIQUE_ITEMS,
1132
+ data,
1133
+ path: _options.path,
1134
+ errorScheme: arrayScheme,
1135
+ errorData: value
1136
+ });
1137
+ break;
1138
+ }
1139
+ }
1140
+ if (definedTester(arrayScheme.items)) {
1141
+ // convert array to object
1142
+ if (valueAsArray.length > 0) {
1143
+ const now = new Date();
1144
+ const tempKeyArr = valueAsArray.map((_value, i) => {
1145
+ return '' + (+now + i);
1146
+ });
1147
+ if (stringTester(arrayScheme.items) // by DataType
1148
+ || (arrayTester(arrayScheme.items) && arrayTypeOfTester(arrayScheme.items, DATA_TYPE.STRING)) // by DataType[]
1149
+ ) {
1150
+ const itemTypes = (arrayTester(arrayScheme.items)
1151
+ ? arrayScheme.items
1152
+ : [arrayScheme.items]);
1153
+ const itemTypeError = itemTypes.find((type) => {
1154
+ return !definedTester(type)
1155
+ || !stringTester(type)
1156
+ || !enumTester(type, allDataType);
1157
+ });
1158
+ if (itemTypeError) {
1159
+ return new EjvError({
1160
+ type: ERROR_TYPE.INVALID_SCHEMES,
1161
+ message: createErrorMsg(ERROR_MESSAGE.SCHEMES_HAS_INVALID_TYPE, {
1162
+ placeholders: [itemTypeError]
1163
+ }),
1164
+ data: data,
1165
+ errorScheme: scheme,
1166
+ isSchemeError: true
1167
+ });
1168
+ }
1169
+ const partialData = {};
1170
+ const partialSchemes = [];
1171
+ tempKeyArr.forEach((tempKey, i) => {
1172
+ partialData[tempKey] = valueAsArray[i];
1173
+ partialSchemes.push({
1174
+ key: tempKey,
1175
+ type: itemTypes
1176
+ });
1177
+ });
1178
+ scheme.parent = arrayScheme;
1179
+ // call recursively
1180
+ const partialResult = _ejv(partialData, partialSchemes, _options);
1181
+ // convert new EjvError
1182
+ if (partialResult) {
1183
+ let errorMsg;
1184
+ if (arrayTester(arrayScheme.items)) {
1185
+ errorMsg = createErrorMsg(ERROR_MESSAGE.ITEMS_TYPE, {
1186
+ placeholders: [JSON.stringify(itemTypes)]
1187
+ });
1188
+ }
1189
+ else {
1190
+ errorMsg = createErrorMsg(ERROR_MESSAGE.ITEMS_TYPE, {
1191
+ placeholders: [arrayScheme.items]
1192
+ });
1193
+ }
1194
+ const partialKeys = (partialResult.path || '').split('/');
1195
+ const partialKey = partialKeys[partialKeys.length - 1];
1196
+ const partialScheme = partialSchemes.find((_scheme) => {
1197
+ return _scheme.key === partialKey;
1198
+ });
1199
+ const partialKeyIndex = partialSchemes.indexOf(partialScheme);
1200
+ result = new EjvError({
1201
+ type: ERROR_TYPE.ITEMS_TYPE,
1202
+ message: errorMsg,
1203
+ data,
1204
+ path: [..._options.path, '' + partialKeyIndex],
1205
+ errorScheme: partialScheme,
1206
+ errorData: partialData[partialKey]
1207
+ });
1208
+ }
1209
+ break;
1210
+ }
1211
+ else if ((objectTester(arrayScheme.items) && arrayScheme.items !== null) // by Scheme
1212
+ || (arrayTester(arrayScheme.items) && arrayTypeOfTester(arrayScheme.items, DATA_TYPE.OBJECT)) // by Scheme[]
1213
+ ) {
1214
+ const itemsAsSchemes = arrayTester(arrayScheme.items)
1215
+ ? arrayScheme.items
1216
+ : [arrayScheme.items];
1217
+ let partialError = null;
1218
+ // use for() instead of forEach() to break
1219
+ const valueLength = valueAsArray.length;
1220
+ for (let arrIndex = 0; arrIndex < valueLength; arrIndex++) {
1221
+ const oneValue = valueAsArray[arrIndex];
1222
+ const partialData = {};
1223
+ const partialSchemes = [];
1224
+ const tempKeyForThisValue = tempKeyArr[arrIndex];
1225
+ partialData[tempKeyForThisValue] = oneValue;
1226
+ partialSchemes.push(...itemsAsSchemes.map((oneScheme) => {
1227
+ const newScheme = clone(oneScheme); // divide instance
1228
+ newScheme.key = tempKeyForThisValue;
1229
+ return newScheme;
1230
+ }));
1231
+ const partialResults = partialSchemes.map((partialScheme) => {
1232
+ // call recursively
1233
+ const partialResult = _ejv(partialData, [partialScheme], _options);
1234
+ if (partialResult) {
1235
+ partialResult.path = (partialResult.path || '').replace(tempKeyForThisValue, '' + arrIndex);
1236
+ }
1237
+ return partialResult;
1238
+ });
1239
+ if (!partialResults.some((oneResult) => oneResult === null)) {
1240
+ partialError = partialResults.find((oneResult) => {
1241
+ return !!oneResult;
1242
+ });
1243
+ break;
1244
+ }
1245
+ }
1246
+ if (partialError) {
1247
+ let errorType;
1248
+ let errorMsg;
1249
+ if (!!itemsAsSchemes && itemsAsSchemes.length > 1) {
1250
+ errorType = ERROR_TYPE.ITEMS_SCHEMES;
1251
+ errorMsg = createErrorMsg(ERROR_MESSAGE.ITEMS_SCHEMES, {
1252
+ placeholders: [JSON.stringify(itemsAsSchemes)]
1253
+ });
1254
+ }
1255
+ else {
1256
+ errorType = partialError.type;
1257
+ errorMsg = partialError.message;
1258
+ if (errorType === ERROR_TYPE.REQUIRED) {
1259
+ // REQUIRED in array is TYPE_MISMATCH except with nullable === true
1260
+ errorType = ERROR_TYPE.TYPE_MISMATCH;
1261
+ errorMsg = createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH, {
1262
+ placeholders: [JSON.stringify(arrayScheme.items)]
1263
+ });
1264
+ }
1265
+ }
1266
+ result = new EjvError({
1267
+ type: errorType,
1268
+ message: errorMsg,
1269
+ data
1270
+ });
1271
+ if (errorType === ERROR_TYPE.INVALID_SCHEMES) {
1272
+ result.errorScheme = arrayScheme;
1273
+ result.isSchemeError = true;
1274
+ result.isDataError = false;
1275
+ }
1276
+ else {
1277
+ result.path = partialError.path;
1278
+ result.errorData = partialError.errorData;
1279
+ }
1280
+ break;
1281
+ }
1282
+ }
1283
+ else {
1284
+ return new EjvError({
1285
+ type: ERROR_TYPE.INVALID_SCHEMES,
1286
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_ITEMS_SCHEME, {
1287
+ placeholders: [JSON.stringify(arrayScheme.items)]
1288
+ }),
1289
+ data: data,
1290
+ errorScheme: arrayScheme,
1291
+ isSchemeError: true
1292
+ });
1293
+ }
1294
+ }
1295
+ }
1296
+ break;
1297
+ }
1298
+ }
1299
+ if (result) {
1300
+ break;
1301
+ }
1302
+ }
1303
+ if (result !== null && definedTester(options.customErrorMsg)) {
1304
+ const customErrorMsgObj = options.customErrorMsg;
1305
+ // override error message
1306
+ const customMsg = customErrorMsgObj[result.type];
1307
+ if (definedTester(customMsg)) {
1308
+ result.message = customMsg;
1309
+ }
1310
+ }
1311
+ return result;
1312
+ };
1313
+ export const ejv = (data, schemes, options) => {
1314
+ // check data itself
1315
+ if (!definedTester(data) || !objectTester(data) || data === null) {
1316
+ return new EjvError({
1317
+ type: ERROR_TYPE.NO_DATA,
1318
+ message: ERROR_MESSAGE.NO_DATA,
1319
+ data: data,
1320
+ path: undefined,
1321
+ errorScheme: undefined,
1322
+ errorData: data,
1323
+ isSchemeError: false
1324
+ });
1325
+ }
1326
+ const internalOption = (options
1327
+ ? {
1328
+ ...options
1329
+ }
1330
+ : {});
1331
+ if (!definedTester(internalOption.path)) {
1332
+ internalOption.path = [];
1333
+ }
1334
+ return _ejv(data, schemes, internalOption);
1335
+ };
1336
+ //# sourceMappingURL=ejv.js.map