@rjsf/utils 5.18.0 → 5.18.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.
@@ -18,33 +18,47 @@ export function splitKeyElementFromObject(key: string, object: GenericObjectType
18
18
  return [remaining, value];
19
19
  }
20
20
 
21
- /** Given the name of a `$ref` from within a schema, using the `rootSchema`, look up and return the sub-schema using the
22
- * path provided by that reference. If `#` is not the first character of the reference, or the path does not exist in
23
- * the schema, then throw an Error. Otherwise return the sub-schema. Also deals with nested `$ref`s in the sub-schema.
21
+ /** Given the name of a `$ref` from within a schema, using the `rootSchema`, recursively look up and return the
22
+ * sub-schema using the path provided by that reference. If `#` is not the first character of the reference, the path
23
+ * does not exist in the schema, or the reference resolves circularly back to itself, then throw an Error.
24
+ * Otherwise return the sub-schema. Also deals with nested `$ref`s in the sub-schema.
24
25
  *
25
26
  * @param $ref - The ref string for which the schema definition is desired
26
27
  * @param [rootSchema={}] - The root schema in which to search for the definition
28
+ * @param recurseList - List of $refs already resolved to prevent recursion
27
29
  * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
28
- * @throws - Error indicating that no schema for that reference exists
30
+ * @throws - Error indicating that no schema for that reference could be resolved
29
31
  */
30
- export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(
32
+ export function findSchemaDefinitionRecursive<S extends StrictRJSFSchema = RJSFSchema>(
31
33
  $ref?: string,
32
- rootSchema: S = {} as S
34
+ rootSchema: S = {} as S,
35
+ recurseList: string[] = []
33
36
  ): S {
34
- let ref = $ref || '';
37
+ const ref = $ref || '';
38
+ let decodedRef;
35
39
  if (ref.startsWith('#')) {
36
40
  // Decode URI fragment representation.
37
- ref = decodeURIComponent(ref.substring(1));
41
+ decodedRef = decodeURIComponent(ref.substring(1));
38
42
  } else {
39
43
  throw new Error(`Could not find a definition for ${$ref}.`);
40
44
  }
41
- const current: S = jsonpointer.get(rootSchema, ref);
45
+ const current: S = jsonpointer.get(rootSchema, decodedRef);
42
46
  if (current === undefined) {
43
47
  throw new Error(`Could not find a definition for ${$ref}.`);
44
48
  }
45
- if (current[REF_KEY]) {
49
+ const nextRef = current[REF_KEY];
50
+ if (nextRef) {
51
+ // Check for circular references.
52
+ if (recurseList.includes(nextRef)) {
53
+ if (recurseList.length === 1) {
54
+ throw new Error(`Definition for ${$ref} is a circular reference`);
55
+ }
56
+ const [firstRef, ...restRefs] = recurseList;
57
+ const circularPath = [...restRefs, ref, firstRef].join(' -> ');
58
+ throw new Error(`Definition for ${firstRef} contains a circular reference through ${circularPath}`);
59
+ }
46
60
  const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current);
47
- const subSchema = findSchemaDefinition<S>(theRef, rootSchema);
61
+ const subSchema = findSchemaDefinitionRecursive<S>(theRef, rootSchema, [...recurseList, ref]);
48
62
  if (Object.keys(remaining).length > 0) {
49
63
  return { ...remaining, ...subSchema };
50
64
  }
@@ -52,3 +66,21 @@ export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSc
52
66
  }
53
67
  return current;
54
68
  }
69
+
70
+ /** Given the name of a `$ref` from within a schema, using the `rootSchema`, look up and return the sub-schema using the
71
+ * path provided by that reference. If `#` is not the first character of the reference, the path does not exist in
72
+ * the schema, or the reference resolves circularly back to itself, then throw an Error. Otherwise return the
73
+ * sub-schema. Also deals with nested `$ref`s in the sub-schema.
74
+ *
75
+ * @param $ref - The ref string for which the schema definition is desired
76
+ * @param [rootSchema={}] - The root schema in which to search for the definition
77
+ * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists
78
+ * @throws - Error indicating that no schema for that reference could be resolved
79
+ */
80
+ export default function findSchemaDefinition<S extends StrictRJSFSchema = RJSFSchema>(
81
+ $ref?: string,
82
+ rootSchema: S = {} as S
83
+ ): S {
84
+ const recurseList: string[] = [];
85
+ return findSchemaDefinitionRecursive($ref, rootSchema, recurseList);
86
+ }