@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
@@ -1,4 +1,4 @@
1
- import jsonStringify from "fastest-stable-stringify";
1
+ import jsonStringify from "json-stringify-deterministic";
2
2
  import { pipe, asyncMap, asyncCollectArray } from "@hyperjump/pact";
3
3
  import * as Browser from "@hyperjump/browser";
4
4
  import * as Instance from "../instance.js";
@@ -13,6 +13,9 @@ const compile = (schema) => pipe(
13
13
  asyncCollectArray
14
14
  );
15
15
 
16
- const interpret = (enum_, instance) => enum_.some((enumValue) => jsonStringify(Instance.value(instance)) === enumValue);
16
+ const interpret = (enum_, instance) => {
17
+ const instanceValue = jsonStringify(Instance.value(instance));
18
+ return enum_.some((enumValue) => instanceValue === enumValue);
19
+ };
17
20
 
18
21
  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/examples", ...metaData };
5
+ const id = "https://json-schema.org/keyword/examples";
6
+
7
+ const compile = (schema) => Browser.value(schema);
8
+
9
+ const interpret = (examples, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
10
+ Instance.setAnnotation(instance, id, schemaLocation, examples);
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/format", ...metaData };
5
+ const id = "https://json-schema.org/keyword/format";
6
+
7
+ const compile = (schema) => Browser.value(schema);
8
+
9
+ const interpret = (format, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
10
+ Instance.setAnnotation(instance, id, schemaLocation, format);
11
+ return true;
12
+ };
13
+
14
+ export default { id, compile, interpret };
@@ -1,4 +1,4 @@
1
- import { pipe, drop, every } from "@hyperjump/pact";
1
+ import { drop } 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";
@@ -19,11 +19,14 @@ const interpret = ([numberOfPrefixItems, items], instance, ast, dynamicAnchors,
19
19
  return true;
20
20
  }
21
21
 
22
- return pipe(
23
- Instance.iter(instance),
24
- drop(numberOfPrefixItems),
25
- every((item) => Validation.interpret(items, item, ast, dynamicAnchors, quiet))
26
- );
22
+ let isValid = true;
23
+ for (const item of drop(numberOfPrefixItems, Instance.iter(instance))) {
24
+ if (!Validation.interpret(items, item, ast, dynamicAnchors, quiet)) {
25
+ isValid = false;
26
+ }
27
+ }
28
+
29
+ return isValid;
27
30
  };
28
31
 
29
32
  const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
@@ -1,4 +1,8 @@
1
- import metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
2
 
3
3
 
4
- export default { id: "https://json-schema.org/keyword/maxContains", ...metaData };
4
+ const id = "https://json-schema.org/keyword/maxContains";
5
+ const compile = (schema) => Browser.value(schema);
6
+ const interpret = () => true;
7
+
8
+ export default { id, compile, interpret };
@@ -5,6 +5,8 @@ import * as Instance from "../instance.js";
5
5
  const id = "https://json-schema.org/keyword/maxItems";
6
6
 
7
7
  const compile = (schema) => Browser.value(schema);
8
- const interpret = (maxItems, instance) => Instance.typeOf(instance) !== "array" || Instance.length(instance) <= maxItems;
8
+ const interpret = (maxItems, instance) => {
9
+ return Instance.typeOf(instance) !== "array" || Instance.length(instance) <= maxItems;
10
+ };
9
11
 
10
12
  export default { id, compile, interpret };
@@ -5,6 +5,8 @@ import * as Instance from "../instance.js";
5
5
  const id = "https://json-schema.org/keyword/maxLength";
6
6
 
7
7
  const compile = (schema) => Browser.value(schema);
8
- const interpret = (maxLength, instance) => Instance.typeOf(instance) !== "string" || [...Instance.value(instance)].length <= maxLength;
8
+ const interpret = (maxLength, instance) => {
9
+ return Instance.typeOf(instance) !== "string" || [...Instance.value(instance)].length <= maxLength;
10
+ };
9
11
 
10
12
  export default { id, compile, interpret };
@@ -1,4 +1,8 @@
1
- import metaData from "./meta-data.js";
1
+ import * as Browser from "@hyperjump/browser";
2
2
 
3
3
 
