@hyperjump/json-schema 0.23.3 → 1.0.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/LICENSE +1 -1
- package/README.md +459 -120
- package/draft-04/additionalItems.js +29 -0
- package/{lib/keywords → draft-04}/dependencies.js +9 -5
- package/draft-04/exclusiveMaximum.js +5 -0
- package/draft-04/exclusiveMinimum.js +5 -0
- package/draft-04/id.js +1 -0
- package/draft-04/index.d.ts +43 -0
- package/draft-04/index.js +69 -0
- package/draft-04/items.js +35 -0
- package/draft-04/maximum.js +26 -0
- package/draft-04/minimum.js +25 -0
- package/draft-04/ref.js +1 -0
- package/draft-04/schema.js +149 -0
- package/draft-06/contains.js +13 -0
- package/draft-06/index.d.ts +47 -0
- package/draft-06/index.js +66 -0
- package/draft-06/schema.js +154 -0
- package/{lib/draft-07.d.ts → draft-07/index.d.ts} +21 -19
- package/draft-07/index.js +72 -0
- package/draft-07/schema.js +172 -0
- package/{lib/keywords/contains-minContains-maxContains.js → draft-2019-09/contains.js} +14 -7
- package/{lib/draft-2019-09.d.ts → draft-2019-09/index.d.ts} +24 -22
- package/draft-2019-09/index.js +117 -0
- package/draft-2019-09/meta/applicator.js +55 -0
- package/draft-2019-09/meta/content.js +17 -0
- package/draft-2019-09/meta/core.js +57 -0
- package/draft-2019-09/meta/format.js +14 -0
- package/draft-2019-09/meta/meta-data.js +37 -0
- package/draft-2019-09/meta/validation.js +98 -0
- package/draft-2019-09/recursiveAnchor.js +1 -0
- package/draft-2019-09/recursiveRef.js +19 -0
- package/draft-2019-09/schema.js +42 -0
- package/draft-2020-12/dynamicAnchor.js +1 -0
- package/draft-2020-12/dynamicRef.js +35 -0
- package/draft-2020-12/index.d.ts +66 -0
- package/draft-2020-12/index.js +124 -0
- package/draft-2020-12/meta/applicator.js +46 -0
- package/draft-2020-12/meta/content.js +14 -0
- package/draft-2020-12/meta/core.js +54 -0
- package/draft-2020-12/meta/format-annotation.js +11 -0
- package/draft-2020-12/meta/format-assertion.js +11 -0
- package/draft-2020-12/meta/meta-data.js +34 -0
- package/draft-2020-12/meta/unevaluated.js +12 -0
- package/draft-2020-12/meta/validation.js +95 -0
- package/draft-2020-12/schema.js +44 -0
- package/lib/common.d.ts +5 -1
- package/lib/common.js +80 -9
- package/lib/configuration.d.ts +9 -0
- package/lib/configuration.js +18 -0
- package/lib/core.d.ts +48 -0
- package/lib/core.js +102 -0
- package/lib/experimental.d.ts +8 -0
- package/lib/experimental.js +4 -0
- package/lib/fetch.browser.js +1 -0
- package/lib/fetch.js +19 -0
- package/lib/index.d.ts +11 -42
- package/lib/index.js +130 -23
- package/lib/instance.d.ts +75 -0
- package/lib/instance.js +58 -0
- package/lib/invalid-schema-error.d.ts +8 -0
- package/lib/invalid-schema-error.js +7 -0
- package/lib/keywords/additionalProperties.js +19 -17
- package/lib/keywords/allOf.js +10 -7
- package/lib/keywords/anchor.js +1 -0
- package/lib/keywords/anyOf.js +10 -7
- package/lib/keywords/comment.js +4 -0
- package/lib/keywords/const.js +6 -3
- package/lib/keywords/contains.js +48 -5
- package/lib/keywords/contentEncoding.js +4 -0
- package/lib/keywords/contentMediaType.js +4 -0
- package/lib/keywords/contentSchema.js +4 -0
- package/lib/keywords/default.js +4 -0
- package/lib/keywords/definitions.js +7 -4
- package/lib/keywords/dependentRequired.js +6 -3
- package/lib/keywords/dependentSchemas.js +10 -6
- package/lib/keywords/deprecated.js +4 -0
- package/lib/keywords/description.js +4 -0
- package/lib/keywords/dynamicAnchor.js +1 -0
- package/lib/keywords/dynamicRef.js +13 -17
- package/lib/keywords/else.js +16 -11
- package/lib/keywords/enum.js +6 -3
- package/lib/keywords/examples.js +4 -0
- package/lib/keywords/exclusiveMaximum.js +5 -2
- package/lib/keywords/exclusiveMinimum.js +5 -2
- package/lib/keywords/format.js +4 -0
- package/lib/keywords/id.js +1 -0
- package/lib/keywords/if.js +8 -6
- package/lib/keywords/items.js +17 -19
- package/lib/keywords/maxContains.js +4 -0
- package/lib/keywords/maxItems.js +5 -2
- package/lib/keywords/maxLength.js +5 -2
- package/lib/keywords/maxProperties.js +5 -2
- package/lib/keywords/maximum.js +5 -2
- package/lib/keywords/meta-data.js +4 -0
- package/lib/keywords/minContains.js +4 -0
- package/lib/keywords/minItems.js +5 -2
- package/lib/keywords/minLength.js +5 -2
- package/lib/keywords/minProperties.js +5 -2
- package/lib/keywords/minimum.js +5 -2
- package/lib/keywords/multipleOf.js +5 -2
- package/lib/keywords/not.js +6 -4
- package/lib/keywords/oneOf.js +9 -6
- package/lib/keywords/pattern.js +5 -2
- package/lib/keywords/patternProperties.js +9 -5
- package/lib/keywords/prefixItems.js +28 -0
- package/lib/keywords/properties.js +11 -6
- package/lib/keywords/propertyDependencies.js +49 -0
- package/lib/keywords/propertyNames.js +7 -4
- package/lib/keywords/readOnly.js +4 -0
- package/lib/keywords/ref.js +9 -6
- package/lib/keywords/requireAllExcept.js +24 -0
- package/lib/keywords/required.js +5 -2
- package/lib/keywords/then.js +16 -11
- package/lib/keywords/title.js +4 -0
- package/lib/keywords/type.js +5 -2
- package/lib/keywords/unevaluatedItems.js +9 -5
- package/lib/keywords/unevaluatedProperties.js +9 -5
- package/lib/keywords/uniqueItems.js +6 -3
- package/lib/keywords/validation.js +123 -0
- package/lib/keywords/vocabulary.js +1 -0
- package/lib/keywords/writeOnly.js +4 -0
- package/lib/keywords.d.ts +19 -0
- package/lib/keywords.js +59 -0
- package/lib/media-types.d.ts +9 -0
- package/lib/media-types.js +26 -0
- package/lib/pubsub.js +42 -0
- package/lib/reference.d.ts +11 -0
- package/lib/reference.js +11 -0
- package/lib/schema.d.ts +64 -0
- package/lib/schema.js +308 -0
- package/package.json +31 -22
- package/{lib/draft-2020-12.d.ts → stable/index.d.ts} +26 -24
- package/stable/index.js +118 -0
- package/stable/meta/applicator.js +49 -0
- package/stable/meta/content.js +12 -0
- package/stable/meta/core.js +49 -0
- package/stable/meta/format-annotation.js +10 -0
- package/stable/meta/format-assertion.js +10 -0
- package/stable/meta/meta-data.js +16 -0
- package/stable/meta/unevaluated.js +11 -0
- package/stable/meta/validation.js +67 -0
- package/stable/validation.js +24 -0
- package/dist/json-schema-amd.js +0 -6602
- package/dist/json-schema-amd.js.map +0 -1
- package/dist/json-schema-amd.min.js +0 -3
- package/dist/json-schema-amd.min.js.map +0 -1
- package/dist/json-schema-cjs.js +0 -6600
- package/dist/json-schema-cjs.js.map +0 -1
- package/dist/json-schema-cjs.min.js +0 -3
- package/dist/json-schema-cjs.min.js.map +0 -1
- package/dist/json-schema-esm.js +0 -6596
- package/dist/json-schema-esm.js.map +0 -1
- package/dist/json-schema-esm.min.js +0 -3
- package/dist/json-schema-esm.min.js.map +0 -1
- package/dist/json-schema-iife.js +0 -6605
- package/dist/json-schema-iife.js.map +0 -1
- package/dist/json-schema-iife.min.js +0 -3
- package/dist/json-schema-iife.min.js.map +0 -1
- package/dist/json-schema-system.js +0 -6603
- package/dist/json-schema-system.js.map +0 -1
- package/dist/json-schema-system.min.js +0 -3
- package/dist/json-schema-system.min.js.map +0 -1
- package/dist/json-schema-umd.js +0 -6606
- package/dist/json-schema-umd.js.map +0 -1
- package/dist/json-schema-umd.min.js +0 -3
- package/dist/json-schema-umd.min.js.map +0 -1
- package/lib/draft-04.d.ts +0 -41
- package/lib/draft-04.js +0 -46
- package/lib/draft-06.d.ts +0 -45
- package/lib/draft-06.js +0 -51
- package/lib/draft-07.js +0 -55
- package/lib/draft-2019-09.js +0 -92
- package/lib/draft-2020-12.js +0 -103
- package/lib/index.mjs +0 -19
- package/lib/keywords/additionalItems.js +0 -27
- package/lib/keywords/additionalItems6.js +0 -23
- package/lib/keywords/additionalProperties6.js +0 -28
- package/lib/keywords/index.js +0 -53
- package/lib/keywords/items202012.js +0 -23
- package/lib/keywords/maximum-exclusiveMaximum.js +0 -20
- package/lib/keywords/minimum-exclusiveMinimum.js +0 -20
- package/lib/keywords/tupleItems.js +0 -24
- package/meta/draft/2019-09/meta/applicator.js +0 -55
- package/meta/draft/2019-09/meta/content.js +0 -17
- package/meta/draft/2019-09/meta/core.js +0 -57
- package/meta/draft/2019-09/meta/format.js +0 -14
- package/meta/draft/2019-09/meta/meta-data.js +0 -37
- package/meta/draft/2019-09/meta/validation.js +0 -98
- package/meta/draft/2019-09/schema.js +0 -42
- package/meta/draft/2020-12/meta/applicator.js +0 -49
- package/meta/draft/2020-12/meta/content.js +0 -17
- package/meta/draft/2020-12/meta/core.js +0 -57
- package/meta/draft/2020-12/meta/format-annotation.js +0 -14
- package/meta/draft/2020-12/meta/format-assertion.js +0 -14
- package/meta/draft/2020-12/meta/meta-data.js +0 -37
- package/meta/draft/2020-12/meta/unevaluated.js +0 -15
- package/meta/draft/2020-12/meta/validation.js +0 -98
- package/meta/draft/2020-12/schema.js +0 -44
- package/meta/draft-04/schema.js +0 -149
- package/meta/draft-06/schema.js +0 -154
- package/meta/draft-07/schema.js +0 -172
package/README.md
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
|
-
# Hyperjump - JSON Schema
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* Schemas can reference other schemas using a different
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
format-annotations
|
|
12
|
-
* Create your own keywords and vocabularies with [JSC](https://github.com/hyperjump-io/json-schema-core)
|
|
13
|
-
* Output formats
|
|
14
|
-
* FLAG, BASIC, DETAILED, VERBOSE
|
|
15
|
-
* Create your own output format with [JSC](https://github.com/hyperjump-io/json-schema-core)
|
|
16
|
-
* Load schemas from filesystem (file://), network (http(s)://), or JavaScript
|
|
17
|
-
* Build non-validation JSON-Schema based tools with [JSC](https://github.com/hyperjump-io/json-schema-core)
|
|
1
|
+
# Hyperjump - JSON Schema
|
|
2
|
+
|
|
3
|
+
A collection of modules for working with JSON Schemas.
|
|
4
|
+
|
|
5
|
+
* Validate JSON-compatible values against a JSON Schema
|
|
6
|
+
* Dialects: draft-2020-12, draft-2019-09, draft-07, draft-06, draft-04
|
|
7
|
+
* Schemas can reference other schemas using a different dialect
|
|
8
|
+
* Work directly with schemas on the filesystem or HTTP
|
|
9
|
+
* Create custom keywords, vocabularies, and dialects
|
|
10
|
+
* Provides utilities for building non-validation JSON Schema tooling
|
|
18
11
|
|
|
19
12
|
## Install
|
|
20
|
-
|
|
21
|
-
TypeScript, and browsers.
|
|
13
|
+
Includes support for node.js (ES Modules, TypeScript) and browsers.
|
|
22
14
|
|
|
23
15
|
### Node.js
|
|
24
16
|
```bash
|
|
@@ -26,7 +18,7 @@ npm install @hyperjump/json-schema
|
|
|
26
18
|
```
|
|
27
19
|
|
|
28
20
|
### Browser
|
|
29
|
-
When in a browser context,
|
|
21
|
+
When in a browser context, this library is designed to use the browser's `fetch`
|
|
30
22
|
implementation instead of a node.js fetch clone. The Webpack bundler does this
|
|
31
23
|
properly without any extra configuration, but if you are using the Rollup
|
|
32
24
|
bundler you will need to include the `browser: true` option in your Rollup
|
|
@@ -36,72 +28,162 @@ configuration.
|
|
|
36
28
|
plugins: [
|
|
37
29
|
resolve({
|
|
38
30
|
browser: true
|
|
39
|
-
})
|
|
40
|
-
commonjs()
|
|
31
|
+
})
|
|
41
32
|
]
|
|
42
33
|
```
|
|
43
34
|
|
|
44
35
|
### Versioning
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
36
|
+
The API for this library is divided into two categories: Stable and
|
|
37
|
+
Experimental. The Stable API strictly follows semantic versioning, but the
|
|
38
|
+
Experimental API may have backward-incompatible changes between minor versions.
|
|
48
39
|
|
|
49
40
|
## Usage
|
|
41
|
+
This library supports many versions of JSON Schema. Use the pattern
|
|
42
|
+
`@hyperjump/json-schema/*` to import the version you need.
|
|
43
|
+
|
|
50
44
|
```javascript
|
|
51
|
-
|
|
45
|
+
import { addSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
|
|
46
|
+
```
|
|
52
47
|
|
|
48
|
+
You can import support for additional versions as needed.
|
|
53
49
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
"type": "string"
|
|
59
|
-
};
|
|
60
|
-
JsonSchema.add(schemaJson);
|
|
61
|
-
const schema = await JsonSchema.get("http://example.com/schemas/string");
|
|
50
|
+
```javascript
|
|
51
|
+
import { addSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
|
|
52
|
+
import "@hyperjump/json-schema/draft-07";
|
|
53
|
+
```
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
**Note**: The default export (`@hyperjump/json-schema`) is reserved for the
|
|
56
|
+
stable version of JSON Schema that will hopefully be released in 2023.
|
|
65
57
|
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
**Validate schema from JavaScript**
|
|
59
|
+
```javascript
|
|
60
|
+
addSchema({
|
|
61
|
+
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
62
|
+
type: "string"
|
|
63
|
+
}, "http://example.com/schemas/string");
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
const output = await JsonSchema.validate(schema, "foo");
|
|
65
|
+
const output = await validate("http://example.com/schemas/string", "foo");
|
|
71
66
|
if (output.valid) {
|
|
72
67
|
console.log("Instance is valid :-)");
|
|
73
68
|
} else {
|
|
74
69
|
console.log("Instance is invalid :-(");
|
|
75
70
|
}
|
|
71
|
+
```
|
|
76
72
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
**Compile schema**
|
|
74
|
+
|
|
75
|
+
If you need to validate multiple instances against the same schema, you can
|
|
76
|
+
compile the schema into a reusable validation function.
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
const isString = await validate("http://example.com/schemas/string");
|
|
80
|
+
const output1 = isString("foo");
|
|
81
|
+
const output2 = isString(42);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Fetching schemas**
|
|
85
|
+
|
|
86
|
+
You can fetch schemas from the web or from the file system, but when fetching
|
|
87
|
+
from the file system, there are limitations for security reasons. If your schema
|
|
88
|
+
has an identifier with an http(s) scheme (**https**://example.com), it's not
|
|
89
|
+
allowed to reference schemas with a file scheme
|
|
90
|
+
(**file**:///path/to/my/schemas).
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
const output = await validate("http://example.com/schemas/string", "foo");
|
|
94
|
+
```
|
|
80
95
|
|
|
81
|
-
|
|
82
|
-
const output = await
|
|
96
|
+
```javascript
|
|
97
|
+
const output = await validate(`file://${__dirname}/string.schema.json`, "foo");
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Media type plugins**
|
|
101
|
+
|
|
102
|
+
There is a plugin system for adding support for different media types. By
|
|
103
|
+
default it's configured to accept schemas that have the
|
|
104
|
+
`application/schema+json` Content-Type (web) or a `.schema.json` file extension
|
|
105
|
+
(filesystem). If, for example, you want to fetch schemas that are written in
|
|
106
|
+
YAML, you can add a MediaTypePlugin to support that.
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
import { addMediaTypePlugin, validate } from "@hyperjump/json-schema/draft-2020-12";
|
|
110
|
+
import YAML from "yaml";
|
|
83
111
|
|
|
84
|
-
// Example: Specify meta-validation output format
|
|
85
|
-
JsonSchema.setMetaOutputFormat(JsonSchema.FLAG);
|
|
86
112
|
|
|
87
|
-
//
|
|
88
|
-
|
|
113
|
+
// Add support for JSON Schemas written in YAML
|
|
114
|
+
addMediaTypePlugin("application/schema+yaml", {
|
|
115
|
+
parse: async (response) => [YAML.parse(await response.text()), undefined],
|
|
116
|
+
matcher: (path) => path.endsWith(".schema.yaml")
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Example: Fetch schema with Content-Type: application/schema+yaml from the web
|
|
120
|
+
const isString = await validate("http://example.com/schemas/string");
|
|
121
|
+
|
|
122
|
+
// Example: Fetch from file with JSON Schema YAML file extension
|
|
123
|
+
const isString = await validate(`file://${__dirname}/string.schema.yaml`);
|
|
124
|
+
|
|
125
|
+
// Then validate against your schema like normal
|
|
126
|
+
const output = isString("foo");
|
|
89
127
|
```
|
|
90
128
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
MediaTypePlugin to support that.
|
|
129
|
+
## API
|
|
130
|
+
These are available from any of the exports that refer to a version of JSON
|
|
131
|
+
Schema, such as `@hyperjump/json-schema/draft-2020-12`.
|
|
132
|
+
|
|
133
|
+
* **addSchema**: (schema: object, retrievalUri?: string, defaultDialectId?: string) => void
|
|
97
134
|
|
|
98
|
-
|
|
135
|
+
Load a schema manually rather than fetching it from the filesystem or over
|
|
136
|
+
the network.
|
|
137
|
+
* **validate**: (schemaURI: string, instance: any, outputFormat: OutputFormat = FLAG) => Promise<OutputUnit>
|
|
138
|
+
|
|
139
|
+
Validate an instance against a schema. This function is curried to allow
|
|
140
|
+
compiling the schema once and applying it to multiple instances.
|
|
141
|
+
* **validate**: (schemaURI: string) => Promise<(instance: any, outputFormat: OutputFormat = FLAG) => OutputUnit>
|
|
142
|
+
|
|
143
|
+
Compiling a schema to a validation function.
|
|
144
|
+
* **FLAG**: "FLAG"
|
|
145
|
+
|
|
146
|
+
An identifier for the `FLAG` output format as defined by the 2019-09 and
|
|
147
|
+
2020-12 specifications.
|
|
148
|
+
* **InvalidSchemaError**: Error & { output: OutputUnit }
|
|
149
|
+
|
|
150
|
+
This error is thrown if the schema being compiled is found to be invalid.
|
|
151
|
+
The `output` field contains an `OutputUnit` with information about the
|
|
152
|
+
error. You can use the `setMetaOutputFormat` configuration to set the output
|
|
153
|
+
format that is returned in `output`.
|
|
154
|
+
* **setMetaOutputFormat**: (outputFormat: OutputFormat) => void
|
|
155
|
+
|
|
156
|
+
Set the output format used for validating schemas.
|
|
157
|
+
* **getMetaOutputFormat**: () => OutputFormat
|
|
158
|
+
|
|
159
|
+
Get the output format used for validating schemas.
|
|
160
|
+
* **setShouldMetaValidate**: (isEnabled: boolean) => void
|
|
161
|
+
|
|
162
|
+
Enable or disable validating schemas.
|
|
163
|
+
* **getShouldMetaValidate**: (isEnabled: boolean) => void
|
|
164
|
+
|
|
165
|
+
Determine if validating schemas is enabled.
|
|
166
|
+
* **addMediaTypePlugin**: (contentType: string, plugin: MediaTypePlugin) => void
|
|
99
167
|
|
|
100
168
|
Add a custom media type handler to support things like YAML or to change the
|
|
101
169
|
way JSON is supported.
|
|
170
|
+
|
|
171
|
+
**Type Definitions**
|
|
172
|
+
|
|
173
|
+
The following types are used in the above definitions
|
|
174
|
+
|
|
175
|
+
* **OutputFormat**: **FLAG**
|
|
176
|
+
|
|
177
|
+
Only the `FLAG` output format is part of the Stable API. Additional output
|
|
178
|
+
formats are included as part of the Experimental API.
|
|
179
|
+
* **OutputUnit**: { valid: boolean }
|
|
180
|
+
|
|
181
|
+
Output is an experimental feature of the JSON Schema specification. There
|
|
182
|
+
may be additional fields present in the OutputUnit, but only the `valid`
|
|
183
|
+
property should be considered part of the Stable API.
|
|
102
184
|
* **MediaTypePlugin**: object
|
|
103
185
|
|
|
104
|
-
* parse: (response: Response, mediaTypeParameters: object) => [
|
|
186
|
+
* parse: (response: Response, mediaTypeParameters: object) => [object | boolean, string?]
|
|
105
187
|
|
|
106
188
|
Given a fetch Response object, parse the body of the request. Return the
|
|
107
189
|
parsed schema and an optional default dialectId.
|
|
@@ -110,96 +192,353 @@ MediaTypePlugin to support that.
|
|
|
110
192
|
Given a filesystem path, return whether or not the file should be
|
|
111
193
|
considered a member of this media type.
|
|
112
194
|
|
|
195
|
+
## Experimental
|
|
196
|
+
The JSON Schema specification includes several features that are experimental in
|
|
197
|
+
nature including the Vocabulary System, Output Formats, and Annotations. This
|
|
198
|
+
implementation aims to support only the latest version of experimental features
|
|
199
|
+
as they evolve. There will not be a major version bump if there needs to be
|
|
200
|
+
backward incompatible changes to the Experimental API.
|
|
201
|
+
|
|
202
|
+
### Usage
|
|
203
|
+
All experimental features are segregated into exports that include the word
|
|
204
|
+
"experimental" so you never accidentally depend on something that could change
|
|
205
|
+
or be removed in future releases.
|
|
206
|
+
|
|
113
207
|
```javascript
|
|
114
|
-
|
|
115
|
-
|
|
208
|
+
import { BASIC } from "@hyperjump/json-schema/experimental";
|
|
209
|
+
```
|
|
116
210
|
|
|
211
|
+
**Change the validation output format**
|
|
117
212
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
parse: async (response) => [YAML.parse(await response.text()), undefined],
|
|
121
|
-
matcher: (path) => path.endsWith(".schema.yaml")
|
|
122
|
-
});
|
|
213
|
+
The `FLAG` output format isn't very informative. You can change the output
|
|
214
|
+
format used for validation to get more information.
|
|
123
215
|
|
|
124
|
-
|
|
125
|
-
const
|
|
216
|
+
```javascript
|
|
217
|
+
const output = await validate("https://example.com/schema1", 42, BASIC);
|
|
218
|
+
```
|
|
126
219
|
|
|
127
|
-
|
|
128
|
-
const schema = await JsonSchema.get("file:///path/to/my/schemas/string.schema.yaml");
|
|
220
|
+
**Change the schema validation output format**
|
|
129
221
|
|
|
130
|
-
|
|
222
|
+
The output format used for validating schemas can be changed as well.
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
setMetaOutputFormat(BASIC);
|
|
226
|
+
try {
|
|
227
|
+
const output = await validate("https://example.com/invalid-schema");
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.log(error.output);
|
|
230
|
+
}
|
|
131
231
|
```
|
|
132
232
|
|
|
133
|
-
|
|
134
|
-
Although the package is written in JavaScript, type definitions are included for
|
|
135
|
-
TypeScript support. The following example shows the types you might want to
|
|
136
|
-
know.
|
|
233
|
+
**Keywords, Vocabularies, and Dialects**
|
|
137
234
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
235
|
+
In order to create and use a custom keyword, you need to define your keyword's
|
|
236
|
+
behavior, create a vocabulary that includes that keyword, and then create a
|
|
237
|
+
dialect that includes your vocabulary.
|
|
141
238
|
|
|
239
|
+
```javascript
|
|
240
|
+
import { addSchema, validate } from "@hyperjump/json-schema/draft-2020-12";
|
|
241
|
+
import { addKeyword, defineVocabulary, Validation } from "@hyperjump/json-schema/experimental";
|
|
242
|
+
import * as Schema from "@hyperjump/json-schema/schema/experimental";
|
|
142
243
|
|
|
143
|
-
const schemaJson: Draft202012Schema = {
|
|
144
|
-
"$id": "https://json-schema.hyperjump.io/schema",
|
|
145
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
146
244
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
245
|
+
// Define a keyword that's an array of schemas that are applied sequentially
|
|
246
|
+
// using implication: A -> B -> C -> D
|
|
247
|
+
addKeyword({
|
|
248
|
+
id: "https://example.com/keyword/implication",
|
|
150
249
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
} else {
|
|
160
|
-
console.log(error);
|
|
250
|
+
compile: (schema, ast) => {
|
|
251
|
+
return Schema.map(async (itemSchema) => Validation.compile(await itemSchema, ast), schema);
|
|
252
|
+
},
|
|
253
|
+
|
|
254
|
+
interpret: (implies, instance, ast, dynamicAnchors) => {
|
|
255
|
+
return implies.reduce((acc, schema) => {
|
|
256
|
+
return !acc || Validation.interpret(schema, instance, ast, dynamicAnchors);
|
|
257
|
+
}, true);
|
|
161
258
|
}
|
|
162
|
-
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Create a vocabulary with this keyword and call it "implies"
|
|
262
|
+
defineVocabulary("https://example.com/vocab/logic", {
|
|
263
|
+
"implies": "https://example.com/keyword/implication"
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Create a vocabulary schema for this vocabulary
|
|
267
|
+
addSchema({
|
|
268
|
+
"$id": "https://example.com/meta/logic",
|
|
269
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
270
|
+
|
|
271
|
+
"$dynamicAnchor": "meta",
|
|
272
|
+
"properties": {
|
|
273
|
+
"implies": {
|
|
274
|
+
"type": "array",
|
|
275
|
+
"items": { "$dynamicRef": "meta" },
|
|
276
|
+
"minItems": 2
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Create a dialect schema adding this vocabulary to the standard JSON Schema
|
|
282
|
+
// vocabularies
|
|
283
|
+
addSchema({
|
|
284
|
+
"$id": "https://example.com/dialect/logic",
|
|
285
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
286
|
+
|
|
287
|
+
"$vocabulary": {
|
|
288
|
+
"https://json-schema.org/vocab/core": true,
|
|
289
|
+
"https://json-schema.org/vocab/applicator": true,
|
|
290
|
+
"https://json-schema.org/vocab/unevaluated": true,
|
|
291
|
+
"https://json-schema.org/vocab/validation": true,
|
|
292
|
+
"https://json-schema.org/vocab/meta-data": true,
|
|
293
|
+
"https://json-schema.org/vocab/format-annotation": true,
|
|
294
|
+
"https://json-schema.org/vocab/content": true,
|
|
295
|
+
"https://example.com/vocab/logic": true
|
|
296
|
+
},
|
|
297
|
+
|
|
298
|
+
"$dynamicAnchor": "meta",
|
|
299
|
+
|
|
300
|
+
"allOf": [
|
|
301
|
+
{ "$ref": "https://json-schema.org/draft/2020-12/schema" },
|
|
302
|
+
{ "$ref": "/meta/logic" }
|
|
303
|
+
]
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// Use your dialect to validate a JSON instance
|
|
307
|
+
addSchema({
|
|
308
|
+
"$schema": "https://example.com/dialect/logic",
|
|
309
|
+
|
|
310
|
+
"type": "number",
|
|
311
|
+
"implies": [
|
|
312
|
+
{ "minimum": 10 },
|
|
313
|
+
{ "multipleOf": 2 }
|
|
314
|
+
]
|
|
315
|
+
}, "https://example.com/schema1");
|
|
316
|
+
const output = await validate("https://example.com/schema1", 42);
|
|
163
317
|
```
|
|
164
318
|
|
|
165
|
-
|
|
166
|
-
* **add**: (schema: object, url?: URI, dialectId?: string) => SDoc
|
|
319
|
+
**Custom Meta Schema**
|
|
167
320
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
* **get**: (url: URI, contextDoc?: SDoc, recursive: boolean = false) => Promise<SDoc>
|
|
321
|
+
You can use a custom meta-schema to restrict users to a subset of JSON Schema
|
|
322
|
+
functionality. This example requires that no unknown keywords are used in the
|
|
323
|
+
schema.
|
|
172
324
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
325
|
+
```javascript
|
|
326
|
+
addSchema({
|
|
327
|
+
"$id": "https://example.com/meta-schema1",
|
|
328
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
176
329
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
330
|
+
"$vocabulary": {
|
|
331
|
+
"https://json-schema.org/draft/2020-12/vocab/core": true,
|
|
332
|
+
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
|
|
333
|
+
"https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
|
|
334
|
+
"https://json-schema.org/draft/2020-12/vocab/validation": true,
|
|
335
|
+
"https://json-schema.org/draft/2020-12/vocab/meta-data": true,
|
|
336
|
+
"https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
|
|
337
|
+
"https://json-schema.org/draft/2020-12/vocab/content": true
|
|
338
|
+
},
|
|
180
339
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
340
|
+
"$dynamicAnchor": "meta",
|
|
341
|
+
|
|
342
|
+
"$ref": "https://json-schema.org/draft/2020-12/schema",
|
|
343
|
+
"unevaluatedProperties": false
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
addSchema({
|
|
347
|
+
$schema: "https://example.com/meta-schema1",
|
|
348
|
+
type: "number",
|
|
349
|
+
foo: 42
|
|
350
|
+
}, "https://example.com/schema1");
|
|
351
|
+
|
|
352
|
+
const output = await validate("https://example.com/schema1", 42); // Expect InvalidSchemaError
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### API
|
|
356
|
+
These are available from the `@hyperjump/json-schema/experimental` export.
|
|
357
|
+
|
|
358
|
+
* **compile**: (schema: SchemaDocument) => Promise<CompiledSchema>
|
|
359
|
+
|
|
360
|
+
Return a compiled schema. This is useful if you're creating tooling for
|
|
361
|
+
something other than validation.
|
|
362
|
+
* **interpret**: (schema: CompiledSchema, instance: Instance, outputFormat: OutputFormat = BASIC) => OutputUnit
|
|
184
363
|
|
|
185
364
|
A curried function for validating an instance against a compiled schema.
|
|
186
|
-
|
|
365
|
+
This can be useful for creating custom output formats.
|
|
366
|
+
* **addKeyword**: (keywordHandler: Keyword) => void
|
|
367
|
+
|
|
368
|
+
Define a keyword for use in a vocabulary.
|
|
369
|
+
* **defineVocabulary**: (id: string, keywords: { [keyword: string]: string }) => void
|
|
370
|
+
|
|
371
|
+
Define a vocabulary that maps keyword name to keyword URIs defined using
|
|
372
|
+
`addKeyword`.
|
|
373
|
+
* **getKeyword**: (keywordId: string) => Keyword
|
|
374
|
+
|
|
375
|
+
Get a keyword object by its URI. This is useful for building non-validation
|
|
376
|
+
tooling.
|
|
377
|
+
* **getKeywordName**: (dialectId: string, keywordId: string) => string
|
|
378
|
+
|
|
379
|
+
Determine a keyword's name given its URI a dialect URI. This is useful when
|
|
380
|
+
defining a keyword that depends on the value of another keyword (such as how
|
|
381
|
+
`contains` depends on `minContains` and `maxContains`).
|
|
382
|
+
* **loadDialect**: (dialectId: string, dialect: { [vocabularyId: string] }) => void
|
|
383
|
+
|
|
384
|
+
Define a dialect. In most cases, dialects are loaded automatically from the
|
|
385
|
+
`$vocabulary` keyword in the meta-schema. The only time you would need to
|
|
386
|
+
load a dialect manually is if you're creating a distinct version of JSON
|
|
387
|
+
Schema rather than creating a dialect of an existing version of JSON Schema.
|
|
388
|
+
* **Validation**: Keyword
|
|
389
|
+
|
|
390
|
+
A Keyword object that represents a "validate" operation. You would use this
|
|
391
|
+
for compiling and evaluating sub-schemas when defining a custom keyword.
|
|
392
|
+
|
|
393
|
+
**Type Definitions**
|
|
394
|
+
|
|
395
|
+
The following types are used in the above definitions
|
|
396
|
+
|
|
397
|
+
* **OutputFormat**: **FLAG** | **BASIC** | **DETAILED** | **VERBOSE**
|
|
398
|
+
|
|
399
|
+
In addition to the `FLAG` output format in the Stable API, the Experimental
|
|
400
|
+
API includes support for the `BASIC`, `DETAILED`, and `VERBOSE` formats as
|
|
401
|
+
specified in the 2019-09 specification (with some minor customizations).
|
|
402
|
+
This implementation doesn't include annotations or human readable error
|
|
403
|
+
messages. The output can be processed to create human readable error
|
|
404
|
+
messages as needed.
|
|
405
|
+
* **Keyword**: object
|
|
406
|
+
* id: string
|
|
407
|
+
|
|
408
|
+
A URI that uniquely identifies the keyword. It should use a domain you
|
|
409
|
+
own to avoid conflict with keywords defined by others.
|
|
410
|
+
* compile: (schema: SchemaDocument, ast: AST, parentSchema: SchemaDocument) => Promise<A>
|
|
411
|
+
|
|
412
|
+
This function takes the keyword value, does whatever preprocessing it
|
|
413
|
+
can on it without an instance, and returns the result. The returned
|
|
414
|
+
value will be passed to the `interpret` function. The `ast` parameter is
|
|
415
|
+
needed for compiling sub-schemas. The `parentSchema` parameter is
|
|
416
|
+
primarily useful for looking up the value of an adjacent keyword that
|
|
417
|
+
might effect this one.
|
|
418
|
+
* interpret: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors) => boolean
|
|
419
|
+
|
|
420
|
+
This function takes the value returned by the `compile` function and the
|
|
421
|
+
instance value that is being validated and returns whether the value is
|
|
422
|
+
valid or not. The other parameters are only needed for validating
|
|
423
|
+
sub-schemas.
|
|
424
|
+
* collectEvaluatedProperties?: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors) => string[] | false
|
|
425
|
+
|
|
426
|
+
If the keyword is an applicator, it will need to implements this
|
|
427
|
+
function for `unevaluatedProperties` to work as expected.
|
|
428
|
+
* collectEvaluatedItems?: (compiledKeywordValue: A, instance: JsonDocument, ast: AST, dynamicAnchors: Anchors) => Set<number> | false
|
|
429
|
+
|
|
430
|
+
If the keyword is an applicator, it will need to implements this
|
|
431
|
+
function for `unevaluatedItems` to work as expected.
|
|
432
|
+
|
|
433
|
+
### Schema
|
|
434
|
+
These functions are available from the
|
|
435
|
+
`@hyperjump/json-schema/schema/experimental` export.
|
|
436
|
+
|
|
437
|
+
This library uses SchemaDocument objects to represent a value in a schema.
|
|
438
|
+
You'll work with these objects if you create a custom keyword. This module is a
|
|
439
|
+
set of functions for working with SchemaDocuments.
|
|
440
|
+
|
|
441
|
+
* **Schema.add**: (schema: object, retrievalUri?: string, dialectId?: string) => string
|
|
442
|
+
|
|
443
|
+
Load a schema. Returns the identifier for the schema.
|
|
444
|
+
* **Schema.get**: (url: string, contextDoc?: SchemaDocument) => Promise<SchemaDocument>
|
|
445
|
+
|
|
446
|
+
Fetch a schema. Schemas can come from an HTTP request, a file, or a schema
|
|
447
|
+
that was added with `Schema.add`.
|
|
448
|
+
* **Schema.uri**: (doc: SchemaDocument) => string
|
|
449
|
+
|
|
450
|
+
Returns a URI for the value the SchemaDocument represents.
|
|
451
|
+
* **Schema.value**: (doc: SchemaDocument) => any
|
|
452
|
+
|
|
453
|
+
Returns the value the SchemaDocument represents.
|
|
454
|
+
* **Schema.typeOf**: (doc: SchemaDocument, type: string) => boolean
|
|
455
|
+
|
|
456
|
+
Determines if the JSON type of the given doc matches the given type.
|
|
457
|
+
* **Schema.has**: (key: string, doc: SchemaDocument) => Promise<SchemaDocument>
|
|
458
|
+
|
|
459
|
+
Similar to `key in schema`.
|
|
460
|
+
* **Schema.step**: (key: string, doc: SchemaDocument) => Promise<SchemaDocument>
|
|
461
|
+
|
|
462
|
+
Similar to `schema[key]`, but returns an SchemaDocument.
|
|
463
|
+
* **Schema.entries**: (doc: SchemaDocument) => Promise<[[string, SchemaDocument]]>
|
|
464
|
+
|
|
465
|
+
Similar to `Object.entries`, but returns SchemaDocuments for values.
|
|
466
|
+
* **Schema.keys**: (doc: SchemaDocument) => [string]
|
|
467
|
+
|
|
468
|
+
Similar to `Object.keys`.
|
|
469
|
+
* **Schema.map**: (fn: (item: Promise<SchemaDocument>, index: integer) => T, doc: SchemaDocument) => Promise<[T]>
|
|
470
|
+
|
|
471
|
+
A `map` function for an SchemaDocument whose value is an array.
|
|
472
|
+
* **Schema.length**: (doc: SchemaDocument) => number
|
|
473
|
+
|
|
474
|
+
Similar to `Array.prototype.length`.
|
|
475
|
+
* **Schema.toSchema**: (doc: SchemaDocument, options: ToSchemaOptions) => object
|
|
476
|
+
|
|
477
|
+
Get a raw schema from a Schema Document.
|
|
478
|
+
|
|
479
|
+
**Type Definitions**
|
|
480
|
+
|
|
481
|
+
The following types are used in the above definitions
|
|
482
|
+
|
|
483
|
+
* **ToSchemaOptions**: object
|
|
484
|
+
|
|
485
|
+
* parentId: string (default: "") -- `file://` URIs will be generated
|
|
486
|
+
relative to this path.
|
|
487
|
+
* parentDialect: string (default: "") -- If the dialect of the schema
|
|
488
|
+
* matches this value, the `$schema` keyword will be omitted.
|
|
489
|
+
* includeEmbedded: boolean (default: true) -- If false, embedded schemas
|
|
490
|
+
will be unbundled from the schema.
|
|
491
|
+
|
|
492
|
+
### Instance
|
|
493
|
+
These functions are available from the
|
|
494
|
+
`@hyperjump/json-schema/instance/experimental` export.
|
|
495
|
+
|
|
496
|
+
This library uses InstanceDocument objects to represent a value in an instance.
|
|
497
|
+
You'll work with these objects if you create a custom keyword. This module is a
|
|
498
|
+
set of functions for working with InstanceDocuments.
|
|
499
|
+
|
|
500
|
+
* **Instance.cons**: (instance: any, uri?: string) => InstanceDocument
|
|
501
|
+
|
|
502
|
+
Construct an InstanceDocument from a value.
|
|
503
|
+
* **Instance.get**: (url: string, contextDoc: InstanceDocument) => InstanceDocument
|
|
504
|
+
|
|
505
|
+
Apply a same-resource reference to a InstanceDocument.
|
|
506
|
+
* **Instance.uri**: (doc: InstanceDocument) => string
|
|
507
|
+
|
|
508
|
+
Returns a URI for the value the InstanceDocument represents.
|
|
509
|
+
* **Instance.value**: (doc: InstanceDocument) => any
|
|
510
|
+
|
|
511
|
+
Returns the value the InstanceDocument represents.
|
|
512
|
+
* **Instance.has**: (key: string, doc: InstanceDocument) => any
|
|
513
|
+
|
|
514
|
+
Similar to `key in instance`.
|
|
515
|
+
* **Instance.typeOf**: (doc: InstanceDocument, type: string) => boolean
|
|
516
|
+
|
|
517
|
+
Determines if the JSON type of the given doc matches the given type.
|
|
518
|
+
* **Instance.step**: (key: string, doc: InstanceDocument) => InstanceDocument
|
|
519
|
+
|
|
520
|
+
Similar to `schema[key]`, but returns a InstanceDocument.
|
|
521
|
+
* **Instance.entries**: (doc: InstanceDocument) => [string, InstanceDocument]
|
|
522
|
+
|
|
523
|
+
Similar to `Object.entries`, but returns IDocs for values.
|
|
524
|
+
* **Instance.keys**: (doc: InstanceDocument) => [string]
|
|
525
|
+
|
|
526
|
+
Similar to `Object.keys`.
|
|
527
|
+
* **Instance.map**: (fn: (item: InstanceDocument, index: integer) => T, doc: InstanceDocument) => [T]
|
|
187
528
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
* **setShouldMetaValidate**: (isEnabled: boolean) => undefined
|
|
529
|
+
A `map` function for an InstanceDocument whose value is an array.
|
|
530
|
+
* **Instance.reduce**: (fn: (accumulator: T, item: InstanceDocument, index: integer) => T, initial: T, doc: InstanceDocument) => T
|
|
191
531
|
|
|
192
|
-
|
|
193
|
-
* **
|
|
532
|
+
A `reduce` function for an InstanceDocument whose value is an array.
|
|
533
|
+
* **Instance.every**: (fn: (doc: InstanceDocument, index: integer) => boolean, doc: InstanceDocument) => boolean
|
|
194
534
|
|
|
195
|
-
|
|
196
|
-
|
|
535
|
+
An `every` function for an InstanceDocument whose value is an array.
|
|
536
|
+
* **Instance.some**: (fn: (doc: InstanceDocument, index: integer) => boolean, doc: InstanceDocument) => boolean
|
|
197
537
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
optional features are not supported yet.
|
|
538
|
+
A `some` function for an InstanceDocument whose value is an array.
|
|
539
|
+
* **Instance.length**: (doc: InstanceDocument) => number
|
|
201
540
|
|
|
202
|
-
|
|
541
|
+
Similar to `Array.prototype.length`.
|
|
203
542
|
|
|
204
543
|
## Contributing
|
|
205
544
|
|