UNPKG

@rjsf/utils

Version:
76 lines 3.99 kB
import jsonpointer from 'jsonpointer'; import omit from 'lodash-es/omit.js'; import { REF_KEY } from './constants.js'; /** Splits out the value at the `key` in `object` from the `object`, returning an array that contains in the first * location, the `object` minus the `key: value` and in the second location the `value`. * * @param key - The key from the object to extract * @param object - The object from which to extract the element * @returns - An array with the first value being the object minus the `key` element and the second element being the * value from `object[key]` */ export function splitKeyElementFromObject(key, object) { const value = object[key]; const remaining = omit(object, [key]); return [remaining, value]; } /** Given the name of a `$ref` from within a schema, using the `rootSchema`, recursively look up and return the * sub-schema using the path provided by that reference. If `#` is not the first character of the reference, the path * does not exist in the schema, or the reference resolves circularly back to itself, then throw an Error. * Otherwise return the sub-schema. Also deals with nested `$ref`s in the sub-schema. * * @param $ref - The ref string for which the schema definition is desired * @param [rootSchema={}] - The root schema in which to search for the definition * @param recurseList - List of $refs already resolved to prevent recursion * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists * @throws - Error indicating that no schema for that reference could be resolved */ export function findSchemaDefinitionRecursive($ref, rootSchema = {}, recurseList = []) { const ref = $ref || ''; let decodedRef; if (ref.startsWith('#')) { // Decode URI fragment representation. decodedRef = decodeURIComponent(ref.substring(1)); } else { throw new Error(`Could not find a definition for ${$ref}.`); } const current = jsonpointer.get(rootSchema, decodedRef); if (current === undefined) { throw new Error(`Could not find a definition for ${$ref}.`); } const nextRef = current[REF_KEY]; if (nextRef) { // Check for circular references. if (recurseList.includes(nextRef)) { if (recurseList.length === 1) { throw new Error(`Definition for ${$ref} is a circular reference`); } const [firstRef, ...restRefs] = recurseList; const circularPath = [...restRefs, ref, firstRef].join(' -> '); throw new Error(`Definition for ${firstRef} contains a circular reference through ${circularPath}`); } const [remaining, theRef] = splitKeyElementFromObject(REF_KEY, current); const subSchema = findSchemaDefinitionRecursive(theRef, rootSchema, [...recurseList, ref]); if (Object.keys(remaining).length > 0) { return { ...remaining, ...subSchema }; } return subSchema; } return current; } /** Given the name of a `$ref` from within a schema, using the `rootSchema`, look up and return the sub-schema using the * path provided by that reference. If `#` is not the first character of the reference, the path does not exist in * the schema, or the reference resolves circularly back to itself, then throw an Error. Otherwise return the * sub-schema. Also deals with nested `$ref`s in the sub-schema. * * @param $ref - The ref string for which the schema definition is desired * @param [rootSchema={}] - The root schema in which to search for the definition * @returns - The sub-schema within the `rootSchema` which matches the `$ref` if it exists * @throws - Error indicating that no schema for that reference could be resolved */ export default function findSchemaDefinition($ref, rootSchema = {}) { const recurseList = []; return findSchemaDefinitionRecursive($ref, rootSchema, recurseList); } //# sourceMappingURL=findSchemaDefinition.js.map