z-schema 7.0.5 → 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 (75) hide show
  1. package/README.md +0 -9
  2. package/cjs/index.d.ts +192 -119
  3. package/cjs/index.js +1044 -1097
  4. package/{src/FormatValidators.ts → dist/format-validators.js} +97 -65
  5. package/dist/index.js +1 -1
  6. package/dist/json-schema.js +40 -0
  7. package/dist/{JsonValidation.js → json-validation.js} +75 -69
  8. package/dist/{Report.js → report.js} +35 -45
  9. package/dist/schema-cache.js +109 -0
  10. package/dist/schema-compiler.js +255 -0
  11. package/dist/{SchemaValidation.js → schema-validator.js} +153 -149
  12. package/dist/types/{Errors.d.ts → errors.d.ts} +2 -0
  13. package/dist/types/format-validators.d.ts +10 -0
  14. package/dist/types/index.d.ts +10 -1
  15. package/dist/types/json-schema.d.ts +50 -0
  16. package/dist/types/json-validation.d.ts +7 -0
  17. package/dist/types/{Report.d.ts → report.d.ts} +22 -23
  18. package/dist/types/schema-cache.d.ts +17 -0
  19. package/dist/types/schema-compiler.d.ts +16 -0
  20. package/dist/types/schema-validator.d.ts +10 -0
  21. package/dist/types/utils/array.d.ts +2 -0
  22. package/dist/types/utils/clone.d.ts +2 -0
  23. package/dist/types/utils/json.d.ts +7 -0
  24. package/dist/types/utils/symbols.d.ts +2 -0
  25. package/dist/types/utils/unicode.d.ts +14 -0
  26. package/dist/types/utils/uri.d.ts +4 -0
  27. package/dist/types/utils/what-is.d.ts +3 -0
  28. package/dist/types/z-schema.d.ts +75 -0
  29. package/dist/utils/array.js +27 -0
  30. package/dist/utils/clone.js +61 -0
  31. package/dist/utils/json.js +59 -0
  32. package/dist/utils/symbols.js +2 -0
  33. package/dist/utils/unicode.js +45 -0
  34. package/dist/utils/uri.js +15 -0
  35. package/dist/utils/what-is.js +29 -0
  36. package/dist/{ZSchema.js → z-schema.js} +66 -81
  37. package/package.json +6 -3
  38. package/src/{Errors.ts → errors.ts} +4 -0
  39. package/src/format-validators.ts +191 -0
  40. package/src/index.ts +12 -1
  41. package/src/json-schema.ts +97 -0
  42. package/src/{JsonValidation.ts → json-validation.ts} +137 -127
  43. package/src/{Report.ts → report.ts} +60 -70
  44. package/src/schema-cache.ts +122 -0
  45. package/src/schema-compiler.ts +300 -0
  46. package/src/{SchemaValidation.ts → schema-validator.ts} +213 -215
  47. package/src/utils/array.ts +29 -0
  48. package/src/utils/clone.ts +63 -0
  49. package/src/utils/json.ts +74 -0
  50. package/src/utils/symbols.ts +3 -0
  51. package/src/utils/unicode.ts +43 -0
  52. package/src/utils/uri.ts +18 -0
  53. package/src/utils/what-is.ts +46 -0
  54. package/src/{ZSchema.ts → z-schema.ts} +108 -118
  55. package/umd/ZSchema.js +1044 -1097
  56. package/umd/ZSchema.min.js +1 -1
  57. package/dist/FormatValidators.js +0 -136
  58. package/dist/SchemaCache.js +0 -172
  59. package/dist/SchemaCompilation.js +0 -259
  60. package/dist/Utils.js +0 -266
  61. package/dist/types/FormatValidators.d.ts +0 -12
  62. package/dist/types/JsonValidation.d.ts +0 -37
  63. package/dist/types/SchemaCache.d.ts +0 -26
  64. package/dist/types/SchemaCompilation.d.ts +0 -1
  65. package/dist/types/SchemaValidation.d.ts +0 -6
  66. package/dist/types/Utils.d.ts +0 -64
  67. package/dist/types/ZSchema.d.ts +0 -99
  68. package/src/SchemaCache.ts +0 -188
  69. package/src/SchemaCompilation.ts +0 -293
  70. package/src/Utils.ts +0 -286
  71. /package/dist/{Errors.js → errors.js} +0 -0
  72. /package/dist/schemas/{hyper-schema.json → draft-04-hyper-schema.json} +0 -0
  73. /package/dist/schemas/{schema.json → draft-04-schema.json} +0 -0
  74. /package/src/schemas/{hyper-schema.json → draft-04-hyper-schema.json} +0 -0
  75. /package/src/schemas/{schema.json → draft-04-schema.json} +0 -0
