@dwp/govuk-casa 7.0.6 → 8.0.0-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +22 -17
- package/dist/{casa → assets}/css/casa-ie8.css +1 -1
- package/dist/assets/css/casa.css +1 -0
- package/dist/casa.d.ts +11 -0
- package/dist/casa.js +46 -0
- package/dist/lib/CasaTemplateLoader.d.ts +29 -0
- package/dist/lib/CasaTemplateLoader.js +74 -0
- package/dist/lib/JourneyContext.d.ts +297 -0
- package/dist/lib/JourneyContext.js +581 -0
- package/dist/lib/MutableRouter.d.ts +155 -0
- package/dist/lib/MutableRouter.js +277 -0
- package/dist/lib/Plan.d.ts +154 -0
- package/dist/lib/Plan.js +442 -0
- package/dist/lib/ValidationError.d.ts +74 -0
- package/dist/lib/ValidationError.js +159 -0
- package/dist/lib/ValidatorFactory.d.ts +83 -0
- package/dist/lib/ValidatorFactory.js +106 -0
- package/dist/lib/configuration-ingestor.d.ts +262 -0
- package/dist/lib/configuration-ingestor.js +490 -0
- package/dist/lib/configure.d.ts +90 -0
- package/dist/lib/configure.js +192 -0
- package/dist/lib/dirname.cjs +1 -0
- package/dist/lib/dirname.d.cts +2 -0
- package/dist/lib/end-session.d.ts +13 -0
- package/dist/lib/end-session.js +43 -0
- package/dist/lib/field.d.ts +77 -0
- package/dist/lib/field.js +255 -0
- package/dist/lib/index.d.ts +14 -0
- package/dist/lib/index.js +54 -0
- package/dist/lib/logger.d.ts +9 -0
- package/dist/lib/logger.js +18 -0
- package/dist/lib/nunjucks-filters.d.ts +26 -0
- package/dist/lib/nunjucks-filters.js +90 -0
- package/dist/lib/nunjucks.d.ts +23 -0
- package/dist/lib/nunjucks.js +49 -0
- package/dist/lib/utils.d.ts +48 -0
- package/dist/lib/utils.js +111 -0
- package/dist/lib/validators/dateObject.d.ts +4 -0
- package/dist/lib/validators/dateObject.js +135 -0
- package/dist/lib/validators/email.d.ts +4 -0
- package/dist/lib/validators/email.js +46 -0
- package/dist/lib/validators/inArray.d.ts +4 -0
- package/dist/lib/validators/inArray.js +60 -0
- package/dist/lib/validators/index.d.ts +21 -0
- package/dist/lib/validators/index.js +47 -0
- package/dist/lib/validators/nino.d.ts +4 -0
- package/dist/lib/validators/nino.js +46 -0
- package/dist/lib/validators/postalAddressObject.d.ts +4 -0
- package/dist/lib/validators/postalAddressObject.js +123 -0
- package/dist/lib/validators/regex.d.ts +4 -0
- package/dist/lib/validators/regex.js +40 -0
- package/dist/lib/validators/required.d.ts +4 -0
- package/dist/lib/validators/required.js +56 -0
- package/dist/lib/validators/strlen.d.ts +4 -0
- package/dist/lib/validators/strlen.js +51 -0
- package/dist/lib/validators/wordCount.d.ts +5 -0
- package/dist/lib/validators/wordCount.js +54 -0
- package/dist/lib/waypoint-url.d.ts +23 -0
- package/dist/lib/waypoint-url.js +52 -0
- package/dist/middleware/body-parser.d.ts +1 -0
- package/dist/middleware/body-parser.js +24 -0
- package/dist/middleware/csrf.d.ts +1 -0
- package/dist/middleware/csrf.js +31 -0
- package/dist/middleware/data.d.ts +5 -0
- package/dist/middleware/data.js +53 -0
- package/dist/middleware/dirname.cjs +1 -0
- package/dist/middleware/dirname.d.cts +2 -0
- package/dist/middleware/gather-fields.d.ts +6 -0
- package/dist/middleware/gather-fields.js +48 -0
- package/dist/middleware/i18n.d.ts +4 -0
- package/dist/middleware/i18n.js +88 -0
- package/dist/middleware/post.d.ts +3 -0
- package/dist/middleware/post.js +57 -0
- package/dist/middleware/pre.d.ts +3 -0
- package/dist/middleware/pre.js +51 -0
- package/dist/middleware/progress-journey.d.ts +6 -0
- package/dist/middleware/progress-journey.js +80 -0
- package/dist/middleware/sanitise-fields.d.ts +5 -0
- package/dist/middleware/sanitise-fields.js +53 -0
- package/dist/middleware/session.d.ts +11 -0
- package/dist/middleware/session.js +121 -0
- package/dist/middleware/skip-waypoint.d.ts +5 -0
- package/dist/middleware/skip-waypoint.js +43 -0
- package/dist/middleware/steer-journey.d.ts +7 -0
- package/dist/middleware/steer-journey.js +62 -0
- package/dist/middleware/validate-fields.d.ts +7 -0
- package/dist/middleware/validate-fields.js +67 -0
- package/dist/mjs/esm-wrapper.js +11 -0
- package/dist/mjs/package.json +3 -0
- package/dist/package.json +3 -0
- package/dist/routes/ancillary.d.ts +11 -0
- package/dist/routes/ancillary.js +27 -0
- package/dist/routes/dirname.cjs +1 -0
- package/dist/routes/dirname.d.cts +2 -0
- package/dist/routes/journey.d.ts +8 -0
- package/dist/routes/journey.js +127 -0
- package/dist/routes/static.d.ts +26 -0
- package/dist/routes/static.js +68 -0
- package/package.json +64 -89
- package/views/casa/components/checkboxes/template.njk +4 -1
- package/views/casa/components/date-input/template.njk +3 -3
- package/views/casa/components/journey-form/README.md +3 -1
- package/views/casa/components/journey-form/template.njk +1 -1
- package/views/casa/components/postal-address-object/template.njk +5 -5
- package/views/casa/components/radios/template.njk +1 -1
- package/views/casa/errors/static.njk +11 -0
- package/views/casa/layouts/journey.njk +26 -9
- package/views/casa/layouts/main.njk +7 -20
- package/views/casa/partials/scripts.njk +8 -3
- package/views/casa/partials/styles.njk +2 -2
- package/casa.js +0 -208
- package/definitions/review-page.js +0 -60
- package/dist/casa/css/casa.css +0 -1
- package/dist/casa/js/casa.js +0 -1
- package/index.d.ts +0 -121
- package/lib/ConfigIngestor.js +0 -588
- package/lib/GatherModifier.js +0 -14
- package/lib/I18n.js +0 -160
- package/lib/JourneyContext.d.ts +0 -97
- package/lib/JourneyContext.js +0 -552
- package/lib/JourneyMap.js +0 -233
- package/lib/JourneyRoad.js +0 -330
- package/lib/Logger.js +0 -59
- package/lib/PageDictionary.d.ts +0 -11
- package/lib/PageDirectory.js +0 -77
- package/lib/Plan.js +0 -423
- package/lib/RoadConverter.js +0 -153
- package/lib/UserJourney.js +0 -8
- package/lib/Util.js +0 -227
- package/lib/Validation.js +0 -20
- package/lib/bootstrap/end-session.js +0 -44
- package/lib/bootstrap/load-definitions.js +0 -64
- package/lib/commonBodyParser.js +0 -15
- package/lib/enums.js +0 -6
- package/lib/gather-modifiers/index.js +0 -7
- package/lib/gather-modifiers/trimPostalAddressObject.js +0 -75
- package/lib/gather-modifiers/trimWhitespace.js +0 -16
- package/lib/utils/createGetRequest.d.ts +0 -5
- package/lib/utils/createGetRequest.js +0 -59
- package/lib/utils/index.js +0 -11
- package/lib/utils/parseRequest.d.ts +0 -5
- package/lib/utils/parseRequest.js +0 -72
- package/lib/utils/sanitise.js +0 -74
- package/lib/utils/validate.js +0 -32
- package/lib/validation/ArrayObjectField.js +0 -49
- package/lib/validation/ObjectField.js +0 -53
- package/lib/validation/SimpleField.d.ts +0 -11
- package/lib/validation/SimpleField.js +0 -46
- package/lib/validation/ValidationError.d.ts +0 -14
- package/lib/validation/ValidationError.js +0 -170
- package/lib/validation/ValidatorFactory.d.ts +0 -32
- package/lib/validation/ValidatorFactory.js +0 -91
- package/lib/validation/index.js +0 -22
- package/lib/validation/processor/flattenErrorArray.js +0 -24
- package/lib/validation/processor/queue.js +0 -214
- package/lib/validation/processor.js +0 -84
- package/lib/validation/rules/README.md +0 -3
- package/lib/validation/rules/ValidationRules.d.ts +0 -22
- package/lib/validation/rules/dateObject.js +0 -156
- package/lib/validation/rules/email.js +0 -44
- package/lib/validation/rules/inArray.js +0 -61
- package/lib/validation/rules/index.js +0 -23
- package/lib/validation/rules/nino.js +0 -48
- package/lib/validation/rules/optional.js +0 -14
- package/lib/validation/rules/postalAddressObject.js +0 -142
- package/lib/validation/rules/regex.js +0 -39
- package/lib/validation/rules/required.js +0 -57
- package/lib/validation/rules/strlen.js +0 -57
- package/lib/validation/rules/wordCount.js +0 -61
- package/lib/view-filters/formatDateObject.js +0 -35
- package/lib/view-filters/includes.js +0 -10
- package/lib/view-filters/index.js +0 -23
- package/lib/view-filters/mergeObjectsDeep.js +0 -21
- package/lib/view-filters/renderAsAttributes.js +0 -33
- package/middleware/errors/404.js +0 -12
- package/middleware/errors/catch-all.js +0 -27
- package/middleware/errors/index.js +0 -9
- package/middleware/headers/config-defaults.js +0 -57
- package/middleware/headers/headers.js +0 -40
- package/middleware/headers/index.js +0 -9
- package/middleware/i18n/i18n.js +0 -56
- package/middleware/i18n/index.js +0 -16
- package/middleware/index.js +0 -55
- package/middleware/mount/index.js +0 -9
- package/middleware/mount/mount.js +0 -10
- package/middleware/nunjucks/environment.js +0 -57
- package/middleware/nunjucks/index.js +0 -8
- package/middleware/page/csrf.js +0 -37
- package/middleware/page/edit-mode.js +0 -52
- package/middleware/page/gather.js +0 -75
- package/middleware/page/index.js +0 -103
- package/middleware/page/journey-continue.js +0 -157
- package/middleware/page/journey-rails.js +0 -102
- package/middleware/page/prepare-request.js +0 -77
- package/middleware/page/render.js +0 -75
- package/middleware/page/skip.js +0 -72
- package/middleware/page/utils.js +0 -206
- package/middleware/page/validate.js +0 -67
- package/middleware/session/expiry.js +0 -95
- package/middleware/session/genid.js +0 -18
- package/middleware/session/index.js +0 -18
- package/middleware/session/init.js +0 -25
- package/middleware/session/seed.js +0 -50
- package/middleware/session/timeout.js +0 -5
- package/middleware/static/asset-versions.js +0 -23
- package/middleware/static/index.js +0 -104
- package/middleware/static/prepare-assets.js +0 -51
- package/middleware/static/serve-assets.js +0 -58
- package/middleware/variables/index.js +0 -12
- package/middleware/variables/variables.js +0 -35
- package/src/browserconfig.xml +0 -5
- package/src/js/casa.js +0 -132
- package/src/scss/_casaElements.scss +0 -11
- package/src/scss/_casaGovukTemplateJinjaPolyfill.scss +0 -39
- package/src/scss/_casaMountUrl.scss +0 -8
- package/src/scss/casa-ie8.scss +0 -3
- package/src/scss/casa.scss +0 -14
- package/test/unit/templates/README.md +0 -5
- package/test/utils/BaseTestWaypoint.js +0 -106
- package/test/utils/concatWaypoints.js +0 -26
- package/test/utils/index.js +0 -6
- package/test/utils/testTraversal.js +0 -90
- package/views/casa/partials/cookie_message.njk +0 -3
- package/views/casa/partials/phase_banner_alpha.njk +0 -8
- package/views/casa/partials/phase_banner_beta.njk +0 -8
- package/views/casa/review/page-block.njk +0 -8
- package/views/casa/review/review.njk +0 -47
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
const util = require('../../Util.js');
|
|
2
|
-
const ValidationError = require('../ValidationError.js');
|
|
3
|
-
const rules = require('../rules/index.js');
|
|
4
|
-
const flattenErrorArray = require('./flattenErrorArray.js');
|
|
5
|
-
|
|
6
|
-
const T_SIMPLE = 'simple';
|
|
7
|
-
const T_OBJECT = 'object';
|
|
8
|
-
const T_ARRAY_OBJECT = 'array_object';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Add a validator object to the processing queue.
|
|
12
|
-
*
|
|
13
|
-
* @param {Array} queue Queue to which validators will be added
|
|
14
|
-
* @param {string} waypointId Waypoint under validation
|
|
15
|
-
* @param {PageMeta} pageMeta Meta object representing the page being validated
|
|
16
|
-
* @param {object} journeyContext Full JourneyContext
|
|
17
|
-
* @param {string} field Field to validate (in square-brace notation)
|
|
18
|
-
* @param {import('../SimpleField')} validatorObj Validation attributes to apply
|
|
19
|
-
* @returns {void}
|
|
20
|
-
*/
|
|
21
|
-
/* eslint-disable-next-line consistent-return,require-jsdoc */
|
|
22
|
-
function queueValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj) {
|
|
23
|
-
// Do not queue if condition is not met
|
|
24
|
-
if (validatorObj.condition({
|
|
25
|
-
fieldName: util.normalizeHtmlObjectPath(field),
|
|
26
|
-
journeyContext,
|
|
27
|
-
waypointId,
|
|
28
|
-
})) {
|
|
29
|
-
switch (validatorObj.type) {
|
|
30
|
-
case T_SIMPLE:
|
|
31
|
-
/* eslint-disable-next-line no-use-before-define */
|
|
32
|
-
return queueSimpleValidator(
|
|
33
|
-
queue, waypointId, pageMeta, journeyContext, field, validatorObj,
|
|
34
|
-
);
|
|
35
|
-
case T_OBJECT:
|
|
36
|
-
/* eslint-disable-next-line no-use-before-define */
|
|
37
|
-
return queueObjectValidator(
|
|
38
|
-
queue, waypointId, pageMeta, journeyContext, field, validatorObj,
|
|
39
|
-
);
|
|
40
|
-
case T_ARRAY_OBJECT:
|
|
41
|
-
/* eslint-disable-next-line no-use-before-define */
|
|
42
|
-
return queueArrayObjectValidator(
|
|
43
|
-
queue, waypointId, pageMeta, journeyContext, field, validatorObj,
|
|
44
|
-
);
|
|
45
|
-
default:
|
|
46
|
-
throw new Error('Unknown or unspecified validator type');
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Add a Validation.SimpleField object to the processing queue.
|
|
53
|
-
*
|
|
54
|
-
* @param {Array} queue Queue to which validators will be added.
|
|
55
|
-
* @param {string} waypointId Waypoint under validation.
|
|
56
|
-
* @param {PageMeta} pageMeta Meta object representing the page being validated.
|
|
57
|
-
* @param {object} journeyContext Full JourneyContext.
|
|
58
|
-
* @param {string} field Field to validate (in square-brace notation).
|
|
59
|
-
* @param {object} validatorObj Validation attributes to apply.
|
|
60
|
-
* @returns {void}
|
|
61
|
-
*/
|
|
62
|
-
function queueSimpleValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj) {
|
|
63
|
-
// Ensure pageMeta.id is defined when extracting data for the waypoint
|
|
64
|
-
let pageData;
|
|
65
|
-
if (!Object.prototype.hasOwnProperty.call(pageMeta, 'id')) {
|
|
66
|
-
pageData = journeyContext.getDataForPage({
|
|
67
|
-
id: waypointId,
|
|
68
|
-
...pageMeta,
|
|
69
|
-
});
|
|
70
|
-
} else {
|
|
71
|
-
pageData = journeyContext.getDataForPage(pageMeta);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// For optional fields (i.e. one whose validation rules contains the
|
|
75
|
-
// `optional` rule), first check if the field value is present before
|
|
76
|
-
// queuing all other rules.
|
|
77
|
-
const fieldValue = util.objectPathValue(pageData, field);
|
|
78
|
-
if (
|
|
79
|
-
validatorObj.validators.some((v) => (v.validate === rules.optional))
|
|
80
|
-
&& rules.optional(fieldValue)
|
|
81
|
-
) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
validatorObj.validators.forEach((validator) => {
|
|
86
|
-
// A more useful exception with reference to field name
|
|
87
|
-
if (typeof validator.validate !== 'function') {
|
|
88
|
-
throw new Error(`Validator defined on '${field}'' is not a function`);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Skip `optional` rule as it does not return a Promise, and has already
|
|
92
|
-
// been evaluated above.
|
|
93
|
-
if (validator.validate === rules.optional) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Create context object which allows a validator to optionally looks at
|
|
98
|
-
// other data within the page being validated
|
|
99
|
-
const dataContext = {
|
|
100
|
-
fieldName: field,
|
|
101
|
-
journeyContext,
|
|
102
|
-
waypointId,
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
// Determine the name of the validator function so that we can pass it
|
|
106
|
-
// back to the template for Anayltics purposes.
|
|
107
|
-
const validatorName = (validator.name || validator.validate.name).replace(/^.*?([a-z0-9_]+)$/i, '$1');
|
|
108
|
-
|
|
109
|
-
// As well as the validator, we add an immediate `catch()` handler after
|
|
110
|
-
// it in order to collect _all_ errors thrown by all validators. Otherise
|
|
111
|
-
// `Promise.all()` would reject at the first failure and miss all other
|
|
112
|
-
// errors.
|
|
113
|
-
queue.push(validator.validate(fieldValue, dataContext).catch((validationError) => {
|
|
114
|
-
let err = validationError;
|
|
115
|
-
if (err instanceof Error) {
|
|
116
|
-
err = ValidationError.make({ errorMsg: err });
|
|
117
|
-
} else if (err === undefined) {
|
|
118
|
-
err = ValidationError.make({ errorMsg: 'Unknown error' });
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
let errors;
|
|
122
|
-
try {
|
|
123
|
-
errors = flattenErrorArray(err);
|
|
124
|
-
} catch (ex) {
|
|
125
|
-
errors = [ValidationError.make({ errorMsg: ex })];
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Apply current context to each error
|
|
129
|
-
errors.forEach((error) => error.withContext({ ...dataContext, validator: validatorName }));
|
|
130
|
-
|
|
131
|
-
return Promise.resolve(errors);
|
|
132
|
-
}));
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Add a Validation.ObjectField object to the queue.
|
|
138
|
-
*
|
|
139
|
-
* @param {Array} queue Queue to which validators will be added.
|
|
140
|
-
* @param {string} waypointId Waypoint under validation.
|
|
141
|
-
* @param {PageMeta} pageMeta Meta object representing the page being validated.
|
|
142
|
-
* @param {object} journeyContext Full JourneyContext.
|
|
143
|
-
* @param {string} field Field to validate (in square-brace notation).
|
|
144
|
-
* @param {object} validatorObj Validation attributes to apply.
|
|
145
|
-
* @returns {void}
|
|
146
|
-
*/
|
|
147
|
-
function queueObjectValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj) {
|
|
148
|
-
// Add this validator's rules to the queue (if any)
|
|
149
|
-
queueSimpleValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj);
|
|
150
|
-
|
|
151
|
-
// Queue the child validator objects
|
|
152
|
-
Object.keys(validatorObj.children).forEach((childField) => {
|
|
153
|
-
const child = validatorObj.children[childField];
|
|
154
|
-
queueValidator(
|
|
155
|
-
queue,
|
|
156
|
-
waypointId,
|
|
157
|
-
pageMeta,
|
|
158
|
-
journeyContext,
|
|
159
|
-
util.objectPathString(field, childField),
|
|
160
|
-
child,
|
|
161
|
-
);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Add a Validation.ArrayObjectField object to the queue.
|
|
167
|
-
*
|
|
168
|
-
* @param {Array} queue Queue to which validators will be added.
|
|
169
|
-
* @param {string} waypointId Waypoint under validation.
|
|
170
|
-
* @param {PageMeta} pageMeta Meta object representing the page being validated.
|
|
171
|
-
* @param {object} journeyContext Full JourneyContext.
|
|
172
|
-
* @param {string} field Field to validate (in square-brace notation).
|
|
173
|
-
* @param {object} validatorObj Validation attributes to apply.
|
|
174
|
-
* @returns {void}
|
|
175
|
-
*/
|
|
176
|
-
function queueArrayObjectValidator(
|
|
177
|
-
queue, waypointId, pageMeta, journeyContext, field, validatorObj,
|
|
178
|
-
) {
|
|
179
|
-
// Add this validator's rules to the queue (if any)
|
|
180
|
-
queueSimpleValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj);
|
|
181
|
-
|
|
182
|
-
// The object at `pageData[field]` should be an array, indexed from 0. If it
|
|
183
|
-
// is anything else, it is ignored.
|
|
184
|
-
// Some caution is needed here because a non-/empty array will not trigger
|
|
185
|
-
// any validations on the fields that _should_ be in objects in that array.
|
|
186
|
-
const pageData = journeyContext.getDataForPage(pageMeta);
|
|
187
|
-
let arrayObj = util.objectPathValue(pageData, util.objectPathString(field));
|
|
188
|
-
if (!Array.isArray(arrayObj)) {
|
|
189
|
-
arrayObj = [];
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Cycle through each element in the array and add all validators for each
|
|
193
|
-
// one.
|
|
194
|
-
arrayObj.forEach((obj, index) => {
|
|
195
|
-
Object.keys(validatorObj.children).forEach((childField) => {
|
|
196
|
-
const child = validatorObj.children[childField];
|
|
197
|
-
queueValidator(
|
|
198
|
-
queue,
|
|
199
|
-
waypointId,
|
|
200
|
-
pageMeta,
|
|
201
|
-
journeyContext,
|
|
202
|
-
util.objectPathString(`${field}[${index}]`, childField),
|
|
203
|
-
child,
|
|
204
|
-
);
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
module.exports = {
|
|
210
|
-
queueValidator,
|
|
211
|
-
queueSimpleValidator,
|
|
212
|
-
queueObjectValidator,
|
|
213
|
-
queueArrayObjectValidator,
|
|
214
|
-
};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
const { queueValidator } = require('./processor/queue.js');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This is the core function that carries out validation on a page's data.
|
|
5
|
-
*
|
|
6
|
-
* For objects/array fields, use square-braces syntax.
|
|
7
|
-
*
|
|
8
|
-
* Parameters:
|
|
9
|
-
* string waypointId = The waypoint being validated
|
|
10
|
-
* object pageMeta = The meta object representing the page being processed
|
|
11
|
-
* JourneyContext journeyContext = The full JourneyContext
|
|
12
|
-
* bool reduceErrors = Reduces each field to a single error (default false)
|
|
13
|
-
*
|
|
14
|
-
* @param {object} params Parameters object as above
|
|
15
|
-
* @param {string} params.waypointId Waypoint ID
|
|
16
|
-
* @param {object} params.pageMeta Page meta
|
|
17
|
-
* @param {Function} params.journeyContext Journey context
|
|
18
|
-
* @param {boolean} params.reduceErrors True is errors should be reduced to a single error
|
|
19
|
-
* @returns {Promise} Promise
|
|
20
|
-
*/
|
|
21
|
-
// module.exports = (fieldValidators = {}, userData = {}, options = {}) => {
|
|
22
|
-
module.exports = ({
|
|
23
|
-
waypointId, pageMeta = { fieldValidators: {} }, journeyContext = {}, reduceErrors = false,
|
|
24
|
-
} = {}) => {
|
|
25
|
-
// Build up a queue of Promises that will be executed on each field
|
|
26
|
-
const validatorQueue = [];
|
|
27
|
-
Object.keys(pageMeta.fieldValidators).forEach((field) => {
|
|
28
|
-
queueValidator(
|
|
29
|
-
validatorQueue, waypointId, pageMeta, journeyContext, field, pageMeta.fieldValidators[field],
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Reduce the errors to include only the first error per field. Some fields
|
|
35
|
-
* have multiple validation rules that may each be violated and thus result
|
|
36
|
-
* in their own error messages, which can quickly stack up on larger pages.
|
|
37
|
-
*
|
|
38
|
-
* @param {object} errors All errors.
|
|
39
|
-
* @returns {object} Reduced error list, indexed by field name.
|
|
40
|
-
*/
|
|
41
|
-
function reduceGroupedErrors(errors) {
|
|
42
|
-
const reduced = Object.create(null);
|
|
43
|
-
Object.keys(errors).forEach((field) => {
|
|
44
|
-
reduced[field] = [errors[field][0]];
|
|
45
|
-
});
|
|
46
|
-
return reduced;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Gather the array of errors generated by the validation process, into a flat
|
|
51
|
-
* object indexed by the field names. This makes it easier to reference errors
|
|
52
|
-
* in the front-end template.
|
|
53
|
-
*
|
|
54
|
-
* @param {Array} errorsList Array of errors.
|
|
55
|
-
* @returns {Promise} Promise.
|
|
56
|
-
*/
|
|
57
|
-
function gatherErrors(errorsList) {
|
|
58
|
-
let grouped = Object.create(null);
|
|
59
|
-
errorsList.forEach((errors) => {
|
|
60
|
-
if (Array.isArray(errors)) {
|
|
61
|
-
errors.forEach((e) => {
|
|
62
|
-
if (!grouped[e.field]) {
|
|
63
|
-
grouped[e.field] = [];
|
|
64
|
-
}
|
|
65
|
-
grouped[e.field].push(e);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
if (reduceErrors) {
|
|
71
|
-
grouped = reduceGroupedErrors(grouped);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return Object.keys(grouped).length
|
|
75
|
-
? Promise.reject(grouped)
|
|
76
|
-
: Promise.resolve();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Resulting Promise
|
|
80
|
-
if (validatorQueue.length) {
|
|
81
|
-
return Promise.all(validatorQueue).then(gatherErrors);
|
|
82
|
-
}
|
|
83
|
-
return Promise.resolve();
|
|
84
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import DateObject from './dateObject';
|
|
2
|
-
import Email from './email';
|
|
3
|
-
import InArray from './inArray';
|
|
4
|
-
import Nino from './nino';
|
|
5
|
-
import PostalAddressObject from './postalAddressObject';
|
|
6
|
-
import Regex from './dateObject';
|
|
7
|
-
import Required from './required';
|
|
8
|
-
import Strlen from './strlen';
|
|
9
|
-
import WordCount from './wordCount';
|
|
10
|
-
|
|
11
|
-
export namespace ValidationRules {
|
|
12
|
-
export type dateObject = DateObject;
|
|
13
|
-
export type email = Email;
|
|
14
|
-
export type inArray = InArray;
|
|
15
|
-
export type nino = Nino;
|
|
16
|
-
export function optional(value: any):boolean;
|
|
17
|
-
export type postalAddressObject = PostalAddressObject;
|
|
18
|
-
export type regex = Regex;
|
|
19
|
-
export type required = Required;
|
|
20
|
-
export type strlen = Strlen;
|
|
21
|
-
export type wordCount = WordCount;
|
|
22
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
/* eslint-disable class-methods-use-this */
|
|
2
|
-
/**
|
|
3
|
-
* Date object format:
|
|
4
|
-
* {
|
|
5
|
-
* dd: <string>,
|
|
6
|
-
* mm: <string>,
|
|
7
|
-
* yyyy: <string>
|
|
8
|
-
* }.
|
|
9
|
-
*
|
|
10
|
-
* Note that the time part of any injected "DateTime" objects will be zero'ed, as
|
|
11
|
-
* we are only interested in the date component (minimum day resolution).
|
|
12
|
-
*
|
|
13
|
-
* Config options:
|
|
14
|
-
* string|object errorMsg = Error message to use on validation failure
|
|
15
|
-
* object|luxon.Duration afterOffsetFromNow = Date must be after offset from now
|
|
16
|
-
* string|object errorMsgAfterOffset = Error for afterOffsetFromNow failure
|
|
17
|
-
* object|luxon.Duration beforeOffsetFromNow = Date must be before offset from now
|
|
18
|
-
* string|object errorMsgBeforeOffset = Error for beforeOffsetFromNow failure
|
|
19
|
-
* bool allowMonthNames = Allow "Jan", "January", etc (default = false)
|
|
20
|
-
* bool allowSingleDigitDay = Allow "1" rather than "01" (default = false)
|
|
21
|
-
* bool allowSingleDigitMonth = Allow "1" rather than "01" (default = false)
|
|
22
|
-
* luxon.DateTime now = Override the notion of "now" (useful for testing)
|
|
23
|
-
*/
|
|
24
|
-
const { DateTime } = require('luxon');
|
|
25
|
-
const ValidationError = require('../ValidationError.js');
|
|
26
|
-
const ValidatorFactory = require('../ValidatorFactory.js');
|
|
27
|
-
const { isObjectType, stringifyInput } = require('../../Util.js');
|
|
28
|
-
|
|
29
|
-
class DateObject extends ValidatorFactory {
|
|
30
|
-
validate(value, dataContext = {}) {
|
|
31
|
-
const config = {
|
|
32
|
-
errorMsg: {
|
|
33
|
-
inline: 'validation:rule.dateObject.inline',
|
|
34
|
-
summary: 'validation:rule.dateObject.summary',
|
|
35
|
-
},
|
|
36
|
-
errorMsgAfterOffset: {
|
|
37
|
-
inline: 'validation:rule.dateObject.afterOffset.inline',
|
|
38
|
-
summary: 'validation:rule.dateObject.afterOffset.summary',
|
|
39
|
-
},
|
|
40
|
-
errorMsgBeforeOffset: {
|
|
41
|
-
inline: 'validation:rule.dateObject.beforeOffset.inline',
|
|
42
|
-
summary: 'validation:rule.dateObject.beforeOffset.summary',
|
|
43
|
-
},
|
|
44
|
-
now: DateTime.local(),
|
|
45
|
-
allowSingleDigitDay: false,
|
|
46
|
-
allowSingleDigitMonth: false,
|
|
47
|
-
allowMonthNames: false,
|
|
48
|
-
afterOffsetFromNow: undefined,
|
|
49
|
-
beforeOffsetFromNow: undefined,
|
|
50
|
-
...this.config,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
let valid = false;
|
|
54
|
-
let { errorMsg } = config;
|
|
55
|
-
let luxonDate;
|
|
56
|
-
const NOW = config.now.startOf('day');
|
|
57
|
-
|
|
58
|
-
// Accepted formats
|
|
59
|
-
let formats = ['dd-MM-yyyy'];
|
|
60
|
-
const formatTests = [{
|
|
61
|
-
flags: [config.allowSingleDigitDay],
|
|
62
|
-
formats: ['d-MM-yyyy'],
|
|
63
|
-
}, {
|
|
64
|
-
flags: [config.allowSingleDigitDay, config.allowSingleDigitMonth],
|
|
65
|
-
formats: ['d-M-yyyy'],
|
|
66
|
-
}, {
|
|
67
|
-
flags: [config.allowSingleDigitDay, config.allowMonthNames],
|
|
68
|
-
formats: ['d-MMM-yyyy', 'd-MMMM-yyyy'],
|
|
69
|
-
}, {
|
|
70
|
-
flags: [config.allowSingleDigitMonth],
|
|
71
|
-
formats: ['dd-M-yyyy'],
|
|
72
|
-
}, {
|
|
73
|
-
flags: [config.allowMonthNames],
|
|
74
|
-
formats: ['dd-MMM-yyyy', 'dd-MMMM-yyyy'],
|
|
75
|
-
}];
|
|
76
|
-
formatTests.forEach((test) => {
|
|
77
|
-
if (test.flags.every((v) => v === true)) {
|
|
78
|
-
formats = [...formats, ...test.formats]
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
if (typeof value === 'object') {
|
|
83
|
-
formats.find((format) => {
|
|
84
|
-
luxonDate = DateTime.fromFormat(
|
|
85
|
-
[value.dd, value.mm, value.yyyy].join('-'),
|
|
86
|
-
format,
|
|
87
|
-
).startOf('day');
|
|
88
|
-
|
|
89
|
-
valid = luxonDate.isValid;
|
|
90
|
-
|
|
91
|
-
return valid;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
if (luxonDate) {
|
|
95
|
-
// Check date is after the specified duration from now.
|
|
96
|
-
// Need to use UTC() otherwise DST shifts can affect the calculated offset
|
|
97
|
-
if (config.afterOffsetFromNow) {
|
|
98
|
-
const offsetDate = NOW.plus(config.afterOffsetFromNow).startOf('day');
|
|
99
|
-
|
|
100
|
-
if (luxonDate <= offsetDate) {
|
|
101
|
-
valid = false;
|
|
102
|
-
errorMsg = config.errorMsgAfterOffset;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Check date is before the specified duration from now
|
|
107
|
-
// Need to use UTC() otherwise DST shifts can affect the calculated offset
|
|
108
|
-
if (config.beforeOffsetFromNow) {
|
|
109
|
-
const offsetDate = NOW.plus(config.beforeOffsetFromNow).startOf('day');
|
|
110
|
-
|
|
111
|
-
if (luxonDate >= offsetDate) {
|
|
112
|
-
valid = false;
|
|
113
|
-
errorMsg = config.errorMsgBeforeOffset;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Check presence of each object component (dd, mm, yyyy) in order to log
|
|
119
|
-
// which specific parts are in error
|
|
120
|
-
errorMsg.focusSuffix = [];
|
|
121
|
-
if (!Object.prototype.hasOwnProperty.call(value, 'dd') || !value.dd) {
|
|
122
|
-
errorMsg.focusSuffix.push('[dd]');
|
|
123
|
-
}
|
|
124
|
-
if (!Object.prototype.hasOwnProperty.call(value, 'mm') || !value.mm) {
|
|
125
|
-
errorMsg.focusSuffix.push('[mm]');
|
|
126
|
-
}
|
|
127
|
-
if (!Object.prototype.hasOwnProperty.call(value, 'yyyy') || !value.yyyy) {
|
|
128
|
-
errorMsg.focusSuffix.push('[yyyy]');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// If the date is invalid, but not specific parts have been highighted in
|
|
132
|
-
// error, then highlight all inputs, focusing on the [dd] first
|
|
133
|
-
if (!valid && !errorMsg.focusSuffix.length) {
|
|
134
|
-
errorMsg.focusSuffix = ['[dd]', '[mm]', '[yyyy]'];
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return valid ? Promise.resolve() : Promise.reject(ValidationError.make({
|
|
139
|
-
errorMsg,
|
|
140
|
-
dataContext,
|
|
141
|
-
}));
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
sanitise(value) {
|
|
145
|
-
if (value !== undefined) {
|
|
146
|
-
return isObjectType(value) ? {
|
|
147
|
-
dd: stringifyInput(value.dd),
|
|
148
|
-
mm: stringifyInput(value.mm),
|
|
149
|
-
yyyy: stringifyInput(value.yyyy),
|
|
150
|
-
} : Object.create(null);
|
|
151
|
-
}
|
|
152
|
-
return undefined;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
module.exports = DateObject;
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/* eslint-disable class-methods-use-this */
|
|
2
|
-
/**
|
|
3
|
-
* Email address.
|
|
4
|
-
*
|
|
5
|
-
* This is not an exhaustive validation, and is permissive.
|
|
6
|
-
*
|
|
7
|
-
* Config options:
|
|
8
|
-
* string|object errorMsg = Error message to use on validation failure
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const { isEmail } = require('validator');
|
|
12
|
-
const ValidationError = require('../ValidationError.js');
|
|
13
|
-
const ValidatorFactory = require('../ValidatorFactory.js');
|
|
14
|
-
const { stringifyInput } = require('../../Util.js');
|
|
15
|
-
|
|
16
|
-
class Email extends ValidatorFactory {
|
|
17
|
-
validate(value, dataContext = {}) {
|
|
18
|
-
let isValid;
|
|
19
|
-
try {
|
|
20
|
-
isValid = isEmail(value);
|
|
21
|
-
} catch (e) {
|
|
22
|
-
isValid = false;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const errorMsg = this.config.errorMsg || {
|
|
26
|
-
summary: 'validation:rule.email.summary',
|
|
27
|
-
inline: 'validation:rule.email.inline',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
return isValid ? Promise.resolve() : Promise.reject(ValidationError.make({
|
|
31
|
-
errorMsg,
|
|
32
|
-
dataContext,
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
sanitise(value) {
|
|
37
|
-
if (value !== undefined) {
|
|
38
|
-
return stringifyInput(value);
|
|
39
|
-
}
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
module.exports = Email;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/* eslint-disable class-methods-use-this */
|
|
2
|
-
/**
|
|
3
|
-
* Test if a value is present in an array.
|
|
4
|
-
*
|
|
5
|
-
* Config options:
|
|
6
|
-
* Array source = Array of values to test against
|
|
7
|
-
*
|
|
8
|
-
* If the value itself is an array, all values within that array must be present
|
|
9
|
-
* in the `source` array in order to pass validation.
|
|
10
|
-
*/
|
|
11
|
-
const ValidationError = require('../ValidationError.js');
|
|
12
|
-
const ValidatorFactory = require('../ValidatorFactory.js');
|
|
13
|
-
const { stringifyInput, isStringable } = require('../../Util.js');
|
|
14
|
-
|
|
15
|
-
class InArray extends ValidatorFactory {
|
|
16
|
-
validate(value, dataContext = {}) {
|
|
17
|
-
let valid = false;
|
|
18
|
-
const source = this.config.source || [];
|
|
19
|
-
const errorMsg = this.config.errorMsg || {
|
|
20
|
-
inline: 'validation:rule.inArray.inline',
|
|
21
|
-
summary: 'validation:rule.inArray.summary',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
if (value !== null && typeof value !== 'undefined') {
|
|
25
|
-
const search = Array.isArray(value) ? value : [value];
|
|
26
|
-
for (let i = 0, l = search.length; i < l; i += 1) {
|
|
27
|
-
if (source.indexOf(search[i]) > -1) {
|
|
28
|
-
valid = true;
|
|
29
|
-
} else {
|
|
30
|
-
valid = false;
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return valid ? Promise.resolve() : Promise.reject(ValidationError.make({
|
|
37
|
-
errorMsg,
|
|
38
|
-
dataContext,
|
|
39
|
-
}));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
sanitise(value) {
|
|
43
|
-
const coerce = (val) => (stringifyInput(val, undefined));
|
|
44
|
-
|
|
45
|
-
// Basic stringable
|
|
46
|
-
if (isStringable(value)) {
|
|
47
|
-
return stringifyInput(value);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Coerce all elements to Strings.
|
|
51
|
-
// This only supports one dimensional array, with stringable element.
|
|
52
|
-
if (Array.isArray(value)) {
|
|
53
|
-
return value.map(coerce);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Unsupported value
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
module.exports = InArray;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const dateObject = require('./dateObject.js');
|
|
2
|
-
const email = require('./email.js');
|
|
3
|
-
const inArray = require('./inArray.js');
|
|
4
|
-
const nino = require('./nino.js');
|
|
5
|
-
const optional = require('./optional.js');
|
|
6
|
-
const postalAddressObject = require('./postalAddressObject.js');
|
|
7
|
-
const regex = require('./regex.js');
|
|
8
|
-
const required = require('./required.js');
|
|
9
|
-
const strlen = require('./strlen.js');
|
|
10
|
-
const wordCount = require('./wordCount.js');
|
|
11
|
-
|
|
12
|
-
module.exports = {
|
|
13
|
-
dateObject,
|
|
14
|
-
email,
|
|
15
|
-
inArray,
|
|
16
|
-
nino,
|
|
17
|
-
optional,
|
|
18
|
-
postalAddressObject,
|
|
19
|
-
regex,
|
|
20
|
-
required,
|
|
21
|
-
strlen,
|
|
22
|
-
wordCount,
|
|
23
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/* eslint-disable class-methods-use-this */
|
|
2
|
-
/**
|
|
3
|
-
* UK National Insurance number.
|
|
4
|
-
*
|
|
5
|
-
* Config options:
|
|
6
|
-
* string|object errorMsg = Error message to use on validation failure
|
|
7
|
-
* boolean allowWhitespace = will permit input values that contain spaces.
|
|
8
|
-
*
|
|
9
|
-
* Ref:
|
|
10
|
-
* https://en.wikipedia.org/wiki/National_Insurance_number#Format
|
|
11
|
-
* https://design-system.service.gov.uk/patterns/national-insurance-numbers/
|
|
12
|
-
*/
|
|
13
|
-
const ValidationError = require('../ValidationError.js');
|
|
14
|
-
const ValidatorFactory = require('../ValidatorFactory.js');
|
|
15
|
-
const { stringifyInput } = require('../../Util.js');
|
|
16
|
-
|
|
17
|
-
class Nino extends ValidatorFactory {
|
|
18
|
-
validate(value, dataContext = {}) {
|
|
19
|
-
const {
|
|
20
|
-
allowWhitespace,
|
|
21
|
-
errorMsg = {
|
|
22
|
-
inline: 'validation:rule.nino.inline',
|
|
23
|
-
summary: 'validation:rule.nino.summary',
|
|
24
|
-
},
|
|
25
|
-
} = this.config;
|
|
26
|
-
|
|
27
|
-
if (typeof allowWhitespace !== 'undefined' && typeof allowWhitespace !== 'boolean') {
|
|
28
|
-
throw new TypeError(`NINO validation rule option "allowWhitespace" must been a boolean. received ${typeof allowWhitespace}`);
|
|
29
|
-
}
|
|
30
|
-
const valid = typeof value === 'string'
|
|
31
|
-
&& value.replace((typeof allowWhitespace !== 'undefined' && allowWhitespace) ? /\u0020/g : '', '')
|
|
32
|
-
.match(/^(?!BG|GB|NK|KN|TN|NT|ZZ)[ABCEGHJ-PRSTW-Z][ABCEGHJ-NPRSTW-Z]\d{6}[A-D]$/i);
|
|
33
|
-
|
|
34
|
-
return valid ? Promise.resolve() : Promise.reject(ValidationError.make({
|
|
35
|
-
errorMsg,
|
|
36
|
-
dataContext,
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
sanitise(value) {
|
|
41
|
-
if (value !== undefined) {
|
|
42
|
-
return stringifyInput(value);
|
|
43
|
-
}
|
|
44
|
-
return undefined;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = Nino;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const Util = require('../../Util.js');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* This is different to all other rules in that it _must_ return a value
|
|
5
|
-
* synchronously. You must not `bind()` this function to create a new one.
|
|
6
|
-
*
|
|
7
|
-
* @param {any} value Value
|
|
8
|
-
* @returns {boolean} Return true if the value is not present
|
|
9
|
-
*/
|
|
10
|
-
function optional(value) {
|
|
11
|
-
return Util.isEmpty(value);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
module.exports = optional;
|