json-schema-library 10.0.0-rc9 → 10.1.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 (210) hide show
  1. package/.mocharc.js +5 -0
  2. package/CHANGELOG.md +2 -0
  3. package/README.md +166 -62
  4. package/bowtie_jlib.js +140 -0
  5. package/dist/index.d.ts +3 -1
  6. package/dist/jsonSchemaLibrary.js +1 -1
  7. package/dist/module/index.js +22 -0
  8. package/dist/module/remotes/index.js +43 -0
  9. package/dist/module/src/Draft.js +51 -0
  10. package/dist/module/src/SchemaNode.js +281 -0
  11. package/dist/module/src/compileSchema.js +69 -0
  12. package/dist/module/src/draft04/keywords/$ref.js +132 -0
  13. package/dist/module/src/draft04/keywords/exclusiveMaximum.js +20 -0
  14. package/dist/module/src/draft04/keywords/exclusiveMinimum.js +20 -0
  15. package/dist/module/src/draft04.js +105 -0
  16. package/dist/module/src/draft06/keywords/$ref.js +60 -0
  17. package/dist/module/src/draft06.js +107 -0
  18. package/dist/module/src/draft07.js +99 -0
  19. package/dist/module/src/draft2019-09/keywords/$ref.js +182 -0
  20. package/dist/module/src/draft2019-09/keywords/additionalItems.js +57 -0
  21. package/dist/module/src/draft2019-09/keywords/items.js +64 -0
  22. package/dist/module/src/draft2019-09/keywords/unevaluatedItems.js +82 -0
  23. package/dist/module/src/draft2019-09/methods/getChildSelection.js +39 -0
  24. package/dist/module/src/draft2019-09/methods/getData.js +298 -0
  25. package/dist/module/src/draft2019.js +110 -0
  26. package/dist/module/src/draft2020.js +120 -0
  27. package/dist/module/src/draftEditor.js +31 -0
  28. package/dist/module/src/errors/errors.js +67 -0
  29. package/dist/module/src/errors/render.js +11 -0
  30. package/dist/module/src/formats/formats.js +294 -0
  31. package/dist/module/src/getNode.js +44 -0
  32. package/dist/module/src/getNodeChild.js +45 -0
  33. package/dist/module/src/isItemEvaluated.js +59 -0
  34. package/dist/module/src/isPropertyEvaluated.js +69 -0
  35. package/dist/module/src/keywords/$defs.js +25 -0
  36. package/dist/module/src/keywords/$ref.js +214 -0
  37. package/dist/module/src/keywords/additionalProperties.js +91 -0
  38. package/dist/module/src/keywords/allOf.js +48 -0
  39. package/dist/module/src/keywords/anyOf.js +46 -0
  40. package/dist/module/src/keywords/const.js +14 -0
  41. package/dist/module/src/keywords/contains.js +64 -0
  42. package/dist/module/src/keywords/dependencies.js +117 -0
  43. package/dist/module/src/keywords/dependentRequired.js +52 -0
  44. package/dist/module/src/keywords/dependentSchemas.js +85 -0
  45. package/dist/module/src/keywords/enum.js +27 -0
  46. package/dist/module/src/keywords/exclusiveMaximum.js +20 -0
  47. package/dist/module/src/keywords/exclusiveMinimum.js +20 -0
  48. package/dist/module/src/keywords/format.js +11 -0
  49. package/dist/module/src/keywords/ifthenelse.js +66 -0
  50. package/dist/module/src/keywords/items.js +55 -0
  51. package/dist/module/src/keywords/maxItems.js +18 -0
  52. package/dist/module/src/keywords/maxLength.js +23 -0
  53. package/dist/module/src/keywords/maxProperties.js +23 -0
  54. package/dist/module/src/keywords/maximum.js +31 -0
  55. package/dist/module/src/keywords/minItems.js +21 -0
  56. package/dist/module/src/keywords/minLength.js +24 -0
  57. package/dist/module/src/keywords/minProperties.js +22 -0
  58. package/dist/module/src/keywords/minimum.js +31 -0
  59. package/dist/module/src/keywords/multipleOf.js +38 -0
  60. package/dist/module/src/keywords/not.js +20 -0
  61. package/dist/module/src/keywords/oneOf.js +240 -0
  62. package/dist/module/src/keywords/pattern.js +24 -0
  63. package/dist/module/src/keywords/patternProperties.js +98 -0
  64. package/dist/module/src/keywords/prefixItems.js +46 -0
  65. package/dist/module/src/keywords/properties.js +42 -0
  66. package/dist/module/src/keywords/propertyNames.js +59 -0
  67. package/dist/module/src/keywords/required.js +25 -0
  68. package/dist/module/src/keywords/type.js +40 -0
  69. package/dist/module/src/keywords/unevaluatedItems.js +74 -0
  70. package/dist/module/src/keywords/unevaluatedProperties.js +61 -0
  71. package/dist/module/src/keywords/uniqueItems.js +30 -0
  72. package/dist/module/src/mergeNode.js +111 -0
  73. package/dist/module/src/methods/createSchema.js +33 -0
  74. package/dist/module/src/methods/getChildSelection.js +40 -0
  75. package/dist/module/src/methods/getData.js +295 -0
  76. package/dist/module/src/methods/toDataNodes.js +27 -0
  77. package/dist/module/src/methods/toSchemaNodes.js +37 -0
  78. package/dist/module/src/settings.js +19 -0
  79. package/dist/module/src/tests/spec/draft04.spec.js +11 -0
  80. package/dist/module/src/tests/spec/draft06.spec.js +11 -0
  81. package/dist/module/src/tests/spec/draft07.spec.js +11 -0
  82. package/dist/module/src/tests/spec/draft2019-09.spec.js +79 -0
  83. package/dist/module/src/tests/spec/draft2020-12.spec.js +63 -0
  84. package/dist/module/src/tests/types.js +13 -0
  85. package/dist/module/src/tests/utils/addRemotes.js +17 -0
  86. package/dist/module/src/tests/utils/getDraftTests.js +36 -0
  87. package/dist/module/src/tests/utils/runTestCases.js +102 -0
  88. package/dist/module/src/types.js +9 -0
  89. package/dist/module/src/utils/copyDraft.js +6 -0
  90. package/dist/module/src/utils/getDefaultValue.js +15 -0
  91. package/dist/module/src/utils/getPrecision.js +11 -0
  92. package/dist/module/src/utils/getSchemaType.js +122 -0
  93. package/dist/module/src/utils/getTypeOf.js +8 -0
  94. package/dist/module/src/utils/getValue.js +9 -0
  95. package/dist/module/src/utils/hasProperty.js +2 -0
  96. package/dist/module/src/utils/isEmpty.js +17 -0
  97. package/dist/module/src/utils/isObject.js +4 -0
  98. package/dist/module/src/utils/isType.js +1 -0
  99. package/dist/module/src/utils/joinId.js +40 -0
  100. package/dist/module/src/utils/mergeSchema.js +77 -0
  101. package/dist/module/src/utils/omit.js +19 -0
  102. package/dist/module/src/utils/pick.js +9 -0
  103. package/dist/module/src/utils/punycode.ucs2decode.js +43 -0
  104. package/dist/module/src/utils/sanitizeErrors.js +16 -0
  105. package/dist/module/src/utils/splitRef.js +18 -0
  106. package/dist/module/src/validateNode.js +28 -0
  107. package/dist/src/SchemaNode.d.ts +69 -12
  108. package/dist/src/keywords/dependencies.d.ts +1 -1
  109. package/dist/src/keywords/oneOf.d.ts +2 -2
  110. package/dist/src/types.d.ts +1 -1
  111. package/index.ts +3 -1
  112. package/package.json +1 -1
  113. package/src/SchemaNode.ts +87 -26
  114. package/src/compileSchema.getChild.test.ts +40 -37
  115. package/src/compileSchema.reduceSchema.test.ts +18 -31
  116. package/src/compileSchema.test.ts +11 -11
  117. package/src/compileSchema.ts +3 -4
  118. package/src/compileSchema.validate.test.ts +32 -1
  119. package/src/draft04/keywords/$ref.ts +14 -13
  120. package/src/draft06/keywords/$ref.ts +5 -5
  121. package/src/draft2019-09/keywords/$ref.ts +13 -13
  122. package/src/draft2019-09/keywords/additionalItems.ts +10 -13
  123. package/src/draft2019-09/keywords/items.ts +10 -7
  124. package/src/draft2019-09/keywords/unevaluatedItems.ts +2 -2
  125. package/src/draft2019-09/methods/getChildSchemaSelection.test.ts +2 -0
  126. package/src/draft2019-09/methods/getChildSelection.ts +3 -4
  127. package/src/draft2019-09/methods/getData.test.ts +1 -0
  128. package/src/draft2019-09/methods/getData.ts +6 -8
  129. package/src/getNodeChild.ts +2 -2
  130. package/src/keywords/$defs.ts +10 -12
  131. package/src/keywords/$ref.ts +18 -21
  132. package/src/keywords/additionalProperties.ts +11 -3
  133. package/src/keywords/allOf.ts +5 -5
  134. package/src/keywords/anyOf.ts +5 -5
  135. package/src/keywords/contains.ts +4 -4
  136. package/src/keywords/dependencies.ts +12 -14
  137. package/src/keywords/dependentSchemas.ts +4 -4
  138. package/src/keywords/ifthenelse.ts +16 -6
  139. package/src/keywords/items.ts +6 -2
  140. package/src/keywords/not.ts +2 -2
  141. package/src/keywords/oneOf.ts +5 -5
  142. package/src/keywords/patternProperties.ts +4 -4
  143. package/src/keywords/prefixItems.ts +6 -2
  144. package/src/keywords/properties.ts +3 -3
  145. package/src/keywords/propertyNames.ts +2 -2
  146. package/src/keywords/type.ts +1 -1
  147. package/src/keywords/unevaluatedItems.ts +2 -2
  148. package/src/keywords/unevaluatedProperties.ts +2 -2
  149. package/src/mergeNode.ts +2 -3
  150. package/src/methods/eachSchema.test.ts +16 -16
  151. package/src/methods/getData.ts +2 -2
  152. package/src/methods/toSchemaNodes.ts +0 -1
  153. package/src/types.ts +1 -1
  154. package/src/utils/getSchemaType.ts +9 -9
  155. package/src/utils/joinId.test.ts +8 -0
  156. package/src/utils/joinId.ts +4 -0
  157. package/src/validateNode.ts +2 -2
  158. package/src/validationPath.test.ts +1 -1
  159. package/tsconfig.json +1 -0
  160. package/webpack.config.js +49 -0
  161. package/dist/src/compileSchema.getNode.test.d.ts +0 -1
  162. package/dist/src/compileSchema.reduceSchema.test.d.ts +0 -1
  163. package/dist/src/compileSchema.test.d.ts +0 -1
  164. package/dist/src/compileSchema.validate.test.d.ts +0 -1
  165. package/dist/src/draft2019-09/compileSchema.getNode.test.d.ts +0 -1
  166. package/dist/src/draft2019-09/compileSchema.validate.test.d.ts +0 -1
  167. package/dist/src/draft2019-09/keywords/$ref.test.d.ts +0 -1
  168. package/dist/src/draft2019-09/keywords/additionalItems.test.d.ts +0 -1
  169. package/dist/src/draft2019-09/keywords/items.test.d.ts +0 -1
  170. package/dist/src/draft2019-09/methods/getChildSchemaSelection.test.d.ts +0 -1
  171. package/dist/src/draft2019-09/methods/getData.test.d.ts +0 -1
  172. package/dist/src/draft2019-09/methods/toDataNodes.test.d.ts +0 -1
  173. package/dist/src/extendDraft.test.d.ts +0 -1
  174. package/dist/src/keywords/additionalProperties.test.d.ts +0 -1
  175. package/dist/src/keywords/allOf.test.d.ts +0 -1
  176. package/dist/src/keywords/const.test.d.ts +0 -1
  177. package/dist/src/keywords/ifthenelse.test.d.ts +0 -1
  178. package/dist/src/keywords/object.test.d.ts +0 -1
  179. package/dist/src/keywords/oneOf.test.d.ts +0 -1
  180. package/dist/src/keywords/patternProperties.test.d.ts +0 -1
  181. package/dist/src/keywords/properties.test.d.ts +0 -1
  182. package/dist/src/keywords/required.test.d.ts +0 -1
  183. package/dist/src/keywords/string.test.d.ts +0 -1
  184. package/dist/src/keywords/type.test.d.ts +0 -1
  185. package/dist/src/mergeNode.test.d.ts +0 -1
  186. package/dist/src/methods/createSchema.test.d.ts +0 -1
  187. package/dist/src/methods/eachSchema.test.d.ts +0 -1
  188. package/dist/src/methods/getChildSelection.test.d.ts +0 -1
  189. package/dist/src/methods/getData.test.d.ts +0 -1
  190. package/dist/src/methods/toDataNodes.test.d.ts +0 -1
  191. package/dist/src/tests/issues/issue19.get.dependencies.test.d.ts +0 -1
  192. package/dist/src/tests/issues/issue21.getTemplate.test.d.ts +0 -1
  193. package/dist/src/tests/issues/issue22.each.test.d.ts +0 -1
  194. package/dist/src/tests/issues/issue32.getTemplate.integer.test.d.ts +0 -1
  195. package/dist/src/tests/issues/issue33.rootOneOf.test.d.ts +0 -1
  196. package/dist/src/tests/issues/issue35.oneOf.remote.test.d.ts +0 -1
  197. package/dist/src/tests/issues/issue38.getTemplate.anyOf.test.d.ts +0 -1
  198. package/dist/src/tests/issues/issue43.multipleOf.float.test.d.ts +0 -1
  199. package/dist/src/tests/issues/issue44.chainedNegLogic.test.d.ts +0 -1
  200. package/dist/src/tests/issues/issue52.test.d.ts +0 -1
  201. package/dist/src/tests/issues/issue57.allOfMutatesData.test.d.ts +0 -1
  202. package/dist/src/tests/issues/issue58.oneOfType.test.d.ts +0 -1
  203. package/dist/src/tests/issues/issue64.compileSchema.test.d.ts +0 -1
  204. package/dist/src/utils/getPrecision.test.d.ts +0 -1
  205. package/dist/src/utils/getTypeOf.test.d.ts +0 -1
  206. package/dist/src/utils/joinId.test.d.ts +0 -1
  207. package/dist/src/utils/mergeSchema.test.d.ts +0 -1
  208. package/dist/src/utils/splitRef.test.d.ts +0 -1
  209. package/dist/src/validationPath.test.d.ts +0 -1
  210. /package/dist/{src/compileSchema.getChild.test.d.ts → module/src/Keyword.js} +0 -0
