z-schema 6.0.2 → 7.0.0-beta.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.
Files changed (47) hide show
  1. package/README.md +154 -134
  2. package/bin/z-schema +128 -124
  3. package/dist/Errors.js +50 -0
  4. package/dist/FormatValidators.js +136 -0
  5. package/{src → dist}/JsonValidation.js +184 -213
  6. package/dist/Report.js +220 -0
  7. package/{src → dist}/SchemaCache.js +67 -82
  8. package/{src → dist}/SchemaCompilation.js +89 -129
  9. package/dist/SchemaValidation.js +631 -0
  10. package/{src → dist}/Utils.js +96 -104
  11. package/dist/ZSchema-umd-min.js +1 -0
  12. package/dist/ZSchema-umd.js +13791 -0
  13. package/dist/ZSchema.cjs +13785 -0
  14. package/dist/ZSchema.js +366 -0
  15. package/dist/schemas/hyper-schema.json +156 -0
  16. package/dist/schemas/schema.json +151 -0
  17. package/dist/types/Errors.d.ts +44 -0
  18. package/dist/types/FormatValidators.d.ts +12 -0
  19. package/dist/types/JsonValidation.d.ts +37 -0
  20. package/dist/types/Report.d.ts +87 -0
  21. package/dist/types/SchemaCache.d.ts +26 -0
  22. package/dist/types/SchemaCompilation.d.ts +1 -0
  23. package/dist/types/SchemaValidation.d.ts +6 -0
  24. package/dist/types/Utils.d.ts +64 -0
  25. package/dist/types/ZSchema.d.ts +97 -0
  26. package/package.json +54 -43
  27. package/src/Errors.ts +56 -0
  28. package/src/FormatValidators.ts +136 -0
  29. package/src/JsonValidation.ts +624 -0
  30. package/src/Report.ts +337 -0
  31. package/src/SchemaCache.ts +189 -0
  32. package/src/SchemaCompilation.ts +293 -0
  33. package/src/SchemaValidation.ts +629 -0
  34. package/src/Utils.ts +286 -0
  35. package/src/ZSchema.ts +469 -0
  36. package/src/schemas/_ +0 -0
  37. package/dist/ZSchema-browser-min.js +0 -2
  38. package/dist/ZSchema-browser-min.js.map +0 -1
  39. package/dist/ZSchema-browser-test.js +0 -32247
  40. package/dist/ZSchema-browser.js +0 -12745
  41. package/index.d.ts +0 -175
  42. package/src/Errors.js +0 -60
  43. package/src/FormatValidators.js +0 -129
  44. package/src/Polyfills.js +0 -16
  45. package/src/Report.js +0 -299
  46. package/src/SchemaValidation.js +0 -619
  47. package/src/ZSchema.js +0 -409
