@jarenjs/validate 0.8.3 → 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 -1802
  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/number.js ADDED
@@ -0,0 +1,159 @@
1
+ //@ts-check
2
+
3
+ import {
4
+ isNumberType,
5
+ getInclusiveExclusiveBounds,
6
+ } from '@jarenjs/core';
7
+
8
+ import {
9
+ getNumbishType,
10
+ } from '@jarenjs/core/number';
11
+
12
+ import {
13
+ trueThat,
14
+ } from '@jarenjs/core/function';
15
+
16
+ function compileNumberMaximum(schemaObj, jsonSchema) {
17
+ const [max, emax] = getInclusiveExclusiveBounds(
18
+ getNumbishType,
19
+ jsonSchema.maximum,
20
+ jsonSchema.exclusiveMaximum,
21
+ );
22
+
23
+ if (emax != null) {
24
+ const addError = schemaObj.createErrorHandler(emax, 'exclusiveMaximum');
25
+
26
+ return function validateExclusiveMaximum(data, dataPath) {
27
+ return data < emax
28
+ || addError(data, dataPath);
29
+ };
30
+ }
31
+ else if (max != null) {
32
+ const addError = schemaObj.createErrorHandler(max, 'maximum');
33
+
34
+ return function validateMaximum(data, dataPath) {
35
+ return data <= max
36
+ || addError(data, dataPath);
37
+ };
38
+ }
39
+
40
+ return undefined;
41
+ }
42
+
43
+ function compileNumberMinimum(schemaObj, jsonSchema) {
44
+ const [min, emin] = getInclusiveExclusiveBounds(
45
+ getNumbishType,
46
+ jsonSchema.minimum,
47
+ jsonSchema.exclusiveMinimum,
48
+ );
49
+
50
+ if (emin != null) {
51
+ const addError = schemaObj.createErrorHandler(emin, 'exclusiveMinimum');
52
+
53
+ return function validateExclusiveMinimum(data, dataPath) {
54
+ return data > emin
55
+ || addError(data, dataPath);
56
+ };
57
+ }
58
+ else if (min != null) {
59
+ const addError = schemaObj.createErrorHandler(min, 'minimum');
60
+
61
+ return function validateMinimum(data, dataPath) {
62
+ return data >= min
63
+ || addError(data, dataPath);
64
+ };
65
+ }
66
+
67
+ return undefined;
68
+ }
69
+
70
+ function compileNumberMultipleOf(schemaObj, jsonSchema) {
71
+ const mulOf = getNumbishType(jsonSchema.multipleOf);
72
+ if (mulOf == null) return undefined;
73
+
74
+ const addError = schemaObj.createErrorHandler(mulOf, 'multipleOf');
75
+
76
+ return function validateMultipleOf(data, dataPath) {
77
+ // Handle overflow: if data is too large, division may overflow to Infinity
78
+ // In such cases, check if the data is divisible using alternative methods
79
+ const q = data / mulOf;
80
+
81
+ // If q overflowed to Infinity, use alternative validation methods
82
+ if (!Number.isFinite(q)) {
83
+ // For large integers with power-of-2 fractional multipleOf
84
+ // we can determine validity based on the exponent
85
+ if (Number.isInteger(data) && data !== 0) {
86
+ // Check if multipleOf is a negative power of 2 (0.5, 0.25, 0.125, etc.)
87
+ // These can be checked using binary representation
88
+ const mulOfInverse = 1 / mulOf;
89
+ if (Number.isInteger(mulOfInverse) && (mulOfInverse & (mulOfInverse - 1)) === 0) {
90
+ // mulOfInverse is a power of 2 (1, 2, 4, 8, ...)
91
+ // Any integer divided by 0.5, 0.25, etc. gives an integer result
92
+ // Since data is integer and mulOf is 1/(power of 2), data/mulOf is always integer
93
+ return true;
94
+ }
95
+ // For integer multipleOf, use modulo
96
+ if (Number.isInteger(mulOf)) {
97
+ return data % mulOf === 0 || addError(data, dataPath);
98
+ }
99
+ }
100
+ // For other overflow cases, the result is not an integer
101
+ // This handles cases like 1e308 / 0.123456789 which overflows
102
+ return addError(data, dataPath);
103
+ }
104
+
105
+ return Math.abs(q - Math.round(q)) < 1e-6
106
+ || addError(data, dataPath);
107
+ };
108
+ }
109
+
110
+ function compileNumberIntern(schemaObj, jsonSchema) {
111
+ const maximum = compileNumberMaximum(schemaObj, jsonSchema);
112
+ const minimum = compileNumberMinimum(schemaObj, jsonSchema);
113
+ const multipleOf = compileNumberMultipleOf(schemaObj, jsonSchema);
114
+ if (maximum == null && minimum == null && multipleOf == null)
115
+ return undefined;
116
+
117
+ // Single-constraint schemas are the common case; call the one
118
+ // validator directly instead of chaining through trueThat stubs.
119
+ const count = (maximum ? 1 : 0) + (minimum ? 1 : 0) + (multipleOf ? 1 : 0);
120
+ if (count === 1)
121
+ return maximum || minimum || multipleOf;
122
+
123
+ if (multipleOf == null) {
124
+ /**
125
+ * @param {number} data
126
+ * @param {string} dataPath
127
+ * @returns {boolean}
128
+ */
129
+ return function validateNumberMinMax(data, dataPath) {
130
+ return /** @type {Function} */ (maximum)(data, dataPath)
131
+ && /** @type {Function} */ (minimum)(data, dataPath);
132
+ };
133
+ }
134
+
135
+ const isMax = maximum || trueThat;
136
+ const isMin = minimum || trueThat;
137
+
138
+ /**
139
+ * @param {number} data
140
+ * @param {string} dataPath
141
+ * @returns {boolean}
142
+ */
143
+ return function validateNumberIntern(data, dataPath) {
144
+ return isMax(data, dataPath)
145
+ && isMin(data, dataPath)
146
+ && multipleOf(data, dataPath);
147
+ };
148
+ }
149
+
150
+ export function compileNumberBasic(schemaObj, jsonSchema) {
151
+ const intern = compileNumberIntern(schemaObj, jsonSchema);
152
+ if (intern == null) return undefined;
153
+
154
+ return function validateNumber(data, dataPath) {
155
+ return isNumberType(data)
156
+ ? intern(data, dataPath)
157
+ : true;
158
+ };
159
+ }