fielder
Version:
A field-first form library for React and React Native
68 lines (58 loc) • 1.58 kB
text/typescript
import { FieldsState } from '../types';
/** Joins all validation errors (sync/async) into a single validation function */
export const batchValidationErrors = ({
state,
promises,
}: {
state: FieldsState;
promises?: Record<string, Promise<any>>;
}) => {
const syncErrors = getErrorsFromState(state);
if (!promises || Object.keys(promises).length === 0) {
return syncErrors;
}
return getErrorsFromPromises(promises).then((errs) =>
cleanupKeys({
...syncErrors,
...errs, // Intentionally set some errors to undefined
})
);
};
const getErrorsFromState = (state: FieldsState) =>
Object.entries(state).reduce((errors, [name, field]) => {
if (field._isActive && field.error) {
return {
...errors,
[name]: field.error,
};
}
return errors;
}, {});
const getErrorsFromPromises = async (
promises: Record<string, Promise<any>>
) => {
const results = await Promise.all(
Object.entries(promises).map<
Promise<{ key: string; error: string | undefined }>
>(([key, promise]) =>
promise
.then(() => ({ key, error: undefined }))
.catch((err) => ({ key, error: err.message }))
)
);
return results.reduce(
(errors, result) => ({
...errors,
[result.key]: result.error,
}),
{}
);
};
/** Remove keys from object where value is undefined */
const cleanupKeys = (arg: object) =>
Object.entries(arg).reduce((acc, [key, value]) => {
if (value === undefined) {
return acc;
}
return { ...acc, [key]: value };
}, {});