json-schema-library 5.3.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 (161) hide show
  1. package/.editorconfig +1 -0
  2. package/.prettierignore +1 -0
  3. package/.prettierrc +7 -0
  4. package/CHANGELOG.md +106 -0
  5. package/README.md +811 -199
  6. package/TASKS.md +3 -81
  7. package/dist/index.d.ts +29 -71
  8. package/dist/jsonSchemaLibrary.js +1 -1
  9. package/dist/lib/SchemaService.d.ts +6 -8
  10. package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
  11. package/dist/lib/addValidator.d.ts +3 -2
  12. package/dist/lib/compile/getRef.d.ts +2 -1
  13. package/dist/lib/compile/index.d.ts +15 -1
  14. package/dist/lib/compile/types.d.ts +5 -0
  15. package/dist/lib/config/strings.d.ts +1 -39
  16. package/dist/lib/draft/index.d.ts +132 -0
  17. package/dist/lib/draft04/index.d.ts +7 -0
  18. package/dist/lib/draft06/compile/index.d.ts +16 -0
  19. package/dist/lib/draft06/index.d.ts +7 -0
  20. package/dist/lib/draft06/validation/keyword.d.ts +3 -0
  21. package/dist/lib/draft06/validation/type.d.ts +10 -0
  22. package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
  23. package/dist/lib/draft07/index.d.ts +7 -0
  24. package/dist/lib/each.d.ts +3 -2
  25. package/dist/lib/eachSchema.d.ts +2 -4
  26. package/dist/lib/getChildSchemaSelection.d.ts +7 -5
  27. package/dist/lib/getSchema.d.ts +2 -2
  28. package/dist/lib/getTemplate.d.ts +1 -1
  29. package/dist/lib/getTypeOf.d.ts +2 -1
  30. package/dist/lib/isValid.d.ts +1 -1
  31. package/dist/lib/jsoneditor/index.d.ts +7 -0
  32. package/dist/lib/resolveAllOf.d.ts +1 -1
  33. package/dist/lib/resolveAnyOf.d.ts +1 -1
  34. package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
  35. package/dist/lib/resolveOneOf.strict.d.ts +2 -2
  36. package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
  37. package/dist/lib/schema/getTypeDefs.d.ts +6 -4
  38. package/dist/lib/schema/getTypeId.d.ts +1 -1
  39. package/dist/lib/schema/types.d.ts +7 -57
  40. package/dist/lib/step.d.ts +5 -5
  41. package/dist/lib/types.d.ts +11 -3
  42. package/dist/lib/utils/createCustomError.d.ts +8 -11
  43. package/dist/lib/utils/filter.d.ts +4 -4
  44. package/dist/lib/utils/flattenArray.d.ts +1 -1
  45. package/dist/lib/utils/merge.d.ts +3 -0
  46. package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
  47. package/dist/lib/validate.d.ts +2 -2
  48. package/dist/lib/validateAsync.d.ts +1 -1
  49. package/dist/lib/validation/errors.d.ts +1 -3
  50. package/dist/lib/validation/format.d.ts +4 -11
  51. package/dist/lib/validation/keyword.d.ts +2 -27
  52. package/dist/lib/validation/type.d.ts +3 -10
  53. package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
  54. package/dist/module/index.js +23 -32
  55. package/dist/module/lib/SchemaService.js +7 -4
  56. package/dist/module/lib/{addSchema.js → addRemoteSchema.js} +2 -4
  57. package/dist/module/lib/addValidator.js +3 -4
  58. package/dist/module/lib/compile/getRef.js +1 -1
  59. package/dist/module/lib/compile/index.js +43 -18
  60. package/dist/module/lib/compile/types.js +1 -0
  61. package/dist/module/lib/config/strings.js +15 -2
  62. package/dist/module/lib/createSchemaOf.js +1 -1
  63. package/dist/module/lib/draft/index.js +133 -0
  64. package/dist/module/lib/draft04/index.js +90 -0
  65. package/dist/module/lib/draft06/compile/index.js +77 -0
  66. package/dist/module/lib/draft06/index.js +96 -0
  67. package/dist/module/lib/draft06/validation/keyword.js +168 -0
  68. package/dist/module/lib/draft06/validation/type.js +31 -0
  69. package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
  70. package/dist/module/lib/draft07/index.js +96 -0
  71. package/dist/module/lib/each.js +2 -2
  72. package/dist/module/lib/eachSchema.js +28 -19
  73. package/dist/module/lib/getChildSchemaSelection.js +7 -6
  74. package/dist/module/lib/getSchema.js +4 -2
  75. package/dist/module/lib/getTemplate.js +42 -15
  76. package/dist/module/lib/jsoneditor/index.js +16 -0
  77. package/dist/module/lib/resolveAllOf.js +3 -4
  78. package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
  79. package/dist/module/lib/resolveOneOf.strict.js +49 -2
  80. package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
  81. package/dist/module/lib/resolveRef.strict.js +8 -0
  82. package/dist/module/lib/schema/getTypeDefs.js +14 -3
  83. package/dist/module/lib/schema/getTypeId.js +10 -6
  84. package/dist/module/lib/schema/types.js +33 -9
  85. package/dist/module/lib/step.js +67 -13
  86. package/dist/module/lib/types.js +7 -1
  87. package/dist/module/lib/utils/createCustomError.js +4 -4
  88. package/dist/module/lib/utils/filter.js +3 -5
  89. package/dist/module/lib/utils/flattenArray.js +4 -3
  90. package/dist/module/lib/utils/merge.js +4 -0
  91. package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
  92. package/dist/module/lib/validate.js +34 -8
  93. package/dist/module/lib/validateAsync.js +7 -7
  94. package/dist/module/lib/validation/errors.js +16 -3
  95. package/dist/module/lib/validation/format.js +115 -8
  96. package/dist/module/lib/validation/keyword.js +79 -32
  97. package/dist/module/lib/validation/type.js +2 -1
  98. package/index.ts +46 -32
  99. package/lib/SchemaService.ts +18 -11
  100. package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
  101. package/lib/addValidator.ts +15 -12
  102. package/lib/compile/getRef.ts +3 -4
  103. package/lib/compile/index.ts +65 -19
  104. package/lib/compile/types.ts +6 -0
  105. package/lib/config/strings.ts +17 -3
  106. package/lib/createSchemaOf.ts +1 -3
  107. package/lib/draft/index.ts +201 -0
  108. package/lib/draft04/index.ts +95 -0
  109. package/lib/draft06/compile/index.ts +104 -0
  110. package/lib/draft06/index.ts +101 -0
  111. package/lib/draft06/validation/keyword.ts +199 -0
  112. package/lib/draft06/validation/type.ts +47 -0
  113. package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
  114. package/lib/draft07/index.ts +101 -0
  115. package/lib/each.ts +11 -4
  116. package/lib/eachSchema.ts +45 -32
  117. package/lib/getChildSchemaSelection.ts +14 -7
  118. package/lib/getSchema.ts +18 -9
  119. package/lib/getTemplate.ts +155 -42
  120. package/lib/getTypeOf.ts +2 -1
  121. package/lib/isValid.ts +7 -3
  122. package/lib/jsoneditor/index.ts +20 -0
  123. package/lib/resolveAllOf.ts +10 -6
  124. package/lib/resolveAnyOf.ts +7 -3
  125. package/lib/resolveOneOf.fuzzy.ts +26 -9
  126. package/lib/resolveOneOf.strict.ts +63 -5
  127. package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
  128. package/lib/resolveRef.strict.ts +9 -0
  129. package/lib/schema/getTypeDefs.ts +19 -7
  130. package/lib/schema/getTypeId.ts +11 -8
  131. package/lib/schema/types.ts +41 -9
  132. package/lib/step.ts +109 -25
  133. package/lib/types.ts +23 -5
  134. package/lib/utils/createCustomError.ts +8 -13
  135. package/lib/utils/filter.ts +7 -9
  136. package/lib/utils/flattenArray.ts +5 -4
  137. package/lib/utils/merge.ts +5 -0
  138. package/lib/utils/punycode.ucs2decode.ts +6 -5
  139. package/lib/validate.ts +47 -16
  140. package/lib/validateAsync.ts +15 -14
  141. package/lib/validation/errors.ts +17 -6
  142. package/lib/validation/format.ts +147 -13
  143. package/lib/validation/keyword.ts +172 -103
  144. package/lib/validation/type.ts +5 -1
  145. package/package.json +75 -63
  146. package/{dist/module/remotes/draft04.json → remotes/draft06.json} +47 -42
  147. package/remotes/draft07.json +172 -0
  148. package/remotes/draft2019-09.json +86 -0
  149. package/tsconfig.json +3 -10
  150. package/dist/lib/cores/CoreInterface.d.ts +0 -23
  151. package/dist/lib/cores/Draft04.d.ts +0 -13
  152. package/dist/lib/cores/JsonEditor.d.ts +0 -13
  153. package/dist/module/lib/cores/CoreInterface.js +0 -51
  154. package/dist/module/lib/cores/Draft04.js +0 -52
  155. package/dist/module/lib/cores/JsonEditor.js +0 -51
  156. package/dist/module/remotes/index.js +0 -10
  157. package/dist/remotes/index.d.ts +0 -5
  158. package/lib/cores/CoreInterface.ts +0 -76
  159. package/lib/cores/Draft04.ts +0 -66
  160. package/lib/cores/JsonEditor.ts +0 -64
  161. package/remotes/index.ts +0 -11
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,269 +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 all draft4 features (@see [benchmark](https://github.com/ebdrup/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 `v5.0.0` the api has changed to es6 modules, where there is no default epxport, 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.
27
- 2. with version `v4.0.0` the api has changed in order to use the defined (root) schema in core as default where
28
- 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
29
- 3. additionally `iterateSchema` has been renamed to `eachSchema` for consistency
30
-
31
-
32
- ## Overview
33
-
34
- Either select an existing __validator__ (`core`) or create your own. Each __Core__ holds all functions that are required
35
- for the json-schema operations like validation. In order to overwrite a custom function you can either
36
-
37
- - modify the map-objects (i.e. [/lib/validation/keywords.js](./lib/validation/keyword.js))
38
- - overwrite functions or keys in the generated instance (`const instance = new Core()`)
39
- - Create a custom __Core__ following the examples in [/lib/cores](./lib/cores)
40
-
41
- Additionally, helper functions and tools are separately exposed via CommonJS Modules. Most of them do require a
42
- core-object as parameter, but use only some of the functions defined in an core-instance.
43
-
44
-
45
- ### Core
46
-
47
- The default interface of a validator can be found in [/lib/cores/CoreInterface](./lib/cores/CoreInterface). It exposes
48
- the following methods
49
-
50
- | method | signature | description
51
- | ----------------- | ------------------------------------- | -------------------------------------------------------------
52
- | constructor | schema : instance | pass the root-schema in the constructor
53
- | each | data, callback, [schema], [pointer] | Iterates over the data, passing value and its schema
54
- | getSchema | pointer, [data], [schema] : Schema | Get the json-schema describing the `data` found at `pointer`
55
- | getTemplate | data, [schema] : Mixed | returns a template object based of the given json-schema
56
- | isValid | data, [schema], [pointer] : Boolean | Check if the given schema validates the data
57
- | resolveOneOf | data, [schema], [pointer] : Schema | returns the oneOf-schema for the passed data
58
- | resolveRef | schema : Schema | resolves a $ref on a given schema-object
59
- | setSchema | schema | set a new (root) schema
60
- | step | key, schema, data, [pointer] : Schema | step into a json-schema by the given key (property or index)
61
- | validate | data, [schema], [pointer] : Array | Get a list of validation errors
62
-
63
-
64
- Each core holds some mapping objects, that may be modified
65
-
66
- ```js
67
- Core {
68
- // keyword validations for each type, e.g. "array": ["enum", "items", "minItems", "maxItems", ...]
69
- // for each item in the given list, the validation function in `validationKeyword` will be called
70
- typeKeywords: {}
71
- // keyword validation functions, e.g. validateKeyword.enum(), validateKeyword.items(), ...
72
- validateKeyword: {}
73
- // type validation for array, object, number, etc. Basically runs over typeKeywords and executes
74
- // validation functions from `validateKeyword`
75
- validateType: {}
76
- // format validation functions. will be executed if a) typeKeywords includes 'format' and a
77
- // validation function is set in validateFormat
78
- validateFormat: {}
79
- // list of error-creator functions. They receive an object with the data of the error and must
80
- // return an object like { type: 'error', message: "" }
81
- errors: {}
82
- }
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);
83
36
  ```
84
37
 
38
+ What follows is a description of the main draft methods.
85
39
 
86
- #### Examples
40
+ ## Draft methods
87
41
 
88
- ##### getSchema(core, pointer, [data], [schema])
89
- > Get the json-schema describing the `data` found at `pointer`.
90
- > The default json-schema definitions can be resolved without any data as input: `core.getSchema('#/article/title')`.
91
- > 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)
92
54
 
93
- ```js
94
- import { Draft04 as Core } from "json-schema-library";
95
- const core = new Core(rootSchema);
96
- const targetSchema = core.getSchema('#/path/to/target', rootData);
97
- ```
98
55
 
99
- Currently may also return an error:
56
+ ### validate
100
57
 
101
- ```js
102
- if (targetSchema.type === "error") {
103
- throw new Error(targetSchema.message);
104
- }
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);
105
63
  ```
106
64
 
107
- 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_
108
66
 
109
- ```js
110
- import { Draft04 as Core } from "json-schema-library";
111
- const core = new Core(rootSchema);
112
- 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" });
113
70
  ```
114
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).
115
73
 
