z-schema 7.0.0 → 7.0.6

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 (76) hide show
  1. package/README.md +7 -11
  2. package/bin/z-schema +0 -0
  3. package/cjs/index.d.ts +192 -117
  4. package/cjs/index.js +949 -998
  5. package/{src/FormatValidators.ts → dist/format-validators.js} +97 -65
  6. package/dist/index.js +1 -1
  7. package/dist/json-schema.js +40 -0
  8. package/dist/{JsonValidation.js → json-validation.js} +75 -69
  9. package/dist/{Report.js → report.js} +35 -45
  10. package/dist/schema-cache.js +109 -0
  11. package/dist/schema-compiler.js +255 -0
  12. package/dist/{SchemaValidation.js → schema-validator.js} +153 -149
  13. package/dist/types/{Errors.d.ts → errors.d.ts} +2 -0
  14. package/dist/types/format-validators.d.ts +10 -0
  15. package/dist/types/index.d.ts +10 -1
  16. package/dist/types/json-schema.d.ts +50 -0
  17. package/dist/types/json-validation.d.ts +7 -0
  18. package/dist/types/{Report.d.ts → report.d.ts} +22 -23
  19. package/dist/types/schema-cache.d.ts +17 -0
  20. package/dist/types/schema-compiler.d.ts +16 -0
  21. package/dist/types/schema-validator.d.ts +10 -0
  22. package/dist/types/utils/array.d.ts +2 -0
  23. package/dist/types/utils/clone.d.ts +2 -0
  24. package/dist/types/utils/json.d.ts +7 -0
  25. package/dist/types/utils/symbols.d.ts +2 -0
  26. package/dist/types/utils/unicode.d.ts +14 -0
  27. package/dist/types/utils/uri.d.ts +4 -0
  28. package/dist/types/utils/what-is.d.ts +3 -0
  29. package/dist/types/z-schema.d.ts +75 -0
  30. package/dist/utils/array.js +27 -0
  31. package/dist/utils/clone.js +61 -0
  32. package/dist/utils/json.js +59 -0
  33. package/dist/utils/symbols.js +2 -0
  34. package/dist/utils/unicode.js +45 -0
  35. package/dist/utils/uri.js +15 -0
  36. package/dist/utils/what-is.js +29 -0
  37. package/dist/{ZSchema.js → z-schema.js} +66 -77
  38. package/package.json +8 -4
  39. package/src/{Errors.ts → errors.ts} +4 -0
  40. package/src/format-validators.ts +191 -0
  41. package/src/index.ts +12 -1
  42. package/src/json-schema.ts +97 -0
  43. package/src/{JsonValidation.ts → json-validation.ts} +137 -127
  44. package/src/{Report.ts → report.ts} +60 -70
  45. package/src/schema-cache.ts +122 -0
  46. package/src/schema-compiler.ts +300 -0
  47. package/src/{SchemaValidation.ts → schema-validator.ts} +213 -215
  48. package/src/utils/array.ts +29 -0
  49. package/src/utils/clone.ts +63 -0
  50. package/src/utils/json.ts +74 -0
  51. package/src/utils/symbols.ts +3 -0
  52. package/src/utils/unicode.ts +43 -0
  53. package/src/utils/uri.ts +18 -0
  54. package/src/utils/what-is.ts +46 -0
  55. package/src/{ZSchema.ts → z-schema.ts} +108 -113
  56. package/umd/ZSchema.js +949 -998
  57. package/umd/ZSchema.min.js +1 -1
  58. package/dist/FormatValidators.js +0 -136
  59. package/dist/SchemaCache.js +0 -173
  60. package/dist/SchemaCompilation.js +0 -259
  61. package/dist/Utils.js +0 -266
  62. package/dist/types/FormatValidators.d.ts +0 -12
  63. package/dist/types/JsonValidation.d.ts +0 -37
  64. package/dist/types/SchemaCache.d.ts +0 -26
  65. package/dist/types/SchemaCompilation.d.ts +0 -1
  66. package/dist/types/SchemaValidation.d.ts +0 -6
  67. package/dist/types/Utils.d.ts +0 -64
  68. package/dist/types/ZSchema.d.ts +0 -97
  69. package/src/SchemaCache.ts +0 -189
  70. package/src/SchemaCompilation.ts +0 -293
  71. package/src/Utils.ts +0 -286
  72. /package/dist/{Errors.js → errors.js} +0 -0
  73. /package/dist/schemas/{hyper-schema.json → draft-04-hyper-schema.json} +0 -0
  74. /package/dist/schemas/{schema.json → draft-04-schema.json} +0 -0
  75. /package/src/schemas/{hyper-schema.json → draft-04-hyper-schema.json} +0 -0
  76. /package/src/schemas/{schema.json → draft-04-schema.json} +0 -0