4
- export default { id: "https://json-schema.org/keyword/minContains", ...metaData };
4
+ const id = "https://json-schema.org/keyword/minContains";
5
+ const compile = (schema) => Browser.value(schema);
6
+ const interpret = () => true;
7
+
8
+ export default { id, compile, interpret };
@@ -5,6 +5,8 @@ import * as Instance from "../instance.js";
5
5
  const id = "https://json-schema.org/keyword/minItems";
6
6
 
7
7
  const compile = (schema) => Browser.value(schema);
8
- const interpret = (minItems, instance) => Instance.typeOf(instance) !== "array" || Instance.length(instance) >= minItems;
8
+ const interpret = (minItems, instance) => {
9
+ return Instance.typeOf(instance) !== "array" || Instance.length(instance) >= minItems;
10
+ };
9
11
 
10
12
  export default { id, compile, interpret };
@@ -5,6 +5,8 @@ import * as Instance from "../instance.js";
5
5
  const id = "https://json-schema.org/keyword/minLength";
6
6
 
7
7
  const compile = (schema) => Browser.value(schema);
8
- const interpret = (minLength, instance) => Instance.typeOf(instance) !== "string" || [...Instance.value(instance)].length >= minLength;
8
+ const interpret = (minLength, instance) => {
9
+ return Instance.typeOf(instance) !== "string" || [...Instance.value(instance)].length >= minLength;
10
+ };
9
11
 
10
12
  export default { id, compile, interpret };
@@ -17,10 +17,6 @@ const interpret = (oneOf, instance, ast, dynamicAnchors, quiet) => {
17
17
  if (Validation.interpret(schemaUrl, instance, ast, dynamicAnchors, quiet)) {
18
18
  validCount++;
19
19
  }
20
-
21
- if (validCount > 1) {
22
- break;
23
- }
24
20
  }
25
21
 
26
22
  return validCount === 1;
@@ -5,6 +5,8 @@ import * as Instance from "../instance.js";
5
5
  const id = "https://json-schema.org/keyword/pattern";
6
6
 
7
7
  const compile = (schema) => new RegExp(Browser.value(schema), "u");
8
- const interpret = (pattern, instance) => Instance.typeOf(instance) !== "string" || pattern.test(Instance.value(instance));
8
+ const interpret = (pattern, instance) => {
9
+ return Instance.typeOf(instance) !== "string" || pattern.test(Instance.value(instance));
10
+ };
9
11
 
10
12
  export default { id, compile, interpret };
@@ -1,4 +1,4 @@
1
- import { pipe, asyncMap, asyncCollectArray, filter, every } from "@hyperjump/pact";
1
+ import { pipe, asyncMap, asyncCollectArray } from "@hyperjump/pact";
2
2
  import * as Browser from "@hyperjump/browser";
3
3
  import * as Instance from "../instance.js";
4
4
  import { Validation } from "../experimental.js";
@@ -16,13 +16,21 @@ const compile = (schema, ast) => pipe(
16
16
  );
17
17
 
18
18
  const interpret = (patternProperties, instance, ast, dynamicAnchors, quiet) => {
19
- return Instance.typeOf(instance) !== "object" || patternProperties.every(([pattern, schemaUrl]) => {
20
- return pipe(
21
- Instance.entries(instance),
22
- filter(([propertyName]) => pattern.test(propertyName)),
23
- every(([, propertyValue]) => Validation.interpret(schemaUrl, propertyValue, ast, dynamicAnchors, quiet))
24
- );
25
- });
19
+ if (Instance.typeOf(instance) !== "object") {
20
+ return true;
21
+ }
22
+
23
+ let isValid = true;
24
+ for (const [pattern, schemaUri] of patternProperties) {
25
+ for (const [propertyNameNode, propertyValue] of Instance.entries(instance)) {
26
+ const propertyName = Instance.value(propertyNameNode);
27
+ if (pattern.test(propertyName) && !Validation.interpret(schemaUri, propertyValue, ast, dynamicAnchors, quiet)) {
28
+ isValid = false;
29
+ }
30
+ }
31
+ }
32
+
33
+ return isValid;
26
34
  };
27
35
 