116
- ##### getTemplate(core, data, [schema])
117
- > Generate data which is valid to the given json-schema. Additionally, a data object may be given, which will be
118
- extended by any missing items or properties.
74
+ <details><summary>About type JSONError</summary>
119
75
 
120
- ```js
121
- import { Draft04 as Core } from "json-schema-library";
122
- const core = new Core();
123
- const baseData = core.getTemplate(
124
- { other: true },
125
- { type: "object", properties: { target: { type: "string", default: "v" } } },
126
- ); // 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
+ };
127
86
  ```
128
87
 
129
- ##### validate(core, data, [schema])
130
- > 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";
131
98
 
132
- ```js
133
- import { Draft04 as Core } from "json-schema-library";
134
- const core = new Core(rootSchema);
135
- const errors = core.validate({ validationOf: "rootSchema" });
136
- // validation errors running data for 'rootSchema'
137
- const customSchemaErrors = core.validate("", { type: "number" });
138
- // 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
+ ]);
139
148
  ```
140
149
 
141
- ##### isValid(core, data, [schema])
142
- > Check if the given schema validates the data
150
+ </details>
143
151
 
144
- basically `core.validate("", { type: "number" }).length === 0`
145
152
 
146
- ```js
147
- import { Draft04 as Core } from "json-schema-library";
148
- const core = new Core(rootSchema);
149
- const baseSchema = core.isValid("", { type: "number" });
150
- // 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);
151
160
  ```
