@hyperjump/json-schema 1.6.7 → 1.7.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 +247 -255
- package/annotations/annotated-instance.js +3 -3
- package/annotations/index.d.ts +7 -1
- package/annotations/index.js +3 -3
- package/bundle/index.d.ts +1 -5
- package/bundle/index.js +112 -156
- package/draft-04/additionalItems.js +6 -7
- package/draft-04/dependencies.js +5 -5
- package/draft-04/index.js +2 -2
- package/draft-04/items.js +5 -5
- package/draft-04/maximum.js +8 -8
- package/draft-04/minimum.js +8 -8
- package/draft-06/contains.js +2 -2
- package/draft-06/index.js +3 -2
- package/draft-07/index.js +3 -2
- package/draft-2019-09/index.js +9 -11
- package/draft-2020-12/dynamicRef.js +5 -5
- package/draft-2020-12/index.js +11 -13
- package/lib/common.d.ts +1 -1
- package/lib/common.js +44 -60
- package/lib/configuration.js +0 -6
- package/lib/core.js +32 -30
- package/lib/experimental.d.ts +75 -5
- package/lib/experimental.js +2 -2
- package/lib/index.d.ts +43 -11
- package/lib/index.js +11 -11
- package/lib/instance.d.ts +1 -17
- package/lib/instance.js +3 -3
- package/lib/keywords/additionalProperties.js +12 -13
- package/lib/keywords/allOf.js +3 -3
- package/lib/keywords/anyOf.js +3 -3
- package/lib/keywords/conditional.js +6 -7
- package/lib/keywords/const.js +2 -2
- package/lib/keywords/contains.js +14 -35
- package/lib/keywords/contentSchema.js +1 -1
- package/lib/keywords/definitions.js +2 -2
- package/lib/keywords/dependentRequired.js +4 -4
- package/lib/keywords/dependentSchemas.js +5 -5
- package/lib/keywords/dynamicRef.js +10 -5
- package/lib/keywords/else.js +5 -6
- package/lib/keywords/enum.js +4 -4
- package/lib/keywords/exclusiveMaximum.js +3 -3
- package/lib/keywords/exclusiveMinimum.js +3 -3
- package/lib/keywords/if.js +1 -1
- package/lib/keywords/itemPattern.js +17 -14
- package/lib/keywords/items.js +6 -7
- package/lib/keywords/maxItems.js +3 -3
- package/lib/keywords/maxLength.js +3 -3
- package/lib/keywords/maxProperties.js +3 -3
- package/lib/keywords/maximum.js +3 -3
- package/lib/keywords/meta-data.js +1 -1
- package/lib/keywords/minItems.js +3 -3
- package/lib/keywords/minLength.js +3 -3
- package/lib/keywords/minProperties.js +3 -3
- package/lib/keywords/minimum.js +3 -3
- package/lib/keywords/multipleOf.js +3 -3
- package/lib/keywords/not.js +1 -1
- package/lib/keywords/oneOf.js +3 -3
- package/lib/keywords/pattern.js +3 -3
- package/lib/keywords/patternProperties.js +5 -5
- package/lib/keywords/prefixItems.js +5 -5
- package/lib/keywords/properties.js +5 -5
- package/lib/keywords/propertyDependencies.js +6 -7
- package/lib/keywords/propertyNames.js +2 -2
- package/lib/keywords/ref.js +2 -7
- package/lib/keywords/requireAllExcept.js +8 -9
- package/lib/keywords/required.js +3 -3
- package/lib/keywords/then.js +5 -5
- package/lib/keywords/type.js +9 -3
- package/lib/keywords/unevaluatedItems.js +4 -4
- package/lib/keywords/unevaluatedProperties.js +4 -5
- package/lib/keywords/uniqueItems.js +3 -3
- package/lib/keywords/validation.js +11 -23
- package/lib/keywords.js +27 -14
- package/lib/openapi.js +19 -6
- package/lib/schema.js +236 -227
- package/openapi-3-0/index.js +5 -5
- package/openapi-3-0/type.js +13 -7
- package/openapi-3-1/index.js +22 -21
- package/openapi-3-1/{schema-base/2022-10-07.js → schema-base.js} +12 -2
- package/openapi-3-1/schema-draft-04.js +33 -0
- package/openapi-3-1/schema-draft-06.js +33 -0
- package/openapi-3-1/schema-draft-07.js +33 -0
- package/openapi-3-1/schema-draft-2019-09.js +33 -0
- package/openapi-3-1/schema-draft-2020-12.js +33 -0
- package/package.json +11 -11
- package/stable/index.js +10 -10
- package/annotations/validation-error.d.ts +0 -8
- package/draft-2019-09/contains.js +0 -44
- package/lib/configuration.d.ts +0 -9
- package/lib/context-uri.browser.js +0 -1
- package/lib/context-uri.js +0 -4
- package/lib/core.d.ts +0 -48
- package/lib/fetch.browser.js +0 -1
- package/lib/fetch.js +0 -20
- package/lib/invalid-schema-error.d.ts +0 -8
- package/lib/keywords.d.ts +0 -19
- package/lib/media-types.d.ts +0 -11
- package/lib/media-types.js +0 -48
- package/lib/reference.d.ts +0 -11
- package/lib/reference.js +0 -11
- package/lib/schema.d.ts +0 -60
- /package/openapi-3-0/{schema/2021-09-28.js → schema.js} +0 -0
- /package/openapi-3-1/{schema/2022-10-07.js → schema.js} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/minProperties";
|
|
6
6
|
|
|
7
|
-
const compile = (schema) =>
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
8
|
const interpret = (minProperties, instance) => {
|
|
9
|
-
return
|
|
9
|
+
return Instance.typeOf(instance) !== "object" || [...Instance.keys(instance)].length >= minProperties;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
export default { id, compile, interpret };
|
package/lib/keywords/minimum.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/minimum";
|
|
6
6
|
|
|
7
|
-
const compile = (schema) =>
|
|
8
|
-
const interpret = (minimum, instance) =>
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
const interpret = (minimum, instance) => Instance.typeOf(instance) !== "number" || Instance.value(instance) >= minimum;
|
|
9
9
|
|
|
10
10
|
export default { id, compile, interpret };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/multipleOf";
|
|
6
6
|
|
|
7
|
-
const compile = (schema) =>
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
8
|
|
|
9
9
|
const interpret = (multipleOf, instance) => {
|
|
10
|
-
if (
|
|
10
|
+
if (Instance.typeOf(instance) !== "number") {
|
|
11
11
|
return true;
|
|
12
12
|
}
|
|
13
13
|
|
package/lib/keywords/not.js
CHANGED
package/lib/keywords/oneOf.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { pipe, asyncMap, asyncCollectArray } from "@hyperjump/pact";
|
|
2
|
-
import * as
|
|
3
|
-
import Validation from "
|
|
2
|
+
import * as Browser from "@hyperjump/browser";
|
|
3
|
+
import { Validation } from "../experimental.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const id = "https://json-schema.org/keyword/oneOf";
|
|
7
7
|
|
|
8
8
|
const compile = (schema, ast) => pipe(
|
|
9
|
-
|
|
9
|
+
Browser.iter(schema),
|
|
10
10
|
asyncMap((itemSchema) => Validation.compile(itemSchema, ast)),
|
|
11
11
|
asyncCollectArray
|
|
12
12
|
);
|
package/lib/keywords/pattern.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/pattern";
|
|
6
6
|
|
|
7
|
-
const compile = (schema) => new RegExp(
|
|
8
|
-
const interpret = (pattern, instance) =>
|
|
7
|
+
const compile = (schema) => new RegExp(Browser.value(schema), "u");
|
|
8
|
+
const interpret = (pattern, instance) => Instance.typeOf(instance) !== "string" || pattern.test(Instance.value(instance));
|
|
9
9
|
|
|
10
10
|
export default { id, compile, interpret };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { pipe, asyncMap, asyncCollectArray, filter, every } from "@hyperjump/pact";
|
|
2
|
-
import * as
|
|
2
|
+
import * as Browser from "@hyperjump/browser";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
|
-
import Validation from "
|
|
4
|
+
import { Validation } from "../experimental.js";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const id = "https://json-schema.org/keyword/patternProperties";
|
|
8
8
|
|
|
9
9
|
const compile = (schema, ast) => pipe(
|
|
10
|
-
|
|
10
|
+
Browser.entries(schema),
|
|
11
11
|
asyncMap(async ([pattern, propertySchema]) => [
|
|
12
12
|
new RegExp(pattern, "u"),
|
|
13
13
|
await Validation.compile(propertySchema, ast)
|
|
@@ -16,7 +16,7 @@ const compile = (schema, ast) => pipe(
|
|
|
16
16
|
);
|
|
17
17
|
|
|
18
18
|
const interpret = (patternProperties, instance, ast, dynamicAnchors, quiet) => {
|
|
19
|
-
return
|
|
19
|
+
return Instance.typeOf(instance) !== "object" || patternProperties.every(([pattern, schemaUrl]) => {
|
|
20
20
|
return pipe(
|
|
21
21
|
Instance.entries(instance),
|
|
22
22
|
filter(([propertyName]) => pattern.test(propertyName)),
|
|
@@ -26,7 +26,7 @@ const interpret = (patternProperties, instance, ast, dynamicAnchors, quiet) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
const collectEvaluatedProperties = (patternProperties, instance, ast, dynamicAnchors) => {
|
|
29
|
-
if (
|
|
29
|
+
if (Instance.typeOf(instance) !== "object") {
|
|
30
30
|
return false;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { pipe, asyncMap, asyncCollectArray, every, zip, take } from "@hyperjump/pact";
|
|
2
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
3
|
import * as Instance from "../instance.js";
|
|
3
|
-
import
|
|
4
|
-
import Validation from "./validation.js";
|
|
4
|
+
import { Validation } from "../experimental.js";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const id = "https://json-schema.org/keyword/prefixItems";
|
|
8
8
|
|
|
9
9
|
const compile = (schema, ast) => pipe(
|
|
10
|
-
|
|
10
|
+
Browser.iter(schema),
|
|
11
11
|
asyncMap((itemSchema) => Validation.compile(itemSchema, ast)),
|
|
12
12
|
asyncCollectArray
|
|
13
13
|
);
|
|
14
14
|
|
|
15
15
|
const interpret = (prefixItems, instance, ast, dynamicAnchors, quiet) => {
|
|
16
|
-
return
|
|
16
|
+
return Instance.typeOf(instance) !== "array" || pipe(
|
|
17
17
|
zip(prefixItems, Instance.iter(instance)),
|
|
18
18
|
take(Instance.length(instance)),
|
|
19
19
|
every(([prefixItem, item]) => Validation.interpret(prefixItem, item, ast, dynamicAnchors, quiet))
|
|
@@ -21,7 +21,7 @@ const interpret = (prefixItems, instance, ast, dynamicAnchors, quiet) => {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const collectEvaluatedItems = (items, instance, ast, dynamicAnchors) => {
|
|
24
|
-
return interpret(items, instance, ast, dynamicAnchors, true) && new Set(items.map((
|
|
24
|
+
return interpret(items, instance, ast, dynamicAnchors, true) && new Set(items.map((_item, ndx) => ndx));
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export default { id, compile, interpret, collectEvaluatedItems };
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { pipe, asyncMap, asyncCollectObject, filter, every } from "@hyperjump/pact";
|
|
2
|
-
import * as
|
|
2
|
+
import * as Browser from "@hyperjump/browser";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
|
-
import Validation from "
|
|
4
|
+
import { Validation } from "../experimental.js";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const id = "https://json-schema.org/keyword/properties";
|
|
8
8
|
|
|
9
9
|
const compile = (schema, ast) => pipe(
|
|
10
|
-
|
|
10
|
+
Browser.entries(schema),
|
|
11
11
|
asyncMap(async ([propertyName, propertySchema]) => [propertyName, await Validation.compile(propertySchema, ast)]),
|
|
12
12
|
asyncCollectObject
|
|
13
13
|
);
|
|
14
14
|
|
|
15
15
|
const interpret = (properties, instance, ast, dynamicAnchors, quiet) => {
|
|
16
|
-
return
|
|
16
|
+
return Instance.typeOf(instance) !== "object" || pipe(
|
|
17
17
|
Instance.entries(instance),
|
|
18
18
|
filter(([propertyName]) => propertyName in properties),
|
|
19
19
|
every(([propertyName, property]) => Validation.interpret(properties[propertyName], property, ast, dynamicAnchors, quiet))
|
|
@@ -21,7 +21,7 @@ const interpret = (properties, instance, ast, dynamicAnchors, quiet) => {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const collectEvaluatedProperties = (properties, instance, ast, dynamicAnchors) => {
|
|
24
|
-
if (
|
|
24
|
+
if (Instance.typeOf(instance) !== "object") {
|
|
25
25
|
return false;
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { pipe, asyncMap, asyncCollectObject } from "@hyperjump/pact";
|
|
2
|
-
import * as
|
|
2
|
+
import * as Browser from "@hyperjump/browser";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
|
-
import Validation from "
|
|
4
|
+
import { Validation } from "../experimental.js";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const id = "https://json-schema.org/keyword/propertyDependencies";
|
|
8
|
-
const experimental = true;
|
|
9
8
|
|
|
10
9
|
const compile = (schema, ast) => {
|
|
11
10
|
return pipe(
|
|
12
|
-
|
|
11
|
+
Browser.entries(schema),
|
|
13
12
|
asyncMap(async ([propertyName, valueMappings]) => {
|
|
14
13
|
return [propertyName, await pipe(
|
|
15
|
-
|
|
14
|
+
Browser.entries(valueMappings),
|
|
16
15
|
asyncMap(async ([propertyValue, conditionalSchema]) => [propertyValue, await Validation.compile(conditionalSchema, ast)]),
|
|
17
16
|
asyncCollectObject
|
|
18
17
|
)];
|
|
@@ -22,7 +21,7 @@ const compile = (schema, ast) => {
|
|
|
22
21
|
};
|
|
23
22
|
|
|
24
23
|
const interpret = (propertyDependencies, instance, ast, dynamicAnchors, quiet) => {
|
|
25
|
-
return
|
|
24
|
+
return Instance.typeOf(instance) !== "object" || Object.entries(propertyDependencies).every(([propertyName, valueMappings]) => {
|
|
26
25
|
const propertyValue = Instance.value(instance)[propertyName];
|
|
27
26
|
return !Instance.has(propertyName, instance)
|
|
28
27
|
|| !(propertyValue in valueMappings)
|
|
@@ -44,4 +43,4 @@ const collectEvaluatedProperties = (propertyDependencies, instance, ast, dynamic
|
|
|
44
43
|
}, []);
|
|
45
44
|
};
|
|
46
45
|
|
|
47
|
-
export default { id,
|
|
46
|
+
export default { id, compile, interpret, collectEvaluatedProperties };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { every } from "@hyperjump/pact";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
|
-
import Validation from "
|
|
3
|
+
import { Validation } from "../experimental.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const id = "https://json-schema.org/keyword/propertyNames";
|
|
@@ -8,7 +8,7 @@ const id = "https://json-schema.org/keyword/propertyNames";
|
|
|
8
8
|
const compile = (schema, ast) => Validation.compile(schema, ast);
|
|
9
9
|
|
|
10
10
|
const interpret = (propertyNames, instance, ast, dynamicAnchors) => {
|
|
11
|
-
return
|
|
11
|
+
return Instance.typeOf(instance) !== "object" || every((key) => {
|
|
12
12
|
return Validation.interpret(propertyNames, Instance.cons(key), ast, dynamicAnchors, true);
|
|
13
13
|
}, Instance.keys(instance));
|
|
14
14
|
};
|
package/lib/keywords/ref.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Validation from "./validation.js";
|
|
1
|
+
import { Validation } from "../experimental.js";
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
const id = "https://json-schema.org/keyword/ref";
|
|
6
5
|
|
|
7
|
-
const compile =
|
|
8
|
-
const referencedSchema = await Schema.get(Schema.value(ref), ref);
|
|
9
|
-
return Validation.compile(referencedSchema, ast);
|
|
10
|
-
};
|
|
11
|
-
|
|
6
|
+
const compile = Validation.compile;
|
|
12
7
|
const interpret = Validation.interpret;
|
|
13
8
|
const collectEvaluatedProperties = Validation.collectEvaluatedProperties;
|
|
14
9
|
const collectEvaluatedItems = Validation.collectEvaluatedItems;
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
1
2
|
import * as Instance from "../instance.js";
|
|
2
|
-
import { getKeywordName } from "../
|
|
3
|
-
import * as Schema from "../schema.js";
|
|
3
|
+
import { getKeywordName } from "../experimental.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const id = "https://json-schema.org/keyword/requireAllExcept";
|
|
7
|
-
const experimental = true;
|
|
8
7
|
|
|
9
|
-
const compile = async (schema,
|
|
10
|
-
const requireAllExcept = await
|
|
8
|
+
const compile = async (schema, _ast, parentSchema) => {
|
|
9
|
+
const requireAllExcept = await Browser.value(schema);
|
|
11
10
|
const propertiesKeyword = getKeywordName(schema.dialectId, "https://json-schema.org/keyword/properties");
|
|
12
|
-
const propertiesSchema = await
|
|
13
|
-
const propertyNames =
|
|
11
|
+
const propertiesSchema = await Browser.step(propertiesKeyword, parentSchema);
|
|
12
|
+
const propertyNames = Browser.typeOf(propertiesSchema) === "object" ? Browser.keys(propertiesSchema) : [];
|
|
14
13
|
|
|
15
14
|
const required = new Set(propertyNames);
|
|
16
15
|
requireAllExcept.forEach((propertyName) => propertyNames.remove(propertyName));
|
|
@@ -18,7 +17,7 @@ const compile = async (schema, ast, parentSchema) => {
|
|
|
18
17
|
};
|
|
19
18
|
|
|
20
19
|
const interpret = (required, instance) => {
|
|
21
|
-
return
|
|
20
|
+
return Instance.typeOf(instance) !== "object" || required.every((propertyName) => Object.hasOwn(Instance.value(instance), propertyName));
|
|
22
21
|
};
|
|
23
22
|
|
|
24
|
-
export default { id,
|
|
23
|
+
export default { id, compile, interpret };
|
package/lib/keywords/required.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/required";
|
|
6
6
|
|
|
7
|
-
const compile = (schema) =>
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
8
|
|
|
9
9
|
const interpret = (required, instance) => {
|
|
10
|
-
return
|
|
10
|
+
return Instance.typeOf(instance) !== "object" || required.every((propertyName) => Object.hasOwn(Instance.value(instance), propertyName));
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
export default { id, compile, interpret };
|
package/lib/keywords/then.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import { getKeywordName } from "../keywords.js";
|
|
3
|
-
import Validation from "
|
|
3
|
+
import { Validation } from "../experimental.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const id = "https://json-schema.org/keyword/then";
|
|
7
7
|
|
|
8
8
|
const compile = async (schema, ast, parentSchema) => {
|
|
9
|
-
const ifKeyword = getKeywordName(schema.dialectId, "https://json-schema.org/keyword/if");
|
|
10
|
-
if (
|
|
11
|
-
const ifSchema = await
|
|
9
|
+
const ifKeyword = getKeywordName(schema.document.dialectId, "https://json-schema.org/keyword/if");
|
|
10
|
+
if (Browser.has(ifKeyword, parentSchema)) {
|
|
11
|
+
const ifSchema = await Browser.step(ifKeyword, parentSchema);
|
|
12
12
|
return [await Validation.compile(ifSchema, ast), await Validation.compile(schema, ast)];
|
|
13
13
|
} else {
|
|
14
14
|
return [];
|
package/lib/keywords/type.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as Browser from "@hyperjump/browser";
|
|
2
2
|
import * as Instance from "../instance.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const id = "https://json-schema.org/keyword/type";
|
|
6
6
|
|
|
7
|
-
const compile = (schema) =>
|
|
8
|
-
const interpret = (type, instance) => typeof type === "string"
|
|
7
|
+
const compile = (schema) => Browser.value(schema);
|
|
8
|
+
const interpret = (type, instance) => typeof type === "string"
|
|
9
|
+
? isTypeOf(instance)(type)
|
|
10
|
+
: type.some(isTypeOf(instance));
|
|
11
|
+
|
|
12
|
+
const isTypeOf = (instance) => (type) => type === "integer"
|
|
13
|
+
? Instance.typeOf(instance) === "number" && Number.isInteger(Instance.value(instance))
|
|
14
|
+
: Instance.typeOf(instance) === type;
|
|
9
15
|
|
|
10
16
|
export default { id, compile, interpret };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { pipe, filter, every, zip, range } from "@hyperjump/pact";
|
|
2
|
-
import
|
|
2
|
+
import { canonicalUri } from "../schema.js";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
|
-
import Validation from "
|
|
4
|
+
import { Validation } from "../experimental.js";
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
const id = "https://json-schema.org/keyword/unevaluatedItems";
|
|
8
8
|
|
|
9
9
|
const compile = async (schema, ast, parentSchema) => {
|
|
10
|
-
return [
|
|
10
|
+
return [canonicalUri(parentSchema), await Validation.compile(schema, ast)];
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
const interpret = ([schemaUrl, unevaluatedItems], instance, ast, dynamicAnchors, quiet) => {
|
|
14
|
-
if (
|
|
14
|
+
if (Instance.typeOf(instance) !== "array") {
|
|
15
15
|
return true;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { pipe, filter, every } from "@hyperjump/pact";
|
|
2
|
-
import * as Schema from "../schema.js";
|
|
3
2
|
import * as Instance from "../instance.js";
|
|
4
|
-
import Validation from "
|
|
3
|
+
import { Validation, canonicalUri } from "../experimental.js";
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
const id = "https://json-schema.org/keyword/unevaluatedProperties";
|
|
8
7
|
|
|
9
8
|
const compile = async (schema, ast, parentSchema) => {
|
|
10
|
-
return [
|
|
9
|
+
return [canonicalUri(parentSchema), await Validation.compile(schema, ast)];
|
|
11
10
|
};
|
|
12
11
|
|
|
13
12
|
const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors, quiet) => {
|
|
14
|
-
if (
|
|
13
|
+
if (Instance.typeOf(instance) !== "object") {
|
|
15
14
|
return true;
|
|
16
15
|
}
|
|
17
16
|
|
|
@@ -25,7 +24,7 @@ const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnc
|
|
|
25
24
|
};
|
|
26
25
|
|
|
27
26
|
const collectEvaluatedProperties = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors) => {
|
|
28
|
-
if (
|
|
27
|
+
if (Instance.typeOf(instance) !== "object") {
|
|
29
28
|
return true;
|
|
30
29
|
}
|
|
31
30
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import jsonStringify from "fastest-stable-stringify";
|
|
2
|
-
import * as
|
|
2
|
+
import * as Browser from "@hyperjump/browser";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
const id = "https://json-schema.org/keyword/uniqueItems";
|
|
7
7
|
|
|
8
|
-
const compile = (schema) =>
|
|
8
|
+
const compile = (schema) => Browser.value(schema);
|
|
9
9
|
|
|
10
10
|
const interpret = (uniqueItems, instance) => {
|
|
11
|
-
if (
|
|
11
|
+
if (Instance.typeOf(instance) !== "array" || uniqueItems === false) {
|
|
12
12
|
return true;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { value, entries } from "@hyperjump/browser";
|
|
1
2
|
import { pipe, asyncMap, asyncCollectArray } from "@hyperjump/pact";
|
|
3
|
+
import { append as pointerAppend } from "@hyperjump/json-pointer";
|
|
2
4
|
import { publishAsync, publish } from "../pubsub.js";
|
|
3
|
-
import { isExperimentalKeywordEnabled } from "../configuration.js";
|
|
4
5
|
import * as Instance from "../instance.js";
|
|
5
|
-
import { getKeywordId, getKeyword } from "../keywords.js";
|
|
6
6
|
import { toAbsoluteUri } from "../common.js";
|
|
7
|
-
import
|
|
7
|
+
import { canonicalUri, getKeyword, getKeywordByName } from "../experimental.js";
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
const id = "https://json-schema.org/evaluation/validate";
|
|
@@ -14,40 +14,28 @@ const compile = async (schema, ast) => {
|
|
|
14
14
|
await publishAsync("validate.metaValidate", schema);
|
|
15
15
|
|
|
16
16
|
// Dynamic Scope
|
|
17
|
-
if (!(schema.
|
|
18
|
-
ast.metaData[schema.
|
|
19
|
-
dynamicAnchors: schema.dynamicAnchors
|
|
17
|
+
if (!(schema.document.baseUri in ast.metaData)) {
|
|
18
|
+
ast.metaData[schema.document.baseUri] = {
|
|
19
|
+
dynamicAnchors: schema.document.dynamicAnchors
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Compile
|
|
24
|
-
const url =
|
|
24
|
+
const url = canonicalUri(schema);
|
|
25
25
|
if (!(url in ast)) {
|
|
26
26
|
ast[url] = false; // Place dummy entry in ast to avoid recursive loops
|
|
27
27
|
|
|
28
|
-
const schemaValue =
|
|
28
|
+
const schemaValue = value(schema);
|
|
29
29
|
if (!["object", "boolean"].includes(typeof schemaValue)) {
|
|
30
30
|
throw Error(`No schema found at '${url}'`);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
ast[url] = typeof schemaValue === "boolean" ? schemaValue : await pipe(
|
|
34
|
-
|
|
34
|
+
entries(schema),
|
|
35
35
|
asyncMap(async ([keyword, keywordSchema]) => {
|
|
36
|
-
const
|
|
37
|
-
if (!keywordId) {
|
|
38
|
-
throw Error(`Encountered unknown keyword '${keyword}' at ${url}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const keywordHandler = getKeyword(keywordId);
|
|
42
|
-
if (!keywordHandler) {
|
|
43
|
-
throw Error(`Encountered unsupported keyword ${keyword} at '${url}'. You can provide an implementation for the '${keywordId}' keyword using the 'addKeyword' function.`);
|
|
44
|
-
}
|
|
45
|
-
if (keywordHandler.experimental && !isExperimentalKeywordEnabled(keywordId)) {
|
|
46
|
-
throw Error(`Encountered experimental keyword ${keyword} at '${url}'. You can enable this keyword with: setExperimentalKeywordEnabled('${keywordId}', true)`);
|
|
47
|
-
}
|
|
48
|
-
|
|
36
|
+
const keywordHandler = getKeywordByName(keyword, schema.document.dialectId);
|
|
49
37
|
const keywordAst = await keywordHandler.compile(keywordSchema, ast, schema);
|
|
50
|
-
return [
|
|
38
|
+
return [keywordHandler.id, pointerAppend(keyword, canonicalUri(schema)), keywordAst];
|
|
51
39
|
}),
|
|
52
40
|
asyncCollectArray
|
|
53
41
|
);
|
package/lib/keywords.js
CHANGED
|
@@ -4,6 +4,20 @@ import { toAbsoluteUri } from "./common.js";
|
|
|
4
4
|
const _keywords = {};
|
|
5
5
|
export const getKeyword = (id) => _keywords[toAbsoluteUri(id)];
|
|
6
6
|
|
|
7
|
+
export const getKeywordByName = (keyword, dialectId) => {
|
|
8
|
+
const keywordId = getKeywordId(keyword, dialectId);
|
|
9
|
+
if (!keywordId) {
|
|
10
|
+
throw Error(`Encountered unknown keyword '${keyword}'`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const keywordHandler = getKeyword(keywordId);
|
|
14
|
+
if (!keywordHandler) {
|
|
15
|
+
throw Error(`Encountered unsupported keyword ${keyword}. You can provide an implementation for the '${keywordId}' keyword using the 'addKeyword' function.`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return keywordHandler;
|
|
19
|
+
};
|
|
20
|
+
|
|
7
21
|
export const addKeyword = (keywordHandler) => {
|
|
8
22
|
_keywords[keywordHandler.id] = keywordHandler;
|
|
9
23
|
};
|
|
@@ -16,26 +30,25 @@ export const defineVocabulary = (id, keywords) => {
|
|
|
16
30
|
const _dialects = {};
|
|
17
31
|
const _allowUnknownKeywords = {};
|
|
18
32
|
|
|
19
|
-
export const getKeywordId = (
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
33
|
+
export const getKeywordId = (keyword, dialectId) => getDialect(dialectId)?.[keyword]
|
|
34
|
+
|| (_allowUnknownKeywords[dialectId] || keyword.startsWith("x-"))
|
|
35
|
+
&& `https://json-schema.org/keyword/unknown#${keyword}`;
|
|
23
36
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
37
|
+
export const getKeywordName = (dialectId, keywordId) => {
|
|
38
|
+
const dialect = getDialect(dialectId);
|
|
39
|
+
for (const keyword in dialect) {
|
|
40
|
+
if (dialect[keyword] === keywordId) {
|
|
41
|
+
return keyword;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
27
44
|
};
|
|
28
45
|
|
|
29
|
-
|
|
30
|
-
if (!
|
|
46
|
+
const getDialect = (dialectId) => {
|
|
47
|
+
if (!(dialectId in _dialects)) {
|
|
31
48
|
throw Error(`Encountered unknown dialect '${dialectId}'`);
|
|
32
49
|
}
|
|
33
50
|
|
|
34
|
-
|
|
35
|
-
if (_dialects[dialectId][keyword] === keywordId) {
|
|
36
|
-
return keyword;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
51
|
+
return _dialects[dialectId];
|
|
39
52
|
};
|
|
40
53
|
|
|
41
54
|
export const hasDialect = (dialectId) => dialectId in _dialects;
|
package/lib/openapi.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import contentTypeParser from "content-type";
|
|
2
|
+
import { addMediaTypePlugin } from "@hyperjump/browser";
|
|
3
|
+
import { buildSchemaDocument } from "./schema.js";
|
|
2
4
|
|
|
3
5
|
|
|
4
6
|
const is31 = RegExp.prototype.test.bind(/^3\.1\.\d+(-.+)?$/);
|
|
5
7
|
const is30 = RegExp.prototype.test.bind(/^3\.0\.\d+(-.+)?$/);
|
|
6
8
|
|
|
7
9
|
addMediaTypePlugin("application/openapi+json", {
|
|
8
|
-
parse: async (response
|
|
10
|
+
parse: async (response) => {
|
|
9
11
|
const doc = await response.json();
|
|
10
12
|
|
|
11
13
|
let defaultDialect;
|
|
12
|
-
const
|
|
14
|
+
const contentType = contentTypeParser.parse(response.headers.get("content-type") ?? "");
|
|
15
|
+
const version = doc.openapi || contentType.parameters.version;
|
|
13
16
|
|
|
14
17
|
if (!version) {
|
|
15
18
|
throw Error("Invalid OpenAPI document. Add the 'openapi' field and try again.");
|
|
@@ -18,14 +21,24 @@ addMediaTypePlugin("application/openapi+json", {
|
|
|
18
21
|
} else if (is31(version)) {
|
|
19
22
|
if (!("jsonSchemaDialect" in doc) || doc.jsonSchemaDialect === "https://spec.openapis.org/oas/3.1/dialect/base") {
|
|
20
23
|
defaultDialect = "https://spec.openapis.org/oas/3.1/schema-base";
|
|
24
|
+
} else if (doc.jsonSchemaDialect === "https://json-schema.org/draft/2020-12/schema") {
|
|
25
|
+
defaultDialect = `https://spec.openapis.org/oas/3.1/schema-draft-2020-12`;
|
|
26
|
+
} else if (doc.jsonSchemaDialect === "https://json-schema.org/draft/2019-09/schema") {
|
|
27
|
+
defaultDialect = `https://spec.openapis.org/oas/3.1/schema-draft-2019-09`;
|
|
28
|
+
} else if (doc.jsonSchemaDialect === "http://json-schema.org/draft-07/schema#") {
|
|
29
|
+
defaultDialect = `https://spec.openapis.org/oas/3.1/schema-draft-07`;
|
|
30
|
+
} else if (doc.jsonSchemaDialect === "http://json-schema.org/draft-06/schema#") {
|
|
31
|
+
defaultDialect = `https://spec.openapis.org/oas/3.1/schema-draft-06`;
|
|
32
|
+
} else if (doc.jsonSchemaDialect === "http://json-schema.org/draft-04/schema#") {
|
|
33
|
+
defaultDialect = `https://spec.openapis.org/oas/3.1/schema-draft-04`;
|
|
21
34
|
} else {
|
|
22
|
-
defaultDialect = `https://spec.openapis.org/oas/3.1/schema
|
|
35
|
+
defaultDialect = `https://spec.openapis.org/oas/3.1/schema?${encodeURIComponent(doc.jsonSchemaDialect)}`;
|
|
23
36
|
}
|
|
24
37
|
} else {
|
|
25
38
|
throw Error(`Encountered unsupported OpenAPI version '${version}' in ${response.url}`);
|
|
26
39
|
}
|
|
27
40
|
|
|
28
|
-
return
|
|
41
|
+
return buildSchemaDocument(doc, response.url, defaultDialect);
|
|
29
42
|
},
|
|
30
|
-
|
|
43
|
+
fileMatcher: (path) => /(\/|\.)openapi\.json$/.test(path)
|
|
31
44
|
});
|