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.
@@ -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 oneOfValue = getValue(data, oneOfProperty);
113
+ const oneOfPropertyValue = getValue(data, oneOfProperty);
112
114
 
113
- if (oneOfValue === undefined) {
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
- property: oneOfProperty,
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
- schemaPointer: node.oneOf[i].schemaLocation,
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
- const result = sanitizeErrors(validateNode(resultNode, oneOfValue, pointer, path));
136
- // result = result.filter(errorOrPromise);
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: oneOfValue,
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): SchemaNode[] | JsonError {
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
  }