ejv 2.1.0 → 2.1.2

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 (62) hide show
  1. package/.mocharc.json +8 -8
  2. package/CHANGELOG.md +134 -127
  3. package/README-KR.md +597 -597
  4. package/README.md +603 -603
  5. package/build/cjs/constants.js +124 -0
  6. package/build/cjs/constants.js.map +1 -0
  7. package/build/cjs/ejv.js +1341 -0
  8. package/build/cjs/ejv.js.map +1 -0
  9. package/build/cjs/index.js +14 -0
  10. package/build/cjs/index.js.map +1 -0
  11. package/build/cjs/interfaces.js +29 -0
  12. package/build/cjs/interfaces.js.map +1 -0
  13. package/build/cjs/package.json +1 -0
  14. package/build/cjs/tester.js +288 -0
  15. package/build/cjs/tester.js.map +1 -0
  16. package/build/cjs/util.js +103 -0
  17. package/build/cjs/util.js.map +1 -0
  18. package/build/constants.d.ts +107 -0
  19. package/build/ejv.d.ts +2 -0
  20. package/build/esm/constants.js +121 -0
  21. package/build/esm/constants.js.map +1 -0
  22. package/build/esm/ejv.js +1339 -0
  23. package/build/esm/ejv.js.map +1 -0
  24. package/build/esm/index.js +4 -0
  25. package/build/esm/index.js.map +1 -0
  26. package/build/esm/interfaces.js +33 -0
  27. package/build/esm/interfaces.js.map +1 -0
  28. package/build/esm/package.json +1 -0
  29. package/build/esm/tester.js +252 -0
  30. package/build/esm/tester.js.map +1 -0
  31. package/build/esm/util.js +96 -0
  32. package/build/esm/util.js.map +1 -0
  33. package/build/index.d.ts +3 -0
  34. package/build/interfaces.d.ts +77 -0
  35. package/build/scripts/add-js-extensions.js +46 -0
  36. package/build/scripts/add-js-extensions.js.map +1 -0
  37. package/build/tester.d.ts +35 -0
  38. package/build/util.d.ts +7 -0
  39. package/eslint.config.mjs +66 -59
  40. package/package.json +54 -55
  41. package/scripts/add-js-extensions.ts +59 -59
  42. package/spec/ArrayScheme.ts +1021 -1021
  43. package/spec/CommonScheme.ts +251 -251
  44. package/spec/DateScheme.ts +472 -472
  45. package/spec/NumberScheme.ts +1160 -1160
  46. package/spec/ObjectScheme.ts +499 -499
  47. package/spec/RegExpScheme.ts +112 -112
  48. package/spec/StringScheme.ts +1407 -1336
  49. package/spec/common-test-util.ts +63 -63
  50. package/spec/ejv.spec.ts +235 -235
  51. package/spec/testers.spec.ts +833 -833
  52. package/src/constants.ts +164 -162
  53. package/src/ejv.ts +1751 -1746
  54. package/src/index.ts +14 -14
  55. package/src/interfaces.ts +144 -144
  56. package/src/tester.ts +323 -312
  57. package/src/util.ts +124 -124
  58. package/tsconfig.cjs.json +8 -8
  59. package/tsconfig.esm.json +7 -7
  60. package/tsconfig.json +19 -18
  61. package/tsconfig.scripts.json +14 -14
  62. package/tsconfig.types.json +9 -9