@@ -1,6 +1,10 @@
1
- import { FormatValidators } from './FormatValidators.js';
2
- import { Report } from './Report.js';
3
- import * as Utils from './Utils.js';
1
+ import { Report } from './report.js';
2
+ import { isObject, whatIs } from './utils/what-is.js';
3
+ import { ucs2decode } from './utils/unicode.js';
4
+ import { difference, isUniqueArray } from './utils/array.js';
5
+ import { areEqual } from './utils/json.js';
6
+ import { shallowClone } from './utils/clone.js';
7
+ import { getFormatValidators } from './format-validators.js';
4
8
  const shouldSkipValidate = function (options, errors) {
5
9
  return (options &&
6
10
  Array.isArray(options.includeErrors) &&
@@ -10,6 +14,12 @@ const shouldSkipValidate = function (options, errors) {
10
14
  }));
11
15
  };
12
16
  export const JsonValidators = {
17
+ id: () => { },
18
+ $ref: () => { },
19
+ $schema: () => { },
20
+ title: () => { },
21
+ description: () => { },
22
+ default: () => { },
13
23
  multipleOf: function (report, schema, json) {
14
24
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.2
15
25
  if (shouldSkipValidate(this.validateOptions, ['MULTIPLE_OF'])) {
@@ -20,8 +30,8 @@ export const JsonValidators = {
20
30
  }
21
31
  const stringMultipleOf = String(schema.multipleOf);
22
32
  const scale = Math.pow(10, stringMultipleOf.length - stringMultipleOf.indexOf('.') - 1);
23
- if (Utils.whatIs((json * scale) / (schema.multipleOf * scale)) !== 'integer') {
24
- report.addError('MULTIPLE_OF', [json, schema.multipleOf], null, schema);
33
+ if (whatIs((json * scale) / (schema.multipleOf * scale)) !== 'integer') {
34
+ report.addError('MULTIPLE_OF', [json, schema.multipleOf], undefined, schema);
25
35
  }
26
36
  },
27
37
  maximum: function (report, schema, json) {
@@ -34,12 +44,12 @@ export const JsonValidators = {
34
44
  }
35
45
  if (schema.exclusiveMaximum !== true) {
36
46
  if (json > schema.maximum) {
37
- report.addError('MAXIMUM', [json, schema.maximum], null, schema);
47
+ report.addError('MAXIMUM', [json, schema.maximum], undefined, schema);
38
48
  }
39
49
  }
40
50
  else {
41
51
  if (json >= schema.maximum) {
42
- report.addError('MAXIMUM_EXCLUSIVE', [json, schema.maximum], null, schema);
52
+ report.addError('MAXIMUM_EXCLUSIVE', [json, schema.maximum], undefined, schema);
43
53
  }
44
54
  }
45
55
  },
@@ -56,12 +66,12 @@ export const JsonValidators = {
56
66
  }
57
67
  if (schema.exclusiveMinimum !== true) {
58
68
  if (json < schema.minimum) {
59
- report.addError('MINIMUM', [json, schema.minimum], null, schema);
69
+ report.addError('MINIMUM', [json, schema.minimum], undefined, schema);
60
70
  }
61
71
  }
62
72
  else {
63
73
  if (json <= schema.minimum) {
64
- report.addError('MINIMUM_EXCLUSIVE', [json, schema.minimum], null, schema);
74
+ report.addError('MINIMUM_EXCLUSIVE', [json, schema.minimum], undefined, schema);
65
75
  }
66
76
  }
67
77
  },
@@ -76,8 +86,8 @@ export const JsonValidators = {
76
86
  if (typeof json !== 'string') {
77
87
  return;
78
88
  }
79
- if (Utils.ucs2decode(json).length > schema.maxLength) {
80
- report.addError('MAX_LENGTH', [json.length, schema.maxLength], null, schema);
89
+ if (ucs2decode(json).length > schema.maxLength) {
90
+ report.addError('MAX_LENGTH', [json.length, schema.maxLength], undefined, schema);
81
91
  }
82
92
  },
83
93
  minLength: function (report, schema, json) {
@@ -88,8 +98,8 @@ export const JsonValidators = {
88
98
  if (typeof json !== 'string') {
89
99
  return;
90
100
  }
91
- if (Utils.ucs2decode(json).length < schema.minLength) {
92
- report.addError('MIN_LENGTH', [json.length, schema.minLength], null, schema);
101
+ if (ucs2decode(json).length < schema.minLength) {
102
+ report.addError('MIN_LENGTH', [json.length, schema.minLength], undefined, schema);
93
103
  }
94
104
  },
95
105
  pattern: function (report, schema, json) {
@@ -101,7 +111,7 @@ export const JsonValidators = {
101
111
  return;
102
112
  }
103
113
  if (RegExp(schema.pattern).test(json) === false) {
104
- report.addError('PATTERN', [schema.pattern, json], null, schema);
114
+ report.addError('PATTERN', [schema.pattern, json], undefined, schema);
105
115
  }
106
116
  },
107
117
  additionalItems: function (report, schema, json) {
@@ -116,12 +126,12 @@ export const JsonValidators = {
116
126
  // the json is valid if its size is less than, or equal to, the size of "items".
117
127
  if (schema.additionalItems === false && Array.isArray(schema.items)) {
118
128
  if (json.length > schema.items.length) {
119
- report.addError('ARRAY_ADDITIONAL_ITEMS', null, null, schema);
129
+ report.addError('ARRAY_ADDITIONAL_ITEMS', undefined, undefined, schema);
120
130
  }
121
131
  }
122
132
  },
123
133
  items: function () {
124
- /*report, schema, json*/
134
+ /*report: Report, schema: JsonSchemaInternal, json: unknown*/
125
135
  // covered in additionalItems
126
136
  },
127
137
  maxItems: function (report, schema, json) {
@@ -133,7 +143,7 @@ export const JsonValidators = {
133
143
  return;
134
144
  }
135
145
  if (json.length > schema.maxItems) {
136
- report.addError('ARRAY_LENGTH_LONG', [json.length, schema.maxItems], null, schema);
146
+ report.addError('ARRAY_LENGTH_LONG', [json.length, schema.maxItems], undefined, schema);
137
147
  }
138
148
  },
139
149
  minItems: function (report, schema, json) {
@@ -145,7 +155,7 @@ export const JsonValidators = {
145
155
  return;
146
156
  }
147
157
  if (json.length < schema.minItems) {
148
- report.addError('ARRAY_LENGTH_SHORT', [json.length, schema.minItems], null, schema);
158
+ report.addError('ARRAY_LENGTH_SHORT', [json.length, schema.minItems], undefined, schema);
149
159
  }
150
160
  },
151
161
  uniqueItems: function (report, schema, json) {
@@ -158,8 +168,8 @@ export const JsonValidators = {
158
168
  }
159
169
  if (schema.uniqueItems === true) {
160
170
  const matches = [];
161
- if (Utils.isUniqueArray(json, matches) === false) {
162
- report.addError('ARRAY_UNIQUE', matches, null, schema);
171
+ if (isUniqueArray(json, matches) === false) {
172
+ report.addError('ARRAY_UNIQUE', matches, undefined, schema);
163
173
  }
164
174
  }
165
175
  },
@@ -168,12 +178,12 @@ export const JsonValidators = {
168
178
  if (shouldSkipValidate(this.validateOptions, ['OBJECT_PROPERTIES_MAXIMUM'])) {
169
179
  return;
170
180
  }
171
- if (Utils.whatIs(json) !== 'object') {
181
+ if (!isObject(json)) {
172
182
  return;
173
183
  }
174
184
  const keysCount = Object.keys(json).length;
175
185
  if (keysCount > schema.maxProperties) {
176
- report.addError('OBJECT_PROPERTIES_MAXIMUM', [keysCount, schema.maxProperties], null, schema);
186
+ report.addError('OBJECT_PROPERTIES_MAXIMUM', [keysCount, schema.maxProperties], undefined, schema);
177
187
  }
178
188
  },
179
189
  minProperties: function (report, schema, json) {
@@ -181,12 +191,12 @@ export const JsonValidators = {
181
191
  if (shouldSkipValidate(this.validateOptions, ['OBJECT_PROPERTIES_MINIMUM'])) {
182
192
  return;
183
193
  }
184
- if (Utils.whatIs(json) !== 'object') {
194
+ if (!isObject(json)) {
185
195
  return;
186
196
  }
187
197
  const keysCount = Object.keys(json).length;
188
198
  if (keysCount < schema.minProperties) {
189
- report.addError('OBJECT_PROPERTIES_MINIMUM', [keysCount, schema.minProperties], null, schema);
199
+ report.addError('OBJECT_PROPERTIES_MINIMUM', [keysCount, schema.minProperties], undefined, schema);
190
200
  }
191
201
  },
192
202
  required: function (report, schema, json) {
@@ -194,14 +204,14 @@ export const JsonValidators = {
194
204
  if (shouldSkipValidate(this.validateOptions, ['OBJECT_MISSING_REQUIRED_PROPERTY'])) {
195
205
  return;
196
206
  }
197
- if (Utils.whatIs(json) !== 'object') {
207
+ if (!isObject(json)) {
198
208
  return;
199
209
  }
200
210
  let idx = schema.required.length;
201
211
  while (idx--) {
202
212
  const requiredPropertyName = schema.required[idx];
203
213
  if (json[requiredPropertyName] === undefined) {
204
- report.addError('OBJECT_MISSING_REQUIRED_PROPERTY', [requiredPropertyName], null, schema);
214
+ report.addError('OBJECT_MISSING_REQUIRED_PROPERTY', [requiredPropertyName], undefined, schema);
205
215
  }
206
216
  }
207
217
  },
@@ -222,7 +232,7 @@ export const JsonValidators = {
222
232
  if (shouldSkipValidate(this.validateOptions, ['OBJECT_ADDITIONAL_PROPERTIES'])) {
223
233
  return;
224
234
  }
225
- if (Utils.whatIs(json) !== 'object') {
235
+ if (!isObject(json)) {
226
236
  return;
227
237
  }
228
238
  const properties = schema.properties !== undefined ? schema.properties : {};
@@ -235,7 +245,7 @@ export const JsonValidators = {
235
245
  // The property set from "patternProperties".
236
246
  const pp = Object.keys(patternProperties);
237
247
  // remove from "s" all elements of "p", if any;
238
- s = Utils.difference(s, p);
248
+ s = difference(s, p);
239
249
  // for each regex in "pp", remove all elements of "s" which this regex matches.
240
250
  let idx = pp.length;
241
251
  while (idx--) {
@@ -250,19 +260,21 @@ export const JsonValidators = {
250
260
  // Validation of the json succeeds if, after these two steps, set "s" is empty.
251
261
  if (s.length > 0) {
252
262
  // assumeAdditional can be an array of allowed properties
253
- let idx3 = this.options.assumeAdditional.length;
254
- if (idx3) {
255
- while (idx3--) {
256
- const io = s.indexOf(this.options.assumeAdditional[idx3]);
257
- if (io !== -1) {
258
- s.splice(io, 1);
263
+ if (Array.isArray(this.options.assumeAdditional)) {
264
+ let idx3 = this.options.assumeAdditional.length;
265
+ if (idx3) {
266
+ while (idx3--) {
267
+ const io = s.indexOf(this.options.assumeAdditional[idx3]);
268
+ if (io !== -1) {
269
+ s.splice(io, 1);
270
+ }
259
271
  }
260
272
  }
261
273
  }
262
274
  let idx4 = s.length;
263
275
  if (idx4) {
264
276
  while (idx4--) {
265
- report.addError('OBJECT_ADDITIONAL_PROPERTIES', [s[idx4]], null, schema);
277
+ report.addError('OBJECT_ADDITIONAL_PROPERTIES', [s[idx4]], undefined, schema);
266
278
  }
267
279
  }
268
280
  }
@@ -273,7 +285,7 @@ export const JsonValidators = {
273
285
  if (shouldSkipValidate(this.validateOptions, ['OBJECT_DEPENDENCY_KEY'])) {
274
286
  return;
275
287
  }
276
- if (Utils.whatIs(json) !== 'object') {
288
+ if (!isObject(json)) {
277
289
  return;
278
290
  }
279
291
  const keys = Object.keys(schema.dependencies);
@@ -283,21 +295,21 @@ export const JsonValidators = {
283
295
  const dependencyName = keys[idx];
284
296
  if (json[dependencyName]) {
285
297
  const dependencyDefinition = schema.dependencies[dependencyName];
286
- if (Utils.whatIs(dependencyDefinition) === 'object') {
287
- // if dependency is a schema, validate against this schema
288
- validate.call(this, report, dependencyDefinition, json);
289
- }
290
- else {
298
+ if (Array.isArray(dependencyDefinition)) {
291
299
  // Array
292
300
  // if dependency is an array, object needs to have all properties in this array
293
301
  let idx2 = dependencyDefinition.length;
294
302
  while (idx2--) {
295
303
  const requiredPropertyName = dependencyDefinition[idx2];
296
304
  if (json[requiredPropertyName] === undefined) {
297
- report.addError('OBJECT_DEPENDENCY_KEY', [requiredPropertyName, dependencyName], null, schema);
305
+ report.addError('OBJECT_DEPENDENCY_KEY', [requiredPropertyName, dependencyName], undefined, schema);
298
306
  }
299
307
  }
300
308
  }
309
+ else {
310
+ // if dependency is a schema, validate against this schema
311
+ validate.call(this, report, dependencyDefinition, json);
312
+ }
301
313
  }
302
314
  }
303
315
  },
@@ -308,17 +320,17 @@ export const JsonValidators = {
308
320
  }
309
321
  let match = false, caseInsensitiveMatch = false, idx = schema.enum.length;
310
322
  while (idx--) {
311
- if (Utils.areEqual(json, schema.enum[idx])) {
323
+ if (areEqual(json, schema.enum[idx])) {
312
324
  match = true;
313
325
  break;
314
326
  }
315
- else if (Utils.areEqual(json, schema.enum[idx], { caseInsensitiveComparison: true })) {
327
+ else if (areEqual(json, schema.enum[idx], { caseInsensitiveComparison: true })) {
316
328
  caseInsensitiveMatch = true;
317
329
  }
318
330
  }
319
331
  if (match === false) {
320
332
  const error = caseInsensitiveMatch && this.options.enumCaseInsensitiveComparison ? 'ENUM_CASE_MISMATCH' : 'ENUM_MISMATCH';
321
- report.addError(error, [json], null, schema);
333
+ report.addError(error, [JSON.stringify(json)], undefined, schema);
322
334
  }
323
335
  },
324
336
  type: function (report, schema, json) {
@@ -326,15 +338,15 @@ export const JsonValidators = {
326
338
  if (shouldSkipValidate(this.validateOptions, ['INVALID_TYPE'])) {
327
339
  return;
328
340
  }
329
- const jsonType = Utils.whatIs(json);
341
+ const jsonType = whatIs(json);
330
342
  if (typeof schema.type === 'string') {
331
343
  if (jsonType !== schema.type && (jsonType !== 'integer' || schema.type !== 'number')) {
332
- report.addError('INVALID_TYPE', [schema.type, jsonType], null, schema);
344
+ report.addError('INVALID_TYPE', [schema.type, jsonType], undefined, schema);
333
345
  }
334
346
  }
335
347
  else {
336
348
  if (schema.type.indexOf(jsonType) === -1 && (jsonType !== 'integer' || schema.type.indexOf('number') === -1)) {
337
- report.addError('INVALID_TYPE', [schema.type, jsonType], null, schema);
349
+ report.addError('INVALID_TYPE', [JSON.stringify(schema.type), jsonType], undefined, schema);
338
350
  }
339
351
  }
340
352
  },
@@ -378,39 +390,40 @@ export const JsonValidators = {
378
390
  report.addError('ONE_OF_MISSING', undefined, subReports, schema);
379
391
  }
380
392
  else if (passes > 1) {
381
- report.addError('ONE_OF_MULTIPLE', null, null, schema);
393
+ report.addError('ONE_OF_MULTIPLE', undefined, undefined, schema);
382
394
  }
383
395
  },
384
396
  not: function (report, schema, json) {
385
397
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.2
386
398
  const subReport = new Report(report);
387
399
  if (validate.call(this, subReport, schema.not, json) === true) {
388
- report.addError('NOT_PASSED', null, null, schema);
400
+ report.addError('NOT_PASSED', undefined, undefined, schema);
389
401
  }
390
402
  },
391
403
  definitions: function () {
392
- /*report, schema, json*/
404
+ /*report: Report, schema: JsonSchemaInternal, json: unknown*/
393
405
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.2
394
406
  // nothing to do here
395
407
  },
396
408
  format: function (report, schema, json) {
397
409
  // http://json-schema.org/latest/json-schema-validation.html#rfc.section.7.2
398
- const formatValidatorFn = FormatValidators[schema.format];
410
+ const formatValidators = getFormatValidators(this.options);
411
+ const formatValidatorFn = formatValidators[schema.format];
399
412
  if (typeof formatValidatorFn === 'function') {
400
413
  if (shouldSkipValidate(this.validateOptions, ['INVALID_FORMAT'])) {
401
414
  return;
402
415
  }
403
- if (report.hasError('INVALID_TYPE', [schema.type, Utils.whatIs(json)])) {
416
+ if (report.hasError('INVALID_TYPE', [schema.type, whatIs(json)])) {
404
417
  return;
405
418
  }
406
419
  if (formatValidatorFn.length === 2) {
407
420
  // async - need to clone the path here, because it will change by the time async function reports back
408
- const pathBeforeAsync = Utils.clone(report.path);
421
+ const pathBeforeAsync = shallowClone(report.path);
409
422
  report.addAsyncTask(formatValidatorFn, [json], function (result) {
410
423
  if (result !== true) {
411
424
  const backup = report.path;
412
425
  report.path = pathBeforeAsync;
413
- report.addError('INVALID_FORMAT', [schema.format, json], null, schema);
426
+ report.addError('INVALID_FORMAT', [schema.format, JSON.stringify(json)], undefined, schema);
414
427
  report.path = backup;
415
428
  }
416
429
  });
@@ -418,12 +431,12 @@ export const JsonValidators = {
418
431
  else {
419
432
  // sync
420
433
  if (formatValidatorFn.call(this, json) !== true) {
421
- report.addError('INVALID_FORMAT', [schema.format, json], null, schema);
434
+ report.addError('INVALID_FORMAT', [schema.format, JSON.stringify(json)], undefined, schema);
422
435
  }
423
436
  }
424
437
  }
425
438
  else if (this.options.ignoreUnknownFormats !== true) {
426
- report.addError('UNKNOWN_FORMAT', [schema.format], null, schema);
439
+ report.addError('UNKNOWN_FORMAT', [schema.format], undefined, schema);
427
440
  }
428
441
  },
429
442
  };
@@ -509,18 +522,12 @@ const recurseObject = function (report, schema, json) {
509
522
  }
510
523
  }
511
524
  };
512
- /**
513
- *
514
- * @param {Report} report
515
- * @param {*} schema
516
- * @param {*} json
517
- */
518
525
  export function validate(report, schema, json) {
519
526
  report.commonErrorMessage = 'JSON_OBJECT_VALIDATION_FAILED';
520
527
  // check if schema is an object
521
- const to = Utils.whatIs(schema);
528
+ const to = whatIs(schema);
522
529
  if (to !== 'object') {
523
- report.addError('SCHEMA_NOT_AN_OBJECT', [to], null, schema);
530
+ report.addError('SCHEMA_NOT_AN_OBJECT', [to], undefined, schema);
524
531
  return false;
525
532
  }
526
533
  // check if schema is empty, everything is valid against empty schema
@@ -540,7 +547,7 @@ export function validate(report, schema, json) {
540
547
  let maxRefs = 99;
541
548
  while (schema.$ref && maxRefs > 0) {
542
549
  if (!schema.__$refResolved) {
543
- report.addError('REF_UNRESOLVED', [schema.$ref], null, schema);
550
+ report.addError('REF_UNRESOLVED', [schema.$ref], undefined, schema);
544
551
  break;
545
552
  }
546
553
  else if (schema.__$refResolved === schema) {
@@ -557,7 +564,6 @@ export function validate(report, schema, json) {
557
564
  }
558
565
  }
559
566
  // type checking first
560
- const jsonType = Utils.whatIs(json);
561
567
  if (schema.type) {
562
568
  keys.splice(keys.indexOf('type'), 1);
563
569
  JsonValidators.type.call(this, report, schema, json);
@@ -576,10 +582,10 @@ export function validate(report, schema, json) {
576
582
  }
577
583
  }
578
584
  if (report.errors.length === 0 || this.options.breakOnFirstError === false) {
579
- if (jsonType === 'array') {
585
+ if (Array.isArray(json)) {
580
586
  recurseArray.call(this, report, schema, json);
581
587
  }
582
- else if (jsonType === 'object') {
588
+ else if (isObject(json)) {
583
589
  recurseObject.call(this, report, schema, json);
584
590
  }
585
591
  }
@@ -1,29 +1,22 @@
1
1
  import get from 'lodash.get';
2
- import { Errors } from './Errors.js';
3
- import * as Utils from './Utils.js';
2
+ import { Errors } from './errors.js';
3
+ import { whatIs } from './utils/what-is.js';
4
+ import { schemaSymbol, jsonSymbol } from './utils/symbols.js';
5
+ import { isAbsoluteUri } from './utils/uri.js';
4
6
  export class Report {
5
- errors;
7
+ asyncTasks = [];
8
+ commonErrorMessage;
9
+ errors = [];
10
+ json;
11
+ path = [];
12
+ rootSchema;
6
13
  parentReport;
7
14
  options;
8
15
  reportOptions;
9
- path;
10
- asyncTasks;
11
- rootSchema;
12
- commonErrorMessage;
13
- json;
14
16
  constructor(parentOrOptions, reportOptions) {
15
17
  this.parentReport = parentOrOptions instanceof Report ? parentOrOptions : undefined;
16
18
  this.options = parentOrOptions instanceof Report ? parentOrOptions.options : parentOrOptions || {};
17
19
  this.reportOptions = reportOptions || {};
18
- this.errors = [];
19
- /**
20
- * @type {string[]}
21
- */
22
- this.path = [];
23
- this.asyncTasks = [];
24
- this.rootSchema = undefined;
25
- this.commonErrorMessage = undefined;
26
- this.json = undefined;
27
20
  }
28
21
  isValid() {
29
22
  if (this.asyncTasks.length > 0) {
@@ -54,17 +47,15 @@ export class Report {
54
47
  callback(err, valid);
55
48
  }, 0);
56
49
  };
57
- function respond(asyncTaskResultProcessFn) {
58
- return function (asyncTaskResult) {
59
- if (timedOut) {
60
- return;
61
- }
62
- asyncTaskResultProcessFn(asyncTaskResult);
63
- if (--tasksCount === 0) {
64
- finish();
65
- }
66
- };
67
- }
50
+ const respond = (asyncTaskResultProcessFn) => (asyncTaskResult) => {
51
+ if (timedOut) {
52
+ return;
53
+ }
54
+ asyncTaskResultProcessFn(asyncTaskResult);
55
+ if (--tasksCount === 0) {
56
+ finish();
57
+ }
58
+ };
68
59
  // finish if tasks are completed or there are any errors and breaking on first error was requested
69
60
  if (tasksCount === 0 || (this.errors.length > 0 && this.options.breakOnFirstError)) {
70
61
  finish();
@@ -84,9 +75,6 @@ export class Report {
84
75
  }, validationTimeout);
85
76
  }
86
77
  getPath(returnPathAsString) {
87
- /**
88
- * @type {string[]|string}
89
- */
90
78
  let path = [];
91
79
  if (this.parentReport) {
92
80
  path = path.concat(this.parentReport.path);
@@ -98,7 +86,7 @@ export class Report {
98
86
  path
99
87
  .map(function (segment) {
100
88
  segment = segment.toString();
101
- if (Utils.isAbsoluteUri(segment)) {
89
+ if (isAbsoluteUri(segment)) {
102
90
  return 'uri(' + segment + ')';
103
91
  }
104
92
  return segment.replace(/~/g, '~0').replace(/\//g, '~1');
@@ -109,7 +97,7 @@ export class Report {
109
97
  }
110
98
  getSchemaId() {
111
99
  if (!this.rootSchema) {
112
- return null;
100
+ return undefined;
113
101
  }
114
102
  // get the error path as an array
115
103
  let path = [];
@@ -128,16 +116,16 @@ export class Report {
128
116
  // return id of the root
129
117
  return this.rootSchema.id;
130
118
  }
131
- hasError(errorCode, params) {
119
+ hasError(errCode, errParams) {
132
120
  let idx = this.errors.length;
133
121
  while (idx--) {
134
- if (this.errors[idx].code === errorCode) {
122
+ if (this.errors[idx].code === errCode) {
135
123
  // assume match
136
124
  let match = true;
137
125
  // check the params too
138
126
  let idx2 = this.errors[idx].params.length;
139
127
  while (idx2--) {
140
- if (this.errors[idx].params[idx2] !== params[idx2]) {
128
+ if (this.errors[idx].params[idx2] !== errParams[idx2]) {
141
129
  match = false;
142
130
  }
143
131
  }
@@ -149,12 +137,13 @@ export class Report {
149
137
  }
150
138
  return false;
151
139
  }
152
- addError(errorCode, params, subReports, schema) {
153
- if (!errorCode) {
140
+ addError(errCode, errParams, subReports, schema) {
141
+ if (!errCode) {
154
142
  throw new Error('No errorCode passed into addError()');
155
143
  }
156
- this.addCustomError(errorCode, Errors[errorCode], params, subReports, schema);
144
+ this.addCustomError(errCode, Errors[errCode], errParams, subReports, schema);
157
145
  }
146
+ // this returns the root object being validated (the one passed into validator.validate)
158
147
  getJson() {
159
148
  if (this.json) {
160
149
  return this.json;
@@ -165,7 +154,7 @@ export class Report {
165
154
  return undefined;
166
155
  }
167
156
  addCustomError(errorCode, errorMessage, params, subReports, schema) {
168
- if (this.errors.length >= this.reportOptions.maxErrors) {
157
+ if (typeof this.reportOptions.maxErrors === 'number' && this.errors.length >= this.reportOptions.maxErrors) {
169
158
  return;
170
159
  }
171
160
  if (!errorMessage) {
@@ -174,9 +163,9 @@ export class Report {
174
163
  params = params || [];
175
164
  let idx = params.length;
176
165
  while (idx--) {
177
- const whatIs = Utils.whatIs(params[idx]);
178
- const param = whatIs === 'object' || whatIs === 'null' ? JSON.stringify(params[idx]) : params[idx];
179
- errorMessage = errorMessage.replace('{' + idx + '}', param);
166
+ const paramType = whatIs(params[idx]);
167
+ const param = paramType === 'object' || paramType === 'null' ? JSON.stringify(params[idx]) : params[idx];
168
+ errorMessage = errorMessage.replace('{' + idx + '}', param.toString());
180
169
  }
181
170
  const err = {
182
171
  code: errorCode,
@@ -185,8 +174,9 @@ export class Report {
185
174
  path: this.getPath(this.options.reportPathAsArray),
186
175
  schemaId: this.getSchemaId(),
187
176
  };
188
- err[Utils.schemaSymbol] = schema;
189
- err[Utils.jsonSymbol] = this.getJson();
177
+ // TODO v8: remove Symbol usage
178
+ err[schemaSymbol] = schema;
179
+ err[jsonSymbol] = this.getJson();
190
180
  if (schema && typeof schema === 'string') {
191
181
  err.description = schema;
192
182
  }