react-formal
Version:
Classy HTML form management for React
55 lines • 2 kB
JavaScript
import { EMPTY_ERRORS } from './Errors';
import errToJSON from './utils/errToJSON';
import { trim, inPath } from './utils/paths';
import uniqBy from 'lodash/uniqBy';
function trimChildren(rootPath, errors) {
let result = {};
Object.keys(errors).forEach(path => {
if (rootPath !== path && inPath(rootPath, path)) return;
result[path] = errors[path];
});
return result;
}
function reduce(paths) {
paths = uniqBy(paths, p => p.path);
if (paths.length <= 1) return paths;
return paths.reduce((innerPaths, current) => {
innerPaths = innerPaths.filter(p => !inPath(current.path, p.path));
if (!innerPaths.some(p => inPath(p.path, current.path))) innerPaths.push(current);
return innerPaths;
}, []);
}
export let isValidationError = err => err && err.name === 'ValidationError';
export default function errorManager(handleValidation) {
return {
async collect(paths, pristineErrors = EMPTY_ERRORS, options) {
const specs = reduce(paths.map(p => typeof p === 'string' ? {
path: p,
shallow: false
} : p));
let errors = Object.assign({}, pristineErrors);
let nextErrors = errors;
let workDone = false;
specs.forEach(({
path,
shallow
}) => {
nextErrors = trim(path, nextErrors, shallow);
if (errors !== nextErrors) workDone = true;
});
let validations = specs.map(spec => Promise.resolve(handleValidation(spec, options)).then(validationError => {
if (!validationError) return true;
if (!isValidationError(validationError)) throw validationError;
if (!spec.shallow) {
errToJSON(validationError, nextErrors);
return;
}
const fieldErrors = errToJSON(validationError);
Object.assign(nextErrors, trimChildren(spec.path, fieldErrors));
}));
const results = await Promise.all(validations);
if (!workDone && results.every(Boolean)) return pristineErrors;
return nextErrors;
}
};
}