@dwp/govuk-casa 8.16.1 → 8.16.3
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/dist/assets/css/casa-ie8.css +1 -1
- package/dist/assets/css/casa.css +1 -1
- package/dist/casa.d.ts +13 -13
- package/dist/casa.js +17 -7
- package/dist/casa.js.map +1 -1
- package/dist/lib/CasaTemplateLoader.d.ts +1 -1
- package/dist/lib/CasaTemplateLoader.js +13 -14
- package/dist/lib/CasaTemplateLoader.js.map +1 -1
- package/dist/lib/JourneyContext.d.ts +10 -4
- package/dist/lib/JourneyContext.js +57 -47
- package/dist/lib/JourneyContext.js.map +1 -1
- package/dist/lib/MutableRouter.d.ts +1 -1
- package/dist/lib/MutableRouter.js +22 -23
- package/dist/lib/MutableRouter.js.map +1 -1
- package/dist/lib/Plan.d.ts +5 -5
- package/dist/lib/Plan.js +49 -36
- package/dist/lib/Plan.js.map +1 -1
- package/dist/lib/ValidationError.d.ts +1 -1
- package/dist/lib/ValidationError.js +9 -9
- package/dist/lib/ValidationError.js.map +1 -1
- package/dist/lib/ValidatorFactory.js +4 -7
- package/dist/lib/ValidatorFactory.js.map +1 -1
- package/dist/lib/configuration-ingestor.d.ts +75 -14
- package/dist/lib/configuration-ingestor.js +156 -64
- package/dist/lib/configuration-ingestor.js.map +1 -1
- package/dist/lib/configure.js +11 -10
- package/dist/lib/configure.js.map +1 -1
- package/dist/lib/constants.js +8 -8
- package/dist/lib/context-id-generators.d.ts +1 -1
- package/dist/lib/context-id-generators.js +7 -4
- package/dist/lib/context-id-generators.js.map +1 -1
- package/dist/lib/end-session.js +2 -2
- package/dist/lib/field.d.ts +6 -6
- package/dist/lib/field.js +15 -21
- package/dist/lib/field.js.map +1 -1
- package/dist/lib/index.d.ts +13 -13
- package/dist/lib/index.js +17 -7
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/logger.js +7 -7
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/mount.js +3 -3
- package/dist/lib/mount.js.map +1 -1
- package/dist/lib/nunjucks-filters.d.ts +5 -1
- package/dist/lib/nunjucks-filters.js +37 -23
- package/dist/lib/nunjucks-filters.js.map +1 -1
- package/dist/lib/nunjucks.d.ts +2 -2
- package/dist/lib/nunjucks.js +6 -7
- package/dist/lib/nunjucks.js.map +1 -1
- package/dist/lib/utils.js +52 -42
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/validators/dateObject.d.ts +3 -3
- package/dist/lib/validators/dateObject.js +44 -37
- package/dist/lib/validators/dateObject.js.map +1 -1
- package/dist/lib/validators/email.d.ts +2 -2
- package/dist/lib/validators/email.js +4 -5
- package/dist/lib/validators/email.js.map +1 -1
- package/dist/lib/validators/inArray.d.ts +2 -2
- package/dist/lib/validators/inArray.js +5 -6
- package/dist/lib/validators/inArray.js.map +1 -1
- package/dist/lib/validators/index.d.ts +10 -10
- package/dist/lib/validators/index.js.map +1 -1
- package/dist/lib/validators/nino.d.ts +2 -2
- package/dist/lib/validators/nino.js +10 -7
- package/dist/lib/validators/nino.js.map +1 -1
- package/dist/lib/validators/postalAddressObject.d.ts +2 -2
- package/dist/lib/validators/postalAddressObject.js +52 -39
- package/dist/lib/validators/postalAddressObject.js.map +1 -1
- package/dist/lib/validators/range.d.ts +2 -2
- package/dist/lib/validators/range.js +6 -7
- package/dist/lib/validators/range.js.map +1 -1
- package/dist/lib/validators/regex.d.ts +2 -2
- package/dist/lib/validators/regex.js +4 -5
- package/dist/lib/validators/regex.js.map +1 -1
- package/dist/lib/validators/required.d.ts +2 -2
- package/dist/lib/validators/required.js +6 -9
- package/dist/lib/validators/required.js.map +1 -1
- package/dist/lib/validators/strlen.d.ts +2 -2
- package/dist/lib/validators/strlen.js +8 -9
- package/dist/lib/validators/strlen.js.map +1 -1
- package/dist/lib/validators/wordCount.d.ts +2 -2
- package/dist/lib/validators/wordCount.js +10 -9
- package/dist/lib/validators/wordCount.js.map +1 -1
- package/dist/lib/waypoint-url.d.ts +4 -4
- package/dist/lib/waypoint-url.js +23 -23
- package/dist/lib/waypoint-url.js.map +1 -1
- package/dist/middleware/body-parser.d.ts +27 -5
- package/dist/middleware/body-parser.js +37 -6
- package/dist/middleware/body-parser.js.map +1 -1
- package/dist/middleware/csrf.d.ts +3 -0
- package/dist/middleware/csrf.js +3 -0
- package/dist/middleware/csrf.js.map +1 -1
- package/dist/middleware/data.d.ts +22 -5
- package/dist/middleware/data.js +37 -7
- package/dist/middleware/data.js.map +1 -1
- package/dist/middleware/gather-fields.d.ts +1 -1
- package/dist/middleware/gather-fields.js +4 -3
- package/dist/middleware/gather-fields.js.map +1 -1
- package/dist/middleware/i18n.d.ts +11 -2
- package/dist/middleware/i18n.js +26 -17
- package/dist/middleware/i18n.js.map +1 -1
- package/dist/middleware/post.d.ts +3 -1
- package/dist/middleware/post.js +35 -18
- package/dist/middleware/post.js.map +1 -1
- package/dist/middleware/pre.d.ts +1 -1
- package/dist/middleware/pre.js +44 -21
- package/dist/middleware/pre.js.map +1 -1
- package/dist/middleware/progress-journey.d.ts +1 -1
- package/dist/middleware/progress-journey.js +5 -5
- package/dist/middleware/progress-journey.js.map +1 -1
- package/dist/middleware/sanitise-fields.d.ts +2 -2
- package/dist/middleware/sanitise-fields.js +13 -11
- package/dist/middleware/sanitise-fields.js.map +1 -1
- package/dist/middleware/serve-first-waypoint.d.ts +1 -1
- package/dist/middleware/serve-first-waypoint.js +6 -4
- package/dist/middleware/serve-first-waypoint.js.map +1 -1
- package/dist/middleware/session.d.ts +27 -8
- package/dist/middleware/session.js +53 -25
- package/dist/middleware/session.js.map +1 -1
- package/dist/middleware/skip-waypoint.d.ts +1 -1
- package/dist/middleware/skip-waypoint.js +3 -3
- package/dist/middleware/skip-waypoint.js.map +1 -1
- package/dist/middleware/steer-journey.d.ts +1 -1
- package/dist/middleware/steer-journey.js +15 -13
- package/dist/middleware/steer-journey.js.map +1 -1
- package/dist/middleware/strip-proxy-path.d.ts +1 -1
- package/dist/middleware/strip-proxy-path.js +3 -3
- package/dist/middleware/strip-proxy-path.js.map +1 -1
- package/dist/middleware/validate-fields.d.ts +2 -2
- package/dist/middleware/validate-fields.js +2 -5
- package/dist/middleware/validate-fields.js.map +1 -1
- package/dist/routes/ancillary.d.ts +2 -2
- package/dist/routes/ancillary.js +3 -3
- package/dist/routes/ancillary.js.map +1 -1
- package/dist/routes/journey.d.ts +1 -1
- package/dist/routes/journey.js +85 -31
- package/dist/routes/journey.js.map +1 -1
- package/dist/routes/static.d.ts +2 -2
- package/dist/routes/static.js +18 -18
- package/dist/routes/static.js.map +1 -1
- package/package.json +39 -42
- package/src/casa.js +13 -13
- package/src/lib/CasaTemplateLoader.js +21 -17
- package/src/lib/JourneyContext.js +118 -79
- package/src/lib/MutableRouter.js +30 -26
- package/src/lib/Plan.js +109 -62
- package/src/lib/ValidationError.js +13 -10
- package/src/lib/ValidatorFactory.js +7 -8
- package/src/lib/configuration-ingestor.js +200 -74
- package/src/lib/configure.js +31 -30
- package/src/lib/constants.js +8 -8
- package/src/lib/context-id-generators.js +39 -38
- package/src/lib/end-session.js +3 -3
- package/src/lib/field.js +48 -32
- package/src/lib/index.js +12 -12
- package/src/lib/logger.js +9 -9
- package/src/lib/mount.js +68 -73
- package/src/lib/nunjucks-filters.js +57 -44
- package/src/lib/nunjucks.js +20 -16
- package/src/lib/utils.js +69 -44
- package/src/lib/validators/dateObject.js +57 -48
- package/src/lib/validators/email.js +8 -9
- package/src/lib/validators/inArray.js +8 -9
- package/src/lib/validators/index.js +11 -11
- package/src/lib/validators/nino.js +25 -12
- package/src/lib/validators/postalAddressObject.js +73 -55
- package/src/lib/validators/range.js +9 -11
- package/src/lib/validators/regex.js +7 -8
- package/src/lib/validators/required.js +13 -14
- package/src/lib/validators/strlen.js +11 -12
- package/src/lib/validators/wordCount.js +17 -12
- package/src/lib/waypoint-url.js +48 -33
- package/src/middleware/body-parser.js +44 -10
- package/src/middleware/csrf.js +4 -1
- package/src/middleware/data.js +62 -25
- package/src/middleware/gather-fields.js +8 -8
- package/src/middleware/i18n.js +49 -39
- package/src/middleware/post.js +47 -21
- package/src/middleware/pre.js +60 -35
- package/src/middleware/progress-journey.js +32 -18
- package/src/middleware/sanitise-fields.js +43 -20
- package/src/middleware/serve-first-waypoint.js +12 -10
- package/src/middleware/session.js +97 -65
- package/src/middleware/skip-waypoint.js +7 -9
- package/src/middleware/steer-journey.js +39 -27
- package/src/middleware/strip-proxy-path.js +8 -7
- package/src/middleware/validate-fields.js +5 -12
- package/src/routes/ancillary.js +4 -6
- package/src/routes/journey.js +158 -78
- package/src/routes/static.js +61 -28
package/src/lib/constants.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* General-purpose references to the different request lifecycle phases.
|
|
3
3
|
*/
|
|
4
|
-
export const REQUEST_PHASE_STEER = Symbol(
|
|
5
|
-
export const REQUEST_PHASE_SANITISE = Symbol(
|
|
6
|
-
export const REQUEST_PHASE_GATHER = Symbol(
|
|
7
|
-
export const REQUEST_PHASE_VALIDATE = Symbol(
|
|
8
|
-
export const REQUEST_PHASE_REDIRECT = Symbol(
|
|
9
|
-
export const REQUEST_PHASE_RENDER = Symbol(
|
|
10
|
-
export const CONFIG_ERROR_VISIBILITY_ONSUBMIT = Symbol(
|
|
11
|
-
export const CONFIG_ERROR_VISIBILITY_ALWAYS = Symbol(
|
|
4
|
+
export const REQUEST_PHASE_STEER = Symbol("steer");
|
|
5
|
+
export const REQUEST_PHASE_SANITISE = Symbol("sanitise");
|
|
6
|
+
export const REQUEST_PHASE_GATHER = Symbol("gather");
|
|
7
|
+
export const REQUEST_PHASE_VALIDATE = Symbol("validate");
|
|
8
|
+
export const REQUEST_PHASE_REDIRECT = Symbol("redirect");
|
|
9
|
+
export const REQUEST_PHASE_RENDER = Symbol("render");
|
|
10
|
+
export const CONFIG_ERROR_VISIBILITY_ONSUBMIT = Symbol("onsubmit");
|
|
11
|
+
export const CONFIG_ERROR_VISIBILITY_ALWAYS = Symbol("always");
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { randomUUID } from 'node:crypto';
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* @typedef {import('../casa.js').ContextIdGenerator} ContextIdGenerator
|
|
@@ -21,51 +20,53 @@ const uuid = () => () => randomUUID();
|
|
|
21
20
|
*
|
|
22
21
|
* @returns {ContextIdGenerator} Generator function
|
|
23
22
|
*/
|
|
24
|
-
const sequentialInteger =
|
|
25
|
-
|
|
23
|
+
const sequentialInteger =
|
|
24
|
+
() =>
|
|
25
|
+
({ reservedIds }) => {
|
|
26
|
+
const contextIds = Array.from(reservedIds).sort();
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
if (!contextIds.length) {
|
|
29
|
+
return "1";
|
|
30
|
+
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
// Find the first numeric ID that we can increment
|
|
33
|
+
let lastInSequence;
|
|
34
|
+
do {
|
|
35
|
+
lastInSequence = Number.parseInt(contextIds.pop(), 10);
|
|
36
|
+
} while (contextIds.length && Number.isNaN(lastInSequence));
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
};
|
|
38
|
+
return String(!Number.isNaN(lastInSequence) ? lastInSequence + 1 : 1);
|
|
39
|
+
};
|
|
39
40
|
|
|
40
|
-
const shortGuid =
|
|
41
|
-
length = 5,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
// Ambiguous characters excluded
|
|
46
|
-
const poolSize = pool.length;
|
|
41
|
+
const shortGuid =
|
|
42
|
+
({ length = 5, prefix = "", pool = "abcdefhkmnprtwxy346789" } = {}) =>
|
|
43
|
+
({ reservedIds }) => {
|
|
44
|
+
// Ambiguous characters excluded
|
|
45
|
+
const poolSize = pool.length;
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
const maxAttempts = 10;
|
|
48
|
+
let attempts = maxAttempts;
|
|
49
|
+
let id;
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
do {
|
|
52
|
+
id = Array(length)
|
|
53
|
+
.fill(0)
|
|
54
|
+
/* eslint-disable-next-line sonarjs/pseudo-random */
|
|
55
|
+
.map(() => pool.charAt(Math.floor(Math.random() * poolSize)))
|
|
56
|
+
.join("");
|
|
57
|
+
attempts--;
|
|
58
|
+
} while (attempts > 0 && reservedIds.includes(id));
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
if (attempts === 0) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Failed to generate GUID after ${maxAttempts} iterations`,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
60
65
|
|
|
61
|
-
|
|
62
|
-
}
|
|
66
|
+
return `${prefix}${id}`;
|
|
67
|
+
};
|
|
63
68
|
|
|
64
69
|
/**
|
|
65
70
|
* @namespace ContextIdGenerators
|
|
66
71
|
*/
|
|
67
|
-
export {
|
|
68
|
-
uuid,
|
|
69
|
-
sequentialInteger,
|
|
70
|
-
shortGuid,
|
|
71
|
-
};
|
|
72
|
+
export { uuid, sequentialInteger, shortGuid };
|
package/src/lib/end-session.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import logger from
|
|
1
|
+
import logger from "./logger.js";
|
|
2
2
|
|
|
3
|
-
const log = logger(
|
|
3
|
+
const log = logger("lib:end-session");
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A convenience for ending the current session, but retaining some data in it,
|
|
@@ -19,7 +19,7 @@ export default function endSession(req, next) {
|
|
|
19
19
|
const { language } = req.session;
|
|
20
20
|
|
|
21
21
|
Object.entries(req.session).forEach(([k]) => {
|
|
22
|
-
if (![
|
|
22
|
+
if (!["cookie"].includes(k)) {
|
|
23
23
|
// ESLint disabled as `Object.entries()` returns "own" properties, and
|
|
24
24
|
// all values are being null'd, so not assigned any user-controlled values
|
|
25
25
|
/* eslint-disable-next-line security/detect-object-injection */
|
package/src/lib/field.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import lodash from
|
|
2
|
-
import { isEmpty } from
|
|
3
|
-
import logger from
|
|
1
|
+
import lodash from "lodash";
|
|
2
|
+
import { isEmpty } from "./utils.js";
|
|
3
|
+
import logger from "./logger.js";
|
|
4
4
|
|
|
5
|
-
const log = logger(
|
|
5
|
+
const log = logger("lib:field");
|
|
6
6
|
const { isFunction } = lodash;
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -78,12 +78,17 @@ export class PageField {
|
|
|
78
78
|
*
|
|
79
79
|
* @param {string} name Field name
|
|
80
80
|
* @param {object} [opts] Options
|
|
81
|
-
* @param {boolean} [opts.optional
|
|
82
|
-
* @param {boolean} [opts.persist
|
|
81
|
+
* @param {boolean} [opts.optional] Whether this field is optional
|
|
82
|
+
* @param {boolean} [opts.persist] Whether this field will persist in `req.body`
|
|
83
83
|
*/
|
|
84
|
-
constructor(
|
|
84
|
+
constructor(
|
|
85
|
+
name,
|
|
86
|
+
{ optional = false, persist = true } = Object.create(null),
|
|
87
|
+
) {
|
|
85
88
|
if (!name) {
|
|
86
|
-
throw new SyntaxError(
|
|
89
|
+
throw new SyntaxError(
|
|
90
|
+
"A name for this field is required, i.e. \"field('myField')\".",
|
|
91
|
+
);
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
this.#name = undefined;
|
|
@@ -100,7 +105,7 @@ export class PageField {
|
|
|
100
105
|
};
|
|
101
106
|
|
|
102
107
|
// Apply name
|
|
103
|
-
|
|
108
|
+
|
|
104
109
|
this.rename(name);
|
|
105
110
|
}
|
|
106
111
|
|
|
@@ -139,7 +144,9 @@ export class PageField {
|
|
|
139
144
|
*/
|
|
140
145
|
getValue(obj = Object.create(null)) {
|
|
141
146
|
if (this.#meta.complex) {
|
|
142
|
-
return obj[this.#meta.complexFieldName]?.[
|
|
147
|
+
return obj[this.#meta.complexFieldName]?.[
|
|
148
|
+
this.#meta.complexFieldProperty
|
|
149
|
+
];
|
|
143
150
|
}
|
|
144
151
|
return obj[this.#name];
|
|
145
152
|
}
|
|
@@ -156,13 +163,11 @@ export class PageField {
|
|
|
156
163
|
*/
|
|
157
164
|
putValue(obj = Object.create(null), value = undefined) {
|
|
158
165
|
if (this.#meta.complex) {
|
|
159
|
-
/* eslint-disable-next-line no-param-reassign */
|
|
160
166
|
obj[this.#meta.complexFieldName] = {
|
|
161
167
|
...(obj[this.#meta.complexFieldName] ?? {}),
|
|
162
168
|
[this.#meta.complexFieldProperty]: value,
|
|
163
169
|
};
|
|
164
170
|
} else {
|
|
165
|
-
/* eslint-disable-next-line no-param-reassign */
|
|
166
171
|
obj[this.#name] = value;
|
|
167
172
|
}
|
|
168
173
|
|
|
@@ -188,7 +193,9 @@ export class PageField {
|
|
|
188
193
|
*/
|
|
189
194
|
rename(name) {
|
|
190
195
|
if (reInvalidName.test(String(name))) {
|
|
191
|
-
throw new SyntaxError(
|
|
196
|
+
throw new SyntaxError(
|
|
197
|
+
`Field '${String(name)}' name contains invalid characters.`,
|
|
198
|
+
);
|
|
192
199
|
}
|
|
193
200
|
|
|
194
201
|
// Complex names are only supported to one level deep. For example,
|
|
@@ -196,7 +203,9 @@ export class PageField {
|
|
|
196
203
|
// early to aid developer.
|
|
197
204
|
const isComplex = reComplexType.test(name);
|
|
198
205
|
if (isComplex && name.match(/\[/g).length > 1) {
|
|
199
|
-
throw new SyntaxError(
|
|
206
|
+
throw new SyntaxError(
|
|
207
|
+
"Complex field names are only supported to 1 property depth. E.g. a[b] is ok, a[b][c] is not",
|
|
208
|
+
);
|
|
200
209
|
}
|
|
201
210
|
|
|
202
211
|
this.#name = String(name);
|
|
@@ -232,10 +241,12 @@ export class PageField {
|
|
|
232
241
|
*/
|
|
233
242
|
validators(items = []) {
|
|
234
243
|
if (!items.length) {
|
|
235
|
-
log.warn(
|
|
244
|
+
log.warn(
|
|
245
|
+
"Calling validators() to get all validators is deprecated, please use getValidators()",
|
|
246
|
+
);
|
|
236
247
|
return this.getValidators();
|
|
237
248
|
}
|
|
238
|
-
this.#validators = [...this.#validators, ...
|
|
249
|
+
this.#validators = [...this.#validators, ...items.flat()];
|
|
239
250
|
return this;
|
|
240
251
|
}
|
|
241
252
|
|
|
@@ -259,11 +270,13 @@ export class PageField {
|
|
|
259
270
|
*/
|
|
260
271
|
processors(items = []) {
|
|
261
272
|
if (!items.length) {
|
|
262
|
-
log.warn(
|
|
273
|
+
log.warn(
|
|
274
|
+
"Calling processors() to get all processors is deprecated, please use getProcessors()",
|
|
275
|
+
);
|
|
263
276
|
return this.getProcessors();
|
|
264
277
|
}
|
|
265
278
|
|
|
266
|
-
this.#processors = [...this.#processors, ...
|
|
279
|
+
this.#processors = [...this.#processors, ...items.flat()];
|
|
267
280
|
return this;
|
|
268
281
|
}
|
|
269
282
|
|
|
@@ -288,10 +301,12 @@ export class PageField {
|
|
|
288
301
|
*/
|
|
289
302
|
conditions(items = []) {
|
|
290
303
|
if (!items.length) {
|
|
291
|
-
log.warn(
|
|
304
|
+
log.warn(
|
|
305
|
+
"Calling conditions() to get all conditions is deprecated, please use getConditions()",
|
|
306
|
+
);
|
|
292
307
|
return this.getConditions();
|
|
293
308
|
}
|
|
294
|
-
this.#conditions = [...this.#conditions, ...
|
|
309
|
+
this.#conditions = [...this.#conditions, ...items.flat()];
|
|
295
310
|
return this;
|
|
296
311
|
}
|
|
297
312
|
|
|
@@ -325,22 +340,23 @@ export class PageField {
|
|
|
325
340
|
// ESLint disabled as `i` is an integer
|
|
326
341
|
/* eslint-disable security/detect-object-injection */
|
|
327
342
|
// TODO: Replace `value` with `context.fieldValue` here
|
|
328
|
-
let fieldErrors = this.#validators[i].validate(value, context)
|
|
343
|
+
let fieldErrors = this.#validators[i].validate(value, context);
|
|
329
344
|
if (!Array.isArray(fieldErrors)) {
|
|
330
345
|
// Friendly message for developer
|
|
331
|
-
throw new TypeError(
|
|
346
|
+
throw new TypeError(
|
|
347
|
+
`The validator at index ${i} (name: ${this.#validators[i].name || "unknown"}) for field '${this.#name}' did not return an array`,
|
|
348
|
+
);
|
|
332
349
|
}
|
|
333
350
|
|
|
334
|
-
fieldErrors = fieldErrors.map((e) =>
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
351
|
+
fieldErrors = fieldErrors.map((e) =>
|
|
352
|
+
e.withContext({
|
|
353
|
+
...context,
|
|
354
|
+
validator: this.#validators[i].name,
|
|
355
|
+
}),
|
|
356
|
+
);
|
|
338
357
|
/* eslint-enable security/detect-object-injection */
|
|
339
358
|
|
|
340
|
-
errors = [
|
|
341
|
-
...errors,
|
|
342
|
-
...(fieldErrors ?? []),
|
|
343
|
-
];
|
|
359
|
+
errors = [...errors, ...(fieldErrors ?? [])];
|
|
344
360
|
}
|
|
345
361
|
|
|
346
362
|
return errors;
|
|
@@ -447,8 +463,8 @@ export class PageField {
|
|
|
447
463
|
* @memberof module:@dwp/govuk-casa
|
|
448
464
|
* @param {string} name Field name
|
|
449
465
|
* @param {object} [opts] Options
|
|
450
|
-
* @param {boolean} [opts.optional
|
|
451
|
-
* @param {boolean} [opts.persist
|
|
466
|
+
* @param {boolean} [opts.optional] Whether this field is optional
|
|
467
|
+
* @param {boolean} [opts.persist] Whether this field will persist in `req.body`
|
|
452
468
|
* @returns {PageField} A PageField
|
|
453
469
|
*/
|
|
454
470
|
export default function field(name, opts) {
|
package/src/lib/index.js
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
* imported anywhere in code, other than JSDoc references.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import CasaTemplateLoader from
|
|
7
|
-
import configure from
|
|
8
|
-
import configurationIngestor from
|
|
9
|
-
import endSession from
|
|
10
|
-
import field, { PageField } from
|
|
11
|
-
import JourneyContext from
|
|
12
|
-
import MutableRouter from
|
|
13
|
-
import Plan from
|
|
14
|
-
import ValidationError from
|
|
15
|
-
import ValidatorFactory from
|
|
16
|
-
import waypointUrl from
|
|
17
|
-
import * as utils from
|
|
6
|
+
import CasaTemplateLoader from "./CasaTemplateLoader.js";
|
|
7
|
+
import configure from "./configure.js";
|
|
8
|
+
import configurationIngestor from "./configuration-ingestor.js";
|
|
9
|
+
import endSession from "./end-session.js";
|
|
10
|
+
import field, { PageField } from "./field.js";
|
|
11
|
+
import JourneyContext from "./JourneyContext.js";
|
|
12
|
+
import MutableRouter from "./MutableRouter.js";
|
|
13
|
+
import Plan from "./Plan.js";
|
|
14
|
+
import ValidationError from "./ValidationError.js";
|
|
15
|
+
import ValidatorFactory from "./ValidatorFactory.js";
|
|
16
|
+
import waypointUrl from "./waypoint-url.js";
|
|
17
|
+
import * as utils from "./utils.js";
|
|
18
18
|
|
|
19
19
|
export {
|
|
20
20
|
CasaTemplateLoader,
|
package/src/lib/logger.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import debug from
|
|
1
|
+
import debug from "debug";
|
|
2
2
|
|
|
3
|
-
const casaDebugger = debug(
|
|
3
|
+
const casaDebugger = debug("casa");
|
|
4
4
|
|
|
5
5
|
export default (namespace) => {
|
|
6
6
|
const logger = casaDebugger.extend(namespace);
|
|
7
7
|
|
|
8
8
|
return {
|
|
9
|
-
trace: logger.extend(
|
|
10
|
-
debug: logger.extend(
|
|
11
|
-
info: logger.extend(
|
|
12
|
-
warn: logger.extend(
|
|
13
|
-
error: logger.extend(
|
|
14
|
-
fatal: logger.extend(
|
|
9
|
+
trace: logger.extend("trace"),
|
|
10
|
+
debug: logger.extend("debug"),
|
|
11
|
+
info: logger.extend("info"),
|
|
12
|
+
warn: logger.extend("warn"),
|
|
13
|
+
error: logger.extend("error"),
|
|
14
|
+
fatal: logger.extend("fatal"),
|
|
15
15
|
};
|
|
16
|
-
}
|
|
16
|
+
};
|
package/src/lib/mount.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Router } from
|
|
2
|
-
import { pathToRegexp } from
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { pathToRegexp } from "path-to-regexp";
|
|
3
3
|
|
|
4
|
-
import stripProxyPathMiddlewareFactory from
|
|
5
|
-
import serveFirstWaypointMiddlewareFactory from
|
|
4
|
+
import stripProxyPathMiddlewareFactory from "../middleware/strip-proxy-path.js";
|
|
5
|
+
import serveFirstWaypointMiddlewareFactory from "../middleware/serve-first-waypoint.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @access private
|
|
@@ -48,80 +48,75 @@ import serveFirstWaypointMiddlewareFactory from '../middleware/serve-first-waypo
|
|
|
48
48
|
* @returns {Mounter} mount
|
|
49
49
|
*/
|
|
50
50
|
export default ({
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}) =>
|
|
64
|
-
app,
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
serveFirstWaypoint = false,
|
|
68
|
-
} = {},
|
|
69
|
-
) => {
|
|
70
|
-
nunjucksEnv.express(app);
|
|
71
|
-
app.set('view engine', 'njk');
|
|
51
|
+
nunjucksEnv,
|
|
52
|
+
mountUrl,
|
|
53
|
+
plan,
|
|
54
|
+
staticRouter,
|
|
55
|
+
ancillaryRouter,
|
|
56
|
+
journeyRouter,
|
|
57
|
+
preMiddleware,
|
|
58
|
+
sessionMiddleware,
|
|
59
|
+
i18nMiddleware,
|
|
60
|
+
bodyParserMiddleware,
|
|
61
|
+
dataMiddleware,
|
|
62
|
+
postMiddleware,
|
|
63
|
+
}) =>
|
|
64
|
+
(app, { route = "/", serveFirstWaypoint = false } = {}) => {
|
|
65
|
+
nunjucksEnv.express(app);
|
|
66
|
+
app.set("view engine", "njk");
|
|
72
67
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
// If a `mountUrl` has been defined, then we're potentially in "proxy mode",
|
|
69
|
+
// in which we strip the proxy path prefix from the incoming request URLs.
|
|
70
|
+
if (mountUrl) {
|
|
71
|
+
app.use(stripProxyPathMiddlewareFactory({ mountUrl }));
|
|
72
|
+
}
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
// Attach a handler to redirect requests for `/` to the first waypoint in
|
|
75
|
+
// the plan
|
|
76
|
+
if (serveFirstWaypoint && plan) {
|
|
77
|
+
const re = pathToRegexp(`${route}`.replace(/\/+/g, "/"));
|
|
78
|
+
app.use(re.regexp, serveFirstWaypointMiddlewareFactory({ plan }));
|
|
79
|
+
}
|
|
85
80
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
81
|
+
// Capture the mount path of this CASA app, before any parameterised path
|
|
82
|
+
// segments exert influence over `req.baseUrl` in the `router` further below.
|
|
83
|
+
// This can later be used by middleware that wants to use the
|
|
84
|
+
// "unparameterised" version of the request's `baseUrl`, such as the static
|
|
85
|
+
// router's middleware.
|
|
86
|
+
app.use((req, res, next) => {
|
|
87
|
+
req.unparameterisedBaseUrl = req.baseUrl;
|
|
88
|
+
next();
|
|
89
|
+
});
|
|
95
90
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
91
|
+
// Serve static assets from the `app` rather than the `router`. The router
|
|
92
|
+
// may contain parameterised path segments which would mean serving static
|
|
93
|
+
// assets over a dynamic URL each time, thus causing lots of cache misses on
|
|
94
|
+
// the browser.
|
|
95
|
+
const sealedStaticRouter = staticRouter.seal();
|
|
96
|
+
app.use(preMiddleware);
|
|
97
|
+
app.use(sealedStaticRouter);
|
|
103
98
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
const router = Router({
|
|
100
|
+
// Required so that any parameters in the URL are propagated to middleware
|
|
101
|
+
mergeParams: true,
|
|
102
|
+
});
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
104
|
+
router.use(preMiddleware);
|
|
105
|
+
// !!! DEPRECATE in v9 !!! For performance reasons, static assets will
|
|
106
|
+
// always be handled via the `app` middleware rather than `router`.
|
|
107
|
+
// Anywhere `mountUrl` is used in templates to service static assets must be
|
|
108
|
+
// changed to use `staticMountUrl`.
|
|
109
|
+
// TASK: remove this line below
|
|
110
|
+
router.use(sealedStaticRouter);
|
|
111
|
+
router.use(sessionMiddleware);
|
|
112
|
+
router.use(i18nMiddleware);
|
|
113
|
+
router.use(bodyParserMiddleware);
|
|
114
|
+
router.use(dataMiddleware);
|
|
115
|
+
router.use(ancillaryRouter.seal());
|
|
116
|
+
router.use(journeyRouter.seal());
|
|
117
|
+
router.use(postMiddleware);
|
|
123
118
|
|
|
124
|
-
|
|
119
|
+
app.use(route, router);
|
|
125
120
|
|
|
126
|
-
|
|
127
|
-
};
|
|
121
|
+
return app;
|
|
122
|
+
};
|