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.
- package/.editorconfig +1 -0
- package/.prettierignore +1 -0
- package/.prettierrc +7 -0
- package/CHANGELOG.md +106 -0
- package/README.md +811 -199
- package/TASKS.md +3 -81
- package/dist/index.d.ts +29 -71
- package/dist/jsonSchemaLibrary.js +1 -1
- package/dist/lib/SchemaService.d.ts +6 -8
- package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
- package/dist/lib/addValidator.d.ts +3 -2
- package/dist/lib/compile/getRef.d.ts +2 -1
- package/dist/lib/compile/index.d.ts +15 -1
- package/dist/lib/compile/types.d.ts +5 -0
- package/dist/lib/config/strings.d.ts +1 -39
- package/dist/lib/draft/index.d.ts +132 -0
- package/dist/lib/draft04/index.d.ts +7 -0
- package/dist/lib/draft06/compile/index.d.ts +16 -0
- package/dist/lib/draft06/index.d.ts +7 -0
- package/dist/lib/draft06/validation/keyword.d.ts +3 -0
- package/dist/lib/draft06/validation/type.d.ts +10 -0
- package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
- package/dist/lib/draft07/index.d.ts +7 -0
- package/dist/lib/each.d.ts +3 -2
- package/dist/lib/eachSchema.d.ts +2 -4
- package/dist/lib/getChildSchemaSelection.d.ts +7 -5
- package/dist/lib/getSchema.d.ts +2 -2
- package/dist/lib/getTemplate.d.ts +1 -1
- package/dist/lib/getTypeOf.d.ts +2 -1
- package/dist/lib/isValid.d.ts +1 -1
- package/dist/lib/jsoneditor/index.d.ts +7 -0
- package/dist/lib/resolveAllOf.d.ts +1 -1
- package/dist/lib/resolveAnyOf.d.ts +1 -1
- package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
- package/dist/lib/resolveOneOf.strict.d.ts +2 -2
- package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
- package/dist/lib/schema/getTypeDefs.d.ts +6 -4
- package/dist/lib/schema/getTypeId.d.ts +1 -1
- package/dist/lib/schema/types.d.ts +7 -57
- package/dist/lib/step.d.ts +5 -5
- package/dist/lib/types.d.ts +11 -3
- package/dist/lib/utils/createCustomError.d.ts +8 -11
- package/dist/lib/utils/filter.d.ts +4 -4
- package/dist/lib/utils/flattenArray.d.ts +1 -1
- package/dist/lib/utils/merge.d.ts +3 -0
- package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
- package/dist/lib/validate.d.ts +2 -2
- package/dist/lib/validateAsync.d.ts +1 -1
- package/dist/lib/validation/errors.d.ts +1 -3
- package/dist/lib/validation/format.d.ts +4 -11
- package/dist/lib/validation/keyword.d.ts +2 -27
- package/dist/lib/validation/type.d.ts +3 -10
- package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
- package/dist/module/index.js +23 -32
- package/dist/module/lib/SchemaService.js +7 -4
- package/dist/module/lib/{addSchema.js → addRemoteSchema.js} +2 -4
- package/dist/module/lib/addValidator.js +3 -4
- package/dist/module/lib/compile/getRef.js +1 -1
- package/dist/module/lib/compile/index.js +43 -18
- package/dist/module/lib/compile/types.js +1 -0
- package/dist/module/lib/config/strings.js +15 -2
- package/dist/module/lib/createSchemaOf.js +1 -1
- package/dist/module/lib/draft/index.js +133 -0
- package/dist/module/lib/draft04/index.js +90 -0
- package/dist/module/lib/draft06/compile/index.js +77 -0
- package/dist/module/lib/draft06/index.js +96 -0
- package/dist/module/lib/draft06/validation/keyword.js +168 -0
- package/dist/module/lib/draft06/validation/type.js +31 -0
- package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
- package/dist/module/lib/draft07/index.js +96 -0
- package/dist/module/lib/each.js +2 -2
- package/dist/module/lib/eachSchema.js +28 -19
- package/dist/module/lib/getChildSchemaSelection.js +7 -6
- package/dist/module/lib/getSchema.js +4 -2
- package/dist/module/lib/getTemplate.js +42 -15
- package/dist/module/lib/jsoneditor/index.js +16 -0
- package/dist/module/lib/resolveAllOf.js +3 -4
- package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
- package/dist/module/lib/resolveOneOf.strict.js +49 -2
- package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
- package/dist/module/lib/resolveRef.strict.js +8 -0
- package/dist/module/lib/schema/getTypeDefs.js +14 -3
- package/dist/module/lib/schema/getTypeId.js +10 -6
- package/dist/module/lib/schema/types.js +33 -9
- package/dist/module/lib/step.js +67 -13
- package/dist/module/lib/types.js +7 -1
- package/dist/module/lib/utils/createCustomError.js +4 -4
- package/dist/module/lib/utils/filter.js +3 -5
- package/dist/module/lib/utils/flattenArray.js +4 -3
- package/dist/module/lib/utils/merge.js +4 -0
- package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
- package/dist/module/lib/validate.js +34 -8
- package/dist/module/lib/validateAsync.js +7 -7
- package/dist/module/lib/validation/errors.js +16 -3
- package/dist/module/lib/validation/format.js +115 -8
- package/dist/module/lib/validation/keyword.js +79 -32
- package/dist/module/lib/validation/type.js +2 -1
- package/index.ts +46 -32
- package/lib/SchemaService.ts +18 -11
- package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
- package/lib/addValidator.ts +15 -12
- package/lib/compile/getRef.ts +3 -4
- package/lib/compile/index.ts +65 -19
- package/lib/compile/types.ts +6 -0
- package/lib/config/strings.ts +17 -3
- package/lib/createSchemaOf.ts +1 -3
- package/lib/draft/index.ts +201 -0
- package/lib/draft04/index.ts +95 -0
- package/lib/draft06/compile/index.ts +104 -0
- package/lib/draft06/index.ts +101 -0
- package/lib/draft06/validation/keyword.ts +199 -0
- package/lib/draft06/validation/type.ts +47 -0
- package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
- package/lib/draft07/index.ts +101 -0
- package/lib/each.ts +11 -4
- package/lib/eachSchema.ts +45 -32
- package/lib/getChildSchemaSelection.ts +14 -7
- package/lib/getSchema.ts +18 -9
- package/lib/getTemplate.ts +155 -42
- package/lib/getTypeOf.ts +2 -1
- package/lib/isValid.ts +7 -3
- package/lib/jsoneditor/index.ts +20 -0
- package/lib/resolveAllOf.ts +10 -6
- package/lib/resolveAnyOf.ts +7 -3
- package/lib/resolveOneOf.fuzzy.ts +26 -9
- package/lib/resolveOneOf.strict.ts +63 -5
- package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
- package/lib/resolveRef.strict.ts +9 -0
- package/lib/schema/getTypeDefs.ts +19 -7
- package/lib/schema/getTypeId.ts +11 -8
- package/lib/schema/types.ts +41 -9
- package/lib/step.ts +109 -25
- package/lib/types.ts +23 -5
- package/lib/utils/createCustomError.ts +8 -13
- package/lib/utils/filter.ts +7 -9
- package/lib/utils/flattenArray.ts +5 -4
- package/lib/utils/merge.ts +5 -0
- package/lib/utils/punycode.ucs2decode.ts +6 -5
- package/lib/validate.ts +47 -16
- package/lib/validateAsync.ts +15 -14
- package/lib/validation/errors.ts +17 -6
- package/lib/validation/format.ts +147 -13
- package/lib/validation/keyword.ts +172 -103
- package/lib/validation/type.ts +5 -1
- package/package.json +75 -63
- package/{dist/module/remotes/draft04.json → remotes/draft06.json} +47 -42
- package/remotes/draft07.json +172 -0
- package/remotes/draft2019-09.json +86 -0
- package/tsconfig.json +3 -10
- package/dist/lib/cores/CoreInterface.d.ts +0 -23
- package/dist/lib/cores/Draft04.d.ts +0 -13
- package/dist/lib/cores/JsonEditor.d.ts +0 -13
- package/dist/module/lib/cores/CoreInterface.js +0 -51
- package/dist/module/lib/cores/Draft04.js +0 -52
- package/dist/module/lib/cores/JsonEditor.js +0 -51
- package/dist/module/remotes/index.js +0 -10
- package/dist/remotes/index.d.ts +0 -5
- package/lib/cores/CoreInterface.ts +0 -76
- package/lib/cores/Draft04.ts +0 -66
- package/lib/cores/JsonEditor.ts +0 -64
- package/remotes/index.ts +0 -11
|
@@ -4,6 +4,7 @@ import getTypeOf from "./getTypeOf";
|
|
|
4
4
|
import merge from "./utils/merge";
|
|
5
5
|
import copy from "./utils/copy";
|
|
6
6
|
import settings from "./config/settings";
|
|
7
|
+
import { isJSONError } from "./types";
|
|
7
8
|
const defaultOptions = {
|
|
8
9
|
addOptionalProps: true
|
|
9
10
|
};
|
|
@@ -17,7 +18,7 @@ function shouldResolveRef(schema, pointer) {
|
|
|
17
18
|
if ($ref == null) {
|
|
18
19
|
return true;
|
|
19
20
|
}
|
|
20
|
-
const value =
|
|
21
|
+
const value = cache[pointer] == null || cache[pointer][$ref] == null ? 0 : cache[pointer][$ref];
|
|
21
22
|
return value < settings.GET_TEMPLATE_RECURSION_LIMIT;
|
|
22
23
|
}
|
|
23
24
|
function resolveRef(core, schema, pointer) {
|
|
@@ -118,13 +119,16 @@ function getTemplate(core, data, _schema, pointer, opts) {
|
|
|
118
119
|
return undefined;
|
|
119
120
|
}
|
|
120
121
|
pointer = schema.pointer;
|
|
122
|
+
if (schema === null || schema === void 0 ? void 0 : schema.const) {
|
|
123
|
+
return schema.const;
|
|
124
|
+
}
|
|
121
125
|
if (schema.oneOf) {
|
|
122
126
|
// find correct schema for data
|
|
123
127
|
const resolvedSchema = resolveOneOfFuzzy(core, data, schema);
|
|
124
|
-
if (data == null && resolvedSchema
|
|
128
|
+
if (data == null && isJSONError(resolvedSchema)) {
|
|
125
129
|
schema = schema.oneOf[0];
|
|
126
130
|
}
|
|
127
|
-
else if (resolvedSchema.type
|
|
131
|
+
else if (isJSONError(resolvedSchema.type)) {
|
|
128
132
|
// @todo - check: do not return schema, but either input-data or undefined (clearing wrong data)
|
|
129
133
|
return data;
|
|
130
134
|
}
|
|
@@ -132,6 +136,9 @@ function getTemplate(core, data, _schema, pointer, opts) {
|
|
|
132
136
|
schema = resolvedSchema;
|
|
133
137
|
}
|
|
134
138
|
}
|
|
139
|
+
// @todo Array.isArray(schema.type)
|
|
140
|
+
// -> hasDefault? return
|
|
141
|
+
// if not -> pick first type
|
|
135
142
|
if (!isJSONSchema(schema) || schema.type == null) {
|
|
136
143
|
return undefined;
|
|
137
144
|
}
|
|
@@ -139,23 +146,25 @@ function getTemplate(core, data, _schema, pointer, opts) {
|
|
|
139
146
|
if (data != null && getTypeOf(data) !== schema.type) {
|
|
140
147
|
data = convertValue(schema.type, data);
|
|
141
148
|
}
|
|
142
|
-
if (TYPE[schema.type] == null) {
|
|
149
|
+
if (TYPE[schema.type] == null) {
|
|
150
|
+
// eslint-disable-line no-use-before-define
|
|
143
151
|
throw new Error(`Unsupported type '${schema.type} in ${JSON.stringify(schema)}'`);
|
|
144
152
|
}
|
|
145
153
|
const templateData = TYPE[schema.type](core, schema, data, pointer, opts); // eslint-disable-line no-use-before-define
|
|
146
154
|
return templateData;
|
|
147
155
|
}
|
|
148
156
|
const TYPE = {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
null: (core, schema, data) => getDefault(schema, data, null),
|
|
158
|
+
string: (core, schema, data) => getDefault(schema, data, ""),
|
|
159
|
+
number: (core, schema, data) => getDefault(schema, data, 0),
|
|
160
|
+
integer: (core, schema, data) => getDefault(schema, data, 0),
|
|
161
|
+
boolean: (core, schema, data) => getDefault(schema, data, false),
|
|
162
|
+
object: (core, schema, data, pointer, opts) => {
|
|
154
163
|
const template = schema.default === undefined ? {} : schema.default;
|
|
155
164
|
const d = {}; // do not assign data here, to keep ordering from json-schema
|
|
156
165
|
if (schema.properties) {
|
|
157
|
-
Object.keys(schema.properties).forEach(key => {
|
|
158
|
-
const value =
|
|
166
|
+
Object.keys(schema.properties).forEach((key) => {
|
|
167
|
+
const value = data == null || data[key] == null ? template[key] : data[key];
|
|
159
168
|
const isRequired = Array.isArray(schema.required) && schema.required.includes(key);
|
|
160
169
|
// Omit adding a property if it is not required or optional props should be added
|
|
161
170
|
if (value != null || isRequired || opts.addOptionalProps) {
|
|
@@ -163,18 +172,33 @@ const TYPE = {
|
|
|
163
172
|
}
|
|
164
173
|
});
|
|
165
174
|
}
|
|
175
|
+
if (schema.dependencies) {
|
|
176
|
+
Object.keys(schema.dependencies).forEach((key) => {
|
|
177
|
+
const dependency = schema.dependencies[key];
|
|
178
|
+
if (getTypeOf(dependency) !== "object") {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (d[key] === undefined) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
const result = getTemplate(core, data, { ...dependency, type: "object" }, `${pointer}/dependencies/${key}`, opts);
|
|
185
|
+
if (result && !isJSONError(result)) {
|
|
186
|
+
Object.assign(d, result);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
166
190
|
if (data) {
|
|
167
191
|
// merge any missing data (additionals) to resulting object
|
|
168
|
-
Object.keys(data).forEach(key =>
|
|
192
|
+
Object.keys(data).forEach((key) => d[key] == null && (d[key] = data[key]));
|
|
169
193
|
}
|
|
170
194
|
// returns object, which is ordered by json-schema
|
|
171
195
|
return d;
|
|
172
196
|
},
|
|
173
197
|
// build array type of items, ignores additionalItems
|
|
174
|
-
|
|
198
|
+
array: (core, schema, data, pointer, opts) => {
|
|
175
199
|
const template = schema.default === undefined ? [] : schema.default;
|
|
176
|
-
const d = data || [];
|
|
177
200
|
schema.minItems = schema.minItems || 0;
|
|
201
|
+
const d = data || [];
|
|
178
202
|
// items are undefined
|
|
179
203
|
if (schema.items == null) {
|
|
180
204
|
return d;
|
|
@@ -232,6 +256,9 @@ function getDefault(schema, templateValue, initValue) {
|
|
|
232
256
|
if (templateValue != null) {
|
|
233
257
|
return templateValue;
|
|
234
258
|
}
|
|
259
|
+
else if (schema.const) {
|
|
260
|
+
return schema.const;
|
|
261
|
+
}
|
|
235
262
|
else if (schema.default === undefined && Array.isArray(schema.enum)) {
|
|
236
263
|
return schema.enum[0];
|
|
237
264
|
}
|
|
@@ -241,6 +268,6 @@ function getDefault(schema, templateValue, initValue) {
|
|
|
241
268
|
return schema.default;
|
|
242
269
|
}
|
|
243
270
|
export default (core, data, schema = core.rootSchema, opts = defaultOptions) => {
|
|
244
|
-
cache = {
|
|
271
|
+
cache = { mi: {} };
|
|
245
272
|
return getTemplate(core, data, schema, "#", opts);
|
|
246
273
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import merge from "../utils/merge";
|
|
2
|
+
import resolveOneOf from "../resolveOneOf.fuzzy";
|
|
3
|
+
import resolveRef from "../resolveRef.merge";
|
|
4
|
+
import { Draft } from "../draft";
|
|
5
|
+
import { draft07Config } from "../draft07";
|
|
6
|
+
const draftJsonEditorConfig = {
|
|
7
|
+
...draft07Config,
|
|
8
|
+
resolveOneOf,
|
|
9
|
+
resolveRef
|
|
10
|
+
};
|
|
11
|
+
class JsonEditor extends Draft {
|
|
12
|
+
constructor(schema, config = {}) {
|
|
13
|
+
super(merge(draftJsonEditorConfig, config), schema);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export { JsonEditor, draftJsonEditorConfig };
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import copy from "./utils/copy";
|
|
2
2
|
import merge from "./utils/merge";
|
|
3
|
-
import errors from "./validation/errors";
|
|
4
3
|
export default function resolveAllOf(core, data, schema = core.rootSchema, pointer = "#") {
|
|
5
4
|
let mergedSchema = copy(schema);
|
|
6
5
|
for (let i = 0; i < schema.allOf.length; i += 1) {
|
|
7
6
|
const allOfSchema = core.resolveRef(schema.allOf[i]);
|
|
8
|
-
if (core.isValid(data, allOfSchema, pointer) === false) {
|
|
9
|
-
|
|
10
|
-
}
|
|
7
|
+
// if (core.isValid(data, allOfSchema, pointer) === false) {
|
|
8
|
+
// return errors.allOfError({ value: data, pointer, allOf: JSON.stringify(schema.allOf) });
|
|
9
|
+
// }
|
|
11
10
|
mergedSchema = merge(mergedSchema, allOfSchema);
|
|
12
11
|
}
|
|
13
12
|
delete mergedSchema.allOf;
|
|
@@ -2,6 +2,7 @@ import { errorOrPromise } from "./utils/filter";
|
|
|
2
2
|
import flattenArray from "./utils/flattenArray";
|
|
3
3
|
import getTypeOf from "./getTypeOf";
|
|
4
4
|
import settings from "./config/settings";
|
|
5
|
+
import { isJSONError } from "./types";
|
|
5
6
|
const { DECLARATOR_ONEOF } = settings;
|
|
6
7
|
/**
|
|
7
8
|
* Returns a ranking for the data and given schema
|
|
@@ -52,7 +53,7 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
|
|
|
52
53
|
for (let i = 0; i < schema.oneOf.length; i += 1) {
|
|
53
54
|
const one = core.resolveRef(schema.oneOf[i]);
|
|
54
55
|
const oneOfPropertySchema = core.step(oneOfProperty, one, data, pointer);
|
|
55
|
-
if (oneOfPropertySchema
|
|
56
|
+
if (isJSONError(oneOfPropertySchema)) {
|
|
56
57
|
return oneOfPropertySchema;
|
|
57
58
|
}
|
|
58
59
|
let result = flattenArray(core.validate(oneOfValue, oneOfPropertySchema, pointer));
|
|
@@ -64,7 +65,12 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
|
|
|
64
65
|
return one; // return resolved schema
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
|
-
return core.errors.oneOfPropertyError({
|
|
68
|
+
return core.errors.oneOfPropertyError({
|
|
69
|
+
property: oneOfProperty,
|
|
70
|
+
value: oneOfValue,
|
|
71
|
+
pointer,
|
|
72
|
+
errors
|
|
73
|
+
});
|
|
68
74
|
}
|
|
69
75
|
// keyword: oneOf
|
|
70
76
|
const matches = [];
|
|
@@ -90,7 +96,11 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
|
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
if (schemaOfItem === undefined) {
|
|
93
|
-
return core.errors.oneOfError({
|
|
99
|
+
return core.errors.oneOfError({
|
|
100
|
+
value: JSON.stringify(data),
|
|
101
|
+
pointer,
|
|
102
|
+
oneOf: schema.oneOf
|
|
103
|
+
});
|
|
94
104
|
}
|
|
95
105
|
return schemaOfItem;
|
|
96
106
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { errorOrPromise } from "./utils/filter";
|
|
2
2
|
import flattenArray from "./utils/flattenArray";
|
|
3
|
+
import settings from "./config/settings";
|
|
4
|
+
import { isJSONError } from "./types";
|
|
5
|
+
const { DECLARATOR_ONEOF } = settings;
|
|
3
6
|
/**
|
|
4
7
|
* Selects and returns a oneOf schema for the given data
|
|
5
8
|
*
|
|
@@ -10,6 +13,41 @@ import flattenArray from "./utils/flattenArray";
|
|
|
10
13
|
* @return oneOf schema or an error
|
|
11
14
|
*/
|
|
12
15
|
export default function resolveOneOf(core, data, schema = core.rootSchema, pointer = "#") {
|
|
16
|
+
// !keyword: oneOfProperty
|
|
17
|
+
// an additional <DECLARATOR_ONEOF> (default `oneOfProperty`) on the schema will exactly determine the
|
|
18
|
+
// oneOf value (if set in data)
|
|
19
|
+
// @fixme
|
|
20
|
+
// abort if no data is given an DECLARATOR_ONEOF is set (used by getChildSchemaSelection)
|
|
21
|
+
// this case (data != null) should not be necessary
|
|
22
|
+
if (data != null && schema[DECLARATOR_ONEOF]) {
|
|
23
|
+
const errors = [];
|
|
24
|
+
const oneOfProperty = schema[DECLARATOR_ONEOF];
|
|
25
|
+
const oneOfValue = data[schema[DECLARATOR_ONEOF]];
|
|
26
|
+
if (oneOfValue === undefined) {
|
|
27
|
+
return core.errors.missingOneOfPropertyError({ property: oneOfProperty, pointer });
|
|
28
|
+
}
|
|
29
|
+
for (let i = 0; i < schema.oneOf.length; i += 1) {
|
|
30
|
+
const one = core.resolveRef(schema.oneOf[i]);
|
|
31
|
+
const oneOfPropertySchema = core.step(oneOfProperty, one, data, pointer);
|
|
32
|
+
if (isJSONError(oneOfPropertySchema)) {
|
|
33
|
+
return oneOfPropertySchema;
|
|
34
|
+
}
|
|
35
|
+
let result = flattenArray(core.validate(oneOfValue, oneOfPropertySchema, pointer));
|
|
36
|
+
result = result.filter(errorOrPromise);
|
|
37
|
+
if (result.length > 0) {
|
|
38
|
+
errors.push(...result);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
return one; // return resolved schema
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return core.errors.oneOfPropertyError({
|
|
45
|
+
property: oneOfProperty,
|
|
46
|
+
value: oneOfValue,
|
|
47
|
+
pointer,
|
|
48
|
+
errors
|
|
49
|
+
});
|
|
50
|
+
}
|
|
13
51
|
const matches = [];
|
|
14
52
|
const errors = [];
|
|
15
53
|
for (let i = 0; i < schema.oneOf.length; i += 1) {
|
|
@@ -27,7 +65,16 @@ export default function resolveOneOf(core, data, schema = core.rootSchema, point
|
|
|
27
65
|
return matches[0];
|
|
28
66
|
}
|
|
29
67
|
if (matches.length > 1) {
|
|
30
|
-
return core.errors.multipleOneOfError({
|
|
68
|
+
return core.errors.multipleOneOfError({
|
|
69
|
+
value: data,
|
|
70
|
+
pointer,
|
|
71
|
+
matches
|
|
72
|
+
});
|
|
31
73
|
}
|
|
32
|
-
return core.errors.oneOfError({
|
|
74
|
+
return core.errors.oneOfError({
|
|
75
|
+
value: JSON.stringify(data),
|
|
76
|
+
pointer,
|
|
77
|
+
oneOf: schema.oneOf,
|
|
78
|
+
errors
|
|
79
|
+
});
|
|
33
80
|
}
|
|
File without changes
|
|
@@ -2,6 +2,14 @@ export default function resolveRef(schema, rootSchema) {
|
|
|
2
2
|
if (schema == null || schema.$ref == null) {
|
|
3
3
|
return schema;
|
|
4
4
|
}
|
|
5
|
+
if (schema.getRoot) {
|
|
6
|
+
// we actually always need to resolve the schema like this, since returned subschemas
|
|
7
|
+
// must resolve relative from their schema
|
|
8
|
+
const resolvedSchema = schema.getRoot().getRef(schema);
|
|
9
|
+
// console.log(schema.$ref, "=>", resolvedSchema);
|
|
10
|
+
return resolvedSchema;
|
|
11
|
+
}
|
|
12
|
+
// tryout - this should never be called, except we missed something
|
|
5
13
|
const resolvedSchema = rootSchema.getRef(schema);
|
|
6
14
|
return resolvedSchema;
|
|
7
15
|
}
|
|
@@ -2,7 +2,7 @@ import gp from "gson-pointer";
|
|
|
2
2
|
import { get } from "gson-query";
|
|
3
3
|
import getTypeId from "./getTypeId";
|
|
4
4
|
import types from "./types";
|
|
5
|
-
const isObject = value => Object.prototype.toString.call(value) === "[object Object]";
|
|
5
|
+
const isObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
6
6
|
/**
|
|
7
7
|
* Returns a list of all (direct) type definitions from the given schema
|
|
8
8
|
* @param schema
|
|
@@ -14,11 +14,22 @@ export default function getTypeDefs(schema) {
|
|
|
14
14
|
if (id == null) {
|
|
15
15
|
return defs;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
let type;
|
|
18
|
+
if (Array.isArray(id)) {
|
|
19
|
+
// since types can also be declared as a set of types, merge the definitions
|
|
20
|
+
// maybe this will require a more sophisticated approach
|
|
21
|
+
type = {};
|
|
22
|
+
for (let i = 0, l = id.length; i < l; i += 1) {
|
|
23
|
+
Object.assign(type, types[id[i]]);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
type = types[id];
|
|
28
|
+
}
|
|
18
29
|
if (type.definitions == null) {
|
|
19
30
|
return defs;
|
|
20
31
|
}
|
|
21
|
-
type.definitions.forEach(query => {
|
|
32
|
+
type.definitions.forEach((query) => {
|
|
22
33
|
get(schema, query, (value, key, parent, pointer) => {
|
|
23
34
|
if (isObject(value) && getTypeId(value)) {
|
|
24
35
|
defs.push({ pointer: gp.join(gp.split(pointer), false), def: value });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import types from "./types";
|
|
2
|
-
const isObject = value => Object.prototype.toString.call(value) === "[object Object]";
|
|
3
|
-
const typeKeywords = Object.keys(types).filter(id => types[id].type === false);
|
|
2
|
+
const isObject = (value) => Object.prototype.toString.call(value) === "[object Object]";
|
|
3
|
+
const typeKeywords = Object.keys(types).filter((id) => types[id].type === false);
|
|
4
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
4
5
|
/**
|
|
5
6
|
* @throws Error on multiple matches (invalid schema)
|
|
6
7
|
*
|
|
@@ -15,10 +16,11 @@ export default function getTypeId(schema) {
|
|
|
15
16
|
if (schema.enum) {
|
|
16
17
|
return "enum";
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
if (types[schema.type] || Array.isArray(schema.type)) {
|
|
19
21
|
return schema.type;
|
|
20
22
|
}
|
|
21
|
-
const ids = typeKeywords.filter(type => schema[type]);
|
|
23
|
+
const ids = typeKeywords.filter((type) => schema[type]);
|
|
22
24
|
if (ids.length === 1) {
|
|
23
25
|
return ids[0];
|
|
24
26
|
}
|
|
@@ -26,14 +28,16 @@ export default function getTypeId(schema) {
|
|
|
26
28
|
// @expensive, guess type object
|
|
27
29
|
for (let i = 0, l = types.object.keywords.length; i < l; i += 1) {
|
|
28
30
|
const keyword = types.object.keywords[i];
|
|
29
|
-
if (
|
|
31
|
+
if (hasOwnProperty.call(schema, keyword)) {
|
|
32
|
+
// eslint-disable-line
|
|
30
33
|
return "object";
|
|
31
34
|
}
|
|
32
35
|
}
|
|
33
36
|
// @expensive, guess type array
|
|
34
37
|
for (let i = 0, l = types.array.keywords.length; i < l; i += 1) {
|
|
35
38
|
const keyword = types.array.keywords[i];
|
|
36
|
-
if (
|
|
39
|
+
if (hasOwnProperty.call(schema, keyword)) {
|
|
40
|
+
// eslint-disable-line
|
|
37
41
|
return "array";
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
const Types = {
|
|
2
2
|
$ref: {
|
|
3
3
|
type: false
|
|
4
4
|
},
|
|
@@ -13,14 +13,22 @@ export default {
|
|
|
13
13
|
array: {
|
|
14
14
|
type: true,
|
|
15
15
|
// ignore additionalItems:TypeDef, when items:TypeDef
|
|
16
|
-
definitions: [
|
|
16
|
+
definitions: [
|
|
17
|
+
"allOf/*",
|
|
18
|
+
"anyOf/*",
|
|
19
|
+
"oneOf/*",
|
|
20
|
+
"not",
|
|
21
|
+
"items",
|
|
22
|
+
"items/*",
|
|
23
|
+
"additionalItems"
|
|
24
|
+
],
|
|
17
25
|
validationKeywords: ["minItems", "maxItems", "uniqueItems"],
|
|
18
26
|
keywords: ["items", "additionalItems", "minItems", "maxItems", "uniqueItems"]
|
|
19
27
|
},
|
|
20
|
-
|
|
28
|
+
boolean: {
|
|
21
29
|
type: true
|
|
22
30
|
},
|
|
23
|
-
|
|
31
|
+
enum: {
|
|
24
32
|
type: false
|
|
25
33
|
},
|
|
26
34
|
integer: {
|
|
@@ -37,7 +45,7 @@ export default {
|
|
|
37
45
|
definitions: ["allOf/*", "anyOf/*", "oneOf/*", "not"],
|
|
38
46
|
validationKeywords: ["minimum", "maximum", "multipleOf"]
|
|
39
47
|
},
|
|
40
|
-
|
|
48
|
+
null: {
|
|
41
49
|
type: true
|
|
42
50
|
},
|
|
43
51
|
object: {
|
|
@@ -45,11 +53,26 @@ export default {
|
|
|
45
53
|
// patternProperties also validate properties
|
|
46
54
|
// dependencies:(string, TypeDef) extend current TypeDef
|
|
47
55
|
// additional Properties validate only remaining properties (after properties & pattern)
|
|
48
|
-
definitions: [
|
|
49
|
-
"
|
|
56
|
+
definitions: [
|
|
57
|
+
"allOf/*",
|
|
58
|
+
"anyOf/*",
|
|
59
|
+
"oneOf/*",
|
|
60
|
+
"not",
|
|
61
|
+
"properties/*",
|
|
62
|
+
"additionalProperties",
|
|
63
|
+
"patternProperties/*",
|
|
64
|
+
"dependencies/*"
|
|
65
|
+
],
|
|
50
66
|
validationKeywords: ["minProperties", "maxProperties", "required"],
|
|
51
|
-
keywords: [
|
|
52
|
-
"
|
|
67
|
+
keywords: [
|
|
68
|
+
"properties",
|
|
69
|
+
"additionalProperties",
|
|
70
|
+
"patternProperties",
|
|
71
|
+
"dependencies",
|
|
72
|
+
"minProperties",
|
|
73
|
+
"maxProperties",
|
|
74
|
+
"required"
|
|
75
|
+
]
|
|
53
76
|
},
|
|
54
77
|
oneOf: {
|
|
55
78
|
type: false,
|
|
@@ -61,3 +84,4 @@ export default {
|
|
|
61
84
|
validationKeywords: ["minLength", "maxLength", "pattern"]
|
|
62
85
|
}
|
|
63
86
|
};
|
|
87
|
+
export default Types;
|
package/dist/module/lib/step.js
CHANGED
|
@@ -2,6 +2,7 @@ import getTypeOf from "./getTypeOf";
|
|
|
2
2
|
import createSchemaOf from "./createSchemaOf";
|
|
3
3
|
import errors from "./validation/errors";
|
|
4
4
|
import merge from "./utils/merge";
|
|
5
|
+
import { isJSONError } from "./types";
|
|
5
6
|
const stepType = {
|
|
6
7
|
array: (core, key, schema, data, pointer) => {
|
|
7
8
|
const itemsType = getTypeOf(schema.items);
|
|
@@ -23,11 +24,27 @@ const stepType = {
|
|
|
23
24
|
return core.resolveRef(schema.items);
|
|
24
25
|
}
|
|
25
26
|
if (itemsType === "array") {
|
|
27
|
+
// @draft >= 7 bool schema, items:[true, false]
|
|
28
|
+
if (schema.items[key] === true) {
|
|
29
|
+
return createSchemaOf(data[key]);
|
|
30
|
+
}
|
|
31
|
+
// @draft >= 7 bool schema, items:[true, false]
|
|
32
|
+
if (schema.items[key] === false) {
|
|
33
|
+
return errors.invalidDataError({
|
|
34
|
+
key,
|
|
35
|
+
value: data[key],
|
|
36
|
+
pointer
|
|
37
|
+
});
|
|
38
|
+
}
|
|
26
39
|
if (schema.items[key]) {
|
|
27
40
|
return core.resolveRef(schema.items[key]);
|
|
28
41
|
}
|
|
29
42
|
if (schema.additionalItems === false) {
|
|
30
|
-
return errors.additionalItemsError({
|
|
43
|
+
return errors.additionalItemsError({
|
|
44
|
+
key,
|
|
45
|
+
value: data[key],
|
|
46
|
+
pointer
|
|
47
|
+
});
|
|
31
48
|
}
|
|
32
49
|
if (schema.additionalItems === true || schema.additionalItems === undefined) {
|
|
33
50
|
return createSchemaOf(data[key]);
|
|
@@ -50,21 +67,21 @@ const stepType = {
|
|
|
50
67
|
const oneOfSchema = core.resolveOneOf(data, schema, pointer);
|
|
51
68
|
// resolveOneOf does currently not apply merge with base schema
|
|
52
69
|
schema = merge(schema, oneOfSchema);
|
|
53
|
-
if (schema
|
|
70
|
+
if (isJSONError(schema)) {
|
|
54
71
|
return schema;
|
|
55
72
|
}
|
|
56
73
|
}
|
|
57
74
|
if (Array.isArray(schema.anyOf)) {
|
|
58
75
|
// update current schema
|
|
59
76
|
schema = core.resolveAnyOf(data, schema, pointer);
|
|
60
|
-
if (schema
|
|
77
|
+
if (isJSONError(schema)) {
|
|
61
78
|
return schema;
|
|
62
79
|
}
|
|
63
80
|
}
|
|
64
81
|
if (Array.isArray(schema.allOf)) {
|
|
65
82
|
// update current schema
|
|
66
83
|
schema = core.resolveAllOf(data, schema, pointer);
|
|
67
|
-
if (schema
|
|
84
|
+
if (isJSONError(schema)) {
|
|
68
85
|
return schema;
|
|
69
86
|
}
|
|
70
87
|
}
|
|
@@ -73,7 +90,7 @@ const stepType = {
|
|
|
73
90
|
if (schema.properties && schema.properties[key] !== undefined) {
|
|
74
91
|
// @todo patternProperties also validate properties
|
|
75
92
|
targetSchema = core.resolveRef(schema.properties[key]);
|
|
76
|
-
if (targetSchema
|
|
93
|
+
if (isJSONError(targetSchema)) {
|
|
77
94
|
return targetSchema;
|
|
78
95
|
}
|
|
79
96
|
// check if there is a oneOf selection, which must be resolved
|
|
@@ -81,8 +98,10 @@ const stepType = {
|
|
|
81
98
|
// @special case: this is a mix of a schema and optional definitions
|
|
82
99
|
// we resolve the schema here and add the original schema to `oneOfSchema`
|
|
83
100
|
let resolvedSchema = core.resolveOneOf(data[key], targetSchema, `${pointer}/${key}`);
|
|
101
|
+
const oneOfIndex = targetSchema.oneOf.findIndex((s) => s === resolvedSchema);
|
|
84
102
|
resolvedSchema = JSON.parse(JSON.stringify(resolvedSchema));
|
|
85
103
|
resolvedSchema.variableSchema = true;
|
|
104
|
+
resolvedSchema.oneOfIndex = oneOfIndex;
|
|
86
105
|
resolvedSchema.oneOfSchema = targetSchema;
|
|
87
106
|
return resolvedSchema;
|
|
88
107
|
}
|
|
@@ -91,6 +110,20 @@ const stepType = {
|
|
|
91
110
|
return targetSchema;
|
|
92
111
|
}
|
|
93
112
|
}
|
|
113
|
+
// @draft <= 07
|
|
114
|
+
const { dependencies } = schema;
|
|
115
|
+
if (getTypeOf(dependencies) === "object") {
|
|
116
|
+
const dependentProperties = Object.keys(dependencies).filter((propertyName) =>
|
|
117
|
+
// data[propertyName] !== undefined &&
|
|
118
|
+
getTypeOf(dependencies[propertyName]) === "object");
|
|
119
|
+
for (let i = 0, l = dependentProperties.length; i < l; i += 1) {
|
|
120
|
+
const dependentProperty = dependentProperties[i];
|
|
121
|
+
const schema = step(core, key, dependencies[dependentProperty], data);
|
|
122
|
+
if (!isJSONError(schema)) {
|
|
123
|
+
return schema;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
94
127
|
// find matching property key
|
|
95
128
|
if (getTypeOf(schema.patternProperties) === "object") {
|
|
96
129
|
let regex;
|
|
@@ -106,9 +139,14 @@ const stepType = {
|
|
|
106
139
|
return schema.additionalProperties;
|
|
107
140
|
}
|
|
108
141
|
if (schema.additionalProperties === true) {
|
|
109
|
-
return createSchemaOf(data);
|
|
142
|
+
return createSchemaOf(data[key]);
|
|
110
143
|
}
|
|
111
|
-
return errors.unknownPropertyError({
|
|
144
|
+
return errors.unknownPropertyError({
|
|
145
|
+
property: key,
|
|
146
|
+
value: data,
|
|
147
|
+
// pointer: `${pointer}/${key}`,
|
|
148
|
+
pointer: `${pointer}`
|
|
149
|
+
});
|
|
112
150
|
}
|
|
113
151
|
};
|
|
114
152
|
/**
|
|
@@ -118,17 +156,33 @@ const stepType = {
|
|
|
118
156
|
* This helper determines the location of the property within the schema (additional properties, oneOf, ...) and
|
|
119
157
|
* returns the correct schema.
|
|
120
158
|
*
|
|
121
|
-
* @param core
|
|
122
|
-
* @param key
|
|
123
|
-
* @param schema
|
|
159
|
+
* @param core - validator
|
|
160
|
+
* @param key - property-name or array-index
|
|
161
|
+
* @param schema - json schema of current data
|
|
124
162
|
* @param data - parent of key
|
|
125
|
-
* @param [pointer]
|
|
163
|
+
* @param [pointer] - pointer to schema and data (parent of key)
|
|
126
164
|
* @return Schema or Error if failed resolving key
|
|
127
165
|
*/
|
|
128
166
|
export default function step(core, key, schema, data, pointer = "#") {
|
|
167
|
+
// @draft >= 4 ?
|
|
168
|
+
if (Array.isArray(schema.type)) {
|
|
169
|
+
const dataType = getTypeOf(data);
|
|
170
|
+
if (schema.type.includes(dataType)) {
|
|
171
|
+
// @ts-ignore
|
|
172
|
+
return stepType[dataType](core, `${key}`, schema, data, pointer);
|
|
173
|
+
}
|
|
174
|
+
return core.errors.typeError({
|
|
175
|
+
value: data,
|
|
176
|
+
pointer,
|
|
177
|
+
expected: schema.type,
|
|
178
|
+
received: dataType
|
|
179
|
+
});
|
|
180
|
+
}
|
|
129
181
|
const expectedType = schema.type || getTypeOf(data);
|
|
130
|
-
|
|
131
|
-
|
|
182
|
+
// @ts-ignore
|
|
183
|
+
const stepFunction = stepType[expectedType];
|
|
184
|
+
if (stepFunction) {
|
|
185
|
+
return stepFunction(core, `${key}`, schema, data, pointer);
|
|
132
186
|
}
|
|
133
187
|
return new Error(`Unsupported schema type ${schema.type} for key ${key}`);
|
|
134
188
|
}
|
package/dist/module/lib/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import __ from "./__";
|
|
2
|
-
function dashCase(
|
|
3
|
-
return
|
|
2
|
+
function dashCase(text) {
|
|
3
|
+
return text.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
4
4
|
}
|
|
5
5
|
export function createError(name, data) {
|
|
6
6
|
return {
|
|
@@ -13,11 +13,11 @@ export function createError(name, data) {
|
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
15
|
* Creates a custom Error-Constructor which instances may be identified by `customError instanceof Error`. Its messages
|
|
16
|
-
* are defined by strings-object
|
|
16
|
+
* are defined by strings-object @see config/strings.ts
|
|
17
17
|
*
|
|
18
18
|
* @param name - id of error (camelcased)
|
|
19
19
|
* @return error constructor function
|
|
20
20
|
*/
|
|
21
|
-
export
|
|
21
|
+
export function createCustomError(name) {
|
|
22
22
|
return createError.bind(null, name);
|
|
23
23
|
}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
+
import { isJSONError } from "../types";
|
|
1
2
|
export function isPromise(obj) {
|
|
2
3
|
return obj instanceof Promise;
|
|
3
4
|
}
|
|
4
|
-
export function isError(obj) {
|
|
5
|
-
return obj && obj.type === "error";
|
|
6
|
-
}
|
|
7
5
|
export function errorOrPromise(error) {
|
|
8
|
-
return
|
|
6
|
+
return isJSONError(error) || isPromise(error);
|
|
9
7
|
}
|
|
10
8
|
export function errorsOnly(error) {
|
|
11
|
-
return
|
|
9
|
+
return isJSONError(error);
|
|
12
10
|
}
|