@@ -0,0 +1,631 @@
1
+ import { FormatValidators } from './FormatValidators.js';
2
+ import * as JsonValidation from './JsonValidation.js';
3
+ import { Report } from './Report.js';
4
+ import * as Utils from './Utils.js';
5
+ const SchemaValidators = {
6
+ $ref: function (report, schema) {
7
+ // http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
8
+ // http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
9
+ if (typeof schema.$ref !== 'string') {
10
+ report.addError('KEYWORD_TYPE_EXPECTED', ['$ref', 'string']);
11
+ }
12
+ },
13
+ $schema: function (report, schema) {
14
+ // http://json-schema.org/latest/json-schema-core.html#rfc.section.6
15
+ if (typeof schema.$schema !== 'string') {
16
+ report.addError('KEYWORD_TYPE_EXPECTED', ['$schema', 'string']);
17
+ }
18
+ },
19
+ multipleOf: function (report, schema) {
20
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.1
21
+ if (typeof schema.multipleOf !== 'number') {
22
+ report.addError('KEYWORD_TYPE_EXPECTED', ['multipleOf', 'number']);
23
+ }
24
+ else if (schema.multipleOf <= 0) {
25
+ report.addError('KEYWORD_MUST_BE', ['multipleOf', 'strictly greater than 0']);
26
+ }
27
+ },
28
+ maximum: function (report, schema) {
29
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
30
+ if (typeof schema.maximum !== 'number') {
31
+ report.addError('KEYWORD_TYPE_EXPECTED', ['maximum', 'number']);
32
+ }
33
+ },
34
+ exclusiveMaximum: function (report, schema) {
35
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
36
+ if (typeof schema.exclusiveMaximum !== 'boolean') {
37
+ report.addError('KEYWORD_TYPE_EXPECTED', ['exclusiveMaximum', 'boolean']);
38
+ }
39
+ else if (schema.maximum === undefined) {
40
+ report.addError('KEYWORD_DEPENDENCY', ['exclusiveMaximum', 'maximum']);
41
+ }
42
+ },
43
+ minimum: function (report, schema) {
44
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.1
45
+ if (typeof schema.minimum !== 'number') {
46
+ report.addError('KEYWORD_TYPE_EXPECTED', ['minimum', 'number']);
47
+ }
48
+ },
49
+ exclusiveMinimum: function (report, schema) {
50
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.1
51
+ if (typeof schema.exclusiveMinimum !== 'boolean') {
52
+ report.addError('KEYWORD_TYPE_EXPECTED', ['exclusiveMinimum', 'boolean']);
53
+ }
54
+ else if (schema.minimum === undefined) {
55
+ report.addError('KEYWORD_DEPENDENCY', ['exclusiveMinimum', 'minimum']);
56
+ }
57
+ },
58
+ maxLength: function (report, schema) {
59
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.1.1
60
+ if (Utils.whatIs(schema.maxLength) !== 'integer') {
61
+ report.addError('KEYWORD_TYPE_EXPECTED', ['maxLength', 'integer']);
62
+ }
63
+ else if (schema.maxLength < 0) {
64
+ report.addError('KEYWORD_MUST_BE', ['maxLength', 'greater than, or equal to 0']);
65
+ }
66
+ },
67
+ minLength: function (report, schema) {
68
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.2.1
69
+ if (Utils.whatIs(schema.minLength) !== 'integer') {
70
+ report.addError('KEYWORD_TYPE_EXPECTED', ['minLength', 'integer']);
71
+ }
72
+ else if (schema.minLength < 0) {
73
+ report.addError('KEYWORD_MUST_BE', ['minLength', 'greater than, or equal to 0']);
74
+ }
75
+ },
76
+ pattern: function (report, schema) {
77
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.3.1
78
+ if (typeof schema.pattern !== 'string') {
79
+ report.addError('KEYWORD_TYPE_EXPECTED', ['pattern', 'string']);
80
+ }
81
+ else {
82
+ try {
83
+ RegExp(schema.pattern);
84
+ }
85
+ catch (_e) {
86
+ report.addError('KEYWORD_PATTERN', ['pattern', schema.pattern]);
87
+ }
88
+ }
89
+ },
90
+ additionalItems: function (report, schema) {
91
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.1
92
+ const type = Utils.whatIs(schema.additionalItems);
93
+ if (type !== 'boolean' && type !== 'object') {
94
+ report.addError('KEYWORD_TYPE_EXPECTED', ['additionalItems', ['boolean', 'object']]);
95
+ }
96
+ else if (type === 'object') {
97
+ report.path.push('additionalItems');
98
+ validateSchema.call(this, report, schema.additionalItems);
99
+ report.path.pop();
100
+ }
101
+ },
102
+ items: function (report, schema) {
103
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.1
104
+ const type = Utils.whatIs(schema.items);
105
+ if (type === 'object') {
106
+ report.path.push('items');
107
+ validateSchema.call(this, report, schema.items);
108
+ report.path.pop();
109
+ }
110
+ else if (type === 'array') {
111
+ let idx = schema.items.length;
112
+ while (idx--) {
113
+ report.path.push('items');
114
+ report.path.push(idx.toString());
115
+ validateSchema.call(this, report, schema.items[idx]);
116
+ report.path.pop();
117
+ report.path.pop();
118
+ }
119
+ }
120
+ else {
121
+ report.addError('KEYWORD_TYPE_EXPECTED', ['items', ['array', 'object']]);
122
+ }
123
+ // custom - strict mode
124
+ if (this.options.forceAdditional === true && schema.additionalItems === undefined && Array.isArray(schema.items)) {
125
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['additionalItems']);
126
+ }
127
+ // custome - assume defined false mode
128
+ if (this.options.assumeAdditional && schema.additionalItems === undefined && Array.isArray(schema.items)) {
129
+ schema.additionalItems = false;
130
+ }
131
+ },
132
+ maxItems: function (report, schema) {
133
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.2.1
134
+ if (typeof schema.maxItems !== 'number') {
135
+ report.addError('KEYWORD_TYPE_EXPECTED', ['maxItems', 'integer']);
136
+ }
137
+ else if (schema.maxItems < 0) {
138
+ report.addError('KEYWORD_MUST_BE', ['maxItems', 'greater than, or equal to 0']);
139
+ }
140
+ },
141
+ minItems: function (report, schema) {
142
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.3.1
143
+ if (Utils.whatIs(schema.minItems) !== 'integer') {
144
+ report.addError('KEYWORD_TYPE_EXPECTED', ['minItems', 'integer']);
145
+ }
146
+ else if (schema.minItems < 0) {
147
+ report.addError('KEYWORD_MUST_BE', ['minItems', 'greater than, or equal to 0']);
148
+ }
149
+ },
150
+ uniqueItems: function (report, schema) {
151
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.4.1
152
+ if (typeof schema.uniqueItems !== 'boolean') {
153
+ report.addError('KEYWORD_TYPE_EXPECTED', ['uniqueItems', 'boolean']);
154
+ }
155
+ },
156
+ maxProperties: function (report, schema) {
157
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.1.1
158
+ if (Utils.whatIs(schema.maxProperties) !== 'integer') {
159
+ report.addError('KEYWORD_TYPE_EXPECTED', ['maxProperties', 'integer']);
160
+ }
161
+ else if (schema.maxProperties < 0) {
162
+ report.addError('KEYWORD_MUST_BE', ['maxProperties', 'greater than, or equal to 0']);
163
+ }
164
+ },
165
+ minProperties: function (report, schema) {
166
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.2.1
167
+ if (Utils.whatIs(schema.minProperties) !== 'integer') {
168
+ report.addError('KEYWORD_TYPE_EXPECTED', ['minProperties', 'integer']);
169
+ }
170
+ else if (schema.minProperties < 0) {
171
+ report.addError('KEYWORD_MUST_BE', ['minProperties', 'greater than, or equal to 0']);
172
+ }
173
+ },
174
+ required: function (report, schema) {
175
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.3.1
176
+ if (Utils.whatIs(schema.required) !== 'array') {
177
+ report.addError('KEYWORD_TYPE_EXPECTED', ['required', 'array']);
178
+ }
179
+ else if (schema.required.length === 0) {
180
+ report.addError('KEYWORD_MUST_BE', ['required', 'an array with at least one element']);
181
+ }
182
+ else {
183
+ let idx = schema.required.length;
184
+ while (idx--) {
185
+ if (typeof schema.required[idx] !== 'string') {
186
+ report.addError('KEYWORD_VALUE_TYPE', ['required', 'string']);
187
+ }
188
+ }
189
+ if (Utils.isUniqueArray(schema.required) === false) {
190
+ report.addError('KEYWORD_MUST_BE', ['required', 'an array with unique items']);
191
+ }
192
+ }
193
+ },
194
+ additionalProperties: function (report, schema) {
195
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
196
+ const type = Utils.whatIs(schema.additionalProperties);
197
+ if (type !== 'boolean' && type !== 'object') {
198
+ report.addError('KEYWORD_TYPE_EXPECTED', ['additionalProperties', ['boolean', 'object']]);
199
+ }
200
+ else if (type === 'object') {
201
+ report.path.push('additionalProperties');
202
+ validateSchema.call(this, report, schema.additionalProperties);
203
+ report.path.pop();
204
+ }
205
+ },
206
+ properties: function (report, schema) {
207
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
208
+ if (Utils.whatIs(schema.properties) !== 'object') {
209
+ report.addError('KEYWORD_TYPE_EXPECTED', ['properties', 'object']);
210
+ return;
211
+ }
212
+ const keys = Object.keys(schema.properties);
213
+ let idx = keys.length;
214
+ while (idx--) {
215
+ const key = keys[idx], val = schema.properties[key];
216
+ report.path.push('properties');
217
+ report.path.push(key);
218
+ validateSchema.call(this, report, val);
219
+ report.path.pop();
220
+ report.path.pop();
221
+ }
222
+ // custom - strict mode
223
+ if (this.options.forceAdditional === true && schema.additionalProperties === undefined) {
224
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['additionalProperties']);
225
+ }
226
+ // custome - assume defined false mode
227
+ if (this.options.assumeAdditional && schema.additionalProperties === undefined) {
228
+ schema.additionalProperties = false;
229
+ }
230
+ // custom - forceProperties
231
+ if (this.options.forceProperties === true && keys.length === 0) {
232
+ report.addError('CUSTOM_MODE_FORCE_PROPERTIES', ['properties']);
233
+ }
234
+ },
235
+ patternProperties: function (report, schema) {
236
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
237
+ if (Utils.whatIs(schema.patternProperties) !== 'object') {
238
+ report.addError('KEYWORD_TYPE_EXPECTED', ['patternProperties', 'object']);
239
+ return;
240
+ }
241
+ const keys = Object.keys(schema.patternProperties);
242
+ let idx = keys.length;
243
+ while (idx--) {
244
+ const key = keys[idx], val = schema.patternProperties[key];
245
+ try {
246
+ RegExp(key);
247
+ }
248
+ catch (_e) {
249
+ report.addError('KEYWORD_PATTERN', ['patternProperties', key]);
250
+ }
251
+ report.path.push('patternProperties');
252
+ report.path.push(key.toString());
253
+ validateSchema.call(this, report, val);
254
+ report.path.pop();
255
+ report.path.pop();
256
+ }
257
+ // custom - forceProperties
258
+ if (this.options.forceProperties === true && keys.length === 0) {
259
+ report.addError('CUSTOM_MODE_FORCE_PROPERTIES', ['patternProperties']);
260
+ }
261
+ },
262
+ dependencies: function (report, schema) {
263
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.5.1
264
+ if (Utils.whatIs(schema.dependencies) !== 'object') {
265
+ report.addError('KEYWORD_TYPE_EXPECTED', ['dependencies', 'object']);
266
+ }
267
+ else {
268
+ const keys = Object.keys(schema.dependencies);
269
+ let idx = keys.length;
270
+ while (idx--) {
271
+ const schemaKey = keys[idx], schemaDependency = schema.dependencies[schemaKey], type = Utils.whatIs(schemaDependency);
272
+ if (type === 'object') {
273
+ report.path.push('dependencies');
274
+ report.path.push(schemaKey);
275
+ validateSchema.call(this, report, schemaDependency);
276
+ report.path.pop();
277
+ report.path.pop();
278
+ }
279
+ else if (type === 'array') {
280
+ let idx2 = schemaDependency.length;
281
+ if (idx2 === 0) {
282
+ report.addError('KEYWORD_MUST_BE', ['dependencies', 'not empty array']);
283
+ }
284
+ while (idx2--) {
285
+ if (typeof schemaDependency[idx2] !== 'string') {
286
+ report.addError('KEYWORD_VALUE_TYPE', ['dependensices', 'string']);
287
+ }
288
+ }
289
+ if (Utils.isUniqueArray(schemaDependency) === false) {
290
+ report.addError('KEYWORD_MUST_BE', ['dependencies', 'an array with unique items']);
291
+ }
292
+ }
293
+ else {
294
+ report.addError('KEYWORD_VALUE_TYPE', ['dependencies', 'object or array']);
295
+ }
296
+ }
297
+ }
298
+ },
299
+ enum: function (report, schema) {
300
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.1.1
301
+ if (Array.isArray(schema.enum) === false) {
302
+ report.addError('KEYWORD_TYPE_EXPECTED', ['enum', 'array']);
303
+ }
304
+ else if (schema.enum.length === 0) {
305
+ report.addError('KEYWORD_MUST_BE', ['enum', 'an array with at least one element']);
306
+ }
307
+ else if (Utils.isUniqueArray(schema.enum) === false) {
308
+ report.addError('KEYWORD_MUST_BE', ['enum', 'an array with unique elements']);
309
+ }
310
+ },
311
+ type: function (report, schema) {
312
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.1
313
+ const primitiveTypes = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string'], primitiveTypeStr = primitiveTypes.join(','), isArray = Array.isArray(schema.type);
314
+ if (isArray) {
315
+ let idx = schema.type.length;
316
+ while (idx--) {
317
+ if (primitiveTypes.indexOf(schema.type[idx]) === -1) {
318
+ report.addError('KEYWORD_TYPE_EXPECTED', ['type', primitiveTypeStr]);
319
+ }
320
+ }
321
+ if (Utils.isUniqueArray(schema.type) === false) {
322
+ report.addError('KEYWORD_MUST_BE', ['type', 'an object with unique properties']);
323
+ }
324
+ }
325
+ else if (typeof schema.type === 'string') {
326
+ if (primitiveTypes.indexOf(schema.type) === -1) {
327
+ report.addError('KEYWORD_TYPE_EXPECTED', ['type', primitiveTypeStr]);
328
+ }
329
+ }
330
+ else {
331
+ report.addError('KEYWORD_TYPE_EXPECTED', ['type', ['string', 'array']]);
332
+ }
333
+ if (this.options.noEmptyStrings === true) {
334
+ if (schema.type === 'string' || (isArray && schema.type.indexOf('string') !== -1)) {
335
+ if (schema.minLength === undefined && schema.enum === undefined && schema.format === undefined) {
336
+ schema.minLength = 1;
337
+ }
338
+ }
339
+ }
340
+ if (this.options.noEmptyArrays === true) {
341
+ if (schema.type === 'array' || (isArray && schema.type.indexOf('array') !== -1)) {
342
+ if (schema.minItems === undefined) {
343
+ schema.minItems = 1;
344
+ }
345
+ }
346
+ }
347
+ if (this.options.forceProperties === true) {
348
+ if (schema.type === 'object' || (isArray && schema.type.indexOf('object') !== -1)) {
349
+ if (schema.properties === undefined && schema.patternProperties === undefined) {
350
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['properties']);
351
+ }
352
+ }
353
+ }
354
+ if (this.options.forceItems === true) {
355
+ if (schema.type === 'array' || (isArray && schema.type.indexOf('array') !== -1)) {
356
+ if (schema.items === undefined) {
357
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['items']);
358
+ }
359
+ }
360
+ }
361
+ if (this.options.forceMinItems === true) {
362
+ if (schema.type === 'array' || (isArray && schema.type.indexOf('array') !== -1)) {
363
+ if (schema.minItems === undefined) {
364
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['minItems']);
365
+ }
366
+ }
367
+ }
368
+ if (this.options.forceMaxItems === true) {
369
+ if (schema.type === 'array' || (isArray && schema.type.indexOf('array') !== -1)) {
370
+ if (schema.maxItems === undefined) {
371
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['maxItems']);
372
+ }
373
+ }
374
+ }
375
+ if (this.options.forceMinLength === true) {
376
+ if (schema.type === 'string' || (isArray && schema.type.indexOf('string') !== -1)) {
377
+ if (schema.minLength === undefined &&
378
+ schema.format === undefined &&
379
+ schema.enum === undefined &&
380
+ schema.pattern === undefined) {
381
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['minLength']);
382
+ }
383
+ }
384
+ }
385
+ if (this.options.forceMaxLength === true) {
386
+ if (schema.type === 'string' || (isArray && schema.type.indexOf('string') !== -1)) {
387
+ if (schema.maxLength === undefined &&
388
+ schema.format === undefined &&
389
+ schema.enum === undefined &&
390
+ schema.pattern === undefined) {
391
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['maxLength']);
392
+ }
393
+ }
394
+ }
395
+ },
396
+ allOf: function (report, schema) {
397
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.3.1
398
+ if (Array.isArray(schema.allOf) === false) {
399
+ report.addError('KEYWORD_TYPE_EXPECTED', ['allOf', 'array']);
400
+ }
401
+ else if (schema.allOf.length === 0) {
402
+ report.addError('KEYWORD_MUST_BE', ['allOf', 'an array with at least one element']);
403
+ }
404
+ else {
405
+ let idx = schema.allOf.length;
406
+ while (idx--) {
407
+ report.path.push('allOf');
408
+ report.path.push(idx.toString());
409
+ validateSchema.call(this, report, schema.allOf[idx]);
410
+ report.path.pop();
411
+ report.path.pop();
412
+ }
413
+ }
414
+ },
415
+ anyOf: function (report, schema) {
416
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.4.1
417
+ if (Array.isArray(schema.anyOf) === false) {
418
+ report.addError('KEYWORD_TYPE_EXPECTED', ['anyOf', 'array']);
419
+ }
420
+ else if (schema.anyOf.length === 0) {
421
+ report.addError('KEYWORD_MUST_BE', ['anyOf', 'an array with at least one element']);
422
+ }
423
+ else {
424
+ let idx = schema.anyOf.length;
425
+ while (idx--) {
426
+ report.path.push('anyOf');
427
+ report.path.push(idx.toString());
428
+ validateSchema.call(this, report, schema.anyOf[idx]);
429
+ report.path.pop();
430
+ report.path.pop();
431
+ }
432
+ }
433
+ },
434
+ oneOf: function (report, schema) {
435
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.5.1
436
+ if (Array.isArray(schema.oneOf) === false) {
437
+ report.addError('KEYWORD_TYPE_EXPECTED', ['oneOf', 'array']);
438
+ }
439
+ else if (schema.oneOf.length === 0) {
440
+ report.addError('KEYWORD_MUST_BE', ['oneOf', 'an array with at least one element']);
441
+ }
442
+ else {
443
+ let idx = schema.oneOf.length;
444
+ while (idx--) {
445
+ report.path.push('oneOf');
446
+ report.path.push(idx.toString());
447
+ validateSchema.call(this, report, schema.oneOf[idx]);
448
+ report.path.pop();
449
+ report.path.pop();
450
+ }
451
+ }
452
+ },
453
+ not: function (report, schema) {
454
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.1
455
+ if (Utils.whatIs(schema.not) !== 'object') {
456
+ report.addError('KEYWORD_TYPE_EXPECTED', ['not', 'object']);
457
+ }
458
+ else {
459
+ report.path.push('not');
460
+ validateSchema.call(this, report, schema.not);
461
+ report.path.pop();
462
+ }
463
+ },
464
+ definitions: function (report, schema) {
465
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.1
466
+ if (Utils.whatIs(schema.definitions) !== 'object') {
467
+ report.addError('KEYWORD_TYPE_EXPECTED', ['definitions', 'object']);
468
+ }
469
+ else {
470
+ const keys = Object.keys(schema.definitions);
471
+ let idx = keys.length;
472
+ while (idx--) {
473
+ const key = keys[idx], val = schema.definitions[key];
474
+ report.path.push('definitions');
475
+ report.path.push(key);
476
+ validateSchema.call(this, report, val);
477
+ report.path.pop();
478
+ report.path.pop();
479
+ }
480
+ }
481
+ },
482
+ format: function (report, schema) {
483
+ if (typeof schema.format !== 'string') {
484
+ report.addError('KEYWORD_TYPE_EXPECTED', ['format', 'string']);
485
+ }
486
+ else {
487
+ if (FormatValidators[schema.format] === undefined && this.options.ignoreUnknownFormats !== true) {
488
+ report.addError('UNKNOWN_FORMAT', [schema.format]);
489
+ }
490
+ }
491
+ },
492
+ id: function (report, schema) {
493
+ // http://json-schema.org/latest/json-schema-core.html#rfc.section.7.2
494
+ if (typeof schema.id !== 'string') {
495
+ report.addError('KEYWORD_TYPE_EXPECTED', ['id', 'string']);
496
+ }
497
+ },
498
+ title: function (report, schema) {
499
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1
500
+ if (typeof schema.title !== 'string') {
501
+ report.addError('KEYWORD_TYPE_EXPECTED', ['title', 'string']);
502
+ }
503
+ },
504
+ description: function (report, schema) {
505
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1
506
+ if (typeof schema.description !== 'string') {
507
+ report.addError('KEYWORD_TYPE_EXPECTED', ['description', 'string']);
508
+ }
509
+ },
510
+ default: function ( /* report, schema */) {
511
+ // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.2
512
+ // There are no restrictions placed on the value of this keyword.
513
+ },
514
+ };
515
+ /**
516
+ *
517
+ * @param {Report} report
518
+ * @param {*[]} arr
519
+ *
520
+ * @returns {boolean}
521
+ */
522
+ const validateArrayOfSchemas = function (report, arr) {
523
+ let idx = arr.length;
524
+ while (idx--) {
525
+ validateSchema.call(this, report, arr[idx]);
526
+ }
527
+ return report.isValid();
528
+ };
529
+ /**
530
+ *
531
+ * @param {Report} report
532
+ * @param {*} schema
533
+ */
534
+ export function validateSchema(report, schema) {
535
+ report.commonErrorMessage = 'SCHEMA_VALIDATION_FAILED';
536
+ // if schema is an array, assume it's an array of schemas
537
+ if (Array.isArray(schema)) {
538
+ return validateArrayOfSchemas.call(this, report, schema);
539
+ }
540
+ // do not revalidate schema that has already been validated once
541
+ if (schema.__$validated) {
542
+ return true;
543
+ }
544
+ // if $schema is present, this schema should validate against that $schema
545
+ const hasParentSchema = schema.$schema && schema.id !== schema.$schema;
546
+ if (hasParentSchema) {
547
+ if (schema.__$schemaResolved && schema.__$schemaResolved !== schema) {
548
+ const subReport = new Report(report);
549
+ const valid = JsonValidation.validate.call(this, subReport, schema.__$schemaResolved, schema);
550
+ if (valid === false) {
551
+ report.addError('PARENT_SCHEMA_VALIDATION_FAILED', null, subReport);
552
+ }
553
+ }
554
+ else {
555
+ if (this.options.ignoreUnresolvableReferences !== true) {
556
+ report.addError('REF_UNRESOLVED', [schema.$schema]);
557
+ }
558
+ }
559
+ }
560
+ if (this.options.noTypeless === true) {
561
+ // issue #36 - inherit type to anyOf, oneOf, allOf if noTypeless is defined
562
+ if (schema.type !== undefined) {
563
+ let schemas = [];
564
+ if (Array.isArray(schema.anyOf)) {
565
+ schemas = schemas.concat(schema.anyOf);
566
+ }
567
+ if (Array.isArray(schema.oneOf)) {
568
+ schemas = schemas.concat(schema.oneOf);
569
+ }
570
+ if (Array.isArray(schema.allOf)) {
571
+ schemas = schemas.concat(schema.allOf);
572
+ }
573
+ schemas.forEach(function (sch) {
574
+ if (!sch.type) {
575
+ sch.type = schema.type;
576
+ }
577
+ });
578
+ }
579
+ // end issue #36
580
+ if (schema.enum === undefined &&
581
+ schema.type === undefined &&
582
+ schema.anyOf === undefined &&
583
+ schema.oneOf === undefined &&
584
+ schema.not === undefined &&
585
+ schema.$ref === undefined) {
586
+ report.addError('KEYWORD_UNDEFINED_STRICT', ['type']);
587
+ }
588
+ }
589
+ const keys = Object.keys(schema);
590
+ let idx = keys.length;
591
+ while (idx--) {
592
+ const key = keys[idx];
593
+ if (key.indexOf('__') === 0) {
594
+ continue;
595
+ }
596
+ if (SchemaValidators[key] !== undefined) {
597
+ SchemaValidators[key].call(this, report, schema);
598
+ }
599
+ else if (!hasParentSchema) {
600
+ if (this.options.noExtraKeywords === true) {
601
+ report.addError('KEYWORD_UNEXPECTED', [key]);
602
+ }
603
+ }
604
+ }
605
+ if (this.options.pedanticCheck === true) {
606
+ if (schema.enum) {
607
+ // break recursion
608
+ const tmpSchema = Utils.clone(schema);
609
+ delete tmpSchema.enum;
610
+ delete tmpSchema.default;
611
+ report.path.push('enum');
612
+ idx = schema.enum.length;
613
+ while (idx--) {
614
+ report.path.push(idx.toString());
615
+ JsonValidation.validate.call(this, report, tmpSchema, schema.enum[idx]);
616
+ report.path.pop();
617
+ }
618
+ report.path.pop();
619
+ }
620
+ if (schema.default) {
621
+ report.path.push('default');
622
+ JsonValidation.validate.call(this, report, schema, schema.default);
623
+ report.path.pop();
624
+ }
625
+ }
626
+ const isValid = report.isValid();
627
+ if (isValid) {
628
+ schema.__$validated = true;
629
+ }
630
+ return isValid;
631
+ }