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