json-schema-library 10.5.4 → 11.0.1

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 (39) hide show
  1. package/README.md +128 -14
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.d.cts +42 -19
  4. package/dist/index.d.mts +42 -19
  5. package/dist/index.mjs +1 -1
  6. package/dist/jlib.js +2 -2
  7. package/index.ts +8 -4
  8. package/package.json +6 -6
  9. package/src/Keyword.ts +8 -3
  10. package/src/SchemaNode.ts +46 -10
  11. package/src/compileSchema.validate.test.ts +89 -54
  12. package/src/draft04.ts +10 -8
  13. package/src/draft06.ts +10 -8
  14. package/src/draft07.ts +10 -8
  15. package/src/draft2019-09/keywords/additionalItems.ts +2 -2
  16. package/src/draft2019-09/keywords/items.ts +2 -2
  17. package/src/draft2019-09/keywords/unevaluatedItems.ts +12 -6
  18. package/src/draft2019.ts +10 -8
  19. package/src/draft2020.ts +8 -6
  20. package/src/errors/errors.ts +3 -1
  21. package/src/formats/formats.ts +2 -6
  22. package/src/keywords/additionalProperties.ts +2 -2
  23. package/src/keywords/allOf.ts +2 -2
  24. package/src/keywords/dependencies.ts +5 -6
  25. package/src/keywords/dependentRequired.ts +2 -2
  26. package/src/keywords/dependentSchemas.ts +4 -3
  27. package/src/keywords/deprecated.ts +18 -0
  28. package/src/keywords/items.ts +2 -2
  29. package/src/keywords/oneOf.test.ts +150 -15
  30. package/src/keywords/oneOf.ts +64 -4
  31. package/src/keywords/patternProperties.ts +2 -2
  32. package/src/keywords/prefixItems.ts +2 -11
  33. package/src/keywords/properties.ts +2 -2
  34. package/src/keywords/unevaluatedItems.ts +2 -2
  35. package/src/keywords/unevaluatedProperties.ts +2 -2
  36. package/src/methods/getData.test.ts +1779 -1781
  37. package/src/types.ts +32 -18
  38. package/src/utils/sanitizeErrors.ts +9 -8
  39. package/src/validateNode.ts +2 -2
package/index.ts CHANGED
@@ -3,16 +3,19 @@ export type { CompileOptions } from "./src/compileSchema";
3
3
  export type { Context, SchemaNode, GetNodeOptions, ValidateReturnType } from "./src/SchemaNode";
4
4
  export type { DataNode } from "./src/methods/toDataNodes";
5
5
  export type { Draft, DraftVersion } from "./src/Draft";
6
- export type { JsonError, JsonPointer, JsonSchema, OptionalNodeOrError, NodeOrError } from "./src/types";
6
+ export type { JsonError, JsonAnnotation, JsonPointer, JsonSchema, OptionalNodeOrError, NodeOrError } from "./src/types";
7
7
  export type {
8
8
  Keyword,
9
+ Maybe,
9
10
  ValidationPath,
10
11
  JsonSchemaReducerParams,
11
12
  JsonSchemaReducer,
12
13
  JsonSchemaResolverParams,
13
14
  JsonSchemaResolver,
14
15
  JsonSchemaValidatorParams,
15
- JsonSchemaValidator
16
+ JsonSchemaValidator,
17
+ ValidationAnnotation,
18
+ ValidationReturnType
16
19
  } from "./src/Keyword";
17
20
  export { default as settings } from "./src/settings";
18
21
 
@@ -29,16 +32,17 @@ export { oneOfFuzzyKeyword, oneOfKeyword } from "./src/keywords/oneOf";
29
32
 
30
33
  // errors
31
34
  export { render } from "./src/errors/render";
32
- export type { ErrorData, ErrorConfig } from "./src/types";
35
+ export type { Annotation, AnnotationData, ErrorConfig } from "./src/types";
33
36
 
34
37
  // utilities
35
38
  export { getTypeOf } from "./src/utils/getTypeOf";
36
39
  export { isReduceable } from "./src/SchemaNode";
37
- export { isJsonError, isSchemaNode } from "./src/types";
40
+ export { isJsonError, isJsonAnnotation, isAnnotation, isSchemaNode } from "./src/types";
38
41
  export { extendDraft, addKeywords } from "./src/Draft";
39
42
  export { mergeNode } from "./src/mergeNode";
40
43
  export { mergeSchema } from "./src/utils/mergeSchema";
