@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.
Files changed (63) hide show
  1. package/README.md +61 -56
  2. package/annotations/annotated-instance.d.ts +4 -82
  3. package/annotations/annotated-instance.js +31 -33
  4. package/annotations/index.d.ts +7 -3
  5. package/annotations/index.js +8 -108
  6. package/draft-04/additionalItems.js +1 -1
  7. package/draft-04/items.js +1 -1
  8. package/lib/core.js +8 -50
  9. package/lib/experimental.d.ts +6 -7
  10. package/lib/experimental.js +6 -2
  11. package/lib/index.d.ts +5 -2
  12. package/lib/instance.d.ts +24 -23
  13. package/lib/instance.js +133 -38
  14. package/lib/keywords/additionalProperties.js +12 -7
  15. package/lib/keywords/allOf.js +7 -1
  16. package/lib/keywords/comment.js +4 -3
  17. package/lib/keywords/const.js +1 -1
  18. package/lib/keywords/contentEncoding.js +12 -2
  19. package/lib/keywords/contentMediaType.js +12 -2
  20. package/lib/keywords/contentSchema.js +8 -3
  21. package/lib/keywords/default.js +12 -2
  22. package/lib/keywords/dependentRequired.js +12 -3
  23. package/lib/keywords/dependentSchemas.js +12 -3
  24. package/lib/keywords/deprecated.js +12 -2
  25. package/lib/keywords/description.js +12 -2
  26. package/lib/keywords/enum.js +5 -2
  27. package/lib/keywords/examples.js +12 -2
  28. package/lib/keywords/format.js +12 -2
  29. package/lib/keywords/items.js +9 -6
  30. package/lib/keywords/maxContains.js +6 -2
  31. package/lib/keywords/maxItems.js +3 -1
  32. package/lib/keywords/maxLength.js +3 -1
  33. package/lib/keywords/minContains.js +6 -2
  34. package/lib/keywords/minItems.js +3 -1
  35. package/lib/keywords/minLength.js +3 -1
  36. package/lib/keywords/oneOf.js +0 -4
  37. package/lib/keywords/pattern.js +3 -1
  38. package/lib/keywords/patternProperties.js +18 -9
  39. package/lib/keywords/prefixItems.js +21 -6
  40. package/lib/keywords/properties.js +16 -7
  41. package/lib/keywords/propertyDependencies.js +18 -6
  42. package/lib/keywords/propertyNames.js +13 -5
  43. package/lib/keywords/readOnly.js +12 -2
  44. package/lib/keywords/title.js +12 -2
  45. package/lib/keywords/unevaluatedItems.js +14 -7
  46. package/lib/keywords/unevaluatedProperties.js +15 -8
  47. package/lib/keywords/uniqueItems.js +1 -1
  48. package/lib/keywords/unknown.js +12 -2
  49. package/lib/keywords/validation.js +24 -27
  50. package/lib/keywords/writeOnly.js +12 -2
  51. package/lib/keywords.js +5 -0
  52. package/lib/output.js +43 -0
  53. package/lib/schema.js +4 -2
  54. package/openapi-3-0/discriminator.js +12 -2
  55. package/openapi-3-0/example.js +12 -2
  56. package/openapi-3-0/externalDocs.js +12 -2
  57. package/openapi-3-0/index.js +2 -2
  58. package/openapi-3-0/nullable.js +8 -2
  59. package/openapi-3-0/xml.js +12 -2
  60. package/openapi-3-1/index.js +2 -2
  61. package/package.json +3 -3
  62. package/bundle/README.md +0 -134
  63. 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, unsubscribe } from "./pubsub.js";
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", DETAILED = "DETAILED", VERBOSE = "VERBOSE";
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.cons(value), outputFormat);
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 }, value, outputFormat = FLAG) => {
34
- if (![FLAG, BASIC, DETAILED, VERBOSE].includes(outputFormat)) {
35
- throw Error(`The '${outputFormat}' error format is not supported`);
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.cons(schema.document.root, schema.document.baseUri);
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);
@@ -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 { JsonDocument } from "./instance.js";
3
+ import type { JsonNode } from "./instance.js";
4
4
 
5
5
 
6
6
  // Compile/interpret
7
- export const compile: (url: string) => Promise<CompiledSchema>;
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: JsonDocument, ast: AST, dynamicAnchors: Anchors) => boolean;
72
- collectEvaluatedProperties?: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors, isTop?: boolean) => Set<string> | false;
73
- collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors, isTop?: boolean) => Set<number> | false;
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
  };
@@ -1,4 +1,8 @@
1
- export { compile, interpret, BASIC, DETAILED, VERBOSE } from "./core.js";
2
- export { getKeyword, getKeywordByName, addKeyword, defineVocabulary, getKeywordName, getKeywordId, loadDialect, hasDialect } from "./keywords.js";
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: unknown, outputFormat?: OutputFormat) => Promise<OutputUnit>
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: unknown, outputFormat?: OutputFormat) => OutputUnit;
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 { JsonType } from "./common.js";
2
- import type { Json, JsonObject } from "@hyperjump/json-pointer";
1
+ import type { Json } from "@hyperjump/json-pointer";
3
2
 
4
3
 
