@dwp/govuk-casa 9.7.0 → 10.1.0
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.css +1 -1
- package/dist/assets/css/casa.css.map +1 -1
- package/dist/casa.d.ts +90 -44
- package/dist/casa.d.ts.map +1 -0
- package/dist/casa.js +85 -101
- package/dist/core-plugins/edit-snapshot/src/configure.d.ts +1 -0
- package/dist/core-plugins/edit-snapshot/src/configure.d.ts.map +1 -0
- package/dist/core-plugins/edit-snapshot/src/configure.js +7 -14
- package/dist/core-plugins/edit-snapshot/src/index.d.ts +1 -0
- package/dist/core-plugins/edit-snapshot/src/index.d.ts.map +1 -0
- package/dist/core-plugins/edit-snapshot/src/index.js +3 -9
- package/dist/core-plugins/edit-snapshot/src/post-steer-hook.d.ts +2 -1
- package/dist/core-plugins/edit-snapshot/src/post-steer-hook.d.ts.map +1 -0
- package/dist/core-plugins/edit-snapshot/src/post-steer-hook.js +8 -13
- package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.d.ts +2 -1
- package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.d.ts.map +1 -0
- package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.js +13 -18
- package/dist/core-plugins/edit-snapshot/src/utils.d.ts +8 -5
- package/dist/core-plugins/edit-snapshot/src/utils.d.ts.map +1 -0
- package/dist/core-plugins/edit-snapshot/src/utils.js +37 -19
- package/dist/core-plugins/index.d.ts +1 -0
- package/dist/core-plugins/index.d.ts.map +1 -0
- package/dist/core-plugins/index.js +1 -9
- package/dist/lib/CasaTemplateLoader.d.ts +1 -0
- package/dist/lib/CasaTemplateLoader.d.ts.map +1 -0
- package/dist/lib/CasaTemplateLoader.js +2 -6
- package/dist/lib/JourneyContext.d.ts +22 -11
- package/dist/lib/JourneyContext.d.ts.map +1 -0
- package/dist/lib/JourneyContext.js +40 -45
- package/dist/lib/MutableRouter.d.ts +79 -55
- package/dist/lib/MutableRouter.d.ts.map +1 -0
- package/dist/lib/MutableRouter.js +53 -45
- package/dist/lib/NullObject.d.ts +3 -0
- package/dist/lib/NullObject.d.ts.map +1 -0
- package/dist/lib/NullObject.js +3 -0
- package/dist/lib/Plan.d.ts +2 -1
- package/dist/lib/Plan.d.ts.map +1 -0
- package/dist/lib/Plan.js +44 -62
- package/dist/lib/ValidationError.d.ts +2 -1
- package/dist/lib/ValidationError.d.ts.map +1 -0
- package/dist/lib/ValidationError.js +3 -11
- package/dist/lib/ValidatorFactory.d.ts +5 -6
- package/dist/lib/ValidatorFactory.d.ts.map +1 -0
- package/dist/lib/ValidatorFactory.js +4 -12
- package/dist/lib/configuration-ingestor.d.ts +10 -22
- package/dist/lib/configuration-ingestor.d.ts.map +1 -0
- package/dist/lib/configuration-ingestor.js +61 -143
- package/dist/lib/configure.d.ts +2 -1
- package/dist/lib/configure.d.ts.map +1 -0
- package/dist/lib/configure.js +40 -52
- package/dist/lib/constants.d.ts +1 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +8 -12
- package/dist/lib/context-id-generators.d.ts +1 -0
- package/dist/lib/context-id-generators.d.ts.map +1 -0
- package/dist/lib/context-id-generators.js +4 -9
- package/dist/lib/end-session.d.ts +2 -1
- package/dist/lib/end-session.d.ts.map +1 -0
- package/dist/lib/end-session.js +4 -11
- package/dist/lib/field.d.ts +2 -1
- package/dist/lib/field.d.ts.map +1 -0
- package/dist/lib/field.js +11 -21
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +13 -65
- package/dist/lib/logger.d.ts +25 -2
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +18 -9
- package/dist/lib/mount.d.ts +1 -0
- package/dist/lib/mount.d.ts.map +1 -0
- package/dist/lib/mount.js +10 -16
- package/dist/lib/nunjucks-filters.d.ts +7 -3
- package/dist/lib/nunjucks-filters.d.ts.map +1 -0
- package/dist/lib/nunjucks-filters.js +58 -71
- package/dist/lib/nunjucks.d.ts +4 -4
- package/dist/lib/nunjucks.d.ts.map +1 -0
- package/dist/lib/nunjucks.js +14 -26
- package/dist/lib/utils.d.ts +4 -2
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +14 -28
- package/dist/lib/validators/dateObject.d.ts +1 -0
- package/dist/lib/validators/dateObject.d.ts.map +1 -0
- package/dist/lib/validators/dateObject.js +14 -21
- package/dist/lib/validators/email.d.ts +1 -0
- package/dist/lib/validators/email.d.ts.map +1 -0
- package/dist/lib/validators/email.js +8 -15
- package/dist/lib/validators/inArray.d.ts +1 -0
- package/dist/lib/validators/inArray.d.ts.map +1 -0
- package/dist/lib/validators/inArray.js +8 -15
- package/dist/lib/validators/index.d.ts +1 -0
- package/dist/lib/validators/index.d.ts.map +1 -0
- package/dist/lib/validators/index.js +21 -27
- package/dist/lib/validators/nino.d.ts +1 -0
- package/dist/lib/validators/nino.d.ts.map +1 -0
- package/dist/lib/validators/nino.js +6 -13
- package/dist/lib/validators/postalAddressObject.d.ts +1 -0
- package/dist/lib/validators/postalAddressObject.d.ts.map +1 -0
- package/dist/lib/validators/postalAddressObject.js +12 -19
- package/dist/lib/validators/range.d.ts +1 -0
- package/dist/lib/validators/range.d.ts.map +1 -0
- package/dist/lib/validators/range.js +6 -13
- package/dist/lib/validators/regex.d.ts +1 -0
- package/dist/lib/validators/regex.d.ts.map +1 -0
- package/dist/lib/validators/regex.js +6 -13
- package/dist/lib/validators/required.d.ts +1 -0
- package/dist/lib/validators/required.d.ts.map +1 -0
- package/dist/lib/validators/required.js +9 -17
- package/dist/lib/validators/strlen.d.ts +1 -0
- package/dist/lib/validators/strlen.d.ts.map +1 -0
- package/dist/lib/validators/strlen.js +6 -13
- package/dist/lib/validators/wordCount.d.ts +1 -0
- package/dist/lib/validators/wordCount.d.ts.map +1 -0
- package/dist/lib/validators/wordCount.js +6 -13
- package/dist/lib/waypoint-url.d.ts +3 -2
- package/dist/lib/waypoint-url.d.ts.map +1 -0
- package/dist/lib/waypoint-url.js +12 -19
- package/dist/middleware/body-parser.d.ts +1 -0
- package/dist/middleware/body-parser.d.ts.map +1 -0
- package/dist/middleware/body-parser.js +4 -9
- package/dist/middleware/csrf.d.ts +1 -0
- package/dist/middleware/csrf.d.ts.map +1 -0
- package/dist/middleware/csrf.js +4 -8
- package/dist/middleware/data.d.ts +2 -3
- package/dist/middleware/data.d.ts.map +1 -0
- package/dist/middleware/data.js +23 -25
- package/dist/middleware/gather-fields.d.ts +3 -1
- package/dist/middleware/gather-fields.d.ts.map +1 -0
- package/dist/middleware/gather-fields.js +13 -14
- package/dist/middleware/i18n.d.ts +1 -0
- package/dist/middleware/i18n.d.ts.map +1 -0
- package/dist/middleware/i18n.js +26 -31
- package/dist/middleware/post.d.ts +4 -2
- package/dist/middleware/post.d.ts.map +1 -0
- package/dist/middleware/post.js +6 -11
- package/dist/middleware/pre.d.ts +2 -1
- package/dist/middleware/pre.d.ts.map +1 -0
- package/dist/middleware/pre.js +6 -12
- package/dist/middleware/progress-journey.d.ts +5 -3
- package/dist/middleware/progress-journey.d.ts.map +1 -0
- package/dist/middleware/progress-journey.js +20 -18
- package/dist/middleware/sanitise-fields.d.ts +5 -3
- package/dist/middleware/sanitise-fields.d.ts.map +1 -0
- package/dist/middleware/sanitise-fields.js +25 -17
- package/dist/middleware/serve-first-waypoint.d.ts +1 -0
- package/dist/middleware/serve-first-waypoint.d.ts.map +1 -0
- package/dist/middleware/serve-first-waypoint.js +3 -6
- package/dist/middleware/session.d.ts +15 -0
- package/dist/middleware/session.d.ts.map +1 -0
- package/dist/middleware/session.js +53 -57
- package/dist/middleware/skip-waypoint.d.ts +3 -2
- package/dist/middleware/skip-waypoint.d.ts.map +1 -0
- package/dist/middleware/skip-waypoint.js +15 -14
- package/dist/middleware/steer-journey.d.ts +2 -1
- package/dist/middleware/steer-journey.d.ts.map +1 -0
- package/dist/middleware/steer-journey.js +7 -13
- package/dist/middleware/strip-proxy-path.d.ts +3 -2
- package/dist/middleware/strip-proxy-path.d.ts.map +1 -0
- package/dist/middleware/strip-proxy-path.js +24 -24
- package/dist/middleware/validate-fields.d.ts +7 -4
- package/dist/middleware/validate-fields.d.ts.map +1 -0
- package/dist/middleware/validate-fields.js +22 -11
- package/dist/routes/ancillary.d.ts +1 -0
- package/dist/routes/ancillary.d.ts.map +1 -0
- package/dist/routes/ancillary.js +3 -10
- package/dist/routes/journey.d.ts +7 -2
- package/dist/routes/journey.d.ts.map +1 -0
- package/dist/routes/journey.js +56 -55
- package/dist/routes/static.d.ts +1 -0
- package/dist/routes/static.d.ts.map +1 -0
- package/dist/routes/static.js +15 -23
- package/package.json +30 -36
- package/src/casa.js +63 -31
- package/src/core-plugins/edit-snapshot/src/post-steer-hook.js +1 -0
- package/src/core-plugins/edit-snapshot/src/pre-steer-hook.js +2 -1
- package/src/core-plugins/edit-snapshot/src/utils.js +29 -1
- package/src/lib/JourneyContext.js +31 -28
- package/src/lib/MutableRouter.js +52 -38
- package/src/lib/NullObject.js +4 -0
- package/src/lib/Plan.js +41 -55
- package/src/lib/ValidationError.js +2 -4
- package/src/lib/ValidatorFactory.js +3 -5
- package/src/lib/configuration-ingestor.js +18 -38
- package/src/lib/configure.js +7 -10
- package/src/lib/end-session.js +1 -1
- package/src/lib/field.js +7 -12
- package/src/lib/logger.js +16 -0
- package/src/lib/mount.js +1 -1
- package/src/lib/nunjucks-filters.js +51 -61
- package/src/lib/nunjucks.js +5 -13
- package/src/lib/utils.js +2 -1
- package/src/lib/validators/dateObject.js +3 -4
- package/src/lib/validators/postalAddressObject.js +6 -7
- package/src/lib/validators/required.js +1 -3
- package/src/lib/waypoint-url.js +15 -19
- package/src/middleware/csrf.js +1 -1
- package/src/middleware/data.js +13 -13
- package/src/middleware/gather-fields.js +8 -2
- package/src/middleware/i18n.js +9 -6
- package/src/middleware/post.js +3 -1
- package/src/middleware/pre.js +1 -1
- package/src/middleware/progress-journey.js +8 -0
- package/src/middleware/sanitise-fields.js +17 -2
- package/src/middleware/session.js +53 -12
- package/src/middleware/skip-waypoint.js +8 -1
- package/src/middleware/steer-journey.js +1 -1
- package/src/middleware/strip-proxy-path.js +21 -16
- package/src/middleware/validate-fields.js +19 -0
- package/src/routes/journey.js +18 -8
- package/src/routes/static.js +5 -4
- package/views/casa/layouts/journey.njk +1 -1
- package/views/casa/layouts/main.njk +11 -21
- package/dist/casa.js.map +0 -1
- package/dist/core-plugins/edit-snapshot/src/configure.js.map +0 -1
- package/dist/core-plugins/edit-snapshot/src/index.js.map +0 -1
- package/dist/core-plugins/edit-snapshot/src/post-steer-hook.js.map +0 -1
- package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.js.map +0 -1
- package/dist/core-plugins/edit-snapshot/src/utils.js.map +0 -1
- package/dist/core-plugins/index.js.map +0 -1
- package/dist/lib/CasaTemplateLoader.js.map +0 -1
- package/dist/lib/JourneyContext.js.map +0 -1
- package/dist/lib/MutableRouter.js.map +0 -1
- package/dist/lib/Plan.js.map +0 -1
- package/dist/lib/ValidationError.js.map +0 -1
- package/dist/lib/ValidatorFactory.js.map +0 -1
- package/dist/lib/configuration-ingestor.js.map +0 -1
- package/dist/lib/configure.js.map +0 -1
- package/dist/lib/constants.js.map +0 -1
- package/dist/lib/context-id-generators.js.map +0 -1
- package/dist/lib/dirname.cjs +0 -1
- package/dist/lib/dirname.d.cts +0 -2
- package/dist/lib/end-session.js.map +0 -1
- package/dist/lib/field.js.map +0 -1
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/logger.js.map +0 -1
- package/dist/lib/mount.js.map +0 -1
- package/dist/lib/nunjucks-filters.js.map +0 -1
- package/dist/lib/nunjucks.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
- package/dist/lib/validators/dateObject.js.map +0 -1
- package/dist/lib/validators/email.js.map +0 -1
- package/dist/lib/validators/inArray.js.map +0 -1
- package/dist/lib/validators/index.js.map +0 -1
- package/dist/lib/validators/nino.js.map +0 -1
- package/dist/lib/validators/postalAddressObject.js.map +0 -1
- package/dist/lib/validators/range.js.map +0 -1
- package/dist/lib/validators/regex.js.map +0 -1
- package/dist/lib/validators/required.js.map +0 -1
- package/dist/lib/validators/strlen.js.map +0 -1
- package/dist/lib/validators/wordCount.js.map +0 -1
- package/dist/lib/waypoint-url.js.map +0 -1
- package/dist/middleware/body-parser.js.map +0 -1
- package/dist/middleware/csrf.js.map +0 -1
- package/dist/middleware/data.js.map +0 -1
- package/dist/middleware/dirname.cjs +0 -1
- package/dist/middleware/dirname.d.cts +0 -2
- package/dist/middleware/gather-fields.js.map +0 -1
- package/dist/middleware/i18n.js.map +0 -1
- package/dist/middleware/post.js.map +0 -1
- package/dist/middleware/pre.js.map +0 -1
- package/dist/middleware/progress-journey.js.map +0 -1
- package/dist/middleware/sanitise-fields.js.map +0 -1
- package/dist/middleware/serve-first-waypoint.js.map +0 -1
- package/dist/middleware/session.js.map +0 -1
- package/dist/middleware/skip-waypoint.js.map +0 -1
- package/dist/middleware/steer-journey.js.map +0 -1
- package/dist/middleware/strip-proxy-path.js.map +0 -1
- package/dist/middleware/validate-fields.js.map +0 -1
- package/dist/mjs/esm-wrapper.js +0 -20
- package/dist/mjs/package.json +0 -3
- package/dist/package.json +0 -3
- package/dist/routes/ancillary.js.map +0 -1
- package/dist/routes/dirname.cjs +0 -1
- package/dist/routes/dirname.d.cts +0 -2
- package/dist/routes/journey.js.map +0 -1
- package/dist/routes/static.js.map +0 -1
- package/src/lib/dirname.cjs +0 -1
- package/src/middleware/dirname.cjs +0 -1
- package/src/routes/dirname.cjs +0 -1
package/src/lib/Plan.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Graph } from "@dagrejs/graphlib";
|
|
2
2
|
import JourneyContext from "./JourneyContext.js";
|
|
3
|
+
import NullObject from "./NullObject.js";
|
|
3
4
|
import logger from "./logger.js";
|
|
4
5
|
|
|
5
6
|
const log = logger("lib:plan");
|
|
@@ -140,18 +141,26 @@ const makeRouteObject = (dgraph, edge) => {
|
|
|
140
141
|
*/
|
|
141
142
|
const reExitNodeProtocol = /^[a-z]+:\/\//i;
|
|
142
143
|
|
|
143
|
-
/**
|
|
144
|
-
* For storing private properties for each instance
|
|
145
|
-
*
|
|
146
|
-
* @access private
|
|
147
|
-
* @todo Use property private class properties.
|
|
148
|
-
*/
|
|
149
|
-
const priv = new WeakMap();
|
|
150
|
-
|
|
151
|
-
/** @memberof module:@dwp/govuk-casa */
|
|
144
|
+
/** @memberof module:"@dwp/govuk-casa" */
|
|
152
145
|
export default class Plan {
|
|
146
|
+
/** @type {graphlib.Graph} - This is our directed, multigraph representation */
|
|
147
|
+
#dgraph = new Graph({
|
|
148
|
+
directed: true,
|
|
149
|
+
multigraph: true,
|
|
150
|
+
compound: false,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
153
|
/** @type {string[]} These Waypoints can be skipped */
|
|
154
|
-
#skippableWaypoints;
|
|
154
|
+
#skippableWaypoints = [];
|
|
155
|
+
|
|
156
|
+
/** @type {{ next: object; previous: object }} */
|
|
157
|
+
#follows = {
|
|
158
|
+
next: {},
|
|
159
|
+
prev: {},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/** @type {PlanConstructorOptions} */
|
|
163
|
+
#options;
|
|
155
164
|
|
|
156
165
|
/**
|
|
157
166
|
* Waypoints using the url:// protocol are known as "exit nodes" as they
|
|
@@ -170,16 +179,9 @@ export default class Plan {
|
|
|
170
179
|
* @param {PlanConstructorOptions} opts Options
|
|
171
180
|
*/
|
|
172
181
|
constructor(opts = {}) {
|
|
173
|
-
// This is our directed, multigraph representation
|
|
174
|
-
const dgraph = new Graph({
|
|
175
|
-
directed: true,
|
|
176
|
-
multigraph: true,
|
|
177
|
-
compound: false,
|
|
178
|
-
});
|
|
179
|
-
|
|
180
182
|
// Gather options
|
|
181
183
|
const options = Object.assign(
|
|
182
|
-
|
|
184
|
+
new NullObject(),
|
|
183
185
|
{
|
|
184
186
|
// When true, the validation state of the source node must be `null` (i.e.
|
|
185
187
|
// no validation errors) before any custom route conditions are evaluated.
|
|
@@ -191,17 +193,7 @@ export default class Plan {
|
|
|
191
193
|
opts,
|
|
192
194
|
);
|
|
193
195
|
Object.freeze(options);
|
|
194
|
-
|
|
195
|
-
priv.set(this, {
|
|
196
|
-
dgraph,
|
|
197
|
-
follows: {
|
|
198
|
-
next: {},
|
|
199
|
-
prev: {},
|
|
200
|
-
},
|
|
201
|
-
options,
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
this.#skippableWaypoints = [];
|
|
196
|
+
this.#options = options;
|
|
205
197
|
}
|
|
206
198
|
|
|
207
199
|
/**
|
|
@@ -210,7 +202,7 @@ export default class Plan {
|
|
|
210
202
|
* @returns {PlanConstructorOptions} Options map
|
|
211
203
|
*/
|
|
212
204
|
getOptions() {
|
|
213
|
-
return
|
|
205
|
+
return this.#options;
|
|
214
206
|
}
|
|
215
207
|
|
|
216
208
|
/**
|
|
@@ -249,7 +241,7 @@ export default class Plan {
|
|
|
249
241
|
* @returns {string[]} List of waypoints
|
|
250
242
|
*/
|
|
251
243
|
getWaypoints() {
|
|
252
|
-
return
|
|
244
|
+
return this.#dgraph.nodes();
|
|
253
245
|
}
|
|
254
246
|
|
|
255
247
|
/**
|
|
@@ -268,10 +260,9 @@ export default class Plan {
|
|
|
268
260
|
* @returns {PlanRoute[]} Routes
|
|
269
261
|
*/
|
|
270
262
|
getRoutes() {
|
|
271
|
-
|
|
272
|
-
return self.dgraph
|
|
263
|
+
return this.#dgraph
|
|
273
264
|
.edges()
|
|
274
|
-
.map((edge) => makeRouteObject(
|
|
265
|
+
.map((edge) => makeRouteObject(this.#dgraph, edge));
|
|
275
266
|
}
|
|
276
267
|
|
|
277
268
|
/**
|
|
@@ -283,7 +274,7 @@ export default class Plan {
|
|
|
283
274
|
* @returns {PlanRouteCondition} Route condition function
|
|
284
275
|
*/
|
|
285
276
|
getRouteCondition(src, tgt, name) {
|
|
286
|
-
return
|
|
277
|
+
return this.#follows[validateRouteName(name)][`${src}/${tgt}`];
|
|
287
278
|
}
|
|
288
279
|
|
|
289
280
|
/**
|
|
@@ -295,10 +286,9 @@ export default class Plan {
|
|
|
295
286
|
* @returns {PlanRoute[]} Route objects found.
|
|
296
287
|
*/
|
|
297
288
|
getOutwardRoutes(src, tgt = null) {
|
|
298
|
-
|
|
299
|
-
return self.dgraph
|
|
289
|
+
return this.#dgraph
|
|
300
290
|
.outEdges(src, tgt)
|
|
301
|
-
.map((e) => makeRouteObject(
|
|
291
|
+
.map((e) => makeRouteObject(this.#dgraph, e));
|
|
302
292
|
}
|
|
303
293
|
|
|
304
294
|
/**
|
|
@@ -421,8 +411,6 @@ export default class Plan {
|
|
|
421
411
|
* @throws {Error} If attempting to create a "next" route from an exit node
|
|
422
412
|
*/
|
|
423
413
|
setNamedRoute(src, tgt, name, follow) {
|
|
424
|
-
const self = priv.get(this);
|
|
425
|
-
|
|
426
414
|
// Validate
|
|
427
415
|
validateWaypointId(src);
|
|
428
416
|
validateWaypointId(tgt);
|
|
@@ -435,7 +423,7 @@ export default class Plan {
|
|
|
435
423
|
const conditionName = follow && follow.name;
|
|
436
424
|
|
|
437
425
|
// Warn if we're overwriting an existing edge on the same name
|
|
438
|
-
if (
|
|
426
|
+
if (this.#dgraph.hasEdge(src, tgt, name)) {
|
|
439
427
|
log.warn(
|
|
440
428
|
"Setting a route that already exists (%s, %s, %s). Will be overridden",
|
|
441
429
|
src,
|
|
@@ -443,12 +431,12 @@ export default class Plan {
|
|
|
443
431
|
name,
|
|
444
432
|
);
|
|
445
433
|
}
|
|
446
|
-
|
|
434
|
+
this.#dgraph.setEdge(src, tgt, { conditionName }, name);
|
|
447
435
|
|
|
448
436
|
// Determine which follow function to use
|
|
449
437
|
let followFunc;
|
|
450
438
|
if (follow) {
|
|
451
|
-
if (!
|
|
439
|
+
if (!this.#options.validateBeforeRouteCondition) {
|
|
452
440
|
followFunc = follow;
|
|
453
441
|
} else if (name === "next") {
|
|
454
442
|
// Retain the original function name of route condition
|
|
@@ -469,7 +457,7 @@ export default class Plan {
|
|
|
469
457
|
|
|
470
458
|
// ESLint disabled as `name` has been validated further above
|
|
471
459
|
/* eslint-disable-next-line security/detect-object-injection */
|
|
472
|
-
|
|
460
|
+
this.#follows[name][`${src}/${tgt}`] = followFunc;
|
|
473
461
|
|
|
474
462
|
return this;
|
|
475
463
|
}
|
|
@@ -533,17 +521,15 @@ export default class Plan {
|
|
|
533
521
|
);
|
|
534
522
|
}
|
|
535
523
|
|
|
536
|
-
const self = priv.get(this);
|
|
537
|
-
|
|
538
524
|
/** @type {PlanTraverseOptions} */
|
|
539
525
|
const {
|
|
540
526
|
startWaypoint = this.getWaypoints()[0],
|
|
541
527
|
stopCondition = () => false,
|
|
542
|
-
arbiter =
|
|
528
|
+
arbiter = this.#options.arbiter,
|
|
543
529
|
routeName,
|
|
544
530
|
} = options;
|
|
545
531
|
|
|
546
|
-
if (!
|
|
532
|
+
if (!this.#dgraph.hasNode(startWaypoint)) {
|
|
547
533
|
throw new ReferenceError(
|
|
548
534
|
`Plan does not contain waypoint '${startWaypoint}'`,
|
|
549
535
|
);
|
|
@@ -554,15 +540,15 @@ export default class Plan {
|
|
|
554
540
|
const history = new Map();
|
|
555
541
|
|
|
556
542
|
const traverse = (startWP) => {
|
|
557
|
-
let target =
|
|
543
|
+
let target = this.#dgraph.outEdges(startWP).filter((e) => {
|
|
558
544
|
if (e.name !== routeName) {
|
|
559
545
|
return false;
|
|
560
546
|
}
|
|
561
|
-
const route = makeRouteObject(
|
|
547
|
+
const route = makeRouteObject(this.#dgraph, e);
|
|
562
548
|
try {
|
|
563
549
|
// ESLint disabled as `routeName` has been validated further above
|
|
564
550
|
/* eslint-disable-next-line security/detect-object-injection */
|
|
565
|
-
return
|
|
551
|
+
return this.#follows[routeName][`${e.v}/${e.w}`](route, context);
|
|
566
552
|
} catch (ex) {
|
|
567
553
|
log.warn(
|
|
568
554
|
'Route follow function threw an exception, "%s" (%s)',
|
|
@@ -593,7 +579,7 @@ export default class Plan {
|
|
|
593
579
|
// Convert to routeObject and back to edge object so that only the
|
|
594
580
|
// routeObject is used in the public API
|
|
595
581
|
target = arbiter({
|
|
596
|
-
targets: target.map((t) => makeRouteObject(
|
|
582
|
+
targets: target.map((t) => makeRouteObject(this.#dgraph, t)),
|
|
597
583
|
journeyContext: context,
|
|
598
584
|
travereOptions: options,
|
|
599
585
|
});
|
|
@@ -609,7 +595,7 @@ export default class Plan {
|
|
|
609
595
|
}
|
|
610
596
|
|
|
611
597
|
if (target.length === 1) {
|
|
612
|
-
const route = makeRouteObject(
|
|
598
|
+
const route = makeRouteObject(this.#dgraph, target[0]);
|
|
613
599
|
const routeHash = `${route.name}/${route.source}/${route.target}`;
|
|
614
600
|
|
|
615
601
|
if (stopCondition(route)) {
|
|
@@ -637,7 +623,7 @@ export default class Plan {
|
|
|
637
623
|
}
|
|
638
624
|
|
|
639
625
|
return [
|
|
640
|
-
makeRouteObject(
|
|
626
|
+
makeRouteObject(this.#dgraph, {
|
|
641
627
|
v: startWP,
|
|
642
628
|
w: null,
|
|
643
629
|
name: routeName,
|
|
@@ -656,6 +642,6 @@ export default class Plan {
|
|
|
656
642
|
* @returns {Graph} Graph data structure.
|
|
657
643
|
*/
|
|
658
644
|
getGraphStructure() {
|
|
659
|
-
return
|
|
645
|
+
return this.#dgraph;
|
|
660
646
|
}
|
|
661
647
|
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
const { isPlainObject } = lodash; // CommonJS
|
|
1
|
+
import isPlainObject from "is-plain-obj";
|
|
4
2
|
|
|
5
3
|
const params = new WeakMap();
|
|
6
4
|
|
|
@@ -20,7 +18,7 @@ const params = new WeakMap();
|
|
|
20
18
|
*/
|
|
21
19
|
|
|
22
20
|
/**
|
|
23
|
-
* @memberof module
|
|
21
|
+
* @memberof module:"@dwp/govuk-casa"
|
|
24
22
|
* @class
|
|
25
23
|
*/
|
|
26
24
|
export default class ValidationError {
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
const { isPlainObject } = lodash; // CommonJS
|
|
1
|
+
import isPlainObject from "is-plain-obj";
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* @typedef {import("../casa").ErrorMessageConfig} ErrorMessageConfig
|
|
@@ -28,12 +26,12 @@ const { isPlainObject } = lodash; // CommonJS
|
|
|
28
26
|
*/
|
|
29
27
|
|
|
30
28
|
/**
|
|
31
|
-
* @typedef {
|
|
29
|
+
* @typedef {{ [key: string]: unknown }} ValidatorFactoryOptions
|
|
32
30
|
* @property {ErrorMessageConfig} errorMsg Error message
|
|
33
31
|
*/
|
|
34
32
|
|
|
35
33
|
/**
|
|
36
|
-
* @memberof module
|
|
34
|
+
* @memberof module:"@dwp/govuk-casa"
|
|
37
35
|
* @class
|
|
38
36
|
*/
|
|
39
37
|
export default class ValidatorFactory {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import bytes from "bytes";
|
|
2
2
|
import { PageField } from "./field.js";
|
|
3
|
+
import NullObject from "./NullObject.js";
|
|
3
4
|
import Plan from "./Plan.js";
|
|
4
5
|
import logger from "./logger.js";
|
|
5
6
|
import {
|
|
@@ -54,6 +55,11 @@ import {
|
|
|
54
55
|
* @access private
|
|
55
56
|
*/
|
|
56
57
|
|
|
58
|
+
/**
|
|
59
|
+
* @typedef {true | false | "Lax" | "None" | "Strict" | "auto"} CookieSameSite
|
|
60
|
+
* @access private
|
|
61
|
+
*/
|
|
62
|
+
|
|
57
63
|
const log = logger("lib:configuration-ingestor");
|
|
58
64
|
|
|
59
65
|
const echo = (a) => a;
|
|
@@ -67,7 +73,7 @@ const echo = (a) => a;
|
|
|
67
73
|
* @throws {TypeError} For invalid object.
|
|
68
74
|
* @access private
|
|
69
75
|
*/
|
|
70
|
-
export function validateI18nObject(i18n =
|
|
76
|
+
export function validateI18nObject(i18n = new NullObject(), cb = echo) {
|
|
71
77
|
if (Object.prototype.toString.call(i18n) !== "[object Object]") {
|
|
72
78
|
throw new TypeError("I18n must be an object");
|
|
73
79
|
}
|
|
@@ -95,6 +101,7 @@ export function validateI18nDirs(dirs = []) {
|
|
|
95
101
|
`I18n directory must be a string, got ${typeof dir} (i18n.dirs[${i++}])`,
|
|
96
102
|
);
|
|
97
103
|
}
|
|
104
|
+
i++;
|
|
98
105
|
}
|
|
99
106
|
return dirs;
|
|
100
107
|
}
|
|
@@ -120,6 +127,7 @@ export function validateI18nLocales(locales = ["en", "cy"]) {
|
|
|
120
127
|
`I18n locale must be a string, got ${typeof locale} (i18n.locales[${i++}])`,
|
|
121
128
|
);
|
|
122
129
|
}
|
|
130
|
+
i++;
|
|
123
131
|
}
|
|
124
132
|
return locales;
|
|
125
133
|
}
|
|
@@ -179,10 +187,7 @@ export function validateMountUrl(mountUrl) {
|
|
|
179
187
|
* @throws {TypeError} For invalid object.
|
|
180
188
|
* @access private
|
|
181
189
|
*/
|
|
182
|
-
export function validateSessionObject(
|
|
183
|
-
session = Object.create(null),
|
|
184
|
-
cb = echo,
|
|
185
|
-
) {
|
|
190
|
+
export function validateSessionObject(session = new NullObject(), cb = echo) {
|
|
186
191
|
if (session === undefined) {
|
|
187
192
|
return cb(session);
|
|
188
193
|
}
|
|
@@ -215,6 +220,7 @@ export function validateViews(dirs = []) {
|
|
|
215
220
|
`View directory must be a string, got ${typeof dir} (views[${i++}])`,
|
|
216
221
|
);
|
|
217
222
|
}
|
|
223
|
+
i++;
|
|
218
224
|
}
|
|
219
225
|
return dirs;
|
|
220
226
|
}
|
|
@@ -322,17 +328,6 @@ export function validateSessionCookiePath(cookiePath, defaultPath = "/") {
|
|
|
322
328
|
return cookiePath;
|
|
323
329
|
}
|
|
324
330
|
|
|
325
|
-
/**
|
|
326
|
-
* Validates and sanitises sessions cookie "sameSite" flag. One of: true
|
|
327
|
-
* (Strict) false (will not set the flag at all) Strict Lax None
|
|
328
|
-
*
|
|
329
|
-
* @param {any} cookieSameSite Session cookie "sameSite" flag
|
|
330
|
-
* @param {any} defaultFlag Default path if none specified
|
|
331
|
-
* @returns {boolean} Cookie path
|
|
332
|
-
* @throws {TypeError} When invalid arguments are provided
|
|
333
|
-
* @access private
|
|
334
|
-
*/
|
|
335
|
-
|
|
336
331
|
/**
|
|
337
332
|
* Validates errorVisibility.
|
|
338
333
|
*
|
|
@@ -361,9 +356,14 @@ export function validateErrorVisibility(
|
|
|
361
356
|
}
|
|
362
357
|
|
|
363
358
|
/**
|
|
364
|
-
*
|
|
365
|
-
*
|
|
359
|
+
* Validates and sanitises sessions cookie "sameSite" flag. One of: true
|
|
360
|
+
* (Strict) false (will not set the flag at all) Strict Lax None
|
|
361
|
+
*
|
|
362
|
+
* @param {CookieSameSite} cookieSameSite Session cookie "sameSite" flag
|
|
363
|
+
* @param {CookieSameSite} defaultFlag Default value
|
|
366
364
|
* @returns {boolean | string} Validated value
|
|
365
|
+
* @throws {TypeError} When invalid arguments are provided
|
|
366
|
+
* @access private
|
|
367
367
|
*/
|
|
368
368
|
export function validateSessionCookieSameSite(cookieSameSite, defaultFlag) {
|
|
369
369
|
const validValues = [true, false, "Strict", "Lax", "None"];
|
|
@@ -634,24 +634,6 @@ export function validateContextIdGenerator(generator) {
|
|
|
634
634
|
return generator;
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
/**
|
|
638
|
-
* Validates the govuk rebrand feature flag.
|
|
639
|
-
*
|
|
640
|
-
* @param {boolean} [govukRebrand] Govuk rebrand feature flag
|
|
641
|
-
* @returns {boolean | true} Boolean.
|
|
642
|
-
* @throws {TypeError} For invalid feagure flag is set.
|
|
643
|
-
* @access private
|
|
644
|
-
*/
|
|
645
|
-
export function validateGovukRebrand(govukRebrand) {
|
|
646
|
-
if (govukRebrand === undefined) {
|
|
647
|
-
return false;
|
|
648
|
-
}
|
|
649
|
-
if (typeof govukRebrand !== "boolean") {
|
|
650
|
-
throw new TypeError("govukRebrand must be a boolean");
|
|
651
|
-
}
|
|
652
|
-
return govukRebrand;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
637
|
/**
|
|
656
638
|
* Ingest, validate, sanitise and manipulate configuration parameters.
|
|
657
639
|
*
|
|
@@ -716,8 +698,6 @@ export default function ingest(config = {}) {
|
|
|
716
698
|
|
|
717
699
|
// Context ID generator
|
|
718
700
|
contextIdGenerator: validateContextIdGenerator(config.contextIdGenerator),
|
|
719
|
-
|
|
720
|
-
govukRebrand: validateGovukRebrand(config.govukRebrand),
|
|
721
701
|
};
|
|
722
702
|
|
|
723
703
|
// Freeze to modifications
|
package/src/lib/configure.js
CHANGED
|
@@ -2,7 +2,6 @@ import { MemoryStore } from "express-session";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import cookieParserFactory from "cookie-parser";
|
|
5
|
-
import dirname from "./dirname.cjs";
|
|
6
5
|
|
|
7
6
|
import configurationIngestor from "./configuration-ingestor.js";
|
|
8
7
|
import nunjucks from "./nunjucks.js";
|
|
@@ -42,7 +41,7 @@ import { CONFIG_ERROR_VISIBILITY_ONSUBMIT } from "./constants.js";
|
|
|
42
41
|
/**
|
|
43
42
|
* Configure some middleware for use in creating a new CASA app.
|
|
44
43
|
*
|
|
45
|
-
* @memberof module
|
|
44
|
+
* @memberof module:"@dwp/govuk-casa"
|
|
46
45
|
* @param {ConfigurationOptions} config Configuration options
|
|
47
46
|
* @returns {ConfigureResult} Result
|
|
48
47
|
*/
|
|
@@ -81,7 +80,6 @@ export default function configure(config = {}) {
|
|
|
81
80
|
formMaxParams,
|
|
82
81
|
formMaxBytes,
|
|
83
82
|
contextIdGenerator,
|
|
84
|
-
govukRebrand = false,
|
|
85
83
|
} = ingestedConfig;
|
|
86
84
|
|
|
87
85
|
// Prepare all page hooks so they are prefixed with the `journey.` scope.
|
|
@@ -98,10 +96,12 @@ export default function configure(config = {}) {
|
|
|
98
96
|
const nunjucksEnv = nunjucks({
|
|
99
97
|
views: [
|
|
100
98
|
...views,
|
|
101
|
-
resolve(dirname, "../../views"),
|
|
102
|
-
resolve(
|
|
99
|
+
resolve(import.meta.dirname, "../../views"),
|
|
100
|
+
resolve(
|
|
101
|
+
createRequire(import.meta.dirname).resolve("govuk-frontend"),
|
|
102
|
+
"../../",
|
|
103
|
+
),
|
|
103
104
|
],
|
|
104
|
-
govukRebrand,
|
|
105
105
|
});
|
|
106
106
|
|
|
107
107
|
// Prepare mandatory middleware
|
|
@@ -125,7 +125,7 @@ export default function configure(config = {}) {
|
|
|
125
125
|
const i18nMiddleware = i18nMiddlewareFactory({
|
|
126
126
|
directories: [
|
|
127
127
|
// Order is important; latter directories take precedence
|
|
128
|
-
resolve(dirname, "../../locales/"),
|
|
128
|
+
resolve(import.meta.dirname, "../../locales/"),
|
|
129
129
|
...i18n.dirs,
|
|
130
130
|
],
|
|
131
131
|
languages: i18n.locales,
|
|
@@ -135,7 +135,6 @@ export default function configure(config = {}) {
|
|
|
135
135
|
plan,
|
|
136
136
|
events,
|
|
137
137
|
contextIdGenerator,
|
|
138
|
-
govukRebrand,
|
|
139
138
|
});
|
|
140
139
|
|
|
141
140
|
// Prepare form middleware and its constituent parts
|
|
@@ -185,8 +184,6 @@ export default function configure(config = {}) {
|
|
|
185
184
|
// Nunjucks environment, so it can be attached to other ExpressJS instances
|
|
186
185
|
// using `nunjucksEnv.express(myApp); myApp.set('view engine', 'njk');`.
|
|
187
186
|
nunjucksEnv,
|
|
188
|
-
// govuk rebrand flag
|
|
189
|
-
govukRebrand,
|
|
190
187
|
|
|
191
188
|
// Mandatory middleware. User must add these to their ExpressJS app.
|
|
192
189
|
preMiddleware,
|
package/src/lib/end-session.js
CHANGED
|
@@ -10,7 +10,7 @@ const log = logger("lib:end-session");
|
|
|
10
10
|
* Note: this will not remove the session from server-side storage, which will
|
|
11
11
|
* instead be left up to the storage mechanism to clean up.
|
|
12
12
|
*
|
|
13
|
-
* @memberof module
|
|
13
|
+
* @memberof module:"@dwp/govuk-casa"
|
|
14
14
|
* @param {import("express").Request} req HTTP request
|
|
15
15
|
* @param {Function} next Chain
|
|
16
16
|
* @returns {void}
|
package/src/lib/field.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import lodash from "lodash";
|
|
2
1
|
import { isEmpty } from "./utils.js";
|
|
3
|
-
|
|
4
|
-
const { isFunction } = lodash;
|
|
2
|
+
import NullObject from "./NullObject.js";
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* @typedef {import("./index").JourneyContext} JourneyContext
|
|
@@ -71,10 +69,7 @@ export class PageField {
|
|
|
71
69
|
* @param {boolean} [opts.persist] Whether this field will persist in
|
|
72
70
|
* `req.body`. Default is `true`
|
|
73
71
|
*/
|
|
74
|
-
constructor(
|
|
75
|
-
name,
|
|
76
|
-
{ optional = false, persist = true } = Object.create(null),
|
|
77
|
-
) {
|
|
72
|
+
constructor(name, { optional = false, persist = true } = new NullObject()) {
|
|
78
73
|
if (!name) {
|
|
79
74
|
throw new SyntaxError(
|
|
80
75
|
"A name for this field is required, i.e. \"field('myField')\".",
|
|
@@ -132,7 +127,7 @@ export class PageField {
|
|
|
132
127
|
* @param {object} obj Object from which to extract the value
|
|
133
128
|
* @returns {any} Value extracted from object
|
|
134
129
|
*/
|
|
135
|
-
getValue(obj =
|
|
130
|
+
getValue(obj = new NullObject()) {
|
|
136
131
|
if (this.#meta.complex) {
|
|
137
132
|
return obj[this.#meta.complexFieldName]?.[
|
|
138
133
|
this.#meta.complexFieldProperty
|
|
@@ -151,7 +146,7 @@ export class PageField {
|
|
|
151
146
|
* @param {any} value Value to be stored
|
|
152
147
|
* @returns {any} Value extracted from object
|
|
153
148
|
*/
|
|
154
|
-
putValue(obj =
|
|
149
|
+
putValue(obj = new NullObject(), value = undefined) {
|
|
155
150
|
if (this.#meta.complex) {
|
|
156
151
|
obj[this.#meta.complexFieldName] = {
|
|
157
152
|
...(obj[this.#meta.complexFieldName] ?? {}),
|
|
@@ -298,7 +293,7 @@ export class PageField {
|
|
|
298
293
|
* @returns {ValidationError[]} Errors, or an empty array if all valid
|
|
299
294
|
* @throws {TypeError} If validator does not return an array
|
|
300
295
|
*/
|
|
301
|
-
runValidators(context =
|
|
296
|
+
runValidators(context = new NullObject()) {
|
|
302
297
|
// Skip validation if the field is empty and optional
|
|
303
298
|
if (this.#meta.optional && isEmpty(context?.fieldValue)) {
|
|
304
299
|
return [];
|
|
@@ -352,7 +347,7 @@ export class PageField {
|
|
|
352
347
|
// ESLint disabled as `i` is an integer
|
|
353
348
|
/* eslint-disable security/detect-object-injection */
|
|
354
349
|
for (let i = 0, l = this.#validators.length; i < l; i++) {
|
|
355
|
-
if (
|
|
350
|
+
if (this.#validators[i].sanitise instanceof Function) {
|
|
356
351
|
processedValue = this.#validators[i].sanitise(processedValue);
|
|
357
352
|
}
|
|
358
353
|
}
|
|
@@ -435,7 +430,7 @@ export class PageField {
|
|
|
435
430
|
/**
|
|
436
431
|
* Factory for creating PageField instances.
|
|
437
432
|
*
|
|
438
|
-
* @memberof module
|
|
433
|
+
* @memberof module:"@dwp/govuk-casa"
|
|
439
434
|
* @param {string} name Field name
|
|
440
435
|
* @param {object} [opts] Options
|
|
441
436
|
* @param {boolean} [opts.optional] Whether this field is optional. Default is
|
package/src/lib/logger.js
CHANGED
|
@@ -2,6 +2,12 @@ import debug from "debug";
|
|
|
2
2
|
|
|
3
3
|
const casaDebugger = debug("casa");
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Get a debug logger for a given namespace
|
|
7
|
+
*
|
|
8
|
+
* @param {string} namespace Debug log namespace
|
|
9
|
+
* @returns {CASADebugLogger} CASA Debug logger
|
|
10
|
+
*/
|
|
5
11
|
export default (namespace) => {
|
|
6
12
|
const logger = casaDebugger.extend(namespace);
|
|
7
13
|
|
|
@@ -14,3 +20,13 @@ export default (namespace) => {
|
|
|
14
20
|
fatal: logger.extend("fatal"),
|
|
15
21
|
};
|
|
16
22
|
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {object} CASADebugLogger CASA Debug logger
|
|
26
|
+
* @property {debug.Debugger} trace Trace level logger
|
|
27
|
+
* @property {debug.Debugger} debug Debug level logger
|
|
28
|
+
* @property {debug.Debugger} info Info level logger
|
|
29
|
+
* @property {debug.Debugger} warn Warn level logger
|
|
30
|
+
* @property {debug.Debugger} error Error level logger
|
|
31
|
+
* @property {debug.Debugger} fatal Fatal level logger
|
|
32
|
+
*/
|
package/src/lib/mount.js
CHANGED
|
@@ -103,9 +103,9 @@ export default ({
|
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
router.use(preMiddleware);
|
|
106
|
+
router.use(bodyParserMiddleware);
|
|
106
107
|
router.use(sessionMiddleware);
|
|
107
108
|
router.use(i18nMiddleware);
|
|
108
|
-
router.use(bodyParserMiddleware);
|
|
109
109
|
router.use(dataMiddleware);
|
|
110
110
|
router.use(ancillaryRouter.seal());
|
|
111
111
|
router.use(journeyRouter.seal());
|