152
161
 
153
- ##### validateAsync(core, data, [options])
154
- > 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
155
166
 
156
167
  Optional support for onError helper, which is invoked for each error (after being resolved)
157
168
 
158
- ```js
159
- import { Draft04 as Core } from "json-schema-library";
160
- const core = new Core(rootSchema);
161
- // signature: Core, data, { onError: [onErrorCallback], schema: JSONSchema, pointer: [Pointer]} : Promise
162
- validateAsync(core, "", { onError: (err) => {}, schema: { type: "number" } })
163
- .then(allErrors => {});
164
- ```
165
-
166
- ##### step(core, key, schema, data)
167
- > Get the json-schema of a child-property
168
-
169
- ```js
170
- import { Draft04 as Core } from "json-schema-library";
171
- const core = new Core(rootSchema);
172
- const baseSchema = core.step(
173
- "target"
174
- { type: "object", properties: { target: { type: "string" } } },
175
- { target: "value" }
176
- ); // returns {type: "string"}
177
- ```
178
-
179
- ##### each(core, data, callback, [schema])
180
- > Iterates over each data-item (object, array and value); passing the value and its corresponding schema
181
-
182
- ```js
183
- import { Draft04 as Core } from "json-schema-library";
184
- const core = new Core({
185
- type: "array",
186
- items: [
187
- { type: "number" },
188
- { type: "string" }
189
- ]
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']
190
226
  });
191
- core.each([5, "nine"], (schema, value, pointer) => {
192
- // 1. schema = { type: "array", items: [...] }, data = [5, "nine"], pointer = #
193
- // 2. schema = { type: "number" }, data = 5, pointer = #/0
194
- // 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"]
195
262
  });
196
263
  ```
