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