json-schema-library 11.0.0 → 11.0.2
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/.vscode/launch.json +37 -0
- package/README.md +4 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +27 -3
- package/dist/index.d.mts +27 -3
- package/dist/index.mjs +1 -1
- package/dist/jlib.js +2 -2
- package/package.json +2 -2
- package/src/SchemaNode.ts +26 -4
- package/src/draftEditor.ts +4 -4
- package/src/errors/errors.ts +3 -2
- package/src/getNode.oneOfProperty.test.ts +43 -0
- package/src/{compileSchema.getNode.test.ts → getNode.test.ts} +1 -1
- package/src/getNode.ts +16 -3
- package/src/getNodeChild.ts +34 -28
- package/src/keywords/oneOf.test.ts +190 -32
- package/src/keywords/oneOf.ts +83 -8
- package/src/keywords/prefixItems.ts +0 -9
- package/src/methods/getChildSelection.test.ts +18 -0
- package/src/methods/getChildSelection.ts +1 -1
- package/src/methods/getData.test.ts +1779 -1781
- package/src/{compileSchema.reduceSchema.test.ts → reduceNode.test.ts} +0 -1
- package/src/{compileSchema.validate.test.ts → validate.test.ts} +1 -1
- /package/src/{compileSchema.getChild.test.ts → getChildNode.test.ts} +0 -0
package/src/keywords/oneOf.ts
CHANGED
|
@@ -101,42 +101,57 @@ function reduceOneOf({ node, data, pointer, path }: Omit<JsonSchemaReducerParams
|
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Returns matching oneOf schema identified by matching schema for oneOfProperty
|
|
106
|
+
*/
|
|
104
107
|
export function reduceOneOfDeclarator({ node, data, pointer, path }: Omit<JsonSchemaReducerParams, "key">) {
|
|
105
108
|
if (node.oneOf == null) {
|
|
106
109
|
return;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
const errors: ValidationReturnType = [];
|
|
110
112
|
const oneOfProperty = node.schema[DECLARATOR_ONEOF];
|
|
111
|
-
const
|
|
113
|
+
const oneOfPropertyValue = getValue(data, oneOfProperty);
|
|
112
114
|
|
|
113
|
-
|
|
115
|
+
// in this case, we also fail when data undefined as this always is valid,
|
|
116
|
+
// but not in context on an expected oneOfProperty
|
|
117
|
+
if (data === undefined || oneOfPropertyValue === undefined) {
|
|
114
118
|
return node.createError("missing-one-of-property-error", {
|
|
115
|
-
|
|
119
|
+
oneOfProperty,
|
|
116
120
|
pointer,
|
|
117
121
|
schema: node.schema,
|
|
118
122
|
value: data
|
|
119
123
|
});
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
// find oneOf schema that has a matching oneOfProperty to the current input data
|
|
127
|
+
// TODO throw an error if multiple matches were found
|
|
128
|
+
const errors: ValidationReturnType = [];
|
|
122
129
|
for (let i = 0; i < node.oneOf.length; i += 1) {
|
|
123
130
|
const { node: resultNode } = node.oneOf[i].getNodeChild(oneOfProperty, data);
|
|
124
131
|
if (!isSchemaNode(resultNode)) {
|
|
132
|
+
// one of the oneOf schemas has a missing oneOfTypeProperty
|
|
133
|
+
// TODO this still might succeed
|
|
134
|
+
// TODO there is a possibility this throws an invalid error as we use input data
|
|
125
135
|
return node.createError("missing-one-of-declarator-error", {
|
|
126
136
|
declarator: DECLARATOR_ONEOF,
|
|
127
137
|
oneOfProperty,
|
|
128
|
-
|
|
138
|
+
schemaLocation: node.oneOf[i].schemaLocation,
|
|
129
139
|
pointer: `${pointer}/oneOf/${i}`,
|
|
130
140
|
schema: node.schema,
|
|
131
141
|
value: data
|
|
132
142
|
});
|
|
133
143
|
}
|
|
134
144
|
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
// collect errors in case we fail finding a matching schema
|
|
146
|
+
const result = sanitizeErrors(
|
|
147
|
+
validateNode(resultNode, oneOfPropertyValue, `${pointer}/${oneOfProperty}`, path)
|
|
148
|
+
);
|
|
149
|
+
|
|
137
150
|
if (result.length > 0) {
|
|
138
151
|
errors.push(...result);
|
|
139
152
|
} else {
|
|
153
|
+
// return at once when we found a schema
|
|
154
|
+
// TODO should check all oneOf-schema
|
|
140
155
|
const { node: reducedNode } = node.oneOf[i].reduceNode(data, { pointer, path });
|
|
141
156
|
if (reducedNode) {
|
|
142
157
|
reducedNode.oneOfIndex = i; // @evaluation-info
|
|
@@ -147,7 +162,7 @@ export function reduceOneOfDeclarator({ node, data, pointer, path }: Omit<JsonSc
|
|
|
147
162
|
|
|
148
163
|
return node.createError("one-of-property-error", {
|
|
149
164
|
property: oneOfProperty,
|
|
150
|
-
value:
|
|
165
|
+
value: data,
|
|
151
166
|
pointer,
|
|
152
167
|
schema: node.schema,
|
|
153
168
|
errors
|
|
@@ -236,11 +251,71 @@ export function reduceOneOfFuzzy({ node, data, pointer, path }: Omit<JsonSchemaR
|
|
|
236
251
|
return oneOfResult;
|
|
237
252
|
}
|
|
238
253
|
|
|
254
|
+
function validateFromDeclarator({ node, data, pointer = "#", path }: JsonSchemaValidatorParams) {
|
|
255
|
+
const { oneOf, schema } = node;
|
|
256
|
+
if (!oneOf) {
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// with a declarator we only validate by a declarator to retrieve matches.
|
|
261
|
+
// - if a single match was found, we return validation errors if any
|
|
262
|
+
// - if no match was found we return a one-of-error
|
|
263
|
+
// - if multiples matches were found we return a multiple-one-of-error
|
|
264
|
+
const oneOfProperty = schema[DECLARATOR_ONEOF];
|
|
265
|
+
const oneOfValue = getValue(data, oneOfProperty);
|
|
266
|
+
const matches: { index: number; node: SchemaNode }[] = [];
|
|
267
|
+
const errors: ValidationReturnType = [];
|
|
268
|
+
for (const oneOfNode of oneOf) {
|
|
269
|
+
const { node: oneOfPropertyNode, error } = oneOfNode.getNodeChild(oneOfProperty, oneOfValue);
|
|
270
|
+
if (oneOfPropertyNode) {
|
|
271
|
+
const validationResult = validateNode(oneOfPropertyNode, oneOfValue, `${pointer}/${oneOfProperty}`, path);
|
|
272
|
+
if (validationResult.length > 0) {
|
|
273
|
+
errors.push(...validationResult);
|
|
274
|
+
} else {
|
|
275
|
+
matches.push({ index: oneOf.indexOf(oneOfNode), node: oneOfNode });
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
console.log(
|
|
279
|
+
`jlib oneOf error: failed getting schema for '${oneOfProperty}' to resolve ${DECLARATOR_ONEOF} in ${pointer}/oneOf/${oneOf.indexOf(oneOfNode)}`,
|
|
280
|
+
error
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (matches.length === 1) {
|
|
286
|
+
const match = matches[0];
|
|
287
|
+
match.node.oneOfIndex = match.index; // @evaluation-info
|
|
288
|
+
return validateNode(match.node, data, pointer, path);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (matches.length > 1) {
|
|
292
|
+
return node.createError("multiple-one-of-error", {
|
|
293
|
+
value: data,
|
|
294
|
+
pointer,
|
|
295
|
+
schema,
|
|
296
|
+
matches
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return node.createError("one-of-error", {
|
|
301
|
+
value: JSON.stringify(data),
|
|
302
|
+
pointer,
|
|
303
|
+
schema,
|
|
304
|
+
oneOf: schema.oneOf,
|
|
305
|
+
errors
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
239
309
|
function oneOfValidator({ node, data, pointer = "#", path }: JsonSchemaValidatorParams) {
|
|
240
310
|
const { oneOf, schema } = node;
|
|
241
311
|
if (!oneOf) {
|
|
242
312
|
return;
|
|
243
313
|
}
|
|
314
|
+
|
|
315
|
+
if (schema[DECLARATOR_ONEOF]) {
|
|
316
|
+
return validateFromDeclarator({ node, data, pointer, path });
|
|
317
|
+
}
|
|
318
|
+
|
|
244
319
|
const matches: { index: number; node: SchemaNode }[] = [];
|
|
245
320
|
const errors: ValidationReturnType = [];
|
|
246
321
|
for (let i = 0; i < oneOf.length; i += 1) {
|
|
@@ -32,19 +32,10 @@ export function parseItems(node: SchemaNode) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function validatePrefixItems({ node, data, pointer = "#", path }: JsonSchemaValidatorParams) {
|
|
35
|
-
// const { schema } = node;
|
|
36
35
|
if (!Array.isArray(data) || data.length === 0) {
|
|
37
36
|
return;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
// @draft >= 7 bool schema
|
|
41
|
-
// if (schema.items === false) {
|
|
42
|
-
// if (Array.isArray(data) && data.length === 0) {
|
|
43
|
-
// return undefined;
|
|
44
|
-
// }
|
|
45
|
-
// return node.createError("InvalidDataError", { pointer, value: data, schema });
|
|
46
|
-
// }
|
|
47
|
-
|
|
48
39
|
const errors: ValidationReturnType = [];
|
|
49
40
|
if (node.prefixItems) {
|
|
50
41
|
// note: schema is valid when data does not have enough elements as defined by array-list
|
|
@@ -34,6 +34,24 @@ describe("getChildSelection", () => {
|
|
|
34
34
|
);
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
+
it("should return resolved $ref", () => {
|
|
38
|
+
const result = compileSchema({
|
|
39
|
+
type: "array",
|
|
40
|
+
prefixItems: [{ $ref: "#/$defs/first" }, { $ref: "#/$defs/second" }],
|
|
41
|
+
$defs: {
|
|
42
|
+
first: { type: "string" },
|
|
43
|
+
second: { type: "number" }
|
|
44
|
+
}
|
|
45
|
+
}).getChildSelection(1);
|
|
46
|
+
|
|
47
|
+
assert(!isJsonError(result));
|
|
48
|
+
assert.deepEqual(result.length, 1);
|
|
49
|
+
assert.deepEqual(
|
|
50
|
+
result.map((n) => n.schema),
|
|
51
|
+
[{ type: "number" }]
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
37
55
|
it("should return an empty array if items schema is undefined", () => {
|
|
38
56
|
const result = compileSchema({
|
|
39
57
|
type: "array",
|
|
@@ -5,7 +5,7 @@ import { isSchemaNode, JsonError, SchemaNode } from "../types";
|
|
|
5
5
|
* could be added at the given property (e.g. item-index), thus an array of options is returned. In all other cases
|
|
6
6
|
* a list with a single item will be returned
|
|
7
7
|
*/
|
|
8
|
-
export function getChildSelection(node: SchemaNode, property: string | number)
|
|
8
|
+
export function getChildSelection(node: SchemaNode, property: string | number) {
|
|
9
9
|
if (node.oneOf) {
|
|
10
10
|
return node.oneOf.map((childNode: SchemaNode) => childNode.resolveRef());
|
|
11
11
|
}
|