schema-shield 0.0.6 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +219 -65
- package/dist/formats.d.ts.map +1 -1
- package/dist/index.d.ts +25 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1837 -484
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.mjs +1837 -484
- package/dist/keywords/array-keywords.d.ts.map +1 -1
- package/dist/keywords/object-keywords.d.ts.map +1 -1
- package/dist/keywords/other-keywords.d.ts.map +1 -1
- package/dist/keywords/string-keywords.d.ts.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/deep-freeze.d.ts +5 -0
- package/dist/utils/deep-freeze.d.ts.map +1 -0
- package/dist/utils/has-changed.d.ts +2 -0
- package/dist/utils/has-changed.d.ts.map +1 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{utils.d.ts → utils/main-utils.d.ts} +7 -9
- package/dist/utils/main-utils.d.ts.map +1 -0
- package/dist/utils/pattern-matcher.d.ts +3 -0
- package/dist/utils/pattern-matcher.d.ts.map +1 -0
- package/lib/formats.ts +468 -155
- package/lib/index.ts +702 -107
- package/lib/keywords/array-keywords.ts +260 -52
- package/lib/keywords/number-keywords.ts +1 -1
- package/lib/keywords/object-keywords.ts +295 -88
- package/lib/keywords/other-keywords.ts +263 -70
- package/lib/keywords/string-keywords.ts +123 -7
- package/lib/types.ts +5 -18
- package/lib/utils/deep-freeze.ts +208 -0
- package/lib/utils/has-changed.ts +51 -0
- package/lib/utils/index.ts +4 -0
- package/lib/{utils.ts → utils/main-utils.ts} +63 -77
- package/lib/utils/pattern-matcher.ts +66 -0
- package/package.json +2 -2
- package/tsconfig.json +4 -4
- package/dist/utils.d.ts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// lib/utils.ts
|
|
1
|
+
// lib/utils/main-utils.ts
|
|
2
2
|
var ValidationError = class extends Error {
|
|
3
3
|
message;
|
|
4
4
|
item;
|
|
@@ -53,14 +53,18 @@ var ValidationError = class extends Error {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
|
-
|
|
56
|
+
var FAIL_FAST_DEFINE_ERROR = () => true;
|
|
57
|
+
function getDefinedErrorFunctionForKey(key, schema, failFast) {
|
|
58
|
+
if (failFast) {
|
|
59
|
+
return FAIL_FAST_DEFINE_ERROR;
|
|
60
|
+
}
|
|
57
61
|
const KeywordError = new ValidationError(`Invalid ${key}`);
|
|
58
62
|
KeywordError.keyword = key;
|
|
59
63
|
KeywordError.schema = schema;
|
|
60
64
|
const defineError = (message, options = {}) => {
|
|
61
65
|
KeywordError.message = message;
|
|
62
66
|
KeywordError.item = options.item;
|
|
63
|
-
KeywordError.cause = options.cause;
|
|
67
|
+
KeywordError.cause = options.cause && options.cause !== true ? options.cause : void 0;
|
|
64
68
|
KeywordError.data = options.data;
|
|
65
69
|
return KeywordError;
|
|
66
70
|
};
|
|
@@ -69,216 +73,394 @@ function getDefinedErrorFunctionForKey(key, schema) {
|
|
|
69
73
|
defineError
|
|
70
74
|
);
|
|
71
75
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
function isCompiledSchema(subSchema) {
|
|
77
|
+
return !!subSchema && typeof subSchema === "object" && !Array.isArray(subSchema) && "$validate" in subSchema;
|
|
78
|
+
}
|
|
79
|
+
function getNamedFunction(name, fn) {
|
|
80
|
+
return Object.defineProperty(fn, "name", { value: name });
|
|
81
|
+
}
|
|
82
|
+
function resolvePath(root, path) {
|
|
83
|
+
if (!path || path === "#") {
|
|
84
|
+
return root;
|
|
85
|
+
}
|
|
86
|
+
if (path.startsWith("#/")) {
|
|
87
|
+
const parts = path.split("/").slice(1);
|
|
88
|
+
let current = root;
|
|
89
|
+
for (const part of parts) {
|
|
90
|
+
const decodedUriPart = decodeURIComponent(part);
|
|
91
|
+
const key = decodedUriPart.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
92
|
+
if (current && typeof current === "object" && key in current) {
|
|
93
|
+
current = current[key];
|
|
94
|
+
} else {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
76
97
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
98
|
+
return current;
|
|
99
|
+
}
|
|
100
|
+
if (!path.includes("#")) {
|
|
101
|
+
if (root.definitions && root.definitions[path]) {
|
|
102
|
+
return root.definitions[path];
|
|
103
|
+
}
|
|
104
|
+
if (root.defs && root.defs[path]) {
|
|
105
|
+
return root.defs[path];
|
|
106
|
+
}
|
|
107
|
+
if (root.$id && typeof root.$id === "string") {
|
|
108
|
+
if (root.$id === path || root.$id.endsWith("/" + path)) {
|
|
109
|
+
return root;
|
|
80
110
|
}
|
|
81
111
|
}
|
|
82
|
-
return true;
|
|
83
112
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
function areCloseEnough(a, b, epsilon = 1e-15) {
|
|
116
|
+
return Math.abs(a - b) <= epsilon * Math.max(Math.abs(a), Math.abs(b));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// lib/formats.ts
|
|
120
|
+
var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
121
|
+
var DURATION_REGEX = /^P(?!$)((\d+Y)?(\d+M)?(\d+W)?(\d+D)?)(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$/;
|
|
122
|
+
var URI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
123
|
+
var EMAIL_REGEX = /^(?!\.)(?!.*\.$)[a-z0-9!#$%&'*+/=?^_`{|}~-]{1,20}(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]{1,21}){0,2}@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,60}[a-z0-9])?){0,3}$/i;
|
|
124
|
+
var HOSTNAME_REGEX = /^[a-z0-9][a-z0-9-]{0,62}(?:\.[a-z0-9][a-z0-9-]{0,62})*[a-z0-9]$/i;
|
|
125
|
+
var DATE_REGEX = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
126
|
+
var TIME_REGEX = /^([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(\.\d+)?(Z|([+-])([01]\d|2[0-3]):([0-5]\d))$/;
|
|
127
|
+
var URI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
128
|
+
var IRI_REGEX = /^[a-zA-Z][a-zA-Z0-9+\-.]*:[^\s]*$/;
|
|
129
|
+
var IRI_REFERENCE_REGEX = /^(([^:/?#]+):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#((?![^#]*\\)[^#]*))?/i;
|
|
130
|
+
var IDN_EMAIL_REGEX = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
131
|
+
var IDN_HOSTNAME_REGEX = /^[^\s!@#$%^&*()_+\=\[\]{};':"\\|,<>\/?]+$/;
|
|
132
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
133
|
+
function isDigitCharCode(code) {
|
|
134
|
+
return code >= 48 && code <= 57;
|
|
135
|
+
}
|
|
136
|
+
function parseTwoDigits(data, index) {
|
|
137
|
+
const first = data.charCodeAt(index) - 48;
|
|
138
|
+
const second = data.charCodeAt(index + 1) - 48;
|
|
139
|
+
if (first < 0 || first > 9 || second < 0 || second > 9) {
|
|
140
|
+
return -1;
|
|
141
|
+
}
|
|
142
|
+
return first * 10 + second;
|
|
143
|
+
}
|
|
144
|
+
function parseFourDigits(data, index) {
|
|
145
|
+
const a = data.charCodeAt(index) - 48;
|
|
146
|
+
const b = data.charCodeAt(index + 1) - 48;
|
|
147
|
+
const c = data.charCodeAt(index + 2) - 48;
|
|
148
|
+
const d = data.charCodeAt(index + 3) - 48;
|
|
149
|
+
if (a < 0 || a > 9 || b < 0 || b > 9 || c < 0 || c > 9 || d < 0 || d > 9) {
|
|
150
|
+
return -1;
|
|
151
|
+
}
|
|
152
|
+
return a * 1e3 + b * 100 + c * 10 + d;
|
|
153
|
+
}
|
|
154
|
+
function isValidIpv4Range(data, start, end) {
|
|
155
|
+
let segmentCount = 0;
|
|
156
|
+
let segmentStart = start;
|
|
157
|
+
for (let i = start; i <= end; i++) {
|
|
158
|
+
if (i !== end && data.charCodeAt(i) !== 46) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const segmentLength = i - segmentStart;
|
|
162
|
+
if (segmentLength < 1 || segmentLength > 3) {
|
|
163
|
+
return false;
|
|
87
164
|
}
|
|
88
|
-
|
|
89
|
-
if (keys.length !== Object.keys(other).length) {
|
|
165
|
+
if (segmentLength > 1 && data.charCodeAt(segmentStart) === 48) {
|
|
90
166
|
return false;
|
|
91
167
|
}
|
|
92
|
-
|
|
93
|
-
|
|
168
|
+
let value = 0;
|
|
169
|
+
for (let j = segmentStart; j < i; j++) {
|
|
170
|
+
const digit = data.charCodeAt(j) - 48;
|
|
171
|
+
if (digit < 0 || digit > 9) {
|
|
94
172
|
return false;
|
|
95
173
|
}
|
|
174
|
+
value = value * 10 + digit;
|
|
96
175
|
}
|
|
97
|
-
|
|
176
|
+
if (value > 255) {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
segmentCount++;
|
|
180
|
+
segmentStart = i + 1;
|
|
98
181
|
}
|
|
99
|
-
return
|
|
182
|
+
return segmentCount === 4;
|
|
100
183
|
}
|
|
101
|
-
function
|
|
102
|
-
return
|
|
184
|
+
function isValidIpv4(data) {
|
|
185
|
+
return isValidIpv4Range(data, 0, data.length);
|
|
103
186
|
}
|
|
104
|
-
function
|
|
105
|
-
return
|
|
187
|
+
function isHexCharCode(code) {
|
|
188
|
+
return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
|
|
106
189
|
}
|
|
107
|
-
function
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
190
|
+
function isValidIpv6(data) {
|
|
191
|
+
const length = data.length;
|
|
192
|
+
if (length === 0) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
let hasColon = false;
|
|
196
|
+
let hasDoubleColon = false;
|
|
197
|
+
let hextetCount = 0;
|
|
198
|
+
let i = 0;
|
|
199
|
+
while (i < length) {
|
|
200
|
+
if (data.charCodeAt(i) === 58) {
|
|
201
|
+
hasColon = true;
|
|
202
|
+
if (i + 1 < length && data.charCodeAt(i + 1) === 58) {
|
|
203
|
+
if (hasDoubleColon) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
hasDoubleColon = true;
|
|
207
|
+
i += 2;
|
|
208
|
+
if (i === length) {
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
const segmentStart = i;
|
|
216
|
+
let segmentLength = 0;
|
|
217
|
+
while (i < length && isHexCharCode(data.charCodeAt(i))) {
|
|
218
|
+
segmentLength++;
|
|
219
|
+
if (segmentLength > 4) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
i++;
|
|
223
|
+
}
|
|
224
|
+
if (segmentLength === 0) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
if (i < length && data.charCodeAt(i) === 46) {
|
|
228
|
+
if (!hasColon) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
if (!isValidIpv4Range(data, segmentStart, length)) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
if (hasDoubleColon) {
|
|
235
|
+
return hextetCount < 6;
|
|
236
|
+
}
|
|
237
|
+
return hextetCount === 6;
|
|
238
|
+
}
|
|
239
|
+
hextetCount++;
|
|
240
|
+
if (hextetCount > 8) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
if (i === length) {
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
if (data.charCodeAt(i) !== 58) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
hasColon = true;
|
|
250
|
+
i++;
|
|
251
|
+
if (i === length) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
if (data.charCodeAt(i) === 58) {
|
|
255
|
+
if (hasDoubleColon) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
hasDoubleColon = true;
|
|
259
|
+
i++;
|
|
260
|
+
if (i === length) {
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
112
263
|
}
|
|
113
|
-
return result;
|
|
114
264
|
}
|
|
115
|
-
if (
|
|
116
|
-
return
|
|
265
|
+
if (!hasColon) {
|
|
266
|
+
return false;
|
|
117
267
|
}
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
268
|
+
if (hasDoubleColon) {
|
|
269
|
+
return hextetCount < 8;
|
|
270
|
+
}
|
|
271
|
+
return hextetCount === 8;
|
|
272
|
+
}
|
|
273
|
+
function isValidJsonPointer(data) {
|
|
274
|
+
if (data === "") {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
if (data.charCodeAt(0) !== 47) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
for (let i = 1; i < data.length; i++) {
|
|
281
|
+
if (data.charCodeAt(i) !== 126) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const next = data.charCodeAt(i + 1);
|
|
285
|
+
if (next !== 48 && next !== 49) {
|
|
286
|
+
return false;
|
|
124
287
|
}
|
|
125
|
-
|
|
288
|
+
i++;
|
|
126
289
|
}
|
|
127
|
-
return
|
|
290
|
+
return true;
|
|
128
291
|
}
|
|
129
|
-
function
|
|
130
|
-
|
|
292
|
+
function isValidRelativeJsonPointer(data) {
|
|
293
|
+
if (data.length === 0) {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
let i = 0;
|
|
297
|
+
while (i < data.length) {
|
|
298
|
+
const code = data.charCodeAt(i);
|
|
299
|
+
if (code < 48 || code > 57) {
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
i++;
|
|
303
|
+
}
|
|
304
|
+
if (i === 0) {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
if (i === data.length) {
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
if (data.charCodeAt(i) === 35) {
|
|
311
|
+
return i + 1 === data.length;
|
|
312
|
+
}
|
|
313
|
+
if (data.charCodeAt(i) !== 47) {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
for (i = i + 1; i < data.length; i++) {
|
|
317
|
+
if (data.charCodeAt(i) !== 126) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const next = data.charCodeAt(i + 1);
|
|
321
|
+
if (next !== 48 && next !== 49) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
i++;
|
|
325
|
+
}
|
|
326
|
+
return true;
|
|
131
327
|
}
|
|
132
|
-
function
|
|
133
|
-
|
|
328
|
+
function isValidUriTemplate(data) {
|
|
329
|
+
for (let i = 0; i < data.length; i++) {
|
|
330
|
+
const code = data.charCodeAt(i);
|
|
331
|
+
if (code === 125) {
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
if (code !== 123) {
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
const closeIndex = data.indexOf("}", i + 1);
|
|
338
|
+
if (closeIndex === -1 || closeIndex === i + 1) {
|
|
339
|
+
return false;
|
|
340
|
+
}
|
|
341
|
+
i = closeIndex;
|
|
342
|
+
}
|
|
343
|
+
return true;
|
|
134
344
|
}
|
|
135
|
-
|
|
136
|
-
// lib/formats.ts
|
|
137
345
|
var Formats = {
|
|
138
346
|
["date-time"](data) {
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
347
|
+
const length = data.length;
|
|
348
|
+
if (length < 19) {
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
if (data.charCodeAt(4) !== 45 || data.charCodeAt(7) !== 45 || data.charCodeAt(13) !== 58 || data.charCodeAt(16) !== 58) {
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
const tCode = data.charCodeAt(10);
|
|
355
|
+
if (tCode !== 84 && tCode !== 116) {
|
|
143
356
|
return false;
|
|
144
357
|
}
|
|
145
|
-
|
|
146
|
-
|
|
358
|
+
const year = parseFourDigits(data, 0);
|
|
359
|
+
const month = parseTwoDigits(data, 5);
|
|
360
|
+
const day = parseTwoDigits(data, 8);
|
|
361
|
+
const hour = parseTwoDigits(data, 11);
|
|
362
|
+
const minute = parseTwoDigits(data, 14);
|
|
363
|
+
const second = parseTwoDigits(data, 17);
|
|
364
|
+
if (year < 0 || month < 0 || day < 0 || hour < 0 || minute < 0 || second < 0) {
|
|
147
365
|
return false;
|
|
148
366
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
if (hour > 23) {
|
|
184
|
-
day += 1;
|
|
185
|
-
hour -= 24;
|
|
186
|
-
} else if (hour < 0) {
|
|
187
|
-
day -= 1;
|
|
188
|
-
hour += 24;
|
|
189
|
-
}
|
|
190
|
-
if (day > 31) {
|
|
191
|
-
month += 1;
|
|
192
|
-
day -= 31;
|
|
193
|
-
} else if (day < 1) {
|
|
194
|
-
month -= 1;
|
|
195
|
-
day += 31;
|
|
196
|
-
}
|
|
197
|
-
if (month > 12) {
|
|
198
|
-
year += 1;
|
|
199
|
-
month -= 12;
|
|
200
|
-
} else if (month < 1) {
|
|
201
|
-
year -= 1;
|
|
202
|
-
month += 12;
|
|
203
|
-
}
|
|
204
|
-
if (year < 0) {
|
|
367
|
+
if (hour > 23 || minute > 59 || second > 60) {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
let cursor = 19;
|
|
371
|
+
let offsetSign = null;
|
|
372
|
+
let offsetHour = 0;
|
|
373
|
+
let offsetMinute = 0;
|
|
374
|
+
if (cursor < length && data.charCodeAt(cursor) === 46) {
|
|
375
|
+
cursor++;
|
|
376
|
+
const fracStart = cursor;
|
|
377
|
+
while (cursor < length && isDigitCharCode(data.charCodeAt(cursor))) {
|
|
378
|
+
cursor++;
|
|
379
|
+
}
|
|
380
|
+
if (cursor === fracStart) {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (cursor < length) {
|
|
385
|
+
const tzCode = data.charCodeAt(cursor);
|
|
386
|
+
if (tzCode === 90 || tzCode === 122) {
|
|
387
|
+
cursor++;
|
|
388
|
+
} else if (tzCode === 43 || tzCode === 45) {
|
|
389
|
+
offsetSign = tzCode === 43 ? "+" : "-";
|
|
390
|
+
if (cursor + 6 > length || data.charCodeAt(cursor + 3) !== 58) {
|
|
391
|
+
return false;
|
|
392
|
+
}
|
|
393
|
+
offsetHour = parseTwoDigits(data, cursor + 1);
|
|
394
|
+
offsetMinute = parseTwoDigits(data, cursor + 4);
|
|
395
|
+
if (offsetHour < 0 || offsetMinute < 0 || offsetHour > 23 || offsetMinute > 59) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
cursor += 6;
|
|
399
|
+
} else {
|
|
205
400
|
return false;
|
|
206
401
|
}
|
|
207
402
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
403
|
+
if (cursor !== length) {
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
if (month < 1 || month > 12) {
|
|
211
407
|
return false;
|
|
212
408
|
}
|
|
213
|
-
if (
|
|
409
|
+
if (day < 1) {
|
|
214
410
|
return false;
|
|
215
411
|
}
|
|
412
|
+
const maxDays = month === 2 ? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28 : DAYS_IN_MONTH[month - 1];
|
|
413
|
+
if (!maxDays || day > maxDays) {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
if (second === 60) {
|
|
417
|
+
let utcTotalMinutes = hour * 60 + minute;
|
|
418
|
+
if (offsetSign) {
|
|
419
|
+
const offsetTotalMinutes = offsetHour * 60 + offsetMinute;
|
|
420
|
+
utcTotalMinutes += offsetSign === "+" ? -offsetTotalMinutes : offsetTotalMinutes;
|
|
421
|
+
utcTotalMinutes %= 24 * 60;
|
|
422
|
+
if (utcTotalMinutes < 0) {
|
|
423
|
+
utcTotalMinutes += 24 * 60;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (utcTotalMinutes !== 23 * 60 + 59) {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
216
430
|
return true;
|
|
217
431
|
},
|
|
218
432
|
uri(data) {
|
|
219
|
-
return
|
|
433
|
+
return URI_REGEX.test(data);
|
|
220
434
|
},
|
|
221
435
|
email(data) {
|
|
222
|
-
return
|
|
223
|
-
data
|
|
224
|
-
);
|
|
436
|
+
return EMAIL_REGEX.test(data);
|
|
225
437
|
},
|
|
226
438
|
ipv4(data) {
|
|
227
|
-
return
|
|
228
|
-
data
|
|
229
|
-
);
|
|
439
|
+
return isValidIpv4(data);
|
|
230
440
|
},
|
|
231
|
-
// ipv6: isMyIpValid({ version: 6 }),
|
|
232
441
|
ipv6(data) {
|
|
233
|
-
|
|
234
|
-
return true;
|
|
235
|
-
}
|
|
236
|
-
if (data.indexOf(":") === -1 || /(?:\s+|:::+|^\w{5,}|\w{5}$|^:{1}\w|\w:{1}$)/.test(data)) {
|
|
237
|
-
return false;
|
|
238
|
-
}
|
|
239
|
-
const hasIpv4 = data.indexOf(".") !== -1;
|
|
240
|
-
let addressParts = data;
|
|
241
|
-
if (hasIpv4) {
|
|
242
|
-
addressParts = data.split(":");
|
|
243
|
-
const ipv4Part = addressParts.pop();
|
|
244
|
-
if (!/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])$/.test(
|
|
245
|
-
ipv4Part
|
|
246
|
-
)) {
|
|
247
|
-
return false;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
const isShortened = data.indexOf("::") !== -1;
|
|
251
|
-
const ipv6Part = hasIpv4 ? addressParts.join(":") : data;
|
|
252
|
-
if (isShortened) {
|
|
253
|
-
if (ipv6Part.split("::").length - 1 > 1) {
|
|
254
|
-
return false;
|
|
255
|
-
}
|
|
256
|
-
if (!/^[0-9a-fA-F:.]*$/.test(ipv6Part)) {
|
|
257
|
-
return false;
|
|
258
|
-
}
|
|
259
|
-
return /^(?:(?:(?:[0-9a-fA-F]{1,4}(?::|$)){1,6}))|(?:::(?:[0-9a-fA-F]{1,4})){0,5}$/.test(
|
|
260
|
-
ipv6Part
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
const isIpv6Valid = /^(?:(?:[0-9a-fA-F]{1,4}:){7}(?:[0-9a-fA-F]{1,4}|:))$/.test(ipv6Part);
|
|
264
|
-
const hasInvalidChar = /(?:[0-9a-fA-F]{5,}|\D[0-9a-fA-F]{3}:)/.test(
|
|
265
|
-
ipv6Part
|
|
266
|
-
);
|
|
267
|
-
if (hasIpv4) {
|
|
268
|
-
return isIpv6Valid || !hasInvalidChar;
|
|
269
|
-
}
|
|
270
|
-
return isIpv6Valid && !hasInvalidChar;
|
|
442
|
+
return isValidIpv6(data);
|
|
271
443
|
},
|
|
272
444
|
hostname(data) {
|
|
273
|
-
return
|
|
274
|
-
data
|
|
275
|
-
);
|
|
445
|
+
return HOSTNAME_REGEX.test(data);
|
|
276
446
|
},
|
|
277
447
|
date(data) {
|
|
278
|
-
|
|
448
|
+
const match = DATE_REGEX.exec(data);
|
|
449
|
+
if (!match) {
|
|
279
450
|
return false;
|
|
280
451
|
}
|
|
281
|
-
|
|
452
|
+
const [, yearStr, monthStr, dayStr] = match;
|
|
453
|
+
const year = Number(yearStr);
|
|
454
|
+
const month = Number(monthStr);
|
|
455
|
+
const day = Number(dayStr);
|
|
456
|
+
if (month < 1 || month > 12) {
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
if (day < 1) {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
const maxDays = month === 2 ? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28 : DAYS_IN_MONTH[month - 1];
|
|
463
|
+
return !!maxDays && day <= maxDays;
|
|
282
464
|
},
|
|
283
465
|
regex(data) {
|
|
284
466
|
try {
|
|
@@ -289,54 +471,55 @@ var Formats = {
|
|
|
289
471
|
}
|
|
290
472
|
},
|
|
291
473
|
"json-pointer"(data) {
|
|
292
|
-
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
return /^\/(?:[^~]|~0|~1)*$/.test(data);
|
|
474
|
+
return isValidJsonPointer(data);
|
|
296
475
|
},
|
|
297
476
|
"relative-json-pointer"(data) {
|
|
298
|
-
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
return /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/.test(data);
|
|
477
|
+
return isValidRelativeJsonPointer(data);
|
|
302
478
|
},
|
|
303
479
|
time(data) {
|
|
304
|
-
return
|
|
305
|
-
data
|
|
306
|
-
);
|
|
480
|
+
return TIME_REGEX.test(data);
|
|
307
481
|
},
|
|
308
482
|
"uri-reference"(data) {
|
|
309
|
-
if (
|
|
483
|
+
if (data.includes("\\")) {
|
|
310
484
|
return false;
|
|
311
485
|
}
|
|
312
|
-
return
|
|
313
|
-
data
|
|
314
|
-
);
|
|
486
|
+
return URI_REFERENCE_REGEX.test(data);
|
|
315
487
|
},
|
|
316
488
|
"uri-template"(data) {
|
|
317
|
-
return
|
|
318
|
-
|
|
319
|
-
|
|
489
|
+
return isValidUriTemplate(data);
|
|
490
|
+
},
|
|
491
|
+
duration(data) {
|
|
492
|
+
return DURATION_REGEX.test(data);
|
|
493
|
+
},
|
|
494
|
+
uuid(data) {
|
|
495
|
+
return UUID_REGEX.test(data);
|
|
320
496
|
},
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
"
|
|
326
|
-
|
|
327
|
-
|
|
497
|
+
// IRI is like URI but allows Unicode. We reuse a permissive logic.
|
|
498
|
+
iri(data) {
|
|
499
|
+
return IRI_REGEX.test(data);
|
|
500
|
+
},
|
|
501
|
+
"iri-reference"(data) {
|
|
502
|
+
if (data.includes("\\")) {
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
return IRI_REFERENCE_REGEX.test(data);
|
|
506
|
+
},
|
|
507
|
+
// Best-effort structural validation for IDN (no punycode/tables)
|
|
508
|
+
"idn-email"(data) {
|
|
509
|
+
return IDN_EMAIL_REGEX.test(data);
|
|
510
|
+
},
|
|
511
|
+
"idn-hostname"(data) {
|
|
512
|
+
return IDN_HOSTNAME_REGEX.test(data);
|
|
513
|
+
}
|
|
328
514
|
};
|
|
329
515
|
|
|
330
516
|
// lib/types.ts
|
|
331
517
|
var Types = {
|
|
332
518
|
object(data) {
|
|
333
|
-
return
|
|
519
|
+
return data !== null && typeof data === "object" && !Array.isArray(data);
|
|
334
520
|
},
|
|
335
521
|
array(data) {
|
|
336
|
-
|
|
337
|
-
return true;
|
|
338
|
-
}
|
|
339
|
-
return typeof data === "object" && data !== null && "length" in data && "0" in data && Object.keys(data).length - 1 === data.length;
|
|
522
|
+
return Array.isArray(data);
|
|
340
523
|
},
|
|
341
524
|
string(data) {
|
|
342
525
|
return typeof data === "string";
|
|
@@ -356,17 +539,126 @@ var Types = {
|
|
|
356
539
|
// Not implemented yet
|
|
357
540
|
timestamp: false,
|
|
358
541
|
int8: false,
|
|
359
|
-
|
|
542
|
+
uint8: false,
|
|
360
543
|
int16: false,
|
|
361
|
-
|
|
544
|
+
uint16: false,
|
|
362
545
|
int32: false,
|
|
363
|
-
|
|
546
|
+
uint32: false,
|
|
364
547
|
float32: false,
|
|
365
548
|
float64: false
|
|
366
549
|
};
|
|
367
550
|
|
|
551
|
+
// lib/utils/has-changed.ts
|
|
552
|
+
function hasChanged(prev, current) {
|
|
553
|
+
if (Object.is(prev, current)) {
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
if (Array.isArray(prev)) {
|
|
557
|
+
if (Array.isArray(current) === false) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
if (prev.length !== current.length) {
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
for (let i = 0; i < current.length; i++) {
|
|
564
|
+
if (hasChanged(prev[i], current[i])) {
|
|
565
|
+
return true;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
if (typeof prev === "object" && prev !== null) {
|
|
571
|
+
if (typeof current !== "object" || current === null) {
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
for (const key in current) {
|
|
575
|
+
if (hasChanged(prev[key], current[key])) {
|
|
576
|
+
return true;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
for (const key in prev) {
|
|
580
|
+
if (key in current) {
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
if (hasChanged(prev[key], void 0)) {
|
|
584
|
+
return true;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
return true;
|
|
590
|
+
}
|
|
591
|
+
|
|
368
592
|
// lib/keywords/array-keywords.ts
|
|
593
|
+
function isUniquePrimitive(value) {
|
|
594
|
+
return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
595
|
+
}
|
|
596
|
+
function getArrayBucketKey(value) {
|
|
597
|
+
const length = value.length;
|
|
598
|
+
if (length === 0) {
|
|
599
|
+
return "0";
|
|
600
|
+
}
|
|
601
|
+
const first = value[0];
|
|
602
|
+
const last = value[length - 1];
|
|
603
|
+
const firstType = first === null ? "null" : typeof first;
|
|
604
|
+
const lastType = last === null ? "null" : typeof last;
|
|
605
|
+
let firstArrayMarker = "";
|
|
606
|
+
if (Array.isArray(first)) {
|
|
607
|
+
const firstSignature = getPrimitiveArraySignature(first);
|
|
608
|
+
firstArrayMarker = firstSignature === null ? `a:${first.length}` : firstSignature;
|
|
609
|
+
}
|
|
610
|
+
let lastArrayMarker = "";
|
|
611
|
+
if (Array.isArray(last)) {
|
|
612
|
+
const lastSignature = getPrimitiveArraySignature(last);
|
|
613
|
+
lastArrayMarker = lastSignature === null ? `a:${last.length}` : lastSignature;
|
|
614
|
+
}
|
|
615
|
+
return `${length}:${firstType}:${firstArrayMarker}:${lastType}:${lastArrayMarker}`;
|
|
616
|
+
}
|
|
617
|
+
function getObjectShapeKey(value) {
|
|
618
|
+
const keys = Object.keys(value).sort();
|
|
619
|
+
return `${keys.length}:${keys.join("")}`;
|
|
620
|
+
}
|
|
621
|
+
function getPrimitiveArraySignature(value) {
|
|
622
|
+
const length = value.length;
|
|
623
|
+
if (length === 0) {
|
|
624
|
+
return "a:0";
|
|
625
|
+
}
|
|
626
|
+
if (!isUniquePrimitive(value[0]) || !isUniquePrimitive(value[length - 1])) {
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
let signature = `a:${length}:`;
|
|
630
|
+
for (let i = 0; i < length; i++) {
|
|
631
|
+
const item = value[i];
|
|
632
|
+
if (item === null) {
|
|
633
|
+
signature += "l;";
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
if (typeof item === "string") {
|
|
637
|
+
signature += `s${item.length}:${item};`;
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
if (typeof item === "number") {
|
|
641
|
+
if (Number.isNaN(item)) {
|
|
642
|
+
signature += "n:NaN;";
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
if (Object.is(item, -0)) {
|
|
646
|
+
signature += "n:-0;";
|
|
647
|
+
continue;
|
|
648
|
+
}
|
|
649
|
+
signature += `n:${item};`;
|
|
650
|
+
continue;
|
|
651
|
+
}
|
|
652
|
+
if (typeof item === "boolean") {
|
|
653
|
+
signature += item ? "b:1;" : "b:0;";
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
return null;
|
|
657
|
+
}
|
|
658
|
+
return signature;
|
|
659
|
+
}
|
|
369
660
|
var ArrayKeywords = {
|
|
661
|
+
// lib/keywords/array-keywords.ts
|
|
370
662
|
items(schema, data, defineError) {
|
|
371
663
|
if (!Array.isArray(data)) {
|
|
372
664
|
return;
|
|
@@ -381,11 +673,11 @@ var ArrayKeywords = {
|
|
|
381
673
|
}
|
|
382
674
|
if (Array.isArray(schemaItems)) {
|
|
383
675
|
const schemaItemsLength = schemaItems.length;
|
|
384
|
-
const itemsLength =
|
|
676
|
+
const itemsLength = schemaItemsLength < dataLength ? schemaItemsLength : dataLength;
|
|
385
677
|
for (let i = 0; i < itemsLength; i++) {
|
|
386
678
|
const schemaItem = schemaItems[i];
|
|
387
679
|
if (typeof schemaItem === "boolean") {
|
|
388
|
-
if (schemaItem === false &&
|
|
680
|
+
if (schemaItem === false && data[i] !== void 0) {
|
|
389
681
|
return defineError("Array item is not allowed", {
|
|
390
682
|
item: i,
|
|
391
683
|
data: data[i]
|
|
@@ -393,8 +685,9 @@ var ArrayKeywords = {
|
|
|
393
685
|
}
|
|
394
686
|
continue;
|
|
395
687
|
}
|
|
396
|
-
|
|
397
|
-
|
|
688
|
+
const validate2 = schemaItem && schemaItem.$validate;
|
|
689
|
+
if (typeof validate2 === "function") {
|
|
690
|
+
const error = validate2(data[i]);
|
|
398
691
|
if (error) {
|
|
399
692
|
return defineError("Array item is invalid", {
|
|
400
693
|
item: i,
|
|
@@ -406,26 +699,32 @@ var ArrayKeywords = {
|
|
|
406
699
|
}
|
|
407
700
|
return;
|
|
408
701
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
702
|
+
const validate = schemaItems && schemaItems.$validate;
|
|
703
|
+
if (typeof validate !== "function") {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
for (let i = 0; i < dataLength; i++) {
|
|
707
|
+
const error = validate(data[i]);
|
|
708
|
+
if (error) {
|
|
709
|
+
return defineError("Array item is invalid", {
|
|
710
|
+
item: i,
|
|
711
|
+
cause: error,
|
|
712
|
+
data: data[i]
|
|
713
|
+
});
|
|
419
714
|
}
|
|
420
715
|
}
|
|
421
|
-
return;
|
|
422
716
|
},
|
|
423
717
|
elements(schema, data, defineError) {
|
|
424
|
-
if (!Array.isArray(data)
|
|
718
|
+
if (!Array.isArray(data)) {
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
const elementsSchema = schema.elements;
|
|
722
|
+
const validate = elementsSchema && elementsSchema.$validate;
|
|
723
|
+
if (typeof validate !== "function") {
|
|
425
724
|
return;
|
|
426
725
|
}
|
|
427
726
|
for (let i = 0; i < data.length; i++) {
|
|
428
|
-
const error =
|
|
727
|
+
const error = validate(data[i]);
|
|
429
728
|
if (error) {
|
|
430
729
|
return defineError("Array item is invalid", {
|
|
431
730
|
item: i,
|
|
@@ -434,7 +733,6 @@ var ArrayKeywords = {
|
|
|
434
733
|
});
|
|
435
734
|
}
|
|
436
735
|
}
|
|
437
|
-
return;
|
|
438
736
|
},
|
|
439
737
|
minItems(schema, data, defineError) {
|
|
440
738
|
if (!Array.isArray(data) || data.length >= schema.minItems) {
|
|
@@ -449,18 +747,28 @@ var ArrayKeywords = {
|
|
|
449
747
|
return defineError("Array is too long", { data });
|
|
450
748
|
},
|
|
451
749
|
additionalItems(schema, data, defineError) {
|
|
452
|
-
if (!
|
|
750
|
+
if (!Array.isArray(data) || !Array.isArray(schema.items)) {
|
|
453
751
|
return;
|
|
454
752
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
753
|
+
let tupleLength = schema._tupleItemsLength;
|
|
754
|
+
if (tupleLength === void 0) {
|
|
755
|
+
tupleLength = schema.items.length;
|
|
756
|
+
Object.defineProperty(schema, "_tupleItemsLength", {
|
|
757
|
+
value: tupleLength,
|
|
758
|
+
enumerable: false,
|
|
759
|
+
configurable: false,
|
|
760
|
+
writable: false
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (data.length <= tupleLength) {
|
|
459
764
|
return;
|
|
460
765
|
}
|
|
461
|
-
if (
|
|
766
|
+
if (schema.additionalItems === false) {
|
|
767
|
+
return defineError("Array is too long", { data });
|
|
768
|
+
}
|
|
769
|
+
if (schema.additionalItems && typeof schema.additionalItems === "object" && !Array.isArray(schema.additionalItems)) {
|
|
462
770
|
if (isCompiledSchema(schema.additionalItems)) {
|
|
463
|
-
for (let i =
|
|
771
|
+
for (let i = tupleLength; i < data.length; i++) {
|
|
464
772
|
const error = schema.additionalItems.$validate(data[i]);
|
|
465
773
|
if (error) {
|
|
466
774
|
return defineError("Array item is invalid", {
|
|
@@ -480,28 +788,89 @@ var ArrayKeywords = {
|
|
|
480
788
|
if (!Array.isArray(data) || !schema.uniqueItems) {
|
|
481
789
|
return;
|
|
482
790
|
}
|
|
483
|
-
const
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
)
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
791
|
+
const len = data.length;
|
|
792
|
+
if (len <= 1) {
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if (len <= 8) {
|
|
796
|
+
for (let i = 0; i < len; i++) {
|
|
797
|
+
const left = data[i];
|
|
798
|
+
for (let j = i + 1; j < len; j++) {
|
|
799
|
+
const right = data[j];
|
|
800
|
+
if (left === right) {
|
|
801
|
+
return defineError("Array items are not unique", { data: right });
|
|
802
|
+
}
|
|
803
|
+
if (typeof left === "number" && typeof right === "number" && Number.isNaN(left) && Number.isNaN(right)) {
|
|
804
|
+
return defineError("Array items are not unique", { data: right });
|
|
805
|
+
}
|
|
806
|
+
if (left && right && typeof left === "object" && typeof right === "object" && !hasChanged(left, right)) {
|
|
807
|
+
return defineError("Array items are not unique", { data: right });
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
const primitiveSeen = /* @__PURE__ */ new Set();
|
|
814
|
+
let primitiveArraySignatures;
|
|
815
|
+
let arrayBuckets;
|
|
816
|
+
let objectBuckets;
|
|
817
|
+
for (let i = 0; i < len; i++) {
|
|
818
|
+
const item = data[i];
|
|
819
|
+
if (isUniquePrimitive(item)) {
|
|
820
|
+
if (primitiveSeen.has(item)) {
|
|
821
|
+
return defineError("Array items are not unique", { data: item });
|
|
822
|
+
}
|
|
823
|
+
primitiveSeen.add(item);
|
|
824
|
+
continue;
|
|
498
825
|
}
|
|
499
|
-
if (
|
|
500
|
-
|
|
826
|
+
if (!item || typeof item !== "object") {
|
|
827
|
+
continue;
|
|
501
828
|
}
|
|
502
|
-
|
|
829
|
+
if (Array.isArray(item)) {
|
|
830
|
+
const signature = getPrimitiveArraySignature(item);
|
|
831
|
+
if (signature !== null) {
|
|
832
|
+
if (!primitiveArraySignatures) {
|
|
833
|
+
primitiveArraySignatures = /* @__PURE__ */ new Set();
|
|
834
|
+
}
|
|
835
|
+
if (primitiveArraySignatures.has(signature)) {
|
|
836
|
+
return defineError("Array items are not unique", { data: item });
|
|
837
|
+
}
|
|
838
|
+
primitiveArraySignatures.add(signature);
|
|
839
|
+
continue;
|
|
840
|
+
}
|
|
841
|
+
if (!arrayBuckets) {
|
|
842
|
+
arrayBuckets = /* @__PURE__ */ new Map();
|
|
843
|
+
}
|
|
844
|
+
const bucketKey2 = getArrayBucketKey(item);
|
|
845
|
+
let candidates2 = arrayBuckets.get(bucketKey2);
|
|
846
|
+
if (!candidates2) {
|
|
847
|
+
candidates2 = [];
|
|
848
|
+
arrayBuckets.set(bucketKey2, candidates2);
|
|
849
|
+
}
|
|
850
|
+
for (let j = 0; j < candidates2.length; j++) {
|
|
851
|
+
if (!hasChanged(candidates2[j], item)) {
|
|
852
|
+
return defineError("Array items are not unique", { data: item });
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
candidates2.push(item);
|
|
856
|
+
continue;
|
|
857
|
+
}
|
|
858
|
+
if (!objectBuckets) {
|
|
859
|
+
objectBuckets = /* @__PURE__ */ new Map();
|
|
860
|
+
}
|
|
861
|
+
const bucketKey = getObjectShapeKey(item);
|
|
862
|
+
let candidates = objectBuckets.get(bucketKey);
|
|
863
|
+
if (!candidates) {
|
|
864
|
+
candidates = [];
|
|
865
|
+
objectBuckets.set(bucketKey, candidates);
|
|
866
|
+
}
|
|
867
|
+
for (let j = 0; j < candidates.length; j++) {
|
|
868
|
+
if (!hasChanged(candidates[j], item)) {
|
|
869
|
+
return defineError("Array items are not unique", { data: item });
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
candidates.push(item);
|
|
503
873
|
}
|
|
504
|
-
return;
|
|
505
874
|
},
|
|
506
875
|
contains(schema, data, defineError) {
|
|
507
876
|
if (!Array.isArray(data)) {
|
|
@@ -516,8 +885,9 @@ var ArrayKeywords = {
|
|
|
516
885
|
}
|
|
517
886
|
return defineError("Array must not contain any items", { data });
|
|
518
887
|
}
|
|
888
|
+
const containsValidate = schema.contains.$validate;
|
|
519
889
|
for (let i = 0; i < data.length; i++) {
|
|
520
|
-
const error =
|
|
890
|
+
const error = containsValidate(data[i]);
|
|
521
891
|
if (!error) {
|
|
522
892
|
return;
|
|
523
893
|
}
|
|
@@ -527,6 +897,140 @@ var ArrayKeywords = {
|
|
|
527
897
|
}
|
|
528
898
|
};
|
|
529
899
|
|
|
900
|
+
// lib/utils/deep-freeze.ts
|
|
901
|
+
function isPlainObject(value) {
|
|
902
|
+
if (!value || typeof value !== "object") {
|
|
903
|
+
return false;
|
|
904
|
+
}
|
|
905
|
+
const proto = Object.getPrototypeOf(value);
|
|
906
|
+
return proto === Object.prototype || proto === null;
|
|
907
|
+
}
|
|
908
|
+
function canUseStructuredClone(value) {
|
|
909
|
+
if (typeof structuredClone !== "function") {
|
|
910
|
+
return false;
|
|
911
|
+
}
|
|
912
|
+
if (typeof Buffer !== "undefined" && value instanceof Buffer) {
|
|
913
|
+
return false;
|
|
914
|
+
}
|
|
915
|
+
return Array.isArray(value) || isPlainObject(value) || value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
916
|
+
}
|
|
917
|
+
function deepCloneUnfreeze(obj, cloneClassInstances = false, seen = /* @__PURE__ */ new WeakMap()) {
|
|
918
|
+
if (typeof obj === "undefined" || obj === null || typeof obj !== "object") {
|
|
919
|
+
return obj;
|
|
920
|
+
}
|
|
921
|
+
const source = obj;
|
|
922
|
+
if (seen.has(source)) {
|
|
923
|
+
return seen.get(source);
|
|
924
|
+
}
|
|
925
|
+
if (canUseStructuredClone(source)) {
|
|
926
|
+
const cloned = structuredClone(source);
|
|
927
|
+
seen.set(source, cloned);
|
|
928
|
+
return cloned;
|
|
929
|
+
}
|
|
930
|
+
let clone;
|
|
931
|
+
switch (true) {
|
|
932
|
+
case Array.isArray(source): {
|
|
933
|
+
clone = [];
|
|
934
|
+
seen.set(source, clone);
|
|
935
|
+
for (let i = 0, l = source.length; i < l; i++) {
|
|
936
|
+
clone[i] = deepCloneUnfreeze(source[i], cloneClassInstances, seen);
|
|
937
|
+
}
|
|
938
|
+
return clone;
|
|
939
|
+
}
|
|
940
|
+
case source instanceof Date: {
|
|
941
|
+
clone = new Date(source.getTime());
|
|
942
|
+
seen.set(source, clone);
|
|
943
|
+
return clone;
|
|
944
|
+
}
|
|
945
|
+
case source instanceof RegExp: {
|
|
946
|
+
clone = new RegExp(source.source, source.flags);
|
|
947
|
+
seen.set(source, clone);
|
|
948
|
+
return clone;
|
|
949
|
+
}
|
|
950
|
+
case source instanceof Map: {
|
|
951
|
+
clone = /* @__PURE__ */ new Map();
|
|
952
|
+
seen.set(source, clone);
|
|
953
|
+
for (const [key, value] of source.entries()) {
|
|
954
|
+
clone.set(
|
|
955
|
+
deepCloneUnfreeze(key, cloneClassInstances, seen),
|
|
956
|
+
deepCloneUnfreeze(value, cloneClassInstances, seen)
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
return clone;
|
|
960
|
+
}
|
|
961
|
+
case source instanceof Set: {
|
|
962
|
+
clone = /* @__PURE__ */ new Set();
|
|
963
|
+
seen.set(source, clone);
|
|
964
|
+
for (const value of source.values()) {
|
|
965
|
+
clone.add(deepCloneUnfreeze(value, cloneClassInstances, seen));
|
|
966
|
+
}
|
|
967
|
+
return clone;
|
|
968
|
+
}
|
|
969
|
+
case source instanceof ArrayBuffer: {
|
|
970
|
+
clone = source.slice(0);
|
|
971
|
+
seen.set(source, clone);
|
|
972
|
+
return clone;
|
|
973
|
+
}
|
|
974
|
+
case ArrayBuffer.isView(source): {
|
|
975
|
+
clone = new source.constructor(source.buffer.slice(0));
|
|
976
|
+
seen.set(source, clone);
|
|
977
|
+
return clone;
|
|
978
|
+
}
|
|
979
|
+
case (typeof Buffer !== "undefined" && source instanceof Buffer): {
|
|
980
|
+
clone = Buffer.from(source);
|
|
981
|
+
seen.set(source, clone);
|
|
982
|
+
return clone;
|
|
983
|
+
}
|
|
984
|
+
case source instanceof Error: {
|
|
985
|
+
clone = new source.constructor(source.message);
|
|
986
|
+
seen.set(source, clone);
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
case (source instanceof Promise || source instanceof WeakMap || source instanceof WeakSet): {
|
|
990
|
+
clone = source;
|
|
991
|
+
seen.set(source, clone);
|
|
992
|
+
return clone;
|
|
993
|
+
}
|
|
994
|
+
case (source.constructor && source.constructor !== Object): {
|
|
995
|
+
if (!cloneClassInstances) {
|
|
996
|
+
clone = source;
|
|
997
|
+
seen.set(source, clone);
|
|
998
|
+
return clone;
|
|
999
|
+
}
|
|
1000
|
+
clone = Object.create(Object.getPrototypeOf(source));
|
|
1001
|
+
seen.set(source, clone);
|
|
1002
|
+
break;
|
|
1003
|
+
}
|
|
1004
|
+
default: {
|
|
1005
|
+
clone = {};
|
|
1006
|
+
seen.set(source, clone);
|
|
1007
|
+
const keys = Reflect.ownKeys(source);
|
|
1008
|
+
for (let i = 0, l = keys.length; i < l; i++) {
|
|
1009
|
+
const key = keys[i];
|
|
1010
|
+
clone[key] = deepCloneUnfreeze(
|
|
1011
|
+
source[key],
|
|
1012
|
+
cloneClassInstances,
|
|
1013
|
+
seen
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
return clone;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
1020
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
1021
|
+
const descriptor = descriptors[key];
|
|
1022
|
+
if ("value" in descriptor) {
|
|
1023
|
+
descriptor.value = deepCloneUnfreeze(
|
|
1024
|
+
descriptor.value,
|
|
1025
|
+
cloneClassInstances,
|
|
1026
|
+
seen
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
Object.defineProperty(clone, key, descriptor);
|
|
1030
|
+
}
|
|
1031
|
+
return clone;
|
|
1032
|
+
}
|
|
1033
|
+
|
|
530
1034
|
// lib/keywords/number-keywords.ts
|
|
531
1035
|
var NumberKeywords = {
|
|
532
1036
|
minimum(schema, data, defineError, instance) {
|
|
@@ -595,16 +1099,129 @@ var NumberKeywords = {
|
|
|
595
1099
|
}
|
|
596
1100
|
};
|
|
597
1101
|
|
|
1102
|
+
// lib/utils/pattern-matcher.ts
|
|
1103
|
+
var REGEX_META_CHARS = /[\\.^$*+?()[\]{}|]/;
|
|
1104
|
+
function hasRegexMeta(value) {
|
|
1105
|
+
return REGEX_META_CHARS.test(value);
|
|
1106
|
+
}
|
|
1107
|
+
var PATTERN_CACHE = /* @__PURE__ */ new Map();
|
|
1108
|
+
function compilePatternMatcher(pattern) {
|
|
1109
|
+
const cached = PATTERN_CACHE.get(pattern);
|
|
1110
|
+
if (cached) {
|
|
1111
|
+
return cached;
|
|
1112
|
+
}
|
|
1113
|
+
let compiled;
|
|
1114
|
+
if (pattern.length === 0) {
|
|
1115
|
+
compiled = (_value) => true;
|
|
1116
|
+
} else if (!hasRegexMeta(pattern)) {
|
|
1117
|
+
compiled = (value) => value.includes(pattern);
|
|
1118
|
+
} else {
|
|
1119
|
+
const patternLength = pattern.length;
|
|
1120
|
+
if (patternLength >= 2 && pattern[0] === "^" && pattern[patternLength - 1] === "$") {
|
|
1121
|
+
const inner = pattern.slice(1, -1);
|
|
1122
|
+
if (!hasRegexMeta(inner)) {
|
|
1123
|
+
if (inner.length === 0) {
|
|
1124
|
+
compiled = (value) => value.length === 0;
|
|
1125
|
+
} else {
|
|
1126
|
+
compiled = (value) => value === inner;
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
compiled = new RegExp(pattern, "u");
|
|
1130
|
+
}
|
|
1131
|
+
} else if (pattern[0] === "^") {
|
|
1132
|
+
const inner = pattern.slice(1);
|
|
1133
|
+
if (!hasRegexMeta(inner)) {
|
|
1134
|
+
if (inner.length === 0) {
|
|
1135
|
+
compiled = (_value) => true;
|
|
1136
|
+
} else {
|
|
1137
|
+
compiled = (value) => value.startsWith(inner);
|
|
1138
|
+
}
|
|
1139
|
+
} else {
|
|
1140
|
+
compiled = new RegExp(pattern, "u");
|
|
1141
|
+
}
|
|
1142
|
+
} else if (pattern[patternLength - 1] === "$") {
|
|
1143
|
+
const inner = pattern.slice(0, -1);
|
|
1144
|
+
if (!hasRegexMeta(inner)) {
|
|
1145
|
+
if (inner.length === 0) {
|
|
1146
|
+
compiled = (_value) => true;
|
|
1147
|
+
} else {
|
|
1148
|
+
compiled = (value) => value.endsWith(inner);
|
|
1149
|
+
}
|
|
1150
|
+
} else {
|
|
1151
|
+
compiled = new RegExp(pattern, "u");
|
|
1152
|
+
}
|
|
1153
|
+
} else {
|
|
1154
|
+
compiled = new RegExp(pattern, "u");
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
PATTERN_CACHE.set(pattern, compiled);
|
|
1158
|
+
return compiled;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
598
1161
|
// lib/keywords/object-keywords.ts
|
|
1162
|
+
var PATTERN_KEY_CACHE_LIMIT = 512;
|
|
1163
|
+
function getPatternPropertyEntries(schema) {
|
|
1164
|
+
let entries = schema._patternPropertyEntries;
|
|
1165
|
+
if (entries) {
|
|
1166
|
+
return entries;
|
|
1167
|
+
}
|
|
1168
|
+
if (!schema.patternProperties || typeof schema.patternProperties !== "object" || Array.isArray(schema.patternProperties)) {
|
|
1169
|
+
return void 0;
|
|
1170
|
+
}
|
|
1171
|
+
const patternKeys = Object.keys(schema.patternProperties);
|
|
1172
|
+
entries = new Array(patternKeys.length);
|
|
1173
|
+
for (let i = 0; i < patternKeys.length; i++) {
|
|
1174
|
+
const key = patternKeys[i];
|
|
1175
|
+
const compiledMatcher = compilePatternMatcher(key);
|
|
1176
|
+
const match = compiledMatcher instanceof RegExp ? (value) => compiledMatcher.test(value) : compiledMatcher;
|
|
1177
|
+
entries[i] = {
|
|
1178
|
+
schemaProp: schema.patternProperties[key],
|
|
1179
|
+
match
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
Object.defineProperty(schema, "_patternPropertyEntries", {
|
|
1183
|
+
value: entries,
|
|
1184
|
+
enumerable: false,
|
|
1185
|
+
configurable: false,
|
|
1186
|
+
writable: false
|
|
1187
|
+
});
|
|
1188
|
+
return entries;
|
|
1189
|
+
}
|
|
1190
|
+
function getPatternKeyMatchIndexes(schema, key, entries) {
|
|
1191
|
+
let cache = schema._patternKeyMatchIndexCache;
|
|
1192
|
+
if (cache) {
|
|
1193
|
+
const cached = cache.get(key);
|
|
1194
|
+
if (cached) {
|
|
1195
|
+
return cached;
|
|
1196
|
+
}
|
|
1197
|
+
} else {
|
|
1198
|
+
cache = /* @__PURE__ */ new Map();
|
|
1199
|
+
Object.defineProperty(schema, "_patternKeyMatchIndexCache", {
|
|
1200
|
+
value: cache,
|
|
1201
|
+
enumerable: false,
|
|
1202
|
+
configurable: false,
|
|
1203
|
+
writable: false
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
const indexes = [];
|
|
1207
|
+
for (let i = 0; i < entries.length; i++) {
|
|
1208
|
+
if (entries[i].match(key)) {
|
|
1209
|
+
indexes.push(i);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
if (cache.size < PATTERN_KEY_CACHE_LIMIT) {
|
|
1213
|
+
cache.set(key, indexes);
|
|
1214
|
+
}
|
|
1215
|
+
return indexes;
|
|
1216
|
+
}
|
|
599
1217
|
var ObjectKeywords = {
|
|
600
|
-
// Object
|
|
601
1218
|
required(schema, data, defineError) {
|
|
602
|
-
if (!
|
|
1219
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
603
1220
|
return;
|
|
604
1221
|
}
|
|
605
1222
|
for (let i = 0; i < schema.required.length; i++) {
|
|
606
1223
|
const key = schema.required[i];
|
|
607
|
-
if (!
|
|
1224
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
608
1225
|
return defineError("Required property is missing", {
|
|
609
1226
|
item: key,
|
|
610
1227
|
data: data[key]
|
|
@@ -614,19 +1231,48 @@ var ObjectKeywords = {
|
|
|
614
1231
|
return;
|
|
615
1232
|
},
|
|
616
1233
|
properties(schema, data, defineError) {
|
|
617
|
-
if (!
|
|
1234
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
618
1235
|
return;
|
|
619
1236
|
}
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
1237
|
+
let propKeys = schema._propKeys;
|
|
1238
|
+
if (!propKeys) {
|
|
1239
|
+
propKeys = Object.keys(schema.properties || {});
|
|
1240
|
+
Object.defineProperty(schema, "_propKeys", {
|
|
1241
|
+
value: propKeys,
|
|
1242
|
+
enumerable: false,
|
|
1243
|
+
configurable: false,
|
|
1244
|
+
writable: false
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
let requiredSet = schema._requiredSet;
|
|
1248
|
+
if (requiredSet === void 0) {
|
|
1249
|
+
requiredSet = Array.isArray(schema.required) ? new Set(schema.required) : null;
|
|
1250
|
+
Object.defineProperty(schema, "_requiredSet", {
|
|
1251
|
+
value: requiredSet,
|
|
1252
|
+
enumerable: false,
|
|
1253
|
+
configurable: false,
|
|
1254
|
+
writable: false
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
for (let i = 0; i < propKeys.length; i++) {
|
|
1258
|
+
const key = propKeys[i];
|
|
1259
|
+
const schemaProp = schema.properties[key];
|
|
1260
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1261
|
+
if (requiredSet && requiredSet.has(key) && schemaProp && typeof schemaProp === "object" && !Array.isArray(schemaProp) && "default" in schemaProp) {
|
|
1262
|
+
const error = schemaProp.$validate(schemaProp.default);
|
|
1263
|
+
if (error) {
|
|
1264
|
+
return defineError("Default property is invalid", {
|
|
1265
|
+
item: key,
|
|
1266
|
+
cause: error,
|
|
1267
|
+
data: schemaProp.default
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
data[key] = deepCloneUnfreeze(schemaProp.default);
|
|
625
1271
|
}
|
|
626
1272
|
continue;
|
|
627
1273
|
}
|
|
628
|
-
if (typeof
|
|
629
|
-
if (
|
|
1274
|
+
if (typeof schemaProp === "boolean") {
|
|
1275
|
+
if (schemaProp === false) {
|
|
630
1276
|
return defineError("Property is not allowed", {
|
|
631
1277
|
item: key,
|
|
632
1278
|
data: data[key]
|
|
@@ -634,8 +1280,8 @@ var ObjectKeywords = {
|
|
|
634
1280
|
}
|
|
635
1281
|
continue;
|
|
636
1282
|
}
|
|
637
|
-
if ("$validate" in
|
|
638
|
-
const error =
|
|
1283
|
+
if (schemaProp && "$validate" in schemaProp) {
|
|
1284
|
+
const error = schemaProp.$validate(data[key]);
|
|
639
1285
|
if (error) {
|
|
640
1286
|
return defineError("Property is invalid", {
|
|
641
1287
|
item: key,
|
|
@@ -648,12 +1294,19 @@ var ObjectKeywords = {
|
|
|
648
1294
|
return;
|
|
649
1295
|
},
|
|
650
1296
|
values(schema, data, defineError) {
|
|
651
|
-
if (!
|
|
1297
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
const valueSchema = schema.values;
|
|
1301
|
+
const validate = valueSchema && valueSchema.$validate;
|
|
1302
|
+
if (typeof validate !== "function") {
|
|
652
1303
|
return;
|
|
653
1304
|
}
|
|
654
|
-
const
|
|
655
|
-
|
|
656
|
-
|
|
1305
|
+
for (const key in data) {
|
|
1306
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
const error = validate(data[key]);
|
|
657
1310
|
if (error) {
|
|
658
1311
|
return defineError("Property is invalid", {
|
|
659
1312
|
item: key,
|
|
@@ -662,39 +1315,63 @@ var ObjectKeywords = {
|
|
|
662
1315
|
});
|
|
663
1316
|
}
|
|
664
1317
|
}
|
|
665
|
-
return;
|
|
666
1318
|
},
|
|
667
1319
|
maxProperties(schema, data, defineError) {
|
|
668
|
-
if (!
|
|
1320
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
669
1321
|
return;
|
|
670
1322
|
}
|
|
671
|
-
|
|
1323
|
+
let count = 0;
|
|
1324
|
+
for (const key in data) {
|
|
1325
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1326
|
+
continue;
|
|
1327
|
+
}
|
|
1328
|
+
count++;
|
|
1329
|
+
if (count > schema.maxProperties) {
|
|
1330
|
+
return defineError("Too many properties", { data });
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
return;
|
|
672
1334
|
},
|
|
673
1335
|
minProperties(schema, data, defineError) {
|
|
674
|
-
if (!
|
|
1336
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
675
1337
|
return;
|
|
676
1338
|
}
|
|
1339
|
+
let count = 0;
|
|
1340
|
+
for (const key in data) {
|
|
1341
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1342
|
+
continue;
|
|
1343
|
+
}
|
|
1344
|
+
count++;
|
|
1345
|
+
if (count >= schema.minProperties) {
|
|
1346
|
+
return;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
677
1349
|
return defineError("Too few properties", { data });
|
|
678
1350
|
},
|
|
679
1351
|
additionalProperties(schema, data, defineError) {
|
|
680
|
-
if (!
|
|
1352
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
681
1353
|
return;
|
|
682
1354
|
}
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
1355
|
+
let apValidate = schema._apValidate;
|
|
1356
|
+
if (apValidate === void 0) {
|
|
1357
|
+
apValidate = isCompiledSchema(schema.additionalProperties) ? schema.additionalProperties.$validate : null;
|
|
1358
|
+
Object.defineProperty(schema, "_apValidate", {
|
|
1359
|
+
value: apValidate,
|
|
1360
|
+
enumerable: false,
|
|
1361
|
+
configurable: false,
|
|
1362
|
+
writable: false
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
const patternEntries = getPatternPropertyEntries(schema);
|
|
1366
|
+
for (const key in data) {
|
|
1367
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
687
1368
|
continue;
|
|
688
1369
|
}
|
|
689
|
-
if (schema.
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
break;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
if (match) {
|
|
1370
|
+
if (schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key)) {
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
if (patternEntries && patternEntries.length) {
|
|
1374
|
+
if (getPatternKeyMatchIndexes(schema, key, patternEntries).length > 0) {
|
|
698
1375
|
continue;
|
|
699
1376
|
}
|
|
700
1377
|
}
|
|
@@ -704,8 +1381,8 @@ var ObjectKeywords = {
|
|
|
704
1381
|
data: data[key]
|
|
705
1382
|
});
|
|
706
1383
|
}
|
|
707
|
-
if (
|
|
708
|
-
const error =
|
|
1384
|
+
if (apValidate) {
|
|
1385
|
+
const error = apValidate(data[key]);
|
|
709
1386
|
if (error) {
|
|
710
1387
|
return defineError("Additional properties are invalid", {
|
|
711
1388
|
item: key,
|
|
@@ -718,39 +1395,46 @@ var ObjectKeywords = {
|
|
|
718
1395
|
return;
|
|
719
1396
|
},
|
|
720
1397
|
patternProperties(schema, data, defineError) {
|
|
721
|
-
if (!
|
|
1398
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
722
1399
|
return;
|
|
723
1400
|
}
|
|
724
|
-
const
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
1401
|
+
const patternEntries = getPatternPropertyEntries(schema);
|
|
1402
|
+
if (!patternEntries || patternEntries.length === 0) {
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
for (const key in data) {
|
|
1406
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1407
|
+
continue;
|
|
1408
|
+
}
|
|
1409
|
+
const matchingIndexes = getPatternKeyMatchIndexes(schema, key, patternEntries);
|
|
1410
|
+
if (matchingIndexes.length === 0) {
|
|
1411
|
+
if (schema.additionalProperties === false && !(schema.properties && Object.prototype.hasOwnProperty.call(schema.properties, key))) {
|
|
1412
|
+
return defineError("Additional properties are not allowed", {
|
|
1413
|
+
item: key,
|
|
1414
|
+
data: data[key]
|
|
1415
|
+
});
|
|
737
1416
|
}
|
|
738
1417
|
continue;
|
|
739
1418
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
if (
|
|
743
|
-
if (
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
1419
|
+
for (let j = 0; j < matchingIndexes.length; j++) {
|
|
1420
|
+
const schemaProp = patternEntries[matchingIndexes[j]].schemaProp;
|
|
1421
|
+
if (typeof schemaProp === "boolean") {
|
|
1422
|
+
if (schemaProp === false) {
|
|
1423
|
+
return defineError("Property is not allowed", {
|
|
1424
|
+
item: key,
|
|
1425
|
+
data: data[key]
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
continue;
|
|
1429
|
+
}
|
|
1430
|
+
if ("$validate" in schemaProp) {
|
|
1431
|
+
const error = schemaProp.$validate(data[key]);
|
|
1432
|
+
if (error) {
|
|
1433
|
+
return defineError("Property is invalid", {
|
|
1434
|
+
item: key,
|
|
1435
|
+
cause: error,
|
|
1436
|
+
data: data[key]
|
|
1437
|
+
});
|
|
754
1438
|
}
|
|
755
1439
|
}
|
|
756
1440
|
}
|
|
@@ -758,30 +1442,40 @@ var ObjectKeywords = {
|
|
|
758
1442
|
return;
|
|
759
1443
|
},
|
|
760
1444
|
propertyNames(schema, data, defineError) {
|
|
761
|
-
if (!
|
|
1445
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
762
1446
|
return;
|
|
763
1447
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
1448
|
+
const pn = schema.propertyNames;
|
|
1449
|
+
if (typeof pn === "boolean") {
|
|
1450
|
+
if (pn === false) {
|
|
1451
|
+
for (const key in data) {
|
|
1452
|
+
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1453
|
+
return defineError("Properties are not allowed", { data });
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
767
1456
|
}
|
|
1457
|
+
return;
|
|
768
1458
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
1459
|
+
const validate = pn && pn.$validate;
|
|
1460
|
+
if (typeof validate !== "function") {
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
for (const key in data) {
|
|
1464
|
+
if (!Object.prototype.hasOwnProperty.call(data, key)) {
|
|
1465
|
+
continue;
|
|
1466
|
+
}
|
|
1467
|
+
const error = validate(key);
|
|
1468
|
+
if (error) {
|
|
1469
|
+
return defineError("Property name is invalid", {
|
|
1470
|
+
item: key,
|
|
1471
|
+
cause: error,
|
|
1472
|
+
data: data[key]
|
|
1473
|
+
});
|
|
779
1474
|
}
|
|
780
1475
|
}
|
|
781
|
-
return;
|
|
782
1476
|
},
|
|
783
1477
|
dependencies(schema, data, defineError) {
|
|
784
|
-
if (!
|
|
1478
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
785
1479
|
return;
|
|
786
1480
|
}
|
|
787
1481
|
for (const key in schema.dependencies) {
|
|
@@ -827,7 +1521,6 @@ var ObjectKeywords = {
|
|
|
827
1521
|
else: false,
|
|
828
1522
|
default: false,
|
|
829
1523
|
// Not implemented yet
|
|
830
|
-
$ref: false,
|
|
831
1524
|
definitions: false,
|
|
832
1525
|
$id: false,
|
|
833
1526
|
$schema: false,
|
|
@@ -844,17 +1537,66 @@ var ObjectKeywords = {
|
|
|
844
1537
|
};
|
|
845
1538
|
|
|
846
1539
|
// lib/keywords/other-keywords.ts
|
|
1540
|
+
function toBranchEntry(item) {
|
|
1541
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
1542
|
+
if ("$validate" in item && typeof item.$validate === "function") {
|
|
1543
|
+
return { kind: "validate", validate: item.$validate };
|
|
1544
|
+
}
|
|
1545
|
+
return { kind: "alwaysValid" };
|
|
1546
|
+
}
|
|
1547
|
+
if (typeof item === "boolean") {
|
|
1548
|
+
return { kind: item ? "alwaysValid" : "alwaysInvalid" };
|
|
1549
|
+
}
|
|
1550
|
+
return { kind: "literal", value: item };
|
|
1551
|
+
}
|
|
1552
|
+
function getBranchEntries(schema, key) {
|
|
1553
|
+
const cacheKey = `_${key}BranchEntries`;
|
|
1554
|
+
let entries = schema[cacheKey];
|
|
1555
|
+
if (entries) {
|
|
1556
|
+
return entries;
|
|
1557
|
+
}
|
|
1558
|
+
const source = schema[key] || [];
|
|
1559
|
+
entries = [];
|
|
1560
|
+
for (let i = 0; i < source.length; i++) {
|
|
1561
|
+
entries.push(toBranchEntry(source[i]));
|
|
1562
|
+
}
|
|
1563
|
+
Object.defineProperty(schema, cacheKey, {
|
|
1564
|
+
value: entries,
|
|
1565
|
+
enumerable: false,
|
|
1566
|
+
configurable: false,
|
|
1567
|
+
writable: false
|
|
1568
|
+
});
|
|
1569
|
+
return entries;
|
|
1570
|
+
}
|
|
847
1571
|
var OtherKeywords = {
|
|
848
1572
|
enum(schema, data, defineError) {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
|
|
1573
|
+
let enumCache = schema._enumCache;
|
|
1574
|
+
if (!enumCache) {
|
|
1575
|
+
const primitiveSet = /* @__PURE__ */ new Set();
|
|
1576
|
+
const objectValues = [];
|
|
1577
|
+
const list = schema.enum;
|
|
1578
|
+
for (let i = 0; i < list.length; i++) {
|
|
1579
|
+
const enumItem = list[i];
|
|
1580
|
+
if (enumItem !== null && typeof enumItem === "object") {
|
|
1581
|
+
objectValues.push(enumItem);
|
|
1582
|
+
} else {
|
|
1583
|
+
primitiveSet.add(enumItem);
|
|
1584
|
+
}
|
|
855
1585
|
}
|
|
856
|
-
|
|
857
|
-
|
|
1586
|
+
enumCache = { primitiveSet, objectValues };
|
|
1587
|
+
Object.defineProperty(schema, "_enumCache", {
|
|
1588
|
+
value: enumCache,
|
|
1589
|
+
enumerable: false,
|
|
1590
|
+
configurable: false,
|
|
1591
|
+
writable: false
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
if (!(typeof data === "number" && Number.isNaN(data)) && enumCache.primitiveSet.has(data)) {
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
if (data !== null && typeof data === "object") {
|
|
1598
|
+
for (let i = 0; i < enumCache.objectValues.length; i++) {
|
|
1599
|
+
if (!hasChanged(enumCache.objectValues[i], data)) {
|
|
858
1600
|
return;
|
|
859
1601
|
}
|
|
860
1602
|
}
|
|
@@ -862,74 +1604,130 @@ var OtherKeywords = {
|
|
|
862
1604
|
return defineError("Value is not one of the allowed values", { data });
|
|
863
1605
|
},
|
|
864
1606
|
allOf(schema, data, defineError) {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
}
|
|
1607
|
+
const branches = getBranchEntries(schema, "allOf");
|
|
1608
|
+
if (branches.length === 1) {
|
|
1609
|
+
const onlyBranch = branches[0];
|
|
1610
|
+
if (onlyBranch.kind === "validate") {
|
|
1611
|
+
const error = onlyBranch.validate(data);
|
|
1612
|
+
if (error) {
|
|
1613
|
+
return defineError("Value is not valid", { cause: error, data });
|
|
872
1614
|
}
|
|
873
|
-
|
|
1615
|
+
return;
|
|
874
1616
|
}
|
|
875
|
-
if (
|
|
876
|
-
|
|
877
|
-
|
|
1617
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
1621
|
+
return defineError("Value is not valid", { data });
|
|
1622
|
+
}
|
|
1623
|
+
if (data !== onlyBranch.value) {
|
|
1624
|
+
return defineError("Value is not valid", { data });
|
|
1625
|
+
}
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
for (let i = 0; i < branches.length; i++) {
|
|
1629
|
+
const branch = branches[i];
|
|
1630
|
+
if (branch.kind === "validate") {
|
|
1631
|
+
const error = branch.validate(data);
|
|
1632
|
+
if (error) {
|
|
1633
|
+
return defineError("Value is not valid", { cause: error, data });
|
|
878
1634
|
}
|
|
879
1635
|
continue;
|
|
880
1636
|
}
|
|
881
|
-
if (
|
|
1637
|
+
if (branch.kind === "alwaysValid") {
|
|
1638
|
+
continue;
|
|
1639
|
+
}
|
|
1640
|
+
if (branch.kind === "alwaysInvalid") {
|
|
1641
|
+
return defineError("Value is not valid", { data });
|
|
1642
|
+
}
|
|
1643
|
+
if (data !== branch.value) {
|
|
882
1644
|
return defineError("Value is not valid", { data });
|
|
883
1645
|
}
|
|
884
1646
|
}
|
|
885
1647
|
return;
|
|
886
1648
|
},
|
|
887
1649
|
anyOf(schema, data, defineError) {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
continue;
|
|
1650
|
+
const branches = getBranchEntries(schema, "anyOf");
|
|
1651
|
+
if (branches.length === 1) {
|
|
1652
|
+
const onlyBranch = branches[0];
|
|
1653
|
+
if (onlyBranch.kind === "validate") {
|
|
1654
|
+
const error = onlyBranch.validate(data);
|
|
1655
|
+
if (!error) {
|
|
1656
|
+
return;
|
|
896
1657
|
}
|
|
1658
|
+
return defineError("Value is not valid", { data });
|
|
1659
|
+
}
|
|
1660
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
897
1661
|
return;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1662
|
+
}
|
|
1663
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
1664
|
+
return defineError("Value is not valid", { data });
|
|
1665
|
+
}
|
|
1666
|
+
if (data === onlyBranch.value) {
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
return defineError("Value is not valid", { data });
|
|
1670
|
+
}
|
|
1671
|
+
for (let i = 0; i < branches.length; i++) {
|
|
1672
|
+
const branch = branches[i];
|
|
1673
|
+
if (branch.kind === "validate") {
|
|
1674
|
+
const error = branch.validate(data);
|
|
1675
|
+
if (!error) {
|
|
905
1676
|
return;
|
|
906
1677
|
}
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
if (branch.kind === "alwaysValid") {
|
|
1681
|
+
return;
|
|
1682
|
+
}
|
|
1683
|
+
if (branch.kind === "alwaysInvalid") {
|
|
1684
|
+
continue;
|
|
1685
|
+
}
|
|
1686
|
+
if (data === branch.value) {
|
|
1687
|
+
return;
|
|
907
1688
|
}
|
|
908
1689
|
}
|
|
909
1690
|
return defineError("Value is not valid", { data });
|
|
910
1691
|
},
|
|
911
1692
|
oneOf(schema, data, defineError) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
}
|
|
920
|
-
continue;
|
|
1693
|
+
const branches = getBranchEntries(schema, "oneOf");
|
|
1694
|
+
if (branches.length === 1) {
|
|
1695
|
+
const onlyBranch = branches[0];
|
|
1696
|
+
if (onlyBranch.kind === "validate") {
|
|
1697
|
+
const error = onlyBranch.validate(data);
|
|
1698
|
+
if (!error) {
|
|
1699
|
+
return;
|
|
921
1700
|
}
|
|
922
|
-
|
|
923
|
-
|
|
1701
|
+
return defineError("Value is not valid", { data });
|
|
1702
|
+
}
|
|
1703
|
+
if (onlyBranch.kind === "alwaysValid") {
|
|
1704
|
+
return;
|
|
1705
|
+
}
|
|
1706
|
+
if (onlyBranch.kind === "alwaysInvalid") {
|
|
1707
|
+
return defineError("Value is not valid", { data });
|
|
1708
|
+
}
|
|
1709
|
+
if (data === onlyBranch.value) {
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1712
|
+
return defineError("Value is not valid", { data });
|
|
1713
|
+
}
|
|
1714
|
+
let validCount = 0;
|
|
1715
|
+
for (let i = 0; i < branches.length; i++) {
|
|
1716
|
+
const branch = branches[i];
|
|
1717
|
+
let isValid = false;
|
|
1718
|
+
if (branch.kind === "validate") {
|
|
1719
|
+
isValid = !branch.validate(data);
|
|
1720
|
+
} else if (branch.kind === "alwaysValid") {
|
|
1721
|
+
isValid = true;
|
|
1722
|
+
} else if (branch.kind === "alwaysInvalid") {
|
|
1723
|
+
isValid = false;
|
|
924
1724
|
} else {
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
if (data === schema.oneOf[i]) {
|
|
932
|
-
validCount++;
|
|
1725
|
+
isValid = data === branch.value;
|
|
1726
|
+
}
|
|
1727
|
+
if (isValid) {
|
|
1728
|
+
validCount++;
|
|
1729
|
+
if (validCount > 1) {
|
|
1730
|
+
return defineError("Value is not valid", { data });
|
|
933
1731
|
}
|
|
934
1732
|
}
|
|
935
1733
|
}
|
|
@@ -939,12 +1737,15 @@ var OtherKeywords = {
|
|
|
939
1737
|
return defineError("Value is not valid", { data });
|
|
940
1738
|
},
|
|
941
1739
|
const(schema, data, defineError) {
|
|
942
|
-
if (data === schema.const
|
|
1740
|
+
if (data === schema.const) {
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
if (data && typeof data === "object" && !Array.isArray(data) && schema.const && typeof schema.const === "object" && !Array.isArray(schema.const) && !hasChanged(data, schema.const) || Array.isArray(data) && Array.isArray(schema.const) && !hasChanged(data, schema.const)) {
|
|
943
1744
|
return;
|
|
944
1745
|
}
|
|
945
1746
|
return defineError("Value is not valid", { data });
|
|
946
1747
|
},
|
|
947
|
-
if(schema, data
|
|
1748
|
+
if(schema, data) {
|
|
948
1749
|
if ("then" in schema === false && "else" in schema === false) {
|
|
949
1750
|
return;
|
|
950
1751
|
}
|
|
@@ -981,21 +1782,45 @@ var OtherKeywords = {
|
|
|
981
1782
|
}
|
|
982
1783
|
return;
|
|
983
1784
|
}
|
|
984
|
-
if (
|
|
1785
|
+
if (schema.not && typeof schema.not === "object" && !Array.isArray(schema.not)) {
|
|
985
1786
|
if ("$validate" in schema.not) {
|
|
986
1787
|
const error = schema.not.$validate(data);
|
|
987
1788
|
if (!error) {
|
|
988
|
-
return defineError("Value is not valid", {
|
|
1789
|
+
return defineError("Value is not valid", { data });
|
|
989
1790
|
}
|
|
990
1791
|
return;
|
|
991
1792
|
}
|
|
992
1793
|
return defineError("Value is not valid", { data });
|
|
993
1794
|
}
|
|
994
1795
|
return defineError("Value is not valid", { data });
|
|
1796
|
+
},
|
|
1797
|
+
$ref(schema, data, defineError, instance) {
|
|
1798
|
+
if (schema._resolvedRef) {
|
|
1799
|
+
if (schema.$validate !== schema._resolvedRef) {
|
|
1800
|
+
schema.$validate = schema._resolvedRef;
|
|
1801
|
+
}
|
|
1802
|
+
return schema._resolvedRef(data);
|
|
1803
|
+
}
|
|
1804
|
+
const refPath = schema.$ref;
|
|
1805
|
+
let targetSchema = instance.getSchemaRef(refPath);
|
|
1806
|
+
if (!targetSchema) {
|
|
1807
|
+
targetSchema = instance.getSchemaById(refPath);
|
|
1808
|
+
}
|
|
1809
|
+
if (!targetSchema) {
|
|
1810
|
+
return defineError(`Missing reference: ${refPath}`);
|
|
1811
|
+
}
|
|
1812
|
+
if (!targetSchema.$validate) {
|
|
1813
|
+
return;
|
|
1814
|
+
}
|
|
1815
|
+
schema._resolvedRef = targetSchema.$validate;
|
|
1816
|
+
schema.$validate = schema._resolvedRef;
|
|
1817
|
+
return schema._resolvedRef(data);
|
|
995
1818
|
}
|
|
996
1819
|
};
|
|
997
1820
|
|
|
998
1821
|
// lib/keywords/string-keywords.ts
|
|
1822
|
+
var PATTERN_MATCH_CACHE_LIMIT = 512;
|
|
1823
|
+
var FORMAT_RESULT_CACHE_LIMIT = 512;
|
|
999
1824
|
var StringKeywords = {
|
|
1000
1825
|
minLength(schema, data, defineError) {
|
|
1001
1826
|
if (typeof data !== "string" || data.length >= schema.minLength) {
|
|
@@ -1013,11 +1838,44 @@ var StringKeywords = {
|
|
|
1013
1838
|
if (typeof data !== "string") {
|
|
1014
1839
|
return;
|
|
1015
1840
|
}
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1841
|
+
let patternMatch = schema._patternMatch;
|
|
1842
|
+
let patternMatchCache = schema._patternMatchCache;
|
|
1843
|
+
if (!patternMatch) {
|
|
1844
|
+
try {
|
|
1845
|
+
const compiled = compilePatternMatcher(schema.pattern);
|
|
1846
|
+
patternMatch = compiled instanceof RegExp ? (value) => compiled.test(value) : compiled;
|
|
1847
|
+
Object.defineProperty(schema, "_patternMatch", {
|
|
1848
|
+
value: patternMatch,
|
|
1849
|
+
enumerable: false,
|
|
1850
|
+
configurable: false,
|
|
1851
|
+
writable: false
|
|
1852
|
+
});
|
|
1853
|
+
} catch (error) {
|
|
1854
|
+
return defineError("Invalid regular expression", {
|
|
1855
|
+
data,
|
|
1856
|
+
cause: error
|
|
1857
|
+
});
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
if (!patternMatchCache) {
|
|
1861
|
+
patternMatchCache = /* @__PURE__ */ new Map();
|
|
1862
|
+
Object.defineProperty(schema, "_patternMatchCache", {
|
|
1863
|
+
value: patternMatchCache,
|
|
1864
|
+
enumerable: false,
|
|
1865
|
+
configurable: false,
|
|
1866
|
+
writable: false
|
|
1867
|
+
});
|
|
1868
|
+
} else if (patternMatchCache.has(data)) {
|
|
1869
|
+
if (patternMatchCache.get(data)) {
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
return defineError("Value does not match the pattern", { data });
|
|
1873
|
+
}
|
|
1874
|
+
const isMatch = patternMatch(data);
|
|
1875
|
+
if (patternMatchCache.size < PATTERN_MATCH_CACHE_LIMIT) {
|
|
1876
|
+
patternMatchCache.set(data, isMatch);
|
|
1019
1877
|
}
|
|
1020
|
-
if (
|
|
1878
|
+
if (isMatch) {
|
|
1021
1879
|
return;
|
|
1022
1880
|
}
|
|
1023
1881
|
return defineError("Value does not match the pattern", { data });
|
|
@@ -1028,8 +1886,58 @@ var StringKeywords = {
|
|
|
1028
1886
|
if (typeof data !== "string") {
|
|
1029
1887
|
return;
|
|
1030
1888
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1889
|
+
let formatValidate = schema._formatValidate;
|
|
1890
|
+
let formatResultCacheEnabled = schema._formatResultCacheEnabled;
|
|
1891
|
+
let formatResultCache = schema._formatResultCache;
|
|
1892
|
+
if (formatValidate === void 0) {
|
|
1893
|
+
formatValidate = instance.getFormat(schema.format);
|
|
1894
|
+
Object.defineProperty(schema, "_formatValidate", {
|
|
1895
|
+
value: formatValidate,
|
|
1896
|
+
enumerable: false,
|
|
1897
|
+
configurable: false,
|
|
1898
|
+
writable: false
|
|
1899
|
+
});
|
|
1900
|
+
}
|
|
1901
|
+
if (!formatValidate) {
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
if (formatResultCacheEnabled === void 0) {
|
|
1905
|
+
formatResultCacheEnabled = instance.isDefaultFormatValidator(
|
|
1906
|
+
schema.format,
|
|
1907
|
+
formatValidate
|
|
1908
|
+
);
|
|
1909
|
+
Object.defineProperty(schema, "_formatResultCacheEnabled", {
|
|
1910
|
+
value: formatResultCacheEnabled,
|
|
1911
|
+
enumerable: false,
|
|
1912
|
+
configurable: false,
|
|
1913
|
+
writable: false
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
if (!formatResultCacheEnabled) {
|
|
1917
|
+
if (formatValidate(data)) {
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
return defineError("Value does not match the format", { data });
|
|
1921
|
+
}
|
|
1922
|
+
if (!formatResultCache) {
|
|
1923
|
+
formatResultCache = /* @__PURE__ */ new Map();
|
|
1924
|
+
Object.defineProperty(schema, "_formatResultCache", {
|
|
1925
|
+
value: formatResultCache,
|
|
1926
|
+
enumerable: false,
|
|
1927
|
+
configurable: false,
|
|
1928
|
+
writable: false
|
|
1929
|
+
});
|
|
1930
|
+
} else if (formatResultCache.has(data)) {
|
|
1931
|
+
if (formatResultCache.get(data)) {
|
|
1932
|
+
return;
|
|
1933
|
+
}
|
|
1934
|
+
return defineError("Value does not match the format", { data });
|
|
1935
|
+
}
|
|
1936
|
+
const isValid = formatValidate(data);
|
|
1937
|
+
if (formatResultCache.size < FORMAT_RESULT_CACHE_LIMIT) {
|
|
1938
|
+
formatResultCache.set(data, isValid);
|
|
1939
|
+
}
|
|
1940
|
+
if (isValid) {
|
|
1033
1941
|
return;
|
|
1034
1942
|
}
|
|
1035
1943
|
return defineError("Value does not match the format", { data });
|
|
@@ -1051,10 +1959,15 @@ var SchemaShield = class {
|
|
|
1051
1959
|
formats = {};
|
|
1052
1960
|
keywords = {};
|
|
1053
1961
|
immutable = false;
|
|
1962
|
+
rootSchema = null;
|
|
1963
|
+
idRegistry = /* @__PURE__ */ new Map();
|
|
1964
|
+
failFast = true;
|
|
1054
1965
|
constructor({
|
|
1055
|
-
immutable = false
|
|
1966
|
+
immutable = false,
|
|
1967
|
+
failFast = true
|
|
1056
1968
|
} = {}) {
|
|
1057
1969
|
this.immutable = immutable;
|
|
1970
|
+
this.failFast = failFast;
|
|
1058
1971
|
for (const [type, validator] of Object.entries(Types)) {
|
|
1059
1972
|
if (validator) {
|
|
1060
1973
|
this.addType(type, validator);
|
|
@@ -1087,6 +2000,9 @@ var SchemaShield = class {
|
|
|
1087
2000
|
getFormat(format) {
|
|
1088
2001
|
return this.formats[format];
|
|
1089
2002
|
}
|
|
2003
|
+
isDefaultFormatValidator(format, validator) {
|
|
2004
|
+
return Formats[format] === validator;
|
|
2005
|
+
}
|
|
1090
2006
|
addKeyword(name, validator, overwrite = false) {
|
|
1091
2007
|
if (this.keywords[name] && !overwrite) {
|
|
1092
2008
|
throw new ValidationError(`Keyword "${name}" already exists`);
|
|
@@ -1096,150 +2012,537 @@ var SchemaShield = class {
|
|
|
1096
2012
|
getKeyword(keyword) {
|
|
1097
2013
|
return this.keywords[keyword];
|
|
1098
2014
|
}
|
|
2015
|
+
getSchemaRef(path) {
|
|
2016
|
+
if (!this.rootSchema) {
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
return resolvePath(this.rootSchema, path);
|
|
2020
|
+
}
|
|
2021
|
+
getSchemaById(id) {
|
|
2022
|
+
return this.idRegistry.get(id);
|
|
2023
|
+
}
|
|
1099
2024
|
compile(schema) {
|
|
2025
|
+
this.idRegistry.clear();
|
|
1100
2026
|
const compiledSchema = this.compileSchema(schema);
|
|
2027
|
+
this.rootSchema = compiledSchema;
|
|
2028
|
+
if (compiledSchema._hasRef === true) {
|
|
2029
|
+
this.linkReferences(compiledSchema);
|
|
2030
|
+
}
|
|
1101
2031
|
if (!compiledSchema.$validate) {
|
|
1102
|
-
if (
|
|
2032
|
+
if (schema === false) {
|
|
2033
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2034
|
+
"oneOf",
|
|
2035
|
+
compiledSchema,
|
|
2036
|
+
this.failFast
|
|
2037
|
+
);
|
|
2038
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2039
|
+
"Validate_False",
|
|
2040
|
+
(data) => defineError("Value is not valid", { data })
|
|
2041
|
+
);
|
|
2042
|
+
} else if (schema === true) {
|
|
2043
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2044
|
+
"Validate_Any",
|
|
2045
|
+
() => {
|
|
2046
|
+
}
|
|
2047
|
+
);
|
|
2048
|
+
} else if (this.isSchemaLike(schema) === false) {
|
|
1103
2049
|
throw new ValidationError("Invalid schema");
|
|
2050
|
+
} else {
|
|
2051
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2052
|
+
"Validate_Any",
|
|
2053
|
+
() => {
|
|
2054
|
+
}
|
|
2055
|
+
);
|
|
1104
2056
|
}
|
|
1105
|
-
compiledSchema.$validate = getNamedFunction(
|
|
1106
|
-
"any",
|
|
1107
|
-
() => {
|
|
1108
|
-
}
|
|
1109
|
-
);
|
|
1110
2057
|
}
|
|
1111
2058
|
const validate = (data) => {
|
|
1112
|
-
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
};
|
|
2059
|
+
this.rootSchema = compiledSchema;
|
|
2060
|
+
const clonedData = this.immutable ? deepCloneUnfreeze(data) : data;
|
|
2061
|
+
const res = compiledSchema.$validate(clonedData);
|
|
2062
|
+
if (res) {
|
|
2063
|
+
return { data: clonedData, error: res, valid: false };
|
|
2064
|
+
}
|
|
2065
|
+
return { data: clonedData, error: null, valid: true };
|
|
1119
2066
|
};
|
|
1120
2067
|
validate.compiledSchema = compiledSchema;
|
|
1121
2068
|
return validate;
|
|
1122
2069
|
}
|
|
2070
|
+
isPlainObject(value) {
|
|
2071
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
2072
|
+
}
|
|
2073
|
+
isTrivialAlwaysValidSubschema(value) {
|
|
2074
|
+
return value === true || this.isPlainObject(value) && Object.keys(value).length === 0;
|
|
2075
|
+
}
|
|
2076
|
+
shallowArrayEquals(a, b) {
|
|
2077
|
+
if (a === b) {
|
|
2078
|
+
return true;
|
|
2079
|
+
}
|
|
2080
|
+
if (a.length !== b.length) {
|
|
2081
|
+
return false;
|
|
2082
|
+
}
|
|
2083
|
+
for (let i = 0; i < a.length; i++) {
|
|
2084
|
+
if (a[i] !== b[i]) {
|
|
2085
|
+
return false;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
return true;
|
|
2089
|
+
}
|
|
2090
|
+
flattenAssociativeBranches(key, branches) {
|
|
2091
|
+
const out = [];
|
|
2092
|
+
for (let i = 0; i < branches.length; i++) {
|
|
2093
|
+
const item = branches[i];
|
|
2094
|
+
if (this.isPlainObject(item) && Object.keys(item).length === 1 && Array.isArray(item[key])) {
|
|
2095
|
+
const nested = this.flattenAssociativeBranches(key, item[key]);
|
|
2096
|
+
for (let j = 0; j < nested.length; j++) {
|
|
2097
|
+
out.push(nested[j]);
|
|
2098
|
+
}
|
|
2099
|
+
continue;
|
|
2100
|
+
}
|
|
2101
|
+
out.push(item);
|
|
2102
|
+
}
|
|
2103
|
+
return out;
|
|
2104
|
+
}
|
|
2105
|
+
flattenSingleWrapperOneOf(branches) {
|
|
2106
|
+
let current = branches;
|
|
2107
|
+
while (current.length === 1) {
|
|
2108
|
+
const item = current[0];
|
|
2109
|
+
if (this.isPlainObject(item) && Object.keys(item).length === 1 && Array.isArray(item.oneOf)) {
|
|
2110
|
+
current = item.oneOf;
|
|
2111
|
+
continue;
|
|
2112
|
+
}
|
|
2113
|
+
break;
|
|
2114
|
+
}
|
|
2115
|
+
return current;
|
|
2116
|
+
}
|
|
2117
|
+
normalizeSchemaForCompile(schema) {
|
|
2118
|
+
let normalized = schema;
|
|
2119
|
+
const schemaKeys = Object.keys(schema);
|
|
2120
|
+
const hasOnlyKey = (key) => schemaKeys.length === 1 && schemaKeys[0] === key;
|
|
2121
|
+
const setNormalized = (key, value) => {
|
|
2122
|
+
if (normalized === schema) {
|
|
2123
|
+
normalized = { ...schema };
|
|
2124
|
+
}
|
|
2125
|
+
normalized[key] = value;
|
|
2126
|
+
};
|
|
2127
|
+
if (Array.isArray(schema.allOf)) {
|
|
2128
|
+
const flattenedAllOf = this.flattenAssociativeBranches(
|
|
2129
|
+
"allOf",
|
|
2130
|
+
schema.allOf
|
|
2131
|
+
).filter(
|
|
2132
|
+
(item) => !(this.isPlainObject(item) && Object.keys(item).length === 0)
|
|
2133
|
+
);
|
|
2134
|
+
if (hasOnlyKey("allOf") && flattenedAllOf.length === 1 && this.isPlainObject(flattenedAllOf[0])) {
|
|
2135
|
+
return flattenedAllOf[0];
|
|
2136
|
+
}
|
|
2137
|
+
if (!this.shallowArrayEquals(flattenedAllOf, schema.allOf)) {
|
|
2138
|
+
setNormalized("allOf", flattenedAllOf);
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
if (Array.isArray(schema.anyOf)) {
|
|
2142
|
+
const flattenedAnyOf = this.flattenAssociativeBranches(
|
|
2143
|
+
"anyOf",
|
|
2144
|
+
schema.anyOf
|
|
2145
|
+
);
|
|
2146
|
+
if (hasOnlyKey("anyOf") && flattenedAnyOf.length === 1 && this.isPlainObject(flattenedAnyOf[0])) {
|
|
2147
|
+
return flattenedAnyOf[0];
|
|
2148
|
+
}
|
|
2149
|
+
if (!this.shallowArrayEquals(flattenedAnyOf, schema.anyOf)) {
|
|
2150
|
+
setNormalized("anyOf", flattenedAnyOf);
|
|
2151
|
+
}
|
|
2152
|
+
}
|
|
2153
|
+
if (Array.isArray(schema.oneOf)) {
|
|
2154
|
+
const flattenedOneOf = this.flattenSingleWrapperOneOf(schema.oneOf);
|
|
2155
|
+
if (hasOnlyKey("oneOf") && flattenedOneOf.length === 1 && this.isPlainObject(flattenedOneOf[0])) {
|
|
2156
|
+
return flattenedOneOf[0];
|
|
2157
|
+
}
|
|
2158
|
+
if (!this.shallowArrayEquals(flattenedOneOf, schema.oneOf)) {
|
|
2159
|
+
setNormalized("oneOf", flattenedOneOf);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
return normalized;
|
|
2163
|
+
}
|
|
2164
|
+
markSchemaHasRef(schema) {
|
|
2165
|
+
if (schema._hasRef === true) {
|
|
2166
|
+
return;
|
|
2167
|
+
}
|
|
2168
|
+
Object.defineProperty(schema, "_hasRef", {
|
|
2169
|
+
value: true,
|
|
2170
|
+
enumerable: false,
|
|
2171
|
+
configurable: false,
|
|
2172
|
+
writable: false
|
|
2173
|
+
});
|
|
2174
|
+
}
|
|
2175
|
+
shouldSkipKeyword(schema, key) {
|
|
2176
|
+
const value = schema[key];
|
|
2177
|
+
switch (key) {
|
|
2178
|
+
case "required":
|
|
2179
|
+
return Array.isArray(value) && value.length === 0;
|
|
2180
|
+
case "uniqueItems":
|
|
2181
|
+
return value === false;
|
|
2182
|
+
case "properties":
|
|
2183
|
+
case "patternProperties":
|
|
2184
|
+
case "dependencies":
|
|
2185
|
+
return this.isPlainObject(value) && Object.keys(value).length === 0;
|
|
2186
|
+
case "propertyNames":
|
|
2187
|
+
case "items":
|
|
2188
|
+
return value === true;
|
|
2189
|
+
case "additionalProperties":
|
|
2190
|
+
if (value === true) {
|
|
2191
|
+
return true;
|
|
2192
|
+
}
|
|
2193
|
+
return value === false && this.isPlainObject(schema.patternProperties) && Object.keys(schema.patternProperties).length > 0;
|
|
2194
|
+
case "additionalItems":
|
|
2195
|
+
return value === true || !Array.isArray(schema.items);
|
|
2196
|
+
case "allOf": {
|
|
2197
|
+
if (!Array.isArray(value)) {
|
|
2198
|
+
return false;
|
|
2199
|
+
}
|
|
2200
|
+
if (value.length === 0) {
|
|
2201
|
+
return true;
|
|
2202
|
+
}
|
|
2203
|
+
for (let i = 0; i < value.length; i++) {
|
|
2204
|
+
if (this.isTrivialAlwaysValidSubschema(value[i])) {
|
|
2205
|
+
continue;
|
|
2206
|
+
}
|
|
2207
|
+
return false;
|
|
2208
|
+
}
|
|
2209
|
+
return true;
|
|
2210
|
+
}
|
|
2211
|
+
case "anyOf": {
|
|
2212
|
+
if (!Array.isArray(value)) {
|
|
2213
|
+
return false;
|
|
2214
|
+
}
|
|
2215
|
+
for (let i = 0; i < value.length; i++) {
|
|
2216
|
+
if (this.isTrivialAlwaysValidSubschema(value[i])) {
|
|
2217
|
+
return true;
|
|
2218
|
+
}
|
|
2219
|
+
}
|
|
2220
|
+
return false;
|
|
2221
|
+
}
|
|
2222
|
+
default:
|
|
2223
|
+
return false;
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
hasRequiredDefaults(schema) {
|
|
2227
|
+
const properties = schema.properties;
|
|
2228
|
+
if (!this.isPlainObject(properties)) {
|
|
2229
|
+
return false;
|
|
2230
|
+
}
|
|
2231
|
+
const keys = Object.keys(properties);
|
|
2232
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2233
|
+
const subSchema = properties[keys[i]];
|
|
2234
|
+
if (this.isPlainObject(subSchema) && "default" in subSchema) {
|
|
2235
|
+
return true;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return false;
|
|
2239
|
+
}
|
|
2240
|
+
isDefaultTypeValidator(type, validator) {
|
|
2241
|
+
return Types[type] === validator;
|
|
2242
|
+
}
|
|
1123
2243
|
compileSchema(schema) {
|
|
1124
|
-
if (!
|
|
2244
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
1125
2245
|
if (schema === true) {
|
|
1126
|
-
schema = {
|
|
1127
|
-
anyOf: [{}]
|
|
1128
|
-
};
|
|
2246
|
+
schema = { anyOf: [{}] };
|
|
1129
2247
|
} else if (schema === false) {
|
|
1130
|
-
schema = {
|
|
1131
|
-
oneOf: []
|
|
1132
|
-
};
|
|
2248
|
+
schema = { oneOf: [] };
|
|
1133
2249
|
} else {
|
|
1134
|
-
schema = {
|
|
1135
|
-
oneOf: [schema]
|
|
1136
|
-
};
|
|
2250
|
+
schema = { oneOf: [schema] };
|
|
1137
2251
|
}
|
|
1138
2252
|
}
|
|
1139
|
-
|
|
1140
|
-
const
|
|
1141
|
-
|
|
1142
|
-
|
|
2253
|
+
schema = this.normalizeSchemaForCompile(schema);
|
|
2254
|
+
const compiledSchema = deepCloneUnfreeze(
|
|
2255
|
+
schema
|
|
2256
|
+
);
|
|
2257
|
+
let schemaHasRef = false;
|
|
2258
|
+
if (typeof schema.$id === "string") {
|
|
2259
|
+
this.idRegistry.set(schema.$id, compiledSchema);
|
|
2260
|
+
}
|
|
2261
|
+
if ("$ref" in schema) {
|
|
2262
|
+
schemaHasRef = true;
|
|
2263
|
+
const refValidator = this.getKeyword("$ref");
|
|
2264
|
+
if (refValidator) {
|
|
2265
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2266
|
+
"$ref",
|
|
2267
|
+
schema["$ref"],
|
|
2268
|
+
this.failFast
|
|
2269
|
+
);
|
|
2270
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2271
|
+
"Validate_Reference",
|
|
2272
|
+
(data) => refValidator(
|
|
2273
|
+
compiledSchema,
|
|
2274
|
+
data,
|
|
2275
|
+
defineError,
|
|
2276
|
+
this
|
|
2277
|
+
)
|
|
2278
|
+
);
|
|
2279
|
+
}
|
|
2280
|
+
this.markSchemaHasRef(compiledSchema);
|
|
2281
|
+
return compiledSchema;
|
|
2282
|
+
}
|
|
2283
|
+
const validators = [];
|
|
2284
|
+
const activeNames = [];
|
|
1143
2285
|
if ("type" in schema) {
|
|
2286
|
+
const defineTypeError = getDefinedErrorFunctionForKey(
|
|
2287
|
+
"type",
|
|
2288
|
+
schema,
|
|
2289
|
+
this.failFast
|
|
2290
|
+
);
|
|
1144
2291
|
const types = Array.isArray(schema.type) ? schema.type : schema.type.split(",").map((t) => t.trim());
|
|
1145
|
-
|
|
1146
|
-
|
|
2292
|
+
const typeFunctions = [];
|
|
2293
|
+
const typeNames = [];
|
|
2294
|
+
const defaultTypeNames = [];
|
|
2295
|
+
let allTypesDefault = true;
|
|
2296
|
+
for (const type2 of types) {
|
|
2297
|
+
const validator = this.getType(type2);
|
|
1147
2298
|
if (validator) {
|
|
1148
|
-
|
|
1149
|
-
|
|
2299
|
+
typeFunctions.push(validator);
|
|
2300
|
+
typeNames.push(validator.name);
|
|
2301
|
+
if (this.isDefaultTypeValidator(type2, validator)) {
|
|
2302
|
+
defaultTypeNames.push(type2);
|
|
2303
|
+
} else {
|
|
2304
|
+
allTypesDefault = false;
|
|
2305
|
+
}
|
|
1150
2306
|
}
|
|
1151
2307
|
}
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
2308
|
+
if (typeFunctions.length === 0) {
|
|
2309
|
+
throw getDefinedErrorFunctionForKey(
|
|
2310
|
+
"type",
|
|
2311
|
+
schema,
|
|
2312
|
+
this.failFast
|
|
2313
|
+
)("Invalid type for schema", { data: schema.type });
|
|
2314
|
+
}
|
|
2315
|
+
let combinedTypeValidator;
|
|
2316
|
+
let typeMethodName = "";
|
|
2317
|
+
if (typeFunctions.length === 1 && allTypesDefault) {
|
|
2318
|
+
const singleTypeName = defaultTypeNames[0];
|
|
2319
|
+
typeMethodName = singleTypeName;
|
|
2320
|
+
switch (singleTypeName) {
|
|
2321
|
+
case "object":
|
|
2322
|
+
combinedTypeValidator = (data) => {
|
|
2323
|
+
if (data === null || typeof data !== "object" || Array.isArray(data)) {
|
|
2324
|
+
return defineTypeError("Invalid type", { data });
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
break;
|
|
2328
|
+
case "array":
|
|
2329
|
+
combinedTypeValidator = (data) => {
|
|
2330
|
+
if (!Array.isArray(data)) {
|
|
2331
|
+
return defineTypeError("Invalid type", { data });
|
|
2332
|
+
}
|
|
2333
|
+
};
|
|
2334
|
+
break;
|
|
2335
|
+
case "string":
|
|
2336
|
+
combinedTypeValidator = (data) => {
|
|
2337
|
+
if (typeof data !== "string") {
|
|
2338
|
+
return defineTypeError("Invalid type", { data });
|
|
2339
|
+
}
|
|
2340
|
+
};
|
|
2341
|
+
break;
|
|
2342
|
+
case "number":
|
|
2343
|
+
combinedTypeValidator = (data) => {
|
|
2344
|
+
if (typeof data !== "number") {
|
|
2345
|
+
return defineTypeError("Invalid type", { data });
|
|
2346
|
+
}
|
|
2347
|
+
};
|
|
2348
|
+
break;
|
|
2349
|
+
case "integer":
|
|
2350
|
+
combinedTypeValidator = (data) => {
|
|
2351
|
+
if (typeof data !== "number" || !Number.isInteger(data)) {
|
|
2352
|
+
return defineTypeError("Invalid type", { data });
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
break;
|
|
2356
|
+
case "boolean":
|
|
2357
|
+
combinedTypeValidator = (data) => {
|
|
2358
|
+
if (typeof data !== "boolean") {
|
|
2359
|
+
return defineTypeError("Invalid type", { data });
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
break;
|
|
2363
|
+
case "null":
|
|
2364
|
+
combinedTypeValidator = (data) => {
|
|
2365
|
+
if (data !== null) {
|
|
2366
|
+
return defineTypeError("Invalid type", { data });
|
|
2367
|
+
}
|
|
2368
|
+
};
|
|
2369
|
+
break;
|
|
2370
|
+
default: {
|
|
2371
|
+
const singleTypeFn = typeFunctions[0];
|
|
2372
|
+
combinedTypeValidator = (data) => {
|
|
2373
|
+
if (!singleTypeFn(data)) {
|
|
2374
|
+
return defineTypeError("Invalid type", { data });
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
} else if (typeFunctions.length > 1 && allTypesDefault) {
|
|
2380
|
+
typeMethodName = defaultTypeNames.join("_OR_");
|
|
2381
|
+
const allowsObject = defaultTypeNames.includes("object");
|
|
2382
|
+
const allowsArray = defaultTypeNames.includes("array");
|
|
2383
|
+
const allowsString = defaultTypeNames.includes("string");
|
|
2384
|
+
const allowsNumber = defaultTypeNames.includes("number");
|
|
2385
|
+
const allowsInteger = defaultTypeNames.includes("integer");
|
|
2386
|
+
const allowsBoolean = defaultTypeNames.includes("boolean");
|
|
2387
|
+
const allowsNull = defaultTypeNames.includes("null");
|
|
2388
|
+
combinedTypeValidator = (data) => {
|
|
2389
|
+
const dataType = typeof data;
|
|
2390
|
+
if (dataType === "number") {
|
|
2391
|
+
if (allowsNumber || allowsInteger && Number.isInteger(data)) {
|
|
2392
|
+
return;
|
|
1163
2393
|
}
|
|
2394
|
+
return defineTypeError("Invalid type", { data });
|
|
1164
2395
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
2396
|
+
if (dataType === "string") {
|
|
2397
|
+
if (allowsString) {
|
|
2398
|
+
return;
|
|
2399
|
+
}
|
|
2400
|
+
return defineTypeError("Invalid type", { data });
|
|
2401
|
+
}
|
|
2402
|
+
if (dataType === "boolean") {
|
|
2403
|
+
if (allowsBoolean) {
|
|
2404
|
+
return;
|
|
2405
|
+
}
|
|
2406
|
+
return defineTypeError("Invalid type", { data });
|
|
2407
|
+
}
|
|
2408
|
+
if (dataType === "object") {
|
|
2409
|
+
if (data === null) {
|
|
2410
|
+
if (allowsNull) {
|
|
2411
|
+
return;
|
|
2412
|
+
}
|
|
2413
|
+
return defineTypeError("Invalid type", { data });
|
|
2414
|
+
}
|
|
2415
|
+
if (Array.isArray(data)) {
|
|
2416
|
+
if (allowsArray) {
|
|
1172
2417
|
return;
|
|
1173
2418
|
}
|
|
2419
|
+
return defineTypeError("Invalid type", { data });
|
|
2420
|
+
}
|
|
2421
|
+
if (allowsObject) {
|
|
2422
|
+
return;
|
|
1174
2423
|
}
|
|
1175
2424
|
return defineTypeError("Invalid type", { data });
|
|
1176
2425
|
}
|
|
1177
|
-
|
|
2426
|
+
return defineTypeError("Invalid type", { data });
|
|
2427
|
+
};
|
|
2428
|
+
} else if (typeFunctions.length === 1) {
|
|
2429
|
+
typeMethodName = typeNames[0];
|
|
2430
|
+
const singleTypeFn = typeFunctions[0];
|
|
2431
|
+
combinedTypeValidator = (data) => {
|
|
2432
|
+
if (!singleTypeFn(data)) {
|
|
2433
|
+
return defineTypeError("Invalid type", { data });
|
|
2434
|
+
}
|
|
2435
|
+
};
|
|
2436
|
+
} else {
|
|
2437
|
+
typeMethodName = typeNames.join("_OR_");
|
|
2438
|
+
combinedTypeValidator = (data) => {
|
|
2439
|
+
for (let i = 0; i < typeFunctions.length; i++) {
|
|
2440
|
+
if (typeFunctions[i](data)) {
|
|
2441
|
+
return;
|
|
2442
|
+
}
|
|
2443
|
+
}
|
|
2444
|
+
return defineTypeError("Invalid type", { data });
|
|
2445
|
+
};
|
|
1178
2446
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
2447
|
+
validators.push({
|
|
2448
|
+
name: typeMethodName,
|
|
2449
|
+
validate: getNamedFunction(typeMethodName, combinedTypeValidator)
|
|
2450
|
+
});
|
|
2451
|
+
activeNames.push(typeMethodName);
|
|
2452
|
+
}
|
|
2453
|
+
const { type, $id, $ref, $validate, required, ...otherKeys } = schema;
|
|
2454
|
+
const keyOrder = required ? this.hasRequiredDefaults(schema) ? [...Object.keys(otherKeys), "required"] : ["required", ...Object.keys(otherKeys)] : Object.keys(otherKeys);
|
|
2455
|
+
for (const key of keyOrder) {
|
|
2456
|
+
const keywordFn = this.getKeyword(key);
|
|
2457
|
+
if (!keywordFn) {
|
|
1183
2458
|
continue;
|
|
1184
2459
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
methodName = keywordValidator.name;
|
|
1208
|
-
compiledSchema.$validate = getNamedFunction(
|
|
1209
|
-
methodName,
|
|
1210
|
-
(data) => keywordValidator(
|
|
1211
|
-
compiledSchema,
|
|
1212
|
-
data,
|
|
1213
|
-
defineError,
|
|
1214
|
-
this
|
|
1215
|
-
)
|
|
1216
|
-
);
|
|
1217
|
-
}
|
|
2460
|
+
if (this.shouldSkipKeyword(schema, key)) {
|
|
2461
|
+
continue;
|
|
2462
|
+
}
|
|
2463
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2464
|
+
key,
|
|
2465
|
+
schema[key],
|
|
2466
|
+
this.failFast
|
|
2467
|
+
);
|
|
2468
|
+
const fnName = keywordFn.name || key;
|
|
2469
|
+
validators.push({
|
|
2470
|
+
name: fnName,
|
|
2471
|
+
validate: getNamedFunction(
|
|
2472
|
+
fnName,
|
|
2473
|
+
(data) => keywordFn(compiledSchema, data, defineError, this)
|
|
2474
|
+
)
|
|
2475
|
+
});
|
|
2476
|
+
activeNames.push(fnName);
|
|
2477
|
+
}
|
|
2478
|
+
const literalKeywords = ["enum", "const", "default", "examples"];
|
|
2479
|
+
for (const key of keyOrder) {
|
|
2480
|
+
if (literalKeywords.includes(key)) {
|
|
2481
|
+
continue;
|
|
1218
2482
|
}
|
|
1219
|
-
if (
|
|
2483
|
+
if (schema[key] && typeof schema[key] === "object" && !Array.isArray(schema[key])) {
|
|
1220
2484
|
if (key === "properties") {
|
|
1221
2485
|
for (const subKey of Object.keys(schema[key])) {
|
|
1222
|
-
|
|
2486
|
+
const compiledSubSchema2 = this.compileSchema(
|
|
1223
2487
|
schema[key][subKey]
|
|
1224
2488
|
);
|
|
2489
|
+
if (compiledSubSchema2._hasRef === true) {
|
|
2490
|
+
schemaHasRef = true;
|
|
2491
|
+
}
|
|
2492
|
+
compiledSchema[key][subKey] = compiledSubSchema2;
|
|
1225
2493
|
}
|
|
1226
2494
|
continue;
|
|
1227
2495
|
}
|
|
1228
|
-
|
|
2496
|
+
const compiledSubSchema = this.compileSchema(schema[key]);
|
|
2497
|
+
if (compiledSubSchema._hasRef === true) {
|
|
2498
|
+
schemaHasRef = true;
|
|
2499
|
+
}
|
|
2500
|
+
compiledSchema[key] = compiledSubSchema;
|
|
1229
2501
|
continue;
|
|
1230
2502
|
}
|
|
1231
2503
|
if (Array.isArray(schema[key])) {
|
|
1232
|
-
|
|
1233
|
-
(
|
|
1234
|
-
|
|
2504
|
+
for (let i = 0; i < schema[key].length; i++) {
|
|
2505
|
+
if (this.isSchemaLike(schema[key][i])) {
|
|
2506
|
+
const compiledSubSchema = this.compileSchema(schema[key][i]);
|
|
2507
|
+
if (compiledSubSchema._hasRef === true) {
|
|
2508
|
+
schemaHasRef = true;
|
|
2509
|
+
}
|
|
2510
|
+
compiledSchema[key][i] = compiledSubSchema;
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
1235
2513
|
continue;
|
|
1236
2514
|
}
|
|
1237
|
-
|
|
2515
|
+
}
|
|
2516
|
+
if (schemaHasRef) {
|
|
2517
|
+
this.markSchemaHasRef(compiledSchema);
|
|
2518
|
+
}
|
|
2519
|
+
if (validators.length === 0) {
|
|
2520
|
+
return compiledSchema;
|
|
2521
|
+
}
|
|
2522
|
+
if (validators.length === 1) {
|
|
2523
|
+
const v = validators[0];
|
|
2524
|
+
compiledSchema.$validate = getNamedFunction(v.name, v.validate);
|
|
2525
|
+
} else {
|
|
2526
|
+
const compositeName = "Validate_" + activeNames.join("_AND_");
|
|
2527
|
+
const masterValidator = (data) => {
|
|
2528
|
+
for (let i = 0; i < validators.length; i++) {
|
|
2529
|
+
const v = validators[i];
|
|
2530
|
+
const error = v.validate(data);
|
|
2531
|
+
if (error) {
|
|
2532
|
+
return error;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
return;
|
|
2536
|
+
};
|
|
2537
|
+
compiledSchema.$validate = getNamedFunction(
|
|
2538
|
+
compositeName,
|
|
2539
|
+
masterValidator
|
|
2540
|
+
);
|
|
1238
2541
|
}
|
|
1239
2542
|
return compiledSchema;
|
|
1240
2543
|
}
|
|
1241
2544
|
isSchemaLike(subSchema) {
|
|
1242
|
-
if (
|
|
2545
|
+
if (subSchema && typeof subSchema === "object" && !Array.isArray(subSchema)) {
|
|
1243
2546
|
if ("type" in subSchema) {
|
|
1244
2547
|
return true;
|
|
1245
2548
|
}
|
|
@@ -1251,9 +2554,59 @@ var SchemaShield = class {
|
|
|
1251
2554
|
}
|
|
1252
2555
|
return false;
|
|
1253
2556
|
}
|
|
2557
|
+
linkReferences(root) {
|
|
2558
|
+
const stack = [root];
|
|
2559
|
+
while (stack.length > 0) {
|
|
2560
|
+
const node = stack.pop();
|
|
2561
|
+
if (!node || typeof node !== "object")
|
|
2562
|
+
continue;
|
|
2563
|
+
if (typeof node.$ref === "string" && typeof node.$validate === "function" && node.$validate.name === "Validate_Reference") {
|
|
2564
|
+
const refPath = node.$ref;
|
|
2565
|
+
let target = this.getSchemaRef(refPath);
|
|
2566
|
+
if (typeof target === "undefined") {
|
|
2567
|
+
target = this.getSchemaById(refPath);
|
|
2568
|
+
}
|
|
2569
|
+
if (typeof target === "boolean") {
|
|
2570
|
+
if (target === true) {
|
|
2571
|
+
node.$validate = getNamedFunction("Validate_Ref_True", () => {
|
|
2572
|
+
});
|
|
2573
|
+
} else {
|
|
2574
|
+
const defineError = getDefinedErrorFunctionForKey(
|
|
2575
|
+
"$ref",
|
|
2576
|
+
node,
|
|
2577
|
+
this.failFast
|
|
2578
|
+
);
|
|
2579
|
+
node.$validate = getNamedFunction(
|
|
2580
|
+
"Validate_Ref_False",
|
|
2581
|
+
(_data) => defineError("Value is not valid")
|
|
2582
|
+
);
|
|
2583
|
+
}
|
|
2584
|
+
continue;
|
|
2585
|
+
}
|
|
2586
|
+
if (target && typeof target.$validate === "function") {
|
|
2587
|
+
node.$validate = target.$validate;
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
for (const key in node) {
|
|
2591
|
+
const value = node[key];
|
|
2592
|
+
if (!value)
|
|
2593
|
+
continue;
|
|
2594
|
+
if (Array.isArray(value)) {
|
|
2595
|
+
for (let i = 0; i < value.length; i++) {
|
|
2596
|
+
const v = value[i];
|
|
2597
|
+
if (v && typeof v === "object") {
|
|
2598
|
+
stack.push(v);
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
} else if (typeof value === "object") {
|
|
2602
|
+
stack.push(value);
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
1254
2607
|
};
|
|
1255
2608
|
export {
|
|
1256
2609
|
SchemaShield,
|
|
1257
2610
|
ValidationError,
|
|
1258
|
-
deepClone
|
|
2611
|
+
deepCloneUnfreeze as deepClone
|
|
1259
2612
|
};
|