@dwp/govuk-casa 9.7.0 → 10.0.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.
Files changed (277) hide show
  1. package/dist/assets/css/casa.css +1 -1
  2. package/dist/assets/css/casa.css.map +1 -1
  3. package/dist/casa.d.ts +81 -41
  4. package/dist/casa.d.ts.map +1 -0
  5. package/dist/casa.js +72 -99
  6. package/dist/core-plugins/edit-snapshot/src/configure.d.ts +1 -0
  7. package/dist/core-plugins/edit-snapshot/src/configure.d.ts.map +1 -0
  8. package/dist/core-plugins/edit-snapshot/src/configure.js +7 -14
  9. package/dist/core-plugins/edit-snapshot/src/index.d.ts +1 -0
  10. package/dist/core-plugins/edit-snapshot/src/index.d.ts.map +1 -0
  11. package/dist/core-plugins/edit-snapshot/src/index.js +3 -9
  12. package/dist/core-plugins/edit-snapshot/src/post-steer-hook.d.ts +2 -1
  13. package/dist/core-plugins/edit-snapshot/src/post-steer-hook.d.ts.map +1 -0
  14. package/dist/core-plugins/edit-snapshot/src/post-steer-hook.js +8 -13
  15. package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.d.ts +2 -1
  16. package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.d.ts.map +1 -0
  17. package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.js +13 -18
  18. package/dist/core-plugins/edit-snapshot/src/utils.d.ts +8 -5
  19. package/dist/core-plugins/edit-snapshot/src/utils.d.ts.map +1 -0
  20. package/dist/core-plugins/edit-snapshot/src/utils.js +37 -19
  21. package/dist/core-plugins/index.d.ts +1 -0
  22. package/dist/core-plugins/index.d.ts.map +1 -0
  23. package/dist/core-plugins/index.js +1 -9
  24. package/dist/lib/CasaTemplateLoader.d.ts +1 -0
  25. package/dist/lib/CasaTemplateLoader.d.ts.map +1 -0
  26. package/dist/lib/CasaTemplateLoader.js +2 -6
  27. package/dist/lib/JourneyContext.d.ts +22 -11
  28. package/dist/lib/JourneyContext.d.ts.map +1 -0
  29. package/dist/lib/JourneyContext.js +40 -45
  30. package/dist/lib/MutableRouter.d.ts +74 -55
  31. package/dist/lib/MutableRouter.d.ts.map +1 -0
  32. package/dist/lib/MutableRouter.js +48 -45
  33. package/dist/lib/NullObject.d.ts +3 -0
  34. package/dist/lib/NullObject.d.ts.map +1 -0
  35. package/dist/lib/NullObject.js +3 -0
  36. package/dist/lib/Plan.d.ts +2 -1
  37. package/dist/lib/Plan.d.ts.map +1 -0
  38. package/dist/lib/Plan.js +44 -62
  39. package/dist/lib/ValidationError.d.ts +2 -1
  40. package/dist/lib/ValidationError.d.ts.map +1 -0
  41. package/dist/lib/ValidationError.js +3 -11
  42. package/dist/lib/ValidatorFactory.d.ts +5 -6
  43. package/dist/lib/ValidatorFactory.d.ts.map +1 -0
  44. package/dist/lib/ValidatorFactory.js +4 -12
  45. package/dist/lib/configuration-ingestor.d.ts +10 -22
  46. package/dist/lib/configuration-ingestor.d.ts.map +1 -0
  47. package/dist/lib/configuration-ingestor.js +61 -143
  48. package/dist/lib/configure.d.ts +2 -1
  49. package/dist/lib/configure.d.ts.map +1 -0
  50. package/dist/lib/configure.js +40 -52
  51. package/dist/lib/constants.d.ts +1 -0
  52. package/dist/lib/constants.d.ts.map +1 -0
  53. package/dist/lib/constants.js +8 -12
  54. package/dist/lib/context-id-generators.d.ts +1 -0
  55. package/dist/lib/context-id-generators.d.ts.map +1 -0
  56. package/dist/lib/context-id-generators.js +4 -9
  57. package/dist/lib/end-session.d.ts +2 -1
  58. package/dist/lib/end-session.d.ts.map +1 -0
  59. package/dist/lib/end-session.js +4 -11
  60. package/dist/lib/field.d.ts +2 -1
  61. package/dist/lib/field.d.ts.map +1 -0
  62. package/dist/lib/field.js +11 -21
  63. package/dist/lib/index.d.ts +1 -0
  64. package/dist/lib/index.d.ts.map +1 -0
  65. package/dist/lib/index.js +13 -65
  66. package/dist/lib/logger.d.ts +25 -2
  67. package/dist/lib/logger.d.ts.map +1 -0
  68. package/dist/lib/logger.js +18 -9
  69. package/dist/lib/mount.d.ts +1 -0
  70. package/dist/lib/mount.d.ts.map +1 -0
  71. package/dist/lib/mount.js +10 -16
  72. package/dist/lib/nunjucks-filters.d.ts +7 -3
  73. package/dist/lib/nunjucks-filters.d.ts.map +1 -0
  74. package/dist/lib/nunjucks-filters.js +58 -71
  75. package/dist/lib/nunjucks.d.ts +2 -2
  76. package/dist/lib/nunjucks.d.ts.map +1 -0
  77. package/dist/lib/nunjucks.js +12 -25
  78. package/dist/lib/utils.d.ts +4 -2
  79. package/dist/lib/utils.d.ts.map +1 -0
  80. package/dist/lib/utils.js +14 -28
  81. package/dist/lib/validators/dateObject.d.ts +1 -0
  82. package/dist/lib/validators/dateObject.d.ts.map +1 -0
  83. package/dist/lib/validators/dateObject.js +14 -21
  84. package/dist/lib/validators/email.d.ts +1 -0
  85. package/dist/lib/validators/email.d.ts.map +1 -0
  86. package/dist/lib/validators/email.js +8 -15
  87. package/dist/lib/validators/inArray.d.ts +1 -0
  88. package/dist/lib/validators/inArray.d.ts.map +1 -0
  89. package/dist/lib/validators/inArray.js +8 -15
  90. package/dist/lib/validators/index.d.ts +1 -0
  91. package/dist/lib/validators/index.d.ts.map +1 -0
  92. package/dist/lib/validators/index.js +21 -27
  93. package/dist/lib/validators/nino.d.ts +1 -0
  94. package/dist/lib/validators/nino.d.ts.map +1 -0
  95. package/dist/lib/validators/nino.js +6 -13
  96. package/dist/lib/validators/postalAddressObject.d.ts +1 -0
  97. package/dist/lib/validators/postalAddressObject.d.ts.map +1 -0
  98. package/dist/lib/validators/postalAddressObject.js +12 -19
  99. package/dist/lib/validators/range.d.ts +1 -0
  100. package/dist/lib/validators/range.d.ts.map +1 -0
  101. package/dist/lib/validators/range.js +6 -13
  102. package/dist/lib/validators/regex.d.ts +1 -0
  103. package/dist/lib/validators/regex.d.ts.map +1 -0
  104. package/dist/lib/validators/regex.js +6 -13
  105. package/dist/lib/validators/required.d.ts +1 -0
  106. package/dist/lib/validators/required.d.ts.map +1 -0
  107. package/dist/lib/validators/required.js +9 -17
  108. package/dist/lib/validators/strlen.d.ts +1 -0
  109. package/dist/lib/validators/strlen.d.ts.map +1 -0
  110. package/dist/lib/validators/strlen.js +6 -13
  111. package/dist/lib/validators/wordCount.d.ts +1 -0
  112. package/dist/lib/validators/wordCount.d.ts.map +1 -0
  113. package/dist/lib/validators/wordCount.js +6 -13
  114. package/dist/lib/waypoint-url.d.ts +3 -2
  115. package/dist/lib/waypoint-url.d.ts.map +1 -0
  116. package/dist/lib/waypoint-url.js +12 -19
  117. package/dist/middleware/body-parser.d.ts +1 -0
  118. package/dist/middleware/body-parser.d.ts.map +1 -0
  119. package/dist/middleware/body-parser.js +4 -9
  120. package/dist/middleware/csrf.d.ts +1 -0
  121. package/dist/middleware/csrf.d.ts.map +1 -0
  122. package/dist/middleware/csrf.js +4 -8
  123. package/dist/middleware/data.d.ts +2 -3
  124. package/dist/middleware/data.d.ts.map +1 -0
  125. package/dist/middleware/data.js +23 -25
  126. package/dist/middleware/gather-fields.d.ts +3 -1
  127. package/dist/middleware/gather-fields.d.ts.map +1 -0
  128. package/dist/middleware/gather-fields.js +13 -14
  129. package/dist/middleware/i18n.d.ts +1 -0
  130. package/dist/middleware/i18n.d.ts.map +1 -0
  131. package/dist/middleware/i18n.js +26 -31
  132. package/dist/middleware/post.d.ts +1 -0
  133. package/dist/middleware/post.d.ts.map +1 -0
  134. package/dist/middleware/post.js +3 -10
  135. package/dist/middleware/pre.d.ts +2 -1
  136. package/dist/middleware/pre.d.ts.map +1 -0
  137. package/dist/middleware/pre.js +6 -12
  138. package/dist/middleware/progress-journey.d.ts +5 -3
  139. package/dist/middleware/progress-journey.d.ts.map +1 -0
  140. package/dist/middleware/progress-journey.js +20 -18
  141. package/dist/middleware/sanitise-fields.d.ts +5 -3
  142. package/dist/middleware/sanitise-fields.d.ts.map +1 -0
  143. package/dist/middleware/sanitise-fields.js +25 -17
  144. package/dist/middleware/serve-first-waypoint.d.ts +1 -0
  145. package/dist/middleware/serve-first-waypoint.d.ts.map +1 -0
  146. package/dist/middleware/serve-first-waypoint.js +3 -6
  147. package/dist/middleware/session.d.ts +15 -0
  148. package/dist/middleware/session.d.ts.map +1 -0
  149. package/dist/middleware/session.js +53 -57
  150. package/dist/middleware/skip-waypoint.d.ts +3 -2
  151. package/dist/middleware/skip-waypoint.d.ts.map +1 -0
  152. package/dist/middleware/skip-waypoint.js +15 -14
  153. package/dist/middleware/steer-journey.d.ts +2 -1
  154. package/dist/middleware/steer-journey.d.ts.map +1 -0
  155. package/dist/middleware/steer-journey.js +7 -13
  156. package/dist/middleware/strip-proxy-path.d.ts +3 -2
  157. package/dist/middleware/strip-proxy-path.d.ts.map +1 -0
  158. package/dist/middleware/strip-proxy-path.js +24 -24
  159. package/dist/middleware/validate-fields.d.ts +7 -4
  160. package/dist/middleware/validate-fields.d.ts.map +1 -0
  161. package/dist/middleware/validate-fields.js +22 -11
  162. package/dist/routes/ancillary.d.ts +1 -0
  163. package/dist/routes/ancillary.d.ts.map +1 -0
  164. package/dist/routes/ancillary.js +3 -10
  165. package/dist/routes/journey.d.ts +7 -2
  166. package/dist/routes/journey.d.ts.map +1 -0
  167. package/dist/routes/journey.js +56 -55
  168. package/dist/routes/static.d.ts +1 -0
  169. package/dist/routes/static.d.ts.map +1 -0
  170. package/dist/routes/static.js +15 -23
  171. package/package.json +20 -26
  172. package/src/casa.js +49 -29
  173. package/src/core-plugins/edit-snapshot/src/post-steer-hook.js +1 -0
  174. package/src/core-plugins/edit-snapshot/src/pre-steer-hook.js +2 -1
  175. package/src/core-plugins/edit-snapshot/src/utils.js +29 -1
  176. package/src/lib/JourneyContext.js +31 -28
  177. package/src/lib/MutableRouter.js +47 -38
  178. package/src/lib/NullObject.js +4 -0
  179. package/src/lib/Plan.js +41 -55
  180. package/src/lib/ValidationError.js +2 -4
  181. package/src/lib/ValidatorFactory.js +3 -5
  182. package/src/lib/configuration-ingestor.js +18 -38
  183. package/src/lib/configure.js +7 -10
  184. package/src/lib/end-session.js +1 -1
  185. package/src/lib/field.js +7 -12
  186. package/src/lib/logger.js +16 -0
  187. package/src/lib/mount.js +1 -1
  188. package/src/lib/nunjucks-filters.js +51 -61
  189. package/src/lib/nunjucks.js +3 -12
  190. package/src/lib/utils.js +2 -1
  191. package/src/lib/validators/dateObject.js +3 -4
  192. package/src/lib/validators/postalAddressObject.js +6 -7
  193. package/src/lib/validators/required.js +1 -3
  194. package/src/lib/waypoint-url.js +15 -19
  195. package/src/middleware/csrf.js +1 -1
  196. package/src/middleware/data.js +13 -13
  197. package/src/middleware/gather-fields.js +8 -2
  198. package/src/middleware/i18n.js +9 -6
  199. package/src/middleware/pre.js +1 -1
  200. package/src/middleware/progress-journey.js +8 -0
  201. package/src/middleware/sanitise-fields.js +17 -2
  202. package/src/middleware/session.js +53 -12
  203. package/src/middleware/skip-waypoint.js +8 -1
  204. package/src/middleware/steer-journey.js +1 -1
  205. package/src/middleware/strip-proxy-path.js +21 -16
  206. package/src/middleware/validate-fields.js +19 -0
  207. package/src/routes/journey.js +18 -8
  208. package/src/routes/static.js +5 -4
  209. package/views/casa/layouts/journey.njk +1 -1
  210. package/views/casa/layouts/main.njk +11 -21
  211. package/dist/casa.js.map +0 -1
  212. package/dist/core-plugins/edit-snapshot/src/configure.js.map +0 -1
  213. package/dist/core-plugins/edit-snapshot/src/index.js.map +0 -1
  214. package/dist/core-plugins/edit-snapshot/src/post-steer-hook.js.map +0 -1
  215. package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.js.map +0 -1
  216. package/dist/core-plugins/edit-snapshot/src/utils.js.map +0 -1
  217. package/dist/core-plugins/index.js.map +0 -1
  218. package/dist/lib/CasaTemplateLoader.js.map +0 -1
  219. package/dist/lib/JourneyContext.js.map +0 -1
  220. package/dist/lib/MutableRouter.js.map +0 -1
  221. package/dist/lib/Plan.js.map +0 -1
  222. package/dist/lib/ValidationError.js.map +0 -1
  223. package/dist/lib/ValidatorFactory.js.map +0 -1
  224. package/dist/lib/configuration-ingestor.js.map +0 -1
  225. package/dist/lib/configure.js.map +0 -1
  226. package/dist/lib/constants.js.map +0 -1
  227. package/dist/lib/context-id-generators.js.map +0 -1
  228. package/dist/lib/dirname.cjs +0 -1
  229. package/dist/lib/dirname.d.cts +0 -2
  230. package/dist/lib/end-session.js.map +0 -1
  231. package/dist/lib/field.js.map +0 -1
  232. package/dist/lib/index.js.map +0 -1
  233. package/dist/lib/logger.js.map +0 -1
  234. package/dist/lib/mount.js.map +0 -1
  235. package/dist/lib/nunjucks-filters.js.map +0 -1
  236. package/dist/lib/nunjucks.js.map +0 -1
  237. package/dist/lib/utils.js.map +0 -1
  238. package/dist/lib/validators/dateObject.js.map +0 -1
  239. package/dist/lib/validators/email.js.map +0 -1
  240. package/dist/lib/validators/inArray.js.map +0 -1
  241. package/dist/lib/validators/index.js.map +0 -1
  242. package/dist/lib/validators/nino.js.map +0 -1
  243. package/dist/lib/validators/postalAddressObject.js.map +0 -1
  244. package/dist/lib/validators/range.js.map +0 -1
  245. package/dist/lib/validators/regex.js.map +0 -1
  246. package/dist/lib/validators/required.js.map +0 -1
  247. package/dist/lib/validators/strlen.js.map +0 -1
  248. package/dist/lib/validators/wordCount.js.map +0 -1
  249. package/dist/lib/waypoint-url.js.map +0 -1
  250. package/dist/middleware/body-parser.js.map +0 -1
  251. package/dist/middleware/csrf.js.map +0 -1
  252. package/dist/middleware/data.js.map +0 -1
  253. package/dist/middleware/dirname.cjs +0 -1
  254. package/dist/middleware/dirname.d.cts +0 -2
  255. package/dist/middleware/gather-fields.js.map +0 -1
  256. package/dist/middleware/i18n.js.map +0 -1
  257. package/dist/middleware/post.js.map +0 -1
  258. package/dist/middleware/pre.js.map +0 -1
  259. package/dist/middleware/progress-journey.js.map +0 -1
  260. package/dist/middleware/sanitise-fields.js.map +0 -1
  261. package/dist/middleware/serve-first-waypoint.js.map +0 -1
  262. package/dist/middleware/session.js.map +0 -1
  263. package/dist/middleware/skip-waypoint.js.map +0 -1
  264. package/dist/middleware/steer-journey.js.map +0 -1
  265. package/dist/middleware/strip-proxy-path.js.map +0 -1
  266. package/dist/middleware/validate-fields.js.map +0 -1
  267. package/dist/mjs/esm-wrapper.js +0 -20
  268. package/dist/mjs/package.json +0 -3
  269. package/dist/package.json +0 -3
  270. package/dist/routes/ancillary.js.map +0 -1
  271. package/dist/routes/dirname.cjs +0 -1
  272. package/dist/routes/dirname.d.cts +0 -2
  273. package/dist/routes/journey.js.map +0 -1
  274. package/dist/routes/static.js.map +0 -1
  275. package/src/lib/dirname.cjs +0 -1
  276. package/src/middleware/dirname.cjs +0 -1
  277. 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
