@hyperjump/json-schema 1.13.0 → 1.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -20
- package/annotations/index.js +27 -7
- package/annotations/test-utils.d.ts +1 -0
- package/annotations/test-utils.js +38 -0
- package/bundle/index.js +39 -227
- package/draft-04/additionalItems.js +13 -19
- package/draft-04/dependencies.js +7 -7
- package/draft-04/items.js +26 -14
- package/draft-2020-12/dynamicRef.js +20 -8
- package/lib/core.js +19 -4
- package/lib/evaluation-plugins/annotations.js +32 -0
- package/lib/evaluation-plugins/basic-output.js +34 -0
- package/lib/evaluation-plugins/detailed-output.js +36 -0
- package/lib/experimental.d.ts +18 -5
- package/lib/experimental.js +3 -0
- package/lib/instance.js +12 -3
- package/lib/keywords/additionalProperties.js +8 -22
- package/lib/keywords/allOf.js +1 -29
- package/lib/keywords/anyOf.js +1 -27
- package/lib/keywords/conditional.js +1 -27
- package/lib/keywords/contains.js +14 -18
- package/lib/keywords/contentSchema.js +6 -3
- package/lib/keywords/dependentSchemas.js +1 -21
- package/lib/keywords/dynamicRef.js +19 -6
- package/lib/keywords/else.js +2 -19
- package/lib/keywords/if.js +1 -9
- package/lib/keywords/itemPattern.js +5 -9
- package/lib/keywords/items.js +5 -14
- package/lib/keywords/oneOf.js +1 -33
- package/lib/keywords/patternProperties.js +7 -25
- package/lib/keywords/prefixItems.js +2 -5
- package/lib/keywords/properties.js +6 -22
- package/lib/keywords/propertyDependencies.js +1 -20
- package/lib/keywords/propertyNames.js +1 -1
- package/lib/keywords/ref.js +1 -3
- package/lib/keywords/then.js +2 -19
- package/lib/keywords/unevaluatedItems.js +44 -20
- package/lib/keywords/unevaluatedProperties.js +40 -26
- package/lib/keywords/validation.js +31 -129
- package/lib/keywords.js +30 -30
- package/package.json +1 -1
package/lib/keywords/oneOf.js
CHANGED
|
@@ -22,36 +22,4 @@ const interpret = (oneOf, instance, context) => {
|
|
|
22
22
|
return validCount === 1;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
let evaluatedProperties = false;
|
|
27
|
-
for (const schemaUrl of oneOf) {
|
|
28
|
-
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, context);
|
|
29
|
-
if (propertyNames) {
|
|
30
|
-
if (evaluatedProperties) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
evaluatedProperties = propertyNames;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return evaluatedProperties;
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const collectEvaluatedItems = (oneOf, instance, context) => {
|
|
42
|
-
let evaluatedItemIndexes = false;
|
|
43
|
-
for (const schemaUrl of oneOf) {
|
|
44
|
-
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, context);
|
|
45
|
-
if (itemIndexes) {
|
|
46
|
-
if (evaluatedItemIndexes) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
evaluatedItemIndexes = itemIndexes;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return evaluatedItemIndexes;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
|
25
|
+
export default { id, compile, interpret };
|
|
@@ -23,38 +23,20 @@ const interpret = (patternProperties, instance, context) => {
|
|
|
23
23
|
let isValid = true;
|
|
24
24
|
for (const [pattern, schemaUri] of patternProperties) {
|
|
25
25
|
for (const [propertyNameNode, propertyValue] of Instance.entries(instance)) {
|
|
26
|
-
const propertyName = Instance.value(propertyNameNode);
|
|
27
|
-
if (pattern.test(propertyName) && !Validation.interpret(schemaUri, propertyValue, context)) {
|
|
28
|
-
isValid = false;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return isValid;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const simpleApplicator = true;
|
|
37
|
-
|
|
38
|
-
const collectEvaluatedProperties = (patternProperties, instance, context) => {
|
|
39
|
-
if (Instance.typeOf(instance) !== "object") {
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const evaluatedPropertyNames = new Set();
|
|
44
|
-
for (const [pattern, propertySchema] of patternProperties) {
|
|
45
|
-
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
46
26
|
const propertyName = Instance.value(propertyNameNode);
|
|
47
27
|
if (pattern.test(propertyName)) {
|
|
48
|
-
if (!Validation.interpret(
|
|
49
|
-
|
|
28
|
+
if (!Validation.interpret(schemaUri, propertyValue, context)) {
|
|
29
|
+
isValid = false;
|
|
50
30
|
}
|
|
51
31
|
|
|
52
|
-
|
|
32
|
+
context.evaluatedProperties?.add(propertyName);
|
|
53
33
|
}
|
|
54
34
|
}
|
|
55
35
|
}
|
|
56
36
|
|
|
57
|
-
return
|
|
37
|
+
return isValid;
|
|
58
38
|
};
|
|
59
39
|
|
|
60
|
-
|
|
40
|
+
const simpleApplicator = true;
|
|
41
|
+
|
|
42
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -29,6 +29,7 @@ const interpret = (prefixItems, instance, context) => {
|
|
|
29
29
|
isValid = false;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
context.evaluatedItems?.add(index);
|
|
32
33
|
index++;
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -37,8 +38,4 @@ const interpret = (prefixItems, instance, context) => {
|
|
|
37
38
|
|
|
38
39
|
const simpleApplicator = true;
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
return interpret(items, instance, context) && new Set(items.map((_item, ndx) => ndx));
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export default { id, compile, interpret, simpleApplicator, collectEvaluatedItems };
|
|
41
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -18,36 +18,20 @@ const interpret = (properties, instance, context) => {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
let isValid = true;
|
|
21
|
-
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
22
|
-
const propertyName = Instance.value(propertyNameNode);
|
|
23
|
-
if (propertyName in properties && !Validation.interpret(properties[propertyName], property, context)) {
|
|
24
|
-
isValid = false;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return isValid;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const simpleApplicator = true;
|
|
32
|
-
|
|
33
|
-
const collectEvaluatedProperties = (properties, instance, context) => {
|
|
34
|
-
if (Instance.typeOf(instance) !== "object") {
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const evaluatedPropertyNames = new Set();
|
|
39
21
|
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
40
22
|
const propertyName = Instance.value(propertyNameNode);
|
|
41
23
|
if (propertyName in properties) {
|
|
42
24
|
if (!Validation.interpret(properties[propertyName], property, context)) {
|
|
43
|
-
|
|
25
|
+
isValid = false;
|
|
44
26
|
}
|
|
45
27
|
|
|
46
|
-
|
|
28
|
+
context.evaluatedProperties?.add(propertyName);
|
|
47
29
|
}
|
|
48
30
|
}
|
|
49
31
|
|
|
50
|
-
return
|
|
32
|
+
return isValid;
|
|
51
33
|
};
|
|
52
34
|
|
|
53
|
-
|
|
35
|
+
const simpleApplicator = true;
|
|
36
|
+
|
|
37
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -43,23 +43,4 @@ const interpret = (propertyDependencies, instance, context) => {
|
|
|
43
43
|
|
|
44
44
|
const simpleApplicator = true;
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
const evaluatedPropertyNames = new Set();
|
|
48
|
-
for (const propertyName in propertyDependencies) {
|
|
49
|
-
const propertyValue = Instance.value(instance)[propertyName];
|
|
50
|
-
|
|
51
|
-
const valueMappings = propertyDependencies[propertyName];
|
|
52
|
-
if (Instance.has(propertyName, instance) && propertyValue in valueMappings) {
|
|
53
|
-
const propertyNames = Validation.collectEvaluatedProperties(valueMappings[propertyValue], instance, context);
|
|
54
|
-
if (!propertyNames) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
propertyNames.forEach(evaluatedPropertyNames.add, evaluatedPropertyNames);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return evaluatedPropertyNames;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export default { id, compile, interpret, simpleApplicator, collectEvaluatedProperties };
|
|
46
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -13,7 +13,7 @@ const interpret = (propertyNames, instance, context) => {
|
|
|
13
13
|
|
|
14
14
|
let isValid = true;
|
|
15
15
|
for (const key of Instance.keys(instance)) {
|
|
16
|
-
if (!Validation.interpret(propertyNames, key,
|
|
16
|
+
if (!Validation.interpret(propertyNames, key, context)) {
|
|
17
17
|
isValid = false;
|
|
18
18
|
}
|
|
19
19
|
}
|
package/lib/keywords/ref.js
CHANGED
|
@@ -5,9 +5,7 @@ const id = "https://json-schema.org/keyword/ref";
|
|
|
5
5
|
|
|
6
6
|
const compile = (...args) => Validation.compile(...args);
|
|
7
7
|
const interpret = (...args) => Validation.interpret(...args);
|
|
8
|
-
const collectEvaluatedProperties = (...args) => Validation.collectEvaluatedProperties(...args);
|
|
9
|
-
const collectEvaluatedItems = (...args) => Validation.collectEvaluatedItems(...args);
|
|
10
8
|
|
|
11
9
|
const simpleApplicator = true;
|
|
12
10
|
|
|
13
|
-
export default { id, compile, interpret, simpleApplicator
|
|
11
|
+
export default { id, compile, interpret, simpleApplicator };
|
package/lib/keywords/then.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as Browser from "@hyperjump/browser";
|
|
2
|
-
import { FLAG } from "../index.js";
|
|
3
2
|
import { getKeywordName, Validation } from "../experimental.js";
|
|
4
3
|
|
|
5
4
|
|
|
@@ -17,26 +16,10 @@ const compile = async (schema, ast, parentSchema) => {
|
|
|
17
16
|
|
|
18
17
|
const interpret = ([ifSchema, thenSchema], instance, context) => {
|
|
19
18
|
return ifSchema === undefined
|
|
20
|
-
|| !Validation.interpret(ifSchema, instance, { ...context,
|
|
19
|
+
|| !Validation.interpret(ifSchema, instance, { ...context, plugins: context.ast.plugins })
|
|
21
20
|
|| Validation.interpret(thenSchema, instance, context);
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
const simpleApplicator = true;
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
if (ifSchema === undefined || !Validation.interpret(ifSchema, instance, context)) {
|
|
28
|
-
return new Set();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return Validation.collectEvaluatedProperties(thenSchema, instance, context);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const collectEvaluatedItems = ([ifSchema, thenSchema], instance, context) => {
|
|
35
|
-
if (ifSchema === undefined || !Validation.interpret(ifSchema, instance, context)) {
|
|
36
|
-
return new Set();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return Validation.collectEvaluatedItems(thenSchema, instance, context);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export default { id, compile, interpret, simpleApplicator, collectEvaluatedProperties, collectEvaluatedItems };
|
|
25
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { zip, range } from "@hyperjump/pact";
|
|
2
|
-
import { FLAG } from "../index.js";
|
|
3
1
|
import { canonicalUri, Validation } from "../experimental.js";
|
|
4
2
|
import * as Instance from "../instance.js";
|
|
5
3
|
|
|
@@ -15,17 +13,33 @@ const interpret = ([schemaUrl, unevaluatedItems], instance, context) => {
|
|
|
15
13
|
return true;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
if (context.rootSchema === schemaUrl) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Because order matters, we re-evaluate this schema skipping this keyword
|
|
21
|
+
// just to collect all the evalauted items.
|
|
22
|
+
const keywordContext = {
|
|
23
|
+
...context,
|
|
24
|
+
plugins: [...context.ast.plugins, unevaluatedPlugin],
|
|
25
|
+
rootSchema: schemaUrl
|
|
26
|
+
};
|
|
27
|
+
if (!Validation.interpret(schemaUrl, instance, keywordContext)) {
|
|
21
28
|
return true;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
31
|
let isValid = true;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
let index = 0;
|
|
33
|
+
for (const item of Instance.iter(instance)) {
|
|
34
|
+
if (!keywordContext.evaluatedItems.has(index)) {
|
|
35
|
+
if (!Validation.interpret(unevaluatedItems, item, context)) {
|
|
36
|
+
isValid = false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
context.evaluatedItems?.add(index);
|
|
28
40
|
}
|
|
41
|
+
|
|
42
|
+
index++;
|
|
29
43
|
}
|
|
30
44
|
|
|
31
45
|
return isValid;
|
|
@@ -33,19 +47,29 @@ const interpret = ([schemaUrl, unevaluatedItems], instance, context) => {
|
|
|
33
47
|
|
|
34
48
|
const simpleApplicator = true;
|
|
35
49
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
const unevaluatedPlugin = {
|
|
51
|
+
beforeSchema(_url, _instance, context) {
|
|
52
|
+
context.evaluatedItems ??= new Set();
|
|
53
|
+
context.schemaEvaluatedItems ??= new Set();
|
|
54
|
+
},
|
|
55
|
+
beforeKeyword(_node, _instance, context, schemaContext) {
|
|
56
|
+
context.rootSchema = schemaContext.rootSchema;
|
|
57
|
+
context.evaluatedItems = new Set();
|
|
58
|
+
},
|
|
59
|
+
afterKeyword(_node, _instance, context, valid, schemaContext) {
|
|
60
|
+
if (valid) {
|
|
61
|
+
for (const index of context.evaluatedItems) {
|
|
62
|
+
schemaContext.schemaEvaluatedItems.add(index);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
afterSchema(_url, _instance, context, valid) {
|
|
67
|
+
if (valid) {
|
|
68
|
+
for (const index of context.schemaEvaluatedItems) {
|
|
69
|
+
context.evaluatedItems.add(index);
|
|
70
|
+
}
|
|
46
71
|
}
|
|
47
72
|
}
|
|
48
|
-
return evaluatedIndexes;
|
|
49
73
|
};
|
|
50
74
|
|
|
51
|
-
export default { id, compile, interpret, simpleApplicator
|
|
75
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FLAG } from "../index.js";
|
|
2
1
|
import { Validation, canonicalUri } from "../experimental.js";
|
|
3
2
|
import * as Instance from "../instance.js";
|
|
4
3
|
|
|
@@ -14,18 +13,33 @@ const interpret = ([schemaUrl, unevaluatedProperties], instance, context) => {
|
|
|
14
13
|
return true;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
if (context.rootSchema === schemaUrl) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Because order matters, we re-evaluate this schema skipping this keyword
|
|
21
|
+
// just to collect all the evalauted properties.
|
|
22
|
+
const keywordContext = {
|
|
23
|
+
...context,
|
|
24
|
+
plugins: [...context.ast.plugins, unevaluatedPlugin],
|
|
25
|
+
rootSchema: schemaUrl
|
|
26
|
+
};
|
|
27
|
+
if (!Validation.interpret(schemaUrl, instance, keywordContext)) {
|
|
20
28
|
return true;
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
let isValid = true;
|
|
24
32
|
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
25
33
|
const propertyName = Instance.value(propertyNameNode);
|
|
26
|
-
if (
|
|
34
|
+
if (keywordContext.evaluatedProperties.has(propertyName)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!Validation.interpret(unevaluatedProperties, property, context)) {
|
|
27
39
|
isValid = false;
|
|
28
40
|
}
|
|
41
|
+
|
|
42
|
+
context.evaluatedProperties?.add(propertyName);
|
|
29
43
|
}
|
|
30
44
|
|
|
31
45
|
return isValid;
|
|
@@ -33,29 +47,29 @@ const interpret = ([schemaUrl, unevaluatedProperties], instance, context) => {
|
|
|
33
47
|
|
|
34
48
|
const simpleApplicator = true;
|
|
35
49
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
const unevaluatedPlugin = {
|
|
51
|
+
beforeSchema(_url, _instance, context) {
|
|
52
|
+
context.evaluatedProperties ??= new Set();
|
|
53
|
+
context.schemaEvaluatedProperties ??= new Set();
|
|
54
|
+
},
|
|
55
|
+
beforeKeyword(_node, _instance, context, schemaContext) {
|
|
56
|
+
context.rootSchema = schemaContext.rootSchema;
|
|
57
|
+
context.evaluatedProperties = new Set();
|
|
58
|
+
},
|
|
59
|
+
afterKeyword(_node, _instance, context, valid, schemaContext) {
|
|
60
|
+
if (valid) {
|
|
61
|
+
for (const property of context.evaluatedProperties) {
|
|
62
|
+
schemaContext.schemaEvaluatedProperties.add(property);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
afterSchema(_url, _instance, context, valid) {
|
|
67
|
+
if (valid) {
|
|
68
|
+
for (const property of context.schemaEvaluatedProperties) {
|
|
69
|
+
context.evaluatedProperties.add(property);
|
|
52
70
|
}
|
|
53
|
-
|
|
54
|
-
evaluatedPropertyNames.add(propertyName);
|
|
55
71
|
}
|
|
56
72
|
}
|
|
57
|
-
|
|
58
|
-
return evaluatedPropertyNames;
|
|
59
73
|
};
|
|
60
74
|
|
|
61
|
-
export default { id, compile, interpret, simpleApplicator
|
|
75
|
+
export default { id, compile, interpret, simpleApplicator };
|
|
@@ -2,10 +2,7 @@ import { value, entries } from "@hyperjump/browser";
|
|
|
2
2
|
import { pipe, asyncMap, asyncCollectArray } from "@hyperjump/pact";
|
|
3
3
|
import { append as pointerAppend } from "@hyperjump/json-pointer";
|
|
4
4
|
import { publishAsync } from "../pubsub.js";
|
|
5
|
-
import
|
|
6
|
-
import { toAbsoluteUri } from "../common.js";
|
|
7
|
-
import { canonicalUri, getKeyword, getKeywordByName, BASIC, DETAILED } from "../experimental.js";
|
|
8
|
-
import { FLAG } from "../index.js";
|
|
5
|
+
import { canonicalUri, getKeyword, getKeywordByName } from "../experimental.js";
|
|
9
6
|
|
|
10
7
|
|
|
11
8
|
const id = "https://json-schema.org/evaluation/validate";
|
|
@@ -35,6 +32,9 @@ const compile = async (schema, ast) => {
|
|
|
35
32
|
entries(schema),
|
|
36
33
|
asyncMap(async ([keyword, keywordSchema]) => {
|
|
37
34
|
const keywordHandler = getKeywordByName(keyword, schema.document.dialectId);
|
|
35
|
+
if (keywordHandler.plugin) {
|
|
36
|
+
ast.plugins.add(keywordHandler.plugin);
|
|
37
|
+
}
|
|
38
38
|
const keywordAst = await keywordHandler.compile(keywordSchema, ast, schema);
|
|
39
39
|
return [keywordHandler.id, pointerAppend(keyword, canonicalUri(schema)), keywordAst];
|
|
40
40
|
}),
|
|
@@ -45,140 +45,42 @@ const compile = async (schema, ast) => {
|
|
|
45
45
|
return url;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
-
const interpret = (url, instance,
|
|
49
|
-
|
|
48
|
+
const interpret = (url, instance, context) => {
|
|
49
|
+
let valid = true;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
} else {
|
|
55
|
-
errors.push({
|
|
56
|
-
keyword: id,
|
|
57
|
-
absoluteKeywordLocation: url,
|
|
58
|
-
instanceLocation: Instance.uri(instance)
|
|
59
|
-
});
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
} else {
|
|
63
|
-
const schemaAnnotations = [];
|
|
51
|
+
for (const plugin of context.plugins) {
|
|
52
|
+
plugin.beforeSchema(url, instance, context);
|
|
53
|
+
}
|
|
64
54
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const
|
|
55
|
+
if (typeof context.ast[url] === "boolean") {
|
|
56
|
+
valid = context.ast[url];
|
|
57
|
+
} else {
|
|
58
|
+
for (const node of context.ast[url]) {
|
|
59
|
+
const [keywordId, , keywordValue] = node;
|
|
60
|
+
const keyword = getKeyword(keywordId);
|
|
61
|
+
|
|
62
|
+
const keywordContext = {
|
|
63
|
+
ast: context.ast,
|
|
64
|
+
plugins: context.plugins
|
|
65
|
+
};
|
|
66
|
+
for (const plugin of context.plugins) {
|
|
67
|
+
plugin.beforeKeyword(node, instance, keywordContext, context, keyword);
|
|
68
|
+
}
|
|
69
|
+
const isKeywordValid = keyword.interpret(keywordValue, instance, keywordContext);
|
|
70
70
|
if (!isKeywordValid) {
|
|
71
|
-
|
|
71
|
+
valid = false;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
break;
|
|
77
|
-
case BASIC:
|
|
78
|
-
if (!isKeywordValid) {
|
|
79
|
-
if (!keywordHandler.simpleApplicator) {
|
|
80
|
-
errors.push({
|
|
81
|
-
keyword: keywordId,
|
|
82
|
-
absoluteKeywordLocation: schemaUri,
|
|
83
|
-
instanceLocation: Instance.uri(instance)
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
errors.push(...context.errors);
|
|
87
|
-
} else {
|
|
88
|
-
const annotation = keywordHandler.annotation?.(keywordValue, instance);
|
|
89
|
-
if (annotation !== undefined) {
|
|
90
|
-
schemaAnnotations.unshift({
|
|
91
|
-
keyword: keywordId,
|
|
92
|
-
absoluteKeywordLocation: schemaUri,
|
|
93
|
-
instanceLocation: Instance.uri(instance),
|
|
94
|
-
annotation: annotation
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
for (const contextAnnotation of context.annotations) {
|
|
98
|
-
schemaAnnotations.unshift(contextAnnotation);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
break;
|
|
102
|
-
case DETAILED: {
|
|
103
|
-
if (!isKeywordValid) {
|
|
104
|
-
const outputUnit = {
|
|
105
|
-
keyword: keywordId,
|
|
106
|
-
absoluteKeywordLocation: schemaUri,
|
|
107
|
-
instanceLocation: Instance.uri(instance)
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
errors.push(outputUnit);
|
|
111
|
-
if (context.errors.length > 0) {
|
|
112
|
-
outputUnit.errors = context.errors;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
default:
|
|
118
|
-
throw Error(`Unsupported output format '${outputFormat}'`);
|
|
74
|
+
for (const plugin of context.plugins) {
|
|
75
|
+
plugin.afterKeyword(node, instance, keywordContext, isKeywordValid, context, keyword);
|
|
119
76
|
}
|
|
120
77
|
}
|
|
121
|
-
|
|
122
|
-
if (outputFormat === BASIC && isSchemaValid) {
|
|
123
|
-
annotations.push(...schemaAnnotations);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
return isSchemaValid;
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const emptyPropertyNames = new Set();
|
|
131
|
-
const collectEvaluatedProperties = (url, instance, context, isTop = false) => {
|
|
132
|
-
if (typeof context.ast[url] === "boolean") {
|
|
133
|
-
return context.ast[url] ? emptyPropertyNames : false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const accumulatedPropertyNames = new Set();
|
|
137
|
-
for (const [keywordId, , keywordValue] of context.ast[url]) {
|
|
138
|
-
if (isTop && keywordId === "https://json-schema.org/keyword/unevaluatedProperties") {
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const keywordHandler = getKeyword(keywordId);
|
|
143
|
-
const propertyNames = "collectEvaluatedProperties" in keywordHandler
|
|
144
|
-
? keywordHandler.collectEvaluatedProperties(keywordValue, instance, context, isTop)
|
|
145
|
-
: keywordHandler.interpret(keywordValue, instance, context) && emptyPropertyNames;
|
|
146
|
-
|
|
147
|
-
if (propertyNames === false) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
propertyNames.forEach(accumulatedPropertyNames.add, accumulatedPropertyNames);
|
|
152
78
|
}
|
|
153
79
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const emptyItemIndexes = new Set();
|
|
158
|
-
const collectEvaluatedItems = (url, instance, context, isTop = false) => {
|
|
159
|
-
if (typeof context.ast[url] === "boolean") {
|
|
160
|
-
return context.ast[url] ? emptyItemIndexes : false;
|
|
80
|
+
for (const plugin of context.plugins) {
|
|
81
|
+
plugin.afterSchema(url, instance, context, valid);
|
|
161
82
|
}
|
|
162
|
-
|
|
163
|
-
const accumulatedItemIndexes = new Set();
|
|
164
|
-
for (const [keywordId, , keywordValue] of context.ast[url]) {
|
|
165
|
-
if (isTop && keywordId === "https://json-schema.org/keyword/unevaluatedItems") {
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const keywordHandler = getKeyword(keywordId);
|
|
170
|
-
const itemIndexes = "collectEvaluatedItems" in keywordHandler
|
|
171
|
-
? keywordHandler.collectEvaluatedItems(keywordValue, instance, context, isTop)
|
|
172
|
-
: keywordHandler.interpret(keywordValue, instance, context) && emptyItemIndexes;
|
|
173
|
-
|
|
174
|
-
if (itemIndexes === false) {
|
|
175
|
-
return false;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
itemIndexes.forEach(accumulatedItemIndexes.add, accumulatedItemIndexes);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
return accumulatedItemIndexes;
|
|
83
|
+
return valid;
|
|
182
84
|
};
|
|
183
85
|
|
|
184
|
-
export default { id, compile, interpret
|
|
86
|
+
export default { id, compile, interpret };
|