28
36
  const collectEvaluatedProperties = (patternProperties, instance, ast, dynamicAnchors) => {
@@ -32,7 +40,8 @@ const collectEvaluatedProperties = (patternProperties, instance, ast, dynamicAnc
32
40
 
33
41
  const evaluatedPropertyNames = new Set();
34
42
  for (const [pattern, propertySchema] of patternProperties) {
35
- for (const [propertyName, property] of Instance.entries(instance)) {
43
+ for (const [propertyNameNode, property] of Instance.entries(instance)) {
44
+ const propertyName = Instance.value(propertyNameNode);
36
45
  if (pattern.test(propertyName)) {
37
46
  if (!Validation.interpret(propertySchema, property, ast, dynamicAnchors, true)) {
38
47
  return false;
@@ -1,4 +1,4 @@
1
- import { pipe, asyncMap, asyncCollectArray, every, zip, take } from "@hyperjump/pact";
1
+ import { pipe, asyncMap, asyncCollectArray, zip } from "@hyperjump/pact";
2
2
  import * as Browser from "@hyperjump/browser";
3
3
  import * as Instance from "../instance.js";
4
4
  import { Validation } from "../experimental.js";
@@ -13,11 +13,26 @@ const compile = (schema, ast) => pipe(
13
13
  );
14
14
 
15
15
  const interpret = (prefixItems, instance, ast, dynamicAnchors, quiet) => {
16
- return Instance.typeOf(instance) !== "array" || pipe(
17
- zip(prefixItems, Instance.iter(instance)),
18
- take(Instance.length(instance)),
19
- every(([prefixItem, item]) => Validation.interpret(prefixItem, item, ast, dynamicAnchors, quiet))
20
- );
16
+ if (Instance.typeOf(instance) !== "array") {
17
+ return true;
18
+ }
19
+
20
+ let isValid = true;
21
+ let index = 0;
22
+ const instanceLength = Instance.length(instance);
23
+ for (const [schemaUri, item] of zip(prefixItems, Instance.iter(instance))) {
24
+ if (index >= instanceLength) {
25
+ break;
26
+ }
27
+
28
+ if (!Validation.interpret(schemaUri, item, ast, dynamicAnchors, quiet)) {
29
+ isValid = false;
30
+ }
31
+
32
+ index++;
33
+ }
34
+
35
+ return isValid;
21
36
  };
22
37
 
23
38
  const collectEvaluatedItems = (items, instance, ast, dynamicAnchors) => {
@@ -1,4 +1,4 @@
1
- import { pipe, asyncMap, asyncCollectObject, filter, every } from "@hyperjump/pact";
1
+ import { pipe, asyncMap, asyncCollectObject } from "@hyperjump/pact";
2
2
  import * as Browser from "@hyperjump/browser";
3
3
  import * as Instance from "../instance.js";
4
4
  import { Validation } from "../experimental.js";
@@ -13,11 +13,19 @@ const compile = (schema, ast) => pipe(
13
13
  );
14
14
 
15
15
  const interpret = (properties, instance, ast, dynamicAnchors, quiet) => {
16
- return Instance.typeOf(instance) !== "object" || pipe(
17
- Instance.entries(instance),
18
- filter(([propertyName]) => propertyName in properties),
19
- every(([propertyName, property]) => Validation.interpret(properties[propertyName], property, ast, dynamicAnchors, quiet))
20
- );
16
+ if (Instance.typeOf(instance) !== "object") {
17
+ return true;
18
+ }
19
+
20
+ let isValid = true;
21
+ for (const [propertyNameNode, property] of Instance.entries(instance)) {
22
+ const propertyName = Instance.value(propertyNameNode);
23
+ if (propertyName in properties && !Validation.interpret(properties[propertyName], property, ast, dynamicAnchors, quiet)) {
24
+ isValid = false;
25
+ }
26
+ }
27
+
28
+ return isValid;
21
29
  };
22
30
 
23
31
  const collectEvaluatedProperties = (properties, instance, ast, dynamicAnchors) => {
@@ -26,7 +34,8 @@ const collectEvaluatedProperties = (properties, instance, ast, dynamicAnchors) =
26
34
  }
27
35
 
28
36
  const evaluatedPropertyNames = new Set();
29
- for (const [propertyName, property] of Instance.entries(instance)) {
37
+ for (const [propertyNameNode, property] of Instance.entries(instance)) {
38
+ const propertyName = Instance.value(propertyNameNode);
30
39
  if (propertyName in properties) {
31
40
  if (!Validation.interpret(properties[propertyName], property, ast, dynamicAnchors, true)) {
32
41
  return false;
@@ -21,12 +21,24 @@ const compile = (schema, ast) => {
21
21
  };
22
22
 
23
23
  const interpret = (propertyDependencies, instance, ast, dynamicAnchors, quiet) => {
24
- return Instance.typeOf(instance) !== "object" || Object.entries(propertyDependencies).every(([propertyName, valueMappings]) => {
25
- const propertyValue = Instance.value(instance)[propertyName];
26
- return !Instance.has(propertyName, instance)
27
- || !(propertyValue in valueMappings)
28
- || Validation.interpret(valueMappings[propertyValue], instance, ast, dynamicAnchors, quiet);
29
- });
24
+ if (Instance.typeOf(instance) !== "object") {
25
+ return true;
26
+ }
27
+
28
+ let isValid = true;
29
+ const instanceValue = Instance.value(instance);
30
+ for (const [propertyName, valueMappings] of Object.entries(propertyDependencies)) {
31
+ const propertyValue = instanceValue[propertyName];
32
+ if (
33
+ Instance.has(propertyName, instance)
34
+ && propertyValue in valueMappings
35
+ && !Validation.interpret(valueMappings[propertyValue], instance, ast, dynamicAnchors, quiet)
36
+ ) {
37
+ isValid = false;
38
+ }
39
+ }
40
+
41
+ return isValid;
30
42
  };
31
43
 
32
44
  const collectEvaluatedProperties = (propertyDependencies, instance, ast, dynamicAnchors) => {
@@ -1,6 +1,5 @@
1
- import { every } from "@hyperjump/pact";
2
- import * as Instance from "../instance.js";
3
1
  import { Validation } from "../experimental.js";
2
+ import * as Instance from "../instance.js";
4
3
 
5
4
 
6
5
  const id = "https://json-schema.org/keyword/propertyNames";
@@ -8,9 +7,18 @@ const id = "https://json-schema.org/keyword/propertyNames";
8
7
  const compile = (schema, ast) => Validation.compile(schema, ast);
9
8
 
10
9
  const interpret = (propertyNames, instance, ast, dynamicAnchors) => {
11
- return Instance.typeOf(instance) !== "object" || every((key) => {
12
- return Validation.interpret(propertyNames, Instance.cons(key), ast, dynamicAnchors, true);
13
- }, Instance.keys(instance));
10
+ if (Instance.typeOf(instance) !== "object") {
11
+ return true;
12
+ }
13
+
14
+ let isValid = true;
15
+ for (const key of Instance.keys(instance)) {
16
+ if (!Validation.interpret(propertyNames, key, ast, dynamicAnchors, true)) {
17
+ isValid = false;
18
+ }
19
+ }
20
+
21
+ return isValid;
14
22
  };
15
23
 
16
24
  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/readOnly", ...metaData };
5
+ const id = "https://json-schema.org/keyword/readOnly";
6
+
7
+ const compile = (schema) => Browser.value(schema);
8
+
9
+ const interpret = (readOnly, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
10
+ Instance.setAnnotation(instance, id, schemaLocation, readOnly);
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/title", ...metaData };
5
+ const id = "https://json-schema.org/keyword/title";
6
+
7
+ const compile = (schema) => Browser.value(schema);
8
+
9
+ const interpret = (title, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
10
+ Instance.setAnnotation(instance, id, schemaLocation, title);
11
+ return true;
12
+ };
13
+
14
+ export default { id, compile, interpret };
@@ -1,6 +1,6 @@
1
- import { pipe, filter, every, zip, range } from "@hyperjump/pact";
2
- import { canonicalUri } from "../schema.js";
1
+ import { zip, range } from "@hyperjump/pact";
3
2
  import * as Instance from "../instance.js";
3
+ import { canonicalUri } from "../schema.js";
4
4
  import { Validation } from "../experimental.js";
5
5
 
6
6
 
@@ -16,11 +16,18 @@ const interpret = ([schemaUrl, unevaluatedItems], instance, ast, dynamicAnchors,
16
16
  }
17
17
 
18
18
  const itemIndexes = Validation.collectEvaluatedItems(schemaUrl, instance, ast, dynamicAnchors, true);
19
- return itemIndexes === false || pipe(
20
- zip(Instance.iter(instance), range(0)),
21
- filter(([, index]) => !itemIndexes.has(index)),
22
- every(([item]) => Validation.interpret(unevaluatedItems, item, ast, dynamicAnchors, quiet))
23
- );
19
+ if (itemIndexes === false) {
20
+ return true;
21
+ }
22
+
23
+ let isValid = true;
24
+ for (const [item, index] of zip(Instance.iter(instance), range(0))) {
25
+ if (!itemIndexes.has(index) && !Validation.interpret(unevaluatedItems, item, ast, dynamicAnchors, quiet)) {
26
+ isValid = false;
27
+ }
28
+ }
29
+
30
+ return isValid;
24
31
  };
25
32
 
26
33
  const collectEvaluatedItems = (keywordValue, instance, ast, dynamicAnchors) => {
@@ -1,6 +1,5 @@
1
- import { pipe, filter, every } from "@hyperjump/pact";
2
- import * as Instance from "../instance.js";
3
1
  import { Validation, canonicalUri } from "../experimental.js";
2
+ import * as Instance from "../instance.js";
4
3
 
5
4
 
6
5
  const id = "https://json-schema.org/keyword/unevaluatedProperties";
@@ -15,12 +14,19 @@ const interpret = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnc
15
14
  }
16
15
 
17
16
  const evaluatedPropertyNames = Validation.collectEvaluatedProperties(schemaUrl, instance, ast, dynamicAnchors, true);
17
+ if (evaluatedPropertyNames === false) {
18
+ return true;
19
+ }
20
+
21
+ let isValid = true;
22
+ for (const [propertyNameNode, property] of Instance.entries(instance)) {
23
+ const propertyName = Instance.value(propertyNameNode);
24
+ if (!evaluatedPropertyNames.has(propertyName) && !Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors, quiet)) {
25
+ isValid = false;
26
+ }
27
+ }
18
28
 
19
- return !evaluatedPropertyNames || pipe(
20
- Instance.entries(instance),
21
- filter(([propertyName]) => !evaluatedPropertyNames.has(propertyName)),
22
- every(([, property]) => Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors, quiet))
23
- );
29
+ return isValid;
24
30
  };
25
31
 
26
32
  const collectEvaluatedProperties = ([schemaUrl, unevaluatedProperties], instance, ast, dynamicAnchors) => {
@@ -34,7 +40,8 @@ const collectEvaluatedProperties = ([schemaUrl, unevaluatedProperties], instance
34
40
  return false;
35
41
  }
36
42
 
37
- for (const [propertyName, property] of Instance.entries(instance)) {
43
+ for (const [propertyNameNode, property] of Instance.entries(instance)) {
44
+ const propertyName = Instance.value(propertyNameNode);
38
45
  if (!evaluatedPropertyNames.has(propertyName)) {
39
46
  if (!Validation.interpret(unevaluatedProperties, property, ast, dynamicAnchors, true)) {
40
47
  return false;
@@ -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/unknown", ...metaData };
5
+ const id = "https://json-schema.org/keyword/unknown";
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 };
@@ -1,8 +1,7 @@
1
1
  import { value, entries } from "@hyperjump/browser";
2
2
  import { pipe, asyncMap, asyncCollectArray } from "@hyperjump/pact";
3
3
  import { append as pointerAppend } from "@hyperjump/json-pointer";
4
- import { publishAsync, publish } from "../pubsub.js";
5
- import * as Instance from "../instance.js";
4
+ import { publishAsync } from "../pubsub.js";
6
5
  import { toAbsoluteUri } from "../common.js";
7
6
  import { canonicalUri, getKeyword, getKeywordByName } from "../experimental.js";
8
7
 
@@ -47,31 +46,29 @@ const compile = async (schema, ast) => {
47
46
  const interpret = (url, instance, ast, dynamicAnchors, quiet = false) => {
48
47
  dynamicAnchors = { ...ast.metaData[toAbsoluteUri(url)].dynamicAnchors, ...dynamicAnchors };
49
48
 
50
- !quiet && publish("result.start");
51
- const isValid = typeof ast[url] === "boolean" ? ast[url] : ast[url].every(([keywordId, schemaUrl, keywordValue]) => {
52
- !quiet && publish("result.start");
53
- const isValid = getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors, quiet);
54
-
55
- !quiet && publish("result", {
56
- keyword: keywordId,
57
- absoluteKeywordLocation: schemaUrl,
58
- instanceLocation: Instance.uri(instance),
59
- valid: isValid,
60
- ast: keywordValue
61
- });
62
- !quiet && publish("result.end");
63
- return isValid;
64
- });
65
-
66
- !quiet && publish("result", {
67
- keyword: id,
68
- absoluteKeywordLocation: url,
69
- instanceLocation: Instance.uri(instance),
70
- valid: isValid,
71
- ast: url
72
- });
73
- !quiet && publish("result.end");
74
- return isValid;
49
+ let isSchemaValid = true;
50
+ if (typeof ast[url] === "boolean") {
51
+ isSchemaValid = ast[url];
52
+ } else {
53
+ for (const [keywordId, schemaUrl, keywordValue] of ast[url]) {
54
+ instance.valid = getKeyword(keywordId).interpret(keywordValue, instance, ast, dynamicAnchors, quiet, url);
55
+ if (!instance.valid) {
56
+ if (!quiet) {
57
+ instance.errors[schemaUrl] = keywordId;
58
+ }
59
+ isSchemaValid = false;
60
+ }
61
+ }
62
+ }
63
+
64
+ if (!isSchemaValid) {
65
+ if (!quiet) {
66
+ instance.errors[url] = id;
67
+ }
68
+ }
69
+
70
+ instance.valid = isSchemaValid;
71
+ return isSchemaValid;
75
72
  };
76
73
 
77
74
  const emptyPropertyNames = new Set();
@@ -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/writeOnly", ...metaData };
5
+ const id = "https://json-schema.org/keyword/writeOnly";
6
+
7
+ const compile = (schema) => Browser.value(schema);
8
+
9
+ const interpret = (writeOnly, instance, _ast, _dynamicAnchors, _quiet, schemaLocation) => {
10
+ Instance.setAnnotation(instance, id, schemaLocation, writeOnly);
11
+ return true;
12
+ };
13
+
14
+ export default { id, compile, interpret };
package/lib/keywords.js CHANGED
@@ -81,3 +81,8 @@ export const loadDialect = (dialectId, dialect, allowUnknownKeywords = false) =>
81
81
  }
82
82
  });
83
83
  };
84
+
85
+ export const unloadDialect = (dialectId) => {
86
+ delete _allowUnknownKeywords[dialectId];
87
+ delete _dialects[dialectId];
88
+ };
package/lib/output.js ADDED
@@ -0,0 +1,43 @@
1
+ import { allNodes } from "./instance.js";
2
+
3
+
4
+ const outputFormats = {};
5
+
6
+ export const toOutputFormat = (node, outputFormat) => {
7
+ if (outputFormat in outputFormats) {
8
+ return outputFormats[outputFormat](node);
9
+ } else {
10
+ throw Error(`The '${outputFormat}' error format is not supported`);
11
+ }
12
+ };
13
+
14
+ outputFormats.FLAG = (instance) => {
15
+ return { valid: instance.valid };
16
+ };
17
+
18
+ outputFormats.BASIC = (instance) => {
19
+ const output = {
20
+ valid: instance.valid
21
+ };
22
+
23
+ if (!instance.valid) {
24
+ output.errors = [];
25
+
26
+ for (const child of allNodes(instance)) {
27
+ for (const [absoluteKeywordLocation, keyword] of Object.entries(child.errors).reverse()) {
28
+ if (!child.valid) {
29
+ output.errors.unshift({
30
+ keyword,
31
+ absoluteKeywordLocation,
32
+ instanceLocation: child.uri(),
33
+ valid: child.valid
34
+ });
35
+ }
36
+ }
37
+ }
38
+
39
+ output.errors.pop();
40
+ }
41
+
42
+ return output;
43
+ };