@@ -1,19 +1,27 @@
1
1
  import get from 'lodash.get';
2
- import { Report, SchemaError, SchemaErrorDetail } from './Report.js';
3
- import { FormatValidators } from './FormatValidators.js';
4
- import * as JsonValidation from './JsonValidation.js';
5
- import * as SchemaCache from './SchemaCache.js';
6
- import * as SchemaCompilation from './SchemaCompilation.js';
7
- import * as SchemaValidation from './SchemaValidation.js';
8
- import * as Utils from './Utils.js';
9
- import Draft4Schema from './schemas/schema.json' with { type: 'json' };
10
- import Draft4HyperSchema from './schemas/hyper-schema.json' with { type: 'json' };
11
- import type { Errors } from './Errors.js';
2
+ import { Report, SchemaError, SchemaErrorDetail } from './report.js';
3
+ import { FormatValidatorFn, getRegisteredFormats, registerFormat, unregisterFormat } from './format-validators.js';
4
+ import { validate as validateJson } from './json-validation.js';
5
+ import { SchemaCache } from './schema-cache.js';
6
+ import { SchemaCompiler } from './schema-compiler.js';
7
+ import { SchemaValidator } from './schema-validator.js';
8
+ import { shallowClone, deepClone } from './utils/clone.js';
9
+ import { whatIs } from './utils/what-is.js';
10
+ import { schemaSymbol, jsonSymbol } from './utils/symbols.js';
11
+ import { getRemotePath } from './utils/uri.js';
12
+ import type { Errors } from './errors.js';
13
+ // import schemas so they don't have to be downloaded for validation purposes
14
+ import type { JsonSchema, JsonSchemaInternal } from './json-schema.js';
15
+ import _Draft4Schema from './schemas/draft-04-schema.json' with { type: 'json' };
16
+ import _Draft4HyperSchema from './schemas/draft-04-hyper-schema.json' with { type: 'json' };
17
+
18
+ const Draft4Schema: JsonSchema = _Draft4Schema;
19
+ const Draft4HyperSchema: JsonSchema = _Draft4HyperSchema;
12
20
 
13
21
  /**
14
22
  * default options
15
23
  */
