@hyperjump/json-schema 1.12.1 → 1.13.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 CHANGED
@@ -800,7 +800,7 @@ following functions are available in addition to the functions available in the
800
800
  * **annotation**: (instance: JsonNode, keyword: string, dialect?: string): any[];
801
801
 
802
802
  Get the annotations for a keyword for the value represented by the JsonNode.
803
- * **annotatedWith**: (instance: JsonNode, keyword: string, dialect?: string): JsonNode[];
803
+ * **annotatedWith**: (instance: JsonNode, keyword: string, dialect?: string): Generator<JsonNode>;
804
804
 
805
805
  Get all JsonNodes that are annotated with the given keyword.
806
806
  * **setAnnotation**: (instance: JsonNode, keywordId: string, value: any) => JsonNode
@@ -1,4 +1,4 @@
1
1
  export const annotation: <A>(instance: JsonNode, keyword: string, dialectUri?: string) => A[];
2
- export const annotatedWith: <A extends JsonNode>(instance: A, keyword: string, dialectUri?: string) => A[];
2
+ export const annotatedWith: <A extends JsonNode>(instance: A, keyword: string, dialectUri?: string) => Generator<A>;
3
3
 
4
4
  export * from "../lib/instance.js";
@@ -1,4 +1,3 @@
1
- import * as JsonPointer from "@hyperjump/json-pointer";
2
1
  import * as Instance from "../lib/instance.js";
3
2
  import { getKeywordId } from "../lib/keywords.js";
4
3
 
@@ -7,43 +6,15 @@ const defaultDialectId = "https://json-schema.org/validation";
7
6
 
8
7
  export const annotation = (node, keyword, dialect = defaultDialectId) => {
9
8
  const keywordUri = getKeywordId(keyword, dialect);
10
-
11
- let currentNode = node.root;
12
- const errors = [...invalidSchemas(currentNode)];
13
- for (let segment of JsonPointer.pointerSegments(node.pointer)) {
14
- segment = segment === "-" && Instance.typeOf(currentNode) === "array" ? Instance.length(currentNode) : segment;
15
- currentNode = Instance.step(segment, currentNode);
16
- errors.push(...invalidSchemas(currentNode));
17
- }
18
-
19
- const annotations = [];
20
- for (const schemaLocation in node.annotations[keywordUri]) {
21
- if (!errors.some((error) => schemaLocation.startsWith(error))) {
22
- annotations.unshift(node.annotations[keywordUri][schemaLocation]);
23
- }
24
- }
25
-
26
- return annotations;
9
+ return node.annotations[keywordUri] ?? [];
27
10
  };
28
11
 
29
- const invalidSchemas = function* (node) {
30
- for (const error in node.errors) {
31
- if (node.errors[error] === "https://json-schema.org/evaluation/validate") {
32
- yield error;
33
- }
34
- }
35
- };
36
-
37
- export const annotatedWith = (instance, keyword, dialectId = defaultDialectId) => {
38
- const nodes = [];
39
-
12
+ export const annotatedWith = function* (instance, keyword, dialectId = defaultDialectId) {
40
13
  for (const node of Instance.allNodes(instance)) {
41
14
  if (annotation(node, keyword, dialectId).length > 0) {
42
- nodes.push(node);
15
+ yield node;
43
16
  }
44
17
  }
45
-
46
- return nodes;
47
18
  };
48
19
 
49
20
  export * from "../lib/instance.js";
@@ -18,7 +18,7 @@ export type CompiledSchema = {
18
18
 
19
19
  type AST = {
20
20
  metaData: Record<string, MetaData>;
21
- } & Record<string, Node<Node<unknown>[] | boolean>>;
21
+ } & Record<string, Node<unknown>[] | boolean>;
22
22
 
23
23
  type Node<A> = [keywordId: string, schemaUri: string, keywordValue: A];
24
24
 
@@ -73,7 +73,7 @@ export type Keyword<A> = {
73
73
  collectEvaluatedProperties?: (compiledKeywordValue: A, instance: JsonNode, context: ValidationContext, isTop?: boolean) => Set<string> | false;
74
74
  collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonNode, context: ValidationContext, isTop?: boolean) => Set<number> | false;
75
75
  collectExternalIds?: (visited: Set<string>, parentSchema: Browser<SchemaDocument>, schema: Browser<SchemaDocument>) => Promise<Set<string>>;
76
- annotation?: <B>(compiledKeywordValue: A) => B;
76
+ annotation?: <B>(compiledKeywordValue: A, instance: JsonNode) => B | undefined;
77
77
  };