41
44
  export { getSchemaType } from "./src/utils/getSchemaType";
45
+ export { default as sanitizeErrors } from "./src/utils/sanitizeErrors";
42
46
 
43
47
  // remotes
44
48
  export { remotes } from "./remotes";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-schema-library",
3
- "version": "10.5.4",
3
+ "version": "11.0.1",
4
4
  "description": "Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",
@@ -67,17 +67,17 @@
67
67
  "@eslint/js": "^10.0.1",
68
68
  "@types/glob": "^9.0.0",
69
69
  "@types/mocha": "^10.0.6",
70
- "@types/node": "^25.2.2",
70
+ "@types/node": "^25.2.3",
71
71
  "@types/valid-url": "^1.0.7",
72
72
  "eslint": "^9.39.2",
73
- "glob": "^13.0.1",
74
- "json-schema-test-suite": "https://github.com/json-schema-org/JSON-Schema-Test-Suite#83e866b46c9f9e7082fd51e83a61c5f2145a1ab7",
73
+ "glob": "^13.0.3",
74
+ "json-schema-test-suite": "https://github.com/json-schema-org/JSON-Schema-Test-Suite#Test-JSON-Schema-Acceptance-1.029",
75
75
  "mocha": "^11.7.5",
76
76
  "nyc": "^17.1.0",
77
77
  "tsdown": "^0.20.3",
78
78
  "tsx": "^4.21.0",
79
79
  "typescript": "^5.9.3",
80
- "typescript-eslint": "^8.54.0",
80
+ "typescript-eslint": "^8.55.0",
81
81
  "watch": "^1.0.1"
82
82
  },
83
83
  "dependencies": {
@@ -99,7 +99,7 @@
99
99
  "lodash": ">=4",
100
100
  "merge": ">=2",
101
101
  "micromatch": ">=4.0.8",
102
- "string-width": "^4.2.3"
102
+ "string-width": ">=4.2.3"
103
103
  },
