json-schema-library 10.5.4 → 11.0.1
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 +128 -14
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +42 -19
- package/dist/index.d.mts +42 -19
- package/dist/index.mjs +1 -1
- package/dist/jlib.js +2 -2
- package/index.ts +8 -4
- package/package.json +6 -6
- package/src/Keyword.ts +8 -3
- package/src/SchemaNode.ts +46 -10
- package/src/compileSchema.validate.test.ts +89 -54
- package/src/draft04.ts +10 -8
- package/src/draft06.ts +10 -8
- package/src/draft07.ts +10 -8
- package/src/draft2019-09/keywords/additionalItems.ts +2 -2
- package/src/draft2019-09/keywords/items.ts +2 -2
- package/src/draft2019-09/keywords/unevaluatedItems.ts +12 -6
- package/src/draft2019.ts +10 -8
- package/src/draft2020.ts +8 -6
- package/src/errors/errors.ts +3 -1
- package/src/formats/formats.ts +2 -6
- package/src/keywords/additionalProperties.ts +2 -2
- package/src/keywords/allOf.ts +2 -2
- package/src/keywords/dependencies.ts +5 -6
- package/src/keywords/dependentRequired.ts +2 -2
- package/src/keywords/dependentSchemas.ts +4 -3
- package/src/keywords/deprecated.ts +18 -0
- package/src/keywords/items.ts +2 -2
- package/src/keywords/oneOf.test.ts +150 -15
- package/src/keywords/oneOf.ts +64 -4
- package/src/keywords/patternProperties.ts +2 -2
- package/src/keywords/prefixItems.ts +2 -11
- package/src/keywords/properties.ts +2 -2
- package/src/keywords/unevaluatedItems.ts +2 -2
- package/src/keywords/unevaluatedProperties.ts +2 -2
- package/src/methods/getData.test.ts +1779 -1781
- package/src/types.ts +32 -18
- package/src/utils/sanitizeErrors.ts +9 -8
- package/src/validateNode.ts +2 -2
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ import myData from "./myData.json";
|
|
|
29
29
|
|
|
30
30
|
const schema: SchemaNode = compileSchema(myJsonSchema);
|
|
31
31
|
// validate data and collect errors if invalid
|
|
32
|
-
const { valid, errors } = schema.validate(myData);
|
|
32
|
+
const { valid, errors, annotations } = schema.validate(myData);
|
|
33
33
|
// create data which validates to the compiled JSON Schema
|
|
34
34
|
const defaultData = schema.getData();
|
|
35
35
|
// access a subschema at a specific JSON Pointer location
|
|
@@ -108,6 +108,8 @@ const titleData = titleNode?.getData();
|
|
|
108
108
|
|
|
109
109
|
<details><summary>Each node has an identity</summary>
|
|
110
110
|
|
|
111
|
+
---
|
|
112
|
+
|
|
111
113
|
```ts
|
|
112
114
|
const titleNode = compileSchema(mySchema).getNode("#/image/title");
|
|
113
115
|
console.log(titleNode.evaluationPath); // #/properties/image/properties/title
|
|
@@ -117,10 +119,14 @@ console.log(titleNode.schemaLocation); // #/properties/image/properties/title
|
|
|
117
119
|
- `evaluationPath` refers to the path in schema and is extended by `$ref`, e.g. if image is defined on `$defs`: `#/properties/image/$ref/properties/title`
|
|
118
120
|
- `schemaLocation` refers to the absolute path within the schema and will not change, e.g. `#/$defs/properties/title`
|
|
119
121
|
|
|
122
|
+
---
|
|
123
|
+
|
|
120
124
|
</details>
|
|
121
125
|
|
|
122
126
|
<details><summary>Each node has a reference to its parent node</summary>
|
|
123
127
|
|
|
128
|
+
---
|
|
129
|
+
|
|
124
130
|
The parent-node can be a sub-schema or intermediary node:
|
|
125
131
|
|
|
126
132
|
```ts
|
|
@@ -129,11 +135,13 @@ const { node: childNode } = root.getNode("#/image");
|
|
|
129
135
|
assert(root === childNode.parent);
|
|
130
136
|
```
|
|
131
137
|
|
|
138
|
+
---
|
|
139
|
+
|
|
132
140
|
</details>
|
|
133
141
|
|
|
134
142
|
<details><summary>All nodes share a context</summary>
|
|
135
143
|
|
|
136
|
-
|
|
144
|
+
---
|
|
137
145
|
|
|
138
146
|
A context is shared across all nodes of a schema
|
|
139
147
|
|
|
@@ -153,14 +161,21 @@ assert(root === childNode.context.rootNode);
|
|
|
153
161
|
|
|
154
162
|
Note that rootNodes will change when working across remote schema (using $ref).
|
|
155
163
|
|
|
164
|
+
---
|
|
165
|
+
|
|
156
166
|
</details>
|
|
157
167
|
|
|
168
|
+
> [!CAUTION]
|
|
169
|
+
> It is not advised to work on context directly, but it might be useful in some situations
|
|
170
|
+
|
|
158
171
|
### Draft Support
|
|
159
172
|
|
|
160
173
|
_json-schema-library_ fully supports all core features of draft versions draft-04, draft-06, draft-07, draft-2019-09 and draft-2020-12. Additionally, most format-validations are supported per default besides the listed format below. You can always override or extend format validation as is documented in [draft customization](#draft-customization).
|
|
161
174
|
|
|
162
175
|
<details><summary>Overview draft support</summary>
|
|
163
176
|
|
|
177
|
+
---
|
|
178
|
+
|
|
164
179
|
Draft support is defined by running a validator against the official [json-schema-test-suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite).
|
|
165
180
|
|
|
166
181
|
- Test results for _json-schema-library_ can be inspected in [github actions](https://github.com/sagold/json-schema-library/actions/workflows/ci.yaml)
|
|
@@ -168,13 +183,19 @@ Draft support is defined by running a validator against the official [json-schem
|
|
|
168
183
|
|
|
169
184
|
Please note that these benchmarks refer to validation only. _json-schema-library_ offers tooling outside of validation and strives to be as spec-compliant as possible.
|
|
170
185
|
|
|
186
|
+
---
|
|
187
|
+
|
|
171
188
|
</details>
|
|
172
189
|
|
|
173
190
|
<details><summary>Overview format validation support</summary>
|
|
174
191
|
|
|
192
|
+
---
|
|
193
|
+
|
|
175
194
|
- **`❌ unsupported formats`** iri, iri-reference, idn-hostname
|
|
176
195
|
- **`✅ supported formats`**: date, date-time, date, duration, ecmascript-regex, email, hostname, idn-email, ipv4, ipv6, json-pointer, regex, relative-json-pointer, time, unknown, uri-reference, uri-template, uri, uuid
|
|
177
196
|
|
|
197
|
+
---
|
|
198
|
+
|
|
178
199
|
</details>
|
|
179
200
|
|
|
180
201
|
## SchemaNode methods
|
|
@@ -193,8 +214,6 @@ Please note that these benchmarks refer to validation only. _json-schema-library
|
|
|
193
214
|
[toSchemaNodes](#toschemanodes) ·
|
|
194
215
|
[validate](#validate)
|
|
195
216
|
|
|
196
|
-
</details>
|
|
197
|
-
|
|
198
217
|
### addRemoteSchema
|
|
199
218
|
|
|
200
219
|
`addRemoteSchema` lets you add additional schemas that can be referenced by an URL using `$ref`. Use this to combine multiple schemas without changing the actual schema.
|
|
@@ -243,6 +262,8 @@ const { node, error } = schemaNode.getNodeRef("https://sagold.com/remote");
|
|
|
243
262
|
|
|
244
263
|
<details><summary>Adding remote schema to compileSchema</summary>
|
|
245
264
|
|
|
265
|
+
---
|
|
266
|
+
|
|
246
267
|
It is possible to pass remoteSchema on compileSchema by passing a SchemaNode (with all its remote schemas) in `remote`:
|
|
247
268
|
|
|
248
269
|
```ts
|
|
@@ -261,10 +282,14 @@ const remote = compileSchema({
|
|
|
261
282
|
const schemaNode = compileSchema({ $ref: "https://sagold.com/remote#/defs/character" }, { remote });
|
|
262
283
|
```
|
|
263
284
|
|
|
285
|
+
---
|
|
286
|
+
|
|
264
287
|
</details>
|
|
265
288
|
|
|
266
289
|
<details><summary>Access local subschemas in remote schemas</summary>
|
|
267
290
|
|
|
291
|
+
---
|
|
292
|
+
|
|
268
293
|
You can add a local uri reference to the remote schema by using the `#` separator. The following example resolves hte local path `/$defs/character` in the remote schema `https://sagold.com/remote` throught the combined url:
|
|
269
294
|
`https://sagold.com/remote#/$defs/character`
|
|
270
295
|
|
|
@@ -317,6 +342,8 @@ schemaNode.getData("A"); // "A" - default value resolved
|
|
|
317
342
|
schemaNode.getNodeRef("https://sagold.com/remote#/properties/character");
|
|
318
343
|
```
|
|
319
344
|
|
|
345
|
+
---
|
|
346
|
+
|
|
320
347
|
</details>
|
|
321
348
|
|
|
322
349
|
### compileSchema
|
|
@@ -463,6 +490,8 @@ expect(myData).to.deep.equal({
|
|
|
463
490
|
|
|
464
491
|
<details><summary>Option: extendDefaults (default: false)</summary>
|
|
465
492
|
|
|
493
|
+
---
|
|
494
|
+
|
|
466
495
|
Per default, `getData` does try to create data that is valid to the json-schema. Example: array-schemas with `minItems: 1` will add one item to fullfil the validation criteria. You can use the option and pass `{ extendDefaults: false }` to override this behaviour with a default value:
|
|
467
496
|
|
|
468
497
|
```ts
|
|
@@ -483,10 +512,14 @@ const myData = compileSchema(myJsonSchema).getData(undefined, { extendDefaults:
|
|
|
483
512
|
expect(myData).to.deep.equal([]);
|
|
484
513
|
```
|
|
485
514
|
|
|
515
|
+
---
|
|
516
|
+
|
|
486
517
|
</details>
|
|
487
518
|
|
|
488
519
|
<details><summary>Option: addOptionalProps (default: false)</summary>
|
|
489
520
|
|
|
521
|
+
---
|
|
522
|
+
|
|
490
523
|
`getData` will only add required properties per default:
|
|
491
524
|
|
|
492
525
|
```ts
|
|
@@ -513,10 +546,14 @@ const data = compileSchema({
|
|
|
513
546
|
console.log(data); // { title: "", subTitle: "sub-title" }
|
|
514
547
|
```
|
|
515
548
|
|
|
549
|
+
---
|
|
550
|
+
|
|
516
551
|
</details>
|
|
517
552
|
|
|
518
553
|
<details><summary>Option: removeInvalidData (default: false)</summary>
|
|
519
554
|
|
|
555
|
+
---
|
|
556
|
+
|
|
520
557
|
With `removeInvalidData:true`, `getData` will remove data that is invalid to the given schema;
|
|
521
558
|
|
|
522
559
|
```ts
|
|
@@ -537,10 +574,14 @@ const data = compileSchema({
|
|
|
537
574
|
console.log(data); // { valid: "stays", invalid: "removed" }
|
|
538
575
|
```
|
|
539
576
|
|
|
577
|
+
---
|
|
578
|
+
|
|
540
579
|
</details>
|
|
541
580
|
|
|
542
581
|
<details><summary>Option: useTypeDefaults (default: true)</summary>
|
|
543
582
|
|
|
583
|
+
---
|
|
584
|
+
|
|
544
585
|
With `useTypeDefaults:true`, `getData` will return initial values for all primitives (non-objects/arrays) that do not have a default-property set:
|
|
545
586
|
|
|
546
587
|
```ts
|
|
@@ -581,6 +622,8 @@ const data = compileSchema({
|
|
|
581
622
|
console.log(data); // { valid: [undefined] }
|
|
582
623
|
```
|
|
583
624
|
|
|
625
|
+
---
|
|
626
|
+
|
|
584
627
|
</details>
|
|
585
628
|
|
|
586
629
|
### getNode
|
|
@@ -673,6 +716,8 @@ expect(node.schema).to.deep.equal({
|
|
|
673
716
|
|
|
674
717
|
<details><summary>Evaluating errors</summary>
|
|
675
718
|
|
|
719
|
+
---
|
|
720
|
+
|
|
676
721
|
All returned json-errors have a data property with the following properties
|
|
677
722
|
|
|
678
723
|
- `pointer` JSON Pointer to the location where the error occured. In case of omitted data, this is the last JSON Schema location that could be resolved
|
|
@@ -686,12 +731,18 @@ if (error) {
|
|
|
686
731
|
}
|
|
687
732
|
```
|
|
688
733
|
|
|
734
|
+
---
|
|
735
|
+
|
|
689
736
|
</details>
|
|
690
737
|
|
|
691
738
|
<details><summary>About JsonPointer</summary>
|
|
692
739
|
|
|
740
|
+
---
|
|
741
|
+
|
|
693
742
|
**[JSON Pointer](https://tools.ietf.org/html/rfc6901)** defines a string syntax for identifying a specific value within a Json document and is [supported by Json-Schema](https://json-schema.org/understanding-json-schema/structuring.html). Given a Json document, it behaves similar to a [lodash path](https://lodash.com/docs/4.17.5#get) (`a[0].b.c`), which follows JS-syntax, but instead uses `/` separators (e.g., `a/0/b/c`). In the end, you describe a path into the Json data to a specific point.
|
|
694
743
|
|
|
744
|
+
---
|
|
745
|
+
|
|
695
746
|
</details>
|
|
696
747
|
|
|
697
748
|
### getNodeChild
|
|
@@ -757,7 +808,7 @@ if (node) {
|
|
|
757
808
|
}
|
|
758
809
|
```
|
|
759
810
|
|
|
760
|
-
|
|
811
|
+
---
|
|
761
812
|
|
|
762
813
|
### reduceNode
|
|
763
814
|
|
|
@@ -789,7 +840,8 @@ expect(reducedNode.schema).to.deep.eq({
|
|
|
789
840
|
});
|
|
790
841
|
```
|
|
791
842
|
|
|
792
|
-
>
|
|
843
|
+
> [!CAUTION]
|
|
844
|
+
> Please be aware that certain schema-definitions are lost when resolving or merging sub-schemas.
|
|
793
845
|
> This mainly refers to validation-properties, but also some ambigiuous schema might get overriden.
|
|
794
846
|
|
|
795
847
|
### toDataNodes
|
|
@@ -873,12 +925,14 @@ expect(calls).to.deep.equal([
|
|
|
873
925
|
`validate` is a complete _JSON Schema validator_ for your input data. Calling _validate_ will return a list of validation errors for the passed data.
|
|
874
926
|
|
|
875
927
|
```ts
|
|
876
|
-
const { valid, errors } = compileSchema(myJsonSchema).validate(myData);
|
|
928
|
+
const { valid, errors, annotations } = compileSchema(myJsonSchema).validate(myData);
|
|
877
929
|
// { valid: boolean, errors: JsonError[] }
|
|
878
930
|
```
|
|
879
931
|
|
|
880
932
|
<details><summary>About type JsonError</summary>
|
|
881
933
|
|
|
934
|
+
---
|
|
935
|
+
|
|
882
936
|
In _json-schema-library_ all errors are in the format of a `JsonError`:
|
|
883
937
|
|
|
884
938
|
```ts
|
|
@@ -892,9 +946,11 @@ type JsonError = {
|
|
|
892
946
|
|
|
893
947
|
In almost all cases, a JSON Pointer is given on _error.data.pointer_, which points to the source within data where the error occured. For more details on how to work with errors, refer to section [custom errors](#extending-a-draft).
|
|
894
948
|
|
|
949
|
+
---
|
|
950
|
+
|
|
895
951
|
</details>
|
|
896
952
|
|
|
897
|
-
<details><summary>Example</summary>
|
|
953
|
+
<details><summary>JsonError Example</summary>
|
|
898
954
|
|
|
899
955
|
```ts
|
|
900
956
|
const myJsonSchema: JsonSchema = { type: "object", additionalProperties: false };
|
|
@@ -913,6 +969,56 @@ expect(errors).to.deep.equal([
|
|
|
913
969
|
|
|
914
970
|
</details>
|
|
915
971
|
|
|
972
|
+
<details><summary>About type JsonAnnotation</summary>
|
|
973
|
+
|
|
974
|
+
---
|
|
975
|
+
|
|
976
|
+
In _json-schema-library_ all annotations are in the format of a `JsonAnnotation`. _Annotations_ are meta-data associated with a json-schema that are not actual errors. They can be a deprecated warning or additional resolved meta-data based on the given value. _Annotations_ do not have an affect on the `valid` property exposed by `validate()`.
|
|
977
|
+
|
|
978
|
+
```ts
|
|
979
|
+
type JsonAnnotation = {
|
|
980
|
+
type: "annotation";
|
|
981
|
+
code: string;
|
|
982
|
+
message: string;
|
|
983
|
+
data?: { [p: string]: any };
|
|
984
|
+
};
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
In all cases, a JSON Pointer is given on _annotation.data.pointer_, which points to the source within data where the error occured.
|
|
988
|
+
|
|
989
|
+
An included annotation is exposed for the keyword: `deprecated: true`:
|
|
990
|
+
|
|
991
|
+
```ts
|
|
992
|
+
const myJsonSchema: JsonSchema = { type: "object", properties: { name: { deprecated: true } } };
|
|
993
|
+
|
|
994
|
+
const { annotations } = compileSchema(myJsonSchema).validate({ name: "my-data" });
|
|
995
|
+
|
|
996
|
+
expect(annotations).to.deep.equal([
|
|
997
|
+
{
|
|
998
|
+
type: "annotation",
|
|
999
|
+
code: "deprecated-warning",
|
|
1000
|
+
message: "Value at `#/name` is deprecated",
|
|
1001
|
+
data: { pointer: "#", value: "my-data", schema: { deprecated: true } }
|
|
1002
|
+
}
|
|
1003
|
+
]);
|
|
1004
|
+
```
|
|
1005
|
+
|
|
1006
|
+
To create a custom annotation you can use the `createAnnotation` helper exposed by _SchemaNode_:
|
|
1007
|
+
|
|
1008
|
+
```ts
|
|
1009
|
+
const validation: JsonSchemaValidator = ({ node, pointer, data }) => {
|
|
1010
|
+
return node.createAnnotation("my-annotation", {
|
|
1011
|
+
schema: node.schema
|
|
1012
|
+
pointer,
|
|
1013
|
+
value: data
|
|
1014
|
+
});
|
|
1015
|
+
};
|
|
1016
|
+
```
|
|
1017
|
+
|
|
1018
|
+
---
|
|
1019
|
+
|
|
1020
|
+
</details>
|
|
1021
|
+
|
|
916
1022
|
You can also use async validators to validate data with json-schema. For this, another property asyncErrors is exposed on validate:
|
|
917
1023
|
|
|
918
1024
|
```ts
|
|
@@ -925,12 +1031,13 @@ if (errorsAsync.length > 0) {
|
|
|
925
1031
|
|
|
926
1032
|
Per default _json-schema-library_ does not contain async validators, so `errorsAsync` is always empty. If you add async validators, a list of `Promise<JsonError|undefined>` is return and you need to resolve and filter non-errors (undefined) yourself.
|
|
927
1033
|
|
|
928
|
-
>
|
|
1034
|
+
> [!NOTE]
|
|
1035
|
+
> `isValid` only refers to errors. `errorsAsync` has to be evaluated separately
|
|
929
1036
|
|
|
930
1037
|
<details><summary>Example Async Validation</summary>
|
|
931
1038
|
|
|
932
1039
|
```ts
|
|
933
|
-
import { JsonSchemaValidator, draft2020 } from "json-schema-library";
|
|
1040
|
+
import { JsonSchemaValidator, draft2020, sanitizeErrors } from "json-schema-library";
|
|
934
1041
|
// return Promise<JsonError>
|
|
935
1042
|
const customValidator: JsonSchemaValidator = async ({ node, pointer, data }) => {
|
|
936
1043
|
return node.createError("type-error", {
|
|
@@ -951,7 +1058,7 @@ const draftList = [
|
|
|
951
1058
|
const { isValid, errorsAsync } = compileSchema({ custom: true }).validate("data");
|
|
952
1059
|
console.log(isValid, errors.length); // true, 0
|
|
953
1060
|
|
|
954
|
-
const errors = await Promise.all(errorsAsync);
|
|
1061
|
+
const errors = await Promise.all(errorsAsync).then(sanitizeErrors);
|
|
955
1062
|
console.log(errors); /// [{ code: "type-error", value: "data", pointer: "#", ... }]
|
|
956
1063
|
```
|
|
957
1064
|
|
|
@@ -1103,8 +1210,7 @@ const myDraft = extendDraft(draft2020, {
|
|
|
1103
1210
|
|
|
1104
1211
|
The built-in format validators may not always align with your specific requirements. For instance, you might need to validate the output of an `<input type="time" />`, which produces values in formats like `HH:MM` or `HH:MM:SS`. In such cases, you can customize or overwrite the format validators to suit your needs using `extendDraft`
|
|
1105
1212
|
|
|
1106
|
-
<details>
|
|
1107
|
-
<summary>Example of overwriting a format validator</summary>
|
|
1213
|
+
<details><summary>Example of overwriting a format validator</summary>
|
|
1108
1214
|
|
|
1109
1215
|
```ts
|
|
1110
1216
|
import { extendDraft, draft2020 } from "json-schema-library";
|
|
@@ -1358,10 +1464,18 @@ settings.REGEX_FLAGS = "v";
|
|
|
1358
1464
|
|
|
1359
1465
|
## Breaking Changes
|
|
1360
1466
|
|
|
1361
|
-
###
|
|
1467
|
+
### v11.0.0
|
|
1362
1468
|
|
|
1363
1469
|
- introduced annotations
|
|
1470
|
+
- added node.createAnnotation helper
|
|
1364
1471
|
- changed typing to strict
|
|
1472
|
+
- added annotations-list to `validate()` result
|
|
1473
|
+
- added keyword support for `deprecated: true` which returns a `deprecated-warning` annotation
|
|
1474
|
+
|
|
1475
|
+
**breaking changes**:
|
|
1476
|
+
|
|
1477
|
+
- Return type of validators is now `ValidationReturnType` instead of `ValidationResult`
|
|
1478
|
+
- type `AnnotationData` replaces `ErroData`
|
|
1365
1479
|
|
|
1366
1480
|
### v10.5.0
|
|
1367
1481
|
|