@hyperjump/json-schema 1.4.1 → 1.4.3

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/lib/common.js CHANGED
@@ -22,7 +22,12 @@ export const resolveUri = (uri, baseUri) => {
22
22
  return resolved;
23
23
  };
24
24
 
25
- export const toAbsoluteUri = (uri) => toAbsoluteIri(uri);
25
+ export const toAbsoluteUri = (uri) => {
26
+ const position = uri.indexOf("#");
27
+ const end = position === -1 ? uri.length : position;
28
+ return uri.slice(0, end);
29
+ };
30
+
26
31
  export const uriFragment = (uri) => decodeURIComponent(parseIriReference(uri).fragment || "");
27
32
 
28
33
  const CHAR_BACKWARD_SLASH = 47;
package/lib/instance.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import { append as pointerAppend } from "@hyperjump/json-pointer";
2
+ import { toAbsoluteIri } from "@hyperjump/uri";
2
3
  import curry from "just-curry-it";
3
- import { toAbsoluteUri, jsonTypeOf } from "./common.js";
4
+ import { jsonTypeOf } from "./common.js";
4
5
  import * as Reference from "./reference.js";
5
6
 
6
7
 
7
8
  export const nil = { id: undefined, pointer: "", instance: undefined, value: undefined };
8
9
  export const cons = (instance, id = undefined) => ({
9
10
  ...nil,
10
- id: id ? toAbsoluteUri(id) : "",
11
+ id: id ? toAbsoluteIri(id) : "",
11
12
  instance,
12
13
  value: instance
13
14
  });
package/lib/keywords.js CHANGED
@@ -1,5 +1,8 @@
1
+ import { toAbsoluteUri } from "./common.js";
2
+
3
+
1
4
  const _keywords = {};
2
- export const getKeyword = (id) => _keywords[id];
5
+ export const getKeyword = (id) => _keywords[toAbsoluteUri(id)];
3
6
 
