@jarenjs/validate 0.8.4 → 0.9.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 (48) hide show
  1. package/ARCHITECTURE.md +1067 -0
  2. package/LICENSE +21 -0
  3. package/README.md +339 -2
  4. package/dist/types/array.d.ts +2 -0
  5. package/dist/types/bigint.d.ts +1 -0
  6. package/dist/types/combine.d.ts +1 -0
  7. package/dist/types/condition.d.ts +1 -0
  8. package/dist/types/content.d.ts +3 -0
  9. package/dist/types/data.d.ts +7 -0
  10. package/dist/types/dollar-data.d.ts +20 -0
  11. package/dist/types/dynamic-ref.d.ts +44 -0
  12. package/dist/types/enum.d.ts +1 -0
  13. package/dist/types/format.d.ts +21 -0
  14. package/dist/types/index.d.ts +874 -0
  15. package/dist/types/number.d.ts +1 -0
  16. package/dist/types/object.d.ts +3 -0
  17. package/dist/types/query-keyword.d.ts +19 -0
  18. package/dist/types/query.d.ts +29 -0
  19. package/dist/types/schema.d.ts +1 -0
  20. package/dist/types/string.d.ts +1 -0
  21. package/dist/types/tools.d.ts +51 -0
  22. package/dist/types/traverse.d.ts +32 -0
  23. package/dist/types/unevaluated.d.ts +12 -0
  24. package/package.json +32 -7
  25. package/src/array.js +565 -0
  26. package/src/bigint.js +97 -0
  27. package/src/combine.js +226 -0
  28. package/src/condition.js +109 -0
  29. package/src/content.js +83 -0
  30. package/src/data.js +477 -0
  31. package/src/dollar-data.js +629 -0
  32. package/src/dynamic-ref.js +121 -0
  33. package/src/enum.js +148 -0
  34. package/src/format.js +66 -0
  35. package/src/index.js +1854 -0
  36. package/src/number.js +159 -0
  37. package/src/object.js +755 -0
  38. package/src/query-keyword.js +99 -0
  39. package/src/query.js +59 -0
  40. package/src/schema.js +645 -0
  41. package/src/string.js +152 -0
  42. package/src/tools.js +205 -0
  43. package/src/traverse.js +433 -0
  44. package/src/unevaluated.js +151 -0
  45. package/dist/index.js +0 -1998
  46. package/dist/index.js.map +0 -7
  47. package/dist/index.min.js +0 -2
  48. package/dist/index.min.js.map +0 -7
