json-schema-library 11.3.0 → 11.4.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 (56) hide show
  1. package/CHANGELOG.md +21 -2
  2. package/README.md +44 -35
  3. package/bowtie/bowtie.test.ts +80 -0
  4. package/bowtie/package.json +1 -1
  5. package/dist/chunk-350yNsax.cjs +1 -0
  6. package/dist/formats.cjs +2 -0
  7. package/dist/formats.cjs.map +1 -0
  8. package/dist/formats.d.cts +8 -0
  9. package/dist/formats.d.mts +8 -0
  10. package/dist/formats.mjs +2 -0
  11. package/dist/formats.mjs.map +1 -0
  12. package/dist/index.cjs +2 -1
  13. package/dist/index.cjs.map +1 -0
  14. package/dist/index.d.cts +4 -4
  15. package/dist/index.d.mts +4 -4
  16. package/dist/index.mjs +2 -1
  17. package/dist/index.mjs.map +1 -0
  18. package/dist/jlib.js +2 -2
  19. package/dist/jlibFormats.iife.js +1 -0
  20. package/dist/jlibRemote.iife.js +1 -0
  21. package/dist/{remotes/index.cjs → remotes.cjs} +2 -1
  22. package/dist/remotes.cjs.map +1 -0
  23. package/dist/remotes.d.cts +8 -0
  24. package/dist/remotes.d.mts +8 -0
  25. package/dist/{remotes/index.mjs → remotes.mjs} +2 -1
  26. package/dist/remotes.mjs.map +1 -0
  27. package/dist/{types-B2wwNWyo.d.cts → types-BDjKcTVR.d.cts} +6 -3
  28. package/dist/{types-BhTU1l2h.d.mts → types-CqkCJmt8.d.mts} +6 -3
  29. package/package.json +21 -15
  30. package/src/SchemaNode.ts +15 -19
  31. package/src/compileSchema.ts +1 -3
  32. package/src/errors/errors.ts +3 -2
  33. package/src/formats/additionalFormats.ts +118 -0
  34. package/src/formats/formats.ts +3 -111
  35. package/src/keywords/$defs.ts +3 -0
  36. package/src/keywords/additionalProperties.ts +1 -0
  37. package/src/keywords/allOf.ts +2 -5
  38. package/src/keywords/anyOf.ts +2 -4
  39. package/src/keywords/dependencies.ts +2 -0
  40. package/src/keywords/dependentSchemas.ts +2 -3
  41. package/src/keywords/format.ts +8 -0
  42. package/src/keywords/ifthenelse.ts +4 -9
  43. package/src/keywords/oneOf.ts +2 -5
  44. package/src/keywords/patternProperties.ts +5 -1
  45. package/src/keywords/prefixItems.ts +14 -9
  46. package/src/keywords/properties.ts +2 -3
  47. package/src/keywords/propertyDependencies.ts +2 -3
  48. package/src/keywords/propertyNames.ts +1 -1
  49. package/src/utils/collectValidationErrors.ts +9 -0
  50. package/src/validateSchema.test.ts +29 -30
  51. package/tsconfig.json +1 -0
  52. package/tsconfig.test.json +1 -0
  53. package/tsdown.config.ts +5 -2
  54. package/tsdown.iife.config.ts +29 -8
  55. package/dist/remotes/index.d.cts +0 -7
  56. package/dist/remotes/index.d.mts +0 -7
package/CHANGELOG.md CHANGED
@@ -1,9 +1,28 @@
1
1
  ## Changelog
2
2
 
3
+ ### v11.4.0
4
+
5
+ - added schema annotation on `compileSchema` for unknown format
6
+ - replaced option `withSchemaAnnotations` in favor of always creating all annotations
7
+
8
+ **Breaking change**: Moved some large format-validators to separate entry point:
9
+
10
+ - the following format-validators have been moved to a separate entry point "json-schema-library/formats": `hostname`, `idn-email`, `ipv4`, `ipv6`, `uri`, `uri-reference`, `uri-template`
11
+ - the following additional format-validators are available through "json-schema-library/formats": `iri`, `iri-reference`, `idn-hostname`
12
+
13
+ _Use the following to add the additional format validators to drafts per default:_
14
+
15
+ ```ts
16
+ import { addFormats } from "json-schema-library/formats";
17
+ import { draft04, draft06, draft07, draft2019, draft2020 } from "json-schema-library";
18
+ // add additional formats to the following drafts
19
+ addFormats([draft04, draft06, draft07, draft2019, draft2020]);
20
+ ```
21
+
3
22
  ### v11.3.0