16
- const defaultOptions = {
24
+ const defaultOptions: ZSchemaOptions = {
17
25
  // default timeout for all async tasks
18
26
  asyncTimeout: 2000,
19
27
  // force additionalProperties and additionalItems to be defined on "object" and "array" types
@@ -57,17 +65,17 @@ const defaultOptions = {
57
65
  // ignore unknown formats (do not report them as an error)
58
66
  ignoreUnknownFormats: false,
59
67
  // function to be called on every schema
60
- customValidator: null,
68
+ customValidator: null as unknown as undefined,
61
69
  };
62
70
 
63
- function normalizeOptions(options) {
71
+ const normalizeOptions = (options?: ZSchemaOptions) => {
64
72
  let normalized;
65
73
 
66
74
  // options
67
75
  if (typeof options === 'object') {
68
- let keys = Object.keys(options),
69
- idx = keys.length,
70
- key;
76
+ let keys = Object.keys(options) as Array<keyof ZSchemaOptions>;
77
+ let idx = keys.length;
78
+ let key;
71
79
 
72
80
  // check that the options are correctly configured
73
81
  while (idx--) {
@@ -78,18 +86,18 @@ function normalizeOptions(options) {
78
86
  }
79
87
 
80
88
  // copy the default options into passed options
81
- keys = Object.keys(defaultOptions);
89
+ keys = Object.keys(defaultOptions) as Array<keyof ZSchemaOptions>;
82
90
  idx = keys.length;
83
91
  while (idx--) {
84
92
  key = keys[idx];
85
93
  if (options[key] === undefined) {
86
- options[key] = Utils.clone(defaultOptions[key]);
94
+ (options as any)[key] = shallowClone(defaultOptions[key]);
87
95
  }
88
96
  }
89
97
 
90
98
  normalized = options;
91
99
  } else {
92
- normalized = Utils.clone(defaultOptions);
100
+ normalized = shallowClone(defaultOptions);
93
101
  }
94
102
 
95
103
  if (normalized.strictMode === true) {
@@ -104,12 +112,13 @@ function normalizeOptions(options) {
104
112
  }
105
113
 
106
114
  return normalized;
107
- }
115
+ };
108
116
 
109
117
  export interface ZSchemaOptions {
110
118
  asyncTimeout?: number;
111
119
  forceAdditional?: boolean;
112
- assumeAdditional?: boolean;
120
+ assumeAdditional?: boolean | string[];
121
+ enumCaseInsensitiveComparison?: boolean;
113
122
  forceItems?: boolean;
114
123
  forceMinItems?: boolean;
115
124
  forceMaxItems?: boolean;
@@ -135,60 +144,39 @@ export interface ValidateOptions {
135
144
  includeErrors?: Array<keyof typeof Errors>;
136
145
  }
137
146
 
138
- type ValidateCallback = (e: Error, valid: boolean) => void;
147
+ export type ValidateCallback = (e: Error | SchemaErrorDetail[] | null, valid: boolean) => void;
139
148
 
140
149
  // a sync function that loads schemas for future use, for example from schemas directory, during server startup
141
- type SchemaReader = (uri: string) => unknown;
150
+ type SchemaReader = (uri: string) => JsonSchema;
142
151
 
143
152
  export class ZSchema {
144
- public lastReport: Report | undefined;
145
-
146
- /**
147
- * Register a custom format.
148
- *
149
- * @param name - name of the custom format
150
- * @param validatorFunction - custom format validator function.
151
- * Returns `true` if `value` matches the custom format.
152
- */
153
- public static registerFormat(formatName: string, validatorFunction: (value: unknown) => boolean): void {
154
- FormatValidators[formatName] = validatorFunction;
153
+ public static registerFormat(name: string, validatorFunction: FormatValidatorFn): void {
154
+ return registerFormat(name, validatorFunction);
155
155
  }
156
156
 
157
- /**
158
- * Unregister a format.
159
- *
160
- * @param name - name of the custom format
161
- */
162
157
  public static unregisterFormat(name: string): void {
163
- delete FormatValidators[name];
158
+ return unregisterFormat(name);
164
159
  }
165
160
 
166
- /**
167
- * Get the list of all registered formats.
168
- *
169
- * Both the names of the burned-in formats and the custom format names are
170
- * returned by this function.
171
- *
172
- * @returns {string[]} the list of all registered format names.
173
- */
174
161
  public static getRegisteredFormats(): string[] {
175
- return Object.keys(FormatValidators);
162
+ return getRegisteredFormats();
176
163
  }
177
164
 
178
165
  public static getDefaultOptions(): ZSchemaOptions {
179
- return Utils.cloneDeep(defaultOptions);
166
+ return deepClone(defaultOptions);
180
167
  }
181
168
 
182
- private cache: Record<string, string>;
183
- private referenceCache: Array<string>;
184
- private validateOptions: ValidateOptions;
169
+ lastReport: Report | undefined;
170
+ scache: SchemaCache;
171
+ sc: SchemaCompiler;
172
+ sv: SchemaValidator;
173
+ validateOptions: ValidateOptions = {};
185
174
  options: ZSchemaOptions;
186
175
 
187
176
  constructor(options?: ZSchemaOptions) {
188
- this.cache = {};
189
- this.referenceCache = [];
190
- this.validateOptions = {};
191
-
177
+ this.scache = new SchemaCache(this);
178
+ this.sc = new SchemaCompiler(this);
179
+ this.sv = new SchemaValidator(this);
192
180
  this.options = normalizeOptions(options);
193
181
 
194
182
  // Disable strict validation for the built-in schemas
@@ -198,42 +186,33 @@ export class ZSchema {
198
186
  this.setRemoteReference('http://json-schema.org/draft-04/hyper-schema', Draft4HyperSchema, metaschemaOptions);
199
187
  }
200
188
 
201
- /** Used by SchemaCache to break circular dependency with SchemaCompilation */
202
- _compileSchema(report: Report, schema: unknown): boolean {
203
- return SchemaCompilation.compileSchema.call(this, report, schema);
204
- }
205
-
206
- /**
207
- * @param schema - JSON object representing schema
208
- * @returns {boolean} true if schema is valid.
209
- */
210
- validateSchema(schema: unknown): boolean {
189
+ validateSchema(schema: JsonSchemaInternal): boolean {
211
190
  if (Array.isArray(schema) && schema.length === 0) {
212
191
  throw new Error('.validateSchema was called with an empty array');
213
192
  }
214
193
 
215
194
  const report = new Report(this.options);
216
195
 
217
- schema = SchemaCache.getSchema.call(this, report, schema);
196
+ schema = this.scache.getSchema(report, schema)!;
218
197
 
219
- const compiled = SchemaCompilation.compileSchema.call(this, report, schema);
198
+ const compiled = this.sc.compileSchema(report, schema);
220
199
  if (compiled) {
221
- SchemaValidation.validateSchema.call(this, report, schema);
200
+ this.sv.validateSchema(report, schema);
222
201
  }
223
202
 
224
203
  this.lastReport = report;
225
204
  return report.isValid();
226
205
  }
227
206
 
228
- /**
229
- * @param json - either a JSON string or a parsed JSON object
230
- * @param schema - the JSON object representing the schema
231
- * @returns true if json matches schema
232
- */
233
- validate(json, schema, options?: ValidateOptions, callback?: ValidateCallback): boolean;
234
- validate(json, schema, callback?): boolean;
235
- validate(json, schema): boolean;
236
- validate(json, schema, options?: ValidateOptions | ValidateCallback, callback?: ValidateCallback): boolean {
207
+ validate(json: unknown, schema: JsonSchema, options?: ValidateOptions, callback?: ValidateCallback): void;
208
+ validate(json: unknown, schema: JsonSchema, callback?: ValidateCallback): void;
209
+ validate(json: unknown, schema: JsonSchema): boolean;
210
+ validate(
211
+ json: unknown,
212
+ schema: JsonSchema,
213
+ options?: ValidateOptions | ValidateCallback,
214
+ callback?: ValidateCallback
215
+ ): boolean | void {
237
216
  if (typeof options === 'function') {
238
217
  callback = options;
239
218
  options = {};
@@ -244,9 +223,11 @@ export class ZSchema {
244
223
 
245
224
  this.validateOptions = options;
246
225
 
247
- const whatIs = Utils.whatIs(schema);
248
- if (whatIs !== 'string' && whatIs !== 'object') {
249
- const e = new Error('Invalid .validate call - schema must be a string or object but ' + whatIs + ' was passed!');
226
+ const schemaType = whatIs(schema);
227
+ if (schemaType !== 'string' && schemaType !== 'object') {
228
+ const e = new Error(
229
+ 'Invalid .validate call - schema must be a string or object but ' + schemaType + ' was passed!'
230
+ );
250
231
  if (callback) {
251
232
  setTimeout(function () {
252
233
  callback(e, false);
@@ -262,17 +243,18 @@ export class ZSchema {
262
243
 
263
244
  if (typeof schema === 'string') {
264
245
  const schemaName = schema;
265
- schema = SchemaCache.getSchema.call(this, report, schemaName);
266
- if (!schema) {
246
+ const _schema = this.scache.getSchema(report, schemaName);
247
+ if (!_schema) {
267
248
  throw new Error("Schema with id '" + schemaName + "' wasn't found in the validator cache!");
268
249
  }
250
+ schema = _schema;
269
251
  } else {
270
- schema = SchemaCache.getSchema.call(this, report, schema);
252
+ schema = this.scache.getSchema(report, schema)!;
271
253
  }
272
254
 
273
255
  let compiled = false;
274
256
  if (!foundError) {
275
- compiled = SchemaCompilation.compileSchema.call(this, report, schema);
257
+ compiled = this.sc.compileSchema(report, schema);
276
258
  }
277
259
  if (!compiled) {
278
260
  this.lastReport = report;
@@ -281,7 +263,7 @@ export class ZSchema {
281
263
 
282
264
  let validated = false;
283
265
  if (!foundError) {
284
- validated = SchemaValidation.validateSchema.call(this, report, schema);
266
+ validated = this.sv.validateSchema(report, schema);
285
267
  }
286
268
  if (!validated) {
287
269
  this.lastReport = report;
@@ -297,7 +279,7 @@ export class ZSchema {
297
279
  }
298
280
 
299
281
  if (!foundError) {
300
- JsonValidation.validate.call(this, report, schema, json);
282
+ validateJson.call(this, report, schema, json);
301
283
  }
302
284
 
303
285
  if (callback) {
@@ -317,13 +299,16 @@ export class ZSchema {
317
299
  /**
318
300
  * Returns an Error object for the most recent failed validation, or null if the validation was successful.
319
301
  */
320
- getLastError(): SchemaError {
302
+ getLastError(): SchemaError | null {
303
+ if (!this.lastReport) {
304
+ throw new Error(`getLastError() called before doing any validation!`);
305
+ }
321
306
  if (this.lastReport.errors.length === 0) {
322
307
  return null;
323
308
  }
324
309
  const e: SchemaError = new Error();
325
310
  e.name = 'z-schema validation error';
326
- e.message = this.lastReport.commonErrorMessage;
311
+ e.message = this.lastReport.commonErrorMessage!;
327
312
  e.details = this.lastReport.errors;
328
313
  return e;
329
314
  }
@@ -332,43 +317,45 @@ export class ZSchema {
332
317
  * Returns the error details for the most recent validation, or undefined if the validation was successful.
333
318
  * This is the same list as the SchemaError.details property.
334
319
  */
335
- getLastErrors(): SchemaErrorDetail[] {
320
+ getLastErrors(): SchemaErrorDetail[] | null {
336
321
  return this.lastReport && this.lastReport.errors.length > 0 ? this.lastReport.errors : null;
337
322
  }
338
323
 
339
- setRemoteReference(uri, schema, validationOptions) {
324
+ setRemoteReference(uri: string, schema: string | JsonSchema, validationOptions: ZSchemaOptions) {
325
+ let _schema: JsonSchemaInternal;
326
+
340
327
  if (typeof schema === 'string') {
341
- schema = JSON.parse(schema);
328
+ _schema = JSON.parse(schema);
342
329
  } else {
343
- schema = Utils.cloneDeep(schema);
330
+ _schema = deepClone(schema);
344
331
  }
345
332
 
346
333
  if (validationOptions) {
347
- schema.__$validationOptions = normalizeOptions(validationOptions);
334
+ _schema.__$validationOptions = normalizeOptions(validationOptions);
348
335
  }
349
336
 
350
- SchemaCache.cacheSchemaByUri.call(this, uri, schema);
337
+ this.scache.cacheSchemaByUri(uri, _schema);
351
338
  }
352
339
 
353
- compileSchema(schema) {
340
+ compileSchema(schema: JsonSchema) {
354
341
  const report = new Report(this.options);
355
342
 
356
- schema = SchemaCache.getSchema.call(this, report, schema);
343
+ schema = this.scache.getSchema(report, schema)!;
357
344
 
358
- SchemaCompilation.compileSchema.call(this, report, schema);
345
+ this.sc.compileSchema(report, schema);
359
346
 
360
347
  this.lastReport = report;
361
348
  return report.isValid();
362
349
  }
363
350
 
364
- getMissingReferences(arr?) {
365
- arr = arr || this.lastReport.errors;
366
- let res = [],
367
- idx = arr.length;
351
+ getMissingReferences(arr?: SchemaErrorDetail[]) {
352
+ arr = arr || this.lastReport?.errors || [];
353
+ let res: string[] = [];
354
+ let idx = arr.length;
368
355
  while (idx--) {
369
356
  const error = arr[idx];
370
357
  if (error.code === 'UNRESOLVABLE_REFERENCE') {
371
- const reference = error.params[0];
358
+ const reference = error.params[0] as string;
372
359
  if (res.indexOf(reference) === -1) {
373
360
  res.push(reference);
374
361
  }
@@ -385,7 +372,7 @@ export class ZSchema {
385
372
  const missingRemoteReferences = [];
386
373
  let idx = missingReferences.length;
387
374
  while (idx--) {
388
- const remoteReference = SchemaCache.getRemotePath(missingReferences[idx]);
375
+ const remoteReference = getRemotePath(missingReferences[idx]);
389
376
  if (remoteReference && missingRemoteReferences.indexOf(remoteReference) === -1) {
390
377
  missingRemoteReferences.push(remoteReference);
391
378
  }
@@ -393,19 +380,22 @@ export class ZSchema {
393
380
  return missingRemoteReferences;
394
381
  }
395
382
 
396
- getResolvedSchema(schema) {
383
+ getResolvedSchema(schema: JsonSchemaInternal): JsonSchema {
397
384
  const report = new Report(this.options);
398
- schema = SchemaCache.getSchema.call(this, report, schema);
385
+ schema = this.scache.getSchema(report, schema)!;
399
386
 
400
387
  // clone before making any modifications
401
- schema = Utils.cloneDeep(schema);
388
+ schema = deepClone(schema);
402
389
 
403
- const visited = [];
390
+ const visited: JsonSchemaInternalCleanup[] = [];
404
391
 
405
392
  // clean-up the schema and resolve references
406
- const cleanup = function (schema) {
393
+ interface JsonSchemaInternalCleanup extends JsonSchemaInternal {
394
+ ___$visited?: boolean;
395
+ }
396
+ const cleanup = function (schema: JsonSchemaInternalCleanup) {
407
397
  let key;
408
- const typeOf = Utils.whatIs(schema);
398
+ const typeOf = whatIs(schema);
409
399
  if (typeOf !== 'object' && typeOf !== 'array') {
410
400
  return;
411
401
  }
@@ -424,16 +414,16 @@ export class ZSchema {
424
414
  delete schema.__$refResolved;
425
415
  for (key in from) {
426
416
  if (Object.prototype.hasOwnProperty.call(from, key)) {
427
- to[key] = from[key];
417
+ (to as any)[key] = (from as any)[key];
428
418
  }
429
419
  }
430
420
  }
431
421
  for (key in schema) {
432
422
  if (Object.prototype.hasOwnProperty.call(schema, key)) {
433
423
  if (key.indexOf('__$') === 0) {
434
- delete schema[key];
424
+ delete (schema as any)[key];
435
425
  } else {
436
- cleanup(schema[key]);
426
+ cleanup((schema as any)[key]);
437
427
  }
438
428
  }
439
429
  }
@@ -454,7 +444,7 @@ export class ZSchema {
454
444
 
455
445
  static schemaReader: SchemaReader;
456
446
 
457
- setSchemaReader(schemaReader) {
447
+ setSchemaReader(schemaReader: SchemaReader) {
458
448
  return ZSchema.setSchemaReader(schemaReader);
459
449
  }
460
450
 
@@ -462,11 +452,11 @@ export class ZSchema {
462
452
  return ZSchema.schemaReader;
463
453
  }
464
454
 
465
- static setSchemaReader(schemaReader) {
455
+ static setSchemaReader(schemaReader: SchemaReader) {
466
456
  ZSchema.schemaReader = schemaReader;
467
457
  }
468
458
 
469
- static schemaSymbol = Utils.schemaSymbol;
459
+ static schemaSymbol = schemaSymbol;
470
460
 
471
- static jsonSymbol = Utils.jsonSymbol;
461
+ static jsonSymbol = jsonSymbol;
472
462
  }