@dwp/govuk-casa
Version:
Framework for creating basic GOVUK Collect-And-Submit-Applications
85 lines (78 loc) • 2.83 kB
JavaScript
const { queueValidator } = require('./processor/queue.js');
/**
* This is the core function that carries out validation on a page's data.
*
* For objects/array fields, use square-braces syntax.
*
* Parameters:
* string waypointId = The waypoint being validated
* object pageMeta = The meta object representing the page being processed
* JourneyContext journeyContext = The full JourneyContext
* bool reduceErrors = Reduces each field to a single error (default false)
*
* @param {object} params Parameters object as above
* @param {string} params.waypointId Waypoint ID
* @param {object} params.pageMeta Page meta
* @param {Function} params.journeyContext Journey context
* @param {boolean} params.reduceErrors True is errors should be reduced to a single error
* @returns {Promise} Promise
*/
// module.exports = (fieldValidators = {}, userData = {}, options = {}) => {
module.exports = ({
waypointId, pageMeta = { fieldValidators: {} }, journeyContext = {}, reduceErrors = false,
} = {}) => {
// Build up a queue of Promises that will be executed on each field
const validatorQueue = [];
Object.keys(pageMeta.fieldValidators).forEach((field) => {
queueValidator(
validatorQueue, waypointId, pageMeta, journeyContext, field, pageMeta.fieldValidators[field],
);
});
/**
* Reduce the errors to include only the first error per field. Some fields
* have multiple validation rules that may each be violated and thus result
* in their own error messages, which can quickly stack up on larger pages.
*
* @param {object} errors All errors.
* @returns {object} Reduced error list, indexed by field name.
*/
function reduceGroupedErrors(errors) {
const reduced = Object.create(null);
Object.keys(errors).forEach((field) => {
reduced[field] = [errors[field][0]];
});
return reduced;
}
/**
* Gather the array of errors generated by the validation process, into a flat
* object indexed by the field names. This makes it easier to reference errors
* in the front-end template.
*
* @param {Array} errorsList Array of errors.
* @returns {Promise} Promise.
*/
function gatherErrors(errorsList) {
let grouped = Object.create(null);
errorsList.forEach((errors) => {
if (Array.isArray(errors)) {
errors.forEach((e) => {
if (!grouped[e.field]) {
grouped[e.field] = [];
}
grouped[e.field].push(e);
});
}
});
if (reduceErrors) {
grouped = reduceGroupedErrors(grouped);
}
return Object.keys(grouped).length
? Promise.reject(grouped)
: Promise.resolve();
}
// Resulting Promise
if (validatorQueue.length) {
return Promise.all(validatorQueue).then(gatherErrors);
}
return Promise.resolve();
}