- Object.create(null),
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 priv.get(this).options;
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 priv.get(this).dgraph.nodes();
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
- const self = priv.get(this);
272
- return self.dgraph
263
+ return this.#dgraph
273
264
  .edges()
274
- .map((edge) => makeRouteObject(self.dgraph, edge));
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 priv.get(this).follows[validateRouteName(name)][`${src}/${tgt}`];
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
- const self = priv.get(this);
299
- return self.dgraph
289
+ return this.#dgraph
300
290
  .outEdges(src, tgt)
301
- .map((e) => makeRouteObject(self.dgraph, e));
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 (self.dgraph.hasEdge(src, tgt, name)) {
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
- self.dgraph.setEdge(src, tgt, { conditionName }, name);
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 (!self.options.validateBeforeRouteCondition) {
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
- self.follows[name][`${src}/${tgt}`] = followFunc;
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 = self.options.arbiter,
528
+ arbiter = this.#options.arbiter,
543
529
  routeName,
544
530
  } = options;
545
531
 
546
- if (!self.dgraph.hasNode(startWaypoint)) {
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 = self.dgraph.outEdges(startWP).filter((e) => {
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(self.dgraph, e);
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 self.follows[routeName][`${e.v}/${e.w}`](route, context);
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(self.dgraph, t)),
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(self.dgraph, target[0]);
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(self.dgraph, {
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 priv.get(this).dgraph;
645
+ return this.#dgraph;
660
646
  }
661
647
  }
@@ -1,6 +1,4 @@
1
- import lodash from "lodash";
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:@dwp/govuk-casa
21
+ * @memberof module:"@dwp/govuk-casa"
24
22
  * @class
25
23
  */
26
24
  export default class ValidationError {
@@ -1,6 +1,4 @@
1
- import lodash from "lodash";
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 {Object<string, unknown>} ValidatorFactoryOptions
29
+ * @typedef {{ [key: string]: unknown }} ValidatorFactoryOptions
32
30
  * @property {ErrorMessageConfig} errorMsg Error message
33
31
  */
34
32
 
35
33
  /**
36
- * @memberof module:@dwp/govuk-casa
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 = Object.create(null), cb = echo) {
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
- * @param {boolean | string} cookieSameSite Cookie SameSite value
365
- * @param {boolean | string} defaultFlag Default value
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
@@ -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:@dwp/govuk-casa
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(createRequire(dirname).resolve("govuk-frontend"), "../../"),
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,
@@ -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:@dwp/govuk-casa
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 = Object.create(null)) {
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 = Object.create(null), value = undefined) {
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 = Object.create(null)) {
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 (isFunction(this.#validators[i].sanitise)) {
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:@dwp/govuk-casa
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());