@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.
Files changed (278) 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 +90 -44
  4. package/dist/casa.d.ts.map +1 -0
  5. package/dist/casa.js +85 -101
  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 +79 -55
  31. package/dist/lib/MutableRouter.d.ts.map +1 -0
  32. package/dist/lib/MutableRouter.js +53 -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 +4 -4
  76. package/dist/lib/nunjucks.d.ts.map +1 -0
  77. package/dist/lib/nunjucks.js +14 -26
  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 +4 -2
  133. package/dist/middleware/post.d.ts.map +1 -0
  134. package/dist/middleware/post.js +6 -11
  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 +30 -36
  172. package/src/casa.js +63 -31
  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 +52 -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 +5 -13
  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/post.js +3 -1
  200. package/src/middleware/pre.js +1 -1
  201. package/src/middleware/progress-journey.js +8 -0
  202. package/src/middleware/sanitise-fields.js +17 -2
  203. package/src/middleware/session.js +53 -12
  204. package/src/middleware/skip-waypoint.js +8 -1
  205. package/src/middleware/steer-journey.js +1 -1
  206. package/src/middleware/strip-proxy-path.js +21 -16
  207. package/src/middleware/validate-fields.js +19 -0
  208. package/src/routes/journey.js +18 -8
  209. package/src/routes/static.js +5 -4
  210. package/views/casa/layouts/journey.njk +1 -1
  211. package/views/casa/layouts/main.njk +11 -21
  212. package/dist/casa.js.map +0 -1
  213. package/dist/core-plugins/edit-snapshot/src/configure.js.map +0 -1
  214. package/dist/core-plugins/edit-snapshot/src/index.js.map +0 -1
  215. package/dist/core-plugins/edit-snapshot/src/post-steer-hook.js.map +0 -1
  216. package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.js.map +0 -1
  217. package/dist/core-plugins/edit-snapshot/src/utils.js.map +0 -1
  218. package/dist/core-plugins/index.js.map +0 -1
  219. package/dist/lib/CasaTemplateLoader.js.map +0 -1
  220. package/dist/lib/JourneyContext.js.map +0 -1
  221. package/dist/lib/MutableRouter.js.map +0 -1
  222. package/dist/lib/Plan.js.map +0 -1
  223. package/dist/lib/ValidationError.js.map +0 -1
  224. package/dist/lib/ValidatorFactory.js.map +0 -1
  225. package/dist/lib/configuration-ingestor.js.map +0 -1
  226. package/dist/lib/configure.js.map +0 -1
  227. package/dist/lib/constants.js.map +0 -1
  228. package/dist/lib/context-id-generators.js.map +0 -1
  229. package/dist/lib/dirname.cjs +0 -1
  230. package/dist/lib/dirname.d.cts +0 -2
  231. package/dist/lib/end-session.js.map +0 -1
  232. package/dist/lib/field.js.map +0 -1
  233. package/dist/lib/index.js.map +0 -1
  234. package/dist/lib/logger.js.map +0 -1
  235. package/dist/lib/mount.js.map +0 -1
  236. package/dist/lib/nunjucks-filters.js.map +0 -1
  237. package/dist/lib/nunjucks.js.map +0 -1
  238. package/dist/lib/utils.js.map +0 -1
  239. package/dist/lib/validators/dateObject.js.map +0 -1
  240. package/dist/lib/validators/email.js.map +0 -1
  241. package/dist/lib/validators/inArray.js.map +0 -1
  242. package/dist/lib/validators/index.js.map +0 -1
  243. package/dist/lib/validators/nino.js.map +0 -1
  244. package/dist/lib/validators/postalAddressObject.js.map +0 -1
  245. package/dist/lib/validators/range.js.map +0 -1
  246. package/dist/lib/validators/regex.js.map +0 -1
  247. package/dist/lib/validators/required.js.map +0 -1
  248. package/dist/lib/validators/strlen.js.map +0 -1
  249. package/dist/lib/validators/wordCount.js.map +0 -1
  250. package/dist/lib/waypoint-url.js.map +0 -1
  251. package/dist/middleware/body-parser.js.map +0 -1
  252. package/dist/middleware/csrf.js.map +0 -1
  253. package/dist/middleware/data.js.map +0 -1
  254. package/dist/middleware/dirname.cjs +0 -1
  255. package/dist/middleware/dirname.d.cts +0 -2
  256. package/dist/middleware/gather-fields.js.map +0 -1
  257. package/dist/middleware/i18n.js.map +0 -1
  258. package/dist/middleware/post.js.map +0 -1
  259. package/dist/middleware/pre.js.map +0 -1
  260. package/dist/middleware/progress-journey.js.map +0 -1
  261. package/dist/middleware/sanitise-fields.js.map +0 -1
  262. package/dist/middleware/serve-first-waypoint.js.map +0 -1
  263. package/dist/middleware/session.js.map +0 -1
  264. package/dist/middleware/skip-waypoint.js.map +0 -1
  265. package/dist/middleware/steer-journey.js.map +0 -1
  266. package/dist/middleware/strip-proxy-path.js.map +0 -1
  267. package/dist/middleware/validate-fields.js.map +0 -1
  268. package/dist/mjs/esm-wrapper.js +0 -20
  269. package/dist/mjs/package.json +0 -3
  270. package/dist/package.json +0 -3
  271. package/dist/routes/ancillary.js.map +0 -1
  272. package/dist/routes/dirname.cjs +0 -1
  273. package/dist/routes/dirname.d.cts +0 -2
  274. package/dist/routes/journey.js.map +0 -1
  275. package/dist/routes/static.js.map +0 -1
  276. package/src/lib/dirname.cjs +0 -1
  277. package/src/middleware/dirname.cjs +0 -1
  278. package/src/routes/dirname.cjs +0 -1
