UNPKG

@rjsf/utils

Version:
85 lines 4.25 kB
import get from 'lodash-es/get.js'; import has from 'lodash-es/has.js'; import isNumber from 'lodash-es/isNumber.js'; import { PROPERTIES_KEY } from '../constants.js'; import getOptionMatchingSimpleDiscriminator from '../getOptionMatchingSimpleDiscriminator.js'; /** Given the `formData` and list of `options`, attempts to find the index of the option that best matches the data. * Deprecated, use `getFirstMatchingOption()` instead. * * @param validator - An implementation of the `ValidatorType` interface that will be used when necessary * @param formData - The current formData, if any, used to figure out a match * @param options - The list of options to find a matching options from * @param rootSchema - The root schema, used to primarily to look up `$ref`s * @param [discriminatorField] - The optional name of the field within the options object whose value is used to * determine which option is selected * @returns - The index of the matched option or 0 if none is available * @deprecated */ export default function getMatchingOption(validator, formData, options, rootSchema, discriminatorField) { // For performance, skip validating subschemas if formData is undefined. We just // want to get the first option in that case. if (formData === undefined) { return 0; } const simpleDiscriminatorMatch = getOptionMatchingSimpleDiscriminator(formData, options, discriminatorField); if (isNumber(simpleDiscriminatorMatch)) { return simpleDiscriminatorMatch; } for (let i = 0; i < options.length; i++) { const option = options[i]; // If we have a discriminator field, then we will use this to make the determination if (discriminatorField && has(option, [PROPERTIES_KEY, discriminatorField])) { const value = get(formData, discriminatorField); const discriminator = get(option, [PROPERTIES_KEY, discriminatorField], {}); if (validator.isValid(discriminator, value, rootSchema)) { return i; } } else if (option[PROPERTIES_KEY]) { // If the schema describes an object then we need to add slightly more // strict matching to the schema, because unless the schema uses the // "requires" keyword, an object will match the schema as long as it // doesn't have matching keys with a conflicting type. To do this we use an // "anyOf" with an array of requires. This augmentation expresses that the // schema should match if any of the keys in the schema are present on the // object and pass validation. // // Create an "anyOf" schema that requires at least one of the keys in the // "properties" object const requiresAnyOf = { anyOf: Object.keys(option[PROPERTIES_KEY]).map((key) => ({ required: [key], })), }; let augmentedSchema; // If the "anyOf" keyword already exists, wrap the augmentation in an "allOf" if (option.anyOf) { // Create a shallow clone of the option const { ...shallowClone } = option; if (!shallowClone.allOf) { shallowClone.allOf = []; } else { // If "allOf" already exists, shallow clone the array shallowClone.allOf = shallowClone.allOf.slice(); } shallowClone.allOf.push(requiresAnyOf); augmentedSchema = shallowClone; } else { augmentedSchema = Object.assign({}, option, requiresAnyOf); } // Remove the "required" field as it's likely that not all fields have // been filled in yet, which will mean that the schema is not valid delete augmentedSchema.required; if (validator.isValid(augmentedSchema, formData, rootSchema)) { return i; } } else if (validator.isValid(option, formData, rootSchema)) { return i; } } return 0; } //# sourceMappingURL=getMatchingOption.js.map