5
- export const nil: JsonDocument<undefined>;
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
- type MapFn<A> = (element: JsonDocument, index: number) => A;
20
- type ForEachFn = (element: JsonDocument, index: number) => void;
21
- type FilterFn = (element: JsonDocument, index: number) => boolean;
22
- type ReduceFn<A> = (accumulator: A, currentValue: JsonDocument, index: number) => A;
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 type JsonDocument<A extends Json | undefined = Json> = {
25
- id: string;
18
+ export const allNodes: (node) => Generator<JsonNode>;
19
+
20
+ export type JsonNode = {
21
+ baseUri: string;
26
22
  pointer: string;
27
- instance: Json;
28
- value: A;
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 { append as pointerAppend, get as pointerGet } from "@hyperjump/json-pointer";
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 nil = { id: undefined, pointer: "", instance: undefined, value: undefined };
8
- export const cons = (instance, id = undefined) => ({
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
- export const get = (url, instance = nil) => {
16
- if (!url.startsWith("#")) {
17
- throw Error(`No JSON document found at '${url.split("#")[0]}'`);
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
- const pointer = uriFragment(url);
21
- return {
22
- ...instance,
43
+ const cons = (baseUri, pointer, value, type, children, parent) => {
44
+ const node = {
45
+ baseUri: baseUri ? toAbsoluteIri(baseUri) : "",
23
46
  pointer: pointer,
24
- value: pointerGet(pointer, instance.instance)
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 uri = (doc) => `${doc.id || ""}#${encodeURI(doc.pointer)}`;
29
- export const value = (doc) => doc.value instanceof Reference ? doc.value.toJSON() : doc.value;
30
- export const has = (key, doc) => key in value(doc);
31
- export const typeOf = (doc) => jsonTypeOf(value(doc));
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 step = (key, doc) => ({
34
- ...doc,
35
- pointer: pointerAppend(key, doc.pointer),
36
- value: value(doc)[key]
37
- });
105
+ export const keys = function* (node) {
106
+ if (node.type !== "object") {
107
+ return;
108
+ }
38
109
 
39
- export const iter = function* (doc) {
40
- for (let index = 0; index < value(doc).length; index++) {
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 keys = function* (doc) {
46
- for (const key in value(doc)) {
47
- yield key;
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 values = function* (doc) {
52
- for (const key in value(doc)) {
53
- yield step(key, doc);
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 entries = function* (doc) {
58
- for (const key in value(doc)) {
59
- yield [key, step(key, doc)];
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 length = (doc) => value(doc).length;
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, filter, every, pipe } from "@hyperjump/pact";
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
- return pipe(
40
- Instance.entries(instance),
41
- filter(([propertyName]) => !isDefinedProperty.test(propertyName)),
42
- every(([, property]) => Validation.interpret(additionalProperties, property, ast, dynamicAnchors, quiet))
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 [propertyName, property] of Instance.entries(instance)) {
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;
@@ -12,7 +12,13 @@ const compile = (schema, ast) => pipe(
12
12
  );
13
13
 
14
14
  const interpret = (allOf, instance, ast, dynamicAnchors, quiet) => {
15
- return allOf.every((schemaUrl) => Validation.interpret(schemaUrl, instance, ast, dynamicAnchors, quiet));
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) => {
@@ -1,4 +1,5 @@
1
- import metaData from "./meta-data.js";
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 };
@@ -1,4 +1,4 @@
1
- import jsonStringify from "fastest-stable-stringify";
1
+ import jsonStringify from "json-stringify-deterministic";
2
2
  import * as Browser from "@hyperjump/browser";
3
3
  import * as Instance from "../instance.js";
4
4
 
@@ -1,4 +1,14 @@
1
- import metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../../annotations/annotated-instance.js";
2
3
 
3
4
 
4
- export default { id: "https://json-schema.org/keyword/contentEncoding", ...metaData };
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 metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../../annotations/annotated-instance.js";
2
3
 
3
4
 
4
- export default { id: "https://json-schema.org/keyword/contentMediaType", ...metaData };
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 * as Schema from "../schema.js";
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) => Schema.canonicalUri(contentSchema);
7
- const interpret = () => true;
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 };
@@ -1,4 +1,14 @@
1
- import metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../../annotations/annotated-instance.js";
2
3
 
3
4
 
4
- export default { id: "https://json-schema.org/keyword/default", ...metaData };
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
- return Instance.typeOf(instance) !== "object" || dependentRequired.every(([propertyName, required]) => {
16
- return !Instance.has(propertyName, instance) || required.every((key) => Instance.has(key, instance));
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
- return Instance.typeOf(instance) !== "object" || dependentSchemas.every(([propertyName, dependentSchema]) => {
17
- return !Instance.has(propertyName, instance) || Validation.interpret(dependentSchema, instance, ast, dynamicAnchors, quiet);
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 metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../../annotations/annotated-instance.js";
2
3
 
3
4
 
4
- export default { id: "https://json-schema.org/keyword/deprecated", ...metaData };
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 metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
+ import * as Instance from "../../annotations/annotated-instance.js";
2
3
 
3
4
 
4
- export default { id: "https://json-schema.org/keyword/description", ...metaData };
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 };