@hyperjump/json-schema 0.23.4 → 1.0.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/LICENSE +1 -1
- package/README.md +459 -120
- package/draft-04/additionalItems.js +29 -0
- package/{lib/keywords → draft-04}/dependencies.js +9 -5
- package/draft-04/exclusiveMaximum.js +5 -0
- package/draft-04/exclusiveMinimum.js +5 -0
- package/draft-04/id.js +1 -0
- package/draft-04/index.d.ts +43 -0
- package/draft-04/index.js +69 -0
- package/draft-04/items.js +35 -0
- package/draft-04/maximum.js +26 -0
- package/draft-04/minimum.js +25 -0
- package/draft-04/ref.js +1 -0
- package/draft-04/schema.js +149 -0
- package/draft-06/contains.js +13 -0
- package/draft-06/index.d.ts +47 -0
- package/draft-06/index.js +66 -0
- package/draft-06/schema.js +154 -0
- package/{lib/draft-07.d.ts → draft-07/index.d.ts} +21 -19
- package/draft-07/index.js +72 -0
- package/draft-07/schema.js +172 -0
- package/{lib/keywords/contains-minContains-maxContains.js → draft-2019-09/contains.js} +14 -7
- package/{lib/draft-2019-09.d.ts → draft-2019-09/index.d.ts} +24 -22
- package/draft-2019-09/index.js +117 -0
- package/draft-2019-09/meta/applicator.js +55 -0
- package/draft-2019-09/meta/content.js +17 -0
- package/draft-2019-09/meta/core.js +57 -0
- package/draft-2019-09/meta/format.js +14 -0
- package/draft-2019-09/meta/meta-data.js +37 -0
- package/draft-2019-09/meta/validation.js +98 -0
- package/draft-2019-09/recursiveAnchor.js +1 -0
- package/draft-2019-09/recursiveRef.js +19 -0
- package/draft-2019-09/schema.js +42 -0
- package/draft-2020-12/dynamicAnchor.js +1 -0
- package/draft-2020-12/dynamicRef.js +35 -0
- package/draft-2020-12/index.d.ts +66 -0
- package/draft-2020-12/index.js +124 -0
- package/draft-2020-12/meta/applicator.js +46 -0
- package/draft-2020-12/meta/content.js +14 -0
- package/draft-2020-12/meta/core.js +54 -0
- package/draft-2020-12/meta/format-annotation.js +11 -0
- package/draft-2020-12/meta/format-assertion.js +11 -0
- package/draft-2020-12/meta/meta-data.js +34 -0
- package/draft-2020-12/meta/unevaluated.js +12 -0
- package/draft-2020-12/meta/validation.js +95 -0
- package/draft-2020-12/schema.js +44 -0
- package/lib/common.d.ts +5 -1
- package/lib/common.js +80 -9
- package/lib/configuration.d.ts +9 -0
- package/lib/configuration.js +18 -0
- package/lib/core.d.ts +48 -0
- package/lib/core.js +102 -0
- package/lib/experimental.d.ts +8 -0
- package/lib/experimental.js +4 -0
- package/lib/fetch.browser.js +1 -0
- package/lib/fetch.js +19 -0
- package/lib/index.d.ts +11 -42
- package/lib/index.js +130 -23
- package/lib/instance.d.ts +75 -0
- package/lib/instance.js +58 -0
- package/lib/invalid-schema-error.d.ts +8 -0
- package/lib/invalid-schema-error.js +7 -0
- package/lib/keywords/additionalProperties.js +19 -17
- package/lib/keywords/allOf.js +10 -7
- package/lib/keywords/anchor.js +1 -0
- package/lib/keywords/anyOf.js +10 -7
- package/lib/keywords/comment.js +4 -0
- package/lib/keywords/const.js +6 -3
- package/lib/keywords/contains.js +48 -5
- package/lib/keywords/contentEncoding.js +4 -0
- package/lib/keywords/contentMediaType.js +4 -0
- package/lib/keywords/contentSchema.js +4 -0
- package/lib/keywords/default.js +4 -0
- package/lib/keywords/definitions.js +7 -4
- package/lib/keywords/dependentRequired.js +6 -3
- package/lib/keywords/dependentSchemas.js +10 -6
- package/lib/keywords/deprecated.js +4 -0
- package/lib/keywords/description.js +4 -0
- package/lib/keywords/dynamicAnchor.js +1 -0
- package/lib/keywords/dynamicRef.js +13 -17
- package/lib/keywords/else.js +16 -11
- package/lib/keywords/enum.js +6 -3
- package/lib/keywords/examples.js +4 -0
- package/lib/keywords/exclusiveMaximum.js +5 -2
- package/lib/keywords/exclusiveMinimum.js +5 -2
- package/lib/keywords/format.js +4 -0
- package/lib/keywords/id.js +1 -0
- package/lib/keywords/if.js +8 -6
- package/lib/keywords/items.js +17 -19
- package/lib/keywords/maxContains.js +4 -0
- package/lib/keywords/maxItems.js +5 -2
- package/lib/keywords/maxLength.js +5 -2
- package/lib/keywords/maxProperties.js +5 -2
- package/lib/keywords/maximum.js +5 -2
- package/lib/keywords/meta-data.js +4 -0
- package/lib/keywords/minContains.js +4 -0
- package/lib/keywords/minItems.js +5 -2
- package/lib/keywords/minLength.js +5 -2
- package/lib/keywords/minProperties.js +5 -2
- package/lib/keywords/minimum.js +5 -2
- package/lib/keywords/multipleOf.js +5 -2
- package/lib/keywords/not.js +6 -4
- package/lib/keywords/oneOf.js +9 -6
- package/lib/keywords/pattern.js +5 -2
- package/lib/keywords/patternProperties.js +9 -5
- package/lib/keywords/prefixItems.js +28 -0
- package/lib/keywords/properties.js +11 -6
- package/lib/keywords/propertyDependencies.js +49 -0
- package/lib/keywords/propertyNames.js +7 -4
- package/lib/keywords/readOnly.js +4 -0
- package/lib/keywords/ref.js +9 -6
- package/lib/keywords/requireAllExcept.js +24 -0
- package/lib/keywords/required.js +5 -2
- package/lib/keywords/then.js +16 -11
- package/lib/keywords/title.js +4 -0
- package/lib/keywords/type.js +5 -2
- package/lib/keywords/unevaluatedItems.js +9 -5
- package/lib/keywords/unevaluatedProperties.js +9 -5
- package/lib/keywords/uniqueItems.js +6 -3
- package/lib/keywords/validation.js +123 -0
- package/lib/keywords/vocabulary.js +1 -0
- package/lib/keywords/writeOnly.js +4 -0
- package/lib/keywords.d.ts +19 -0
- package/lib/keywords.js +59 -0
- package/lib/media-types.d.ts +9 -0
- package/lib/media-types.js +26 -0
- package/lib/pubsub.js +42 -0
- package/lib/reference.d.ts +11 -0
- package/lib/reference.js +11 -0
- package/lib/schema.d.ts +64 -0
- package/lib/schema.js +308 -0
- package/package.json +31 -22
- package/{lib/draft-2020-12.d.ts → stable/index.d.ts} +26 -24
- package/stable/index.js +118 -0
- package/stable/meta/applicator.js +49 -0
- package/stable/meta/content.js +12 -0
- package/stable/meta/core.js +49 -0
- package/stable/meta/format-annotation.js +10 -0
- package/stable/meta/format-assertion.js +10 -0
- package/stable/meta/meta-data.js +16 -0
- package/stable/meta/unevaluated.js +11 -0
- package/stable/meta/validation.js +67 -0
- package/stable/validation.js +24 -0
- package/dist/json-schema-amd.js +0 -6644
- package/dist/json-schema-amd.js.map +0 -1
- package/dist/json-schema-amd.min.js +0 -2
- package/dist/json-schema-amd.min.js.map +0 -1
- package/dist/json-schema-cjs.js +0 -6642
- package/dist/json-schema-cjs.js.map +0 -1
- package/dist/json-schema-cjs.min.js +0 -2
- package/dist/json-schema-cjs.min.js.map +0 -1
- package/dist/json-schema-esm.js +0 -6638
- package/dist/json-schema-esm.js.map +0 -1
- package/dist/json-schema-esm.min.js +0 -2
- package/dist/json-schema-esm.min.js.map +0 -1
- package/dist/json-schema-iife.js +0 -6647
- package/dist/json-schema-iife.js.map +0 -1
- package/dist/json-schema-iife.min.js +0 -2
- package/dist/json-schema-iife.min.js.map +0 -1
- package/dist/json-schema-system.js +0 -6645
- package/dist/json-schema-system.js.map +0 -1
- package/dist/json-schema-system.min.js +0 -2
- package/dist/json-schema-system.min.js.map +0 -1
- package/dist/json-schema-umd.js +0 -6648
- package/dist/json-schema-umd.js.map +0 -1
- package/dist/json-schema-umd.min.js +0 -2
- package/dist/json-schema-umd.min.js.map +0 -1
- package/lib/draft-04.d.ts +0 -41
- package/lib/draft-04.js +0 -46
- package/lib/draft-06.d.ts +0 -45
- package/lib/draft-06.js +0 -51
- package/lib/draft-07.js +0 -55
- package/lib/draft-2019-09.js +0 -92
- package/lib/draft-2020-12.js +0 -103
- package/lib/index.mjs +0 -19
- package/lib/keywords/additionalItems.js +0 -27
- package/lib/keywords/additionalItems6.js +0 -23
- package/lib/keywords/additionalProperties6.js +0 -28
- package/lib/keywords/index.js +0 -53
- package/lib/keywords/items202012.js +0 -23
- package/lib/keywords/maximum-exclusiveMaximum.js +0 -20
- package/lib/keywords/minimum-exclusiveMinimum.js +0 -20
- package/lib/keywords/tupleItems.js +0 -24
- package/meta/draft/2019-09/meta/applicator.js +0 -55
- package/meta/draft/2019-09/meta/content.js +0 -17
- package/meta/draft/2019-09/meta/core.js +0 -57
- package/meta/draft/2019-09/meta/format.js +0 -14
- package/meta/draft/2019-09/meta/meta-data.js +0 -37
- package/meta/draft/2019-09/meta/validation.js +0 -98
- package/meta/draft/2019-09/schema.js +0 -42
- package/meta/draft/2020-12/meta/applicator.js +0 -49
- package/meta/draft/2020-12/meta/content.js +0 -17
- package/meta/draft/2020-12/meta/core.js +0 -57
- package/meta/draft/2020-12/meta/format-annotation.js +0 -14
- package/meta/draft/2020-12/meta/format-assertion.js +0 -14
- package/meta/draft/2020-12/meta/meta-data.js +0 -37
- package/meta/draft/2020-12/meta/unevaluated.js +0 -15
- package/meta/draft/2020-12/meta/validation.js +0 -98
- package/meta/draft/2020-12/schema.js +0 -44
- package/meta/draft-04/schema.js +0 -149
- package/meta/draft-06/schema.js +0 -154
- package/meta/draft-07/schema.js +0 -172
package/lib/keywords/oneOf.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import Validation from "./validation.js";
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
const id = "https://json-schema.org/keyword/oneOf";
|
|
6
|
+
|
|
4
7
|
const compile = async (schema, ast) => {
|
|
5
|
-
const oneOf = await Schema.map((itemSchema) =>
|
|
8
|
+
const oneOf = await Schema.map((itemSchema) => Validation.compile(itemSchema, ast), schema);
|
|
6
9
|
return Promise.all(oneOf);
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
const interpret = (oneOf, instance, ast, dynamicAnchors) => {
|
|
10
13
|
let validCount = 0;
|
|
11
14
|
for (const schemaUrl of oneOf) {
|
|
12
|
-
if (
|
|
15
|
+
if (Validation.interpret(schemaUrl, instance, ast, dynamicAnchors)) {
|
|
13
16
|
validCount++;
|
|
14
17
|
}
|
|
15
18
|
|
|
@@ -28,7 +31,7 @@ const collectEvaluatedProperties = (oneOf, instance, ast, dynamicAnchors) => {
|
|
|
28
31
|
return false;
|
|
29
32
|
}
|
|
30
33
|
|
|
31
|
-
const propertyNames =
|
|
34
|
+
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, ast, dynamicAnchors);
|
|
32
35
|
return propertyNames ? validCount++ === 0 && propertyNames : acc;
|
|
33
36
|
}, false);
|
|
34
37
|
};
|
|
@@ -40,9 +43,9 @@ const collectEvaluatedItems = (oneOf, instance, ast, dynamicAnchors) => {
|
|
|
40
43
|
return false;
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
const itemIndexes =
|
|
46
|
+
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, ast, dynamicAnchors);
|
|
44
47
|
return itemIndexes ? validCount++ === 0 && itemIndexes : acc;
|
|
45
48
|
}, false);
|
|
46
49
|
};
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
package/lib/keywords/pattern.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import * as Instance from "../instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
const id = "https://json-schema.org/keyword/pattern";
|
|
6
|
+
|
|
4
7
|
const compile = (schema) => new RegExp(Schema.value(schema), "u");
|
|
5
8
|
const interpret = (pattern, instance) => !Instance.typeOf(instance, "string") || pattern.test(Instance.value(instance));
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
export default { id, compile, interpret };
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import * as Pact from "@hyperjump/pact";
|
|
2
|
+
import * as Schema from "../schema.js";
|
|
3
|
+
import * as Instance from "../instance.js";
|
|
4
|
+
import Validation from "./validation.js";
|
|
3
5
|
|
|
4
6
|
|
|
7
|
+
const id = "https://json-schema.org/keyword/patternProperties";
|
|
8
|
+
|
|
5
9
|
const compile = (schema, ast) => Pact.pipeline([
|
|
6
10
|
Schema.entries,
|
|
7
|
-
Pact.map(async ([pattern, propertySchema]) => [new RegExp(pattern, "u"), await
|
|
11
|
+
Pact.map(async ([pattern, propertySchema]) => [new RegExp(pattern, "u"), await Validation.compile(propertySchema, ast)]),
|
|
8
12
|
Pact.all
|
|
9
13
|
], schema);
|
|
10
14
|
|
|
@@ -12,7 +16,7 @@ const interpret = (patternProperties, instance, ast, dynamicAnchors) => {
|
|
|
12
16
|
return !Instance.typeOf(instance, "object") || patternProperties.every(([pattern, schemaUrl]) => {
|
|
13
17
|
return Instance.entries(instance)
|
|
14
18
|
.filter(([propertyName]) => pattern.test(propertyName))
|
|
15
|
-
.every(([, propertyValue]) =>
|
|
19
|
+
.every(([, propertyValue]) => Validation.interpret(schemaUrl, propertyValue, ast, dynamicAnchors));
|
|
16
20
|
});
|
|
17
21
|
};
|
|
18
22
|
|
|
@@ -20,4 +24,4 @@ const collectEvaluatedProperties = (patternProperties, instance, ast, dynamicAnc
|
|
|
20
24
|
return interpret(patternProperties, instance, ast, dynamicAnchors) && patternProperties.map(([pattern]) => pattern);
|
|
21
25
|
};
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
export default { id, compile, interpret, collectEvaluatedProperties };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Pact from "@hyperjump/pact";
|
|
2
|
+
import * as Instance from "../instance.js";
|
|
3
|
+
import * as Schema from "../schema.js";
|
|
4
|
+
import Validation from "./validation.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const id = "https://json-schema.org/keyword/prefixItems";
|
|
8
|
+
|
|
9
|
+
const compile = (schema, ast) => {
|
|
10
|
+
return Pact.pipeline([
|
|
11
|
+
Schema.map((itemSchema) => Validation.compile(itemSchema, ast)),
|
|
12
|
+
Pact.all
|
|
13
|
+
], schema);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const interpret = (items, instance, ast, dynamicAnchors) => {
|
|
17
|
+
if (!Instance.typeOf(instance, "array")) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return Instance.every((item, ndx) => !(ndx in items) || Validation.interpret(items[ndx], item, ast, dynamicAnchors), instance);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const collectEvaluatedItems = (items, instance, ast, dynamicAnchors) => {
|
|
25
|
+
return interpret(items, instance, ast, dynamicAnchors) && new Set(items.map((item, ndx) => ndx));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default { id, compile, interpret, collectEvaluatedItems };
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import * as Pact from "@hyperjump/pact";
|
|
2
|
+
import * as Schema from "../schema.js";
|
|
3
|
+
import * as Instance from "../instance.js";
|
|
4
|
+
import Validation from "./validation.js";
|
|
4
5
|
|
|
5
6
|
|
|
7
|
+
const id = "https://json-schema.org/keyword/properties";
|
|
8
|
+
|
|
6
9
|
const compile = (schema, ast) => Pact.pipeline([
|
|
7
10
|
Schema.entries,
|
|
8
11
|
Pact.reduce(async (acc, [propertyName, propertySchema]) => {
|
|
9
|
-
acc[propertyName] = await
|
|
12
|
+
acc[propertyName] = await Validation.compile(propertySchema, ast);
|
|
10
13
|
return acc;
|
|
11
14
|
}, Object.create(null))
|
|
12
15
|
], schema);
|
|
@@ -14,7 +17,7 @@ const compile = (schema, ast) => Pact.pipeline([
|
|
|
14
17
|
const interpret = (properties, instance, ast, dynamicAnchors) => {
|
|
15
18
|
return !Instance.typeOf(instance, "object") || Instance.entries(instance)
|
|
16
19
|
.filter(([propertyName]) => propertyName in properties)
|
|
17
|
-
.every(([propertyName, schemaUrl]) =>
|
|
20
|
+
.every(([propertyName, schemaUrl]) => Validation.interpret(properties[propertyName], schemaUrl, ast, dynamicAnchors));
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
const collectEvaluatedProperties = (properties, instance, ast, dynamicAnchors) => {
|
|
@@ -22,4 +25,6 @@ const collectEvaluatedProperties = (properties, instance, ast, dynamicAnchors) =
|
|
|
22
25
|
.map((propertyName) => new RegExp(`^${escapeRegExp(propertyName)}$`));
|
|
23
26
|
};
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
const escapeRegExp = (string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&");
|
|
29
|
+
|
|
30
|
+
export default { id, compile, interpret, collectEvaluatedProperties };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as Pact from "@hyperjump/pact";
|
|
2
|
+
import * as Schema from "../schema.js";
|
|
3
|
+
import * as Instance from "../instance.js";
|
|
4
|
+
import Validation from "./validation.js";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const id = "https://json-schema.org/keyword/propertyDependencies";
|
|
8
|
+
const experimental = true;
|
|
9
|
+
|
|
10
|
+
const compile = async (schema, ast) => {
|
|
11
|
+
return Pact.pipeline([
|
|
12
|
+
Schema.entries,
|
|
13
|
+
Pact.reduce(async (propertyDependencies, [propertyName, valueMappings]) => {
|
|
14
|
+
propertyDependencies[propertyName] = await Pact.pipeline([
|
|
15
|
+
Schema.entries,
|
|
16
|
+
Pact.reduce(async (valueMappings, [propertyValue, conditionalSchema]) => {
|
|
17
|
+
valueMappings[propertyValue] = await Validation.compile(conditionalSchema, ast);
|
|
18
|
+
return valueMappings;
|
|
19
|
+
}, {})
|
|
20
|
+
], valueMappings);
|
|
21
|
+
return propertyDependencies;
|
|
22
|
+
}, {})
|
|
23
|
+
], schema);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const interpret = (propertyDependencies, instance, ast, dynamicAnchors) => {
|
|
27
|
+
return !Instance.typeOf(instance, "object") || Object.entries(propertyDependencies).every(([propertyName, valueMappings]) => {
|
|
28
|
+
const propertyValue = Instance.value(instance)[propertyName];
|
|
29
|
+
return !Instance.has(propertyName, instance)
|
|
30
|
+
|| !(propertyValue in valueMappings)
|
|
31
|
+
|| Validation.interpret(valueMappings[propertyValue], instance, ast, dynamicAnchors);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const collectEvaluatedProperties = (propertyDependencies, instance, ast, dynamicAnchors) => {
|
|
36
|
+
return Object.entries(propertyDependencies)
|
|
37
|
+
.reduce((acc, [propertyName, valueMappings]) => {
|
|
38
|
+
const propertyValue = Instance.value(instance)[propertyName];
|
|
39
|
+
|
|
40
|
+
if (Instance.has(propertyName, instance) && propertyValue in valueMappings) {
|
|
41
|
+
const propertyNames = Validation.collectEvaluatedProperties(valueMappings[propertyValue], instance, ast, dynamicAnchors);
|
|
42
|
+
return propertyNames !== false && acc.concat(propertyNames);
|
|
43
|
+
} else {
|
|
44
|
+
return acc;
|
|
45
|
+
}
|
|
46
|
+
}, []);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default { id, experimental, compile, interpret, collectEvaluatedProperties };
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Instance from "../instance.js";
|
|
2
|
+
import Validation from "./validation.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const id = "https://json-schema.org/keyword/propertyNames";
|
|
6
|
+
|
|
7
|
+
const compile = (schema, ast) => Validation.compile(schema, ast);
|
|
5
8
|
|
|
6
9
|
const interpret = (propertyNames, instance, ast, dynamicAnchors) => {
|
|
7
10
|
return !Instance.typeOf(instance, "object") || Instance.keys(instance)
|
|
8
|
-
.every((key) =>
|
|
11
|
+
.every((key) => Validation.interpret(propertyNames, Instance.cons(key), ast, dynamicAnchors));
|
|
9
12
|
};
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
export default { id, compile, interpret };
|
package/lib/keywords/ref.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import Validation from "./validation.js";
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
const id = "https://json-schema.org/keyword/ref";
|
|
6
|
+
|
|
4
7
|
const compile = async (ref, ast) => {
|
|
5
8
|
const referencedSchema = await Schema.get(Schema.value(ref), ref);
|
|
6
|
-
return
|
|
9
|
+
return Validation.compile(referencedSchema, ast);
|
|
7
10
|
};
|
|
8
11
|
|
|
9
|
-
const interpret =
|
|
10
|
-
const collectEvaluatedProperties =
|
|
11
|
-
const collectEvaluatedItems =
|
|
12
|
+
const interpret = Validation.interpret;
|
|
13
|
+
const collectEvaluatedProperties = Validation.collectEvaluatedProperties;
|
|
14
|
+
const collectEvaluatedItems = Validation.collectEvaluatedItems;
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as Instance from "../instance.js";
|
|
2
|
+
import { getKeywordName } from "../keywords.js";
|
|
3
|
+
import * as Schema from "../schema.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const id = "https://json-schema.org/keyword/requireAllExcept";
|
|
7
|
+
const experimental = true;
|
|
8
|
+
|
|
9
|
+
const compile = async (schema, ast, parentSchema) => {
|
|
10
|
+
const requireAllExcept = await Schema.value(schema);
|
|
11
|
+
const propertiesKeyword = getKeywordName(schema.dialectId, "https://json-schema.org/keyword/properties");
|
|
12
|
+
const propertiesSchema = await Schema.step(propertiesKeyword, parentSchema);
|
|
13
|
+
const propertyNames = Schema.typeOf(propertiesSchema, "object") ? Schema.keys(propertiesSchema) : [];
|
|
14
|
+
|
|
15
|
+
const required = new Set(propertyNames);
|
|
16
|
+
requireAllExcept.forEach((propertyName) => propertyNames.remove(propertyName));
|
|
17
|
+
return [...required];
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const interpret = (required, instance) => {
|
|
21
|
+
return !Instance.typeOf(instance, "object") || required.every((propertyName) => Instance.value(instance).hasOwnProperty(propertyName));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default { id, experimental, compile, interpret };
|
package/lib/keywords/required.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import * as Instance from "../instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
const id = "https://json-schema.org/keyword/required";
|
|
6
|
+
|
|
4
7
|
const compile = (schema) => Schema.value(schema);
|
|
5
8
|
|
|
6
9
|
const interpret = (required, instance) => {
|
|
7
10
|
return !Instance.typeOf(instance, "object") || required.every((propertyName) => Object.prototype.hasOwnProperty.call(Instance.value(instance), propertyName));
|
|
8
11
|
};
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
export default { id, compile, interpret };
|
package/lib/keywords/then.js
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import { getKeywordName, getKeyword } from "../keywords.js";
|
|
3
|
+
import Validation from "./validation.js";
|
|
2
4
|
|
|
3
5
|
|
|
6
|
+
const id = "https://json-schema.org/keyword/then";
|
|
7
|
+
|
|
4
8
|
const compile = async (schema, ast, parentSchema) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
const ifKeyword = getKeywordName(schema.dialectId, "https://json-schema.org/keyword/if");
|
|
10
|
+
if (Schema.has(ifKeyword, parentSchema)) {
|
|
11
|
+
const ifSchema = await Schema.step(ifKeyword, parentSchema);
|
|
12
|
+
return [await Validation.compile(ifSchema, ast), await Validation.compile(schema, ast)];
|
|
8
13
|
} else {
|
|
9
14
|
return [];
|
|
10
15
|
}
|
|
11
16
|
};
|
|
12
17
|
|
|
13
18
|
const interpret = ([guard, block], instance, ast, dynamicAnchors) => {
|
|
14
|
-
return guard === undefined || !quietInterpretSchema(guard, instance, ast, dynamicAnchors) ||
|
|
19
|
+
return guard === undefined || !quietInterpretSchema(guard, instance, ast, dynamicAnchors) || Validation.interpret(block, instance, ast, dynamicAnchors);
|
|
15
20
|
};
|
|
16
21
|
|
|
17
22
|
// Interpret a schema without events being emitted
|
|
18
|
-
const quietInterpretSchema = (
|
|
19
|
-
const nodes = ast[
|
|
23
|
+
const quietInterpretSchema = (url, instance, ast, dynamicAnchors) => {
|
|
24
|
+
const nodes = ast[url][2];
|
|
20
25
|
|
|
21
26
|
return typeof nodes === "boolean" ? nodes : nodes
|
|
22
27
|
.every(([keywordId, , keywordValue]) => {
|
|
23
|
-
return
|
|
28
|
+
return getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors);
|
|
24
29
|
});
|
|
25
30
|
};
|
|
26
31
|
|
|
@@ -29,7 +34,7 @@ const collectEvaluatedProperties = ([guard, block], instance, ast, dynamicAnchor
|
|
|
29
34
|
return [];
|
|
30
35
|
}
|
|
31
36
|
|
|
32
|
-
return
|
|
37
|
+
return Validation.collectEvaluatedProperties(block, instance, ast, dynamicAnchors);
|
|
33
38
|
};
|
|
34
39
|
|
|
35
40
|
const collectEvaluatedItems = ([guard, block], instance, ast, dynamicAnchors) => {
|
|
@@ -37,7 +42,7 @@ const collectEvaluatedItems = ([guard, block], instance, ast, dynamicAnchors) =>
|
|
|
37
42
|
return new Set();
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
return
|
|
45
|
+
return Validation.collectEvaluatedItems(block, instance, ast, dynamicAnchors);
|
|
41
46
|
};
|
|
42
47
|
|
|
43
|
-
|
|
48
|
+
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
package/lib/keywords/type.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import * as Instance from "../instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
5
|
+
const id = "https://json-schema.org/keyword/type";
|
|
6
|
+
|
|
4
7
|
const compile = (schema) => Schema.value(schema);
|
|
5
8
|
const interpret = (type, instance) => typeof type === "string" ? Instance.typeOf(instance, type) : type.some(Instance.typeOf(instance));
|
|
6
9
|
|
|
7
|
-
|
|
10
|
+
export default { id, compile, interpret };
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import * as Instance from "../instance.js";
|
|
3
|
+
import Validation from "./validation.js";
|
|
2
4
|
|
|
3
5
|
|
|
6
|
+
const id = "https://json-schema.org/keyword/unevaluatedItems";
|
|
7
|
+
|
|
4
8
|
const compile = async (schema, ast, parentSchema) => {
|
|
5
|
-
return [Schema.uri(parentSchema), await
|
|
9
|
+
return [Schema.uri(parentSchema), await Validation.compile(schema, ast)];
|
|
6
10
|
};
|
|
7
11
|
|
|
8
12
|
const interpret = ([schemaUrl, unevaluatedItems], instance, ast, dynamicAnchors) => {
|
|
@@ -10,9 +14,9 @@ const interpret = ([schemaUrl, unevaluatedItems], instance, ast, dynamicAnchors)
|
|
|
10
14
|
return true;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
const itemIndexes =
|
|
17
|
+
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, ast, dynamicAnchors, true);
|
|
14
18
|
return itemIndexes === false || Instance.every((item, itemIndex) => {
|
|
15
|
-
return itemIndexes.has(itemIndex) ||
|
|
19
|
+
return itemIndexes.has(itemIndex) || Validation.interpret(unevaluatedItems, Instance.step(itemIndex, instance), ast, dynamicAnchors);
|
|
16
20
|
}, instance);
|
|
17
21
|
};
|
|
18
22
|
|
|
@@ -20,4 +24,4 @@ const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
|
|
|
20
24
|
return interpret(keywordValue, instance, ast, dynamicAnchors) && new Set(Instance.map((item, ndx) => ndx, instance));
|
|
21
25
|
};
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
export default { id, compile, interpret, collectEvaluatedItems };
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import * as Schema from "../schema.js";
|
|
2
|
+
import * as Instance from "../instance.js";
|
|
3
|
+
import Validation from "./validation.js";
|
|
2
4
|
|
|
3
5
|
|
|
6
|
+
const id = "https://json-schema.org/keyword/unevaluatedProperties";
|
|
7
|
+
|
|
4
8
|
const compile = async (schema, ast, parentSchema) => {
|
|
5
|
-
return [Schema.uri(parentSchema), await
|
|
9
|
+
return [Schema.uri(parentSchema), await Validation.compile(schema, ast)];
|
|
6
10
|
};
|
|
7
11
|
|
|
8
12
|
const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors) => {
|
|
@@ -10,15 +14,15 @@ const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnc
|
|
|
10
14
|
return true;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
const evaluatedPropertyNames =
|
|
17
|
+
const evaluatedPropertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, ast, dynamicAnchors, true);
|
|
14
18
|
|
|
15
19
|
return !evaluatedPropertyNames || Instance.entries(instance)
|
|
16
20
|
.filter(([propertyName]) => !evaluatedPropertyNames.some((pattern) => propertyName.match(pattern)))
|
|
17
|
-
.every(([, property]) =>
|
|
21
|
+
.every(([, property]) => Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors));
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
const collectEvaluatedProperties = (keywordValue, instance, ast, dynamicAnchors) =>{
|
|
21
25
|
return interpret(keywordValue, instance, ast, dynamicAnchors) && [new RegExp("")];
|
|
22
26
|
};
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
export default { id, compile, interpret, collectEvaluatedProperties };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import jsonStringify from "fastest-stable-stringify";
|
|
2
|
+
import * as Schema from "../schema.js";
|
|
3
|
+
import * as Instance from "../instance.js";
|
|
3
4
|
|
|
4
5
|
|
|
6
|
+
const id = "https://json-schema.org/keyword/uniqueItems";
|
|
7
|
+
|
|
5
8
|
const compile = (schema) => Schema.value(schema);
|
|
6
9
|
|
|
7
10
|
const interpret = (uniqueItems, instance) => {
|
|
@@ -13,4 +16,4 @@ const interpret = (uniqueItems, instance) => {
|
|
|
13
16
|
return new Set(normalizedItems).size === normalizedItems.length;
|
|
14
17
|
};
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
export default { id, compile, interpret };
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as Pact from "@hyperjump/pact";
|
|
2
|
+
import { publishAsync, publish } from "../pubsub.js";
|
|
3
|
+
import { isExperimentalKeywordEnabled } from "../configuration.js";
|
|
4
|
+
import * as Instance from "../instance.js";
|
|
5
|
+
import { getKeywordId, getKeyword } from "../keywords.js";
|
|
6
|
+
import { resolveUrl } from "../common.js";
|
|
7
|
+
import * as Schema from "../schema.js";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const id = "https://json-schema.org/evaluation/validate";
|
|
11
|
+
|
|
12
|
+
const compile = async (schema, ast) => {
|
|
13
|
+
// Meta validation
|
|
14
|
+
await publishAsync("validate.metaValidate", schema);
|
|
15
|
+
|
|
16
|
+
// Dynamic Scope
|
|
17
|
+
if (!(schema.id in ast.metaData)) {
|
|
18
|
+
ast.metaData[schema.id] = {
|
|
19
|
+
dynamicAnchors: schema.dynamicAnchors
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Compile
|
|
24
|
+
const url = Schema.uri(schema);
|
|
25
|
+
if (!(url in ast)) {
|
|
26
|
+
ast[url] = false; // Place dummy entry in ast to avoid recursive loops
|
|
27
|
+
|
|
28
|
+
const schemaValue = Schema.value(schema);
|
|
29
|
+
if (!["object", "boolean"].includes(typeof schemaValue)) {
|
|
30
|
+
throw Error(`No schema found at '${Schema.uri(schema)}'`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ast[url] = [
|
|
34
|
+
id,
|
|
35
|
+
Schema.uri(schema),
|
|
36
|
+
typeof schemaValue === "boolean" ? schemaValue : await Pact.pipeline([
|
|
37
|
+
Schema.entries,
|
|
38
|
+
Pact.map(async ([keyword, keywordSchema]) => {
|
|
39
|
+
const keywordId = getKeywordId(schema.dialectId, keyword);
|
|
40
|
+
if (!keywordId) {
|
|
41
|
+
throw Error(`Encountered unknown keyword '${keyword}' at ${Schema.uri(schema)}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const keywordHandler = getKeyword(keywordId);
|
|
45
|
+
if (keywordHandler.experimental && !isExperimentalKeywordEnabled(keywordId)) {
|
|
46
|
+
throw Error(`Encountered experimental keyword ${keyword} at '${Schema.uri(schema)}'. You can enable this keyword with: setExperimentalKeywordEnabled('${keywordId}', true)`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const keywordAst = await keywordHandler.compile(keywordSchema, ast, schema);
|
|
50
|
+
return [keywordId, Schema.uri(keywordSchema), keywordAst];
|
|
51
|
+
}),
|
|
52
|
+
Pact.all
|
|
53
|
+
], schema)
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return url;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const interpret = (url, instance, ast, dynamicAnchors) => {
|
|
61
|
+
const [keywordId, schemaUrl, nodes] = ast[url];
|
|
62
|
+
|
|
63
|
+
dynamicAnchors = { ...ast.metaData[resolveUrl("", url)].dynamicAnchors, ...dynamicAnchors };
|
|
64
|
+
|
|
65
|
+
publish("result.start");
|
|
66
|
+
const isValid = typeof nodes === "boolean" ? nodes : nodes
|
|
67
|
+
.every(([keywordId, schemaUrl, keywordValue]) => {
|
|
68
|
+
publish("result.start");
|
|
69
|
+
const isValid = getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors);
|
|
70
|
+
|
|
71
|
+
publish("result", {
|
|
72
|
+
keyword: keywordId,
|
|
73
|
+
absoluteKeywordLocation: schemaUrl,
|
|
74
|
+
instanceLocation: Instance.uri(instance),
|
|
75
|
+
valid: isValid,
|
|
76
|
+
ast: keywordValue
|
|
77
|
+
});
|
|
78
|
+
publish("result.end");
|
|
79
|
+
return isValid;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
publish("result", {
|
|
83
|
+
keyword: keywordId,
|
|
84
|
+
absoluteKeywordLocation: schemaUrl,
|
|
85
|
+
instanceLocation: Instance.uri(instance),
|
|
86
|
+
valid: isValid,
|
|
87
|
+
ast: url
|
|
88
|
+
});
|
|
89
|
+
publish("result.end");
|
|
90
|
+
return isValid;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const collectEvaluatedProperties = (url, instance, ast, dynamicAnchors, isTop = false) => {
|
|
94
|
+
const nodes = ast[url][2];
|
|
95
|
+
|
|
96
|
+
if (typeof nodes === "boolean") {
|
|
97
|
+
return nodes ? [] : false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return nodes
|
|
101
|
+
.filter(([keywordId]) => !isTop || keywordId !== "https://json-schema.org/keyword/unevaluatedProperties")
|
|
102
|
+
.reduce((acc, [keywordId, , keywordValue]) => {
|
|
103
|
+
const propertyNames = acc && getKeyword(keywordId).collectEvaluatedProperties(keywordValue, instance, ast, dynamicAnchors);
|
|
104
|
+
return propertyNames !== false && [...acc, ...propertyNames];
|
|
105
|
+
}, []);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const collectEvaluatedItems = (url, instance, ast, dynamicAnchors, isTop = false) => {
|
|
109
|
+
const nodes = ast[url][2];
|
|
110
|
+
|
|
111
|
+
if (typeof nodes === "boolean") {
|
|
112
|
+
return nodes ? new Set() : false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return nodes
|
|
116
|
+
.filter(([keywordId]) => !isTop || keywordId !== "https://json-schema.org/keyword/unevaluatedItems")
|
|
117
|
+
.reduce((acc, [keywordId, , keywordValue]) => {
|
|
118
|
+
const itemIndexes = acc !== false && getKeyword(keywordId).collectEvaluatedItems(keywordValue, instance, ast, dynamicAnchors);
|
|
119
|
+
return itemIndexes !== false && new Set([...acc, ...itemIndexes]);
|
|
120
|
+
}, new Set());
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default { id: "https://json-schema.org/keyword/vocabulary" };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { AST } from "./core.js";
|
|
2
|
+
import type { JsonDocument } from "./instance.js";
|
|
3
|
+
import type { SchemaDocument, Anchors } from "./schema.js";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const addKeyword: <A>(keywordHandler: Keyword<A>) => void;
|
|
7
|
+
export const getKeywordName: (dialectId: string, keywordId: string) => string;
|
|
8
|
+
export const getKeyword: <A>(id: string) => Keyword<A>;
|
|
9
|
+
export const defineVocabulary: (id: string, keywords: { [keyword: string]: string }) => void;
|
|
10
|
+
export const loadDialect: (dialectId: string, dialect: { [vocabularyId: string]: boolean }, allowUnknownKeywords?: boolean) => void;
|
|
11
|
+
|
|
12
|
+
export type Keyword<A> = {
|
|
13
|
+
id: string;
|
|
14
|
+
experimental?: boolean;
|
|
15
|
+
compile: (schema: SchemaDocument, ast: AST, parentSchema: SchemaDocument) => Promise<A>;
|
|
16
|
+
interpret: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors) => boolean;
|
|
17
|
+
collectEvaluatedProperties?: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors, isTop?: boolean) => string[] | false;
|
|
18
|
+
collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors, isTop?: boolean) => Set<number> | false;
|
|
19
|
+
};
|