json-schema-library 11.0.5 → 11.2.0

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 (113) hide show
  1. package/.mocharc.js +1 -0
  2. package/CHANGELOG.md +17 -0
  3. package/README.md +120 -0
  4. package/bowtie/.editorconfig +21 -0
  5. package/bowtie/.prettierrc +6 -0
  6. package/bowtie/BOWTIE.md +54 -0
  7. package/bowtie/Dockerfile +6 -0
  8. package/bowtie/bowtie-api.ts +101 -0
  9. package/bowtie/bowtie.test.ts +76 -0
  10. package/bowtie/bowtie.ts +156 -0
  11. package/bowtie/package.json +11 -0
  12. package/bowtie/tsconfig.json +12 -0
  13. package/dist/index.cjs +1 -1
  14. package/dist/index.d.cts +39 -470
  15. package/dist/index.d.mts +39 -470
  16. package/dist/index.mjs +1 -1
  17. package/dist/jlib.js +2 -13
  18. package/dist/remotes/index.cjs +1 -0
  19. package/dist/remotes/index.d.cts +7 -0
  20. package/dist/remotes/index.d.mts +7 -0
  21. package/dist/remotes/index.mjs +1 -0
  22. package/dist/types-B2wwNWyo.d.cts +513 -0
  23. package/dist/types-BhTU1l2h.d.mts +513 -0
  24. package/index.ts +10 -4
  25. package/package.json +14 -8
  26. package/src/Keyword.ts +37 -12
  27. package/src/SchemaNode.ts +84 -16
  28. package/src/compileSchema.ts +56 -4
  29. package/src/draft04/keywords/$ref.ts +22 -14
  30. package/src/draft04/keywords/exclusiveMaximum.ts +14 -0
  31. package/src/draft04/keywords/exclusiveMinimum.ts +14 -0
  32. package/src/draft04/validateSchema.test.ts +20 -0
  33. package/src/draft06/keywords/$ref.ts +15 -5
  34. package/src/draft2019-09/keywords/$ref.test.ts +3 -1
  35. package/src/draft2019-09/keywords/$ref.ts +40 -16
  36. package/src/draft2019-09/keywords/additionalItems.ts +33 -10
  37. package/src/draft2019-09/keywords/items.ts +32 -10
  38. package/src/draft2019-09/keywords/unevaluatedItems.ts +19 -6
  39. package/src/draft2019-09/methods/getData.ts +1 -1
  40. package/src/draft2019-09/validateSchema.test.ts +28 -0
  41. package/src/errors/errors.ts +8 -1
  42. package/src/formats/formats.ts +35 -28
  43. package/src/formats/hyperjump.d.ts +172 -0
  44. package/src/keywords/$defs.ts +34 -8
  45. package/src/keywords/$ref.ts +59 -13
  46. package/src/keywords/additionalProperties.ts +19 -8
  47. package/src/keywords/allOf.ts +44 -18
  48. package/src/keywords/anyOf.ts +38 -19
  49. package/src/keywords/contains.ts +21 -9
  50. package/src/keywords/dependencies.ts +37 -17
  51. package/src/keywords/dependentRequired.ts +56 -38
  52. package/src/keywords/dependentSchemas.ts +37 -13
  53. package/src/keywords/deprecated.ts +32 -8
  54. package/src/keywords/enum.ts +30 -8
  55. package/src/keywords/exclusiveMaximum.ts +21 -2
  56. package/src/keywords/exclusiveMinimum.ts +22 -3
  57. package/src/keywords/format.ts +21 -2
  58. package/src/keywords/ifthenelse.ts +49 -5
  59. package/src/keywords/items.ts +27 -13
  60. package/src/keywords/maxItems.ts +22 -2
  61. package/src/keywords/maxLength.ts +30 -9
  62. package/src/keywords/maxProperties.ts +30 -9
  63. package/src/keywords/maximum.ts +28 -8
  64. package/src/keywords/minItems.ts +30 -9
  65. package/src/keywords/minLength.ts +30 -9
  66. package/src/keywords/minProperties.ts +26 -5
  67. package/src/keywords/minimum.ts +32 -13
  68. package/src/keywords/multipleOf.ts +33 -12
  69. package/src/keywords/not.ts +23 -10
  70. package/src/keywords/oneOf.ts +29 -9
  71. package/src/keywords/pattern.ts +35 -9
  72. package/src/keywords/properties.ts +34 -11
  73. package/src/keywords/propertyDependencies.test.ts +180 -0
  74. package/src/keywords/propertyDependencies.ts +173 -0
  75. package/src/keywords/propertyNames.ts +26 -14
  76. package/src/keywords/required.ts +31 -8
  77. package/src/keywords/type.ts +53 -16
  78. package/src/keywords/unevaluatedItems.ts +24 -8
  79. package/src/keywords/unevaluatedProperties.ts +24 -7
  80. package/src/keywords/uniqueItems.ts +23 -4
  81. package/src/mergeNode.ts +9 -4
  82. package/src/methods/getData.ts +1 -1
  83. package/src/settings.ts +2 -1
  84. package/src/types.ts +1 -1
  85. package/src/utils/isListOfStrings.ts +3 -0
  86. package/src/validate.test.ts +0 -2
  87. package/src/validateNode.ts +6 -3
  88. package/src/validateSchema.test.ts +312 -0
  89. package/tsconfig.json +11 -4
  90. package/tsconfig.test.json +9 -2
  91. package/tsdown.config.ts +1 -1
  92. package/Dockerfile +0 -6
  93. package/bowtie_jlib.js +0 -140
  94. package/remotes/draft04.json +0 -150
  95. package/remotes/draft06.json +0 -155
  96. package/remotes/draft07.json +0 -155
  97. package/remotes/draft2019-09.json +0 -42
  98. package/remotes/draft2019-09_meta_applicator.json +0 -53
  99. package/remotes/draft2019-09_meta_content.json +0 -14
  100. package/remotes/draft2019-09_meta_core.json +0 -54
  101. package/remotes/draft2019-09_meta_format.json +0 -11
  102. package/remotes/draft2019-09_meta_meta-data.json +0 -34
  103. package/remotes/draft2019-09_meta_validation.json +0 -95
  104. package/remotes/draft2020-12.json +0 -55
  105. package/remotes/draft2020-12_meta_applicator.json +0 -45
  106. package/remotes/draft2020-12_meta_content.json +0 -14
  107. package/remotes/draft2020-12_meta_core.json +0 -48
  108. package/remotes/draft2020-12_meta_format_annotation.json +0 -11
  109. package/remotes/draft2020-12_meta_format_assertion.json +0 -11
  110. package/remotes/draft2020-12_meta_meta_data.json +0 -34
  111. package/remotes/draft2020-12_meta_unevaluated.json +0 -12
  112. package/remotes/draft2020-12_meta_validation.json +0 -87
  113. package/remotes/index.ts +0 -48
