json-schema-library 6.1.0 → 7.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.
Files changed (142) hide show
  1. package/.editorconfig +1 -0
  2. package/CHANGELOG.md +106 -0
  3. package/README.md +811 -200
  4. package/TASKS.md +3 -81
  5. package/dist/index.d.ts +23 -34
  6. package/dist/jsonSchemaLibrary.js +1 -1
  7. package/dist/lib/SchemaService.d.ts +6 -8
  8. package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
  9. package/dist/lib/addValidator.d.ts +1 -1
  10. package/dist/lib/compile/getRef.d.ts +2 -1
  11. package/dist/lib/compile/index.d.ts +8 -5
  12. package/dist/lib/compile/types.d.ts +5 -0
  13. package/dist/lib/draft/index.d.ts +132 -0
  14. package/dist/lib/draft04/index.d.ts +7 -0
  15. package/dist/lib/draft06/compile/index.d.ts +2 -1
  16. package/dist/lib/draft06/index.d.ts +7 -0
  17. package/dist/lib/draft06/validation/type.d.ts +3 -10
  18. package/dist/lib/draft07/index.d.ts +7 -0
  19. package/dist/lib/each.d.ts +3 -2
  20. package/dist/lib/eachSchema.d.ts +2 -4
  21. package/dist/lib/getChildSchemaSelection.d.ts +3 -3
  22. package/dist/lib/getSchema.d.ts +1 -1
  23. package/dist/lib/getTemplate.d.ts +1 -1
  24. package/dist/lib/isValid.d.ts +1 -1
  25. package/dist/lib/jsoneditor/index.d.ts +7 -0
  26. package/dist/lib/resolveAllOf.d.ts +1 -1
  27. package/dist/lib/resolveAnyOf.d.ts +1 -1
  28. package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
  29. package/dist/lib/resolveOneOf.strict.d.ts +2 -2
  30. package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
  31. package/dist/lib/schema/getTypeDefs.d.ts +6 -4
  32. package/dist/lib/schema/types.d.ts +7 -57
  33. package/dist/lib/step.d.ts +1 -1
  34. package/dist/lib/types.d.ts +3 -3
  35. package/dist/lib/utils/createCustomError.d.ts +8 -11
  36. package/dist/lib/utils/filter.d.ts +4 -3
  37. package/dist/lib/utils/flattenArray.d.ts +1 -1
  38. package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
  39. package/dist/lib/validate.d.ts +1 -1
  40. package/dist/lib/validateAsync.d.ts +1 -1
  41. package/dist/lib/validation/errors.d.ts +1 -3
  42. package/dist/lib/validation/format.d.ts +4 -17
  43. package/dist/module/index.js +17 -33
  44. package/dist/module/lib/SchemaService.js +7 -4
  45. package/dist/module/lib/{draft06/addSchema.js → addRemoteSchema.js} +2 -4
  46. package/dist/module/lib/compile/getRef.js +1 -1
  47. package/dist/module/lib/compile/index.js +36 -22
  48. package/dist/module/lib/compile/types.js +1 -0
  49. package/dist/module/lib/draft/index.js +133 -0
  50. package/dist/module/lib/draft04/index.js +90 -0
  51. package/dist/module/lib/draft06/compile/index.js +32 -20
  52. package/dist/module/lib/draft06/index.js +96 -0
  53. package/dist/module/lib/draft06/validation/keyword.js +19 -7
  54. package/dist/module/lib/draft06/validation/type.js +18 -17
  55. package/dist/module/lib/draft07/index.js +96 -0
  56. package/dist/module/lib/each.js +1 -1
  57. package/dist/module/lib/eachSchema.js +28 -19
  58. package/dist/module/lib/getChildSchemaSelection.js +1 -1
  59. package/dist/module/lib/getSchema.js +2 -1
  60. package/dist/module/lib/getTemplate.js +2 -2
  61. package/dist/module/lib/jsoneditor/index.js +16 -0
  62. package/dist/module/lib/resolveOneOf.strict.js +40 -2
  63. package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
  64. package/dist/module/lib/schema/getTypeDefs.js +2 -2
  65. package/dist/module/lib/schema/getTypeId.js +9 -5
  66. package/dist/module/lib/schema/types.js +33 -9
  67. package/dist/module/lib/step.js +6 -3
  68. package/dist/module/lib/utils/createCustomError.js +4 -4
  69. package/dist/module/lib/utils/flattenArray.js +4 -3
  70. package/dist/module/lib/utils/merge.js +1 -0
  71. package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
  72. package/dist/module/lib/validate.js +1 -0
  73. package/dist/module/lib/validation/errors.js +1 -1
  74. package/dist/module/lib/validation/format.js +12 -6
  75. package/dist/module/lib/validation/keyword.js +2 -2
  76. package/index.ts +38 -33
  77. package/lib/SchemaService.ts +18 -11
  78. package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
  79. package/lib/addValidator.ts +10 -7
  80. package/lib/compile/getRef.ts +3 -4
  81. package/lib/compile/index.ts +59 -23
  82. package/lib/compile/types.ts +6 -0
  83. package/lib/draft/index.ts +201 -0
  84. package/lib/draft04/index.ts +95 -0
  85. package/lib/draft06/compile/index.ts +57 -21
  86. package/lib/draft06/index.ts +101 -0
  87. package/lib/draft06/validation/keyword.ts +47 -25
  88. package/lib/draft06/validation/type.ts +23 -19
  89. package/lib/draft07/index.ts +101 -0
  90. package/lib/each.ts +6 -4
  91. package/lib/eachSchema.ts +45 -32
  92. package/lib/getChildSchemaSelection.ts +4 -4
  93. package/lib/getSchema.ts +3 -2
  94. package/lib/getTemplate.ts +33 -16
  95. package/lib/isValid.ts +7 -3
  96. package/lib/jsoneditor/index.ts +20 -0
  97. package/lib/resolveAllOf.ts +1 -1
  98. package/lib/resolveAnyOf.ts +7 -3
  99. package/lib/resolveOneOf.fuzzy.ts +1 -1
  100. package/lib/resolveOneOf.strict.ts +49 -4
  101. package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
  102. package/lib/schema/getTypeDefs.ts +6 -7
  103. package/lib/schema/getTypeId.ts +10 -7
  104. package/lib/schema/types.ts +41 -9
  105. package/lib/step.ts +9 -6
  106. package/lib/types.ts +7 -6
  107. package/lib/utils/createCustomError.ts +8 -13
  108. package/lib/utils/filter.ts +4 -4
  109. package/lib/utils/flattenArray.ts +5 -4
  110. package/lib/utils/merge.ts +1 -0
  111. package/lib/utils/punycode.ucs2decode.ts +6 -5
  112. package/lib/validate.ts +2 -1
  113. package/lib/validateAsync.ts +2 -2
  114. package/lib/validation/errors.ts +2 -4
  115. package/lib/validation/format.ts +42 -17
  116. package/lib/validation/keyword.ts +30 -30
  117. package/package.json +3 -1
  118. package/tsconfig.json +1 -1
  119. package/dist/lib/cores/CoreInterface.d.ts +0 -42
  120. package/dist/lib/cores/Draft04.d.ts +0 -13
  121. package/dist/lib/cores/Draft06.d.ts +0 -15
  122. package/dist/lib/cores/Draft07.d.ts +0 -15
  123. package/dist/lib/cores/JsonEditor.d.ts +0 -13
  124. package/dist/lib/draft06/addSchema.d.ts +0 -7
  125. package/dist/module/lib/addSchema.js +0 -11
  126. package/dist/module/lib/cores/CoreInterface.js +0 -73
  127. package/dist/module/lib/cores/Draft04.js +0 -52
  128. package/dist/module/lib/cores/Draft06.js +0 -61
  129. package/dist/module/lib/cores/Draft07.js +0 -61
  130. package/dist/module/lib/cores/JsonEditor.js +0 -51
  131. package/dist/module/remotes/draft04.json +0 -150
  132. package/dist/module/remotes/draft06.json +0 -155
  133. package/dist/module/remotes/draft07.json +0 -172
  134. package/dist/module/remotes/index.js +0 -9
  135. package/dist/remotes/index.d.ts +0 -4
  136. package/lib/cores/CoreInterface.ts +0 -103
  137. package/lib/cores/Draft04.ts +0 -64
  138. package/lib/cores/Draft06.ts +0 -76
  139. package/lib/cores/Draft07.ts +0 -75
  140. package/lib/cores/JsonEditor.ts +0 -62
  141. package/lib/draft06/addSchema.ts +0 -14
  142. package/remotes/index.ts +0 -9
