UNPKG

@talend/react-forms

Version:

React forms library based on json schema form.

266 lines (254 loc) 9.37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.adaptAdditionalRules = adaptAdditionalRules; exports.filterArrayErrorsKeys = filterArrayErrorsKeys; exports.isValid = isValid; exports.shiftArrayErrorsKeys = shiftArrayErrorsKeys; exports.validateAll = validateAll; exports.validateArray = validateArray; exports.validateSimple = validateSimple; exports.validateSingle = validateSingle; exports.validateValue = validateValue; var _jsonSchemaFormCore = require("@talend/json-schema-form-core"); var _properties = require("./properties"); var _condition = _interopRequireDefault(require("./condition")); var _array = require("./array"); var _lodash = require("lodash"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } /* eslint-disable @typescript-eslint/no-use-before-define */ /** * Adapt merged schema from jsfc with additional rules * @param mergedSchema The jsfc merged schema * @returns The adapted merged schema */ function adaptAdditionalRules(mergedSchema) { // skip enum validation if explicitly not restricted const { schema } = mergedSchema; if (mergedSchema.restricted === false) { if (schema.type === 'array' && schema.items && schema.items.enum) { return { ...mergedSchema, schema: { ...schema, items: { ...schema.items, enum: undefined } } }; } else if (schema.enum) { return { ...mergedSchema, schema: { ...schema, enum: undefined } }; } } return mergedSchema; } /** * Validate a value. * @param schema The merged schema * @param value The value * @param properties The values * @param customValidationFn A custom validation function * that is applied on schema.customValidation = true * @returns {object} The validation result. */ function validateValue(schema, value, properties, customValidationFn, event) { const validationSchema = adaptAdditionalRules(schema); const staticResult = (0, _jsonSchemaFormCore.validate)(validationSchema, value, event); if (staticResult.valid && schema.customValidation && customValidationFn) { return customValidationFn(schema, value, properties); } return staticResult.valid ? null : staticResult.error.message; } /** * Validate an array. * @param mergedSchema The array schema * @param value The value * @param properties All the values * @param customValidationFn A custom validation function * that is applied on schema.customValidation = true * @param deepValidation Validate the array values if set to true * @returns {object} The validation result. */ function validateArray(mergedSchema, value, properties, customValidationFn, deepValidation) { const results = {}; const { key } = mergedSchema; // validate array definition, not its sub-items here const schemaWithoutItems = { ...mergedSchema, schema: { ...mergedSchema.schema, items: [] } }; results[key] = validateValue(schemaWithoutItems, value, properties, customValidationFn); // validate each value of the array if (deepValidation && value) { for (let valueIndex = 0; valueIndex < value.length; valueIndex += 1) { // adapt items schema with value index const indexedItems = (0, _array.getArrayElementItems)(mergedSchema, valueIndex); // eslint-disable-next-line no-use-before-define const subResults = validateAll(indexedItems, properties, customValidationFn); _extends(results, subResults); } } return results; } /** * Validate a simple value. * @param mergedSchema The schema to validate * @param value The value * @param properties All the values * @param customValidationFn A custom validation function * that is applied on schema.customValidation = true * @param deepValidation Validate subItems if true * @returns {object} The validation result. */ function validateSimple(mergedSchema, value, properties, customValidationFn, deepValidation, event) { const results = {}; const { key, items } = mergedSchema; // do not break in case we do not have the key // we need to keep deepValidation if (key) { results[key] = validateValue(mergedSchema, value, properties, customValidationFn, event); } if (deepValidation && items) { // eslint-disable-next-line no-use-before-define const subResults = validateAll(items, properties, customValidationFn); _extends(results, subResults); } return results; } /** * Execute the right validation depending on the schema type. * @param mergedSchema The merged schema * @param value The value * @param properties All the values * @param customValidationFn A custom validation function * that is applied on schema.customValidation = true * @param deepValidation Validate subItems if true * @returns {Object} The validation result by field. */ function validateSingle(mergedSchema, value, properties, customValidationFn, deepValidation, event) { if (mergedSchema.type === 'array') { return validateArray(mergedSchema, value, properties, customValidationFn, deepValidation); } return validateSimple(mergedSchema, value, properties, customValidationFn, deepValidation, event); } /** * Validate all values in the schema. * @param mergedSchema The merged schema array * @param properties The values * @param customValidationFn A custom validation function * that is applied on schema.customValidation = true * @returns {object} The validation result by field. */ function validateAll(mergedSchema, properties, customValidationFn) { const results = {}; mergedSchema.filter(schema => (0, _condition.default)(schema.condition, properties, schema.key)).forEach(schema => { const value = (0, _properties.getValue)(properties, schema); // deep validation const subResults = validateSingle(schema, value, properties, customValidationFn, true); _extends(results, subResults); }); return results; } /** * Check if a schema value is valid. * It is invalid if : * - the schema is an invalid field (errors[key] is falsy) * - the schema has items (ex: fieldset, tabs, ...), and at least one of them is invalid * @param schema The schema * @param errors The errors * @returns {boolean} true if it is invalid, false otherwise. */ function isValid(schema, errors) { const { key, items } = schema; if (key && errors[key]) { return false; } if (items) { return items.every(itemSchema => isValid(itemSchema, errors)); } return true; } /** * Filter the errors on array which items indexes are between a range * This returns only the errors keys. * @param errors The errors map * @param arrayKey The array key * @param minIndex The min item index (INCLUDED) * @param maxIndex The max item index (EXCLUDED) */ function filterArrayErrorsKeys(errors, arrayKey, minIndex, maxIndex) { const minArrayIndexKey = Number.isInteger(minIndex) && arrayKey.concat(minIndex).toString(); const maxArrayIndexKey = Number.isInteger(maxIndex) && arrayKey.concat(maxIndex).toString(); return Object.keys(errors).filter(errorKey => errorKey.startsWith(arrayKey) && ( // is on target array !minArrayIndexKey || errorKey >= minArrayIndexKey) && ( // is after min !maxArrayIndexKey || errorKey < maxArrayIndexKey) // is before max ); } /** * Given an error map: * Remove errors on array items if shouldRemoveIndex(index) is true * Shift the index of array items, where new index is getNextIndex(index) * @param oldErrors The errorMap * @param arrayKey The array key * @param minIndex The first index to manipulate * @param maxIndex The last (EXCLUDED) index to manipulate * @param shouldRemoveIndex Predicate to determine if this item errors should be removed * @param getNextIndex New index provider */ function shiftArrayErrorsKeys(oldErrors, { arrayKey, minIndex, maxIndex, shouldRemoveIndex, getNextIndex }) { // extract the errors included between the range const arrayErrorsToShiftOrRemove = filterArrayErrorsKeys(oldErrors, arrayKey, minIndex, maxIndex); // get all errors except those to remove or shift const errors = (0, _lodash.omit)(oldErrors, arrayErrorsToShiftOrRemove); const indexPositionInKey = arrayKey.length; arrayErrorsToShiftOrRemove.map(errorKey => errorKey.split(',')) // filter the index we want to remove (shouldRemoveIndex) .filter(errorKey => { if (!shouldRemoveIndex) { return true; } const itemIndex = Number(errorKey[indexPositionInKey]); return !shouldRemoveIndex(itemIndex); }) // shift the item index (getNextIndex) .map(oldErrorKey => { const oldIndex = Number(oldErrorKey[indexPositionInKey]); const newErrorKey = oldErrorKey.slice(0); newErrorKey[indexPositionInKey] = getNextIndex(oldIndex); return [oldErrorKey, newErrorKey]; }) // populate the final error map .forEach(([oldErrorKey, newErrorKey]) => { errors[newErrorKey] = oldErrors[oldErrorKey]; }); return errors; } //# sourceMappingURL=validation.js.map