104
104
  "publishConfig": {
105
105
  "registry": "https://registry.npmjs.org"
package/src/Keyword.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { SchemaNode, JsonError } from "./types";
1
+ import type { SchemaNode, JsonError, JsonAnnotation } from "./types";
2
2
 
3
3
  export type ValidationPath = {
4
4
  pointer: string;
@@ -30,13 +30,18 @@ export interface JsonSchemaResolver {
30
30
  (options: JsonSchemaResolverParams): SchemaNode | JsonError | undefined;
31
31
  }
32
32
 
33
- export type ValidationResult = JsonError | Promise<JsonError | undefined>;
33
+ // type MaybeAsync<T> = T | Promise<T>;
34
+ // type MaybeArray<T> = T | T[];
35
+ export type Maybe<T> = T | undefined;
36
+ export type ValidationAnnotation = JsonError | JsonAnnotation | Promise<Maybe<ValidationAnnotation>[]>;
37
+ type ValidationResult = Maybe<ValidationAnnotation>;
38
+ export type ValidationReturnType = ValidationResult | ValidationResult[];
34
39
 
35
40
  export type JsonSchemaValidatorParams = { pointer: string; data: unknown; node: SchemaNode; path: ValidationPath };
36
41
  export interface JsonSchemaValidator {
37
42
  toJSON?: () => string;
38
43
  order?: number;
39
- (options: JsonSchemaValidatorParams): undefined | Promise<undefined> | ValidationResult | ValidationResult[];
44
+ (options: JsonSchemaValidatorParams): ValidationReturnType;
40
45
  }
41
46
 
42
47
  export type Keyword = {
package/src/SchemaNode.ts CHANGED
@@ -1,7 +1,15 @@
1
1
  import { copy } from "fast-copy";
2
2
  import sanitizeErrors from "./utils/sanitizeErrors";
3
3
  import settings from "./settings";
4
- import type { JsonSchemaReducer, JsonSchemaResolver, JsonSchemaValidator, Keyword, ValidationPath } from "./Keyword";
4
+ import type {
5
+ JsonSchemaReducer,
6
+ JsonSchemaResolver,
7
+ JsonSchemaValidator,
8
+ Keyword,
9
+ Maybe,
10
+ ValidationAnnotation,
11
+ ValidationPath
12
+ } from "./Keyword";
5
13
  import { createSchema } from "./methods/createSchema";
6
14
  import { Draft } from "./Draft";
7
15
  import { toSchemaNodes } from "./methods/toSchemaNodes";
@@ -9,10 +17,12 @@ import {
9
17
  isJsonError,
10
18
  JsonSchema,
11
19
  JsonError,
12
- ErrorData,
20
+ AnnotationData,
13
21
  DefaultErrors,
14
22
  OptionalNodeOrError,
15
- NodeOrError
23
+ NodeOrError,
24
+ JsonAnnotation,
25
+ isJsonAnnotation
16
26
  } from "./types";
17
27
  import { isObject } from "./utils/isObject";
18
28
  import { join } from "@sagold/json-pointer";
@@ -180,7 +190,8 @@ export interface SchemaNode extends SchemaNodeMethodsType {
180
190
  */
181
191
  interface SchemaNodeMethodsType {
182
192
  compileSchema(schema: JsonSchema, evaluationPath?: string, schemaLocation?: string, dynamicId?: string): SchemaNode;
183
- createError<T extends string = DefaultErrors>(code: T, data: ErrorData, message?: string): JsonError;
193
+ createError<T extends string = DefaultErrors>(code: T, data: AnnotationData, message?: string): JsonError;
194
+ createAnnotation<T extends string = DefaultErrors>(code: T, data: AnnotationData, message?: string): JsonAnnotation;
184
195
  createSchema(data?: unknown): JsonSchema;
185
196
 
186
197
  // getNode overloads
@@ -201,7 +212,7 @@ interface SchemaNodeMethodsType {
201
212
  getNodeRef($ref: string): SchemaNode | undefined;
202
213
  getNodeRoot(): SchemaNode;
203
214
  getDraftVersion(): string;
204
- getData(data?: unknown, options?: TemplateOptions): unknown;
215
+ getData(data?: unknown, options?: TemplateOptions): any; // eslint-disable-line @typescript-eslint/no-explicit-any
205
216
  reduceNode(
206
217
  data: unknown,
207
218
  options?: { key?: string | number; pointer?: string; path?: ValidationPath }
@@ -241,10 +252,14 @@ export type ValidateReturnType = {
241
252
  * List of validation errors or empty
242
253
  */
243
254
  errors: JsonError[];
255
+ /**
256
+ * List of annotations from validators
257
+ */
258
+ annotations: JsonAnnotation[];
244
259
  /**
245
260
  * List of Promises resolving to `JsonError|undefined` or empty.
246
261
  */
247
- errorsAsync: Promise<JsonError | undefined>[];
262
+ errorsAsync: Promise<Maybe<ValidationAnnotation>[]>[];
248
263
  };
249
264
 
250
265
  export function joinDynamicId(a?: string, b?: string) {
@@ -290,7 +305,7 @@ export const SchemaNodeMethods = {
290
305
  return node;
291
306
  },
292
307
 
293
- createError<T extends string = DefaultErrors>(code: T, data: ErrorData, message?: string): JsonError {
308
+ createError<T extends string = DefaultErrors>(code: T, data: AnnotationData, message?: string): JsonError {
294
309
  const node = this as SchemaNode;
295
310
  let errorMessage = message;
296
311
  if (errorMessage === undefined) {
@@ -303,6 +318,23 @@ export const SchemaNodeMethods = {
303
318
  return { type: "error", code, message: errorMessage, data };
304
319
  },
305
320
 
321
+ createAnnotation<T extends string = DefaultErrors>(
322
+ code: T,
323
+ data: AnnotationData,
324
+ message?: string
325
+ ): JsonAnnotation {
326
+ const node = this as SchemaNode;
327
+ let annotationMessage = message;
328
+ if (annotationMessage === undefined) {
329
+ const error = node.schema?.errorMessages?.[code] ?? node.context.errors[code];
330
+ if (typeof error === "function") {
331
+ return error(data);
332
+ }
333
+ annotationMessage = render(error ?? name, data);
334
+ }
335
+ return { type: "annotation", code, message: annotationMessage, data };
336
+ },
337
+
306
338
  createSchema,
307
339
 
308
340
  getChildSelection(property: string | number): JsonError | SchemaNode[] {
@@ -412,20 +444,24 @@ export const SchemaNodeMethods = {
412
444
  const node = this as SchemaNode;
413
445
  const errors = validateNode(node, data, pointer, path) ?? [];
414
446
  const syncErrors: JsonError[] = [];
447
+ const annotations: JsonAnnotation[] = [];
415
448
  const flatErrorList = sanitizeErrors(Array.isArray(errors) ? errors : [errors]).filter(isJsonError);
416
449
 
417
- const errorsAsync: Promise<JsonError | undefined>[] = [];
450
+ const errorsAsync: Promise<Maybe<ValidationAnnotation>[]>[] = [];
418
451
  sanitizeErrors(Array.isArray(errors) ? errors : [errors]).forEach((error) => {
419
452
  if (isJsonError(error)) {
420
453
  syncErrors.push(error);
421
454
  } else if (error instanceof Promise) {
422
- errorsAsync.push(error);
455
+ errorsAsync.push(error.then(sanitizeErrors));
456
+ } else if (isJsonAnnotation(error)) {
457
+ annotations.push(error);
423
458
  }
424
459
  });
425
460
 
426
461
  const result: ValidateReturnType = {
427
462
  valid: flatErrorList.length === 0,
428
463
  errors: syncErrors,
464
+ annotations,
429
465
  errorsAsync
430
466
  };
431
467
 
@@ -478,7 +514,7 @@ export const SchemaNodeMethods = {
478
514
  * @returns a list of all sub-schema as SchemaNode
479
515
  */
480
516
  toSchemaNodes() {
481
- return toSchemaNodes(this as SchemaNode);
517
+ return toSchemaNodes(this);
482
518
  },
483
519
 
484
520
  /**
@@ -1,11 +1,12 @@
1
1
  import { compileSchema } from "./compileSchema";
2
2
  import { strict as assert } from "assert";
3
- import { Draft, JsonError, SchemaNode } from "./types";
3
+ import { Draft, isJsonError, SchemaNode } from "./types";
4
4
  import { draft2020 } from "./draft2020";
5
+ import sanitizeErrors from "./utils/sanitizeErrors";
5
6
 
6
- describe("compileSchema.validate", () => {
7
+ describe("compileSchema : validate", () => {
8
+ // note: boolean schema is already thoroughly tested by spec
7
9
  describe("boolean schema", () => {
8
- // note: all this is tested in spec already
9
10
  it("should fail if root schema is false", () => {
10
11
  // @ts-expect-error boolean typ unsupported
11
12
  const { errors } = compileSchema(false).validate("anything");
@@ -995,73 +996,107 @@ describe("compileSchema.validate - errorsAsync", () => {
995
996
  ...draft2020.keywords,
996
997
  {
997
998
  id: "async",
998
- keyword: "async-error",
999
+ keyword: "asyncError",
999
1000
  addValidate: (node) => node.schema.asyncError != null,
1000
- validate: async ({ node }): Promise<JsonError> => {
1001
+ validate: async ({ node }) => {
1001
1002
  if (node.schema.asyncError === false) {
1002
- return undefined;
1003
+ return [undefined];
1003
1004
  }
1004
- return node.createError("type-error", {
1005
- schema: {},
1006
- pointer: "",
1007
- value: ""
1008
- });
1005
+ return [
1006
+ node.createError("type-error", {
1007
+ schema: {},
1008
+ pointer: "",
1009
+ value: ""
1010
+ })
1011
+ ];
1009
1012
  }
1010
1013
  }
1011
1014
  ]
1012
1015
  };
1016
+ });
1013
1017
 
1014
- it("should resolve async validation returning no error", async () => {
1015
- const { errors, errorsAsync } = compileSchema(
1016
- { type: "number", asyncError: false },
1017
- { drafts: [draft] }
1018
- ).validate(4);
1019
- const asyncErrors = await Promise.all(errorsAsync);
1020
- assert.deepEqual(errors.length, 0);
1021
- assert.deepEqual(asyncErrors.length, 0);
1022
- });
1018
+ it("should resolve async validation returning no error", async () => {
1019
+ const { errors, errorsAsync } = compileSchema(
1020
+ { type: "number", asyncError: false },
1021
+ { drafts: [draft] }
1022
+ ).validate(4);
1023
1023
 
1024
- it("should resolve async validation errors", async () => {
1025
- const { errorsAsync } = compileSchema(
1026
- { type: "number", asyncError: true },
1027
- { drafts: [draft] }
1028
- ).validate(4);
1029
- const asyncErrors = await Promise.all(errorsAsync);
1030
- assert.deepEqual(asyncErrors.length, 1);
1031
- assert.deepEqual(asyncErrors[0].code, "type-error");
1032
- });
1024
+ const asyncErrors = sanitizeErrors(await Promise.all(errorsAsync));
1025
+ assert.deepEqual(errors.length, 0);
1026
+ assert.deepEqual(asyncErrors.length, 0);
1027
+ });
1028
+
1029
+ it("should resolve async validation errors", async () => {
1030
+ const { errorsAsync } = compileSchema({ type: "number", asyncError: true }, { drafts: [draft] }).validate(
1031
+ 4
1032
+ );
1033
+
1034
+ const asyncErrors = sanitizeErrors(await Promise.all(errorsAsync));
1035
+ assert.deepEqual(asyncErrors.length, 1, "should have resolved promise to return error");
1036
+ assert(isJsonError(asyncErrors[0]));
1037
+ assert.deepEqual(asyncErrors[0].code, "type-error");
1033
1038
  });
1034
1039
  });
1035
1040
  });
1036
1041
 
1037
- describe("compileSchema.validate - custom errors", () => {
1038
- it("should return custom error message for minItems", () => {
1039
- const { errors } = compileSchema({
1040
- type: "array",
1041
- minItems: 2,
1042
- errorMessages: {
1043
- "min-items-error": "Custom error {{minItems}}"
1042
+ describe("annotation", () => {
1043
+ let draft: Draft;
1044
+ beforeEach(() => {
1045
+ draft = {
1046
+ ...draft2020,
1047
+ keywords: [
1048
+ ...draft2020.keywords,
1049
+ {
1050
+ id: "annotation",
1051
+ keyword: "annotation",
1052
+ addValidate: (node) => node.schema.annotation === true,
1053
+ validate: ({ node }) =>
1054
+ node.createAnnotation("deprecated-warning", {
1055
+ schema: {},
1056
+ pointer: "",
1057
+ value: ""
1058
+ })
1059
+ }
1060
+ ]
1061
+ };
1062
+ });
1063
+
1064
+ it("should return annotations-property from validate", async () => {
1065
+ const { annotations } = compileSchema(
1066
+ {
1067
+ type: "number",
1068
+ annotation: true
1069
+ },
1070
+ {
1071
+ drafts: [draft]
1044
1072
  }
1045
- }).validate([1]);
1046
- assert.deepEqual(errors.length, 1);
1047
- assert.deepEqual(errors[0].message, "Custom error 2");
1073
+ ).validate(4);
1074
+
1075
+ assert(Array.isArray(annotations));
1048
1076
  });
1049
1077
 
1050
- it("should return custom error for oneOf-error", () => {
1051
- const { errors } = compileSchema({
1052
- type: "array",
1053
- items: {
1054
- errorMessages: {
1055
- "one-of-error": "{{value}} does not match any of the options"
1056
- },
1057
- oneOf: [
1058
- { type: "number" },
1059
- { type: "object", properties: { a: { type: "string" } }, additionalProperties: false }
1060
- ]
1078
+ it("should add annotations to annotations-property", async () => {
1079
+ const { annotations } = compileSchema(
1080
+ {
1081
+ type: "number",
1082
+ annotation: true
1061
1083
  },
1062
- additionalItems: false
1063
- }).validate([100, { a: "correct", b: "not correct" }]);
1064
- assert.deepEqual(errors.length, 1);
1065
- assert.deepEqual(errors[0].message, '{"a":"correct","b":"not correct"} does not match any of the options');
1084
+ {
1085
+ drafts: [draft]
1086
+ }
1087
+ ).validate(4);
1088
+
1089
+ assert.equal(annotations.length, 1);
1090
+ assert.equal(annotations[0].code, "deprecated-warning");
1091
+ });
1092
+
1093
+ it("should return deprecated-warning annotation per default", async () => {
1094
+ const { annotations } = compileSchema({
1095
+ type: "number",
1096
+ deprecated: true
1097
+ }).validate(4);
1098
+
1099
+ assert.equal(annotations.length, 1);
1100
+ assert.equal(annotations[0].code, "deprecated-warning");
1066
1101
  });
1067
1102
  });
package/src/draft04.ts CHANGED
@@ -1,14 +1,21 @@
1
+ import { $defsKeyword } from "./keywords/$defs";
2
+ import { $refKeyword } from "./draft04/keywords/$ref";
1
3
  import { additionalItemsKeyword } from "./draft2019-09/keywords/additionalItems";
2
4
  import { additionalPropertiesKeyword } from "./keywords/additionalProperties";
3
5
  import { allOfKeyword } from "./keywords/allOf";
4
6
  import { anyOfKeyword } from "./keywords/anyOf";
5
7
  import { containsKeyword } from "./keywords/contains";
6
- import { $defsKeyword } from "./keywords/$defs";
8
+ import { createSchema } from "./methods/createSchema";
7
9
  import { dependenciesKeyword } from "./keywords/dependencies";
10
+ import { deprecatedKeyword } from "./keywords/deprecated";
8
11
  import { enumKeyword } from "./keywords/enum";
12
+ import { errors } from "./errors/errors";
9
13
  import { exclusiveMaximumKeyword } from "./draft04/keywords/exclusiveMaximum";
10
14
  import { exclusiveMinimumKeyword } from "./draft04/keywords/exclusiveMinimum";
11
15
  import { formatKeyword } from "./keywords/format";
16
+ import { formats } from "./formats/formats";
17
+ import { getChildSelection } from "./draft2019-09/methods/getChildSelection";
18
+ import { getData } from "./draft2019-09/methods/getData";
12
19
  import { itemsKeyword } from "./draft2019-09/keywords/items";
13
20
  import { maximumKeyword } from "./keywords/maximum";
14
21
  import { maxItemsKeyword } from "./keywords/maxItems";
@@ -25,17 +32,11 @@ import { patternKeyword } from "./keywords/pattern";
25
32
  import { patternPropertiesKeyword } from "./keywords/patternProperties";
26
33
  import { propertiesKeyword } from "./keywords/properties";
27
34
  import { propertyNamesKeyword } from "./keywords/propertyNames";
28
- import { $refKeyword } from "./draft04/keywords/$ref";
29
35
  import { requiredKeyword } from "./keywords/required";
30
36
  import { sanitizeKeywords } from "./Draft";
37
+ import { toDataNodes } from "./methods/toDataNodes";
31
38
  import { typeKeyword } from "./keywords/type";
32
39
  import { uniqueItemsKeyword } from "./keywords/uniqueItems";
33
- import { getChildSelection } from "./draft2019-09/methods/getChildSelection";
34
- import { getData } from "./draft2019-09/methods/getData";
35
- import { toDataNodes } from "./methods/toDataNodes";
36
- import { createSchema } from "./methods/createSchema";
37
- import { errors } from "./errors/errors";
38
- import { formats } from "./formats/formats";
39
40
 
40
41
  /**
41
42
  * @draft-04
@@ -77,6 +78,7 @@ export const draft04 = sanitizeKeywords({
77
78
  containsKeyword,
78
79
  $defsKeyword,
79
80
  dependenciesKeyword, // optional support for old draft-version
81
+ deprecatedKeyword,
80
82
  enumKeyword,
81
83
  exclusiveMaximumKeyword,
82
84
  exclusiveMinimumKeyword,
package/src/draft06.ts CHANGED
@@ -1,15 +1,22 @@
1
+ import { $defsKeyword } from "./keywords/$defs";
2
+ import { $refKeyword } from "./draft06/keywords/$ref";
1
3
  import { additionalItemsKeyword } from "./draft2019-09/keywords/additionalItems";
2
4
  import { additionalPropertiesKeyword } from "./keywords/additionalProperties";
3
5
  import { allOfKeyword } from "./keywords/allOf";
4
6
  import { anyOfKeyword } from "./keywords/anyOf";
5
7
  import { constKeyword } from "./keywords/const";
6
8
  import { containsKeyword } from "./keywords/contains";
7
- import { $defsKeyword } from "./keywords/$defs";
9
+ import { createSchema } from "./methods/createSchema";
8
10
  import { dependenciesKeyword } from "./keywords/dependencies";
11
+ import { deprecatedKeyword } from "./keywords/deprecated";
9
12
  import { enumKeyword } from "./keywords/enum";
13
+ import { errors } from "./errors/errors";
10
14
  import { exclusiveMaximumKeyword } from "./keywords/exclusiveMaximum";
11
15
  import { exclusiveMinimumKeyword } from "./keywords/exclusiveMinimum";
12
16
  import { formatKeyword } from "./keywords/format";
17
+ import { formats } from "./formats/formats";
18
+ import { getChildSelection } from "./draft2019-09/methods/getChildSelection";
19
+ import { getData } from "./draft2019-09/methods/getData";
13
20
  import { itemsKeyword } from "./draft2019-09/keywords/items";
14
21
  import { maximumKeyword } from "./keywords/maximum";
15
22
  import { maxItemsKeyword } from "./keywords/maxItems";
@@ -26,17 +33,11 @@ import { patternKeyword } from "./keywords/pattern";
26
33
  import { patternPropertiesKeyword } from "./keywords/patternProperties";
27
34
  import { propertiesKeyword } from "./keywords/properties";
28
35
  import { propertyNamesKeyword } from "./keywords/propertyNames";
29
- import { $refKeyword } from "./draft06/keywords/$ref";
30
36
  import { requiredKeyword } from "./keywords/required";
31
37
  import { sanitizeKeywords } from "./Draft";
38
+ import { toDataNodes } from "./methods/toDataNodes";
32
39
  import { typeKeyword } from "./keywords/type";
33
40
  import { uniqueItemsKeyword } from "./keywords/uniqueItems";
34
- import { getChildSelection } from "./draft2019-09/methods/getChildSelection";
35
- import { getData } from "./draft2019-09/methods/getData";
36
- import { toDataNodes } from "./methods/toDataNodes";
37
- import { createSchema } from "./methods/createSchema";
38
- import { errors } from "./errors/errors";
39
- import { formats } from "./formats/formats";
40
41
 
41
42
  /**
42
43
  * @draft-06 https://json-schema.org/draft-06/json-schema-release-notes
@@ -79,6 +80,7 @@ export const draft06 = sanitizeKeywords({
79
80
  containsKeyword,
80
81
  $defsKeyword,
81
82
  dependenciesKeyword, // optional support for old draft-version
83
+ deprecatedKeyword,
82
84
  enumKeyword,
83
85
  exclusiveMaximumKeyword,
84
86
  exclusiveMinimumKeyword,
package/src/draft07.ts CHANGED
@@ -1,15 +1,22 @@
1
+ import { $defsKeyword } from "./keywords/$defs";
2
+ import { $refKeyword } from "./draft06/keywords/$ref";
1
3
  import { additionalItemsKeyword } from "./draft2019-09/keywords/additionalItems";
2
4
  import { additionalPropertiesKeyword } from "./keywords/additionalProperties";
3
5
  import { allOfKeyword } from "./keywords/allOf";
4
6
  import { anyOfKeyword } from "./keywords/anyOf";
5
7
  import { constKeyword } from "./keywords/const";
6
8
  import { containsKeyword } from "./keywords/contains";
7
- import { $defsKeyword } from "./keywords/$defs";
9
+ import { createSchema } from "./methods/createSchema";
8
10
  import { dependenciesKeyword } from "./keywords/dependencies";
11
+ import { deprecatedKeyword } from "./keywords/deprecated";
9
12
  import { enumKeyword } from "./keywords/enum";
13
+ import { errors } from "./errors/errors";
10
14
  import { exclusiveMaximumKeyword } from "./keywords/exclusiveMaximum";
11
15
  import { exclusiveMinimumKeyword } from "./keywords/exclusiveMinimum";
12
16
  import { formatKeyword } from "./keywords/format";
17
+ import { formats } from "./formats/formats";
18
+ import { getChildSelection } from "./draft2019-09/methods/getChildSelection";
19
+ import { getData } from "./draft2019-09/methods/getData";
13
20
  import { ifKeyword } from "./keywords/ifthenelse";
14
21
  import { itemsKeyword } from "./draft2019-09/keywords/items";
15
22
  import { maximumKeyword } from "./keywords/maximum";
@@ -27,17 +34,11 @@ import { patternKeyword } from "./keywords/pattern";
27
34
  import { patternPropertiesKeyword } from "./keywords/patternProperties";
28
35
  import { propertiesKeyword } from "./keywords/properties";
29
36
  import { propertyNamesKeyword } from "./keywords/propertyNames";
30
- import { $refKeyword } from "./draft06/keywords/$ref";
31
37
  import { requiredKeyword } from "./keywords/required";
32
38
  import { sanitizeKeywords } from "./Draft";
39
+ import { toDataNodes } from "./methods/toDataNodes";
33
40
  import { typeKeyword } from "./keywords/type";
34
41
  import { uniqueItemsKeyword } from "./keywords/uniqueItems";
35
- import { getChildSelection } from "./draft2019-09/methods/getChildSelection";
36
- import { getData } from "./draft2019-09/methods/getData";
37
- import { toDataNodes } from "./methods/toDataNodes";
38
- import { createSchema } from "./methods/createSchema";
39
- import { errors } from "./errors/errors";
40
- import { formats } from "./formats/formats";
41
42
 
42
43
  /**
43
44
  * @draft-07 https://json-schema.org/draft-07/json-schema-release-notes
@@ -70,6 +71,7 @@ export const draft07 = sanitizeKeywords({
70
71
  containsKeyword,
71
72
  $defsKeyword,
72
73
  dependenciesKeyword, // optional support for old draft-version
74
+ deprecatedKeyword,
73
75
  enumKeyword,
74
76
  exclusiveMaximumKeyword,
75
77
  exclusiveMinimumKeyword,
@@ -1,5 +1,5 @@
1
1
  import { isObject } from "../../utils/isObject";
2
- import { Keyword, JsonSchemaResolverParams, JsonSchemaValidatorParams, ValidationResult } from "../../Keyword";
2
+ import { Keyword, JsonSchemaResolverParams, JsonSchemaValidatorParams, ValidationReturnType } from "../../Keyword";
3
3
  import { SchemaNode } from "../../types";
4
4
  import { getValue } from "../../utils/getValue";
5
5
  import { validateNode } from "../../validateNode";
@@ -49,7 +49,7 @@ function validateAdditionalItems({ node, data, pointer, path }: JsonSchemaValida
49
49
  return;
50
50
  }
51
51
  const startIndex = Array.isArray(schema.items) ? schema.items.length : 0;
52
- const errors: ValidationResult[] = [];
52
+ const errors: ValidationReturnType = [];
53
53
  for (let i = startIndex; i < data.length; i += 1) {
54
54
  const item = data[i];
55
55
  if (node.items) {
@@ -1,4 +1,4 @@
1
- import { Keyword, JsonSchemaResolverParams, JsonSchemaValidatorParams, ValidationResult } from "../../Keyword";
1
+ import { Keyword, JsonSchemaResolverParams, JsonSchemaValidatorParams, ValidationReturnType } from "../../Keyword";
2
2
  import { SchemaNode } from "../../types";
3
3
  import { isObject } from "../../utils/isObject";
4
4
  import { validateNode } from "../../validateNode";
@@ -52,7 +52,7 @@ function validateItems({ node, data, pointer = "#", path }: JsonSchemaValidatorP
52
52
  return node.createError("invalid-data-error", { pointer, value: data, schema });
53
53
  }
54
54
 
55
- const errors: ValidationResult[] = [];
55
+ const errors: ValidationReturnType = [];
56
56
  if (node.prefixItems) {
57
57
  // note: schema is valid when data does not have enough elements as defined by array-list
58
58
  for (let i = 0; i < Math.min(node.prefixItems.length, data.length); i += 1) {
@@ -1,7 +1,6 @@
1
1
  import { isObject } from "../../utils/isObject";
2
2
  import { SchemaNode } from "../../types";
3
- import { Keyword, JsonSchemaValidatorParams, ValidationResult } from "../../Keyword";
4
- import sanitizeErrors from "../../utils/sanitizeErrors";
3
+ import { Keyword, JsonSchemaValidatorParams, ValidationReturnType } from "../../Keyword";
5
4
  import { validateNode } from "../../validateNode";
6
5
 
7
6
  /**
@@ -50,7 +49,7 @@ function validateUnevaluatedItems({ node, data, pointer, path }: JsonSchemaValid
50
49
  // console.log("EVAL", reducedNode.schema);
51
50
 
52
51
  const validIf = node.if != null && validateNode(node.if, data, pointer, path).length === 0;
53
- const errors: ValidationResult[] = [];
52
+ const errors: ValidationReturnType = [];
54
53
  // "unevaluatedItems with nested items"
55
54
  for (let i = 0; i < data.length; i += 1) {
56
55
  const value = data[i];
@@ -63,9 +62,16 @@ function validateUnevaluatedItems({ node, data, pointer, path }: JsonSchemaValid
63
62
  // nothing should validate, so we validate unevaluated items only
64
63
  const unevaluatedItems = node.unevaluatedItems;
65
64
  if (unevaluatedItems) {
66
- return sanitizeErrors(
67
- data.map((value) => validateNode(unevaluatedItems, value, `${pointer}/${i}`, path))
68
- );
65
+ data.forEach((value) => {
66
+ const result = validateNode(unevaluatedItems, value, `${pointer}/${i}`, path);
67
+ if (result == null) {
68
+ return;
69
+ }
70
+ if (Array.isArray(result)) {
71
+ return errors.push(...result);
72
+ }
73
+ errors.push(result);
74
+ });
69
75
  }
70
76
  if (node.schema.unevaluatedItems === false) {
71
77
  return node.createError("unevaluated-items-error", {