package/src/array.js ADDED
@@ -0,0 +1,565 @@
1
+ //@ts-check
2
+
3
+ import {
4
+ isArrayClass,
5
+ getObjectType,
6
+ } from '@jarenjs/core';
7
+
8
+ import {
9
+ isUniqueDeepArray,
10
+ } from '@jarenjs/core/object';
11
+
12
+ import {
13
+ getBoolishType,
14
+ getIntishType,
15
+ } from '@jarenjs/core/number';
16
+
17
+ import {
18
+ trueThat,
19
+ falseThat,
20
+ } from '@jarenjs/core/function';
21
+
22
+ import {
23
+ getBoolOrObjectClass,
24
+ getArrayClassMinItems,
25
+ isOfSchemaType,
26
+ } from './tools.js';
27
+
28
+ //#region Primitives
29
+ function compileMinItems(schemaObj, jsonSchema) {
30
+ const min = getIntishType(jsonSchema.minItems) || 0;
31
+ if (min < 1) return undefined;
32
+
33
+ const addError = schemaObj.createErrorHandler(min, 'minItems');
34
+ return function validateMinItems(len = 0, dataPath = '') {
35
+ return len >= min || addError(len, dataPath);
36
+ };
37
+ }
38
+
39
+ function compileMaxItems(schemaObj, jsonSchema) {
40
+ const max = getIntishType(jsonSchema.maxItems) || -1;
41
+ if (max < 0) return undefined;
42
+ const min = getIntishType(jsonSchema.minItems) || 0;
43
+ if (max < min) throw new Error('maxItems must be greater then minItems');
44
+
45
+ const addError = schemaObj.createErrorHandler(max, 'maxItems');
46
+ return function validateMaxItems(len = 0, dataPath = '') {
47
+ return len <= max || addError(len, dataPath);
48
+ };
49
+ }
50
+
51
+ function createBooleanValidator(schemaObj, jsonSchema, key, validationFn) {
52
+ const value = getBoolishType(jsonSchema[key]);
53
+ if (value !== true) return undefined;
54
+
55
+ const addError = schemaObj.createErrorHandler(value, key);
56
+
57
+ return function validateBooleanComparator(data, dataPath) {
58
+ return validationFn(data) || addError(data, dataPath);
59
+ };
60
+ }
61
+
62
+ const compileUniqueItems = (schemaObj, jsonSchema) =>
63
+ createBooleanValidator(schemaObj, jsonSchema, 'uniqueItems', isUniqueDeepArray);
64
+ //#endregion
65
+
66
+ //#region Tuple
67
+
68
+ function compileTupleInternal(schemaObj, jsonSchema, itemsKey, additionalKey) {
69
+ const tuple = getArrayClassMinItems(jsonSchema[itemsKey], 1);
70
+ if (tuple == null)
71
+ return undefined;
72
+
73
+ // Pre-compile all validators upfront
74
+ const validators = new Array(tuple.length);
75
+ for (let i = 0; i < tuple.length; i++) {
76
+ validators[i] = compileItemValidator(schemaObj, tuple[i], itemsKey, i);
77
+ }
78
+ const vlength = validators.length;
79
+
80
+ const additional = getBoolOrObjectClass(jsonSchema[additionalKey], true);
81
+ if (typeof additional === 'boolean') {
82
+ if (additional === true) {
83
+ return function validateTupleBoolTrue(data, dataPath, dataRoot, i) {
84
+ if (i >= vlength) return true;
85
+ return validators[i](data, dataPath, dataRoot);
86
+ };
87
+ }
88
+ // additional === false
89
+ return function validateTupleBoolFalse(data, dataPath, dataRoot, i) {
90
+ if (i >= vlength) return false;
91
+ return validators[i](data, dataPath, dataRoot);
92
+ };
93
+ }
94
+
95
+ // For object additional schema, compile validator once
96
+ const validateAdditional = schemaObj.createValidator(additional, additionalKey);
97
+ return function validateTupleSchema(data, dataPath, dataRoot, i) {
98
+ if (i < vlength) {
99
+ return validators[i](data, dataPath, dataRoot);
100
+ }
101
+ return validateAdditional(data, dataPath, dataRoot);
102
+ };
103
+ }
104
+
105
+ function compilePrefixItems(schemaObj, jsonSchema) {
106
+ return compileTupleInternal(schemaObj, jsonSchema, 'prefixItems', 'items');
107
+ }
108
+
109
+ function compileTupleItems(schemaObj, jsonSchema) {
110
+ return compileTupleInternal(schemaObj, jsonSchema, 'items', 'additionalItems');
111
+ }
112
+
113
+ //#endregion
114
+
115
+ //#region Contains
116
+ function compileArrayContains(schemaObj, jsonSchema) {
117
+ const contains = getObjectType(jsonSchema.contains);
118
+ if (contains == null) return undefined;
119
+
120
+ return schemaObj.createValidator(contains, 'contains');
121
+ }
122
+
123
+ function compileContainsMinMax(schemaObj, jsonSchema) {
124
+ const contains = getObjectType(jsonSchema.contains);
125
+ if (contains == null) return undefined;
126
+
127
+ const minContains = getIntishType(jsonSchema.minContains);
128
+ const maxContains = getIntishType(jsonSchema.maxContains);
129
+
130
+ const addNonError = schemaObj.createErrorHandler(0, 'contains');
131
+ const addMinError = schemaObj.createErrorHandler(minContains, 'minContains');
132
+ const addMaxError = schemaObj.createErrorHandler(maxContains, 'maxContains');
133
+
134
+ if (minContains == null && maxContains == null) {
135
+ return function validateContainsAtLeastOne(count, dataPath) {
136
+ return count > 0 || addNonError(count, dataPath);
137
+ };
138
+ }
139
+
140
+ if (maxContains == null) {
141
+ return function validateMinContains(count, dataPath) {
142
+ return count >= (minContains || 0)
143
+ || addMinError(count, dataPath);
144
+ };
145
+ }
146
+
147
+ if (minContains == null) {
148
+ return function validateMaxContains(count, dataPath) {
149
+ return count === 0
150
+ ? addNonError(count, dataPath)
151
+ : count <= maxContains
152
+ || addMaxError(count, dataPath);
153
+ };
154
+ }
155
+
156
+ return function validateMinMaxContains(count, dataPath) {
157
+ return (count >= minContains || addMinError(count, dataPath))
158
+ && (count <= maxContains || addMaxError(count, dataPath));
159
+ };
160
+ }
161
+
162
+ function compileArrayContainsBoolean(schemaObj, jsonSchema) {
163
+ const contains = getBoolishType(jsonSchema.contains);
164
+ if (contains === true) {
165
+ const addError = schemaObj.createErrorHandler(true, 'contains');
166
+ return function validateArrayContainsTrue(data, dataPath) {
167
+ return data.length > 0
168
+ || addError(data, dataPath);
169
+ };
170
+ }
171
+ if (contains === false) {
172
+ const addError = schemaObj.createErrorHandler(false, 'contains');
173
+ return function validateArrayContainsFalse(data, dataPath) {
174
+ return addError(data, dataPath);
175
+ };
176
+ }
177
+ return undefined;
178
+ }
179
+ //#endregion
180
+
181
+ //#region Items
182
+ function compileArrayItemsBoolean(schemaObj, jsonSchema) {
183
+ const items = getBoolishType(jsonSchema.items);
184
+ if (items === true) return trueThat;
185
+ if (items !== false) return undefined;
186
+
187
+ // With prefixItems (draft 2020-12), items:false only forbids items beyond
188
+ // the prefix; that is enforced by the tuple validator, not here.
189
+ if (getArrayClassMinItems(jsonSchema.prefixItems, 1) != null)
190
+ return undefined;
191
+
192
+ const addError = schemaObj.createErrorHandler(false, 'items');
193
+ return function validateArrayItemsFalse(data, dataPath) {
194
+ return data.length === 0
195
+ || addError(data, dataPath);
196
+ };
197
+ }
198
+
199
+ /**
200
+ * Compile item schema directly without intermediate wrapper
201
+ * This flattens the call stack by avoiding nested validator function calls
202
+ * @param {Object} schemaObj - The schema object
203
+ * @param {Object} itemSchema - Schema for individual items
204
+ * @param {string} key - Key for error reporting
205
+ * @param {number} index - Index for tuple items
206
+ * @returns {Function} Direct validator function
207
+ */
208
+ function compileItemValidator(schemaObj, itemSchema, key, index) {
209
+ if (itemSchema === true) return trueThat;
210
+ if (itemSchema === false) return falseThat;
211
+
212
+ // For simple type schemas, use inline validation
213
+ if (typeof itemSchema === 'object' && itemSchema !== null) {
214
+ // Fast path: $ref-only schema - check property directly before calling Object.keys
215
+ // This avoids the overhead of Object.keys for the most common case
216
+ if (itemSchema.$ref !== undefined) {
217
+ const keys = Object.keys(itemSchema);
218
+ if (keys.length === 1) {
219
+ // Use the root to resolve the ref directly to the target validator
220
+ // This avoids the overhead of creating an intermediate ValidationObject
221
+ const root = schemaObj.root;
222
+ if (root && root.resolveObject) {
223
+ try {
224
+ const targetObj = root.resolveObject(itemSchema.$ref, schemaObj.path, itemSchema);
225
+ if (targetObj && targetObj.validate) {
226
+ return targetObj.validate;
227
+ }
228
+ } catch (e) {
229
+ // Fall through to default handling
230
+ }
231
+ }
232
+ }
233
+ }
234
+
235
+ // Fast path: type-only schema (most common case) - check property directly first
236
+ if (itemSchema.type !== undefined && Object.keys(itemSchema).length === 1) {
237
+ return compileTypeOnlyValidator(itemSchema.type);
238
+ }
239
+
240
+ // Fast path: required-only schema - check property directly first
241
+ if (itemSchema.required !== undefined && Object.keys(itemSchema).length === 1) {
242
+ const required = itemSchema.required;
243
+ return function validateRequiredOnly(data, dataPath, dataRoot) {
244
+ // Required properties only apply to objects, not arrays or other types
245
+ if (typeof data !== 'object' || data === null || Array.isArray(data)) return true;
246
+ for (let i = 0; i < required.length; i++) {
247
+ if (!(required[i] in data)) return false;
248
+ }
249
+ return true;
250
+ };
251
+ }
252
+ }
253
+
254
+ // Fall back to full schema compilation for complex cases
255
+ return schemaObj.createValidator(itemSchema, key, index);
256
+ }
257
+
258
+ /**
259
+ * Compile a validator for simple type-only schemas
260
+ * @param {string} type - The type to validate
261
+ * @returns {Function} Type validator function
262
+ */
263
+ function compileTypeOnlyValidator(type) {
264
+ switch (type) {
265
+ case 'string':
266
+ return function validateString(data) {
267
+ return typeof data === 'string';
268
+ };
269
+ case 'number':
270
+ return function validateNumber(data) {
271
+ return typeof data === 'number' && !isNaN(data);
272
+ };
273
+ case 'integer':
274
+ return function validateInteger(data) {
275
+ return typeof data === 'number' && Number.isInteger(data);
276
+ };
277
+ case 'boolean':
278
+ return function validateBoolean(data) {
279
+ return typeof data === 'boolean';
280
+ };
281
+ case 'array':
282
+ return function validateArray(data) {
283
+ return Array.isArray(data);
284
+ };
285
+ case 'object':
286
+ return function validateObject(data) {
287
+ return typeof data === 'object' && data !== null && !Array.isArray(data);
288
+ };
289
+ case 'null':
290
+ return function validateNull(data) {
291
+ return data === null;
292
+ };
293
+ default:
294
+ return trueThat;
295
+ }
296
+ }
297
+ //#endregion
298
+
299
+ //#region Main
300
+ export function compileArrayPrimitives(schemaObj, jsonSchema) {
301
+ // minItems/maxItems/uniqueItems belong to the validation vocabulary;
302
+ // assert nothing when the metaschema disables it.
303
+ if (schemaObj.options.vocabValidation === false)
304
+ return undefined;
305
+
306
+ const minItems = compileMinItems(schemaObj, jsonSchema);
307
+ const maxItems = compileMaxItems(schemaObj, jsonSchema);
308
+ const uniqueItems = compileUniqueItems(schemaObj, jsonSchema);
309
+
310
+ if ((minItems
311
+ || maxItems
312
+ || uniqueItems) == null)
313
+ return undefined;
314
+
315
+ // Single-constraint schemas are the common case; skip the trueThat chain.
316
+ if (minItems == null && maxItems == null)
317
+ return uniqueItems;
318
+
319
+ if (uniqueItems == null) {
320
+ if (maxItems == null) {
321
+ return function validateArrayMinItems(data, dataPath) {
322
+ return minItems(data.length, dataPath);
323
+ };
324
+ }
325
+ if (minItems == null) {
326
+ return function validateArrayMaxItems(data, dataPath) {
327
+ return maxItems(data.length, dataPath);
328
+ };
329
+ }
330
+ return function validateArrayMinMaxItems(data, dataPath) {
331
+ const len = data.length;
332
+ return minItems(len, dataPath)
333
+ && maxItems(len, dataPath);
334
+ };
335
+ }
336
+
337
+ const isMinItems = minItems || trueThat;
338
+ const isMaxItems = maxItems || trueThat;
339
+
340
+ return function validateArrayPrimitives(data, dataPath) {
341
+ const len = data.length;
342
+ return isMinItems(len, dataPath)
343
+ && isMaxItems(len, dataPath)
344
+ && uniqueItems(data, dataPath);
345
+ };
346
+ }
347
+
348
+ function compileArrayChildren(schemaObj, jsonSchema) {
349
+ // Check for prefixItems (draft 2020-12+) first, then items.
350
+ // A document that declares an older draft via $schema treats
351
+ // prefixItems as an unknown keyword.
352
+ const prefixItems = (schemaObj.declaredDraft != null && schemaObj.declaredDraft < 2020)
353
+ ? undefined
354
+ : getArrayClassMinItems(jsonSchema.prefixItems, 1);
355
+ const items = jsonSchema.items;
356
+ const isTuple = getArrayClassMinItems(items, 1) != null;
357
+
358
+ const root = schemaObj.root;
359
+ const track = root.usesUnevaluated;
360
+ // In draft 2020-12 contains produces item annotations; in 2019-09 it doesn't.
361
+ const trackContains = track && (schemaObj.options.draftVersion || 7) >= 2020;
362
+ // Item paths are consumed by error reporting and $data resolution only.
363
+ const extendPaths = !schemaObj.options.skipErrors || root.usesDollarData;
364
+
365
+ // Indexes below this limit count as evaluated (for unevaluatedItems) when
366
+ // their item validation succeeds. Extra tuple items beyond the tuple length
367
+ // pass validation when additionalItems/items is ABSENT, but are then not
368
+ // evaluated and must remain visible to unevaluatedItems.
369
+ let evalLimit = Infinity;
370
+ if (track) {
371
+ if (prefixItems != null) {
372
+ if (items === undefined) evalLimit = prefixItems.length;
373
+ } else if (isTuple) {
374
+ if (jsonSchema.additionalItems === undefined) evalLimit = items.length;
375
+ }
376
+ }
377
+
378
+ let validateItem;
379
+
380
+ if (prefixItems != null) {
381
+ // Draft 2020-12+ style prefixItems
382
+ validateItem = compilePrefixItems(schemaObj, jsonSchema);
383
+ } else if (isTuple) {
384
+ // Draft 7 style tuple items
385
+ validateItem = compileTupleItems(schemaObj, jsonSchema);
386
+ } else if (items !== undefined) {
387
+ // Single schema for all items
388
+ const itemsSchema = getObjectType(items);
389
+ if (itemsSchema != null) {
390
+ // Use direct validator compilation for items
391
+ validateItem = compileItemValidator(schemaObj, itemsSchema, 'items', undefined);
392
+
393
+ // Wrap single-item validator with index loop
394
+ const itemValidator = validateItem;
395
+ validateItem = function validateSingleItemSchema(data, dataPath, dataRoot, i) {
396
+ return itemValidator(data, dataPath, dataRoot);
397
+ };
398
+ } else if (items === true) {
399
+ validateItem = trueThat;
400
+ }
401
+ // items === false is fully handled by compileArrayItemsBoolean: only an
402
+ // empty array can pass, so a per-item validator would never be invoked.
403
+ }
404
+
405
+ const validateContains = compileArrayContains(schemaObj, jsonSchema);
406
+ if ((validateItem || validateContains) == null)
407
+ return undefined;
408
+
409
+ const validateMinMax = compileContainsMinMax(schemaObj, jsonSchema) || trueThat;
410
+
411
+ const maxItems = getIntishType(jsonSchema.maxItems) || 0;
412
+
413
+ const resolveLength = len => (maxItems > 0
414
+ ? Math.min(maxItems, len)
415
+ : len);
416
+
417
+ // Fast path: items only, no contains
418
+ if (validateContains == null && validateItem != null) {
419
+ // if validateItem is trueThat, just check length
420
+ if (validateItem === trueThat) {
421
+ // items: true evaluates every item, which matters when annotations
422
+ // are tracked for unevaluatedItems.
423
+ if (track) {
424
+ return function validateArrayItemsTrue(data, dataPath, dataRoot) {
425
+ root.evalLog.add(data, -1);
426
+ return true;
427
+ };
428
+ }
429
+ return undefined; // No actual validation needed
430
+ }
431
+
432
+ const addError = schemaObj.createErrorHandler(0, 'items');
433
+ const validator = validateItem;
434
+
435
+ return function validateArrayItemsOnly(data, dataPath, dataRoot) {
436
+ const len = resolveLength(data.length);
437
+ const arr = data;
438
+
439
+ let invalid = 0;
440
+ for (let i = 0; i < len; ++i) {
441
+ const itemPath = extendPaths ? dataPath + '/' + i : dataPath;
442
+ // Direct validator call, no intermediate wrappers
443
+ if (validator(arr[i], itemPath, dataRoot, i) !== true) {
444
+ invalid++;
445
+ }
446
+ else if (track && i < evalLimit) {
447
+ root.evalLog.add(data, i);
448
+ }
449
+ }
450
+ return invalid === 0
451
+ || addError(invalid, dataPath);
452
+ };
453
+ }
454
+
455
+ // Fast path: contains only, no items
456
+ if (validateItem == null && validateContains != null) {
457
+ const validator = validateContains;
458
+
459
+ return function validateArrayContainsOnly(data, dataPath) {
460
+ const len = resolveLength(data.length);
461
+ const arr = data;
462
+
463
+ let contains = 0;
464
+ for (let i = 0; i < len; ++i) {
465
+ if (validator(arr[i], dataPath) === true) {
466
+ contains++;
467
+ if (trackContains) root.evalLog.add(data, i);
468
+ }
469
+ }
470
+ return validateMinMax(contains, dataPath);
471
+ };
472
+ }
473
+
474
+ // Combined: both items and contains
475
+ const itemValidator = validateItem;
476
+ const containsValidator = validateContains;
477
+
478
+ return function validateArrayChildren(data, dataPath, dataRoot) {
479
+ const len = resolveLength(data.length);
480
+ const arr = data;
481
+
482
+ let invalid = 0;
483
+ let contains = 0;
484
+ for (let i = 0; i < len; ++i) {
485
+ const obj = arr[i];
486
+ const itemPath = extendPaths ? dataPath + '/' + i : dataPath;
487
+ // Direct validator calls without intermediate wrappers
488
+ if (itemValidator(obj, itemPath, dataRoot, i) !== true) {
489
+ invalid++;
490
+ }
491
+ else if (track && i < evalLimit) {
492
+ root.evalLog.add(data, i);
493
+ }
494
+ if (containsValidator(obj, dataPath, dataRoot) === true) {
495
+ contains++;
496
+ if (trackContains) root.evalLog.add(data, i);
497
+ }
498
+ }
499
+ return invalid === 0
500
+ && validateMinMax(contains, dataPath);
501
+ };
502
+ }
503
+
504
+ export function compileArraySchema(schemaObj, jsonSchema) {
505
+ if (isOfSchemaType(jsonSchema, 'set'))
506
+ return undefined;
507
+
508
+ const compiledPrimitives = compileArrayPrimitives(schemaObj, jsonSchema);
509
+ const compiledItemsBoolean = compileArrayItemsBoolean(schemaObj, jsonSchema);
510
+ const compiledContainsBoolean = compileArrayContainsBoolean(schemaObj, jsonSchema);
511
+ const compiledArrayChildren = compileArrayChildren(schemaObj, jsonSchema);
512
+
513
+ if ((compiledPrimitives
514
+ || compiledItemsBoolean
515
+ || compiledContainsBoolean
516
+ || compiledArrayChildren) === undefined)
517
+ return undefined;
518
+
519
+ // Single-validator schemas are the common case; skip the trueThat chain.
520
+ const parts = [];
521
+ if (compiledPrimitives) parts.push(compiledPrimitives);
522
+ if (compiledItemsBoolean && compiledItemsBoolean !== trueThat) parts.push(compiledItemsBoolean);
523
+ if (compiledContainsBoolean) parts.push(compiledContainsBoolean);
524
+ if (compiledArrayChildren) parts.push(compiledArrayChildren);
525
+
526
+ if (parts.length === 0)
527
+ return undefined;
528
+
529
+ if (parts.length === 1) {
530
+ const single = parts[0];
531
+ return function validateArraySchemaSingle(data, dataPath, dataRoot) {
532
+ return isArrayClass(data)
533
+ ? single(data, dataPath, dataRoot)
534
+ : true;
535
+ };
536
+ }
537
+
538
+ if (parts.length === 2) {
539
+ const first = parts[0];
540
+ const second = parts[1];
541
+ return function validateArraySchemaDouble(data, dataPath, dataRoot) {
542
+ if (isArrayClass(data)) {
543
+ return first(data, dataPath, dataRoot)
544
+ && second(data, dataPath, dataRoot);
545
+ }
546
+ return true;
547
+ };
548
+ }
549
+
550
+ const validatePrimitives = compiledPrimitives || trueThat;
551
+ const hasBooleanItems = compiledItemsBoolean || trueThat;
552
+ const hasBooleanContains = compiledContainsBoolean || trueThat;
553
+ const validateItems = compiledArrayChildren || trueThat;
554
+
555
+ return function validateArraySchema(data, dataPath, dataRoot) {
556
+ if (isArrayClass(data)) {
557
+ return validatePrimitives(data, dataPath)
558
+ && hasBooleanItems(data, dataPath, dataRoot)
559
+ && hasBooleanContains(data, dataPath, dataRoot)
560
+ && validateItems(data, dataPath, dataRoot);
561
+ }
562
+ return true;
563
+ };
564
+ }
565
+ //#endregion
package/src/bigint.js ADDED
@@ -0,0 +1,97 @@
1
+ //@ts-check
2
+
3
+ import {
4
+ isBigIntType,
5
+ getBigIntType,
6
+ getInclusiveExclusiveBounds,
7
+ } from '@jarenjs/core';
8
+
9
+ import {
10
+ trueThat,
11
+ } from '@jarenjs/core/function';
12
+
13
+ function compileBigIntMaximum(schemaObj, jsonSchema) {
14
+ const [max, emax] = getInclusiveExclusiveBounds(
15
+ getBigIntType,
16
+ jsonSchema.maximum,
17
+ jsonSchema.exclusiveMaximum,
18
+ );
19
+
20
+ if (emax != null) {
21
+ const addError = schemaObj.createErrorHandler(emax, 'exclusiveMaximum');
22
+
23
+ return function validateExclusiveMaximumBigInt(data, dataPath) {
24
+ return data < emax
25
+ || addError(data, dataPath);
26
+ };
27
+ }
28
+ else if (max != null) {
29
+ const addError = schemaObj.createErrorHandler(max, 'maximum');
30
+
31
+ return function validateMaximumBigInt(data, dataPath) {
32
+ return data <= max
33
+ || addError(data, dataPath);
34
+ };
35
+ }
36
+
37
+ return undefined;
38
+ }
39
+
40
+ function compileBigIntMinimum(schemaObj, jsonSchema) {
41
+ const [min, emin] = getInclusiveExclusiveBounds(
42
+ getBigIntType,
43
+ jsonSchema.minimum,
44
+ jsonSchema.exclusiveMinimum,
45
+ );
46
+
47
+ if (emin != null) {
48
+ const addError = schemaObj.createErrorHandler(emin, 'exclusiveMinimum');
49
+
50
+ return function validateExclusiveMinimumBigInt(data, dataPath) {
51
+ return data > emin
52
+ || addError(data, dataPath);
53
+ };
54
+ }
55
+ else if (min != null) {
56
+ const addError = schemaObj.createErrorHandler(min, 'minimum');
57
+
58
+ return function validateMinimumBigInt(data, dataPath) {
59
+ return data >= min
60
+ || addError(data, dataPath);
61
+ };
62
+ }
63
+
64
+ return undefined;
65
+ }
66
+
67
+ function compileBigIntMultipleOf(schemaObj, jsonSchema) {
68
+ const mulOf = getBigIntType(jsonSchema.multipleOf);
69
+ if (mulOf == null) return undefined;
70
+
71
+ const addError = schemaObj.createErrorHandler(mulOf, 'multipleOf');
72
+
73
+ return function validateMultipleOfBigInt(data, dataPath) {
74
+ return data % mulOf === BigInt(0)
75
+ || addError(data, dataPath);
76
+ };
77
+ }
78
+
79
+ export function compileBigIntBasic(schemaObj, jsonSchema) {
80
+ const maximum = compileBigIntMaximum(schemaObj, jsonSchema);
81
+ const minimum = compileBigIntMinimum(schemaObj, jsonSchema);
82
+ const multipleOf = compileBigIntMultipleOf(schemaObj, jsonSchema);
83
+ if (maximum == null && minimum == null && multipleOf == null) return undefined;
84
+
85
+ const isMax = maximum || trueThat;
86
+ const isMin = minimum || trueThat;
87
+ const isMul = multipleOf || trueThat;
88
+
89
+ return function validateBigIntSchema(data, dataPath) {
90
+ if (isBigIntType(data)) {
91
+ return isMax(data, dataPath)
92
+ && isMin(data, dataPath)
93
+ && isMul(data, dataPath);
94
+ }
95
+ return true;
96
+ };
97
+ }