4
7
  export const addKeyword = (keywordHandler) => {
5
8
  _keywords[keywordHandler.id] = keywordHandler;
@@ -13,7 +16,7 @@ export const defineVocabulary = (id, keywords) => {
13
16
  const _dialects = {};
14
17
  const _allowUnknownKeywords = {};
15
18
  export const getKeywordId = (dialectId, keyword) => _dialects[dialectId]?.[keyword]
16
- || _allowUnknownKeywords[dialectId] && "https://json-schema.org/keyword/unknown";
19
+ || (_allowUnknownKeywords[dialectId] || keyword[0] === "@") && `https://json-schema.org/keyword/unknown#${keyword}`;
17
20
  export const getKeywordName = (dialectId, keywordId) => {
18
21
  for (const keyword in _dialects[dialectId]) {
19
22
  if (_dialects[dialectId][keyword] === keywordId) {
@@ -35,7 +38,7 @@ export const loadDialect = (dialectId, dialect, allowUnknownKeywords = false) =>
35
38
  .forEach(([keyword, keywordId]) => {
36
39
  if (!(keywordId in _keywords) && !isRequired) {
37
40
  // Allow keyword to be ignored
38
- keywordId = "https://json-schema.org/keyword/unknown";
41
+ keywordId = `https://json-schema.org/keyword/unknown#${keyword}`;
39
42
  }
40
43
  _dialects[dialectId][keyword] = keywordId;
41
44
  });
package/lib/schema.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import curry from "just-curry-it";
2
2
  import * as Pact from "@hyperjump/pact";
3
3
  import { nil as nilPointer, append as pointerAppend, get as pointerGet } from "@hyperjump/json-pointer";
4
- import { jsonTypeOf, resolveUri, toAbsoluteUri, uriFragment, pathRelative, jsonStringify } from "./common.js";
4
+ import { toAbsoluteIri } from "@hyperjump/uri";
5
+ import { jsonTypeOf, resolveUri, uriFragment, pathRelative, jsonStringify } from "./common.js";
5
6
  import fetch from "./fetch.js";
6
7
  import { hasDialect, loadDialect, getKeywordName } from "./keywords.js";
7
8
  import { parseResponse, acceptableMediaTypes } from "./media-types.js";
@@ -18,7 +19,7 @@ export const add = (schema, retrievalUri = undefined, contextDialectId = undefin
18
19
  schema = JSON.parse(JSON.stringify(schema));
19
20
 
20
21
  // Dialect / JSON Schema Version
21
- const dialectId = toAbsoluteUri(schema.$schema || contextDialectId || defaultDialectId);
22
+ const dialectId = toAbsoluteIri(schema.$schema || contextDialectId || defaultDialectId);
22
23
  delete schema.$schema;
23
24
 
24
25
  if (!hasDialect(dialectId)) {
@@ -32,10 +33,10 @@ export const add = (schema, retrievalUri = undefined, contextDialectId = undefin
32
33
  throw Error(`Unable to determine an identifier for the schema. Use the '${idToken}' keyword or pass a retrievalUri when loading the schema.`);
33
34
  }
34
35
  const internalUrl = resolveUri(schema[idToken] || retrievalUri, retrievalUri);
35
- const id = toAbsoluteUri(internalUrl);
36
+ const id = toAbsoluteIri(internalUrl);
36
37
  delete schema[idToken];
37
38
  if (retrievalUri) {
38
- const externalId = toAbsoluteUri(retrievalUri);
39
+ const externalId = toAbsoluteIri(retrievalUri);
39
40
  schemaStoreAlias[externalId] = id;
40
41
  }
41
42
 
@@ -74,8 +75,21 @@ export const add = (schema, retrievalUri = undefined, contextDialectId = undefin
74
75
 
75
76
  const processSchema = (subject, id, dialectId, pointer, anchors, dynamicAnchors) => {
76
77
  if (jsonTypeOf(subject, "object")) {
78
+ // Embedded Schema
79
+ const embeddedDialectId = typeof subject.$schema === "string" ? toAbsoluteIri(subject.$schema) : dialectId;
80
+ if (!hasDialect(embeddedDialectId)) {
81
+ throw Error(`Encountered unknown dialect '${embeddedDialectId}'`);
82
+ }
83
+
84
+ const idToken = getKeywordName(embeddedDialectId, "https://json-schema.org/keyword/id");
85
+ if (typeof subject[idToken] === "string") {
86
+ subject[idToken] = resolveUri(subject[idToken], id);
87
+ add(subject, undefined, dialectId);
88
+ return Reference.cons(subject[idToken], subject);
89
+ }
90
+
77
91
  // Legacy id
78
- const legacyIdToken = getKeywordName(dialectId, "https://json-schema.org/keyword/draft-04/id");
92
+ const legacyIdToken = getKeywordName(embeddedDialectId, "https://json-schema.org/keyword/draft-04/id");
79
93
  if (typeof subject[legacyIdToken] === "string") {
80
94
  if (subject[legacyIdToken][0] === "#") {
81
95
  const anchor = decodeURIComponent(subject[legacyIdToken].slice(1));
@@ -89,13 +103,10 @@ const processSchema = (subject, id, dialectId, pointer, anchors, dynamicAnchors)
89
103
  delete subject[legacyIdToken];
90
104
  }
91
105
 
92
- // Embedded Schema
93
- const embeddedDialectId = typeof subject.$schema === "string" ? toAbsoluteUri(subject.$schema) : dialectId;
94
- const idToken = getKeywordName(embeddedDialectId, "https://json-schema.org/keyword/id");
95
- if (typeof subject[idToken] === "string") {
96
- subject[idToken] = resolveUri(subject[idToken], id);
97
- add(subject, undefined, dialectId);
98
- return Reference.cons(subject[idToken], subject);
106
+ const dynamicAnchorToken = getKeywordName(dialectId, "https://json-schema.org/keyword/dynamicAnchor");
107
+ if (typeof subject[dynamicAnchorToken] === "string") {
108
+ dynamicAnchors[subject[dynamicAnchorToken]] = `${id}#${encodeURI(pointer)}`;
109
+ delete subject[dynamicAnchorToken];
99
110
  }
100
111
 
101
112
  // Legacy dynamic anchor
@@ -106,12 +117,6 @@ const processSchema = (subject, id, dialectId, pointer, anchors, dynamicAnchors)
106
117
  delete subject[legacyDynamicAnchorToken];
107
118
  }
108
119
 
109
- const dynamicAnchorToken = getKeywordName(dialectId, "https://json-schema.org/keyword/dynamicAnchor");
110
- if (typeof subject[dynamicAnchorToken] === "string") {
111
- dynamicAnchors[subject[dynamicAnchorToken]] = `${id}#${encodeURI(pointer)}`;
112
- delete subject[dynamicAnchorToken];
113
- }
114
-
115
120
  const anchorToken = getKeywordName(dialectId, "https://json-schema.org/keyword/anchor");
116
121
  if (typeof subject[anchorToken] === "string") {
117
122
  anchors[subject[anchorToken]] = pointer;
@@ -157,7 +162,7 @@ const nil = {
157
162
 
158
163
  export const get = async (url, contextDoc = nil) => {
159
164
  const resolvedUrl = resolveUri(url, contextDoc.id);
160
- const id = toAbsoluteUri(resolvedUrl);
165
+ const id = toAbsoluteIri(resolvedUrl);
161
166
  const fragment = uriFragment(resolvedUrl);
162
167
 
163
168
  if (!hasStoredSchema(id)) {
@@ -170,7 +175,7 @@ export const get = async (url, contextDoc = nil) => {
170
175
  const [schema, contextDialectId] = await parseResponse(response);
171
176
 
172
177
  // Try to determine the dialect from the meta-schema if it isn't already known
173
- const dialectId = toAbsoluteUri(schema.$schema || contextDialectId || defaultDialectId);
178
+ const dialectId = toAbsoluteIri(schema.$schema || contextDialectId || defaultDialectId);
174
179
  if (!hasDialect(dialectId) && !hasStoredSchema(dialectId)) {
175
180
  await get(dialectId);
176
181
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperjump/json-schema",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
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",