@@ -1,26 +1,43 @@
1
1
  import { isObject } from "../utils/isObject";
2
- import { SchemaNode } from "../types";
2
+ import { isBooleanSchema, isJsonSchema, SchemaNode } from "../types";
3
3
  import { Keyword, JsonSchemaValidatorParams, ValidationReturnType } from "../Keyword";
4
4
  import { validateNode } from "../validateNode";
5
5
  import { isPropertyEvaluated } from "../isPropertyEvaluated";
6
6
 
7
+ const KEYWORD = "unevaluatedProperties";
8
+
7
9
  export const unevaluatedPropertiesKeyword: Keyword = {
8
- id: "unevaluatedProperties",
9
- keyword: "unevaluatedProperties",
10
+ id: KEYWORD,
11
+ keyword: KEYWORD,
10
12
  parse: parseUnevaluatedProperties,
11
- addValidate: ({ schema }) => schema.unevaluatedProperties != null,
13
+ addValidate: ({ schema }) => schema[KEYWORD] != null, // currently we do not store boolean schema
12
14
  validate: validateUnevaluatedProperties
13
15
  };
14
16
 
15
17
  export function parseUnevaluatedProperties(node: SchemaNode) {
16
- if (!isObject(node.schema.unevaluatedProperties)) {
18
+ const unevaluatedProperties = node.schema[KEYWORD];
19
+ if (unevaluatedProperties == null) {
20
+ return;
21
+ }
22
+ if (!(isJsonSchema(unevaluatedProperties) || isBooleanSchema(unevaluatedProperties))) {
23
+ return node.createError("schema-error", {
24
+ pointer: `${node.schemaLocation}/${KEYWORD}`,
25
+ schema: node.schema,
26
+ value: unevaluatedProperties,
27
+ message: `Keyword '${KEYWORD}' must be a valid JSON Schema - received '${typeof unevaluatedProperties}'`
28
+ });
29
+ }
30
+
31
+ if (isBooleanSchema(unevaluatedProperties)) {
17
32
  return;
18
33
  }
34
+
19
35
  node.unevaluatedProperties = node.compileSchema(
20
36
  node.schema.unevaluatedProperties,
21
- `${node.evaluationPath}/unevaluatedProperties`,
22
- `${node.schemaLocation}/unevaluatedProperties`
37
+ `${node.evaluationPath}/${KEYWORD}`,
38
+ `${node.schemaLocation}/${KEYWORD}`
23
39
  );
40
+ return node.unevaluatedProperties.schemaValidation;
24
41
  }
25
42
 
26
43
  // @todo we should use collected annotation to evaluated unevaluate properties
@@ -1,14 +1,33 @@
1
- import { JsonError } from "../types";
1
+ import { JsonError, SchemaNode } from "../types";
2
2
  import { Keyword, JsonSchemaValidatorParams } from "../Keyword";
3
3
  import deepEqual from "fast-deep-equal";
4
4
 
5
+ const KEYWORD = "uniqueItems";
6
+
5
7
  export const uniqueItemsKeyword: Keyword = {
6
- id: "uniqueItems",
7
- keyword: "uniqueItems",
8
- addValidate: ({ schema }) => schema.uniqueItems === true,
8
+ id: KEYWORD,
9
+ keyword: KEYWORD,
10
+ parse: parseUniqueItems,
11
+ addValidate: ({ schema }) => schema[KEYWORD] === true,
9
12
  validate: validateUniqueItems
10
13
  };
11
14
 
15
+ function parseUniqueItems(node: SchemaNode) {
16
+ const uniqueItems = node.schema[KEYWORD];
17
+ if (uniqueItems == null || uniqueItems === false) {
18
+ return;
19
+ }
20
+ if (typeof uniqueItems !== "boolean") {
21
+ return node.createError("schema-error", {
22
+ pointer: `${node.schemaLocation}/${KEYWORD}`,
23
+ schema: node.schema,
24
+ value: uniqueItems,
25
+ message: `Keyword '${KEYWORD}' must be a boolean - received ${typeof uniqueItems}`
26
+ });
27
+ }
28
+ node.uniqueItems = true;
29
+ }
30
+
12
31
  function validateUniqueItems({ node, data, pointer }: JsonSchemaValidatorParams) {
13
32
  if (!Array.isArray(data)) {
14
33
  return undefined;
package/src/mergeNode.ts CHANGED
@@ -37,9 +37,12 @@ function mergeObjects(a?: Record<string, SchemaNode>, b?: Record<string, SchemaN
37
37
  return object;
38
38
  }
39
39
 
40
- // function mergeArray<T = unknown[]>(a?: T[], b?: T[]) {
41
- // return a || b ? [...(a ?? []), ...(b ?? [])] : undefined;
42
- // }
40
+ function combineArrays<T>(a?: T[], b?: T[]): T[] | undefined {
41
+ if (a == null || b == null) {
42
+ return b || a;
43
+ }
44
+ return a.concat(b).filter((value, index, list) => list.indexOf(value) === index);
45
+ }
43
46
 
44
47
  function mergePatternProperties(a?: SchemaNode["patternProperties"], b?: SchemaNode["patternProperties"]) {
45
48
  if (a == null || b == null) {
@@ -92,6 +95,7 @@ export function mergeNode(a?: SchemaNode, b?: SchemaNode, ...omit: string[]): Sc
92
95
 
93
96
  additionalProperties: mergeNode(a.additionalProperties, b.additionalProperties),
94
97
  contains: mergeNode(a.contains, b.contains),
98
+ enum: combineArrays(a.enum, b.enum),
95
99
  if: mergeNode(a.if, b.if),
96
100
  then: mergeNode(a.then, b.then),
97
101
  else: mergeNode(a.else, b.else),
@@ -101,7 +105,8 @@ export function mergeNode(a?: SchemaNode, b?: SchemaNode, ...omit: string[]): Sc
101
105
  unevaluatedItems: mergeNode(a.unevaluatedItems, b.unevaluatedItems),
102
106
  $defs: mergeObjects(a.$defs, b.$defs),
103
107
  patternProperties: mergePatternProperties(a.patternProperties, b.patternProperties),
104
- properties: mergeObjects(a.properties, b.properties)
108
+ properties: mergeObjects(a.properties, b.properties),
109
+ required: combineArrays(a.required, b.required)
105
110
  };
106
111
 
107
112
  // this removes any function that has no keyword associated on schema
@@ -159,7 +159,7 @@ export function getData(node: SchemaNode, data?: unknown, opts?: TemplateOptions
159
159
  return defaultData;
160
160
  }
161
161
 
162
- if (resolvedNode && resolvedNode !== currentNode) {
162
+ if (isSchemaNode(resolvedNode)) {
163
163
  defaultData = resolvedNode.getData(defaultData, opts) ?? defaultData;
164
164
  currentNode = resolvedNode;
165
165
  }
package/src/settings.ts CHANGED
@@ -14,7 +14,8 @@ export default {
14
14
  "dependentRequired",
15
15
  "definitions",
16
16
  "dependencies",
17
- "patternProperties"
17
+ "patternProperties",
18
+ "propertyDependencies"
18
19
  ],
19
20
  REGEX_FLAGS: "u"
20
21
  };
package/src/types.ts CHANGED
@@ -67,5 +67,5 @@ export function isJsonError(error: unknown): error is JsonError {
67
67
  }
68
68
 
69
69
  export function isNumber(value: unknown): value is number {
70
- return isNaN(value as number) === false;
70
+ return typeof value === "number";
71
71
  }
@@ -0,0 +1,3 @@
1
+ export function isListOfStrings(v: unknown): v is string[] {
2
+ return Array.isArray(v) && v.find((item) => typeof item !== "string") == null;
3
+ }
@@ -8,7 +8,6 @@ describe("compileSchema : validate", () => {
8
8
  // note: boolean schema is already thoroughly tested by spec
9
9
  describe("boolean schema", () => {
10
10
  it("should fail if root schema is false", () => {
11
- // @ts-expect-error boolean typ unsupported
12
11
  const { errors } = compileSchema(false).validate("anything");
13
12
  assert.deepEqual(errors.length, 1);
14
13
  });
@@ -23,7 +22,6 @@ describe("compileSchema : validate", () => {
23
22
  assert.deepEqual(errors.length, 1);
24
23
  });
25
24
  it("should succeed if root schema is true", () => {
26
- // @ts-expect-error boolean typ unsupported
27
25
  const { errors } = compileSchema(true).validate("anything");
28
26
  assert.deepEqual(errors.length, 0);
29
27
  });
@@ -1,8 +1,11 @@
1
- import { BooleanSchema, JsonSchema, SchemaNode } from "./types";
2
- import { ValidationPath, ValidationReturnType } from "./Keyword";
1
+ import { BooleanSchema, isJsonError, JsonSchema, SchemaNode } from "./types";
2
+ import { SchemaNodeWithRequired, ValidationPath, ValidationReturnType } from "./Keyword";
3
3
  import sanitizeErrors from "./utils/sanitizeErrors";
4
4
 
5
5
  export function validateNode(node: SchemaNode, data: unknown, pointer: string, path: ValidationPath) {
6
+ if (isJsonError(node)) {
7
+ return [node];
8
+ }
6
9
  path.push({ pointer, node });
7
10
  const schema = node.schema as BooleanSchema | JsonSchema;
8
11
  if (schema === true) {
@@ -19,7 +22,7 @@ export function validateNode(node: SchemaNode, data: unknown, pointer: string, p
19
22
  }
20
23
  const errors: ValidationReturnType = [];
21
24
  for (const validate of node.validators) {
22
- const result = validate({ node, data, pointer, path });
25
+ const result = validate({ node: node as SchemaNodeWithRequired<keyof SchemaNode>, data, pointer, path });
23
26
  if (Array.isArray(result)) {
24
27
  errors.push(...result);
25
28
  } else if (result) {
@@ -0,0 +1,312 @@
1
+ import { compileSchema } from "./compileSchema";
2
+ import { strict as assert } from "assert";
3
+ import { extendDraft } from "./Draft";
4
+ import { draft2020 } from "./draft2020";
5
+ import { propertyDependenciesKeyword } from "./keywords/propertyDependencies";
6
+ import { draft07 } from "./draft07";
7
+
8
+ const withAdditionalKeywords = {
9
+ drafts: [
10
+ extendDraft(draft2020, {
11
+ keywords: [propertyDependenciesKeyword]
12
+ })
13
+ ]
14
+ };
15
+
16
+ describe("validateSchema", () => {
17
+ it("should error if `$defs` is not an object", () => {
18
+ const { schemaErrors } = compileSchema({ $defs: true });
19
+ assert.equal(schemaErrors?.length, 1);
20
+ });
21
+ it("should throw an error if schema is invalid and option 'throwOnInvalidSchema = true'", () => {
22
+ assert.throws(() => {
23
+ compileSchema({ $defs: true }, { throwOnInvalidSchema: true });
24
+ });
25
+ });
26
+ it("should error for missing `$ref` target in $defs", () => {
27
+ const { schemaErrors } = compileSchema({
28
+ type: "object",
29
+ properties: {
30
+ invalid: { $ref: "#/$defs/invalid" }
31
+ }
32
+ });
33
+ assert.equal(schemaErrors?.length, 1);
34
+ assert.equal(schemaErrors[0].data.pointer, "#/properties/invalid/$ref");
35
+ assert.equal(schemaErrors[0].data.value, "#/$defs/invalid");
36
+ });
37
+ it("should error if `additionalProperties` is not a valid JSON Schema", () => {
38
+ const { schemaErrors } = compileSchema({ additionalProperties: 999 });
39
+ assert.equal(schemaErrors?.length, 1);
40
+ });
41
+ it("should error if `allOf` is not a an array", () => {
42
+ const { schemaErrors } = compileSchema({ allOf: {} });
43
+ assert.equal(schemaErrors?.length, 1);
44
+ });
45
+ it("should error if `allOf schema` is not a valid JSON Schema", () => {
46
+ const { schemaErrors } = compileSchema({ allOf: [999] });
47
+ assert.equal(schemaErrors?.length, 1);
48
+ });
49
+ it("should error if `anyOf` is not a an array", () => {
50
+ const { schemaErrors } = compileSchema({ anyOf: {} });
51
+ assert.equal(schemaErrors?.length, 1);
52
+ });
53
+ it("should error if `anyOf schema` is not a valid JSON Schema", () => {
54
+ const { schemaErrors } = compileSchema({ anyOf: [999] });
55
+ assert.equal(schemaErrors?.length, 1);
56
+ });
57
+ // any const is valid: https://json-schema.org/draft/2020-12/json-schema-validation#name-const
58
+ it("should error if `contains` is not a valid JSON Schema", () => {
59
+ const { schemaErrors } = compileSchema({ contains: [] });
60
+ assert.equal(schemaErrors?.length, 1);
61
+ });
62
+ it("should error if `dependencies` is not a an object", () => {
63
+ const { schemaErrors } = compileSchema({ dependencies: [] });
64
+ assert.equal(schemaErrors?.length, 1);
65
+ });
66
+ it("should error if `dependentRequired` is not a an object", () => {
67
+ const { schemaErrors } = compileSchema({ dependentRequired: [] });
68
+ assert.equal(schemaErrors?.length, 1);
69
+ });
70
+ it("should error if `dependentRequired` is not a an object with a list of strings", () => {
71
+ const { schemaErrors } = compileSchema({
72
+ dependentRequired: {
73
+ property: ["title", true]
74
+ }
75
+ });
76
+ assert.equal(schemaErrors?.length, 1);
77
+ });
78
+ it("should error if `dependentSchemas` is not a an object containing schemata", () => {
79
+ const { schemaErrors } = compileSchema({
80
+ dependentSchemas: {
81
+ valid: { type: "string" },
82
+ stillValid: true,
83
+ invalid: 999
84
+ }
85
+ });
86
+ assert.equal(schemaErrors?.length, 1);
87
+ assert.equal(schemaErrors[0].data.pointer, "#/dependentSchemas/invalid");
88
+ });
89
+ it("should error if `deprecated` is not a a boolean", () => {
90
+ const { schemaErrors } = compileSchema({ deprecated: {} });
91
+ assert.equal(schemaErrors?.length, 1);
92
+ });
93
+ it("should error if `enum` is not an array", () => {
94
+ const { schemaErrors } = compileSchema({ type: "string", enum: true });
95
+ assert.equal(schemaErrors?.length, 1);
96
+ });
97
+ it("should error if `exclusiveMaximum` is not a number", () => {
98
+ const { schemaErrors } = compileSchema({ exclusiveMaximum: true });
99
+ assert.equal(schemaErrors?.length, 1);
100
+ });
101
+ it("should error if `exclusiveMinimum` is not a number", () => {
102
+ const { schemaErrors } = compileSchema({ exclusiveMinimum: true });
103
+ assert.equal(schemaErrors?.length, 1);
104
+ });
105
+ it("should error if `format` is not a string", () => {
106
+ const { schemaErrors } = compileSchema({ format: {} });
107
+ assert.equal(schemaErrors?.length, 1);
108
+ });
109
+ it("should error if `if` is not a valid JSON Schema", () => {
110
+ const { schemaErrors } = compileSchema({ if: 999, then: false, else: true });
111
+ assert.equal(schemaErrors?.length, 1);
112
+ });
113
+ it("should error if `then` is not a valid JSON Schema", () => {
114
+ const { schemaErrors } = compileSchema({ if: {}, then: [], else: true });
115
+ assert.equal(schemaErrors?.length, 1);
116
+ });
117
+ it("should error if `else` is not a valid JSON Schema", () => {
118
+ const { schemaErrors } = compileSchema({ if: {}, then: false, else: 999 });
119
+ assert.equal(schemaErrors?.length, 1);
120
+ });
121
+ it("should error if `items` is not a valid JSON Schema", () => {
122
+ const { schemaErrors } = compileSchema({ items: [] });
123
+ assert.equal(schemaErrors?.length, 1);
124
+ });
125
+ it("should error if `maximum` is not a number", () => {
126
+ const { schemaErrors } = compileSchema({ maximum: true });
127
+ assert.equal(schemaErrors?.length, 1);
128
+ });
129
+ it("should error if `maxItems` is not a number", () => {
130
+ const { schemaErrors } = compileSchema({ maxItems: true });
131
+ assert.equal(schemaErrors?.length, 1);
132
+ });
133
+ it("should error if `maxLength` is not a number", () => {
134
+ const { schemaErrors } = compileSchema({ maxLength: true });
135
+ assert.equal(schemaErrors?.length, 1);
136
+ });
137
+ it("should error if `maxProperties` is not a number", () => {
138
+ const { schemaErrors } = compileSchema({ maxProperties: true });
139
+ assert.equal(schemaErrors?.length, 1);
140
+ });
141
+ it("should error if `minimum` is not a number", () => {
142
+ const { schemaErrors } = compileSchema({ minimum: true });
143
+ assert.equal(schemaErrors?.length, 1);
144
+ });
145
+ it("should error if `minItems` is not a number", () => {
146
+ const { schemaErrors } = compileSchema({ minItems: true });
147
+ assert.equal(schemaErrors?.length, 1);
148
+ });
149
+ it("should error if `minLength` is not a number", () => {
150
+ const { schemaErrors } = compileSchema({ minLength: true });
151
+ assert.equal(schemaErrors?.length, 1);
152
+ });
153
+ it("should error if `minProperties` is not a number", () => {
154
+ const { schemaErrors } = compileSchema({ minProperties: true });
155
+ assert.equal(schemaErrors?.length, 1);
156
+ });
157
+ it("should error if `multipleOf` is not a number", () => {
158
+ const { schemaErrors } = compileSchema({ multipleOf: true });
159
+ assert.equal(schemaErrors?.length, 1);
160
+ });
161
+ it("should error if `not` is not a JSON Schema", () => {
162
+ const { schemaErrors } = compileSchema({ not: [] });
163
+ assert.equal(schemaErrors?.length, 1);
164
+ });
165
+ it("should error if `oneOf` is not a an array", () => {
166
+ const { schemaErrors } = compileSchema({ oneOf: {} });
167
+ assert.equal(schemaErrors?.length, 1);
168
+ });
169
+ it("should error if `oneOf schema` is not a valid JSON Schema", () => {
170
+ const { schemaErrors } = compileSchema({ oneOf: [999] });
171
+ assert.equal(schemaErrors?.length, 1);
172
+ });
173
+ it("should error if `pattern` is not a string", () => {
174
+ const { schemaErrors } = compileSchema({ type: "string", pattern: true });
175
+ assert.equal(schemaErrors?.length, 1);
176
+ });
177
+ it("should error if `pattern` is an invalid regexp", () => {
178
+ const { schemaErrors } = compileSchema({ type: "string", pattern: "(" });
179
+ assert.equal(schemaErrors?.length, 1);
180
+ });
181
+ it("should error if `properties` is not an object", () => {
182
+ const { schemaErrors } = compileSchema({ type: "object", properties: 999 });
183
+ assert.equal(schemaErrors?.length, 1);
184
+ });
185
+ it("should error if `properties[string]` is not a JSON Schema", () => {
186
+ const { schemaErrors } = compileSchema({
187
+ type: "object",
188
+ properties: {
189
+ valid: { type: "string" },
190
+ alsoValid: false,
191
+ invalid: 999
192
+ }
193
+ });
194
+ assert.equal(schemaErrors?.length, 1);
195
+ assert.equal(schemaErrors[0].data.pointer, "#/properties/invalid");
196
+ });
197
+ it("should error if `propertyDependencies` is not an object", () => {
198
+ const { schemaErrors } = compileSchema({ propertyDependencies: true }, withAdditionalKeywords);
199
+ assert.equal(schemaErrors?.length, 1);
200
+ });
201
+ it("should error if `propertyDependencies[string]` is not an object", () => {
202
+ const { schemaErrors } = compileSchema({ propertyDependencies: { invalid: true } }, withAdditionalKeywords);
203
+ assert.equal(schemaErrors?.length, 1);
204
+ });
205
+ it("should error if `propertyDependencies[string][string]` is not JSON Schema", () => {
206
+ const { schemaErrors } = compileSchema(
207
+ { propertyDependencies: { valid: { invalid: 999 } } },
208
+ withAdditionalKeywords
209
+ );
210
+ assert.equal(schemaErrors?.length, 1);
211
+ });
212
+ it("should error if `propertyNames` is not a JSON Schema type", () => {
213
+ const { schemaErrors } = compileSchema({ propertyNames: "error" });
214
+ assert.equal(schemaErrors?.length, 1);
215
+ assert.equal(schemaErrors[0].data.pointer, "#/propertyNames");
216
+ });
217
+ it("should error if `required` is not a string[]", () => {
218
+ const { schemaErrors } = compileSchema({ type: "object", required: [123, "valid"] });
219
+ assert.equal(schemaErrors?.length, 1);
220
+ assert.equal(schemaErrors[0].data.pointer, "#/required");
221
+ });
222
+ it("should error if `type` is not a JSON Schema type", () => {
223
+ const { schemaErrors } = compileSchema({ type: "error" });
224
+ assert.equal(schemaErrors?.length, 1);
225
+ assert.equal(schemaErrors[0].data.pointer, "#/type");
226
+ });
227
+ it("should error if `type` is not a valid JSON Schema type format", () => {
228
+ const { schemaErrors } = compileSchema({ type: {} });
229
+ assert.equal(schemaErrors?.length, 1);
230
+ assert.equal(schemaErrors[0].data.pointer, "#/type");
231
+ });
232
+ it("should error if `type` is not a valid JSON Schema", () => {
233
+ const { schemaErrors } = compileSchema({ type: "error" });
234
+ assert.equal(schemaErrors?.length, 1);
235
+ assert.equal(schemaErrors[0].data.pointer, "#/type");
236
+ });
237
+ it("should error if `unevaluatedItems` is not a valid JSON Schema", () => {
238
+ const { schemaErrors } = compileSchema({ unevaluatedItems: [] });
239
+ assert.equal(schemaErrors?.length, 1);
240
+ assert.equal(schemaErrors[0].data.pointer, "#/unevaluatedItems");
241
+ });
242
+ it("should error if `unevaluatedProperties` is not a valid JSON Schema", () => {
243
+ const { schemaErrors } = compileSchema({ unevaluatedProperties: 999 });
244
+ assert.equal(schemaErrors?.length, 1);
245
+ assert.equal(schemaErrors[0].data.pointer, "#/unevaluatedProperties");
246
+ });
247
+ it("should error if `uniqueItems` is not a boolean", () => {
248
+ const { schemaErrors } = compileSchema({ uniqueItems: {} });
249
+ assert.equal(schemaErrors?.length, 1);
250
+ assert.equal(schemaErrors[0].data.pointer, "#/uniqueItems");
251
+ });
252
+
253
+ describe("annotations", () => {
254
+ it("should return unknown keywords as annotation", () => {
255
+ const { schemaAnnotations } = compileSchema(
256
+ {
257
+ properties: {
258
+ headline: {
259
+ options: {},
260
+ type: "string"
261
+ }
262
+ }
263
+ },
264
+ { withSchemaAnnotations: true }
265
+ );
266
+ assert.equal(schemaAnnotations.length, 1);
267
+ assert.equal(schemaAnnotations[0].data.pointer, "#/properties/headline/options");
268
+ });
269
+ it("should return not unknown keywords starting with 'x-'", () => {
270
+ const { schemaAnnotations } = compileSchema(
271
+ {
272
+ properties: {
273
+ headline: {
274
+ "x-options": {},
275
+ type: "string"
276
+ }
277
+ }
278
+ },
279
+ { withSchemaAnnotations: true }
280
+ );
281
+ assert.equal(schemaAnnotations.length, 0);
282
+ });
283
+ it("should return removed keywords from old drafts as annotation", () => {
284
+ const { schemaAnnotations } = compileSchema(
285
+ {
286
+ properties: {
287
+ headline: {
288
+ additionalItems: true
289
+ }
290
+ }
291
+ },
292
+ { withSchemaAnnotations: true }
293
+ );
294
+ assert.equal(schemaAnnotations.length, 1);
295
+ assert.equal(schemaAnnotations[0].data.pointer, "#/properties/headline/additionalItems");
296
+ });
297
+ it("should return new keywords in old drafts as annotation", () => {
298
+ const { schemaAnnotations } = compileSchema(
299
+ {
300
+ properties: {
301
+ headline: {
302
+ prefixItems: []
303
+ }
304
+ }
305
+ },
306
+ { drafts: [draft07], withSchemaAnnotations: true }
307
+ );
308
+ assert.equal(schemaAnnotations.length, 1);
309
+ assert.equal(schemaAnnotations[0].data.pointer, "#/properties/headline/prefixItems");
310
+ });
311
+ });
312
+ });
package/tsconfig.json CHANGED
@@ -7,10 +7,17 @@
7
7
  "module": "ESNext",
8
8
  "resolveJsonModule": true,
9
9
  "allowSyntheticDefaultImports": true,
10
- "moduleResolution": "node",
10
+ "moduleResolution": "bundler",
11
11
  "lib": ["DOM", "ES2018"],
12
- "exactOptionalPropertyTypes": true
12
+ "exactOptionalPropertyTypes": true,
13
+ "baseUrl": ".",
14
+ "paths": {
15
+ "json-schema-library": ["./index.ts"],
16
+ "json-schema-library/remotes": ["./remotes/index.ts"],
17
+ "json-schema-library/package.json": ["./package.json"]
18
+ },
19
+ "types": ["node", "mocha"]
13
20
  },
14
- "exclude": ["src/**/*.test.ts"],
15
- "include": ["index.ts", "src/**/*"]
21
+ "exclude": ["src/**/*.test.ts", "src/**/*.spec.ts", "bowtie/**/*.test.ts"],
22
+ "include": ["index.ts", "src/**/*", "remotes/**/*", "bowtie/**/*"]
16
23
  }
@@ -5,11 +5,18 @@
5
5
  "incremental": false /* Enable incremental compilation */,
6
6
  "target": "ESNEXT" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
7
7
  "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
8
+ "moduleResolution": "node10",
8
9
  "sourceMap": false /* Generates corresponding '.map' file. */,
9
10
  "strict": false /* Enable all strict type-checking options. */,
10
11
  "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
11
- "types": ["mocha", "node"]
12
+ "types": ["mocha", "node"],
13
+ "baseUrl": ".",
14
+ "paths": {
15
+ "json-schema-library": ["./index.ts"],
16
+ "json-schema-library/remotes": ["./remotes/index.ts"],
17
+ "json-schema-library/package.json": ["./package.json"]
18
+ }
12
19
  },
13
20
  "exclude": [],
14
- "include": ["src/**/*.test.ts"]
21
+ "include": ["src/**/*.test.ts", "bowtie/**/*.test.ts"]
15
22
  }
package/tsdown.config.ts CHANGED
@@ -2,7 +2,7 @@ import { defineConfig } from "tsdown";
2
2
 
3
3
  export default defineConfig({
4
4
  dts: true,
5
- entry: ["./index.ts"],
5
+ entry: ["./index.ts", "./remotes/index.ts"],
6
6
  exports: true,
7
7
  globalName: "jlib"
8
8
  });
package/Dockerfile DELETED
@@ -1,6 +0,0 @@
1
- FROM node:23-alpine
2
- COPY . /usr/app
3
- WORKDIR /usr/app
4
- #ENV NODE_ENV=production
5
- #RUN npm install --omit=dev
6
- CMD ["node", "bowtie_jlib.js"]