4
23
 
5
- - added option 'draft' as fallback for a missing `$schema` id
6
- - added properties to merge when resolvinf a $ref to `settings.PROPERTIES_TO_MERGE`
24
+ - added option `draft` as fallback for a missing `$schema` id
25
+ - added setting for properties to merge when resolving a `$ref` to `settings.PROPERTIES_TO_MERGE`
7
26
 
8
27
  ### v11.2.0
9
28
 
package/README.md CHANGED
@@ -46,6 +46,11 @@ console.log(schemaNode.getDraftVersion()); // draft-07
46
46
 
47
47
  ## Overview
48
48
 
49
+ [compileSchema](#compileschema) ·
50
+ [validate input schema](#validate-input-schema) ·
51
+ [SchemaNode](#schemanode) ·
52
+ [Draft Support](#draft-support)
53
+
49
54
  ### compileSchema
50
55
 
51
56
  Use `compileSchema` once to turn a JSON Schema into a tree of SchemaNodes. After that, you'll work with individual nodes in the tree. You can also pass an options object to `compileSchema` to customize how the nodes are created.
@@ -54,25 +59,25 @@ Use `compileSchema` once to turn a JSON Schema into a tree of SchemaNodes. After
54
59
  type CompileOptions = {
55
60
  // set of drafts to use
56
61
  drafts: Draft[];
62
+ /** fallback draft version in case no draft_is specified by `schema.$schema` */
63
+ draft?: string;
57
64
  // a context to share
58
65
  remote: SchemaNode;
59
66
  // if format-validations should create errors. Defaults to true
60
67
  formatAssertion: boolean | "meta-schema";
61
68
  /** set to true to throw an Error on errors in input schema. Defaults to false */
62
69
  throwOnInvalidSchema?: boolean;
63
- /** set to true to collect unknown keywords of input schema in `node.schemaAnnotations`. Defaults to false */
64
- withSchemaAnnotations?: boolean;
65
70
  /** set to true to throw an Error when encountering an unresolvable ref */
66
71
  throwOnInvalidRef?: boolean;
67
72
  // default options for all calls to node.getData()
68
73
  getDataDefaultOptions?: {
69
- // Add all properties (required and optional) to the generated data
74
+ // add all properties (required and optional) to the generated data
70
75
  addOptionalProps?: boolean;
71
- // Remove data that does not match input schema. Defaults to false
76
+ // remove data that does not match input schema. Defaults to false
72
77
  removeInvalidData?: boolean;
73
- // Set to false to take default values as they are and not extend them. Defaults to true
78
+ // set to false to take default values as they are and not extend them. Defaults to true
74
79
  extendDefaults?: boolean;
75
- // Limits how often a $ref should be followed before aborting. Prevents infinite data-structure. Defaults to 1
80
+ // limits how often a $ref should be followed before aborting. Prevents infinite data-structure. Defaults to 1
76
81
  recursionLimit?: number;
77
82
  };
78
83
  };
@@ -251,7 +256,19 @@ Note that rootNodes will change when working across remote schema (using $ref).
251
256
 
252
257
  ### Draft Support
253
258
 
254
- _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).
259
+ _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, all JSON Schema format validators are supported:
260
+
261
+ - The following formats are **available per default**: `date`, `date-time`, `duration`, `email`, `json-pointer`, `relative-json-pointer`, `regex`, `time`, `url`, `uuid`
262
+ - **Add remaining format** validators `hostname`, `idn-email`, `ipv4`, `ipv6`, `uri`, `uri-reference`, `uri-template` to drafts with:
263
+
264
+ ```ts
265
+ import { addFormats } from "json-schema-library/formats";
266
+ import { draft04, draft06, draft07, draft2019, draft2020 } from "json-schema-library";
267
+ // add additional formats to the following drafts
268
+ addFormats([draft04, draft06, draft07, draft2019, draft2020]);
269
+ ```
270
+
271
+ You can always override or extend format validation as is documented in [draft customization](#draft-customization).
255
272
 
256
273
  <details><summary>Overview draft support</summary>
257
274
 
@@ -268,17 +285,6 @@ Please note that these benchmarks refer to validation only. _json-schema-library
268
285
 
269
286
  </details>
270
287
 
271
- <details><summary>Overview format validation support</summary>
272
-
273
- ---
274
-
275
- - **`❌ unsupported formats`** iri, iri-reference, idn-hostname
276
- - **`✅ 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
277
-
278
- ---
279
-
280
- </details>
281
-
282
288
  ## SchemaNode methods
283
289
 
284
290
  [addRemoteSchema](#addremoteschema) ·
@@ -435,6 +441,22 @@ schemaNode.getNodeRef("https://sagold.com/remote#/properties/character");
435
441
  const someNode = node.compileSchema({ prefixItems: [{ type: "string" }, { $ref: "#/$defs/string" }] });
436
442
  ```
437
443
 
444
+ #### custom error messages
445
+
446
+ You can set custom errors messages locally by using the errors-keyword:
447
+
448
+ ```ts
449
+ const { errors } = compileSchema({
450
+ type: "array",
451
+ minItems: 2,
452
+ errorMessages: {
453
+ "min-items-error": "Custom error {{minItems}}"
454
+ }
455
+ }).validate([1]);
456
+
457
+ assert.deepEqual(errors[0].message, "Custom error 2");
458
+ ```
459
+
438
460
  ### createSchema
439
461
 
440
462
  `createSchema` returns a simple JSON Schema for the input data.
@@ -892,7 +914,8 @@ if (node) {
892
914
  }
893
915
  ```
894
916
 
895
- ---
917
+ > [!CAUTION]
918
+ > `getNode` returns the root of the current schema. If a remote schema was resolved, the returned node will be the remote-schema root - not the initial schema-root you passed in to compileSchema
896
919
 
897
920
  ### reduceNode
898
921
 
@@ -1150,7 +1173,7 @@ console.log(errors); /// [{ code: "type-error", value: "data", pointer: "#", ...
1150
1173
 
1151
1174
  ## Draft Customization
1152
1175
 
1153
- [**Extending a Draft**](#extending-a-draft) · [**Keyword**](#keyword)
1176
+ [Extending a Draft](#extending-a-draft) · [Overwrite format validator](#overwrite-a-format-validator) · [Keyword](#keyword)
1154
1177
 
1155
1178
  _json-schema-library_ uses the concept of **drafts** to support different versions of the JSON Schema specification — such as Draft 04, Draft 07, or 2020-12 — and to allow customization of schema behavior.
1156
1179
 
@@ -1549,21 +1572,7 @@ const myDraft = extendDraft(draft2020, {
1549
1572
  });
1550
1573
  ```
1551
1574
 
1552
- ### errorMessages
1553
-
1554
- You can set custom errors messages locally by using the errors-keyword:
1555
-
1556
- ```ts
1557
- const { errors } = compileSchema({
1558
- type: "array",
1559
- minItems: 2,
1560
- errorMessages: {
1561
- "min-items-error": "Custom error {{minItems}}"
1562
- }
1563
- }).validate([1]);
1564
-
1565
- assert.deepEqual(errors[0].message, "Custom error 2");
1566
- ```
1575
+ ## Settings
1567
1576
 
1568
1577
  ### regexFlags
1569
1578
 
@@ -14,6 +14,86 @@ const isErrorResponse = (value: unknown): value is ErrorResponse =>
14
14
  const remote = compileSchema({ $id: "draft2020-12" });
15
15
  remotes.map((schema: JsonSchema) => remote.addRemoteSchema(schema.$id ?? schema.id, schema));
16
16
 
17
+ describe("bowtie (draft4)", async () => {
18
+ before(async () => {
19
+ await runCommand({ cmd: "start", version: 1 });
20
+ await runCommand({ cmd: "dialect", dialect: "http://json-schema.org/draft-04/schema#" });
21
+ });
22
+ after(async () => runCommand({ cmd: "stop" }));
23
+
24
+ const registry = {
25
+ "http://localhost:1234/draft4/name.json": {
26
+ definitions: { orNull: { anyOf: [{ type: "null" }, { $ref: "#" }] } },
27
+ type: "string"
28
+ },
29
+ "http://localhost:1234/v1/nested-absolute-ref-to-string.json": {
30
+ $defs: { bar: { $id: "http://localhost:1234/v1/the-nested-id.json", type: "string" } },
31
+ $ref: "http://localhost:1234/v1/the-nested-id.json"
32
+ },
33
+ "http://localhost:1234/nested/string.json": { type: "string" },
34
+ "http://localhost:1234/baseUriChange/folderInteger.json": { type: "integer" },
35
+ "http://localhost:1234/draft4/subSchemas.json": {
36
+ definitions: { integer: { type: "integer" }, refToInteger: { $ref: "#/definitions/integer" } }
37
+ },
38
+ "http://localhost:1234/v1/different-id-ref-string.json": {
39
+ $id: "http://localhost:1234/v1/real-id-ref-string.json",
40
+ $defs: { bar: { type: "string" } },
41
+ $ref: "#/$defs/bar"
42
+ },
43
+ "http://localhost:1234/v1/urn-ref-string.json": {
44
+ $id: "urn:uuid:feebdaed-ffff-0000-ff01-0000deadbeef",
45
+ $defs: { bar: { type: "string" } },
46
+ $ref: "#/$defs/bar"
47
+ },
48
+ "http://localhost:1234/integer.json": { type: "integer" },
49
+ "http://localhost:1234/nested/foo-ref-string.json": {
50
+ type: "object",
51
+ properties: { foo: { $ref: "string.json" } }
52
+ },
53
+ "http://localhost:1234/baseUriChangeFolder/folderInteger.json": { type: "integer" },
54
+ "http://localhost:1234/draft4/locationIndependentIdentifier.json": {
55
+ definitions: { refToInteger: { $ref: "#foo" }, A: { id: "#foo", type: "integer" } }
56
+ },
57
+ "http://localhost:1234/baseUriChangeFolderInSubschema/folderInteger.json": { type: "integer" }
58
+ };
59
+
60
+ it("Location-independent identifier in remote ref - additional items match schema", async () => {
61
+ const response = await runCommand({
62
+ cmd: "run",
63
+ seq: 1,
64
+ case: {
65
+ description: "Location-independent identifier in remote ref",
66
+ schema: {
67
+ $ref: "http://localhost:1234/draft4/locationIndependentIdentifier.json#/definitions/refToInteger"
68
+ },
69
+ registry,
70
+ tests: [{ description: "integer is valid", instance: 1, valid: true }]
71
+ }
72
+ });
73
+ assert(isRunCmdResponse(response));
74
+ assert(!isErrorResponse(response.results[0]));
75
+ assert.equal(response.results[0].valid, true);
76
+ });
77
+
78
+ it("Location-independent identifier in remote ref - additional items do not match schema", async () => {
79
+ const response = await runCommand({
80
+ cmd: "run",
81
+ seq: 1,
82
+ case: {
83
+ description: "Location-independent identifier in remote ref",
84
+ schema: {
85
+ $ref: "http://localhost:1234/draft4/locationIndependentIdentifier.json#/definitions/refToInteger"
86
+ },
87
+ registry,
88
+ tests: [{ description: "string is invalid", instance: "foo", valid: false }]
89
+ }
90
+ });
91
+ assert(isRunCmdResponse(response));
92
+ assert(!isErrorResponse(response.results[0]));
93
+ assert.equal(response.results[0].valid, false);
94
+ });
95
+ });
96
+
17
97
  describe("bowtie (draft7)", async () => {
18
98
  before(async () => {
19
99
  await runCommand({ cmd: "start", version: 1 });
@@ -5,7 +5,7 @@
5
5
  "format": "prettier -w ."
6
6
  },
7
7
  "dependencies": {
8
- "json-schema-library": ">=11.2.0",
8
+ "json-schema-library": ">=11.3.1",
9
9
  "prettier": "^3.8.1"
10
10
  }
11
11
  }
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));Object.defineProperty(exports,`n`,{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return o}});