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.
- package/.mocharc.js +1 -0
- package/CHANGELOG.md +17 -0
- package/README.md +120 -0
- package/bowtie/.editorconfig +21 -0
- package/bowtie/.prettierrc +6 -0
- package/bowtie/BOWTIE.md +54 -0
- package/bowtie/Dockerfile +6 -0
- package/bowtie/bowtie-api.ts +101 -0
- package/bowtie/bowtie.test.ts +76 -0
- package/bowtie/bowtie.ts +156 -0
- package/bowtie/package.json +11 -0
- package/bowtie/tsconfig.json +12 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +39 -470
- package/dist/index.d.mts +39 -470
- package/dist/index.mjs +1 -1
- package/dist/jlib.js +2 -13
- package/dist/remotes/index.cjs +1 -0
- package/dist/remotes/index.d.cts +7 -0
- package/dist/remotes/index.d.mts +7 -0
- package/dist/remotes/index.mjs +1 -0
- package/dist/types-B2wwNWyo.d.cts +513 -0
- package/dist/types-BhTU1l2h.d.mts +513 -0
- package/index.ts +10 -4
- package/package.json +14 -8
- package/src/Keyword.ts +37 -12
- package/src/SchemaNode.ts +84 -16
- package/src/compileSchema.ts +56 -4
- package/src/draft04/keywords/$ref.ts +22 -14
- package/src/draft04/keywords/exclusiveMaximum.ts +14 -0
- package/src/draft04/keywords/exclusiveMinimum.ts +14 -0
- package/src/draft04/validateSchema.test.ts +20 -0
- package/src/draft06/keywords/$ref.ts +15 -5
- package/src/draft2019-09/keywords/$ref.test.ts +3 -1
- package/src/draft2019-09/keywords/$ref.ts +40 -16
- package/src/draft2019-09/keywords/additionalItems.ts +33 -10
- package/src/draft2019-09/keywords/items.ts +32 -10
- package/src/draft2019-09/keywords/unevaluatedItems.ts +19 -6
- package/src/draft2019-09/methods/getData.ts +1 -1
- package/src/draft2019-09/validateSchema.test.ts +28 -0
- package/src/errors/errors.ts +8 -1
- package/src/formats/formats.ts +35 -28
- package/src/formats/hyperjump.d.ts +172 -0
- package/src/keywords/$defs.ts +34 -8
- package/src/keywords/$ref.ts +59 -13
- package/src/keywords/additionalProperties.ts +19 -8
- package/src/keywords/allOf.ts +44 -18
- package/src/keywords/anyOf.ts +38 -19
- package/src/keywords/contains.ts +21 -9
- package/src/keywords/dependencies.ts +37 -17
- package/src/keywords/dependentRequired.ts +56 -38
- package/src/keywords/dependentSchemas.ts +37 -13
- package/src/keywords/deprecated.ts +32 -8
- package/src/keywords/enum.ts +30 -8
- package/src/keywords/exclusiveMaximum.ts +21 -2
- package/src/keywords/exclusiveMinimum.ts +22 -3
- package/src/keywords/format.ts +21 -2
- package/src/keywords/ifthenelse.ts +49 -5
- package/src/keywords/items.ts +27 -13
- package/src/keywords/maxItems.ts +22 -2
- package/src/keywords/maxLength.ts +30 -9
- package/src/keywords/maxProperties.ts +30 -9
- package/src/keywords/maximum.ts +28 -8
- package/src/keywords/minItems.ts +30 -9
- package/src/keywords/minLength.ts +30 -9
- package/src/keywords/minProperties.ts +26 -5
- package/src/keywords/minimum.ts +32 -13
- package/src/keywords/multipleOf.ts +33 -12
- package/src/keywords/not.ts +23 -10
- package/src/keywords/oneOf.ts +29 -9
- package/src/keywords/pattern.ts +35 -9
- package/src/keywords/properties.ts +34 -11
- package/src/keywords/propertyDependencies.test.ts +180 -0
- package/src/keywords/propertyDependencies.ts +173 -0
- package/src/keywords/propertyNames.ts +26 -14
- package/src/keywords/required.ts +31 -8
- package/src/keywords/type.ts +53 -16
- package/src/keywords/unevaluatedItems.ts +24 -8
- package/src/keywords/unevaluatedProperties.ts +24 -7
- package/src/keywords/uniqueItems.ts +23 -4
- package/src/mergeNode.ts +9 -4
- package/src/methods/getData.ts +1 -1
- package/src/settings.ts +2 -1
- package/src/types.ts +1 -1
- package/src/utils/isListOfStrings.ts +3 -0
- package/src/validate.test.ts +0 -2
- package/src/validateNode.ts +6 -3
- package/src/validateSchema.test.ts +312 -0
- package/tsconfig.json +11 -4
- package/tsconfig.test.json +9 -2
- package/tsdown.config.ts +1 -1
- package/Dockerfile +0 -6
- package/bowtie_jlib.js +0 -140
- package/remotes/draft04.json +0 -150
- package/remotes/draft06.json +0 -155
- package/remotes/draft07.json +0 -155
- package/remotes/draft2019-09.json +0 -42
- package/remotes/draft2019-09_meta_applicator.json +0 -53
- package/remotes/draft2019-09_meta_content.json +0 -14
- package/remotes/draft2019-09_meta_core.json +0 -54
- package/remotes/draft2019-09_meta_format.json +0 -11
- package/remotes/draft2019-09_meta_meta-data.json +0 -34
- package/remotes/draft2019-09_meta_validation.json +0 -95
- package/remotes/draft2020-12.json +0 -55
- package/remotes/draft2020-12_meta_applicator.json +0 -45
- package/remotes/draft2020-12_meta_content.json +0 -14
- package/remotes/draft2020-12_meta_core.json +0 -48
- package/remotes/draft2020-12_meta_format_annotation.json +0 -11
- package/remotes/draft2020-12_meta_format_assertion.json +0 -11
- package/remotes/draft2020-12_meta_meta_data.json +0 -34
- package/remotes/draft2020-12_meta_unevaluated.json +0 -12
- package/remotes/draft2020-12_meta_validation.json +0 -87
- 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:
|
|
9
|
-
keyword:
|
|
10
|
+
id: KEYWORD,
|
|
11
|
+
keyword: KEYWORD,
|
|
10
12
|
parse: parseUnevaluatedProperties,
|
|
11
|
-
addValidate: ({ schema }) => schema
|
|
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
|
-
|
|
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}
|
|
22
|
-
`${node.schemaLocation}
|
|
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:
|
|
7
|
-
keyword:
|
|
8
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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
|
package/src/methods/getData.ts
CHANGED
|
@@ -159,7 +159,7 @@ export function getData(node: SchemaNode, data?: unknown, opts?: TemplateOptions
|
|
|
159
159
|
return defaultData;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
-
if (resolvedNode
|
|
162
|
+
if (isSchemaNode(resolvedNode)) {
|
|
163
163
|
defaultData = resolvedNode.getData(defaultData, opts) ?? defaultData;
|
|
164
164
|
currentNode = resolvedNode;
|
|
165
165
|
}
|
package/src/settings.ts
CHANGED
package/src/types.ts
CHANGED
package/src/validate.test.ts
CHANGED
|
@@ -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
|
});
|
package/src/validateNode.ts
CHANGED
|
@@ -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
|
|
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": "
|
|
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
|
}
|
package/tsconfig.test.json
CHANGED
|
@@ -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