78
78
 
79
79
  export type ValidationContext = {
@@ -81,6 +81,7 @@ export type ValidationContext = {
81
81
  dynamicAnchors: Anchors;
82
82
  errors: OutputUnit[];
83
83
  annotations: OutputUnit[];
84
+ outputFormat: OutputFormat;
84
85
  };
85
86
 
86
87
  export const Validation: Keyword<string>;
@@ -1,10 +1,18 @@
1
1
  import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../instance.js";
2
3
 
3
4
 
4
5
  const id = "https://json-schema.org/keyword/contentEncoding";
5
6
 
6
7
  const compile = (schema) => Browser.value(schema);
7
8
  const interpret = () => true;
8
- const annotation = (contentEncoding) => contentEncoding;
9
+
10
+ const annotation = (contentEncoding, instance) => {
11
+ if (Instance.typeOf(instance) !== "string") {
12
+ return;
13
+ }
14
+
15
+ return contentEncoding;
16
+ };
9
17
 
10
18
  export default { id, compile, interpret, annotation };
@@ -1,10 +1,18 @@
1
1
  import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../instance.js";
2
3
 
3
4
 
4
5
  const id = "https://json-schema.org/keyword/contentMediaType";
5
6
 
6
7
  const compile = (schema) => Browser.value(schema);
7
8
  const interpret = () => true;
8
- const annotation = (contentMediaType) => contentMediaType;
9
+
10
+ const annotation = (contentMediaType, instance) => {
11
+ if (Instance.typeOf(instance) !== "string") {
12
+ return;
13
+ }
14
+
15
+ return contentMediaType;
16
+ };
9
17
 
10
18
  export default { id, compile, interpret, annotation };
@@ -1,10 +1,25 @@
1
1
  import { canonicalUri } from "../schema.js";
2
+ import * as Browser from "@hyperjump/browser";
3
+ import * as Instance from "../instance.js";
4
+ import { getKeywordName } from "../keywords.js";
2
5
 
3
6
 
4
7
  const id = "https://json-schema.org/keyword/contentSchema";
5
8
 
6
- const compile = (contentSchema) => canonicalUri(contentSchema);
9
+ const compile = async (contentSchema, _ast, parentSchema) => {
10
+ const contentMediaTypeKeyword = getKeywordName(contentSchema.document.dialectId, "https://json-schema.org/keyword/contentMediaType");
11
+ const contentMediaType = await Browser.step(contentMediaTypeKeyword, parentSchema);
12
+ return Browser.value(contentMediaType) && canonicalUri(contentSchema);
13
+ };
14
+
7
15
  const interpret = () => true;
8
- const annotation = (contentSchema) => contentSchema;
16
+
17
+ const annotation = (contentSchema, instance) => {
18
+ if (Instance.typeOf(instance) !== "string") {
19
+ return;
20
+ }
21
+
22
+ return contentSchema;
23
+ };
9
24
 
10
25
  export default { id, compile, interpret, annotation };
@@ -85,15 +85,18 @@ const interpret = (url, instance, { ast, dynamicAnchors, errors, annotations, ou
85
85
  }
86
86
  errors.push(...context.errors);
87
87
  } else {
88
- if (keywordHandler.annotation) {
89
- schemaAnnotations.push({
88
+ const annotation = keywordHandler.annotation?.(keywordValue, instance);
89
+ if (annotation !== undefined) {
90
+ schemaAnnotations.unshift({
90
91
  keyword: keywordId,
91
92
  absoluteKeywordLocation: schemaUri,
92
93
  instanceLocation: Instance.uri(instance),
93
- annotation: keywordHandler.annotation(keywordValue)
94
+ annotation: annotation
94
95
  });
95
96
  }
96
- schemaAnnotations.push(...context.annotations);
97
+ for (const contextAnnotation of context.annotations) {
98
+ schemaAnnotations.unshift(contextAnnotation);
99
+ }
97
100
  }
98
101
  break;
99
102
  case DETAILED: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperjump/json-schema",
3
- "version": "1.12.1",
3
+ "version": "1.13.0",
4
4
  "description": "A JSON Schema validator with support for custom keywords, vocabularies, and dialects",
5
5
  "type": "module",
6
6
  "main": "./stable/index.js",