@hyperjump/json-schema 1.6.7 → 1.7.0

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