@@ -3,6 +3,7 @@ import { FLAG_FOR_PURGING, deleteSnapshot } from "./utils.js";
3
3
 
4
4
  const log = logger("lib:internal-plugin:edit-snapshot:post-steer-hook");
5
5
 
6
+ /** @type {import("express").RequestHandler} */
6
7
  export default (req, res, next) => {
7
8
  // Snapshot purging is carried out here rather than in the presteer hook,
8
9
  // because the `middleware/steer-journey.js` middleware first needs the opportunity
@@ -9,8 +9,9 @@ import {
9
9
 
10
10
  const log = logger("lib:internal-plugin:edit-snapshot:pre-steer-hook");
11
11
 
12
+ /** @type {import("express").RequestHandler} */
12
13
  export default (req, res, next) => {
13
- if (req.query.editcancel && snapshotExists(req)) {
14
+ if (req.query?.editcancel && snapshotExists(req)) {
14
15
  log.debug(
15
16
  "Edit workflow was actively canceled. Snapshot will be recovered.",
16
17
  );
@@ -1,10 +1,15 @@
1
1
  /* eslint-disable security/detect-object-injection */
2
2
  import { JourneyContext } from "../../../casa.js";
3
+ import NullObject from "../../../lib/NullObject.js";
3
4
 
4
5
  const SESSION_KEY = "casa_edit_snapshots";
5
6
 
6
7
  export const FLAG_FOR_PURGING = Symbol("flag_to_purge_edit_snapshot");
7
8
 
9
+ /**
10
+ * @param {ExpressRequest} req Express request
11
+ * @returns {undefined | boolean} Whether the snapshot exists
12
+ */
8
13
  export const snapshotExists = (req) => {
9
14
  return (
10
15
  req?.session[SESSION_KEY] &&
@@ -12,6 +17,11 @@ export const snapshotExists = (req) => {
12
17
  );
13
18
  };
14
19
 
20
+ /**
21
+ * @param {CASADebugLogger} log Express request
22
+ * @param {ExpressRequest} req Express request
23
+ * @returns {boolean} Reached edit origin
24
+ */
15
25
  export const reachedEditOrigin = (log, req) => {
16
26
  const { pathname: currentPathname } = new URL(
17
27
  req.originalUrl,
@@ -25,15 +35,25 @@ export const reachedEditOrigin = (log, req) => {
25
35
  return editOriginPathname === currentPathname;
26
36
  };
27
37
 
38
+ /**
39
+ * @param {CASADebugLogger} log Express request
40
+ * @param {ExpressRequest} req Express request
41
+ * @returns {void}
42
+ */
28
43
  export const createSnapshot = (log, req) => {
29
44
  log.debug(
30
45
  `Creating a new edit snapshot for context '${req.casa.journeyContext.identity.id}'`,
31
46
  );
32
- req.session[SESSION_KEY] ??= Object.create(null);
47
+ req.session[SESSION_KEY] ??= new NullObject();
33
48
  req.session[SESSION_KEY][req.casa.journeyContext.identity.id] =
34
49
  req.casa.journeyContext.toObject();
35
50
  };
36
51
 
52
+ /**
53
+ * @param {CASADebugLogger} log Express request
54
+ * @param {ExpressRequest} req Express request
55
+ * @returns {void}
56
+ */
37
57
  export const recoverSnapshot = (log, req) => {
38
58
  log.debug(
39
59
  `Recovering snapshot for context '${req.casa.journeyContext.identity.id}'`,
@@ -45,9 +65,17 @@ export const recoverSnapshot = (log, req) => {
45
65
  deleteSnapshot(log, req);
46
66
  };
47
67
 
68
+ /**
69
+ * @param {CASADebugLogger} log Express request
70
+ * @param {ExpressRequest} req Express request
71
+ * @returns {void}
72
+ */
48
73
  export const deleteSnapshot = (log, req) => {
49
74
  log.debug(
50
75
  `Purging edit snapshot for context '${req.casa.journeyContext.identity.id}'`,
51
76
  );
52
77
  req.session[SESSION_KEY][req.casa.journeyContext.identity.id] = undefined;
53
78
  };
79
+
80
+ /** @typedef {import("../../../lib/logger.js").CASADebugLogger} CASADebugLogger */
81
+ /** @typedef {import("express").Request} ExpressRequest */
@@ -6,15 +6,15 @@
6
6
  * - Validation errors on that data
7
7
  * - Navigation information about how the user got where they are.
8
8
  */
9
- import lodash from "lodash";
9
+ import isPlainObject from "is-plain-obj";
10
+ import { deepEqual } from "fast-equals";
10
11
  import rfdc from "rfdc";
12
+ import NullObject from "./NullObject.js";
11
13
  import ValidationError from "./ValidationError.js";
12
14
  import logger from "./logger.js";
13
15
  import { notProto } from "./utils.js";
14
16
  import { uuid as uuidGenerator } from "./context-id-generators.js";
15
17
 
16
- const { isPlainObject, isObject, isEqual } = lodash; // CommonJS
17
-
18
18
  const log = logger("lib:journey-context");
19
19
 
20
20
  const uuid = uuidGenerator();
@@ -46,13 +46,18 @@ const clone = rfdc({ proto: false });
46
46
  * @access private
47
47
  */
48
48
 
49
+ /**
50
+ * @typedef {import("../casa").JourneyContextIdentity} JourneyContextIdentity
51
+ * @access private
52
+ */
53
+
49
54
  /**
50
55
  * @typedef {import("express").Request} ExpressRequest
51
56
  * @access private
52
57
  */
53
58
 
54
59
  /**
55
- * @param {any} key Object key to validate
60
+ * @param {string} key Object key to validate
56
61
  * @returns {string} Validated key
57
62
  */
58
63
  export function validateObjectKey(key = "") {
@@ -67,7 +72,7 @@ export function validateObjectKey(key = "") {
67
72
  return String(key);
68
73
  }
69
74
 
70
- /** @memberof module:@dwp/govuk-casa */
75
+ /** @memberof module:"@dwp/govuk-casa" */
71
76
  export default class JourneyContext {
72
77
  // Private properties
73
78
  #data;
@@ -109,10 +114,11 @@ export default class JourneyContext {
109
114
  * among a group of contexts stored in the session.
110
115
  *
111
116
  * @param {Record<string, any>} data Entire journey data.
112
- * @param {object} validation Page errors (indexed by waypoint id).
113
- * @param {object} nav Navigation context.
114
- * @param {object} identity Some metadata for identifying this context among
115
- * others.
117
+ * @param {Record<string, ValidationError[] | null>} validation Page errors
118
+ * (indexed by waypoint id).
119
+ * @param {{ language?: string }} nav Navigation context.
120
+ * @param {JourneyContextIdentity} identity Some metadata for identifying this
121
+ * context among others.
116
122
  */
117
123
  constructor(data = {}, validation = {}, nav = {}, identity = {}) {
118
124
  this.#data = data;
@@ -129,7 +135,7 @@ export default class JourneyContext {
129
135
  * @returns {JourneyContextObject} Plain object.
130
136
  */
131
137
  toObject() {
132
- return Object.assign(Object.create(null), {
138
+ return Object.assign(new NullObject(), {
133
139
  data: clone(this.#data),
134
140
  validation: clone(this.#validation),
135
141
  nav: clone(this.#nav),
@@ -144,14 +150,14 @@ export default class JourneyContext {
144
150
  * @returns {JourneyContext} Instance.
145
151
  */
146
152
  static fromObject({
147
- data = Object.create(null),
148
- validation = Object.create(null),
149
- nav = Object.create(null),
150
- identity = Object.create(null),
153
+ data = new NullObject(),
154
+ validation = new NullObject(),
155
+ nav = new NullObject(),
156
+ identity = new NullObject(),
151
157
  } = {}) {
152
158
  // As we're constructing a JourneyContext from a plain JS object, we need to
153
159
  // ensure any validation errors are instances of ValidationError.
154
- const deserialisedValidation = Object.create(null);
160
+ const deserialisedValidation = new NullObject();
155
161
  for (const [waypoint, errors] of Object.entries(validation)) {
156
162
  let dErrors = errors;
157
163
 
@@ -341,7 +347,7 @@ export default class JourneyContext {
341
347
  */
342
348
  getValidationErrorsForPageByField(pageId) {
343
349
  const errors = this.getValidationErrorsForPage(pageId);
344
- const obj = Object.create(null);
350
+ const obj = new NullObject();
345
351
 
346
352
  // ESLint disabled as `i` is an integer
347
353
  /* eslint-disable security/detect-object-injection */
@@ -394,8 +400,8 @@ export default class JourneyContext {
394
400
  * @param {string[]} waypoints Waypoints to be removed
395
401
  */
396
402
  purge(waypoints = []) {
397
- const newData = Object.create(null);
398
- const newValidation = Object.create(null);
403
+ const newData = new NullObject();
404
+ const newValidation = new NullObject();
399
405
  const toKeep = Object.keys(this.#data).filter(
400
406
  (w) => !waypoints.includes(w),
401
407
  );
@@ -483,12 +489,12 @@ export default class JourneyContext {
483
489
  logMessage = `Calling waypoint-specific event handler on "${waypoint}"`;
484
490
  runHandler =
485
491
  previousContext.data?.[waypoint] !== undefined &&
486
- !isEqual(this.data?.[waypoint], previousContext.data?.[waypoint]);
492
+ !deepEqual(this.data?.[waypoint], previousContext.data?.[waypoint]);
487
493
  } else if (waypoint && field) {
488
494
  logMessage = `Calling field-specific event handler on "${waypoint} : ${field}"`;
489
495
  runHandler =
490
496
  previousContext.data?.[waypoint]?.[field] !== undefined &&
491
- !isEqual(
497
+ !deepEqual(
492
498
  this.data?.[waypoint]?.[field],
493
499
  previousContext.data?.[waypoint]?.[field],
494
500
  );
@@ -773,7 +779,7 @@ export default class JourneyContext {
773
779
  * @throws {TypeError} When session is not a valid type, or context has no ID
774
780
  */
775
781
  static putContext(session, context, options = {}) {
776
- if (!isObject(session)) {
782
+ if (typeof session !== "object" || session === null) {
777
783
  throw new TypeError("Session must be an object");
778
784
  } else if (!(context instanceof JourneyContext)) {
779
785
  throw new TypeError("Context must be a valid JourneyContext");
@@ -933,20 +939,17 @@ export default class JourneyContext {
933
939
  /* eslint-disable security/detect-object-injection */
934
940
  // Unset, with setSkipped(a, false)
935
941
  if (opts === false) {
936
- this.data[waypoint] ??= Object.create(null);
937
- this.data[waypoint].__skipped__ = undefined;
942
+ this.data[waypoint] ??= new NullObject();
938
943
  this.data[waypoint].__skip__ = undefined;
939
944
  }
940
945
  // Set, with setSkipped(a, true) and clear data
941
946
  else if (opts === true) {
942
- this.data[waypoint] = Object.create(null);
943
- this.data[waypoint].__skipped__ = true;
947
+ this.data[waypoint] = new NullObject();
944
948
  this.data[waypoint].__skip__ = { to: null };
945
949
  }
946
950
  // Set, with setSkipped(a, { to: b }) and clear data
947
951
  else if (typeof opts?.to === "string") {
948
- this.data[waypoint] = Object.create(null);
949
- this.data[waypoint].__skipped__ = true;
952
+ this.data[waypoint] = new NullObject();
950
953
  this.data[waypoint].__skip__ = { to: opts.to };
951
954
  } else {
952
955
  throw new TypeError(
@@ -969,7 +972,7 @@ export default class JourneyContext {
969
972
  const wpData = this.data[String(waypoint)];
970
973
 
971
974
  if (opts === undefined) {
972
- return wpData?.__skipped__ === true || wpData?.__skip__ !== undefined;
975
+ return wpData?.__skip__ !== undefined;
973
976
  } else if (typeof opts.to === "string") {
974
977
  return wpData?.__skip__?.to === opts.to;
975
978
  }
@@ -1,8 +1,8 @@
1
1
  import { Router } from "express";
2
2
 
3
- /** @memberof module:@dwp/govuk-casa */
3
+ /** @memberof module:"@dwp/govuk-casa" */
4
4
  export default class MutableRouter {
5
- /** @type {Array} */
5
+ /** @type {StackRoute[]} */
6
6
  #stack;
7
7
 
8
8
  /** @type {Router} */
@@ -100,8 +100,8 @@ export default class MutableRouter {
100
100
  /**
101
101
  * Prepend middleware function(s) using the `all()` method.
102
102
  *
103
- * @param {string | Function} path Route path or middleware function
104
- * @param {...Function} callbacks Additional middleware functions
103
+ * @param {PathParams | RequestHandler} path Route path or middleware function
104
+ * @param {...RequestHandler} callbacks Additional middleware functions
105
105
  * @returns {void}
106
106
  */
107
107
  prependAll(path, ...callbacks) {
@@ -111,8 +111,8 @@ export default class MutableRouter {
111
111
  /**
112
112
  * Prepend middleware function(s) using the `get()` method.
113
113
  *
114
- * @param {string | Function} path Route path or middleware function
115
- * @param {...Function} callbacks Additional middleware functions
114
+ * @param {PathParams | RequestHandler} path Route path or middleware function
115
+ * @param {...RequestHandler} callbacks Additional middleware functions
116
116
  * @returns {void}
117
117
  */
118
118
  prependGet(path, ...callbacks) {
@@ -122,8 +122,8 @@ export default class MutableRouter {
122
122
  /**
123
123
  * Prepend middleware function(s) using the `post()` method.
124
124
  *
125
- * @param {string | Function} path Route path or middleware function
126
- * @param {...Function} callbacks Additional middleware functions
125
+ * @param {PathParams | RequestHandler} path Route path or middleware function
126
+ * @param {...RequestHandler} callbacks Additional middleware functions
127
127
  * @returns {void}
128
128
  */
129
129
  prependPost(path, ...callbacks) {
@@ -133,8 +133,8 @@ export default class MutableRouter {
133
133
  /**
134
134
  * Prepend middleware function(s) using the `delete()` method.
135
135
  *
136
- * @param {string | Function} path Route path or middleware function
137
- * @param {...Function} callbacks Additional middleware functions
136
+ * @param {PathParams | RequestHandler} path Route path or middleware function
137
+ * @param {...RequestHandler} callbacks Additional middleware functions
138
138
  * @returns {void}
139
139
  */
140
140
  prependDelete(path, ...callbacks) {
@@ -144,8 +144,8 @@ export default class MutableRouter {
144
144
  /**
145
145
  * Prepend middleware function(s) using the `put()` method.
146
146
  *
147
- * @param {string | Function} path Route path or middleware function
148
- * @param {...Function} callbacks Additional middleware functions
147
+ * @param {PathParams | RequestHandler} path Route path or middleware function
148
+ * @param {...RequestHandler} callbacks Additional middleware functions
149
149
  * @returns {void}
150
150
  */
151
151
  prependPut(path, ...callbacks) {
@@ -155,8 +155,9 @@ export default class MutableRouter {
155
155
  /**
156
156
  * Prepend middleware function(s) using the `use()` method.
157
157
  *
158
- * @param {string | Function} path Route path or middleware function
159
- * @param {...Function} callbacks Additional middleware functions
158
+ * @param {PathParams | RequestHandlerParams} path Route path or middleware
159
+ * function
160
+ * @param {...RequestHandlerParams} callbacks Additional middleware functions
160
161
  * @returns {void}
161
162
  */
162
163
  prependUse(path, ...callbacks) {
@@ -168,8 +169,8 @@ export default class MutableRouter {
168
169
  /**
169
170
  * Replace middleware function(s) that were mounted using the `all()` method.
170
171
  *
171
- * @param {string | Function} path Route path or middleware function
172
- * @param {...Function} callbacks Additional middleware functions
172
+ * @param {PathParams | RequestHandler} path Route path or middleware function
173
+ * @param {...RequestHandler} callbacks Additional middleware functions
173
174
  * @returns {void}
174
175
  */
175
176
  replaceAll(path, ...callbacks) {
@@ -179,8 +180,8 @@ export default class MutableRouter {
179
180
  /**
180
181
  * Replace middleware function(s) that were mounted using the `get()` method.
181
182
  *
182
- * @param {string | Function} path Route path or middleware function
183
- * @param {...Function} callbacks Additional middleware functions
183
+ * @param {PathParams | RequestHandler} path Route path or middleware function
184
+ * @param {...RequestHandler} callbacks Additional middleware functions
184
185
  * @returns {void}
185
186
  */
186
187
  replaceGet(path, ...callbacks) {
@@ -190,8 +191,8 @@ export default class MutableRouter {
190
191
  /**
191
192
  * Replace middleware function(s) that were mounted using the `post()` method.
192
193
  *
193
- * @param {string | Function} path Route path or middleware function
194
- * @param {...Function} callbacks Additional middleware functions
194
+ * @param {PathParams | RequestHandler} path Route path or middleware function
195
+ * @param {...RequestHandler} callbacks Additional middleware functions
195
196
  * @returns {void}
196
197
  */
197
198
  replacePost(path, ...callbacks) {
@@ -202,8 +203,8 @@ export default class MutableRouter {
202
203
  * Replace middleware function(s) that were mounted using the `delete()`
203
204
  * method.
204
205
  *
205
- * @param {string | Function} path Route path or middleware function
206
- * @param {...Function} callbacks Additional middleware functions
206
+ * @param {PathParams | RequestHandler} path Route path or middleware function
207
+ * @param {...RequestHandler} callbacks Additional middleware functions
207
208
  * @returns {void}
208
209
  */
209
210
  replaceDelete(path, ...callbacks) {
@@ -213,8 +214,8 @@ export default class MutableRouter {
213
214
  /**
214
215
  * Replace middleware function(s) that were mounted using the `put()` method.
215
216
  *
216
- * @param {string | Function} path Route path or middleware function
217
- * @param {...Function} callbacks Additional middleware functions
217
+ * @param {PathParams | RequestHandler} path Route path or middleware function
218
+ * @param {...RequestHandler} callbacks Additional middleware functions
218
219
  * @returns {void}
219
220
  */
220
221
  replacePut(path, ...callbacks) {
@@ -224,8 +225,9 @@ export default class MutableRouter {
224
225
  /**
225
226
  * Replace middleware function(s) that were mounted using the `use()` method.
226
227
  *
227
- * @param {string | Function} path Route path or middleware function
228
- * @param {...Function} callbacks Additional middleware functions
228
+ * @param {PathParams | RequestHandlerParams} path Route path or middleware
229
+ * function
230
+ * @param {...RequestHandlerParams} callbacks Additional middleware functions
229
231
  * @returns {void}
230
232
  */
231
233
  replaceUse(path, ...callbacks) {
@@ -237,8 +239,8 @@ export default class MutableRouter {
237
239
  /**
238
240
  * Append middleware function(s) using the `all()` method.
239
241
  *
240
- * @param {string | Function} path Route path or middleware function
241
- * @param {...Function} callbacks Additional middleware functions
242
+ * @param {PathParams | RequestHandler} path Route path or middleware function
243
+ * @param {...RequestHandler} callbacks Additional middleware functions
242
244
  * @returns {void}
243
245
  */
244
246
  all(path, ...callbacks) {
@@ -248,8 +250,8 @@ export default class MutableRouter {
248
250
  /**
249
251
  * Append middleware function(s) using the `get()` method.
250
252
  *
251
- * @param {string | Function} path Route path or middleware function
252
- * @param {...Function} callbacks Additional middleware functions
253
+ * @param {PathParams | RequestHandler} path Route path or middleware function
254
+ * @param {...RequestHandler} callbacks Additional middleware functions
253
255
  * @returns {void}
254
256
  */
255
257
  get(path, ...callbacks) {
@@ -259,8 +261,8 @@ export default class MutableRouter {
259
261
  /**
260
262
  * Append middleware function(s) using the `post()` method.
261
263
  *
262
- * @param {string | Function} path Route path or middleware function
263
- * @param {...Function} callbacks Additional middleware functions
264
+ * @param {PathParams | RequestHandler} path Route path or middleware function
265
+ * @param {...RequestHandler} callbacks Additional middleware functions
264
266
  * @returns {void}
265
267
  */
266
268
  post(path, ...callbacks) {
@@ -270,8 +272,8 @@ export default class MutableRouter {
270
272
  /**
271
273
  * Append middleware function(s) using the `delete()` method.
272
274
  *
273
- * @param {string | Function} path Route path or middleware function
274
- * @param {...Function} callbacks Additional middleware functions
275
+ * @param {PathParams | RequestHandler} path Route path or middleware function
276
+ * @param {...RequestHandler} callbacks Additional middleware functions
275
277
  * @returns {void}
276
278
  */
277
279
  delete(path, ...callbacks) {
@@ -281,8 +283,8 @@ export default class MutableRouter {
281
283
  /**
282
284
  * Append middleware function(s) using the `put()` method.
283
285
  *
284
- * @param {string | Function} path Route path or middleware function
285
- * @param {...Function} callbacks Additional middleware functions
286
+ * @param {PathParams | RequestHandler} path Route path or middleware function
287
+ * @param {...RequestHandler} callbacks Additional middleware functions
286
288
  * @returns {void}
287
289
  */
288
290
  put(path, ...callbacks) {
@@ -292,8 +294,9 @@ export default class MutableRouter {
292
294
  /**
293
295
  * Append middleware function(s) using the `use()` method.
294
296
  *
295
- * @param {string | Function} path Route path or middleware function
296
- * @param {...Function} callbacks Additional middleware functions
297
+ * @param {PathParams | RequestHandlerParams} path Route path or middleware
298
+ * function
299
+ * @param {...RequestHandlerParams} callbacks Additional middleware functions
297
300
  * @returns {void}
298
301
  */
299
302
  use(path, ...callbacks) {
@@ -306,3 +309,14 @@ export default class MutableRouter {
306
309
  );
307
310
  }
308
311
  }
312
+
313
+ /** @typedef {import("express").RequestHandler} RequestHandler */
314
+ /** @typedef {import("express-serve-static-core").PathParams} PathParams */
315
+ /** @typedef {import("express-serve-static-core").RequestHandlerParams} RequestHandlerParams */
316
+
317
+ /**
318
+ * @typedef {object} StackRoute Stack route
319
+ * @property {string} method HTTP request method
320
+ * @property {PathParams} path Route path
321
+ * @property {[PathParams, ...RequestHandler[]]} args Router arguments
322
+ */
@@ -0,0 +1,4 @@
1
+ const NullObject = function () {};
2
+ NullObject.prototype = Object.create(null);
3
+
4
+ export default NullObject;