package/.mocharc.js ADDED
@@ -0,0 +1,5 @@
1
+ process.env.TS_NODE_PROJECT = "./tsconfig.test.json";
2
+
3
+ module.exports = {
4
+ require: "ts-node/register"
5
+ };
package/CHANGELOG.md CHANGED
@@ -1,5 +1,7 @@
1
1
  ## Changelog
2
2
 
3
+ - reference for error-format: https://json-schema.org/blog/posts/fixing-json-schema-output
4
+
3
5
  ### v9.0.0
4
6
 
5
7
  - [Breaking] error data to always contain `schema` and `value`
package/README.md CHANGED
@@ -16,8 +16,6 @@
16
16
 
17
17
  ---
18
18
 
19
- > ⚠️ This **documentation** refers to the upcoming release **version 10**, which can be installed by `npm install json-schema-library@10.0.0-rc9`. For the latest release please refer to the **[documentation of version 9.3.5](https://github.com/sagold/json-schema-library/tree/v9.3.5)**.
20
-
21
19
  **Quick start**
22
20
 
23
21
  `npm install json-schema-library`
@@ -61,7 +59,16 @@ type CompileOptions = {
61
59
  // if format-validations should create errors. Defaults to true
62
60
  formatAssertion: boolean | "meta-schema";
63
61
  // default options for all calls to node.getData()
64
- getDataDefaultOptions?: TemplateOptions;
62
+ getDataDefaultOptions?: {
63
+ // Add all properties (required and optional) to the generated data
64
+ addOptionalProps?: boolean;
65
+ // Remove data that does not match input schema. Defaults to false
66
+ removeInvalidData?: boolean;
67
+ // Set to false to take default values as they are and not extend them. Defaults to true
68
+ extendDefaults?: boolean;
69
+ // Limits how often a $ref should be followed before aborting. Prevents infinite data-structure. Defaults to 1
70
+ recursionLimit?: number;
71
+ };
65
72
  };
66
73
  ```
67
74
 
@@ -103,12 +110,12 @@ const titleData = titleNode?.getData();
103
110
 
104
111
  ```ts
105
112
  const titleNode = compileSchema(mySchema).getNode("#/image/title");
106
- console.log(titleNode.spointer); // #/properties/image/properties/title
107
- console.log(titleNode.schemaId); // #/properties/image/properties/title
113
+ console.log(titleNode.evaluationPath); // #/properties/image/properties/title
114
+ console.log(titleNode.schemaLocation); // #/properties/image/properties/title
108
115
  ```
109
116
 
110
- - `spointer` refers to the path in schema and is extended by `$ref`, e.g. if image is defined on `$defs`: `#/properties/image/$ref/properties/title`
111
- - `schemaId` refers to the absolute path within the schema and will not change, e.g. `#/$defs/properties/title`
117
+ - `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
+ - `schemaLocation` refers to the absolute path within the schema and will not change, e.g. `#/$defs/properties/title`
112
119
 
113
120
  </details>
114
121
 
@@ -172,19 +179,19 @@ Please note that these benchmarks refer to validation only. _json-schema-library
172
179
 
173
180
  ## SchemaNode methods
174
181
 
175
- [**addRemoteSchema**](#addremoteschema) ·
176
- [**compileSchema**](#compileSchema-1) ·
177
- [**createSchema**](#createSchema) ·
178
- [**getChildSelection**](#getchildselection) ·
179
- [**getData**](#getdata) ·
180
- [**getNode**](#getnode) ·
181
- [**getNodeChild**](#getnodechild) ·
182
- [**getNodeRef**](#getnoderef) ·
183
- [**getNodeRoot**](#getnoderoot) ·
184
- [**reduceNode**](#reducenode) ·
185
- [**toDataNodes**](#todatanodes) ·
186
- [**toSchemaNodes**](#toschemanodes) ·
187
- [**validate**](#validate)
182
+ [addRemoteSchema](#addremoteschema) ·
183
+ [compileSchema](#compileSchema-1) ·
184
+ [createSchema](#createSchema) ·
185
+ [getChildSelection](#getchildselection) ·
186
+ [getData](#getdata) ·
187
+ [getNode](#getnode) ·
188
+ [getNodeChild](#getnodechild) ·
189
+ [getNodeRef](#getnoderef) ·
190
+ [getNodeRoot](#getnoderoot) ·
191
+ [reduceNode](#reducenode) ·
192
+ [toDataNodes](#todatanodes) ·
193
+ [toSchemaNodes](#toschemanodes) ·
194
+ [validate](#validate)
188
195
 
189
196
  </details>
190
197
 
@@ -192,7 +199,7 @@ Please note that these benchmarks refer to validation only. _json-schema-library
192
199
 
193
200
  `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.
194
201
 
195
- Each schemas is referenced by their unique `$id` (since draft-06, previously `id`). Usually an `$id` is specified as an url, for example `https://mydomain.com/schema/schema-name` or with a file extension like `https://mydomain.com/schema/schema-name.json`.
202
+ Each schema is referenced by their unique `$id` (since draft-06, previously `id`). Usually an `$id` is specified as an url, for example `https://mydomain.com/schema/schema-name` or with a file extension like `https://mydomain.com/schema/schema-name.json`.
196
203
 
197
204
  On a compiled schema
198
205
 
@@ -383,35 +390,35 @@ const myData = compileSchema(myJsonSchema).getData(inputData, { recursionLimit:
383
390
  <details><summary>Example</summary>
384
391
 
385
392
  ```ts
386
- import { compileSchema, JsonSchema } from 'json-schema-library';
393
+ import { compileSchema, JsonSchema } from "json-schema-library";
387
394
 
388
395
  const myJsonSchema: JsonSchema = {
389
- type: 'object',
390
- required: ['name', 'option', 'list'],
391
- properties: {
392
- name: { type: 'string' },
393
- option: {
394
- type: 'string',
395
- enum: ['first-option', 'second-option']
396
- },
397
- list: {
398
- type: 'array',
399
- items: {
400
- type: 'string',
401
- default: 'new item'
402
- },
403
- minItems: 1
396
+ type: "object",
397
+ required: ["name", "option", "list"],
398
+ properties: {
399
+ name: { type: "string" },
400
+ option: {
401
+ type: "string",
402
+ enum: ["first-option", "second-option"]
403
+ },
404
+ list: {
405
+ type: "array",
406
+ items: {
407
+ type: "string",
408
+ default: "new item"
409
+ },
410
+ minItems: 1
411
+ }
404
412
  }
405
- }
406
413
  };
407
414
 
408
415
  const schemaNode = new compileSchema(myJsonSchema);
409
416
  const myData = schemaNode.getData();
410
417
 
411
418
  expect(myData).to.deep.equal({
412
- name: ',
413
- option: 'first-option',
414
- list: ['new item']
419
+ name: "",
420
+ option: "first-option",
421
+ list: ["new item"]
415
422
  });
416
423
  ```
417
424
 
@@ -743,7 +750,7 @@ expect(reducedNode.schema).to.deep.eq({
743
750
 
744
751
  ### toDataNodes
745
752
 
746
- `each` iterates over each data-item (_object_, _array_ and _value_) and emits the data-item, schema and location to a callback.
753
+ `toDataNodes` collects all data-items (_object_, _array_ and _value_) and their SchemaNode and return them as a list of **DataNodes**:
747
754
 
748
755
  ```ts
749
756
  type DataNode = { pointer: string; value: unknown; node: SchemaNode };
@@ -779,7 +786,7 @@ expect(calls).to.deep.equal([
779
786
 
780
787
  ### toSchemaNodes
781
788
 
782
- `eachSchema` emits each sub-schema definition to a callback. A sub-schema is any schema-definition like in `properties["property"]`, `anyOf[1]`, `contains`, `$defs["name"]`, etc.
789
+ `toSchemaNodes` collects all sub-schema definitions, like in `properties["property"]`, `anyOf[1]`, `contains`, `$defs["name"]`, etc. and returns them as a list of **SchemaNodes**:
783
790
 
784
791
  ```ts
785
792
  const nodes: SchemaNode[] = compileSchema(mySchema).toSchemaNodes();
@@ -846,10 +853,7 @@ In almost all cases, a JSON Pointer is given on _error.data.pointer_, which poin
846
853
  <details><summary>Example</summary>
847
854
 
848
855
  ```ts
849
- const myJsonSchema: JsonSchema = {
850
- type: "object",
851
- additionalProperties: false
852
- };
856
+ const myJsonSchema: JsonSchema = { type: "object", additionalProperties: false };
853
857
 
854
858
  const { errors } = compileSchema(myJsonSchema).validate({ name: "my-data" });
855
859
 
@@ -868,14 +872,14 @@ expect(errors).to.deep.equal([
868
872
  You can also use async validators to validate data with json-schema. For this, another property asyncErrors is exposed on validate:
869
873
 
870
874
  ```ts
871
- const { isValid, errors, errorsAsync } = compileSchema(myJsonSchema).validate(myData);
875
+ const { errorsAsync } = compileSchema(myJsonSchema).validate(myData);
872
876
 
873
877
  if (errorsAsync.length > 0) {
874
878
  const additionalErrors = (await Promise.all(errorsAsync)).filter((err) => err != null);
875
879
  }
876
880
  ```
877
881
 
878
- Per default _json-schema-library_ does not have 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.
882
+ 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.
879
883
 
880
884
  > **Note** `isValid` only refers to errors. `errorsAsync` has to be evaluated separately
881
885
 
@@ -1051,17 +1055,73 @@ const myDraft = extendDraft(draft2020, {
1051
1055
  });
1052
1056
  ```
1053
1057
 
1054
- <details><summary>About `oneOfFuzzyKeyword`</summary>
1058
+ ### Overwrite a format validator
1055
1059
 
1056
- If you're working with complex schemas that use the `oneOf` keyword to validate multiple options, `oneOfFuzzyKeyword` offers an alternative approach. It scores the schemas to return the best match, even if none of the schemas fully validate the input data. This makes error messages more readable and helps identify the most appropriate schema when multiple options exist.
1060
+ 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`
1057
1061
 
1058
- `oneOfFuzzyKeyword` helps when no schema fully validates the data but you want to prioritize schemas based on how well they fit the input. This makes it easier to interpret validation results for complex conditions.
1062
+ <details>
1063
+ <summary>Example of overwriting a format validator</summary>
1064
+
1065
+ ```ts
1066
+ import { extendDraft, draft2020 } from "json-schema-library";
1067
+
1068
+ /**
1069
+ * A Regexp that extends http://tools.ietf.org/html/rfc3339#section-5.6 spec.
1070
+ * The specification requires seconds and timezones to be a valid date format.
1071
+ *
1072
+ * matchTimeSecondsAndTimeOptional matches:
1073
+ * - HH:MM:SSz
1074
+ * - HH:MM:SS(+/-)HH:MM
1075
+ * - HH:MM:SS
1076
+ * - HH:MMz
1077
+ * - HH:MM(+/-)HH:MM
1078
+ * - HH:MM
1079
+ */
1080
+ const matchTimeSecondsAndTimeOptional =
1081
+ /^(?<time>(?:([0-1]\d|2[0-3]):[0-5]\d(:(?<second>[0-5]\d|60))?))(?:\.\d+)?(?<offset>(?:z|[+-]([0-1]\d|2[0-3])(?::?[0-5]\d)?)?)$/i;
1082
+
1083
+ const customTimeFormatDraft = extendDraft(draft2020, {
1084
+ formats: {
1085
+ // This example extends the default time formatter which validates against RFC3339
1086
+ time: ({ node, pointer, data }) => {
1087
+ const { schema } = node;
1088
+ if (typeof data !== "string" || data === "") {
1089
+ return undefined;
1090
+ }
1091
+
1092
+ // Use the Custom Regex to validate the date and time.
1093
+ const matches = data.match(matchTimeSecondsAndTimeOptional);
1094
+ if (!matches) {
1095
+ return node.createError("format-date-time-error", { value: data, pointer, schema });
1096
+ }
1097
+
1098
+ // leap second
1099
+ if (matches.groups.second === "60") {
1100
+ // Omitted the code here for brevity.
1101
+ }
1102
+
1103
+ return undefined;
1104
+ }
1105
+ }
1106
+ });
1107
+
1108
+ const { errors, valid } = compileSchema(
1109
+ {
1110
+ type: "string",
1111
+ format: "time",
1112
+ $schema: "https://json-schema.org/draft/2020-12/schema"
1113
+ },
1114
+ { drafts: [customTimeFormatDraft] }
1115
+ ).validate("15:31:12");
1116
+
1117
+ console.assert(valid, errors.at(0)?.message);
1118
+ ```
1059
1119
 
1060
1120
  </details>
1061
1121
 
1062
1122
  ### Keyword
1063
1123
 
1064
- `Keywords` hold the main logic for JSON Schema functionality. Each `Keyword` corresponds to a JSON Schema keyword like `properties`, `prefixItems`, `oneOf`, etc and offers implementations to `parse`, `validate`, `resolve` and `reduce`. Note that support for each implementation is optional, dependending on the feature requirements. The main properties of a `Keyword`:
1124
+ **Keywords** hold the main logic for JSON Schema functionality. Each `Keyword` corresponds to a JSON Schema keyword like `properties`, `prefixItems`, `oneOf`, etc and offers implementations to `parse`, `validate`, `resolve` and `reduce`. Note that support for each implementation is optional, dependending on the feature requirements. The main properties of a `Keyword`:
1065
1125
 
1066
1126
  - a `Keyword` is only processed if the specified `keyword` is available as property on the JSON Schema
1067
1127
  - an optional `order` property may be added as order of keyword execution is sometimes important (`additionalItems` last, `$ref` evaluation first)
@@ -1099,9 +1159,9 @@ export const notKeyword: Keyword = {
1099
1159
  };
1100
1160
 
1101
1161
  export function parseNot(node: SchemaNode) {
1102
- const { schema, spointer, schemaId } = node;
1162
+ const { schema, evaluationPath, schemaLocation } = node;
1103
1163
  if (schema.not != null) {
1104
- node.not = node.compileSchema(schema.not, `${spointer}/not`, `${schemaId}/not`);
1164
+ node.not = node.compileSchema(schema.not, `${evaluationPath}/not`, `${schemaLocation}/not`);
1105
1165
  }
1106
1166
  }
1107
1167
  ```
@@ -1149,7 +1209,7 @@ export const typeKeyword: Keyword = {
1149
1209
  function reduceType({ node, pointer, data }: JsonSchemaReducerParams): undefined | SchemaNode {
1150
1210
  const dataType = getJsonSchemaType(data, node.schema.type);
1151
1211
  if (dataType !== "undefined" && Array.isArray(node.schema.type) && node.schema.type.includes(dataType)) {
1152
- return node.compileSchema({ ...node.schema, pointer, type: dataType }, node.spointer);
1212
+ return node.compileSchema({ ...node.schema, pointer, type: dataType }, node.evaluationPath);
1153
1213
  }
1154
1214
  return undefined;
1155
1215
  }
@@ -1157,6 +1217,13 @@ function reduceType({ node, pointer, data }: JsonSchemaReducerParams): undefined
1157
1217
 
1158
1218
  </details>
1159
1219
 
1220
+ Currently **keywords** are not exposed per default. You can still access any keyword implementation by retrieving them from a draft:
1221
+
1222
+ ```ts
1223
+ import { draft07 } from "json-schema-library";
1224
+ const dependentSchemasKeyword = draft2020.keywords.find((f) => f.keyword === "dependentSchemas");
1225
+ ```
1226
+
1160
1227
  ## Keyword extensions
1161
1228
 
1162
1229
  ### oneOfProperty
@@ -1193,8 +1260,45 @@ expect(resolvedNode?.schema).to.deep.eq({
1193
1260
  });
1194
1261
  ```
1195
1262
 
1263
+ ### oneOfFuzzyKeyword
1264
+
1265
+ If you're working with complex schemas that use the `oneOf` keyword to validate multiple options, `oneOfFuzzyKeyword` offers an alternative approach. It scores the schemas to return the best match, even if none of the schemas fully validate the input data. This makes error messages more readable and helps identify the most appropriate schema when multiple options exist.
1266
+
1267
+ `oneOfFuzzyKeyword` helps when no schema fully validates the data but you want to prioritize schemas based on how well they fit the input. This makes it easier to interpret validation results for complex conditions.
1268
+
1269
+ `oneOfFuzzyKeyword` is exposed by _json-schema-library_ and can be used to extend any draft.
1270
+
1271
+ ```ts
1272
+ import { extendDraft, oneOfFuzzyKeyword, draft2020 } from "json-schema-library";
1273
+
1274
+ const myDraft = extendDraft(draft2020, {
1275
+ keywords: [oneOfFuzzyKeyword]
1276
+ });
1277
+ ```
1278
+
1279
+ ### errorMessages
1280
+
1281
+ You can set custom errors messages locally by using the errors-keyword:
1282
+
1283
+ ```ts
1284
+ const { errors } = compileSchema({
1285
+ type: "array",
1286
+ minItems: 2,
1287
+ errorMessages: {
1288
+ "min-items-error": "Custom error {{minItems}}"
1289
+ }
1290
+ }).validate([1]);
1291
+
1292
+ assert.deepEqual(errors[0].message, "Custom error 2");
1293
+ ```
1294
+
1196
1295
  ## Breaking Changes
1197
1296
 
1297
+ ### v10.1.0
1298
+
1299
+ - replaced `node.additionalItems` by `node.items` for drafts below 2020-12
1300
+ - fixed `additionalItems` behaviour to be ignored when `schema.items` is not an array
1301
+
1198
1302
  ### v10.0.0
1199
1303
 
1200
1304
  > This update involves some significant changes in how you work with the library, so please carefully review the migration guide and adjust your implementation accordingly.
@@ -1212,13 +1316,13 @@ The new implementation revolves around compiling schemas into a **SchemaNode** t
1212
1316
 
1213
1317
  **`compileSchema`** is now a standalone function and replaces the `Draft` class. All return values for JSON Schema are now `SchemaNode` objects that contain a `schema` property.
1214
1318
 
1215
- ```ts
1216
- // PREVIOUSLY
1217
- const draft = new Draft(schema);
1319
+ ```ts
1320
+ // PREVIOUSLY
1321
+ const draft = new Draft(schema);
1218
1322
 
1219
- // NOW
1220
- const node = compileSchema(schema);
1221
- ```
1323
+ // NOW
1324
+ const node = compileSchema(schema);
1325
+ ```
1222
1326
 
1223
1327
  **Changed Methods**:
1224
1328
 
package/bowtie_jlib.js ADDED
@@ -0,0 +1,140 @@
1
+ /**
2
+ * test file for bowtie integration
3
+ *
4
+ * - Tutorial: https://docs.bowtie.report/en/stable/implementers/
5
+ *
6
+ * Build Dockerfile:
7
+ *
8
+ * ```
9
+ * docker build -t localhost/jlib .
10
+ * ````
11
+ *
12
+ * Test setup:
13
+ *
14
+ * ```
15
+ bowtie run -i localhost/jlib -V <<EOF
16
+ {"description": "test case 1", "schema": {}, "tests": [{"description": "a test", "instance": {}}] }
17
+ {"description": "test case 2", "schema": {"const": 37}, "tests": [{"description": "not 37", "instance": {}}, {"description": "is 37", "instance": 37}] }
18
+ EOF
19
+ *
20
+ * Test draft
21
+ *
22
+ * ```
23
+ * bowtie suite -i localhost/jlib draft7 | bowtie summary --show failures
24
+ * ```
25
+ *
26
+ */
27
+ const readline = require("readline/promises");
28
+ const process = require("process");
29
+ const os = require("os");
30
+ const packageJson = require("./package.json");
31
+ const jlib = require("./dist/jsonSchemaLibrary.js");
32
+
33
+ const compileSchema = jlib.compileSchema;
34
+
35
+ const stdio = readline.createInterface({
36
+ input: process.stdin,
37
+ output: process.stdout,
38
+ terminal: false
39
+ });
40
+
41
+ // const schemaIds: { [id: string]: SchemaDraft } = {
42
+ // "https://json-schema.org/draft/2020-12/schema": SchemaDraft.v2020_12,
43
+ // "https://json-schema.org/draft/2019-09/schema": SchemaDraft.v2019_09,
44
+ // "http://json-schema.org/draft-07/schema#": SchemaDraft.v7,
45
+ // "http://json-schema.org/draft-06/schema#": SchemaDraft.v6,
46
+ // "http://json-schema.org/draft-04/schema#": SchemaDraft.v4
47
+ // };
48
+
49
+ function send(data) {
50
+ console.log(JSON.stringify(data));
51
+ }
52
+
53
+ let started = false;
54
+ // let dialect;
55
+
56
+ const cmds = {
57
+ start: async (args) => {
58
+ console.assert(args.version === 1, { args });
59
+ started = true;
60
+ return {
61
+ version: 1,
62
+ implementation: {
63
+ language: "javascript",
64
+ name: "json-schema-library",
65
+ version: packageJson.version,
66
+ homepage: "https://github.com/sagold/json-schema-library",
67
+ issues: "https://github.com/sagold/json-schema-library/issues",
68
+ source: "https://github.com/sagold/json-schema-library",
69
+
70
+ dialects: [
71
+ "https://json-schema.org/draft/2020-12/schema",
72
+ "https://json-schema.org/draft/2019-09/schema",
73
+ "http://json-schema.org/draft-07/schema#",
74
+ "http://json-schema.org/draft-06/schema#",
75
+ "http://json-schema.org/draft-04/schema#"
76
+ ],
77
+ os: os.platform(),
78
+ os_version: os.release(),
79
+ language_version: process.version
80
+ }
81
+ };
82
+ },
83
+
84
+ dialect: async (args) => {
85
+ console.assert(started, "Not started!");
86
+ // dialect = schemaIds[args.dialect];
87
+ return { ok: true };
88
+ },
89
+
90
+ run: async (args) => {
91
+ console.assert(started, "Not started!");
92
+
93
+ // for (const id in testCase.registry) {
94
+ // ajv.addSchema(testCase.registry[id], id);
95
+ // }
96
+
97
+ const testCase = args.case;
98
+ // as {
99
+ // registry: Recors<sring, string>;
100
+ // schema: Record<string, any>;
101
+ // tests: {
102
+ // /** testdata */
103
+ // instance: unknown;
104
+ // }[];
105
+ // };
106
+
107
+ const node = compileSchema(testCase.schema);
108
+ const results = testCase.tests.map((test) => {
109
+ try {
110
+ const errors = node.validate(test.instance);
111
+ return { valid: errors.length === 0 };
112
+ } catch (error) {
113
+ return {
114
+ errored: true,
115
+ context: {
116
+ traceback: error.stack,
117
+ message: error.message
118
+ }
119
+ };
120
+ }
121
+ });
122
+
123
+ return { seq: args.seq, results: results };
124
+ },
125
+
126
+ stop: async (_) => {
127
+ console.assert(started, "Not started!");
128
+ process.exit(0);
129
+ }
130
+ };
131
+
132
+ async function main() {
133
+ for await (const line of stdio) {
134
+ const request = JSON.parse(line);
135
+ const response = await cmds[request.cmd](request);
136
+ send(response);
137
+ }
138
+ }
139
+
140
+ main();
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { compileSchema } from "./src/compileSchema";
2
2
  export type { CompileOptions } from "./src/compileSchema";
3
- export type { Context, SchemaNode, GetNodeOptions } from "./src/SchemaNode";
3
+ export type { Context, SchemaNode, GetNodeOptions, ValidateReturnType } from "./src/SchemaNode";
4
4
  export type { DataNode } from "./src/methods/toDataNodes";
5
5
  export type { Draft, DraftVersion } from "./src/Draft";
6
6
  export type { JsonError, JsonPointer, JsonSchema, OptionalNodeOrError, NodeOrError } from "./src/types";
@@ -9,6 +9,7 @@ export { draft04 } from "./src/draft04";
9
9
  export { draft06 } from "./src/draft06";
10
10
  export { draft07 } from "./src/draft07";
11
11
  export { draft2019 } from "./src/draft2019";
12
+ export { draft2020 } from "./src/draft2020";
12
13
  export { draftEditor } from "./src/draftEditor";
13
14
  export { oneOfFuzzyKeyword, oneOfKeyword } from "./src/keywords/oneOf";
14
15
  export { render } from "./src/errors/render";
@@ -19,4 +20,5 @@ export { isJsonError, isSchemaNode } from "./src/types";
19
20
  export { extendDraft, addKeywords } from "./src/Draft";
20
21
  export { mergeNode } from "./src/mergeNode";
21
22
  export { mergeSchema } from "./src/utils/mergeSchema";
23
+ export { getSchemaType } from "./src/utils/getSchemaType";
22
24
  export { remotes } from "./remotes";