197
264
 
265
+ </details>
266
+
267
+ ### each
198
268
 
199
- ### 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.
200
270
 
201
- ```js
202
- 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
+ ```
203
278
 
204
- // add a custom format 'id'
205
- addValidator.format(core, "id", (core, schema, value, pointer) => {});
279
+ <details><summary>Example</summary>
206
280
 
207
- // add custom keyword 'capitalized' for type 'string'
208
- addValidator.keyword(core, "string", "capitalized", (core, schema, value, pointer) => {});
281
+ ```ts
282
+ import { Draft07, JSONSchema, JSONPointer } from "json-schema-library";
209
283
 
210
- // add a custom error (may overwrite existing errors)
211
- addValidator.error(core, "minLengthError", (data) => ({
212
- type: "error",
213
- code: "custom-min-length-error",
214
- message: "my custom error message",
215
- data
216
- }));
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
+ });
217
420
  ```
218
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
219
432
 
220
- ### 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.
221
434
 
222
- #### getChildSchemaSelection(core, key, schema)
223
- 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
224
436
 
225
- ```js
226
- import { getChildSchemaSelection } from "json-schema-library";
227
- const listOfAvailableOptions = getChildSchemaSelection(core, "childKey", schema);
437
+ ```ts
438
+ const jsonSchema = new Draft07(mySchema);
439
+ const schemas: JSONSchema[] = jsonSchema.getChildSchemaSelection("content", localSchema);
228
440
  ```
229
441
 
230
- #### createSchemaOf(data)
231
- 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);
232
461
 
233
- ```js
234
- import { createSchemaOf } from "json-schema-library";
235
- const baseSchema = createSchemaOf({ target: "" });
236
- // returns {type: "object", properties: { target: "string"}},
462
+ expect(schemas).to.deep.equal([
463
+ { type: "string" },
464
+ { type: "number" }
465
+ ])
237
466
  ```
238
467
 
239
- #### eachSchema(schema, callback)
240
- Iterate the schema, invoking the callback function for each type (schema) definition
468
+ </details>
469
+
470
+
241
471
 
242
- ```js
243
- import { eachSchema } from "json-schema-library";
244
- 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);
245
481
  ```
246
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
+ ```
247
506
 
248
- ## 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
+ ```
249
520
 
250
- ### 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
251
573
 
252
574
  For error generation, an attribute `patternExample` may be set for a `pattern` validation. Instead of the regular
253
575
  expression, the example will be printed in the error message.
254
576
 
255
- ### oneOf-flag
256
577
 
257
- In `resolveOneOf.fuzzy.js` For an explicit oneOf resolution the schema may be extended by a `oneOfProperty`-property.
258
- This will always associate an entry with a matching value (instead of schema validation).
578
+ ### oneOfProperty
259
579
 
260
- 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.
261
581
 
262
- ```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
263
585
  const schema = {
264
- oneOfProperty: "id",
265
- oneOf: [
266
- { type: "object", properties: { id: { type: "string", pattern: "^1$" }, title: { type: "number" } } },
267
- { type: "object", properties: { id: { type: "string", pattern: "^2$" }, title: { type: "number" } } },
268
- { type: "object", properties: { id: { type: "string", pattern: "^3$" }, title: { type: "number" } } }
269
- ]
270
- }
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);
271
604
 
272
- const result = resolveOneOf(core, { id: "2", title: "not a number" }, schema);
273
605
  // will always return (even if invalid)
274
- // { 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
+ });
275
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.