@hyperjump/json-schema 1.16.2 → 1.16.3
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/annotations/index.d.ts +4 -4
- package/lib/experimental.d.ts +2 -2
- package/lib/index.d.ts +11 -4
- package/lib/keywords/unevaluatedItems.js +23 -43
- package/lib/keywords/unevaluatedProperties.js +21 -41
- package/lib/keywords/validation.js +25 -12
- package/package.json +1 -1
package/annotations/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { OutputFormat,
|
|
1
|
+
import type { OutputFormat, Output, ValidationOptions } from "../lib/index.js";
|
|
2
2
|
import type { CompiledSchema } from "../lib/experimental.js";
|
|
3
|
-
import type { JsonNode } from "../lib/
|
|
3
|
+
import type { JsonNode } from "../lib/instance.js";
|
|
4
4
|
import type { Json } from "@hyperjump/json-pointer";
|
|
5
5
|
|
|
6
6
|
|
|
@@ -15,7 +15,7 @@ export type Annotator = (value: Json, options?: OutputFormat | ValidationOptions
|
|
|
15
15
|
export const interpret: (compiledSchema: CompiledSchema, value: JsonNode, options?: OutputFormat | ValidationOptions) => JsonNode;
|
|
16
16
|
|
|
17
17
|
export class ValidationError extends Error {
|
|
18
|
-
public output:
|
|
18
|
+
public output: Output;
|
|
19
19
|
|
|
20
|
-
public constructor(output:
|
|
20
|
+
public constructor(output: Output);
|
|
21
21
|
}
|
package/lib/experimental.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Browser, Document } from "@hyperjump/browser";
|
|
2
|
-
import type { Validator, OutputUnit, OutputFormat, SchemaObject } from "./index.js";
|
|
2
|
+
import type { Validator, Output, OutputUnit, OutputFormat, SchemaObject } from "./index.js";
|
|
3
3
|
import type { JsonNode } from "./instance.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// Compile/interpret
|
|
7
7
|
export const compile: (schema: Browser<SchemaDocument>) => Promise<CompiledSchema>;
|
|
8
8
|
export const interpret: (
|
|
9
|
-
(compiledSchema: CompiledSchema, value: JsonNode, outputFormat?: OutputFormat) =>
|
|
9
|
+
(compiledSchema: CompiledSchema, value: JsonNode, outputFormat?: OutputFormat) => Output
|
|
10
10
|
) & (
|
|
11
11
|
(compiledSchema: CompiledSchema) => Validator
|
|
12
12
|
);
|
package/lib/index.d.ts
CHANGED
|
@@ -23,12 +23,19 @@ export type ValidationOptions = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export const validate: (
|
|
26
|
-
(url: string, value: Json, options?: OutputFormat | ValidationOptions) => Promise<
|
|
26
|
+
(url: string, value: Json, options?: OutputFormat | ValidationOptions) => Promise<Output>
|
|
27
27
|
) & (
|
|
28
28
|
(url: string) => Promise<Validator>
|
|
29
29
|
);
|
|
30
30
|
|
|
31
|
-
export type Validator = (value: Json, options?: OutputFormat | ValidationOptions) =>
|
|
31
|
+
export type Validator = (value: Json, options?: OutputFormat | ValidationOptions) => Output;
|
|
32
|
+
|
|
33
|
+
export type Output = {
|
|
34
|
+
valid: true;
|
|
35
|
+
} | {
|
|
36
|
+
valid: false;
|
|
37
|
+
errors?: OutputUnit[];
|
|
38
|
+
};
|
|
32
39
|
|
|
33
40
|
export type OutputUnit = {
|
|
34
41
|
keyword: string;
|
|
@@ -49,7 +56,7 @@ export const setShouldValidateSchema: (isEnabled: boolean) => void;
|
|
|
49
56
|
export const getShouldValidateSchema: () => boolean;
|
|
50
57
|
|
|
51
58
|
export class InvalidSchemaError extends Error {
|
|
52
|
-
public output:
|
|
59
|
+
public output: Output;
|
|
53
60
|
|
|
54
|
-
public constructor(output:
|
|
61
|
+
public constructor(output: Output);
|
|
55
62
|
}
|
|
@@ -1,31 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Validation } from "../experimental.js";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/unevaluatedItems";
|
|
6
6
|
|
|
7
|
-
const compile =
|
|
8
|
-
return [canonicalUri(parentSchema), await Validation.compile(schema, ast)];
|
|
9
|
-
};
|
|
7
|
+
const compile = (schema, ast) => Validation.compile(schema, ast);
|
|
10
8
|
|
|
11
|
-
const interpret = (
|
|
9
|
+
const interpret = (unevaluatedItems, instance, context) => {
|
|
12
10
|
if (Instance.typeOf(instance) !== "array") {
|
|
13
11
|
return true;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
// just to collect all the evalauted items.
|
|
18
|
-
if (context.rootSchema === schemaUrl) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
const evaluatedItemsPlugin = new EvaluatedItemsPlugin(schemaUrl);
|
|
22
|
-
if (!Validation.interpret(schemaUrl, instance, {
|
|
23
|
-
...context,
|
|
24
|
-
plugins: [...context.ast.plugins, evaluatedItemsPlugin]
|
|
25
|
-
})) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
const evaluatedItems = evaluatedItemsPlugin.evaluatedItems;
|
|
14
|
+
const evaluatedItems = context.schemaEvaluatedItems;
|
|
29
15
|
|
|
30
16
|
let isValid = true;
|
|
31
17
|
let index = 0;
|
|
@@ -46,38 +32,32 @@ const interpret = ([schemaUrl, unevaluatedItems], instance, context) => {
|
|
|
46
32
|
|
|
47
33
|
const simpleApplicator = true;
|
|
48
34
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.rootSchema = rootSchema;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
beforeSchema(_url, _instance, context) {
|
|
35
|
+
const plugin = {
|
|
36
|
+
beforeSchema(_url, instance, context) {
|
|
55
37
|
context.evaluatedItems ??= new Set();
|
|
56
|
-
context.schemaEvaluatedItems
|
|
57
|
-
|
|
38
|
+
context.schemaEvaluatedItems = new Set();
|
|
39
|
+
context.instanceLocation ??= Instance.uri(instance);
|
|
40
|
+
},
|
|
58
41
|
|
|
59
|
-
beforeKeyword(_node,
|
|
60
|
-
context.rootSchema = this.rootSchema;
|
|
42
|
+
beforeKeyword(_node, instance, context, schemaContext) {
|
|
61
43
|
context.evaluatedItems = new Set();
|
|
62
|
-
|
|
44
|
+
context.schemaEvaluatedItems = schemaContext.schemaEvaluatedItems;
|
|
45
|
+
context.instanceLocation = Instance.uri(instance);
|
|
46
|
+
},
|
|
63
47
|
|
|
64
|
-
afterKeyword(_node, _instance, context,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
schemaContext.schemaEvaluatedItems.add(index);
|
|
68
|
-
}
|
|
48
|
+
afterKeyword(_node, _instance, context, _valid, schemaContext) {
|
|
49
|
+
for (const property of context.evaluatedItems) {
|
|
50
|
+
schemaContext.schemaEvaluatedItems.add(property);
|
|
69
51
|
}
|
|
70
|
-
}
|
|
52
|
+
},
|
|
71
53
|
|
|
72
|
-
afterSchema(
|
|
73
|
-
if (valid) {
|
|
74
|
-
for (const
|
|
75
|
-
context.evaluatedItems.add(
|
|
54
|
+
afterSchema(_node, instance, context, valid) {
|
|
55
|
+
if (valid && Instance.uri(instance) === context.instanceLocation) {
|
|
56
|
+
for (const property of context.schemaEvaluatedItems) {
|
|
57
|
+
context.evaluatedItems.add(property);
|
|
76
58
|
}
|
|
77
59
|
}
|
|
78
|
-
|
|
79
|
-
this.evaluatedItems = context.evaluatedItems;
|
|
80
60
|
}
|
|
81
|
-
}
|
|
61
|
+
};
|
|
82
62
|
|
|
83
|
-
export default { id, compile, interpret, simpleApplicator };
|
|
63
|
+
export default { id, compile, interpret, simpleApplicator, plugin };
|
|
@@ -1,31 +1,17 @@
|
|
|
1
|
-
import { Validation
|
|
1
|
+
import { Validation } from "../experimental.js";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/unevaluatedProperties";
|
|
6
6
|
|
|
7
|
-
const compile =
|
|
8
|
-
return [canonicalUri(parentSchema), await Validation.compile(schema, ast)];
|
|
9
|
-
};
|
|
7
|
+
const compile = (schema, ast) => Validation.compile(schema, ast);
|
|
10
8
|
|
|
11
|
-
const interpret = (
|
|
9
|
+
const interpret = (unevaluatedProperties, instance, context) => {
|
|
12
10
|
if (Instance.typeOf(instance) !== "object") {
|
|
13
11
|
return true;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
// just to collect all the evalauted properties.
|
|
18
|
-
if (context.rootSchema === schemaUrl) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
const evaluatedPropertiesPlugin = new EvaluatedPropertiesPlugin(schemaUrl);
|
|
22
|
-
if (!Validation.interpret(schemaUrl, instance, {
|
|
23
|
-
...context,
|
|
24
|
-
plugins: [...context.ast.plugins, evaluatedPropertiesPlugin]
|
|
25
|
-
})) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
const evaluatedProperties = evaluatedPropertiesPlugin.evaluatedProperties;
|
|
14
|
+
const evaluatedProperties = context.schemaEvaluatedProperties;
|
|
29
15
|
|
|
30
16
|
let isValid = true;
|
|
31
17
|
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
@@ -46,38 +32,32 @@ const interpret = ([schemaUrl, unevaluatedProperties], instance, context) => {
|
|
|
46
32
|
|
|
47
33
|
const simpleApplicator = true;
|
|
48
34
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.rootSchema = rootSchema;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
beforeSchema(_url, _instance, context) {
|
|
35
|
+
const plugin = {
|
|
36
|
+
beforeSchema(_url, instance, context) {
|
|
55
37
|
context.evaluatedProperties ??= new Set();
|
|
56
|
-
context.schemaEvaluatedProperties
|
|
57
|
-
|
|
38
|
+
context.schemaEvaluatedProperties = new Set();
|
|
39
|
+
context.instanceLocation ??= Instance.uri(instance);
|
|
40
|
+
},
|
|
58
41
|
|
|
59
|
-
beforeKeyword(_node,
|
|
60
|
-
context.rootSchema = this.rootSchema;
|
|
42
|
+
beforeKeyword(_node, instance, context, schemaContext) {
|
|
61
43
|
context.evaluatedProperties = new Set();
|
|
62
|
-
|
|
44
|
+
context.schemaEvaluatedProperties = schemaContext.schemaEvaluatedProperties;
|
|
45
|
+
context.instanceLocation = Instance.uri(instance);
|
|
46
|
+
},
|
|
63
47
|
|
|
64
|
-
afterKeyword(_node, _instance, context,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
schemaContext.schemaEvaluatedProperties.add(property);
|
|
68
|
-
}
|
|
48
|
+
afterKeyword(_node, _instance, context, _valid, schemaContext) {
|
|
49
|
+
for (const property of context.evaluatedProperties) {
|
|
50
|
+
schemaContext.schemaEvaluatedProperties.add(property);
|
|
69
51
|
}
|
|
70
|
-
}
|
|
52
|
+
},
|
|
71
53
|
|
|
72
|
-
afterSchema(
|
|
73
|
-
if (valid) {
|
|
54
|
+
afterSchema(_node, instance, context, valid) {
|
|
55
|
+
if (valid && Instance.uri(instance) === context.instanceLocation) {
|
|
74
56
|
for (const property of context.schemaEvaluatedProperties) {
|
|
75
57
|
context.evaluatedProperties.add(property);
|
|
76
58
|
}
|
|
77
59
|
}
|
|
78
|
-
|
|
79
|
-
this.evaluatedProperties = context.evaluatedProperties;
|
|
80
60
|
}
|
|
81
|
-
}
|
|
61
|
+
};
|
|
82
62
|
|
|
83
|
-
export default { id, compile, interpret, simpleApplicator };
|
|
63
|
+
export default { id, compile, interpret, simpleApplicator, plugin };
|
|
@@ -28,23 +28,36 @@ const compile = async (schema, ast) => {
|
|
|
28
28
|
throw Error(`No schema found at '${url}'`);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
if (typeof schemaValue === "boolean") {
|
|
32
|
+
ast[url] = schemaValue;
|
|
33
|
+
} else {
|
|
34
|
+
ast[url] = await pipe(
|
|
35
|
+
entries(schema),
|
|
36
|
+
asyncMap(async ([keyword, keywordSchema]) => {
|
|
37
|
+
const keywordHandler = getKeywordByName(keyword, schema.document.dialectId);
|
|
38
|
+
if (keywordHandler.plugin) {
|
|
39
|
+
ast.plugins.add(keywordHandler.plugin);
|
|
40
|
+
}
|
|
41
|
+
const keywordAst = await keywordHandler.compile(keywordSchema, ast, schema);
|
|
42
|
+
return [keywordHandler.id, pointerAppend(keyword, canonicalUri(schema)), keywordAst];
|
|
43
|
+
}),
|
|
44
|
+
asyncCollectArray
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
// Keyword order shouldn't matter, but the unevaluated keywords are an exception :-(
|
|
48
|
+
ast[url].sort(keywordComparator);
|
|
49
|
+
}
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
return url;
|
|
46
53
|
};
|
|
47
54
|
|
|
55
|
+
const lastKeywords = new Set([
|
|
56
|
+
"https://json-schema.org/keyword/unevaluatedProperties",
|
|
57
|
+
"https://json-schema.org/keyword/unevaluatedItems"
|
|
58
|
+
]);
|
|
59
|
+
const keywordComparator = (_a, b) => lastKeywords.has(b[0]) ? -1 : 1;
|
|
60
|
+
|
|
48
61
|
const interpret = (url, instance, context) => {
|
|
49
62
|
let valid = true;
|
|
50
63
|
|
package/package.json
CHANGED