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,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,37 +186,33 @@ export class ZSchema {
198
186
  this.setRemoteReference('http://json-schema.org/draft-04/hyper-schema', Draft4HyperSchema, metaschemaOptions);
199
187
  }
200
188
 
201
- /**
202
- * @param schema - JSON object representing schema
203
- * @returns {boolean} true if schema is valid.
204
- */
205
- validateSchema(schema: unknown): boolean {
189
+ validateSchema(schema: JsonSchemaInternal): boolean {
206
190
  if (Array.isArray(schema) && schema.length === 0) {
207
191
  throw new Error('.validateSchema was called with an empty array');
208
192
  }
209
193
 
210
194
  const report = new Report(this.options);
211
195
 
212
- schema = SchemaCache.getSchema.call(this, report, schema);
196
+ schema = this.scache.getSchema(report, schema)!;
213
197
 
214
- const compiled = SchemaCompilation.compileSchema.call(this, report, schema);
198
+ const compiled = this.sc.compileSchema(report, schema);
215
199
  if (compiled) {
216
- SchemaValidation.validateSchema.call(this, report, schema);
200
+ this.sv.validateSchema(report, schema);
217
201
  }
218
202
 
219
203
  this.lastReport = report;
220
204
  return report.isValid();
221
205
  }
222
206
 
223
- /**
224
- * @param json - either a JSON string or a parsed JSON object
225
- * @param schema - the JSON object representing the schema
226
- * @returns true if json matches schema
227
- */
228
- validate(json, schema, options?: ValidateOptions, callback?: ValidateCallback): boolean;
229
- validate(json, schema, callback?): boolean;
230
- validate(json, schema): boolean;
231
- 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 {
232
216
  if (typeof options === 'function') {
233
217
  callback = options;
234
218
  options = {};
@@ -239,9 +223,11 @@ export class ZSchema {
239
223
 
240
224
  this.validateOptions = options;
241
225
 
242
- const whatIs = Utils.whatIs(schema);
243
- if (whatIs !== 'string' && whatIs !== 'object') {
244
- 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
+ );
245
231
  if (callback) {
246
232
  setTimeout(function () {
247
233
  callback(e, false);
@@ -257,17 +243,18 @@ export class ZSchema {
257
243
 
258
244
  if (typeof schema === 'string') {
259
245
  const schemaName = schema;
260
- schema = SchemaCache.getSchema.call(this, report, schemaName);
261
- if (!schema) {
246
+ const _schema = this.scache.getSchema(report, schemaName);
247
+ if (!_schema) {
262
248
  throw new Error("Schema with id '" + schemaName + "' wasn't found in the validator cache!");
263
249
  }
250
+ schema = _schema;
264
251
  } else {
265
- schema = SchemaCache.getSchema.call(this, report, schema);
252
+ schema = this.scache.getSchema(report, schema)!;
266
253
  }
267
254
 
268
255
  let compiled = false;
269
256
  if (!foundError) {
270
- compiled = SchemaCompilation.compileSchema.call(this, report, schema);
257
+ compiled = this.sc.compileSchema(report, schema);
271
258
  }
272
259
  if (!compiled) {
273
260
  this.lastReport = report;
@@ -276,7 +263,7 @@ export class ZSchema {
276
263
 
277
264
  let validated = false;
278
265
  if (!foundError) {
279
- validated = SchemaValidation.validateSchema.call(this, report, schema);
266
+ validated = this.sv.validateSchema(report, schema);
280
267
  }
281
268
  if (!validated) {
282
269
  this.lastReport = report;
@@ -292,7 +279,7 @@ export class ZSchema {
292
279
  }
293
280
 
294
281
  if (!foundError) {
295
- JsonValidation.validate.call(this, report, schema, json);
282
+ validateJson.call(this, report, schema, json);
296
283
  }
297
284
 
298
285
  if (callback) {
@@ -312,13 +299,16 @@ export class ZSchema {
312
299
  /**
313
300
  * Returns an Error object for the most recent failed validation, or null if the validation was successful.
314
301
  */
315
- getLastError(): SchemaError {
302
+ getLastError(): SchemaError | null {
303
+ if (!this.lastReport) {
304
+ throw new Error(`getLastError() called before doing any validation!`);
305
+ }
316
306
  if (this.lastReport.errors.length === 0) {
317
307
  return null;
318
308
  }
319
309
  const e: SchemaError = new Error();
320
310
  e.name = 'z-schema validation error';
321
- e.message = this.lastReport.commonErrorMessage;
311
+ e.message = this.lastReport.commonErrorMessage!;
322
312
  e.details = this.lastReport.errors;
323
313
  return e;
324
314
  }
@@ -327,43 +317,45 @@ export class ZSchema {
327
317
  * Returns the error details for the most recent validation, or undefined if the validation was successful.
328
318
  * This is the same list as the SchemaError.details property.
329
319
  */
330
- getLastErrors(): SchemaErrorDetail[] {
320
+ getLastErrors(): SchemaErrorDetail[] | null {
331
321
  return this.lastReport && this.lastReport.errors.length > 0 ? this.lastReport.errors : null;
332
322
  }
333
323
 
334
- setRemoteReference(uri, schema, validationOptions) {
324
+ setRemoteReference(uri: string, schema: string | JsonSchema, validationOptions: ZSchemaOptions) {
325
+ let _schema: JsonSchemaInternal;
326
+
335
327
  if (typeof schema === 'string') {
336
- schema = JSON.parse(schema);
328
+ _schema = JSON.parse(schema);
337
329
  } else {
338
- schema = Utils.cloneDeep(schema);
330
+ _schema = deepClone(schema);
339
331
  }
340
332
 
341
333
  if (validationOptions) {
342
- schema.__$validationOptions = normalizeOptions(validationOptions);
334
+ _schema.__$validationOptions = normalizeOptions(validationOptions);
343
335
  }
344
336
 
345
- SchemaCache.cacheSchemaByUri.call(this, uri, schema);
337
+ this.scache.cacheSchemaByUri(uri, _schema);
346
338
  }
347
339
 
348
- compileSchema(schema) {
340
+ compileSchema(schema: JsonSchema) {
349
341
  const report = new Report(this.options);
350
342
 
351
- schema = SchemaCache.getSchema.call(this, report, schema);
343
+ schema = this.scache.getSchema(report, schema)!;
352
344
 
353
- SchemaCompilation.compileSchema.call(this, report, schema);
345
+ this.sc.compileSchema(report, schema);
354
346
 
355
347
  this.lastReport = report;
356
348
  return report.isValid();
357
349
  }
358
350
 
359
- getMissingReferences(arr?) {
360
- arr = arr || this.lastReport.errors;
361
- let res = [],
362
- idx = arr.length;
351
+ getMissingReferences(arr?: SchemaErrorDetail[]) {
352
+ arr = arr || this.lastReport?.errors || [];
353
+ let res: string[] = [];
354
+ let idx = arr.length;
363
355
  while (idx--) {
364
356
  const error = arr[idx];
365
357
  if (error.code === 'UNRESOLVABLE_REFERENCE') {
366
- const reference = error.params[0];
358
+ const reference = error.params[0] as string;
367
359
  if (res.indexOf(reference) === -1) {
368
360
  res.push(reference);
369
361
  }
@@ -380,7 +372,7 @@ export class ZSchema {
380
372
  const missingRemoteReferences = [];
381
373
  let idx = missingReferences.length;
382
374
  while (idx--) {
383
- const remoteReference = SchemaCache.getRemotePath(missingReferences[idx]);
375
+ const remoteReference = getRemotePath(missingReferences[idx]);
384
376
  if (remoteReference && missingRemoteReferences.indexOf(remoteReference) === -1) {
385
377
  missingRemoteReferences.push(remoteReference);
386
378
  }
@@ -388,19 +380,22 @@ export class ZSchema {
388
380
  return missingRemoteReferences;
389
381
  }
390
382
 
391
- getResolvedSchema(schema) {
383
+ getResolvedSchema(schema: JsonSchemaInternal): JsonSchema {
392
384
  const report = new Report(this.options);
393
- schema = SchemaCache.getSchema.call(this, report, schema);
385
+ schema = this.scache.getSchema(report, schema)!;
394
386
 
395
387
  // clone before making any modifications
396
- schema = Utils.cloneDeep(schema);
388
+ schema = deepClone(schema);
397
389
 
398
- const visited = [];
390
+ const visited: JsonSchemaInternalCleanup[] = [];
399
391
 
400
392
  // clean-up the schema and resolve references
401
- const cleanup = function (schema) {
393
+ interface JsonSchemaInternalCleanup extends JsonSchemaInternal {
394
+ ___$visited?: boolean;
395
+ }
396
+ const cleanup = function (schema: JsonSchemaInternalCleanup) {
402
397
  let key;
403
- const typeOf = Utils.whatIs(schema);
398
+ const typeOf = whatIs(schema);
404
399
  if (typeOf !== 'object' && typeOf !== 'array') {
405
400
  return;
406
401
  }
@@ -419,16 +414,16 @@ export class ZSchema {
419
414
  delete schema.__$refResolved;
420
415
  for (key in from) {
421
416
  if (Object.prototype.hasOwnProperty.call(from, key)) {
422
- to[key] = from[key];
417
+ (to as any)[key] = (from as any)[key];
423
418
  }
424
419
  }
425
420
  }
426
421
  for (key in schema) {
427
422
  if (Object.prototype.hasOwnProperty.call(schema, key)) {
428
423
  if (key.indexOf('__$') === 0) {
429
- delete schema[key];
424
+ delete (schema as any)[key];
430
425
  } else {
431
- cleanup(schema[key]);
426
+ cleanup((schema as any)[key]);
432
427
  }
433
428
  }
434
429
  }
@@ -449,7 +444,7 @@ export class ZSchema {
449
444
 
450
445
  static schemaReader: SchemaReader;
451
446
 
452
- setSchemaReader(schemaReader) {
447
+ setSchemaReader(schemaReader: SchemaReader) {
453
448
  return ZSchema.setSchemaReader(schemaReader);
454
449
  }
455
450
 
@@ -457,11 +452,11 @@ export class ZSchema {
457
452
  return ZSchema.schemaReader;
458
453
  }
459
454
 
460
- static setSchemaReader(schemaReader) {
455
+ static setSchemaReader(schemaReader: SchemaReader) {
461
456
  ZSchema.schemaReader = schemaReader;
462
457
  }
463
458
 
464
- static schemaSymbol = Utils.schemaSymbol;
459
+ static schemaSymbol = schemaSymbol;
465
460
 
466
- static jsonSymbol = Utils.jsonSymbol;
461
+ static jsonSymbol = jsonSymbol;
467
462
  }