@@ -0,0 +1,1339 @@
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, jsonStrTester, 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.JSON:
657
+ valid = jsonStrTester(valueAsString);
658
+ break;
659
+ case STRING_FORMAT.DATE:
660
+ valid = dateFormatTester(valueAsString);
661
+ break;
662
+ case STRING_FORMAT.TIME:
663
+ valid = timeFormatTester(valueAsString);
664
+ break;
665
+ case STRING_FORMAT.DATE_TIME:
666
+ valid = dateTimeFormatTester(valueAsString);
667
+ break;
668
+ }
669
+ return valid;
670
+ });
671
+ if (!foundFormatMatching) {
672
+ if (!arrayTester(stringScheme.format)) {
673
+ result = new EjvError({
674
+ type: ERROR_TYPE.FORMAT,
675
+ message: createErrorMsg(ERROR_MESSAGE.FORMAT, {
676
+ placeholders: [stringScheme.format]
677
+ }),
678
+ data,
679
+ path: _options.path,
680
+ errorScheme: stringScheme,
681
+ errorData: value
682
+ });
683
+ }
684
+ else {
685
+ result = new EjvError({
686
+ type: ERROR_TYPE.FORMAT_ONE_OF,
687
+ message: createErrorMsg(ERROR_MESSAGE.FORMAT_ONE_OF, {
688
+ placeholders: [JSON.stringify(stringScheme.format)]
689
+ }),
690
+ data,
691
+ path: _options.path,
692
+ errorScheme: stringScheme,
693
+ errorData: value
694
+ });
695
+ }
696
+ break;
697
+ }
698
+ }
699
+ if (definedTester(stringScheme.pattern)) {
700
+ // check parameter
701
+ if (stringScheme.pattern === null) {
702
+ return new EjvError({
703
+ type: ERROR_TYPE.INVALID_SCHEMES,
704
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
705
+ placeholders: ['null']
706
+ }),
707
+ data: data,
708
+ errorScheme: stringScheme,
709
+ isSchemeError: true
710
+ });
711
+ }
712
+ const isValidPattern = (pattern) => {
713
+ return (stringTester(pattern) && minLengthTester(pattern, 1))
714
+ || (regExpTester(pattern) && pattern.toString() !== '/(?:)/' && pattern.toString() !== '/null/');
715
+ };
716
+ const patternToString = (pattern) => {
717
+ let regExpStr;
718
+ if (pattern === null) {
719
+ regExpStr = '/null/';
720
+ }
721
+ else if (stringTester(pattern)) {
722
+ if (minLengthTester(pattern, 1)) {
723
+ regExpStr = new RegExp(pattern).toString();
724
+ }
725
+ else {
726
+ regExpStr = '//';
727
+ }
728
+ }
729
+ else {
730
+ regExpStr = pattern.toString();
731
+ }
732
+ // empty regular expression
733
+ if (regExpStr === '/(?:)/') {
734
+ regExpStr = '//';
735
+ }
736
+ return regExpStr;
737
+ };
738
+ const createArrayErrorMsg = (patternsAsArray) => {
739
+ return '[' + patternsAsArray.map((onePattern) => {
740
+ return patternToString(onePattern);
741
+ }).join(', ') + ']';
742
+ };
743
+ if (arrayTester(stringScheme.pattern)) {
744
+ const patternsAsArray = stringScheme.pattern;
745
+ if (!minLengthTester(patternsAsArray, 1)) { // empty array
746
+ return new EjvError({
747
+ type: ERROR_TYPE.INVALID_SCHEMES,
748
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
749
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
750
+ }),
751
+ data: data,
752
+ errorScheme: stringScheme,
753
+ isSchemeError: true
754
+ });
755
+ }
756
+ try {
757
+ const regExpPatterns = patternsAsArray.map((pattern) => {
758
+ if (!isValidPattern(pattern)) {
759
+ throw new Error(createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
760
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
761
+ }));
762
+ }
763
+ return new RegExp(pattern);
764
+ });
765
+ // check value
766
+ const foundMatchPattern = regExpPatterns.some((regexp) => {
767
+ return stringRegExpTester(valueAsString, regexp);
768
+ });
769
+ if (!foundMatchPattern) {
770
+ result = new EjvError({
771
+ type: ERROR_TYPE.PATTERN_ONE_OF,
772
+ message: createErrorMsg(ERROR_MESSAGE.PATTERN_ONE_OF, {
773
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
774
+ }),
775
+ data,
776
+ path: _options.path,
777
+ errorScheme: stringScheme,
778
+ errorData: value
779
+ });
780
+ break;
781
+ }
782
+ }
783
+ catch (e) { // eslint-disable-line @typescript-eslint/no-unused-vars
784
+ return new EjvError({
785
+ type: ERROR_TYPE.INVALID_SCHEMES,
786
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
787
+ placeholders: [createArrayErrorMsg(patternsAsArray)]
788
+ }),
789
+ data: data,
790
+ errorScheme: stringScheme,
791
+ isSchemeError: true
792
+ });
793
+ }
794
+ }
795
+ else {
796
+ const patternAsOne = stringScheme.pattern;
797
+ if (!isValidPattern(patternAsOne)) {
798
+ return new EjvError({
799
+ type: ERROR_TYPE.INVALID_SCHEMES,
800
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_STRING_PATTERN, {
801
+ placeholders: [patternToString(patternAsOne)]
802
+ }),
803
+ data: data,
804
+ errorScheme: stringScheme,
805
+ isSchemeError: true
806
+ });
807
+ }
808
+ // check value
809
+ const regExp = new RegExp(patternAsOne);
810
+ if (!stringRegExpTester(valueAsString, regExp)) {
811
+ result = new EjvError({
812
+ type: ERROR_TYPE.PATTERN,
813
+ message: createErrorMsg(ERROR_MESSAGE.PATTERN, {
814
+ placeholders: [patternToString(patternAsOne)]
815
+ }),
816
+ data,
817
+ path: _options.path,
818
+ errorScheme: stringScheme,
819
+ errorData: value
820
+ });
821
+ break;
822
+ }
823
+ }
824
+ }
825
+ break;
826
+ }
827
+ case DATA_TYPE.OBJECT: {
828
+ const valueAsObject = value;
829
+ const objectScheme = scheme;
830
+ if (definedTester(objectScheme.allowNoProperty)) {
831
+ if (!booleanTester(objectScheme.allowNoProperty)) {
832
+ return new EjvError({
833
+ type: ERROR_TYPE.INVALID_SCHEMES,
834
+ message: createErrorMsg(ERROR_MESSAGE.ALLOW_NO_PROPERTY_SHOULD_BE_BOOLEAN),
835
+ data: data,
836
+ errorScheme: objectScheme,
837
+ isSchemeError: true
838
+ });
839
+ }
840
+ if (!objectScheme.allowNoProperty && !hasPropertyTester(valueAsObject)) {
841
+ result = new EjvError({
842
+ type: ERROR_TYPE.PROPERTY,
843
+ message: ERROR_MESSAGE.PROPERTY,
844
+ data,
845
+ path: _options.path,
846
+ errorScheme: objectScheme,
847
+ errorData: value
848
+ });
849
+ break;
850
+ }
851
+ }
852
+ if (definedTester(objectScheme.properties)) {
853
+ if (!arrayTester(objectScheme.properties)) {
854
+ return new EjvError({
855
+ type: ERROR_TYPE.INVALID_SCHEMES,
856
+ message: createErrorMsg(ERROR_MESSAGE.PROPERTIES_SHOULD_BE_ARRAY),
857
+ data: data,
858
+ errorScheme: objectScheme,
859
+ isSchemeError: true
860
+ });
861
+ }
862
+ const properties = objectScheme.properties;
863
+ if (!minLengthTester(properties, 1)) {
864
+ return new EjvError({
865
+ type: ERROR_TYPE.INVALID_SCHEMES,
866
+ message: createErrorMsg(ERROR_MESSAGE.PROPERTIES_SHOULD_HAVE_ITEMS),
867
+ data: data,
868
+ errorScheme: objectScheme,
869
+ isSchemeError: true
870
+ });
871
+ }
872
+ if (!arrayTypeOfTester(properties, DATA_TYPE.OBJECT)) {
873
+ return new EjvError({
874
+ type: ERROR_TYPE.INVALID_SCHEMES,
875
+ message: createErrorMsg(ERROR_MESSAGE.PROPERTIES_SHOULD_BE_ARRAY_OF_OBJECT),
876
+ data: data,
877
+ errorScheme: objectScheme,
878
+ isSchemeError: true
879
+ });
880
+ }
881
+ if (!objectTester(value)) {
882
+ result = new EjvError({
883
+ type: ERROR_TYPE.TYPE_MISMATCH,
884
+ message: createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH, {
885
+ placeholders: ['object']
886
+ }),
887
+ data,
888
+ path: _options.path,
889
+ errorScheme: objectScheme,
890
+ errorData: value
891
+ });
892
+ break;
893
+ }
894
+ const partialData = data[key];
895
+ const partialScheme = objectScheme.properties;
896
+ scheme.parent = objectScheme;
897
+ // call recursively
898
+ result = _ejv(partialData, partialScheme, _options);
899
+ if (result) {
900
+ // inject original data
901
+ result.data = data;
902
+ }
903
+ }
904
+ break;
905
+ }
906
+ case DATA_TYPE.DATE: {
907
+ const valueAsDate = value;
908
+ const dateScheme = scheme;
909
+ const parentDateScheme = scheme.parent;
910
+ if (definedTester(dateScheme.min)
911
+ || definedTester(parentDateScheme?.min)) {
912
+ const minDateCandidate = dateScheme.min || parentDateScheme?.min;
913
+ if (!((stringTester(minDateCandidate)
914
+ && (dateFormatTester(minDateCandidate)
915
+ || dateTimeFormatTester(minDateCandidate)))
916
+ || dateTester(minDateCandidate))) {
917
+ return new EjvError({
918
+ type: ERROR_TYPE.INVALID_SCHEMES,
919
+ message: createErrorMsg(ERROR_MESSAGE.MIN_DATE_SHOULD_BE_DATE_OR_STRING),
920
+ data: data,
921
+ errorScheme: dateScheme,
922
+ isSchemeError: true
923
+ });
924
+ }
925
+ const effectiveMin = new Date(minDateCandidate);
926
+ if (definedTester(dateScheme.exclusiveMin)) {
927
+ if (!booleanTester(dateScheme.exclusiveMin)) {
928
+ return new EjvError({
929
+ type: ERROR_TYPE.INVALID_SCHEMES,
930
+ message: createErrorMsg(ERROR_MESSAGE.EXCLUSIVE_MIN_SHOULD_BE_BOOLEAN),
931
+ data: data,
932
+ errorScheme: dateScheme,
933
+ isSchemeError: true
934
+ });
935
+ }
936
+ if (dateScheme.exclusiveMin) {
937
+ if (!exclusiveMinDateTester(valueAsDate, effectiveMin)) {
938
+ result = new EjvError({
939
+ type: ERROR_TYPE.AFTER_DATE,
940
+ message: createErrorMsg(ERROR_MESSAGE.AFTER_DATE, {
941
+ placeholders: [effectiveMin.toISOString()]
942
+ }),
943
+ data,
944
+ path: _options.path,
945
+ errorScheme: dateScheme,
946
+ errorData: value
947
+ });
948
+ break;
949
+ }
950
+ }
951
+ else {
952
+ if (!minDateTester(valueAsDate, effectiveMin)) {
953
+ result = new EjvError({
954
+ type: ERROR_TYPE.AFTER_OR_SAME_DATE,
955
+ message: createErrorMsg(ERROR_MESSAGE.AFTER_OR_SAME_DATE, {
956
+ placeholders: [effectiveMin.toISOString()]
957
+ }),
958
+ data,
959
+ path: _options.path,
960
+ errorScheme: dateScheme,
961
+ errorData: value
962
+ });
963
+ break;
964
+ }
965
+ }
966
+ }
967
+ else {
968
+ if (!minDateTester(valueAsDate, effectiveMin)) {
969
+ result = new EjvError({
970
+ type: ERROR_TYPE.AFTER_OR_SAME_DATE,
971
+ message: createErrorMsg(ERROR_MESSAGE.AFTER_OR_SAME_DATE, {
972
+ placeholders: [effectiveMin.toISOString()]
973
+ }),
974
+ data,
975
+ path: _options.path,
976
+ errorScheme: dateScheme,
977
+ errorData: value
978
+ });
979
+ break;
980
+ }
981
+ }
982
+ }
983
+ if (definedTester(dateScheme.max)
984
+ || definedTester(parentDateScheme?.max)) {
985
+ const maxDateCandidate = dateScheme.max || parentDateScheme?.max;
986
+ if (!((stringTester(maxDateCandidate)
987
+ && (dateFormatTester(maxDateCandidate)
988
+ || dateTimeFormatTester(maxDateCandidate)))
989
+ || dateTester(maxDateCandidate))) {
990
+ return new EjvError({
991
+ type: ERROR_TYPE.INVALID_SCHEMES,
992
+ message: createErrorMsg(ERROR_MESSAGE.MAX_DATE_SHOULD_BE_DATE_OR_STRING),
993
+ data: data,
994
+ errorScheme: dateScheme,
995
+ isSchemeError: true
996
+ });
997
+ }
998
+ const effectiveMax = new Date(maxDateCandidate);
999
+ if (definedTester(dateScheme.exclusiveMax)) {
1000
+ if (!booleanTester(dateScheme.exclusiveMax)) {
1001
+ return new EjvError({
1002
+ type: ERROR_TYPE.INVALID_SCHEMES,
1003
+ message: createErrorMsg(ERROR_MESSAGE.EXCLUSIVE_MAX_SHOULD_BE_BOOLEAN),
1004
+ data: data,
1005
+ errorScheme: dateScheme,
1006
+ isSchemeError: true
1007
+ });
1008
+ }
1009
+ }
1010
+ if (dateScheme.exclusiveMax) {
1011
+ if (!exclusiveMaxDateTester(valueAsDate, effectiveMax)) {
1012
+ result = new EjvError({
1013
+ type: ERROR_TYPE.BEFORE_DATE,
1014
+ message: createErrorMsg(ERROR_MESSAGE.BEFORE_DATE, {
1015
+ placeholders: [effectiveMax.toISOString()]
1016
+ }),
1017
+ data,
1018
+ path: _options.path,
1019
+ errorScheme: dateScheme,
1020
+ errorData: value
1021
+ });
1022
+ break;
1023
+ }
1024
+ }
1025
+ else {
1026
+ if (!maxDateTester(valueAsDate, effectiveMax)) {
1027
+ result = new EjvError({
1028
+ type: ERROR_TYPE.BEFORE_OR_SAME_DATE,
1029
+ message: createErrorMsg(ERROR_MESSAGE.BEFORE_OR_SAME_DATE, {
1030
+ placeholders: [effectiveMax.toISOString()]
1031
+ }),
1032
+ data,
1033
+ path: _options.path,
1034
+ errorScheme: dateScheme,
1035
+ errorData: value
1036
+ });
1037
+ break;
1038
+ }
1039
+ }
1040
+ }
1041
+ break;
1042
+ }
1043
+ case DATA_TYPE.ARRAY: {
1044
+ const valueAsArray = value;
1045
+ const arrayScheme = scheme;
1046
+ if (definedTester(arrayScheme.length)) {
1047
+ const length = arrayScheme.length;
1048
+ if (!(numberTester(length) && integerTester(length))) {
1049
+ return new EjvError({
1050
+ type: ERROR_TYPE.INVALID_SCHEMES,
1051
+ message: createErrorMsg(ERROR_MESSAGE.LENGTH_SHOULD_BE_INTEGER),
1052
+ data: data,
1053
+ errorScheme: arrayScheme,
1054
+ isSchemeError: true
1055
+ });
1056
+ }
1057
+ if (!lengthTester(valueAsArray, length)) {
1058
+ result = new EjvError({
1059
+ type: ERROR_TYPE.LENGTH,
1060
+ message: createErrorMsg(ERROR_MESSAGE.LENGTH, {
1061
+ placeholders: ['' + length]
1062
+ }),
1063
+ data,
1064
+ path: _options.path,
1065
+ errorScheme: arrayScheme,
1066
+ errorData: value
1067
+ });
1068
+ break;
1069
+ }
1070
+ }
1071
+ if (definedTester(arrayScheme.minLength)) {
1072
+ const minLength = arrayScheme.minLength;
1073
+ if (!(numberTester(arrayScheme.minLength) && integerTester(minLength))) {
1074
+ return new EjvError({
1075
+ type: ERROR_TYPE.INVALID_SCHEMES,
1076
+ message: createErrorMsg(ERROR_MESSAGE.MIN_LENGTH_SHOULD_BE_INTEGER),
1077
+ data: data,
1078
+ errorScheme: arrayScheme,
1079
+ isSchemeError: true
1080
+ });
1081
+ }
1082
+ if (!minLengthTester(valueAsArray, minLength)) {
1083
+ result = new EjvError({
1084
+ type: ERROR_TYPE.MIN_LENGTH,
1085
+ message: createErrorMsg(ERROR_MESSAGE.MIN_LENGTH, {
1086
+ placeholders: ['' + minLength]
1087
+ }),
1088
+ data,
1089
+ path: _options.path,
1090
+ errorScheme: arrayScheme,
1091
+ errorData: value
1092
+ });
1093
+ break;
1094
+ }
1095
+ }
1096
+ if (definedTester(arrayScheme.maxLength)) {
1097
+ const maxLength = arrayScheme.maxLength;
1098
+ if (!(numberTester(arrayScheme.maxLength) && integerTester(maxLength))) {
1099
+ return new EjvError({
1100
+ type: ERROR_TYPE.INVALID_SCHEMES,
1101
+ message: createErrorMsg(ERROR_MESSAGE.MAX_LENGTH_SHOULD_BE_INTEGER),
1102
+ data: data,
1103
+ errorScheme: arrayScheme,
1104
+ isSchemeError: true
1105
+ });
1106
+ }
1107
+ if (!maxLengthTester(valueAsArray, maxLength)) {
1108
+ result = new EjvError({
1109
+ type: ERROR_TYPE.MAX_LENGTH,
1110
+ message: createErrorMsg(ERROR_MESSAGE.MAX_LENGTH, {
1111
+ placeholders: ['' + maxLength]
1112
+ }),
1113
+ data,
1114
+ path: _options.path,
1115
+ errorScheme: arrayScheme,
1116
+ errorData: value
1117
+ });
1118
+ break;
1119
+ }
1120
+ }
1121
+ if (definedTester(arrayScheme.unique)) {
1122
+ if (!booleanTester(arrayScheme.unique)) {
1123
+ return new EjvError({
1124
+ type: ERROR_TYPE.INVALID_SCHEMES,
1125
+ message: createErrorMsg(ERROR_MESSAGE.UNIQUE_SHOULD_BE_BOOLEAN),
1126
+ data: data,
1127
+ errorScheme: arrayScheme,
1128
+ isSchemeError: true
1129
+ });
1130
+ }
1131
+ if (arrayScheme.unique && !uniqueItemsTester(valueAsArray)) {
1132
+ result = new EjvError({
1133
+ type: ERROR_TYPE.UNIQUE_ITEMS,
1134
+ message: ERROR_MESSAGE.UNIQUE_ITEMS,
1135
+ data,
1136
+ path: _options.path,
1137
+ errorScheme: arrayScheme,
1138
+ errorData: value
1139
+ });
1140
+ break;
1141
+ }
1142
+ }
1143
+ if (definedTester(arrayScheme.items)) {
1144
+ // convert array to object
1145
+ if (valueAsArray.length > 0) {
1146
+ const now = new Date();
1147
+ const tempKeyArr = valueAsArray.map((_value, i) => {
1148
+ return '' + (+now + i);
1149
+ });
1150
+ if (stringTester(arrayScheme.items) // by DataType
1151
+ || (arrayTester(arrayScheme.items) && arrayTypeOfTester(arrayScheme.items, DATA_TYPE.STRING)) // by DataType[]
1152
+ ) {
1153
+ const itemTypes = (arrayTester(arrayScheme.items)
1154
+ ? arrayScheme.items
1155
+ : [arrayScheme.items]);
1156
+ const itemTypeError = itemTypes.find((type) => {
1157
+ return !definedTester(type)
1158
+ || !stringTester(type)
1159
+ || !enumTester(type, allDataType);
1160
+ });
1161
+ if (itemTypeError) {
1162
+ return new EjvError({
1163
+ type: ERROR_TYPE.INVALID_SCHEMES,
1164
+ message: createErrorMsg(ERROR_MESSAGE.SCHEMES_HAS_INVALID_TYPE, {
1165
+ placeholders: [itemTypeError]
1166
+ }),
1167
+ data: data,
1168
+ errorScheme: scheme,
1169
+ isSchemeError: true
1170
+ });
1171
+ }
1172
+ const partialData = {};
1173
+ const partialSchemes = [];
1174
+ tempKeyArr.forEach((tempKey, i) => {
1175
+ partialData[tempKey] = valueAsArray[i];
1176
+ partialSchemes.push({
1177
+ key: tempKey,
1178
+ type: itemTypes
1179
+ });
1180
+ });
1181
+ scheme.parent = arrayScheme;
1182
+ // call recursively
1183
+ const partialResult = _ejv(partialData, partialSchemes, _options);
1184
+ // convert new EjvError
1185
+ if (partialResult) {
1186
+ let errorMsg;
1187
+ if (arrayTester(arrayScheme.items)) {
1188
+ errorMsg = createErrorMsg(ERROR_MESSAGE.ITEMS_TYPE, {
1189
+ placeholders: [JSON.stringify(itemTypes)]
1190
+ });
1191
+ }
1192
+ else {
1193
+ errorMsg = createErrorMsg(ERROR_MESSAGE.ITEMS_TYPE, {
1194
+ placeholders: [arrayScheme.items]
1195
+ });
1196
+ }
1197
+ const partialKeys = (partialResult.path || '').split('/');
1198
+ const partialKey = partialKeys[partialKeys.length - 1];
1199
+ const partialScheme = partialSchemes.find((_scheme) => {
1200
+ return _scheme.key === partialKey;
1201
+ });
1202
+ const partialKeyIndex = partialSchemes.indexOf(partialScheme);
1203
+ result = new EjvError({
1204
+ type: ERROR_TYPE.ITEMS_TYPE,
1205
+ message: errorMsg,
1206
+ data,
1207
+ path: [..._options.path, '' + partialKeyIndex],
1208
+ errorScheme: partialScheme,
1209
+ errorData: partialData[partialKey]
1210
+ });
1211
+ }
1212
+ break;
1213
+ }
1214
+ else if ((objectTester(arrayScheme.items) && arrayScheme.items !== null) // by Scheme
1215
+ || (arrayTester(arrayScheme.items) && arrayTypeOfTester(arrayScheme.items, DATA_TYPE.OBJECT)) // by Scheme[]
1216
+ ) {
1217
+ const itemsAsSchemes = arrayTester(arrayScheme.items)
1218
+ ? arrayScheme.items
1219
+ : [arrayScheme.items];
1220
+ let partialError = null;
1221
+ // use for() instead of forEach() to break
1222
+ const valueLength = valueAsArray.length;
1223
+ for (let arrIndex = 0; arrIndex < valueLength; arrIndex++) {
1224
+ const oneValue = valueAsArray[arrIndex];
1225
+ const partialData = {};
1226
+ const partialSchemes = [];
1227
+ const tempKeyForThisValue = tempKeyArr[arrIndex];
1228
+ partialData[tempKeyForThisValue] = oneValue;
1229
+ partialSchemes.push(...itemsAsSchemes.map((oneScheme) => {
1230
+ const newScheme = clone(oneScheme); // divide instance
1231
+ newScheme.key = tempKeyForThisValue;
1232
+ return newScheme;
1233
+ }));
1234
+ const partialResults = partialSchemes.map((partialScheme) => {
1235
+ // call recursively
1236
+ const partialResult = _ejv(partialData, [partialScheme], _options);
1237
+ if (partialResult) {
1238
+ partialResult.path = (partialResult.path || '').replace(tempKeyForThisValue, '' + arrIndex);
1239
+ }
1240
+ return partialResult;
1241
+ });
1242
+ if (!partialResults.some((oneResult) => oneResult === null)) {
1243
+ partialError = partialResults.find((oneResult) => {
1244
+ return !!oneResult;
1245
+ });
1246
+ break;
1247
+ }
1248
+ }
1249
+ if (partialError) {
1250
+ let errorType;
1251
+ let errorMsg;
1252
+ if (!!itemsAsSchemes && itemsAsSchemes.length > 1) {
1253
+ errorType = ERROR_TYPE.ITEMS_SCHEMES;
1254
+ errorMsg = createErrorMsg(ERROR_MESSAGE.ITEMS_SCHEMES, {
1255
+ placeholders: [JSON.stringify(itemsAsSchemes)]
1256
+ });
1257
+ }
1258
+ else {
1259
+ errorType = partialError.type;
1260
+ errorMsg = partialError.message;
1261
+ if (errorType === ERROR_TYPE.REQUIRED) {
1262
+ // REQUIRED in array is TYPE_MISMATCH except with nullable === true
1263
+ errorType = ERROR_TYPE.TYPE_MISMATCH;
1264
+ errorMsg = createErrorMsg(ERROR_MESSAGE.TYPE_MISMATCH, {
1265
+ placeholders: [JSON.stringify(arrayScheme.items)]
1266
+ });
1267
+ }
1268
+ }
1269
+ result = new EjvError({
1270
+ type: errorType,
1271
+ message: errorMsg,
1272
+ data
1273
+ });
1274
+ if (errorType === ERROR_TYPE.INVALID_SCHEMES) {
1275
+ result.errorScheme = arrayScheme;
1276
+ result.isSchemeError = true;
1277
+ result.isDataError = false;
1278
+ }
1279
+ else {
1280
+ result.path = partialError.path;
1281
+ result.errorData = partialError.errorData;
1282
+ }
1283
+ break;
1284
+ }
1285
+ }
1286
+ else {
1287
+ return new EjvError({
1288
+ type: ERROR_TYPE.INVALID_SCHEMES,
1289
+ message: createErrorMsg(ERROR_MESSAGE.INVALID_ITEMS_SCHEME, {
1290
+ placeholders: [JSON.stringify(arrayScheme.items)]
1291
+ }),
1292
+ data: data,
1293
+ errorScheme: arrayScheme,
1294
+ isSchemeError: true
1295
+ });
1296
+ }
1297
+ }
1298
+ }
1299
+ break;
1300
+ }
1301
+ }
1302
+ if (result) {
1303
+ break;
1304
+ }
1305
+ }
1306
+ if (result !== null && definedTester(options.customErrorMsg)) {
1307
+ const customErrorMsgObj = options.customErrorMsg;
1308
+ // override error message
1309
+ const customMsg = customErrorMsgObj[result.type];
1310
+ if (definedTester(customMsg)) {
1311
+ result.message = customMsg;
1312
+ }
1313
+ }
1314
+ return result;
1315
+ };
1316
+ export const ejv = (data, schemes, options) => {
1317
+ // check data itself
1318
+ if (!definedTester(data) || !objectTester(data) || data === null) {
1319
+ return new EjvError({
1320
+ type: ERROR_TYPE.NO_DATA,
1321
+ message: ERROR_MESSAGE.NO_DATA,
1322
+ data: data,
1323
+ path: undefined,
1324
+ errorScheme: undefined,
1325
+ errorData: data,
1326
+ isSchemeError: false
1327
+ });
1328
+ }
1329
+ const internalOption = (options
1330
+ ? {
1331
+ ...options
1332
+ }
1333
+ : {});
1334
+ if (!definedTester(internalOption.path)) {
1335
+ internalOption.path = [];
1336
+ }
1337
+ return _ejv(data, schemes, internalOption);
1338
+ };
1339
+ //# sourceMappingURL=ejv.js.map