package/README.md CHANGED
@@ -1,4 +1,5 @@
1
- <h1 align="center"><img src="./docs/json-schema-library.png" width="256" alt="json-schema-library"></h1>
1
+ <p align="center"><img src="./docs/json-schema-library.png" width="256" alt="json-schema-library"></p>
2
+
2
3
 
3
4
  **Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation**
4
5
 
@@ -7,270 +8,880 @@
7
8
  > footprint or high performance, this package focuses on exposing utilities for browser and node environments and
8
9
  > lessens the pain to build custom tools around json-schema.
9
10
 
10
- `npm i json-schema-library -S` or `yarn add json-schema-library`
11
11
 
12
+ <p align="center">
13
+ <a href="#draft-methods">draft methods</a> | <a href="#draft-extensions">draft extensions</a> | <a href="#draft-customization">draft customization</a> | <a href="#breaking-changes">breaking changes</a>
14
+ </p>
12
15
 
13
- - This package is tested on node v10.16 and in latest Browsers.
14
- - This library currently supports draft4, draft6 and draft7 features (@see [benchmark](https://github.com/sagold/json-schema-benchmark))
15
16
 
17
+ **install**
16
18
 
17
- 1. [Breaking Changes](#breaking-changes)
18
- 1. [Overview](#overview)
19
- 1. [Core](#core)
20
- 1. [Add Custom Validators](#add-custom-validators)
21
- 1. [Custom Extensions](#custom-extensions)
19
+ `yarn add json-schema-library`
22
20
 
21
+ - This package is tested on node v16+ and in latest browsers
22
+ - This library currently supports draft4, draft6 and draft7 features [@see benchmark](https://github.com/sagold/json-schema-benchmark)
23
23
 
24
- ## Breaking Changes
25
24
 
26
- 1. with version `v6.0.0` supported json schema drafts are exported directly as `Draft04`, `Draft06`, `Draft07`, e.g. `import { Draft07 } from "json-schema-library"`
27
- 1. with version `v5.0.0` the api has changed to es6 modules, where there is no default export, only named exports. Additionally all code has been rewritten to typescript. When directly accessing files, switch to `dist/module/*.js`-files for plain js-modules.
28
- 1. with version `v4.0.0` the api has changed in order to use the defined (root) schema in core as default where
29
- possible. This means, most methods have a changed signature, where `data` is passed before an optional `schema` argument. Check the [Core Overview](#core) for the current signature
30
- 1. additionally `iterateSchema` has been renamed to `eachSchema` for consistency
31
-
32
-
33
- ## Overview
34
-
35
- Either select an existing __validator__ (`core`) or create your own. Each __Core__ holds all functions that are required
36
- for the json-schema operations like validation. In order to overwrite a custom function you can either
37
-
38
- - modify the map-objects (i.e. [/lib/validation/keywords.js](./lib/validation/keyword.ts))
39
- - overwrite functions or keys in the generated instance (`const instance = new Core()`)
40
- - Create a custom __Core__ following the examples in [/lib/cores](./lib/cores)
41
-
42
- Additionally, helper functions and tools are separately exposed via CommonJS Modules. Most of them do require a
43
- core-object as parameter, but use only some of the functions defined in an core-instance.
44
-
45
-
46
- ### Core
47
-
48
- The default interface of a validator can be found in [/lib/cores/CoreInterface](./lib/cores/CoreInterface.ts). It exposes
49
- the following methods
50
-
51
- | method | signature | description
52
- | ----------------- | ------------------------------------- | -------------------------------------------------------------
53
- | constructor | schema : instance | pass the root-schema in the constructor
54
- | each | data, callback, [schema], [pointer] | Iterates over the data, passing value and its schema
55
- | getSchema | pointer, [data], [schema] : Schema | Get the json-schema describing the `data` found at `pointer`
56
- | getTemplate | data, [schema] : Mixed | returns a template object based of the given json-schema
57
- | isValid | data, [schema], [pointer] : Boolean | Check if the given schema validates the data
58
- | resolveOneOf | data, [schema], [pointer] : Schema | returns the oneOf-schema for the passed data
59
- | resolveRef | schema : Schema | resolves a $ref on a given schema-object
60
- | setSchema | schema | set a new (root) schema
61
- | step | key, schema, data, [pointer] : Schema | step into a json-schema by the given key (property or index)
62
- | validate | data, [schema], [pointer] : Array | Get a list of validation errors
63
-
64
-
65
- Each core holds some mapping objects, that may be modified
66
-
67
- ```js
68
- Core {
69
- // keyword validations for each type, e.g. "array": ["enum", "items", "minItems", "maxItems", ...]
70
- // for each item in the given list, the validation function in `validationKeyword` will be called
71
- typeKeywords: {}
72
- // keyword validation functions, e.g. validateKeyword.enum(), validateKeyword.items(), ...
73
- validateKeyword: {}
74
- // type validation for array, object, number, etc. Basically runs over typeKeywords and executes
75
- // validation functions from `validateKeyword`
76
- validateType: {}
77
- // format validation functions. will be executed if a) typeKeywords includes 'format' and a
78
- // validation function is set in validateFormat
79
- validateFormat: {}
80
- // list of error-creator functions. They receive an object with the data of the error and must
81
- // return an object like { type: 'error', message: "" }
82
- errors: {}
83
- }
25
+ **usage**
26
+
27
+ `json-schema-library` exposes a `Draft` for most json-schema drafts. Each `Draft` can be instantiated and offers a common set of actions working on the specified json-schema version. e.g.
28
+
29
+ ```ts
30
+ import { Draft04, Draft06, Draft07, Draft, JSONError } from "json-schema-library";
31
+ import myJsonSchema from "./myJsonSchema.json";
32
+ import myData from "./myData.json";
33
+
34
+ const jsonSchema: Draft = new Draft07(myJsonSchema);
35
+ const errors: JSONError[] = jsonSchema.validate(myData);
84
36
  ```
85
37
 
38
+ What follows is a description of the main draft methods.
86
39
 
87
- #### Examples
40
+ ## Draft methods
88
41
 
89
- ##### getSchema(core, pointer, [data], [schema])
90
- > Get the json-schema describing the `data` found at `pointer`.
91
- > The default json-schema definitions can be resolved without any data as input: `core.getSchema('#/article/title')`.
92
- > For any dynamic values (like `oneOf`, `definitions`) the data has to be passed in addition.
42
+ - [validate](#validate)
43
+ - [isValid](#isvalid)
44
+ - [validateAsync](#validateasync)
45
+ - [getTemplate](#gettemplate)
46
+ - [each](#each)
47
+ - [eachSchema](#eachschema)
48
+ - [getSchema](#getschema)
49
+ - [getChildSchemaSelection](#getchildschemaselection)
50
+ - [step](#step)
51
+ - [addRemoteSchema](#addremoteschema)
52
+ - [createSchemaOf](#createschemaof)
53
+ - [compileSchema](#compileschema)
93
54
 
94
- ```js
95
- import { Draft04 as Core } from "json-schema-library";
96
- const core = new Core(rootSchema);
97
- const targetSchema = core.getSchema('#/path/to/target', rootData);
98
- ```
99
55
 
100
- Currently may also return an error:
56
+ ### validate
101
57
 
102
- ```js
103
- if (targetSchema.type === "error") {
104
- throw new Error(targetSchema.message);
105
- }
58
+ `validate` is a complete _json-schema validator_ for your input data. Calling _validate_ will return a list of validation errors for the passed data
59
+
60
+ ```ts
61
+ const jsonSchema = new Draft07(myJsonSchema);
62
+ const errors: JSONError[] = jsonSchema.validate(myData);
106
63
  ```
107
64
 
108
- Or using `getSchema` directly
65
+ Additionally, you can validate a subschema and its data. Doing this, the intial schema will be used as rootSchema to e.g. resolve `$ref` from _definitions_
109
66
 
110
- ```js
111
- import { Draft04 as Core } from "json-schema-library";
112
- const core = new Core(rootSchema);
113
- const targetSchema = getSchema(core, '#/path/to/target', rootData);
67
+ ```ts
68
+ const jsonSchema = new Draft07(myJsonSchema);
69
+ const errors: JSONError[] = jsonSchema.validate("my-string", { type: "number" });
114
70
  ```
115
71
 
72
+ > to prevent some errors when using helper methods with an independent subschema, please use `compileSchema` if it is not retrieved from a draft-method directly (which was compiled by passing it to Draft). Specifically, if the schema contains a $ref you need to use `compileSchema`. More details in [compileSchema](#compileSchema).
116
73
 
117
- ##### getTemplate(core, data, [schema])
118
- > Generate data which is valid to the given json-schema. Additionally, a data object may be given, which will be
119
- extended by any missing items or properties.
74
+ <details><summary>About type JSONError</summary>
120
75
 
121
- ```js
122
- import { Draft04 as Core } from "json-schema-library";
123
- const core = new Core();
124
- const baseData = core.getTemplate(
125
- { other: true },
126
- { type: "object", properties: { target: { type: "string", default: "v" } } },
127
- ); // returns { other: true, target: "v" }
76
+ In `json-schema-library` all errors are in the format of a `JSONError`
77
+
78
+ ```ts
79
+ type JSONError = {
80
+ type: "error";
81
+ name: string;
82
+ code: string;
83
+ message: string;
84
+ data?: { [p: string]: any };
85
+ };
128
86
  ```
129
87
 
130
- ##### validate(core, data, [schema])
131
- > Get a list of validation errors
88
+ in almost all cases, a _json-pointer_ is given on _error.data.pointer_, which points to the source within data where the error occured.
89
+
90
+ For more details on how to work with errors, refer to section [custom errors](#custom-errors).
91
+
92
+ </details>
93
+
94
+ <details><summary>Example</summary>
95
+
96
+ ```ts
97
+ import { Draft07, JSONSchema, JSONError } from "json-schema-library";
132
98
 
133
- ```js
134
- import { Draft04 as Core } from "json-schema-library";
135
- const core = new Core(rootSchema);
136
- const errors = core.validate({ validationOf: "rootSchema" });
137
- // validation errors running data for 'rootSchema'
138
- const customSchemaErrors = core.validate("", { type: "number" });
139
- // returns { type: "TypeError" }
99
+ const myJsonSchema: JSONSchema = {
100
+ type: "object",
101
+ additionalProperties: false
102
+ };
103
+
104
+ const jsonSchema = new Draft07(myJsonSchema);
105
+ const errors: JSONError[] = jsonSchema.validate({ name: "my-data" });
106
+
107
+ expect(errors).to.deep.equal([
108
+ {
109
+ type: "error",
110
+ name: "NoAdditionalPropertiesError",
111
+ code: "no-additional-properties-error",
112
+ message: "Additional property `name` in `#` is not allowed",
113
+ data: { property: "name", properties: [], pointer: "#" }
114
+ }
115
+ ]);
116
+ ```
117
+
118
+ </details>
119
+
120
+ <details><summary>Example with separate schema</summary>
121
+
122
+ ```ts
123
+ import { Draft07, JSONSchema, JSONError } from "json-schema-library";
124
+
125
+ const myJsonSchema: JSONSchema = {
126
+ type: "object",
127
+ additionalProperties: false
128
+ };
129
+
130
+ const jsonSchema = new Draft07(myJsonSchema);
131
+ const mySchema = jsonSchema.compileSchema({ type: "number" });
132
+ const errors: JSONError[] = jsonSchema.validate("my-string", mySchema);
133
+
134
+ expect(errors).to.deep.equal([
135
+ {
136
+ type: "error",
137
+ name: "TypeError",
138
+ code: "type-error",
139
+ message: "Expected `my-string` (string) in `#` to be of type `number`",
140
+ data: {
141
+ received: "string",
142
+ expected: "number",
143
+ value: "my-string",
144
+ pointer: "#"
145
+ }
146
+ }
147
+ ]);
140
148
  ```
141
149
 
142
- ##### isValid(core, data, [schema])
143
- > Check if the given schema validates the data
150
+ </details>
144
151
 
145
- basically `core.validate("", { type: "number" }).length === 0`
146
152
 
147
- ```js
148
- import { Draft04 as Core } from "json-schema-library";
149
- const core = new Core(rootSchema);
150
- const baseSchema = core.isValid("", { type: "number" });
151
- // returns false
153
+ ### isValid
154
+
155
+ `isValid` will return a true if the given json-data is valid against the json-schema
156
+
157
+ ```ts
158
+ const jsonSchema = new Draft07(myJsonSchema);
159
+ const isValid: boolean = jsonSchema.isValid(myData);
152
160
  ```
153
161
 
154
- ##### validateAsync(core, data, [options])
155
- > Asynchronous validation helper
162
+
163
+ ### validateAsync
164
+
165
+ > this method is not yet exposed by a draft directly as the api of this is yet unsatisfactory. Nonetheless, this function is in production and can be used reliably
156
166
 
157
167
  Optional support for onError helper, which is invoked for each error (after being resolved)
158
168
 
159
- ```js
160
- import { Draft04 as Core } from "json-schema-library";
161
- const core = new Core(rootSchema);
162
- // signature: Core, data, { onError: [onErrorCallback], schema: JSONSchema, pointer: [Pointer]} : Promise
163
- validateAsync(core, "", { onError: (err) => {}, schema: { type: "number" } })
164
- .then(allErrors => {});
165
- ```
166
-
167
- ##### step(core, key, schema, data)
168
- > Get the json-schema of a child-property
169
-
170
- ```js
171
- import { Draft04 as Core } from "json-schema-library";
172
- const core = new Core(rootSchema);
173
- const baseSchema = core.step(
174
- "target"
175
- { type: "object", properties: { target: { type: "string" } } },
176
- { target: "value" }
177
- ); // returns {type: "string"}
178
- ```
179
-
180
- ##### each(core, data, callback, [schema])
181
- > Iterates over each data-item (object, array and value); passing the value and its corresponding schema
182
-
183
- ```js
184
- import { Draft04 as Core } from "json-schema-library";
185
- const core = new Core({
186
- type: "array",
187
- items: [
188
- { type: "number" },
189
- { type: "string" }
190
- ]
169
+ ```ts
170
+ import { Draft07, JSONError, validateAsync } from "json-schema-library";
171
+
172
+ const draft = new Core(mySchema);
173
+
174
+ validateAsync(draft, "", { onError: (err: JSONError) => {}, schema: draft.getSchema() })
175
+ .then((allErrors: JSONError[]) => {});
176
+ ```
177
+
178
+
179
+ ### getTemplate
180
+
181
+ `getTemplate` creates input data from a json-schema that is valid to the schema. Where possible the json-schema property `default` will be used to initially setup input data. In other cases, first enum values or initial values, etc are user to build up the json-data.
182
+
183
+ ```ts
184
+ const jsonSchema = new Draft07(myJsonSchema);
185
+ const myData = jsonSchema.getTemplate();
186
+ ```
187
+
188
+ Additionally, you can pass input data. `getTemplate` will then complement any missing values from the schema, while keeping the initial values
189
+
190
+ ```ts
191
+ const jsonSchema = new Draft07(myJsonSchema);
192
+ const myData = jsonSchema.getTemplate({ name: "input-data" });
193
+ ```
194
+
195
+ <details><summary>Example</summary>
196
+
197
+ ```ts
198
+ import { Draft07, JSONSchema } from 'json-schema-library';
199
+
200
+ const myJsonSchema: JSONSchema = {
201
+ type: 'object',
202
+ properties: {
203
+ name: { type: 'string' },
204
+ option: {
205
+ type: 'string',
206
+ enum: ['first-option', 'second-option']
207
+ },
208
+ list: {
209
+ type: 'array',
210
+ items: {
211
+ type: 'string',
212
+ default: 'new item'
213
+ },
214
+ minItems: 1
215
+ }
216
+ }
217
+ };
218
+
219
+ const jsonSchema = new Draft07(myJsonSchema);
220
+ const myData = jsonSchema.getTemplate();
221
+
222
+ expect(myData).to.deep.equal({
223
+ name: ',
224
+ option: 'first-option',
225
+ list: ['new item']
191
226
  });
192
- core.each([5, "nine"], (schema, value, pointer) => {
193
- // 1. schema = { type: "array", items: [...] }, data = [5, "nine"], pointer = #
194
- // 2. schema = { type: "number" }, data = 5, pointer = #/0
195
- // 3. schema = { type: "string" }, data = "nine", pointer = #/1
227
+ ```
228
+
229
+ </details>
230
+
231
+ <details><summary>Example with input data</summary>
232
+
233
+ ```ts
234
+ import { Draft07, JSONSchema } from "json-schema-library";
235
+
236
+ const myJsonSchema: JSONSchema = {
237
+ type: "object",
238
+ properties: {
239
+ name: { type: "string" },
240
+ option: {
241
+ type: "string",
242
+ enum: ["first-option", "second-option"]
243
+ },
244
+ list: {
245
+ type: "array",
246
+ items: {
247
+ type: "string",
248
+ default: "new item"
249
+ },
250
+ minItems: 1
251
+ }
252
+ }
253
+ };
254
+
255
+ const jsonSchema = new Draft07(myJsonSchema);
256
+ const myData = jsonSchema.getTemplate({ name: "input-data", list: [] });
257
+
258
+ expect(myData).to.deep.equal({
259
+ name: "input-data",
260
+ option: "first-option",
261
+ list: ["new item"]
196
262
  });
197
263
  ```
198
264
 
265
+ </details>
266
+
267
+ ### each
199
268
 
200
- ### Add custom validators
269
+ `each` iterates over each data-item (_object_, _array_ and _value_) and emits the data-item, schema and location to a callback.
201
270
 
202
- ```js
203
- import { addValidator } from "json-schema-library";
271
+ ```ts
272
+ const jsonSchema = new Draft07(mySchema);
273
+ const myCallback = (schema: JSONSchema, value: unknown, pointer: JSONPointer) => {
274
+ console.log(schema, value, pointer);
275
+ };
276
+ jsonSchema.each(myData, myCallback);
277
+ ```
204
278
 
205
- // add a custom format 'id'
206
- addValidator.format(core, "id", (core, schema, value, pointer) => {});
279
+ <details><summary>Example</summary>
207
280
 
208
- // add custom keyword 'capitalized' for type 'string'
209
- addValidator.keyword(core, "string", "capitalized", (core, schema, value, pointer) => {});
281
+ ```ts
282
+ import { Draft07, JSONSchema, JSONPointer } from "json-schema-library";
210
283
 
211
- // add a custom error (may overwrite existing errors)
212
- addValidator.error(core, "minLengthError", (data) => ({
213
- type: "error",
214
- code: "custom-min-length-error",
215
- message: "my custom error message",
216
- data
217
- }));
284
+ const mySchema: JSONSchema = {
285
+ type: "array",
286
+ items: [{ type: "number" }, { type: "string" }]
287
+ };
288
+
289
+ const jsonSchema = new Draft07(mySchema);
290
+ const calls = [];
291
+ const myCallback = (schema: JSONSchema, value: unknown, pointer: JSONPointer) => {
292
+ calls.push({ schema, value, pointer });
293
+ };
294
+
295
+ jsonSchema.each([5, "nine"], myCallback);
296
+
297
+ expect(calls).to.deep.equal([
298
+ { schema: mySchema, value: [5, "nine"], pointer: "#" },
299
+ { schema: { type: "number" }, value: 5, pointer: "#/0" },
300
+ { schema: { type: "string" }, value: "nine", pointer: "#/1" }
301
+ ]);
302
+ ```
303
+
304
+ </details>
305
+
306
+
307
+ ### eachSchema
308
+
309
+ `eachSchema` emits each sub schema definition to a callback.
310
+
311
+ ```ts
312
+ const jsonSchema = new Draft07(mySchema);
313
+ const myCallback = (schema: JSONSchema) => {
314
+ console.log(schema);
315
+ };
316
+ jsonSchema.eachSchema(myCallback);
317
+ ```
318
+
319
+ <details><summary>Example</summary>
320
+
321
+ ```ts
322
+ import { Draft07, JSONSchema } from "json-schema-library";
323
+
324
+ const mySchema: JSONSchema = {
325
+ type: "array",
326
+ items: {
327
+ oneOf: [{ type: "number" }, { $ref: "#/$defs/value" }]
328
+ },
329
+ $defs: {
330
+ value: { type: "string" },
331
+ object: { type: "object" }
332
+ }
333
+ };
334
+
335
+ const jsonSchema = new Draft07(mySchema);
336
+ const calls = [];
337
+ const myCallback = (schema: JSONSchema) => {
338
+ calls.push(schema);
339
+ };
340
+
341
+ jsonSchema.eachSchema(myCallback);
342
+
343
+ expect(calls).to.deep.equal([
344
+ mySchema,
345
+ { oneOf: [{ type: "number" }, { $ref: "#/$defs/value" }] },
346
+ { type: "number" },
347
+ { $ref: "#/$defs/value" },
348
+ { type: "string" },
349
+ { type: "object" }
350
+ ]);
351
+ ```
352
+
353
+ </details>
354
+
355
+
356
+ ### getSchema
357
+
358
+ `getSchema` retrieves the json-schema of a specific location in data. The location in data is given by a _json-pointer_. In many cases the schema can be retrieved without passing the actual data, but in situations where the schema is dynamic, e.g. in _oneOf_, _dependencies_, etc, the data is required or will return a _JSONError_ if the location could not be found.
359
+
360
+ ```ts
361
+ const jsonSchema = new Draft07(mySchema);
362
+ let schemaOfName: JSONSchema | JSONError;
363
+ schemaOfName = jsonSchema.getSchema("/list/1/name", myData);
364
+ ```
365
+
366
+ <details><summary>Example</summary>
367
+
368
+ ```ts
369
+ import { Draft07, JSONSchema, JSONError } from "json-schema-library";
370
+
371
+ const mySchema = {
372
+ type: "object",
373
+ properties: {
374
+ list: {
375
+ type: "array",
376
+ items: {
377
+ oneOf: [
378
+ {
379
+ type: "object",
380
+ required: ["name"],
381
+ properties: {
382
+ name: {
383
+ type: "string",
384
+ title: "name of item"
385
+ }
386
+ }
387
+ },
388
+ {
389
+ type: "object",
390
+ required: ["description"],
391
+ properties: {
392
+ description: {
393
+ type: "string",
394
+ title: "description of item"
395
+ }
396
+ }
397
+ }
398
+ ]
399
+ }
400
+ }
401
+ }
402
+ };
403
+
404
+ const jsonSchema = new Draft07(mySchema);
405
+ let schemaOfItem: JSONSchema | JSONError;
406
+ schemaOfItem = jsonSchema.getSchema("/list/1", {
407
+ list: [{ description: "..." }, { name: "my-item" }]
408
+ });
409
+
410
+ expect(schemaOfItem).to.deep.equal({
411
+ type: "object",
412
+ required: ["name"],
413
+ properties: {
414
+ name: {
415
+ type: "string",
416
+ title: "name of item"
417
+ }
418
+ }
419
+ });
218
420
  ```
219
421
 
422
+ </details>
423
+
424
+ <details><summary>About JSONPointer</summary>
425
+
426
+ **[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.
427
+
428
+ </details>
429
+
430
+
431
+ ### getChildSchemaSelection
220
432
 
221
- ### Additional helpers
433
+ `getChildSchemaSelection` returns a list of available sub schemas for the given property. In many cases, a single schema will be returned, but e.g. for _oneOf_-schemas a list of possible options is returned. This helper always returns a list of schemas.
222
434
 
223
- #### getChildSchemaSelection(core, key, schema)
224
- Returns a list of possible schemas for the given child-property or index
435
+ **Note** This helper currenly supports a subset of json-schema for multiple results, mainly oneOf-definitions
225
436
 
226
- ```js
227
- import { getChildSchemaSelection } from "json-schema-library";
228
- const listOfAvailableOptions = getChildSchemaSelection(core, "childKey", schema);
437
+ ```ts
438
+ const jsonSchema = new Draft07(mySchema);
439
+ const schemas: JSONSchema[] = jsonSchema.getChildSchemaSelection("content", localSchema);
229
440
  ```
230
441
 
231
- #### createSchemaOf(data)
232
- Creates a json-schema for the given input-data.
442
+ <details><summary>Example</summary>
443
+
444
+ ```ts
445
+ import { Draft07, JSONSchema, JSONError } from "json-schema-library";
446
+
447
+ const jsonSchema = new Draft07();
448
+ const localSchema = {
449
+ type: "object",
450
+ properties: {
451
+ content: {
452
+ oneOf: [
453
+ { type: "string" },
454
+ { type: "number" }
455
+ ]
456
+ }
457
+ }
458
+ }
459
+
460
+ const schemas: JSONSchema[] = jsonSchema.getChildSchemaSelection("content", localSchema);
233
461
 
234
- ```js
235
- import { createSchemaOf } from "json-schema-library";
236
- const baseSchema = createSchemaOf({ target: "" });
237
- // returns {type: "object", properties: { target: "string"}},
462
+ expect(schemas).to.deep.equal([
463
+ { type: "string" },
464
+ { type: "number" }
465
+ ])
238
466
  ```
239
467
 
240
- #### eachSchema(schema, callback)
241
- Iterate the schema, invoking the callback function for each type (schema) definition
468
+ </details>
469
+
470
+
242
471
 
243
- ```js
244
- import { eachSchema } from "json-schema-library";
245
- const baseSchema = eachSchema(schema, (schema, pointer) => {});
472
+ ### step
473
+
474
+ `step` retrieves the json-schema of a child property or index. Using `step` it is possible to incrementally go through the data, retrieving the schema for each next item.
475
+
476
+ ```ts
477
+ const jsonSchema = new Draft07(mySchema);
478
+ const localSchema = { type: "object", properties: { title: { type: "string" } } };
479
+ const localData = { title: "value" };
480
+ const schemaOfTitle = jsonSchema.step("title", localSchema, localData);
246
481
  ```
247
482
 
483
+ <details><summary>Example</summary>
484
+
485
+ ```ts
486
+ import { Draft07, JSONSchema, JSONError } from "json-schema-library";
487
+
488
+ const jsonSchema = new Draft07(mySchema);
489
+ const localSchema = {
490
+ oneOf: [
491
+ {
492
+ type: "object",
493
+ properties: { title: { type: "string" } }
494
+ },
495
+ {
496
+ type: "object",
497
+ properties: { title: { type: "number" } }
498
+ }
499
+ ]
500
+ };
501
+ const localData = { title: 4 }
502
+ const schemaOfTitle = jsonSchema.step("title", localSchema, localData);
503
+
504
+ expect(res).to.deep.eq({ type: "number" });
505
+ ```
248
506
 
249
- ## Custom extensions
507
+ </details>
508
+
509
+
510
+ ### addRemoteSchema
511
+
512
+ `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.
513
+
514
+ ```ts
515
+ const jsonSchema = new Draft07({
516
+ $ref: "http://json-schema.org/draft-07/schema#definitions/nonNegativeInteger"
517
+ });
518
+ jsonSchema.addRemoteSchema("http://json-schema.org/draft-07/schema", draft07Schema);
519
+ ```
250
520
 
251
- ### pattern
521
+ <details><summary>Example</summary>
522
+
523
+ ```ts
524
+ import { Draft07 } from "json-schema-library";
525
+
526
+ const jsonSchema = new Draft07({
527
+ $ref: "http://drafts.com/7/schema#definitions/nonNegativeInteger"
528
+ });
529
+ jsonSchema.addRemoteSchema("http://drafts.com/7/schema", {
530
+ definitions: {
531
+ nonNegativeInteger: { type: "integer", minimum: 0 }
532
+ }
533
+ });
534
+
535
+ const errors = jsonSchema.validate(1);
536
+ expect(errors).to.deep.equal([]);
537
+
538
+ const schema = jsonSchema.getSchema("#");
539
+ expect(schema).to.deep.equal({ type: "integer", minimum: 0 });
540
+ ```
541
+
542
+ </details>
543
+
544
+ ### createSchemaOf
545
+
546
+ `createSchemaOf` returns a simple json-schema of the input data.
547
+
548
+ ```ts
549
+ const jsonSchema = new Draft07(mySchema);
550
+ const schema: JSONSchema = jsonSchema.createSchemaOf({ title: "initial value" });
551
+ ```
552
+
553
+
554
+ ### compileSchema
555
+
556
+ `compileSchema` adds _$ref_ resolution support to a json-schema. Internally, each draft compiles a passed schema on its own, but when passing additional schemas to individual functions, `compileSchema` has to be called manually for json-schemas containing $ref-references.
557
+
558
+ ```ts
559
+ const jsonSchema = new Draft07(mySchema);
560
+ const compiledSchema = jsonSchema.compileSchema({ $ref: "/$defs/table" });
561
+ const tableSchema = compiledSchema.getRef();
562
+ ```
563
+
564
+ **Note** that `draft.compileSchema` compiles a schema under the current rootSchema. That is, definitions from root schema will be copied to the local schema, to enable $ref resolutions.
565
+
566
+
567
+ ## Draft extensions
568
+
569
+ For each draft `json-schema-library` supports the following custom properties:
570
+
571
+
572
+ ### patternExample
252
573
 
253
574
  For error generation, an attribute `patternExample` may be set for a `pattern` validation. Instead of the regular
254
575
  expression, the example will be printed in the error message.
255
576
 
256
- ### oneOf-flag
257
577
 
258
- In `resolveOneOf.fuzzy.js` For an explicit oneOf resolution the schema may be extended by a `oneOfProperty`-property.
259
- This will always associate an entry with a matching value (instead of schema validation).
578
+ ### oneOfProperty
260
579
 
261
- Example
580
+ For `oneOf` resolution json-schema states that a data is valid, if it validate against exactly one of those sub schemas. In some scenarios this is unwanted behaviour as the actual `oneOf` schema is known and only validation errors of this exact sub schema should be returned.
262
581
 
263
- ```js
582
+ For an explicit `oneOf` resolution the json-schema may be extended by a property `oneOfProperty`. This will always associate an entry with a matching value (instead of schema validation) and return only this schema or validation errors, depending on the current task, e.g.
583
+
584
+ ```ts
264
585
  const schema = {
265
- oneOfProperty: "id",
266
- oneOf: [
267
- { type: "object", properties: { id: { type: "string", pattern: "^1$" }, title: { type: "number" } } },
268
- { type: "object", properties: { id: { type: "string", pattern: "^2$" }, title: { type: "number" } } },
269
- { type: "object", properties: { id: { type: "string", pattern: "^3$" }, title: { type: "number" } } }
270
- ]
271
- }
586
+ oneOfProperty: "id",
587
+ oneOf: [
588
+ {
589
+ type: "object",
590
+ properties: { id: { const: "1" }, title: { type: "number" } }
591
+ },
592
+ {
593
+ type: "object",
594
+ properties: { id: { const: "2" }, title: { type: "number" } }
595
+ },
596
+ {
597
+ type: "object",
598
+ properties: { id: { const: "3" }, title: { type: "number" } }
599
+ }
600
+ ]
601
+ };
602
+
603
+ const resolvedSchema = jsonSchema.resolveOneOf({ id: "2", title: "not a number" }, schema);
272
604
 
273
- const result = resolveOneOf(core, { id: "2", title: "not a number" }, schema);
274
605
  // will always return (even if invalid)
275
- // { type: "object", properties: { id: { type: "string", pattern: "^2$" }, title: { type: "number" } } }
606
+ expect(resolvedSchema).to.deep.eq({
607
+ type: "object",
608
+ properties: { id: { const: "2" }, title: { type: "number" } }
609
+ });
276
610
  ```
611
+
612
+
613
+ ## Draft customization
614
+
615
+ [custom resolvers](#custom-resolvers) | [custom validators](#custom-validators) | [custom errors](#custom-errors)
616
+
617
+
618
+ Each `Draft` in `json-schema-library` is build around a [DraftConfig](./lib/draft/index.ts#19). A `DraftConfig` holds all _functions_ and _configurations_ for each json-schema drafts. The `DraftConfig` is your main way to alter or extend behaviour for `json-schema-library`. You can either create your own _draftConfig_ or adjust any existing _draftConfig_. For the current drafts (4-7), each _draftConfig_ is exposed along with its actual _class_, e.g.
619
+
620
+ ```ts
621
+ import { Draft, Draft07, draft07Config } from 'json-schema-library';
622
+ // the following calls are identical:
623
+ new Draft(draft07Config, mySchema);
624
+ new Draft07(mySchema, draft07Config);
625
+ new Draft07(mySchema, {});
626
+ new Draft07(mySchema);
627
+ ```
628
+
629
+ all draft configurations for specific `Draft` classes take a partial configuration that lets you overwrite default behaviour, e.g.
630
+
631
+ > replace the strict resolveOneOf behaviour to use fuzzy search instead:
632
+
633
+ ```ts
634
+ import { Draft07, draft07Config, resolveOneOfFuzzy } from 'json-schema-library';
635
+ // the following calls are identical:
636
+ new Draft07(mySchema, { resolveOneOf: resolveOneOfFuzzy });
637
+ new Draft({ ...draft07Config, resolveOneOf: resolveOneOfFuzzy }, mySchema);
638
+ ```
639
+
640
+
641
+ ### custom resolvers
642
+
643
+ A _resolver_ is a simple method implementing a specific feature of json-schema to retrieve a sub schema. Implementing the signature of each resolver you can create and pass your own resolvers.
644
+
645
+
646
+ #### `resolveRef` with merge
647
+
648
+ The default json-schema behaviour for `$ref` resolution is to replace the schema where a `$ref` is defined. In some scenarios you what to add context specific information, like e.g. a specific _title_. For this, a modified `$ref`-resolver is exposed by `json-schema-library`
649
+
650
+ ```ts
651
+ import { Draft07, draft07Config, resolveRefMerge } from 'json-schema-library';
652
+ const jsonSchema = new Draft07(mySchema, { resolveRef: resolveRefMerge });
653
+ ```
654
+
655
+ `resolveRefMerge` performs a shallow merge (first level of properties), adding the local schemas properties last.
656
+
657
+ **Note** with this resolver, it is possible to overwrite json-schema behavioural properties. Treat with care.
658
+
659
+ <details><summary>Example</summary>
660
+
661
+ ```ts
662
+ import { Draft07, draft07Config, resolveRefMerge } from 'json-schema-library';
663
+ const mySchema = {
664
+ type: "object",
665
+ properties: {
666
+ subHeader: {
667
+ $ref: "#/$defs/header",
668
+ title: "sub header"
669
+ }
670
+ },
671
+ "$defs": {
672
+ header: {
673
+ title: "header",
674
+ type: "string"
675
+ }
676
+ }
677
+ }
678
+
679
+ const jsonSchema = new Draft07(mySchema, { resolveRef: resolveRefMerge });
680
+ const subHeaderSchema = jsonSchema.getSchema("#/subHeader");
681
+
682
+ expect(subHeaderSchema).to.eq({
683
+ title: "sub header",
684
+ type: "string"
685
+ })
686
+ ```
687
+
688
+ </details>
689
+
690
+
691
+ #### `resolveOneOf` fuzzy search
692
+
693
+ The default json-schema behaviour for `oneOf` resolution is to validate all contained _oneOf_-schemas and return the one schema that validates against the given input data. If no item validates completely an error returned, containing all validation errors of all schemas. When you are interested in the actual error (instead of: data is valid or not), this is behaviour is not very helpful as the result is hard to read.
694
+
695
+ `json-schema-library` exposes a method `resolveOneOfFuzzy`, which will return a single schema in cases where no valid schema could be resolved. `resolveOneOfFuzzy` uses a simple scoring mechanism to return the best fitting schema for the given input data. Thus, `resolveOneOfFuzzy` may return schemas that do not validate a given input data.
696
+
697
+ ```ts
698
+ import { Draft07, draft07Config, resolveOneOfFuzzy } from 'json-schema-library';
699
+ const jsonSchema = new Draft07(mySchema, { resolveOneOf: resolveOneOfFuzzy });
700
+ ```
701
+
702
+
703
+ ### custom validators
704
+
705
+ All json-schema validation is done using validator functions for _keywords_ and _formats_.
706
+
707
+ **keyword validators** are called for each keyword defined on a json-schema, e.g. the following schema will run two keyword-validators, one for `items` and one of `minItems`, which are defined in `draft.validateKeyword.items` and `draft.validateKeyword.minItems`
708
+
709
+ ```ts
710
+ { type: "object", items: {}, minItems: 1 }
711
+ ```
712
+
713
+ Since valid json-schema keywords vary by their `type` an additional mapping registers, which keyword should be tested per schema-type. This mapping is defined in `draft.typeKeywords`, e.g.
714
+
715
+ ```ts
716
+ import { draft07Config } from "json-schema-library";
717
+
718
+ console.log(draft07Config.typeKeywords.array);
719
+ // ["enum", "contains", "items", "minItems", "maxItems", "uniqueItems", "not", "if"];
720
+ ````
721
+
722
+
723
+ > The keyword **format** is also registered in `draft.validateKeyword.format`, but each actual format validation is defined as follows:
724
+
725
+ **format validators** are called on each ocurence of a property format on a json-schema, e.g. the following schema will run the _email_-validator given in `draft.validateFormat.email`
726
+
727
+ ```ts
728
+ { type: "string", format: "email" }
729
+ ```
730
+
731
+ #### add custom keyword validator
732
+
733
+ To add or overwrite a keyword validator you have to add a validator function on your draft config in `validateKeyword`.
734
+
735
+ using specific Draft configuration, where draft configuration objects will be merged:
736
+
737
+ ```ts
738
+ import { Draft07, JSONValidator } from "json-schema-library";
739
+
740
+ const jsonSchema = new Draft07(mySchema, {
741
+ validateKeyword: {
742
+ customKeyword: <JSONValidator>myCustomKeywordValidator
743
+ },
744
+ // in case for new keywords, or if keyword should be supported on other types
745
+ // add keyword-name to typeKeywords
746
+ typeKeywords: {
747
+ object: draft07Config.typeKeywords.object.concat("customKeyword")
748
+ }
749
+ });
750
+ ```
751
+
752
+ manually extending draft configuration
753
+
754
+ ```ts
755
+ import { Draft, draft07Config, JSONValidator } from "json-schema-library";
756
+
757
+ const myDraftConfiguration = {
758
+ ...draft07Config,
759
+ draft07Config,
760
+ validateKeyword: {
761
+ ...draft07Config.validateKeyword,
762
+ customKeyword: <JSONValidator>myCustomKeywordValidator
763
+ },
764
+ // in case for new keywords, or if keyword should be supported on other types
765
+ // add keyword-name to typeKeywords
766
+ typeKeywords: {
767
+ ...draft07Config.typeKeywords,
768
+ object: draft07Config.typeKeywords.object.concat("customKeyword")
769
+ }
770
+ };
771
+
772
+ const jsonSchema = new Draft(myDraftConfiguration, mySchema);
773
+ ```
774
+
775
+
776
+ #### add custom format validator
777
+
778
+ To add or overwrite a format validator you have to add a validator function on your draft config in `validateFormat`.
779
+
780
+ ```ts
781
+ import { Draft07, JSONValidator } from "json-schema-library";
782
+
783
+ const jsonSchema = new Draft07(mySchema, {
784
+ validateFormat: {
785
+ customFormat: <JSONValidator>myCustomFormatValidator
786
+ }
787
+ });
788
+ ```
789
+
790
+
791
+ ### custom errors
792
+
793
+ `json-schema-library` exposes available errors on its draft configurations on `DraftConfig.errors` and uses a global configuration `config.strings` for error messages. Both can be extended or modified.
794
+
795
+ ```ts
796
+ import { draft07Config, createCustomError, config } from "json-schema-library";
797
+
798
+ draft07Config.errors.enumError;
799
+ // (data: { pointer: JSONPointer } & Record<string, unknown>) => JSONError
800
+
801
+ console.log(config.strings.EnumError)
802
+ // "Expected given value `{{value}}` in `{{pointer}}` to be one of `{{values}}`"
803
+ ```
804
+
805
+ Each error message in `config.strings` receives the `data`-property of an error. These properties can be referenced in handlebars brackets and will be replaced automatically. To demonstrate the behaviour:
806
+
807
+ ```ts
808
+ import { render } from "json-schema-library";
809
+
810
+ render(
811
+ "Expected given value `{{value}}` in `{{pointer}}` to be one of `{{values}}`",
812
+ { pointer: "[A]", value: "[B]" }
813
+ );
814
+ // "Expected given value `[B]` in `[A]` to be one of ``"
815
+ ```
816
+
817
+
818
+ #### customize error messages
819
+
820
+ ```ts
821
+ import { config } from "json-schema-library";
822
+
823
+ config.strings.EnumError = "Invalid enum value {{value}} in {{pointer}}`";
824
+ ```
825
+
826
+
827
+ #### customize errors
828
+
829
+ ```ts
830
+ import { draft07Config, ErrorData, JSONError } from "json-schema-library";
831
+
832
+ draft07Config.errors.EnumError = (data: ErrorData): JSONError => {
833
+ return {
834
+ type: "error",
835
+ code: "my-error",
836
+ name: "MyError",
837
+ message: `something went wrong at ${data.pointer}`,
838
+ data
839
+ };
840
+ };
841
+ ```
842
+
843
+
844
+ #### create errors
845
+
846
+ ```ts
847
+ import { draft07Config, createError } from "json-schema-library";
848
+ // will use the string from `config.strings.EnumError` as message
849
+ const error: JSONError = createError("EnumError", { data: { pointer: "#/location" }});
850
+ ```
851
+
852
+
853
+ ## Breaking Changes
854
+
855
+ ### v7.0.0
856
+
857
+ with version `v7.0.0` library export and Draft api has changed heavily. The api is now more consistent across draft-versions and offers a simple and consistent configuration interface for existing and custom drafts. In addition, most standalone functions are no longer exposed separately, but under its current _draftConfigs_ and mainly on each draft-instance. This will help to reduce confusion, when consuming this api.
858
+
859
+ The above documentation reflects all those changes. Just reach out if you have troubles migrating to the latest version.
860
+
861
+ <details><summary>Details on breaking changes</summary>
862
+
863
+ - replaced `Core` interface by new `Draft` interface
864
+ - changed export of `Interface` to `Draft`
865
+ - renamed `addSchema` to `addRemoteSchema`
866
+ - changed api of `compileSchema` to have an additional schema-parameter for rootSchema reference
867
+ - changed `compileSchema` and `addRemoteSchema` to work on instance state, instead of global state
868
+ - `addRemoteSchema`, `compileSchema` now requires draft instance as first parameter
869
+ - removed direct export of following functions: `addValidator`, `compileSchema`, `createSchemaOf`, `each`, `eachSchema`, `getChildSchemaSelection`, `getSchema`, `getTemplate`, `isValid`, `step`, `validate`. They are still accessible under the draftConfigs of each draft-version
870
+ - changed draft version of `JsonEditor` to draft07
871
+
872
+ </details>
873
+
874
+
875
+ ### v6.0.0
876
+
877
+ with version `v6.0.0` supported json schema drafts are exported directly as `Draft04`, `Draft06`, `Draft07`, e.g. `import { Draft07 } from "json-schema-library"`
878
+
879
+
880
+ ### v5.0.0
881
+
882
+ with version `v5.0.0` the api has changed to es6 modules, where there is no default export, only named exports. Additionally all code has been rewritten to typescript. When directly accessing files, switch to `dist/module/*.js`-files for plain js-modules.
883
+
884
+
885
+ ### v4.0.0
886
+
887
+ with version `v4.0.0` the api has changed in order to use the defined (root) schema in draft as default where possible. This means, most methods have a changed signature, where `data` is passed before an optional `schema` argument.