z-schema 7.0.5 → 7.0.7

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 +179 -119
  3. package/cjs/index.js +1048 -1101
  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 +6 -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} +69 -84
  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 +8 -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} +112 -121
  55. package/umd/ZSchema.js +1048 -1101
  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
+ export 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,34 @@ 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: JsonSchema): 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 | string, options?: ValidateOptions, callback?: ValidateCallback): void;
208
+ validate(json: unknown, schema: JsonSchema | string, callback?: ValidateCallback): void;
209
+ validate(json: unknown, schema: JsonSchema | string, options?: ValidateOptions): boolean;
210
+ validate(json: unknown, schema: JsonSchema | string): boolean;
211
+ validate(
212
+ json: unknown,
213
+ schema: JsonSchema | string,
214
+ options?: ValidateOptions | ValidateCallback,
215
+ callback?: ValidateCallback
216
+ ): boolean | void {
237
217
  if (typeof options === 'function') {
238
218
  callback = options;
239
219
  options = {};
@@ -244,9 +224,11 @@ export class ZSchema {
244
224
 
245
225
  this.validateOptions = options;
246
226
 
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!');
227
+ const schemaType = whatIs(schema);
228
+ if (schemaType !== 'string' && schemaType !== 'object') {
229
+ const e = new Error(
230
+ 'Invalid .validate call - schema must be a string or object but ' + schemaType + ' was passed!'
231
+ );
250
232
  if (callback) {
251
233
  setTimeout(function () {
252
234
  callback(e, false);
@@ -260,19 +242,20 @@ export class ZSchema {
260
242
  const report = new Report(this.options);
261
243
  report.json = json;
262
244
 
245
+ let _schema: JsonSchemaInternal;
263
246
  if (typeof schema === 'string') {
264
247
  const schemaName = schema;
265
- schema = SchemaCache.getSchema.call(this, report, schemaName);
266
- if (!schema) {
248
+ _schema = this.scache.getSchema(report, schemaName)!;
249
+ if (!_schema) {
267
250
  throw new Error("Schema with id '" + schemaName + "' wasn't found in the validator cache!");
268
251
  }
269
252
  } else {
270
- schema = SchemaCache.getSchema.call(this, report, schema);
253
+ _schema = this.scache.getSchema(report, schema)!;
271
254
  }
272
255
 
273
256
  let compiled = false;
274
257
  if (!foundError) {
275
- compiled = SchemaCompilation.compileSchema.call(this, report, schema);
258
+ compiled = this.sc.compileSchema(report, _schema);
276
259
  }
277
260
  if (!compiled) {
278
261
  this.lastReport = report;
@@ -281,7 +264,7 @@ export class ZSchema {
281
264
 
282
265
  let validated = false;
283
266
  if (!foundError) {
284
- validated = SchemaValidation.validateSchema.call(this, report, schema);
267
+ validated = this.sv.validateSchema(report, _schema);
285
268
  }
286
269
  if (!validated) {
287
270
  this.lastReport = report;
@@ -289,15 +272,15 @@ export class ZSchema {
289
272
  }
290
273
 
291
274
  if (options.schemaPath) {
292
- report.rootSchema = schema;
293
- schema = get(schema, options.schemaPath);
294
- if (!schema) {
275
+ report.rootSchema = _schema;
276
+ _schema = get(_schema, options.schemaPath);
277
+ if (!_schema) {
295
278
  throw new Error("Schema path '" + options.schemaPath + "' wasn't found in the schema!");
296
279
  }
297
280
  }
298
281
 
299
282
  if (!foundError) {
300
- JsonValidation.validate.call(this, report, schema, json);
283
+ validateJson.call(this, report, _schema, json);
301
284
  }
302
285
 
303
286
  if (callback) {
@@ -317,13 +300,16 @@ export class ZSchema {
317
300
  /**
318
301
  * Returns an Error object for the most recent failed validation, or null if the validation was successful.
319
302
  */
320
- getLastError(): SchemaError {
303
+ getLastError(): SchemaError | null {
304
+ if (!this.lastReport) {
305
+ throw new Error(`getLastError() called before doing any validation!`);
306
+ }
321
307
  if (this.lastReport.errors.length === 0) {
322
308
  return null;
323
309
  }
324
310
  const e: SchemaError = new Error();
325
311
  e.name = 'z-schema validation error';
326
- e.message = this.lastReport.commonErrorMessage;
312
+ e.message = this.lastReport.commonErrorMessage!;
327
313
  e.details = this.lastReport.errors;
328
314
  return e;
329
315
  }
@@ -332,43 +318,45 @@ export class ZSchema {
332
318
  * Returns the error details for the most recent validation, or undefined if the validation was successful.
333
319
  * This is the same list as the SchemaError.details property.
334
320
  */
335
- getLastErrors(): SchemaErrorDetail[] {
321
+ getLastErrors(): SchemaErrorDetail[] | null {
336
322
  return this.lastReport && this.lastReport.errors.length > 0 ? this.lastReport.errors : null;
337
323
  }
338
324
 
339
- setRemoteReference(uri, schema, validationOptions) {
325
+ setRemoteReference(uri: string, schema: string | JsonSchema, validationOptions: ZSchemaOptions) {
326
+ let _schema: JsonSchemaInternal;
327
+
340
328
  if (typeof schema === 'string') {
341
- schema = JSON.parse(schema);
329
+ _schema = JSON.parse(schema);
342
330
  } else {
343
- schema = Utils.cloneDeep(schema);
331
+ _schema = deepClone(schema);
344
332
  }
345
333
 
346
334
  if (validationOptions) {
347
- schema.__$validationOptions = normalizeOptions(validationOptions);
335
+ _schema.__$validationOptions = normalizeOptions(validationOptions);
348
336
  }
349
337
 
350
- SchemaCache.cacheSchemaByUri.call(this, uri, schema);
338
+ this.scache.cacheSchemaByUri(uri, _schema);
351
339
  }
352
340
 
353
- compileSchema(schema) {
341
+ compileSchema(schema: JsonSchema) {
354
342
  const report = new Report(this.options);
355
343
 
356
- schema = SchemaCache.getSchema.call(this, report, schema);
344
+ schema = this.scache.getSchema(report, schema)!;
357
345
 
358
- SchemaCompilation.compileSchema.call(this, report, schema);
346
+ this.sc.compileSchema(report, schema);
359
347
 
360
348
  this.lastReport = report;
361
349
  return report.isValid();
362
350
  }
363
351
 
364
- getMissingReferences(arr?) {
365
- arr = arr || this.lastReport.errors;
366
- let res = [],
367
- idx = arr.length;
352
+ getMissingReferences(arr?: SchemaErrorDetail[]) {
353
+ arr = arr || this.lastReport?.errors || [];
354
+ let res: string[] = [];
355
+ let idx = arr.length;
368
356
  while (idx--) {
369
357
  const error = arr[idx];
370
358
  if (error.code === 'UNRESOLVABLE_REFERENCE') {
371
- const reference = error.params[0];
359
+ const reference = error.params[0] as string;
372
360
  if (res.indexOf(reference) === -1) {
373
361
  res.push(reference);
374
362
  }
@@ -385,7 +373,7 @@ export class ZSchema {
385
373
  const missingRemoteReferences = [];
386
374
  let idx = missingReferences.length;
387
375
  while (idx--) {
388
- const remoteReference = SchemaCache.getRemotePath(missingReferences[idx]);
376
+ const remoteReference = getRemotePath(missingReferences[idx]);
389
377
  if (remoteReference && missingRemoteReferences.indexOf(remoteReference) === -1) {
390
378
  missingRemoteReferences.push(remoteReference);
391
379
  }
@@ -393,19 +381,22 @@ export class ZSchema {
393
381
  return missingRemoteReferences;
394
382
  }
395
383
 
396
- getResolvedSchema(schema) {
384
+ getResolvedSchema(schema: JsonSchema): JsonSchema {
397
385
  const report = new Report(this.options);
398
- schema = SchemaCache.getSchema.call(this, report, schema);
386
+ schema = this.scache.getSchema(report, schema)!;
399
387
 
400
388
  // clone before making any modifications
401
- schema = Utils.cloneDeep(schema);
389
+ schema = deepClone(schema);
402
390
 
403
- const visited = [];
391
+ const visited: JsonSchemaInternalCleanup[] = [];
404
392
 
405
393
  // clean-up the schema and resolve references
406
- const cleanup = function (schema) {
394
+ interface JsonSchemaInternalCleanup extends JsonSchemaInternal {
395
+ ___$visited?: boolean;
396
+ }
397
+ const cleanup = function (schema: JsonSchemaInternalCleanup) {
407
398
  let key;
408
- const typeOf = Utils.whatIs(schema);
399
+ const typeOf = whatIs(schema);
409
400
  if (typeOf !== 'object' && typeOf !== 'array') {
410
401
  return;
411
402
  }
@@ -424,16 +415,16 @@ export class ZSchema {
424
415
  delete schema.__$refResolved;
425
416
  for (key in from) {
426
417
  if (Object.prototype.hasOwnProperty.call(from, key)) {
427
- to[key] = from[key];
418
+ (to as any)[key] = (from as any)[key];
428
419
  }
429
420
  }
430
421
  }
431
422
  for (key in schema) {
432
423
  if (Object.prototype.hasOwnProperty.call(schema, key)) {
433
424
  if (key.indexOf('__$') === 0) {
434
- delete schema[key];
425
+ delete (schema as any)[key];
435
426
  } else {
436
- cleanup(schema[key]);
427
+ cleanup((schema as any)[key]);
437
428
  }
438
429
  }
439
430
  }
@@ -454,7 +445,7 @@ export class ZSchema {
454
445
 
455
446
  static schemaReader: SchemaReader;
456
447
 
457
- setSchemaReader(schemaReader) {
448
+ setSchemaReader(schemaReader: SchemaReader) {
458
449
  return ZSchema.setSchemaReader(schemaReader);
459
450
  }
460
451
 
@@ -462,11 +453,11 @@ export class ZSchema {
462
453
  return ZSchema.schemaReader;
463
454
  }
464
455
 
465
- static setSchemaReader(schemaReader) {
456
+ static setSchemaReader(schemaReader: SchemaReader) {
466
457
  ZSchema.schemaReader = schemaReader;
467
458
  }
468
459
 
469
- static schemaSymbol = Utils.schemaSymbol;
460
+ static schemaSymbol = schemaSymbol;
470
461
 
471
- static jsonSymbol = Utils.jsonSymbol;
462
+ static jsonSymbol = jsonSymbol;
472
463
  }