@hyperjump/json-schema 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -7
- package/lib/context-uri.browser.js +1 -0
- package/lib/context-uri.js +4 -0
- package/lib/core.d.ts +1 -1
- package/lib/fetch.js +7 -7
- package/lib/keywords/additionalProperties.js +1 -1
- package/lib/schema.js +12 -8
- package/package.json +7 -2
- package/stable/index.js +11 -10
- package/stable/meta/applicator.js +1 -1
- package/stable/meta/content.js +1 -1
- package/stable/meta/core.js +1 -1
- package/stable/meta/format-annotation.js +1 -1
- package/stable/meta/format-assertion.js +1 -1
- package/stable/meta/meta-data.js +1 -1
- package/stable/meta/unevaluated.js +1 -1
- package/stable/meta/validation.js +1 -1
- package/stable/validation.js +1 -1
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ A collection of modules for working with JSON Schemas.
|
|
|
18
18
|
* Provides utilities for working with annotations
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
|
-
Includes support for node.js (ES Modules, TypeScript) and browsers (works
|
|
22
|
-
CSP
|
|
21
|
+
Includes support for node.js/bun.js (ES Modules, TypeScript) and browsers (works
|
|
22
|
+
with CSP
|
|
23
23
|
[`unsafe-eval`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions)).
|
|
24
24
|
|
|
25
25
|
### Node.js
|
|
@@ -42,6 +42,16 @@ configuration.
|
|
|
42
42
|
]
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
+
### TypeScript
|
|
46
|
+
This package uses the package.json "exports" field. [TypeScript understands
|
|
47
|
+
"exports"](https://devblogs.microsoft.com/typescript/announcing-typescript-4-5-beta/#packagejson-exports-imports-and-self-referencing),
|
|
48
|
+
but you need to change a couple settings in your `tsconfig.json` for it to work.
|
|
49
|
+
|
|
50
|
+
```jsonc
|
|
51
|
+
"module": "Node16", // or "NodeNext"
|
|
52
|
+
"moduleResolution": "Node16", // or "NodeNext"
|
|
53
|
+
```
|
|
54
|
+
|
|
45
55
|
### Versioning
|
|
46
56
|
The API for this library is divided into two categories: Stable and
|
|
47
57
|
Experimental. The Stable API strictly follows semantic versioning, but the
|
|
@@ -98,20 +108,30 @@ const output2 = isString(42);
|
|
|
98
108
|
|
|
99
109
|
**Fetching schemas**
|
|
100
110
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
has an identifier with an http(s) scheme (**https**://example.com), it's not
|
|
104
|
-
allowed to reference schemas with a file scheme
|
|
105
|
-
(**file**:///path/to/my/schemas).
|
|
111
|
+
Schemas that are available on the web can be loaded automatically without
|
|
112
|
+
needing to load them manually.
|
|
106
113
|
|
|
107
114
|
```javascript
|
|
108
115
|
const output = await validate("http://example.com/schemas/string", "foo");
|
|
109
116
|
```
|
|
110
117
|
|
|
118
|
+
When running on the server, you can also load schemas directly from the
|
|
119
|
+
filesystem using `file:` URIs. When fetching from the file system, there are
|
|
120
|
+
limitations for security reasons. If your schema has an identifier with an
|
|
121
|
+
http(s) scheme (**https**://example.com), it's not allowed to reference schemas
|
|
122
|
+
with a file scheme (**file**:///path/to/my/schemas).
|
|
123
|
+
|
|
111
124
|
```javascript
|
|
112
125
|
const output = await validate(`file://${__dirname}/string.schema.json`, "foo");
|
|
113
126
|
```
|
|
114
127
|
|
|
128
|
+
If the schema URI is relative, the base URI in the browser is the browser
|
|
129
|
+
location and the base URI on the server is the current working directory.
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
const output = await validate(`./string.schema.json`, "foo");
|
|
133
|
+
```
|
|
134
|
+
|
|
115
135
|
**Media type plugins**
|
|
116
136
|
|
|
117
137
|
There is a plugin system for adding support for different media types. By
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const contextUri = () => document.location.toString();
|
package/lib/core.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export const addSchema: typeof add;
|
|
|
20
20
|
|
|
21
21
|
export type Validator = (value: unknown, outputFormat?: OutputFormat) => OutputUnit;
|
|
22
22
|
|
|
23
|
-
export type OutputFormat = "FLAG" | "BASIC" | "DETAILED" | "VERBOSE"
|
|
23
|
+
export type OutputFormat = "FLAG" | "BASIC" | "DETAILED" | "VERBOSE";
|
|
24
24
|
|
|
25
25
|
export type OutputUnit = {
|
|
26
26
|
keyword: string;
|
package/lib/fetch.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createReadStream } from "node:fs";
|
|
2
|
+
import { Readable } from "node:stream";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
import { fetch, Response } from "undici";
|
|
3
|
-
import Url from "url";
|
|
4
5
|
import * as MediaTypes from "./media-types.js";
|
|
5
6
|
|
|
6
7
|
|
|
7
|
-
export default
|
|
8
|
+
export default (url, options) => {
|
|
8
9
|
if (url.startsWith("file://")) {
|
|
9
|
-
const filePath =
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const response = new Response(stream, {
|
|
10
|
+
const filePath = fileURLToPath(url);
|
|
11
|
+
const stream = createReadStream(filePath);
|
|
12
|
+
const response = new Response(Readable.toWeb(stream), {
|
|
13
13
|
headers: { "Content-Type": MediaTypes.getContentType(filePath) }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(response, "url", { value: url });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { concat, join, empty, map, filter, every, pipe
|
|
1
|
+
import { concat, join, empty, map, filter, every, pipe } from "@hyperjump/pact";
|
|
2
2
|
import * as Schema from "../schema.js";
|
|
3
3
|
import * as Instance from "../instance.js";
|
|
4
4
|
import { getKeywordName } from "../keywords.js";
|
package/lib/schema.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { nil as nilPointer, append as pointerAppend, get as pointerGet } from "@hyperjump/json-pointer";
|
|
2
2
|
import { toAbsoluteIri } from "@hyperjump/uri";
|
|
3
3
|
import { jsonTypeOf, resolveUri, uriFragment, pathRelative, jsonStringify } from "./common.js";
|
|
4
|
+
import { contextUri } from "./context-uri.js";
|
|
4
5
|
import fetch from "./fetch.js";
|
|
5
6
|
import { hasDialect, loadDialect, getKeywordName } from "./keywords.js";
|
|
6
7
|
import { parseResponse, acceptableMediaTypes } from "./media-types.js";
|
|
@@ -11,13 +12,14 @@ import * as Reference from "./reference.js";
|
|
|
11
12
|
const schemaStore = {};
|
|
12
13
|
const schemaStoreAlias = {};
|
|
13
14
|
|
|
14
|
-
const defaultDialectId = "https://json-schema.org/validation";
|
|
15
|
-
|
|
16
15
|
export const add = (schema, retrievalUri = undefined, contextDialectId = undefined) => {
|
|
17
16
|
schema = JSON.parse(JSON.stringify(schema));
|
|
18
17
|
|
|
19
18
|
// Dialect / JSON Schema Version
|
|
20
|
-
|
|
19
|
+
if ((typeof schema !== "object" || !("$schema" in schema)) && !contextDialectId) {
|
|
20
|
+
throw Error("Unable to determine a dialect for the schema. The dialect can be declared in a number of ways, but the recommended way is to use the '$schema' keyword in your schema.");
|
|
21
|
+
}
|
|
22
|
+
const dialectId = toAbsoluteIri(schema.$schema || contextDialectId);
|
|
21
23
|
delete schema.$schema;
|
|
22
24
|
|
|
23
25
|
if (!hasDialect(dialectId)) {
|
|
@@ -159,7 +161,7 @@ const nil = {
|
|
|
159
161
|
};
|
|
160
162
|
|
|
161
163
|
export const get = async (url, contextDoc = nil) => {
|
|
162
|
-
const resolvedUrl = resolveUri(url, contextDoc.id);
|
|
164
|
+
const resolvedUrl = resolveUri(url, contextDoc.id || contextUri());
|
|
163
165
|
const id = toAbsoluteIri(resolvedUrl);
|
|
164
166
|
const fragment = uriFragment(resolvedUrl);
|
|
165
167
|
|
|
@@ -173,9 +175,11 @@ export const get = async (url, contextDoc = nil) => {
|
|
|
173
175
|
const [schema, contextDialectId] = await parseResponse(response);
|
|
174
176
|
|
|
175
177
|
// Try to determine the dialect from the meta-schema if it isn't already known
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
if (schema.$schema || contextDialectId) {
|
|
179
|
+
const dialectId = toAbsoluteIri(schema.$schema || contextDialectId);
|
|
180
|
+
if (!hasDialect(dialectId) && !hasStoredSchema(dialectId)) {
|
|
181
|
+
await get(dialectId);
|
|
182
|
+
}
|
|
179
183
|
}
|
|
180
184
|
|
|
181
185
|
add(schema, id, contextDialectId);
|
|
@@ -272,7 +276,7 @@ export const toSchema = (schemaDoc, options = {}) => {
|
|
|
272
276
|
dynamicAnchors[pointer] = anchor;
|
|
273
277
|
}
|
|
274
278
|
|
|
275
|
-
const schema = JSON.parse(jsonStringify(schemaDoc.schema, (
|
|
279
|
+
const schema = JSON.parse(jsonStringify(schemaDoc.schema, (_key, value, pointer) => {
|
|
276
280
|
if (Reference.isReference(value)) {
|
|
277
281
|
const refValue = Reference.value(value);
|
|
278
282
|
if (fullOptions.includeEmbedded || !(idToken in refValue)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperjump/json-schema",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "A JSON Schema validator with support for custom keywords, vocabularies, and dialects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./stable/index.js",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"./bundle": "./bundle/index.js"
|
|
22
22
|
},
|
|
23
23
|
"browser": {
|
|
24
|
-
"./lib/fetch.js": "./lib/fetch.browser.js"
|
|
24
|
+
"./lib/fetch.js": "./lib/fetch.browser.js",
|
|
25
|
+
"./lib/context-uri.js": "./lib/context-uri.browser.js"
|
|
25
26
|
},
|
|
26
27
|
"scripts": {
|
|
27
28
|
"clean": "xargs -a .gitignore rm -rf",
|
|
@@ -31,10 +32,13 @@
|
|
|
31
32
|
"repository": "github:hyperjump-io/json-schema",
|
|
32
33
|
"keywords": [
|
|
33
34
|
"JSON Schema",
|
|
35
|
+
"json-schema",
|
|
36
|
+
"jsonschema",
|
|
34
37
|
"JSON",
|
|
35
38
|
"Schema",
|
|
36
39
|
"2020-12",
|
|
37
40
|
"2019-09",
|
|
41
|
+
"draft-07",
|
|
38
42
|
"draft-06",
|
|
39
43
|
"draft-04",
|
|
40
44
|
"vocabulary",
|
|
@@ -49,6 +53,7 @@
|
|
|
49
53
|
"devDependencies": {
|
|
50
54
|
"@types/chai": "*",
|
|
51
55
|
"@types/mocha": "*",
|
|
56
|
+
"@types/node": "^20.6.2",
|
|
52
57
|
"@typescript-eslint/eslint-plugin": "*",
|
|
53
58
|
"@typescript-eslint/parser": "*",
|
|
54
59
|
"chai": "*",
|
package/stable/index.js
CHANGED
|
@@ -97,7 +97,8 @@ defineVocabulary("https://json-schema.org/vocab/unevaluated", {
|
|
|
97
97
|
"unevaluatedProperties": "https://json-schema.org/keyword/unevaluatedProperties"
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
const dialectId = "https://json-schema.org/validation";
|
|
101
|
+
loadDialect(dialectId, {
|
|
101
102
|
"https://json-schema.org/vocab/core": true,
|
|
102
103
|
"https://json-schema.org/vocab/applicator": true,
|
|
103
104
|
"https://json-schema.org/vocab/validation": true,
|
|
@@ -107,14 +108,14 @@ loadDialect("https://json-schema.org/validation", {
|
|
|
107
108
|
"https://json-schema.org/vocab/unevaluated": true
|
|
108
109
|
});
|
|
109
110
|
|
|
110
|
-
addSchema(metaSchema);
|
|
111
|
-
addSchema(coreMetaSchema);
|
|
112
|
-
addSchema(applicatorMetaSchema);
|
|
113
|
-
addSchema(validationMetaSchema);
|
|
114
|
-
addSchema(metaDataMetaSchema);
|
|
115
|
-
addSchema(formatAnnotationMetaSchema);
|
|
116
|
-
addSchema(formatAssertionMetaSchema);
|
|
117
|
-
addSchema(contentMetaSchema);
|
|
118
|
-
addSchema(unevaluatedMetaSchema);
|
|
111
|
+
addSchema(metaSchema, dialectId);
|
|
112
|
+
addSchema(coreMetaSchema, "https://json-schema.org/meta/core");
|
|
113
|
+
addSchema(applicatorMetaSchema, "https://json-schema.org/meta/applicator");
|
|
114
|
+
addSchema(validationMetaSchema, "https://json-schema.org/meta/validation");
|
|
115
|
+
addSchema(metaDataMetaSchema, "https://json-schema.org/meta/meta-data");
|
|
116
|
+
addSchema(formatAnnotationMetaSchema, "https://json-schema.org/meta/format-annotation");
|
|
117
|
+
addSchema(formatAssertionMetaSchema, "https://json-schema.org/meta/format-assertion");
|
|
118
|
+
addSchema(contentMetaSchema, "https://json-schema.org/meta/content");
|
|
119
|
+
addSchema(unevaluatedMetaSchema, "https://json-schema.org/meta/unevaluated");
|
|
119
120
|
|
|
120
121
|
export * from "../lib/index.js";
|
package/stable/meta/content.js
CHANGED
package/stable/meta/core.js
CHANGED
package/stable/meta/meta-data.js
CHANGED
package/stable/validation.js
CHANGED