@hyperjump/json-schema 1.7.3 → 1.9.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/README.md +61 -56
- package/annotations/annotated-instance.d.ts +4 -82
- package/annotations/annotated-instance.js +31 -33
- package/annotations/index.d.ts +7 -3
- package/annotations/index.js +8 -108
- package/draft-04/additionalItems.js +1 -1
- package/draft-04/items.js +1 -1
- package/lib/core.js +8 -50
- package/lib/experimental.d.ts +6 -7
- package/lib/experimental.js +6 -2
- package/lib/index.d.ts +5 -2
- package/lib/instance.d.ts +24 -23
- package/lib/instance.js +133 -38
- package/lib/keywords/additionalProperties.js +12 -7
- package/lib/keywords/allOf.js +7 -1
- package/lib/keywords/comment.js +4 -3
- package/lib/keywords/const.js +1 -1
- package/lib/keywords/contentEncoding.js +12 -2
- package/lib/keywords/contentMediaType.js +12 -2
- package/lib/keywords/contentSchema.js +8 -3
- package/lib/keywords/default.js +12 -2
- package/lib/keywords/dependentRequired.js +12 -3
- package/lib/keywords/dependentSchemas.js +12 -3
- package/lib/keywords/deprecated.js +12 -2
- package/lib/keywords/description.js +12 -2
- package/lib/keywords/enum.js +5 -2
- package/lib/keywords/examples.js +12 -2
- package/lib/keywords/format.js +12 -2
- package/lib/keywords/items.js +9 -6
- package/lib/keywords/maxContains.js +6 -2
- package/lib/keywords/maxItems.js +3 -1
- package/lib/keywords/maxLength.js +3 -1
- package/lib/keywords/minContains.js +6 -2
- package/lib/keywords/minItems.js +3 -1
- package/lib/keywords/minLength.js +3 -1
- package/lib/keywords/oneOf.js +0 -4
- package/lib/keywords/pattern.js +3 -1
- package/lib/keywords/patternProperties.js +18 -9
- package/lib/keywords/prefixItems.js +21 -6
- package/lib/keywords/properties.js +16 -7
- package/lib/keywords/propertyDependencies.js +18 -6
- package/lib/keywords/propertyNames.js +13 -5
- package/lib/keywords/readOnly.js +12 -2
- package/lib/keywords/title.js +12 -2
- package/lib/keywords/unevaluatedItems.js +14 -7
- package/lib/keywords/unevaluatedProperties.js +15 -8
- package/lib/keywords/uniqueItems.js +1 -1
- package/lib/keywords/unknown.js +12 -2
- package/lib/keywords/validation.js +24 -27
- package/lib/keywords/writeOnly.js +12 -2
- package/lib/keywords.js +5 -0
- package/lib/output.js +43 -0
- package/lib/schema.js +4 -2
- package/openapi-3-0/discriminator.js +12 -2
- package/openapi-3-0/example.js +12 -2
- package/openapi-3-0/externalDocs.js +12 -2
- package/openapi-3-0/index.js +2 -2
- package/openapi-3-0/nullable.js +8 -2
- package/openapi-3-0/xml.js +12 -2
- package/openapi-3-1/index.js +2 -2
- package/package.json +3 -3
- package/bundle/README.md +0 -134
- package/lib/keywords/meta-data.js +0 -7
package/lib/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import curry from "just-curry-it";
|
|
2
2
|
import { resolveIri, toAbsoluteIri } from "@hyperjump/uri";
|
|
3
|
-
import { subscribe
|
|
3
|
+
import { subscribe } from "./pubsub.js";
|
|
4
4
|
import {
|
|
5
5
|
setMetaSchemaOutputFormat,
|
|
6
6
|
getShouldValidateSchema,
|
|
@@ -11,15 +11,16 @@ import { InvalidSchemaError } from "./invalid-schema-error.js";
|
|
|
11
11
|
import { getSchema, registerSchema, unregisterSchema as schemaUnregister } from "./schema.js";
|
|
12
12
|
import { getKeywordName } from "./keywords.js";
|
|
13
13
|
import Validation from "./keywords/validation.js";
|
|
14
|
+
import { toOutputFormat } from "./output.js";
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
export const FLAG = "FLAG", BASIC = "BASIC"
|
|
17
|
+
export const FLAG = "FLAG", BASIC = "BASIC";
|
|
17
18
|
setMetaSchemaOutputFormat(FLAG);
|
|
18
19
|
|
|
19
20
|
export const validate = async (url, value = undefined, outputFormat = undefined) => {
|
|
20
21
|
const schema = await getSchema(url);
|
|
21
22
|
const compiled = await compile(schema);
|
|
22
|
-
const interpretAst = (value, outputFormat) => interpret(compiled, Instance.
|
|
23
|
+
const interpretAst = (value, outputFormat) => interpret(compiled, Instance.fromJs(value), outputFormat);
|
|
23
24
|
|
|
24
25
|
return value === undefined ? interpretAst : interpretAst(value, outputFormat);
|
|
25
26
|
};
|
|
@@ -30,54 +31,11 @@ export const compile = async (schema) => {
|
|
|
30
31
|
return { ast, schemaUri };
|
|
31
32
|
};
|
|
32
33
|
|
|
33
|
-
export const interpret = curry(({ ast, schemaUri },
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const output = [];
|
|
39
|
-
const subscriptionToken = subscribe("result", outputHandler(outputFormat, output));
|
|
40
|
-
try {
|
|
41
|
-
Validation.interpret(schemaUri, value, ast, {});
|
|
42
|
-
} finally {
|
|
43
|
-
unsubscribe("result", subscriptionToken);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return output[0];
|
|
34
|
+
export const interpret = curry(({ ast, schemaUri }, instance, outputFormat = FLAG) => {
|
|
35
|
+
Validation.interpret(schemaUri, instance, ast, {});
|
|
36
|
+
return toOutputFormat(instance, outputFormat);
|
|
47
37
|
});
|
|
48
38
|
|
|
49
|
-
const outputHandler = (outputFormat, output) => {
|
|
50
|
-
const resultStack = [];
|
|
51
|
-
|
|
52
|
-
return (message, keywordResult) => {
|
|
53
|
-
if (message === "result") {
|
|
54
|
-
const { keyword, absoluteKeywordLocation, instanceLocation, valid } = keywordResult;
|
|
55
|
-
const result = { keyword, absoluteKeywordLocation, instanceLocation, valid, errors: [] };
|
|
56
|
-
resultStack.push(result);
|
|
57
|
-
} else if (message === "result.start") {
|
|
58
|
-
resultStack.push(message);
|
|
59
|
-
} else if (message === "result.end") {
|
|
60
|
-
const result = resultStack.pop();
|
|
61
|
-
while (resultStack[resultStack.length - 1] !== "result.start") {
|
|
62
|
-
const topResult = resultStack.pop();
|
|
63
|
-
|
|
64
|
-
const errors = [topResult];
|
|
65
|
-
if (outputFormat === BASIC) {
|
|
66
|
-
errors.push(...topResult.errors);
|
|
67
|
-
delete topResult.errors;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (outputFormat === VERBOSE || (outputFormat !== FLAG && !topResult.valid)) {
|
|
71
|
-
result.errors.unshift(...errors);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
resultStack[resultStack.length - 1] = result;
|
|
75
|
-
|
|
76
|
-
output[0] = result;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
|
|
81
39
|
const metaValidators = {};
|
|
82
40
|
subscribe("validate.metaValidate", async (_message, schema) => {
|
|
83
41
|
if (getShouldValidateSchema() && !schema.document.validated) {
|
|
@@ -91,7 +49,7 @@ subscribe("validate.metaValidate", async (_message, schema) => {
|
|
|
91
49
|
}
|
|
92
50
|
|
|
93
51
|
// Interpret
|
|
94
|
-
const schemaInstance = Instance.
|
|
52
|
+
const schemaInstance = Instance.fromJs(schema.document.root, schema.document.baseUri);
|
|
95
53
|
const metaResults = metaValidators[schema.document.dialectId](schemaInstance, getMetaSchemaOutputFormat());
|
|
96
54
|
if (!metaResults.valid) {
|
|
97
55
|
throw new InvalidSchemaError(metaResults);
|
package/lib/experimental.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Browser, Document } from "@hyperjump/browser";
|
|
2
2
|
import type { Validator, OutputUnit, OutputFormat, SchemaObject } from "./index.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { JsonNode } from "./instance.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// Compile/interpret
|
|
7
|
-
export const compile: (
|
|
7
|
+
export const compile: (schema: Browser<SchemaDocument>) => Promise<CompiledSchema>;
|
|
8
8
|
export const interpret: (
|
|
9
9
|
(compiledSchema: CompiledSchema, value: unknown, outputFormat?: OutputFormat) => OutputUnit
|
|
10
10
|
) & (
|
|
@@ -32,8 +32,6 @@ type Anchors = Record<string, string>;
|
|
|
32
32
|
|
|
33
33
|
// Output Formats
|
|
34
34
|
export const BASIC: "BASIC";
|
|
35
|
-
export const DETAILED: "DETAILED";
|
|
36
|
-
export const VERBOSE: "VERBOSE";
|
|
37
35
|
|
|
38
36
|
// Schema
|
|
39
37
|
export const getSchema: (uri: string, browser?: Browser) => Promise<Browser<SchemaDocument>>;
|
|
@@ -63,14 +61,15 @@ export const getKeywordByName: <A>(keywordName: string, dialectId: string) => Ke
|
|
|
63
61
|
export const getKeywordId: (keywordName: string, dialectId: string) => string;
|
|
64
62
|
export const defineVocabulary: (id: string, keywords: { [keyword: string]: string }) => void;
|
|
65
63
|
export const loadDialect: (dialectId: string, dialect: { [vocabularyId: string]: boolean }, allowUnknownKeywords?: boolean) => void;
|
|
64
|
+
export const unloadDialect: (dialectId: string) => void;
|
|
66
65
|
export const hasDialect: (dialectId: string) => boolean;
|
|
67
66
|
|
|
68
67
|
export type Keyword<A> = {
|
|
69
68
|
id: string;
|
|
70
69
|
compile: (schema: Browser<SchemaDocument>, ast: AST, parentSchema: Browser<SchemaDocument>) => Promise<A>;
|
|
71
|
-
interpret: (compiledKeywordValue: A, instance:
|
|
72
|
-
collectEvaluatedProperties?: (compiledKeywordValue: A, instance:
|
|
73
|
-
collectEvaluatedItems?: (compiledKeywordValue: A, instance:
|
|
70
|
+
interpret: (compiledKeywordValue: A, instance: JsonNode, ast: AST, dynamicAnchors: Anchors, quiet: boolean, schemaLocation: string) => boolean;
|
|
71
|
+
collectEvaluatedProperties?: (compiledKeywordValue: A, instance: JsonNode, ast: AST, dynamicAnchors: Anchors, isTop?: boolean) => Set<string> | false;
|
|
72
|
+
collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonNode, ast: AST, dynamicAnchors: Anchors, isTop?: boolean) => Set<number> | false;
|
|
74
73
|
collectExternalIds?: (visited: Set<string>, parentSchema: Browser<SchemaDocument>, schema: Browser<SchemaDocument>) => Promise<Set<string>>;
|
|
75
74
|
annotation?: <B>(compiledKeywordValue: A) => B;
|
|
76
75
|
};
|
package/lib/experimental.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export { compile, interpret, BASIC
|
|
2
|
-
export {
|
|
1
|
+
export { compile, interpret, BASIC } from "./core.js";
|
|
2
|
+
export {
|
|
3
|
+
addKeyword, getKeyword, getKeywordByName, getKeywordName, getKeywordId,
|
|
4
|
+
defineVocabulary,
|
|
5
|
+
loadDialect, unloadDialect, hasDialect
|
|
6
|
+
} from "./keywords.js";
|
|
3
7
|
export { getSchema, toSchema, canonicalUri, buildSchemaDocument } from "./schema.js";
|
|
4
8
|
export { default as Validation } from "./keywords/validation.js";
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { Json } from "@hyperjump/json-pointer";
|
|
2
|
+
|
|
3
|
+
|
|
1
4
|
export type SchemaFragment = string | number | boolean | null | SchemaObject | SchemaFragment[];
|
|
2
5
|
export type SchemaObject = {
|
|
3
6
|
[keyword: string]: SchemaFragment;
|
|
@@ -12,12 +15,12 @@ export const unregisterSchema: (retrievalUri: string) => void;
|
|
|
12
15
|
export const addSchema: typeof registerSchema;
|
|
13
16
|
|
|
14
17
|
export const validate: (
|
|
15
|
-
(url: string, value:
|
|
18
|
+
(url: string, value: Json, outputFormat?: OutputFormat) => Promise<OutputUnit>
|
|
16
19
|
) & (
|
|
17
20
|
(url: string) => Promise<Validator>
|
|
18
21
|
);
|
|
19
22
|
|
|
20
|
-
export type Validator = (value:
|
|
23
|
+
export type Validator = (value: Json, outputFormat?: OutputFormat) => OutputUnit;
|
|
21
24
|
|
|
22
25
|
export type OutputUnit = {
|
|
23
26
|
keyword: string;
|
package/lib/instance.d.ts
CHANGED
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { Json, JsonObject } from "@hyperjump/json-pointer";
|
|
1
|
+
import type { Json } from "@hyperjump/json-pointer";
|
|
3
2
|
|
|
4
3
|
|
|
5
|
-
export const
|
|
6
|
-
export const cons: (instance: Json, id?: string) => JsonDocument;
|
|
7
|
-
export const get: (url: string, context?: JsonDocument) => JsonDocument;
|
|
8
|
-
export const uri: (doc: JsonDocument) => string;
|
|
9
|
-
export const value: <A extends Json>(doc: JsonDocument<A>) => A;
|
|
10
|
-
export const has: (key: string, doc: JsonDocument<JsonObject>) => boolean;
|
|
11
|
-
export const typeOf: (doc: JsonDocument) => JsonType;
|
|
12
|
-
export const step: (key: string, doc: JsonDocument<JsonObject | Json[]>) => JsonDocument<typeof doc.value>;
|
|
13
|
-
export const iter: (doc: JsonDocument<JsonObject>) => Generator<JsonDocument>;
|
|
14
|
-
export const keys: (doc: JsonDocument<JsonObject>) => Generator<string>;
|
|
15
|
-
export const values: (doc: JsonDocument<JsonObject>) => Generator<JsonDocument>;
|
|
16
|
-
export const entries: (doc: JsonDocument<JsonObject>) => Generator<[string, JsonDocument]>;
|
|
17
|
-
export const length: (doc: JsonDocument<Json[] | string>) => number;
|
|
4
|
+
export const fromJs: (value: Json, uri?: string) => JsonNode;
|
|
18
5
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
6
|
+
export const get: (url: string, context: JsonNode) => JsonNode | undefined;
|
|
7
|
+
export const uri: (node: JsonNode) => string;
|
|
8
|
+
export const value: <A>(node: JsonNode) => A;
|
|
9
|
+
export const has: (key: string, node: JsonNode) => boolean;
|
|
10
|
+
export const typeOf: (node: JsonNode) => JsonType;
|
|
11
|
+
export const step: (key: string, node: JsonNode) => JsonNode;
|
|
12
|
+
export const iter: (node: JsonNode) => Generator<JsonNode>;
|
|
13
|
+
export const keys: (node: JsonNode) => Generator<JsonNode>;
|
|
14
|
+
export const values: (node: JsonNode) => Generator<JsonNode>;
|
|
15
|
+
export const entries: (node: JsonNode) => Generator<[JsonNode, JsonNode]>;
|
|
16
|
+
export const length: (node: JsonNode) => number;
|
|
23
17
|
|
|
24
|
-
export
|
|
25
|
-
|
|
18
|
+
export const allNodes: (node) => Generator<JsonNode>;
|
|
19
|
+
|
|
20
|
+
export type JsonNode = {
|
|
21
|
+
baseUri: string;
|
|
26
22
|
pointer: string;
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
type: JsonNodeType;
|
|
24
|
+
children: JsonNode[];
|
|
25
|
+
parent: JsonNode;
|
|
26
|
+
root: JsonNode;
|
|
27
|
+
valid: boolean;
|
|
29
28
|
};
|
|
29
|
+
|
|
30
|
+
type JsonNodeType = "object" | "array" | "string" | "number" | "boolean" | "null" | "property";
|
package/lib/instance.js
CHANGED
|
@@ -1,63 +1,158 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as JsonPointer from "@hyperjump/json-pointer";
|
|
2
|
+
import { reduce } from "@hyperjump/pact";
|
|
2
3
|
import { toAbsoluteIri } from "@hyperjump/uri";
|
|
3
|
-
import { jsonTypeOf, uriFragment } from "./common.js";
|
|
4
4
|
import { Reference } from "@hyperjump/browser/jref";
|
|
5
|
+
import { toAbsoluteUri, uriFragment } from "./common.js";
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
export const
|
|
8
|
-
|
|
9
|
-
...nil,
|
|
10
|
-
id: id ? toAbsoluteIri(id) : "",
|
|
11
|
-
instance,
|
|
12
|
-
value: instance
|
|
13
|
-
});
|
|
8
|
+
export const fromJs = (value, uri = "", pointer = "", parent = undefined) => {
|
|
9
|
+
const jsType = typeof value;
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
switch (jsType) {
|
|
12
|
+
case "number":
|
|
13
|
+
case "string":
|
|
14
|
+
case "boolean":
|
|
15
|
+
return cons(uri, pointer, value, jsType, [], parent);
|
|
16
|
+
case "object":
|
|
17
|
+
if (value === null) {
|
|
18
|
+
return cons(uri, pointer, value, "null", [], parent);
|
|
19
|
+
} else if (Array.isArray(value)) {
|
|
20
|
+
const arrayNode = cons(uri, pointer, value, "array", [], parent);
|
|
21
|
+
arrayNode.children = value.map((item, index) => {
|
|
22
|
+
return fromJs(item, uri, JsonPointer.append(index, pointer), arrayNode);
|
|
23
|
+
});
|
|
24
|
+
return arrayNode;
|
|
25
|
+
} else if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
26
|
+
const objectNode = cons(uri, pointer, value, "object", [], parent);
|
|
27
|
+
objectNode.children = Object.entries(value).map((entry) => {
|
|
28
|
+
const propertyPointer = JsonPointer.append(entry[0], pointer);
|
|
29
|
+
const propertyNode = cons(uri, propertyPointer, undefined, "property", [], objectNode);
|
|
30
|
+
propertyNode.children = entry.map((property) => fromJs(property, uri, propertyPointer, propertyNode));
|
|
31
|
+
return propertyNode;
|
|
32
|
+
});
|
|
33
|
+
return objectNode;
|
|
34
|
+
} else if (value instanceof Reference) {
|
|
35
|
+
return fromJs(value.toJSON(), uri, pointer, parent);
|
|
36
|
+
}
|
|
37
|
+
default:
|
|
38
|
+
const type = jsType === "object" ? Object.getPrototypeOf(value).constructor.name || "anonymous" : jsType;
|
|
39
|
+
throw Error(`Not a JSON compatible type: ${type}`);
|
|
18
40
|
}
|
|
41
|
+
};
|
|
19
42
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
43
|
+
const cons = (baseUri, pointer, value, type, children, parent) => {
|
|
44
|
+
const node = {
|
|
45
|
+
baseUri: baseUri ? toAbsoluteIri(baseUri) : "",
|
|
23
46
|
pointer: pointer,
|
|
24
|
-
value:
|
|
47
|
+
value: value,
|
|
48
|
+
type: type,
|
|
49
|
+
children: children,
|
|
50
|
+
parent: parent,
|
|
51
|
+
valid: true,
|
|
52
|
+
errors: {},
|
|
53
|
+
annotations: {}
|
|
25
54
|
};
|
|
55
|
+
node.root = parent?.root ?? node;
|
|
56
|
+
|
|
57
|
+
return node;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const get = (uri, instance) => {
|
|
61
|
+
const schemaId = toAbsoluteUri(uri);
|
|
62
|
+
if (schemaId !== instance.baseUri && schemaId !== "") {
|
|
63
|
+
throw Error(`Reference '${uri}' is not local to '${instance.baseUri}'`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const pointer = uriFragment(uri);
|
|
67
|
+
return reduce((node, segment) => {
|
|
68
|
+
segment = segment === "-" && typeOf(node) === "array" ? length(node) : segment;
|
|
69
|
+
return step(segment, node);
|
|
70
|
+
}, instance.root, JsonPointer.pointerSegments(pointer));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const uri = (node) => `${node.baseUri}#${encodeURI(node.pointer)}`;
|
|
74
|
+
export const value = (node) => node.value;
|
|
75
|
+
export const typeOf = (node) => node.type;
|
|
76
|
+
export const has = (key, node) => key in node.value;
|
|
77
|
+
|
|
78
|
+
export const step = (key, node) => {
|
|
79
|
+
if (node.type !== "object" && node.type !== "array") {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
switch (node.type) {
|
|
84
|
+
case "object":
|
|
85
|
+
const property = node.children.find((propertyNode) => {
|
|
86
|
+
return value(propertyNode.children[0]) === key;
|
|
87
|
+
});
|
|
88
|
+
return property?.children[1];
|
|
89
|
+
case "array":
|
|
90
|
+
const index = parseInt(key, 10);
|
|
91
|
+
return node.children[index];
|
|
92
|
+
default:
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
26
95
|
};
|
|
27
96
|
|
|
28
|
-
export const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
97
|
+
export const iter = function* (node) {
|
|
98
|
+
if (node.type !== "array") {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
yield* node.children;
|
|
103
|
+
};
|
|
32
104
|
|
|
33
|
-
export const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
105
|
+
export const keys = function* (node) {
|
|
106
|
+
if (node.type !== "object") {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
38
109
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
yield step(index, doc);
|
|
110
|
+
for (const property of node.children) {
|
|
111
|
+
yield property.children[0];
|
|
42
112
|
}
|
|
43
113
|
};
|
|
44
114
|
|
|
45
|
-
export const
|
|
46
|
-
|
|
47
|
-
|
|
115
|
+
export const values = function* (node) {
|
|
116
|
+
if (node.type !== "object") {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const property of node.children) {
|
|
121
|
+
yield property.children[1];
|
|
48
122
|
}
|
|
49
123
|
};
|
|
50
124
|
|
|
51
|
-
export const
|
|
52
|
-
|
|
53
|
-
|
|
125
|
+
export const entries = function* (node) {
|
|
126
|
+
if (node.type !== "object") {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
for (const property of node.children) {
|
|
131
|
+
yield property.children;
|
|
54
132
|
}
|
|
55
133
|
};
|
|
56
134
|
|
|
57
|
-
export const
|
|
58
|
-
|
|
59
|
-
|
|
135
|
+
export const length = (node) => {
|
|
136
|
+
if (node.type !== "array") {
|
|
137
|
+
return;
|
|
60
138
|
}
|
|
139
|
+
|
|
140
|
+
return node.children.length;
|
|
61
141
|
};
|
|
62
142
|
|
|
63
|
-
export const
|
|
143
|
+
export const allNodes = function* (node) {
|
|
144
|
+
yield node;
|
|
145
|
+
|
|
146
|
+
switch (typeOf(node)) {
|
|
147
|
+
case "object":
|
|
148
|
+
for (const child of values(node)) {
|
|
149
|
+
yield* allNodes(child);
|
|
150
|
+
}
|
|
151
|
+
break;
|
|
152
|
+
case "array":
|
|
153
|
+
for (const child of iter(node)) {
|
|
154
|
+
yield* allNodes(child);
|
|
155
|
+
}
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concat, join, empty, map,
|
|
1
|
+
import { concat, join, empty, map, pipe } from "@hyperjump/pact";
|
|
2
2
|
import * as Browser from "@hyperjump/browser";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
4
|
import { getKeywordName, Validation } from "../experimental.js";
|
|
@@ -36,11 +36,15 @@ const interpret = ([isDefinedProperty, additionalProperties], instance, ast, dyn
|
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
let isValid = true;
|
|
40
|
+
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
41
|
+
const propertyName = Instance.value(propertyNameNode);
|
|
42
|
+
if (!isDefinedProperty.test(propertyName) && !Validation.interpret(additionalProperties, property, ast, dynamicAnchors, quiet)) {
|
|
43
|
+
isValid = false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return isValid;
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
const collectEvaluatedProperties = ([isDefinedProperty, additionalProperties], instance, ast, dynamicAnchors) => {
|
|
@@ -49,7 +53,8 @@ const collectEvaluatedProperties = ([isDefinedProperty, additionalProperties], i
|
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
const evaluatedPropertyNames = new Set();
|
|
52
|
-
for (const [
|
|
56
|
+
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
57
|
+
const propertyName = Instance.value(propertyNameNode);
|
|
53
58
|
if (!isDefinedProperty.test(propertyName)) {
|
|
54
59
|
if (!Validation.interpret(additionalProperties, property, ast, dynamicAnchors, true)) {
|
|
55
60
|
return false;
|
package/lib/keywords/allOf.js
CHANGED
|
@@ -12,7 +12,13 @@ const compile = (schema, ast) => pipe(
|
|
|
12
12
|
);
|
|
13
13
|
|
|
14
14
|
const interpret = (allOf, instance, ast, dynamicAnchors, quiet) => {
|
|
15
|
-
|
|
15
|
+
let isValid = true;
|
|
16
|
+
for (const schemaUri of allOf) {
|
|
17
|
+
if (!Validation.interpret(schemaUri, instance, ast, dynamicAnchors, quiet)) {
|
|
18
|
+
isValid = false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return isValid;
|
|
16
22
|
};
|
|
17
23
|
|
|
18
24
|
const collectEvaluatedProperties = (allOf, instance, ast, dynamicAnchors) => {
|
package/lib/keywords/comment.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
const id = "https://json-schema.org/keyword/comment";
|
|
2
|
+
const compile = () => undefined;
|
|
3
|
+
const interpret = () => true;
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
export default { id: "https://json-schema.org/keyword/comment", ...metaData };
|
|
5
|
+
export default { id, compile, interpret };
|
package/lib/keywords/const.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
|
+
import * as Instance from "../../annotations/annotated-instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const id = "https://json-schema.org/keyword/contentEncoding";
|
|
6
|
+
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
|
|
9
|
+
const interpret = (contentEncoding, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
|
|
10
|
+
Instance.setAnnotation(instance, id, schemaLocation, contentEncoding);
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default { id, compile, interpret };
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
|
+
import * as Instance from "../../annotations/annotated-instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const id = "https://json-schema.org/keyword/contentMediaType";
|
|
6
|
+
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
|
|
9
|
+
const interpret = (contentMediaType, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
|
|
10
|
+
Instance.setAnnotation(instance, id, schemaLocation, contentMediaType);
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default { id, compile, interpret };
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { canonicalUri } from "../schema.js";
|
|
2
|
+
import * as Instance from "../../annotations/annotated-instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
const id = "https://json-schema.org/keyword/contentSchema";
|
|
5
6
|
|
|
6
|
-
const compile = (contentSchema) =>
|
|
7
|
-
|
|
7
|
+
const compile = (contentSchema) => canonicalUri(contentSchema);
|
|
8
|
+
|
|
9
|
+
const interpret = (contentSchema, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
|
|
10
|
+
Instance.setAnnotation(instance, id, schemaLocation, contentSchema);
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
8
13
|
|
|
9
14
|
export default { id, compile, interpret };
|
package/lib/keywords/default.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
|
+
import * as Instance from "../../annotations/annotated-instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const id = "https://json-schema.org/keyword/default";
|
|
6
|
+
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
|
|
9
|
+
const interpret = (value, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
|
|
10
|
+
Instance.setAnnotation(instance, id, schemaLocation, value);
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default { id, compile, interpret };
|
|
@@ -12,9 +12,18 @@ const compile = (schema) => pipe(
|
|
|
12
12
|
);
|
|
13
13
|
|
|
14
14
|
const interpret = (dependentRequired, instance) => {
|
|
15
|
-
|
|
16
|
-
return
|
|
17
|
-
}
|
|
15
|
+
if (Instance.typeOf(instance) !== "object") {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let isValid = true;
|
|
20
|
+
for (const [propertyName, required] of dependentRequired) {
|
|
21
|
+
if (Instance.has(propertyName, instance) && !required.every((key) => Instance.has(key, instance))) {
|
|
22
|
+
isValid = false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return isValid;
|
|
18
27
|
};
|
|
19
28
|
|
|
20
29
|
export default { id, compile, interpret };
|
|
@@ -13,9 +13,18 @@ const compile = (schema, ast) => pipe(
|
|
|
13
13
|
);
|
|
14
14
|
|
|
15
15
|
const interpret = (dependentSchemas, instance, ast, dynamicAnchors, quiet) => {
|
|
16
|
-
|
|
17
|
-
return
|
|
18
|
-
}
|
|
16
|
+
if (Instance.typeOf(instance) !== "object") {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let isValid = true;
|
|
21
|
+
for (const [propertyName, dependentSchema] of dependentSchemas) {
|
|
22
|
+
if (Instance.has(propertyName, instance) && !Validation.interpret(dependentSchema, instance, ast, dynamicAnchors, quiet)) {
|
|
23
|
+
isValid = false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return isValid;
|
|
19
28
|
};
|
|
20
29
|
|
|
21
30
|
const collectEvaluatedProperties = (dependentSchemas, instance, ast, dynamicAnchors) => {
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
|
+
import * as Instance from "../../annotations/annotated-instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const id = "https://json-schema.org/keyword/deprecated";
|
|
6
|
+
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
|
|
9
|
+
const interpret = (deprecated, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
|
|
10
|
+
Instance.setAnnotation(instance, id, schemaLocation, deprecated);
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default { id, compile, interpret };
|
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
|
+
import * as Instance from "../../annotations/annotated-instance.js";
|
|
2
3
|
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const id = "https://json-schema.org/keyword/description";
|
|
6
|
+
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
|
|
9
|
+
const interpret = (description, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
|
|
10
|
+
Instance.setAnnotation(instance, id, schemaLocation, description);
|
|
11
|
+
return true;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default { id, compile, interpret };
|