@hyperjump/json-schema 1.11.0 → 1.12.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 +24 -7
- package/annotations/annotated-instance.d.ts +0 -1
- package/annotations/annotated-instance.js +0 -7
- package/annotations/index.js +19 -3
- package/draft-04/additionalItems.js +7 -5
- package/draft-04/dependencies.js +5 -3
- package/draft-04/items.js +8 -6
- package/draft-06/contains.js +3 -2
- package/draft-06/index.d.ts +4 -2
- package/draft-2019-09/index.d.ts +2 -1
- package/draft-2020-12/dynamicRef.js +8 -6
- package/draft-2020-12/index.d.ts +2 -1
- package/lib/core.js +5 -4
- package/lib/experimental.d.ts +12 -3
- package/lib/experimental.js +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/instance.d.ts +0 -2
- package/lib/instance.js +0 -2
- package/lib/keywords/additionalProperties.js +7 -5
- package/lib/keywords/allOf.js +7 -5
- package/lib/keywords/anyOf.js +4 -4
- package/lib/keywords/conditional.js +9 -9
- package/lib/keywords/contains.js +5 -5
- package/lib/keywords/contentEncoding.js +3 -7
- package/lib/keywords/contentMediaType.js +3 -7
- package/lib/keywords/contentSchema.js +3 -7
- package/lib/keywords/default.js +3 -7
- package/lib/keywords/dependentSchemas.js +7 -5
- package/lib/keywords/deprecated.js +3 -7
- package/lib/keywords/description.js +3 -7
- package/lib/keywords/dynamicRef.js +6 -4
- package/lib/keywords/else.js +13 -10
- package/lib/keywords/examples.js +3 -7
- package/lib/keywords/format.js +3 -7
- package/lib/keywords/if.js +6 -6
- package/lib/keywords/itemPattern.js +7 -7
- package/lib/keywords/items.js +7 -5
- package/lib/keywords/oneOf.js +6 -6
- package/lib/keywords/patternProperties.js +7 -5
- package/lib/keywords/prefixItems.js +7 -5
- package/lib/keywords/properties.js +7 -5
- package/lib/keywords/propertyDependencies.js +7 -5
- package/lib/keywords/propertyNames.js +5 -3
- package/lib/keywords/readOnly.js +3 -7
- package/lib/keywords/ref.js +3 -1
- package/lib/keywords/then.js +14 -12
- package/lib/keywords/title.js +3 -7
- package/lib/keywords/unevaluatedItems.js +11 -8
- package/lib/keywords/unevaluatedProperties.js +11 -7
- package/lib/keywords/unknown.js +3 -7
- package/lib/keywords/validation.js +83 -28
- package/lib/keywords/writeOnly.js +3 -7
- package/openapi-3-0/discriminator.js +3 -7
- package/openapi-3-0/example.js +3 -7
- package/openapi-3-0/externalDocs.js +3 -7
- package/openapi-3-0/index.d.ts +1 -1
- package/openapi-3-0/xml.js +3 -7
- package/package.json +1 -1
- package/stable/index.d.ts +2 -0
- package/lib/output.js +0 -41
package/README.md
CHANGED
|
@@ -402,9 +402,9 @@ addKeyword({
|
|
|
402
402
|
// );
|
|
403
403
|
},
|
|
404
404
|
|
|
405
|
-
interpret: (implies, instance,
|
|
405
|
+
interpret: (implies, instance, context) => {
|
|
406
406
|
return implies.reduce((valid, schema) => {
|
|
407
|
-
return !valid || Validation.interpret(schema, instance,
|
|
407
|
+
return !valid || Validation.interpret(schema, instance, context);
|
|
408
408
|
}, true);
|
|
409
409
|
}
|
|
410
410
|
});
|
|
@@ -524,23 +524,40 @@ These are available from the `@hyperjump/json-schema/experimental` export.
|
|
|
524
524
|
is needed for compiling sub-schemas. The `parentSchema` parameter is
|
|
525
525
|
primarily useful for looking up the value of an adjacent keyword that
|
|
526
526
|
might effect this one.
|
|
527
|
-
* interpret: (compiledKeywordValue: any, instance: JsonNode,
|
|
527
|
+
* interpret: (compiledKeywordValue: any, instance: JsonNode, context: ValidationContext) => boolean
|
|
528
528
|
|
|
529
529
|
This function takes the value returned by the `compile` function and
|
|
530
530
|
the instance value that is being validated and returns whether the
|
|
531
531
|
value is valid or not. The other parameters are only needed for
|
|
532
532
|
validating sub-schemas.
|
|
533
|
-
*
|
|
533
|
+
* simpleApplicator?: boolean
|
|
534
|
+
|
|
535
|
+
Some applicator keywords just apply schemas and don't do any
|
|
536
|
+
validation of its own. In these cases, it isn't helpful to include
|
|
537
|
+
them in BASIC output. This flag is used to trim those nodes from the
|
|
538
|
+
output.
|
|
539
|
+
* collectEvaluatedProperties?: (compiledKeywordValue: any, instance: JsonNode, context: ValidationContext, isTop?: boolean) => Set\<string> | false
|
|
534
540
|
|
|
535
541
|
If the keyword is an applicator, it will need to implement this
|
|
536
542
|
function for `unevaluatedProperties` to work as expected.
|
|
537
|
-
* collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonNode,
|
|
543
|
+
* collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonNode, context: ValidationContext, isTop?: boolean) => Set\<number> | false
|
|
538
544
|
|
|
539
545
|
If the keyword is an applicator, it will need to implement this
|
|
540
546
|
function for `unevaluatedItems` to work as expected.
|
|
541
547
|
* collectExternalIds?: (visited: Set\<string>, parentSchema: Browser, schema: Browser) => Set\<string>
|
|
542
548
|
If the keyword is an applicator, it will need to implement this
|
|
543
|
-
|
|
549
|
+
function to work properly with the [bundle](#bundling) feature.
|
|
550
|
+
* annotation?: (compiledKeywordValue: any) => any
|
|
551
|
+
|
|
552
|
+
If the keyword is an annotation, it will need to implement this
|
|
553
|
+
function to return the annotation.
|
|
554
|
+
|
|
555
|
+
* **ValidationContext**: object
|
|
556
|
+
* ast: AST
|
|
557
|
+
* dynamicAnchors: object
|
|
558
|
+
* schemaUrl: string
|
|
559
|
+
* errors: OutputUnit[]
|
|
560
|
+
* annotations: OutputUnit[]
|
|
544
561
|
* **defineVocabulary**: (id: string, keywords: { [keyword: string]: string }) => void
|
|
545
562
|
|
|
546
563
|
Define a vocabulary that maps keyword name to keyword URIs defined using
|
|
@@ -683,7 +700,7 @@ Schema.
|
|
|
683
700
|
|
|
684
701
|
### Usage
|
|
685
702
|
An annotated JSON document is represented as a
|
|
686
|
-
(JsonNode)[
|
|
703
|
+
(JsonNode)[#instance-api-experimental] AST. You can use this AST to traverse
|
|
687
704
|
the data structure and get annotations for the values it represents.
|
|
688
705
|
|
|
689
706
|
```javascript
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export const setAnnotation: (keywordUri: string, schemaLocation: string, value: string) => void;
|
|
2
1
|
export const annotation: <A>(instance: JsonNode, keyword: string, dialectUri?: string) => A[];
|
|
3
2
|
export const annotatedWith: <A extends JsonNode>(instance: A, keyword: string, dialectUri?: string) => A[];
|
|
4
3
|
|
|
@@ -5,13 +5,6 @@ import { getKeywordId } from "../lib/keywords.js";
|
|
|
5
5
|
|
|
6
6
|
const defaultDialectId = "https://json-schema.org/validation";
|
|
7
7
|
|
|
8
|
-
export const setAnnotation = (node, keywordUri, schemaLocation, value) => {
|
|
9
|
-
if (!(keywordUri in node.annotations)) {
|
|
10
|
-
node.annotations[keywordUri] = {};
|
|
11
|
-
}
|
|
12
|
-
node.annotations[keywordUri][schemaLocation] = value;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
8
|
export const annotation = (node, keyword, dialect = defaultDialectId) => {
|
|
16
9
|
const keywordUri = getKeywordId(keyword, dialect);
|
|
17
10
|
|
package/annotations/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { FLAG } from "../lib/index.js";
|
|
1
2
|
import { ValidationError } from "./validation-error.js";
|
|
2
|
-
import { getSchema, compile,
|
|
3
|
+
import { getSchema, compile, BASIC } from "../lib/experimental.js";
|
|
4
|
+
import Validation from "../lib/keywords/validation.js";
|
|
3
5
|
import * as Instance from "../lib/instance.js";
|
|
4
6
|
|
|
5
7
|
|
|
@@ -12,11 +14,25 @@ export const annotate = async (schemaUri, json = undefined, outputFormat = undef
|
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
export const interpret = ({ ast, schemaUri }, instance, outputFormat = BASIC) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
+
const errors = [];
|
|
18
|
+
const annotations = [];
|
|
19
|
+
const context = { ast, dynamicAnchors: {}, errors, annotations, outputFormat };
|
|
20
|
+
const valid = Validation.interpret(schemaUri, instance, context);
|
|
21
|
+
|
|
22
|
+
if (!valid) {
|
|
23
|
+
const result = outputFormat === FLAG || valid ? { valid } : { valid, errors };
|
|
17
24
|
throw new ValidationError(result);
|
|
18
25
|
}
|
|
19
26
|
|
|
27
|
+
for (const annotation of annotations) {
|
|
28
|
+
const node = Instance.get(annotation.instanceLocation, instance);
|
|
29
|
+
const keyword = annotation.keyword;
|
|
30
|
+
if (!node.annotations[keyword]) {
|
|
31
|
+
node.annotations[keyword] = [];
|
|
32
|
+
}
|
|
33
|
+
node.annotations[keyword].push(annotation.annotation);
|
|
34
|
+
}
|
|
35
|
+
|
|
20
36
|
return instance;
|
|
21
37
|
};
|
|
22
38
|
|
|
@@ -14,7 +14,7 @@ const compile = async (schema, ast, parentSchema) => {
|
|
|
14
14
|
return [numberOfItems, await Validation.compile(schema, ast)];
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
const interpret = ([numberOfItems, additionalItems], instance,
|
|
17
|
+
const interpret = ([numberOfItems, additionalItems], instance, context) => {
|
|
18
18
|
if (Instance.typeOf(instance) !== "array") {
|
|
19
19
|
return true;
|
|
20
20
|
}
|
|
@@ -22,12 +22,14 @@ const interpret = ([numberOfItems, additionalItems], instance, ast, dynamicAncho
|
|
|
22
22
|
return pipe(
|
|
23
23
|
Instance.iter(instance),
|
|
24
24
|
drop(numberOfItems),
|
|
25
|
-
every((item) => Validation.interpret(additionalItems, item,
|
|
25
|
+
every((item) => Validation.interpret(additionalItems, item, context))
|
|
26
26
|
);
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
const
|
|
30
|
-
|
|
29
|
+
const simpleApplicator = true;
|
|
30
|
+
|
|
31
|
+
const collectEvaluatedItems = (keywordValue, instance, context) => {
|
|
32
|
+
if (!interpret(keywordValue, instance, context)) {
|
|
31
33
|
return false;
|
|
32
34
|
}
|
|
33
35
|
|
|
@@ -39,4 +41,4 @@ const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
|
|
|
39
41
|
return evaluatedIndexes;
|
|
40
42
|
};
|
|
41
43
|
|
|
42
|
-
export default { id, compile, interpret, collectEvaluatedItems };
|
|
44
|
+
export default { id, compile, interpret, simpleApplicator, collectEvaluatedItems };
|
package/draft-04/dependencies.js
CHANGED
|
@@ -15,7 +15,7 @@ const compile = (schema, ast) => pipe(
|
|
|
15
15
|
asyncCollectArray
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
const interpret = (dependencies, instance,
|
|
18
|
+
const interpret = (dependencies, instance, context) => {
|
|
19
19
|
const value = Instance.value(instance);
|
|
20
20
|
|
|
21
21
|
return Instance.typeOf(instance) !== "object" || dependencies.every(([propertyName, dependency]) => {
|
|
@@ -26,9 +26,11 @@ const interpret = (dependencies, instance, ast, dynamicAnchors, quiet) => {
|
|
|
26
26
|
if (Array.isArray(dependency)) {
|
|
27
27
|
return dependency.every((key) => key in value);
|
|
28
28
|
} else {
|
|
29
|
-
return Validation.interpret(dependency, instance,
|
|
29
|
+
return Validation.interpret(dependency, instance, context);
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const simpleApplicator = true;
|
|
35
|
+
|
|
36
|
+
export default { id, compile, interpret, simpleApplicator };
|
package/draft-04/items.js
CHANGED
|
@@ -18,26 +18,28 @@ const compile = (schema, ast) => {
|
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
const interpret = (items, instance,
|
|
21
|
+
const interpret = (items, instance, context) => {
|
|
22
22
|
if (Instance.typeOf(instance) !== "array") {
|
|
23
23
|
return true;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (typeof items === "string") {
|
|
27
|
-
return every((itemValue) => Validation.interpret(items, itemValue,
|
|
27
|
+
return every((itemValue) => Validation.interpret(items, itemValue, context), Instance.iter(instance));
|
|
28
28
|
} else {
|
|
29
29
|
return pipe(
|
|
30
30
|
zip(items, Instance.iter(instance)),
|
|
31
31
|
take(Instance.length(instance)),
|
|
32
|
-
every(([prefixItem, item]) => Validation.interpret(prefixItem, item,
|
|
32
|
+
every(([prefixItem, item]) => Validation.interpret(prefixItem, item, context))
|
|
33
33
|
);
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
const
|
|
38
|
-
|
|
37
|
+
const simpleApplicator = true;
|
|
38
|
+
|
|
39
|
+
const collectEvaluatedItems = (items, instance, context) => {
|
|
40
|
+
return interpret(items, instance, context) && (typeof items === "string"
|
|
39
41
|
? collectSet(range(0, Instance.length(instance)))
|
|
40
42
|
: collectSet(range(0, items.length)));
|
|
41
43
|
};
|
|
42
44
|
|
|
43
|
-
export default { id, compile, interpret, collectEvaluatedItems };
|
|
45
|
+
export default { id, compile, interpret, simpleApplicator, collectEvaluatedItems };
|
package/draft-06/contains.js
CHANGED
|
@@ -7,8 +7,9 @@ const id = "https://json-schema.org/keyword/draft-06/contains";
|
|
|
7
7
|
|
|
8
8
|
const compile = (schema, ast) => Validation.compile(schema, ast);
|
|
9
9
|
|
|
10
|
-
const interpret = (contains, instance,
|
|
11
|
-
return Instance.typeOf(instance) !== "array"
|
|
10
|
+
const interpret = (contains, instance, context) => {
|
|
11
|
+
return Instance.typeOf(instance) !== "array"
|
|
12
|
+
|| some((item) => Validation.interpret(contains, item, context), Instance.iter(instance));
|
|
12
13
|
};
|
|
13
14
|
|
|
14
15
|
export default { id, compile, interpret };
|
package/draft-06/index.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ import type { Json } from "@hyperjump/json-pointer";
|
|
|
2
2
|
import type { JsonSchemaType } from "../lib/common.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type JsonSchemaDraft06Ref = {
|
|
6
6
|
$ref: string;
|
|
7
|
-
}
|
|
7
|
+
};
|
|
8
|
+
export type JsonSchemaDraft06Object = {
|
|
8
9
|
$schema?: "http://json-schema.org/draft-06/schema#";
|
|
9
10
|
$id?: string;
|
|
10
11
|
title?: string;
|
|
@@ -43,5 +44,6 @@ export type JsonSchemaDraft06 = boolean | {
|
|
|
43
44
|
oneOf?: JsonSchemaDraft06[];
|
|
44
45
|
not?: JsonSchemaDraft06;
|
|
45
46
|
};
|
|
47
|
+
export type JsonSchemaDraft06 = boolean | JsonSchemaDraft06Ref | JsonSchemaDraft06Object;
|
|
46
48
|
|
|
47
49
|
export * from "../lib/index.js";
|
package/draft-2019-09/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Json } from "@hyperjump/json-pointer";
|
|
|
2
2
|
import type { JsonSchemaType } from "../lib/common.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type JsonSchemaDraft201909Object = {
|
|
6
6
|
$schema?: "https://json-schema.org/draft/2019-09/schema";
|
|
7
7
|
$id?: string;
|
|
8
8
|
$anchor?: string;
|
|
@@ -61,5 +61,6 @@ export type JsonSchemaDraft201909 = boolean | {
|
|
|
61
61
|
contentEncoding?: string;
|
|
62
62
|
contentSchema?: JsonSchemaDraft201909;
|
|
63
63
|
};
|
|
64
|
+
export type JsonSchemaDraft201909 = boolean | JsonSchemaDraft201909Object;
|
|
64
65
|
|
|
65
66
|
export * from "../lib/index.js";
|
|
@@ -12,17 +12,19 @@ const compile = async (dynamicRef, ast) => {
|
|
|
12
12
|
return [referencedSchema.document.baseUri, fragment, canonicalUri(referencedSchema)];
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
const evaluate = (strategy, [id, fragment, ref], instance,
|
|
16
|
-
if (fragment in ast.metaData[id].dynamicAnchors) {
|
|
17
|
-
dynamicAnchors = { ...ast.metaData[id].dynamicAnchors, ...dynamicAnchors };
|
|
18
|
-
return strategy(dynamicAnchors[fragment], instance,
|
|
15
|
+
const evaluate = (strategy, [id, fragment, ref], instance, context) => {
|
|
16
|
+
if (fragment in context.ast.metaData[id].dynamicAnchors) {
|
|
17
|
+
context.dynamicAnchors = { ...context.ast.metaData[id].dynamicAnchors, ...context.dynamicAnchors };
|
|
18
|
+
return strategy(context.dynamicAnchors[fragment], instance, context);
|
|
19
19
|
} else {
|
|
20
|
-
return strategy(ref, instance,
|
|
20
|
+
return strategy(ref, instance, context);
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
+
const simpleApplicator = true;
|
|
25
|
+
|
|
24
26
|
const interpret = (...args) => evaluate(Validation.interpret, ...args);
|
|
25
27
|
const collectEvaluatedProperties = (...args) => evaluate(Validation.collectEvaluatedProperties, ...args);
|
|
26
28
|
const collectEvaluatedItems = (...args) => evaluate(Validation.collectEvaluatedItems, ...args);
|
|
27
29
|
|
|
28
|
-
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
|
30
|
+
export default { id, compile, interpret, simpleApplicator, collectEvaluatedProperties, collectEvaluatedItems };
|
package/draft-2020-12/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Json } from "@hyperjump/json-pointer";
|
|
|
2
2
|
import type { JsonSchemaType } from "../lib/common.js";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
export type
|
|
5
|
+
export type JsonSchemaDraft202012Object = {
|
|
6
6
|
$schema?: "https://json-schema.org/draft/2020-12/schema";
|
|
7
7
|
$id?: string;
|
|
8
8
|
$anchor?: string;
|
|
@@ -62,5 +62,6 @@ export type JsonSchemaDraft202012 = boolean | {
|
|
|
62
62
|
contentEncoding?: string;
|
|
63
63
|
contentSchema?: JsonSchemaDraft202012;
|
|
64
64
|
};
|
|
65
|
+
export type JsonSchemaDraft202012 = boolean | JsonSchemaDraft202012Object;
|
|
65
66
|
|
|
66
67
|
export * from "../lib/index.js";
|
package/lib/core.js
CHANGED
|
@@ -11,10 +11,9 @@ 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";
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
export const FLAG = "FLAG", BASIC = "BASIC";
|
|
16
|
+
export const FLAG = "FLAG", BASIC = "BASIC", DETAILED = "DETAILED";
|
|
18
17
|
setMetaSchemaOutputFormat(FLAG);
|
|
19
18
|
|
|
20
19
|
export const validate = async (url, value = undefined, outputFormat = undefined) => {
|
|
@@ -32,8 +31,10 @@ export const compile = async (schema) => {
|
|
|
32
31
|
};
|
|
33
32
|
|
|
34
33
|
export const interpret = curry(({ ast, schemaUri }, instance, outputFormat = FLAG) => {
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const errors = [];
|
|
35
|
+
const context = { ast, dynamicAnchors: {}, errors, annotations: [], outputFormat };
|
|
36
|
+
const valid = Validation.interpret(schemaUri, instance, context);
|
|
37
|
+
return outputFormat === FLAG || valid ? { valid } : { valid, errors };
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
const metaValidators = {};
|
package/lib/experimental.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ type Anchors = Record<string, string>;
|
|
|
32
32
|
|
|
33
33
|
// Output Formats
|
|
34
34
|
export const BASIC: "BASIC";
|
|
35
|
+
export const DETAILED: "DETAILED";
|
|
35
36
|
|
|
36
37
|
// Schema
|
|
37
38
|
export const getSchema: (uri: string, browser?: Browser) => Promise<Browser<SchemaDocument>>;
|
|
@@ -67,11 +68,19 @@ export const hasDialect: (dialectId: string) => boolean;
|
|
|
67
68
|
export type Keyword<A> = {
|
|
68
69
|
id: string;
|
|
69
70
|
compile: (schema: Browser<SchemaDocument>, ast: AST, parentSchema: Browser<SchemaDocument>) => Promise<A>;
|
|
70
|
-
interpret: (compiledKeywordValue: A, instance: JsonNode,
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
interpret: (compiledKeywordValue: A, instance: JsonNode, context: ValidationContext) => boolean;
|
|
72
|
+
simpleApplicator: boolean;
|
|
73
|
+
collectEvaluatedProperties?: (compiledKeywordValue: A, instance: JsonNode, context: ValidationContext, isTop?: boolean) => Set<string> | false;
|
|
74
|
+
collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonNode, context: ValidationContext, isTop?: boolean) => Set<number> | false;
|
|
73
75
|
collectExternalIds?: (visited: Set<string>, parentSchema: Browser<SchemaDocument>, schema: Browser<SchemaDocument>) => Promise<Set<string>>;
|
|
74
76
|
annotation?: <B>(compiledKeywordValue: A) => B;
|
|
75
77
|
};
|
|
76
78
|
|
|
79
|
+
export type ValidationContext = {
|
|
80
|
+
ast: AST;
|
|
81
|
+
dynamicAnchors: Anchors;
|
|
82
|
+
errors: OutputUnit[];
|
|
83
|
+
annotations: OutputUnit[];
|
|
84
|
+
};
|
|
85
|
+
|
|
77
86
|
export const Validation: Keyword<string>;
|
package/lib/experimental.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Json } from "@hyperjump/json-pointer";
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
export type SchemaFragment = string | number | boolean | null | SchemaObject | SchemaFragment[];
|
|
5
|
-
export type SchemaObject = {
|
|
5
|
+
export type SchemaObject = {
|
|
6
6
|
[keyword: string]: SchemaFragment;
|
|
7
7
|
};
|
|
8
8
|
|
|
@@ -29,6 +29,7 @@ export type OutputUnit = {
|
|
|
29
29
|
absoluteKeywordLocation: string;
|
|
30
30
|
instanceLocation: string;
|
|
31
31
|
valid: boolean;
|
|
32
|
+
annotation?: unknown;
|
|
32
33
|
errors?: OutputUnit[];
|
|
33
34
|
};
|
|
34
35
|
|
package/lib/instance.d.ts
CHANGED
package/lib/instance.js
CHANGED
|
@@ -31,7 +31,7 @@ const regexEscape = (string) => string
|
|
|
31
31
|
.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&")
|
|
32
32
|
.replace(/-/g, "\\x2d");
|
|
33
33
|
|
|
34
|
-
const interpret = ([isDefinedProperty, additionalProperties], instance,
|
|
34
|
+
const interpret = ([isDefinedProperty, additionalProperties], instance, context) => {
|
|
35
35
|
if (Instance.typeOf(instance) !== "object") {
|
|
36
36
|
return true;
|
|
37
37
|
}
|
|
@@ -39,7 +39,7 @@ const interpret = ([isDefinedProperty, additionalProperties], instance, ast, dyn
|
|
|
39
39
|
let isValid = true;
|
|
40
40
|
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
41
41
|
const propertyName = Instance.value(propertyNameNode);
|
|
42
|
-
if (!isDefinedProperty.test(propertyName) && !Validation.interpret(additionalProperties, property,
|
|
42
|
+
if (!isDefinedProperty.test(propertyName) && !Validation.interpret(additionalProperties, property, context)) {
|
|
43
43
|
isValid = false;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -47,7 +47,9 @@ const interpret = ([isDefinedProperty, additionalProperties], instance, ast, dyn
|
|
|
47
47
|
return isValid;
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
const
|
|
50
|
+
const simpleApplicator = true;
|
|
51
|
+
|
|
52
|
+
const collectEvaluatedProperties = ([isDefinedProperty, additionalProperties], instance, context) => {
|
|
51
53
|
if (Instance.typeOf(instance) !== "object") {
|
|
52
54
|
return true;
|
|
53
55
|
}
|
|
@@ -56,7 +58,7 @@ const collectEvaluatedProperties = ([isDefinedProperty, additionalProperties], i
|
|
|
56
58
|
for (const [propertyNameNode, property] of Instance.entries(instance)) {
|
|
57
59
|
const propertyName = Instance.value(propertyNameNode);
|
|
58
60
|
if (!isDefinedProperty.test(propertyName)) {
|
|
59
|
-
if (!Validation.interpret(additionalProperties, property,
|
|
61
|
+
if (!Validation.interpret(additionalProperties, property, context)) {
|
|
60
62
|
return false;
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -67,4 +69,4 @@ const collectEvaluatedProperties = ([isDefinedProperty, additionalProperties], i
|
|
|
67
69
|
return evaluatedPropertyNames;
|
|
68
70
|
};
|
|
69
71
|
|
|
70
|
-
export default { id, compile, interpret, collectEvaluatedProperties };
|
|
72
|
+
export default { id, compile, interpret, simpleApplicator, collectEvaluatedProperties };
|
package/lib/keywords/allOf.js
CHANGED
|
@@ -21,10 +21,12 @@ const interpret = (allOf, instance, ast, dynamicAnchors, quiet) => {
|
|
|
21
21
|
return isValid;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const simpleApplicator = true;
|
|
25
|
+
|
|
26
|
+
const collectEvaluatedProperties = (allOf, instance, context) => {
|
|
25
27
|
const evaluatedPropertyNames = new Set();
|
|
26
28
|
for (const schemaUrl of allOf) {
|
|
27
|
-
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance,
|
|
29
|
+
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, context);
|
|
28
30
|
if (!propertyNames) {
|
|
29
31
|
return false;
|
|
30
32
|
}
|
|
@@ -35,10 +37,10 @@ const collectEvaluatedProperties = (allOf, instance, ast, dynamicAnchors) => {
|
|
|
35
37
|
return evaluatedPropertyNames;
|
|
36
38
|
};
|
|
37
39
|
|
|
38
|
-
const collectEvaluatedItems = (allOf, instance,
|
|
40
|
+
const collectEvaluatedItems = (allOf, instance, context) => {
|
|
39
41
|
const evaluatedItemIndexes = new Set();
|
|
40
42
|
for (const schemaUrl of allOf) {
|
|
41
|
-
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance,
|
|
43
|
+
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, context);
|
|
42
44
|
if (!itemIndexes) {
|
|
43
45
|
return false;
|
|
44
46
|
}
|
|
@@ -49,4 +51,4 @@ const collectEvaluatedItems = (allOf, instance, ast, dynamicAnchors) => {
|
|
|
49
51
|
return evaluatedItemIndexes;
|
|
50
52
|
};
|
|
51
53
|
|
|
52
|
-
export default { id, compile, interpret, collectEvaluatedProperties, collectEvaluatedItems };
|
|
54
|
+
export default { id, compile, interpret, simpleApplicator, collectEvaluatedProperties, collectEvaluatedItems };
|
package/lib/keywords/anyOf.js
CHANGED
|
@@ -16,10 +16,10 @@ const interpret = (anyOf, instance, ast, dynamicAnchors, quiet) => {
|
|
|
16
16
|
return matches.length > 0;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
const collectEvaluatedProperties = (anyOf, instance,
|
|
19
|
+
const collectEvaluatedProperties = (anyOf, instance, context) => {
|
|
20
20
|
let evaluatedPropertyNames = false;
|
|
21
21
|
for (const schemaUrl of anyOf) {
|
|
22
|
-
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance,
|
|
22
|
+
const propertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, context);
|
|
23
23
|
if (propertyNames) {
|
|
24
24
|
evaluatedPropertyNames ||= new Set();
|
|
25
25
|
propertyNames.forEach(evaluatedPropertyNames.add, evaluatedPropertyNames);
|
|
@@ -29,10 +29,10 @@ const collectEvaluatedProperties = (anyOf, instance, ast, dynamicAnchors) => {
|
|
|
29
29
|
return evaluatedPropertyNames;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const collectEvaluatedItems = (anyOf, instance,
|
|
32
|
+
const collectEvaluatedItems = (anyOf, instance, context) => {
|
|
33
33
|
let evaluatedItemIndexes = false;
|
|
34
34
|
for (const schemaUrl of anyOf) {
|
|
35
|
-
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance,
|
|
35
|
+
const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, context);
|
|
36
36
|
if (itemIndexes) {
|
|
37
37
|
evaluatedItemIndexes ||= new Set();
|
|
38
38
|
itemIndexes.forEach(evaluatedItemIndexes.add, evaluatedItemIndexes);
|
|
@@ -12,39 +12,39 @@ const compile = (schema, ast) => pipe(
|
|
|
12
12
|
asyncCollectArray
|
|
13
13
|
);
|
|
14
14
|
|
|
15
|
-
const interpret = (conditional, instance,
|
|
15
|
+
const interpret = (conditional, instance, context) => {
|
|
16
16
|
for (let index = 0; index < conditional.length; index += 2) {
|
|
17
|
-
const isValid = Validation.interpret(conditional[index], instance,
|
|
17
|
+
const isValid = Validation.interpret(conditional[index], instance, context);
|
|
18
18
|
if (index + 1 === conditional.length) {
|
|
19
19
|
return isValid;
|
|
20
20
|
} else if (isValid) {
|
|
21
|
-
return Validation.interpret(conditional[index + 1], instance,
|
|
21
|
+
return Validation.interpret(conditional[index + 1], instance, context);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
return true;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const collectEvaluatedProperties = (conditional, instance,
|
|
28
|
+
const collectEvaluatedProperties = (conditional, instance, context) => {
|
|
29
29
|
for (let index = 0; index < conditional.length; index += 2) {
|
|
30
|
-
const unevaluatedProperties = Validation.collectEvaluatedProperties(conditional[index], instance,
|
|
30
|
+
const unevaluatedProperties = Validation.collectEvaluatedProperties(conditional[index], instance, context);
|
|
31
31
|
if (index + 1 === conditional.length) {
|
|
32
32
|
return unevaluatedProperties;
|
|
33
33
|
} else if (unevaluatedProperties !== false) {
|
|
34
|
-
return Validation.collectEvaluatedProperties(conditional[index + 1], instance,
|
|
34
|
+
return Validation.collectEvaluatedProperties(conditional[index + 1], instance, context);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
return new Set();
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
const collectEvaluatedItems = (conditional, instance,
|
|
41
|
+
const collectEvaluatedItems = (conditional, instance, context) => {
|
|
42
42
|
for (let index = 0; index < conditional.length; index += 2) {
|
|
43
|
-
const unevaluatedItems = Validation.collectEvaluatedItems(conditional[index], instance,
|
|
43
|
+
const unevaluatedItems = Validation.collectEvaluatedItems(conditional[index], instance, context);
|
|
44
44
|
if (index + 1 === conditional.length) {
|
|
45
45
|
return unevaluatedItems;
|
|
46
46
|
} else if (unevaluatedItems !== false) {
|
|
47
|
-
return Validation.collectEvaluatedItems(conditional[index + 1], instance,
|
|
47
|
+
return Validation.collectEvaluatedItems(conditional[index + 1], instance, context);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
package/lib/keywords/contains.js
CHANGED
|
@@ -20,21 +20,21 @@ const compile = async (schema, ast, parentSchema) => {
|
|
|
20
20
|
return { contains, minContains, maxContains };
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
const interpret = ({ contains, minContains, maxContains }, instance,
|
|
23
|
+
const interpret = ({ contains, minContains, maxContains }, instance, context) => {
|
|
24
24
|
const matches = Instance.typeOf(instance) !== "array" || pipe(
|
|
25
25
|
Instance.iter(instance),
|
|
26
|
-
filter((item) => Validation.interpret(contains, item,
|
|
26
|
+
filter((item) => Validation.interpret(contains, item, context)),
|
|
27
27
|
reduce((matches) => matches + 1, 0)
|
|
28
28
|
);
|
|
29
29
|
return matches >= minContains && matches <= maxContains;
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
-
const collectEvaluatedItems = (keywordValue, instance,
|
|
33
|
-
return interpret(keywordValue, instance,
|
|
32
|
+
const collectEvaluatedItems = (keywordValue, instance, context) => {
|
|
33
|
+
return interpret(keywordValue, instance, context)
|
|
34
34
|
&& Instance.typeOf(instance) === "array"
|
|
35
35
|
&& pipe(
|
|
36
36
|
zip(Instance.iter(instance), range(0)),
|
|
37
|
-
filter(([item]) => Validation.interpret(keywordValue.contains, item,
|
|
37
|
+
filter(([item]) => Validation.interpret(keywordValue.contains, item, context)),
|
|
38
38
|
map(([, itemIndex]) => itemIndex),
|
|
39
39
|
collectSet
|
|
40
40
|
);
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import * as Browser from "@hyperjump/browser";
|
|
2
|
-
import * as Instance from "../../annotations/annotated-instance.js";
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
const id = "https://json-schema.org/keyword/contentEncoding";
|
|
6
5
|
|
|
7
6
|
const compile = (schema) => Browser.value(schema);
|
|
7
|
+
const interpret = () => true;
|
|
8
|
+
const annotation = (contentEncoding) => contentEncoding;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
Instance.setAnnotation(instance, id, schemaLocation, contentEncoding);
|
|
11
|
-
return true;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default { id, compile, interpret };
|
|
10
|
+
export default { id, compile, interpret, annotation };
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import * as Browser from "@hyperjump/browser";
|
|
2
|
-
import * as Instance from "../../annotations/annotated-instance.js";
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
const id = "https://json-schema.org/keyword/contentMediaType";
|
|
6
5
|
|
|
7
6
|
const compile = (schema) => Browser.value(schema);
|
|
7
|
+
const interpret = () => true;
|
|
8
|
+
const annotation = (contentMediaType) => contentMediaType;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
Instance.setAnnotation(instance, id, schemaLocation, contentMediaType);
|
|
11
|
-
return true;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export default { id, compile, interpret };
|
|
10
|
+
export default { id, compile, interpret, annotation };
|