@dwp/govuk-casa 9.0.0 → 9.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 (199) hide show
  1. package/README.md +9 -9
  2. package/dist/assets/css/casa.css +1 -1
  3. package/dist/assets/css/casa.css.map +1 -1
  4. package/dist/casa.d.ts +122 -95
  5. package/dist/casa.js +119 -86
  6. package/dist/casa.js.map +1 -1
  7. package/dist/lib/CasaTemplateLoader.d.ts +4 -4
  8. package/dist/lib/CasaTemplateLoader.js +16 -16
  9. package/dist/lib/CasaTemplateLoader.js.map +1 -1
  10. package/dist/lib/JourneyContext.d.ts +38 -40
  11. package/dist/lib/JourneyContext.js +81 -75
  12. package/dist/lib/JourneyContext.js.map +1 -1
  13. package/dist/lib/MutableRouter.d.ts +40 -41
  14. package/dist/lib/MutableRouter.js +64 -71
  15. package/dist/lib/MutableRouter.js.map +1 -1
  16. package/dist/lib/Plan.d.ts +29 -26
  17. package/dist/lib/Plan.js +85 -71
  18. package/dist/lib/Plan.js.map +1 -1
  19. package/dist/lib/ValidationError.d.ts +16 -15
  20. package/dist/lib/ValidationError.js +21 -20
  21. package/dist/lib/ValidationError.js.map +1 -1
  22. package/dist/lib/ValidatorFactory.d.ts +15 -13
  23. package/dist/lib/ValidatorFactory.js +14 -12
  24. package/dist/lib/ValidatorFactory.js.map +1 -1
  25. package/dist/lib/configuration-ingestor.d.ts +37 -40
  26. package/dist/lib/configuration-ingestor.js +93 -93
  27. package/dist/lib/configuration-ingestor.js.map +1 -1
  28. package/dist/lib/configure.d.ts +6 -6
  29. package/dist/lib/configure.js +14 -12
  30. package/dist/lib/configure.js.map +1 -1
  31. package/dist/lib/constants.d.ts +1 -3
  32. package/dist/lib/constants.js +9 -11
  33. package/dist/lib/constants.js.map +1 -1
  34. package/dist/lib/context-id-generators.d.ts +3 -5
  35. package/dist/lib/context-id-generators.js +7 -6
  36. package/dist/lib/context-id-generators.js.map +1 -1
  37. package/dist/lib/end-session.d.ts +4 -4
  38. package/dist/lib/end-session.js +5 -5
  39. package/dist/lib/field.d.ts +20 -18
  40. package/dist/lib/field.js +35 -48
  41. package/dist/lib/field.js.map +1 -1
  42. package/dist/lib/index.d.ts +13 -13
  43. package/dist/lib/logger.d.ts +7 -6
  44. package/dist/lib/logger.js +7 -7
  45. package/dist/lib/logger.js.map +1 -1
  46. package/dist/lib/mount.d.ts +5 -5
  47. package/dist/lib/mount.js +11 -10
  48. package/dist/lib/mount.js.map +1 -1
  49. package/dist/lib/nunjucks-filters.d.ts +10 -12
  50. package/dist/lib/nunjucks-filters.js +35 -35
  51. package/dist/lib/nunjucks-filters.js.map +1 -1
  52. package/dist/lib/nunjucks.d.ts +7 -5
  53. package/dist/lib/nunjucks.js +10 -8
  54. package/dist/lib/nunjucks.js.map +1 -1
  55. package/dist/lib/utils.d.ts +19 -19
  56. package/dist/lib/utils.js +62 -55
  57. package/dist/lib/utils.js.map +1 -1
  58. package/dist/lib/validators/dateObject.d.ts +29 -22
  59. package/dist/lib/validators/dateObject.js +58 -49
  60. package/dist/lib/validators/dateObject.js.map +1 -1
  61. package/dist/lib/validators/email.d.ts +4 -4
  62. package/dist/lib/validators/email.js +4 -4
  63. package/dist/lib/validators/inArray.d.ts +4 -4
  64. package/dist/lib/validators/inArray.js +7 -8
  65. package/dist/lib/validators/inArray.js.map +1 -1
  66. package/dist/lib/validators/index.d.ts +10 -10
  67. package/dist/lib/validators/index.js +1 -3
  68. package/dist/lib/validators/index.js.map +1 -1
  69. package/dist/lib/validators/nino.d.ts +9 -8
  70. package/dist/lib/validators/nino.js +14 -10
  71. package/dist/lib/validators/nino.js.map +1 -1
  72. package/dist/lib/validators/postalAddressObject.d.ts +37 -24
  73. package/dist/lib/validators/postalAddressObject.js +65 -46
  74. package/dist/lib/validators/postalAddressObject.js.map +1 -1
  75. package/dist/lib/validators/range.d.ts +12 -8
  76. package/dist/lib/validators/range.js +11 -9
  77. package/dist/lib/validators/range.js.map +1 -1
  78. package/dist/lib/validators/regex.d.ts +4 -4
  79. package/dist/lib/validators/regex.js +5 -5
  80. package/dist/lib/validators/required.d.ts +6 -6
  81. package/dist/lib/validators/required.js +9 -11
  82. package/dist/lib/validators/required.js.map +1 -1
  83. package/dist/lib/validators/strlen.d.ts +12 -8
  84. package/dist/lib/validators/strlen.js +13 -11
  85. package/dist/lib/validators/strlen.js.map +1 -1
  86. package/dist/lib/validators/wordCount.d.ts +12 -8
  87. package/dist/lib/validators/wordCount.js +15 -11
  88. package/dist/lib/validators/wordCount.js.map +1 -1
  89. package/dist/lib/waypoint-url.d.ts +16 -13
  90. package/dist/lib/waypoint-url.js +39 -36
  91. package/dist/lib/waypoint-url.js.map +1 -1
  92. package/dist/middleware/body-parser.d.ts +1 -1
  93. package/dist/middleware/body-parser.js +6 -6
  94. package/dist/middleware/body-parser.js.map +1 -1
  95. package/dist/middleware/data.d.ts +1 -1
  96. package/dist/middleware/data.js +8 -7
  97. package/dist/middleware/data.js.map +1 -1
  98. package/dist/middleware/gather-fields.d.ts +2 -2
  99. package/dist/middleware/gather-fields.js +6 -4
  100. package/dist/middleware/gather-fields.js.map +1 -1
  101. package/dist/middleware/i18n.js +13 -15
  102. package/dist/middleware/i18n.js.map +1 -1
  103. package/dist/middleware/post.js +30 -18
  104. package/dist/middleware/post.js.map +1 -1
  105. package/dist/middleware/pre.d.ts +2 -2
  106. package/dist/middleware/pre.js +46 -27
  107. package/dist/middleware/pre.js.map +1 -1
  108. package/dist/middleware/progress-journey.d.ts +1 -1
  109. package/dist/middleware/progress-journey.js +5 -5
  110. package/dist/middleware/progress-journey.js.map +1 -1
  111. package/dist/middleware/sanitise-fields.d.ts +1 -1
  112. package/dist/middleware/sanitise-fields.js +13 -11
  113. package/dist/middleware/sanitise-fields.js.map +1 -1
  114. package/dist/middleware/serve-first-waypoint.d.ts +3 -3
  115. package/dist/middleware/serve-first-waypoint.js +8 -6
  116. package/dist/middleware/serve-first-waypoint.js.map +1 -1
  117. package/dist/middleware/session.js +14 -11
  118. package/dist/middleware/session.js.map +1 -1
  119. package/dist/middleware/skip-waypoint.d.ts +1 -1
  120. package/dist/middleware/skip-waypoint.js +3 -3
  121. package/dist/middleware/skip-waypoint.js.map +1 -1
  122. package/dist/middleware/steer-journey.d.ts +1 -1
  123. package/dist/middleware/steer-journey.js +16 -14
  124. package/dist/middleware/steer-journey.js.map +1 -1
  125. package/dist/middleware/strip-proxy-path.d.ts +1 -1
  126. package/dist/middleware/strip-proxy-path.js +3 -3
  127. package/dist/middleware/strip-proxy-path.js.map +1 -1
  128. package/dist/middleware/validate-fields.d.ts +1 -1
  129. package/dist/middleware/validate-fields.js +2 -5
  130. package/dist/middleware/validate-fields.js.map +1 -1
  131. package/dist/routes/ancillary.d.ts +3 -3
  132. package/dist/routes/ancillary.js +4 -4
  133. package/dist/routes/ancillary.js.map +1 -1
  134. package/dist/routes/journey.d.ts +2 -2
  135. package/dist/routes/journey.js +91 -39
  136. package/dist/routes/journey.js.map +1 -1
  137. package/dist/routes/static.d.ts +7 -5
  138. package/dist/routes/static.js +20 -19
  139. package/dist/routes/static.js.map +1 -1
  140. package/package.json +19 -18
  141. package/src/casa.js +133 -100
  142. package/src/lib/CasaTemplateLoader.js +24 -19
  143. package/src/lib/JourneyContext.js +138 -107
  144. package/src/lib/MutableRouter.js +72 -74
  145. package/src/lib/Plan.js +145 -97
  146. package/src/lib/ValidationError.js +25 -21
  147. package/src/lib/ValidatorFactory.js +17 -13
  148. package/src/lib/configuration-ingestor.js +147 -110
  149. package/src/lib/configure.js +34 -32
  150. package/src/lib/constants.js +9 -11
  151. package/src/lib/context-id-generators.js +40 -43
  152. package/src/lib/end-session.js +6 -6
  153. package/src/lib/field.js +69 -58
  154. package/src/lib/index.js +12 -12
  155. package/src/lib/logger.js +9 -9
  156. package/src/lib/mount.js +70 -74
  157. package/src/lib/nunjucks-filters.js +56 -59
  158. package/src/lib/nunjucks.js +23 -18
  159. package/src/lib/utils.js +78 -57
  160. package/src/lib/validators/dateObject.js +71 -60
  161. package/src/lib/validators/email.js +8 -8
  162. package/src/lib/validators/inArray.js +10 -11
  163. package/src/lib/validators/index.js +12 -14
  164. package/src/lib/validators/nino.js +29 -15
  165. package/src/lib/validators/postalAddressObject.js +87 -63
  166. package/src/lib/validators/range.js +14 -12
  167. package/src/lib/validators/regex.js +8 -8
  168. package/src/lib/validators/required.js +16 -16
  169. package/src/lib/validators/strlen.js +16 -14
  170. package/src/lib/validators/wordCount.js +22 -14
  171. package/src/lib/waypoint-url.js +64 -46
  172. package/src/middleware/body-parser.js +10 -10
  173. package/src/middleware/csrf.js +1 -1
  174. package/src/middleware/data.js +28 -24
  175. package/src/middleware/gather-fields.js +10 -9
  176. package/src/middleware/i18n.js +35 -37
  177. package/src/middleware/post.js +41 -21
  178. package/src/middleware/pre.js +62 -41
  179. package/src/middleware/progress-journey.js +32 -18
  180. package/src/middleware/sanitise-fields.js +43 -20
  181. package/src/middleware/serve-first-waypoint.js +14 -12
  182. package/src/middleware/session.js +74 -61
  183. package/src/middleware/skip-waypoint.js +7 -9
  184. package/src/middleware/steer-journey.js +40 -28
  185. package/src/middleware/strip-proxy-path.js +8 -7
  186. package/src/middleware/validate-fields.js +5 -12
  187. package/src/routes/ancillary.js +5 -7
  188. package/src/routes/journey.js +159 -85
  189. package/src/routes/static.js +62 -29
  190. package/views/casa/components/character-count/README.md +2 -2
  191. package/views/casa/components/checkboxes/README.md +6 -6
  192. package/views/casa/components/date-input/README.md +7 -7
  193. package/views/casa/components/input/README.md +2 -2
  194. package/views/casa/components/journey-form/README.md +33 -14
  195. package/views/casa/components/postal-address-object/README.md +4 -4
  196. package/views/casa/components/radios/README.md +6 -6
  197. package/views/casa/components/select/README.md +6 -6
  198. package/views/casa/components/textarea/README.md +2 -2
  199. package/views/casa/layouts/main.njk +2 -1
@@ -1,14 +1,14 @@
1
1
  // This sits in front of all other middleware and prevents the user from
2
2
  // "jumping ahead" in the Plan.
3
3
 
4
- import waypointUrl from '../lib/waypoint-url.js';
5
- import logger from '../lib/logger.js';
4
+ import waypointUrl from "../lib/waypoint-url.js";
5
+ import logger from "../lib/logger.js";
6
6
 
7
- const log = logger('middleware:steer-journey');
7
+ const log = logger("middleware:steer-journey");
8
8
 
9
9
  /**
10
+ * @typedef {import("../lib/Plan")} Plan
10
11
  * @access private
11
- * @typedef {import('../lib/Plan')} Plan
12
12
  */
13
13
 
14
14
  /**
@@ -20,10 +20,7 @@ const log = logger('middleware:steer-journey');
20
20
  * @param {Plan} obj.plan CASA Plan
21
21
  * @returns {void}
22
22
  */
23
- export default ({
24
- waypoint,
25
- plan,
26
- }) => [
23
+ export default ({ waypoint, plan }) => [
27
24
  (req, res, next) => {
28
25
  const mountUrl = `${req.baseUrl}/`;
29
26
 
@@ -32,25 +29,38 @@ export default ({
32
29
  const traversed = plan.traverse(req.casa.journeyContext);
33
30
  if (traversed.indexOf(waypoint) === -1) {
34
31
  const redirectTo = traversed[traversed.length - 1];
35
- log.trace(`Attempted to access "${waypoint}" when not in the journey; redirecting to "${redirectTo}"`);
32
+ log.trace(
33
+ `Attempted to access "${waypoint}" when not in the journey; redirecting to "${redirectTo}"`,
34
+ );
36
35
 
37
- return res.redirect(302, waypointUrl({
38
- waypoint: redirectTo,
39
- mountUrl,
40
- journeyContext: req.casa.journeyContext,
41
- edit: req.casa.editMode,
42
- editOrigin: req.casa.editOrigin,
43
- }));
36
+ return res.redirect(
37
+ 302,
38
+ waypointUrl({
39
+ waypoint: redirectTo,
40
+ mountUrl,
41
+ journeyContext: req.casa.journeyContext,
42
+ edit: req.casa.editMode,
43
+ editOrigin: req.casa.editOrigin,
44
+ }),
45
+ );
44
46
  }
45
47
 
46
48
  // Edit mode
47
49
  // Cannot be in edit mode if we're already on the `editorigin` URL
48
50
  if (req.casa.editMode) {
49
- const { pathname: currentPathname } = new URL(req.originalUrl, 'https://placeholder.test/');
50
- const { pathname: editOriginPathname } = new URL(req.casa.editOrigin, 'https://placeholder.test/');
51
+ const { pathname: currentPathname } = new URL(
52
+ req.originalUrl,
53
+ "https://placeholder.test/",
54
+ );
55
+ const { pathname: editOriginPathname } = new URL(
56
+ req.casa.editOrigin,
57
+ "https://placeholder.test/",
58
+ );
51
59
 
52
60
  if (editOriginPathname === currentPathname) {
53
- log.debug(`Disabling edit mode as we are on the edit origin (${req.casa.editOrigin})`);
61
+ log.debug(
62
+ `Disabling edit mode as we are on the edit origin (${req.casa.editOrigin})`,
63
+ );
54
64
  req.casa.editMode = false;
55
65
  req.casa.editOrigin = undefined;
56
66
  }
@@ -64,16 +74,18 @@ export default ({
64
74
  // Calculate URL for the "back" link
65
75
  const [prevRoute] = plan.traversePrevRoutes(req.casa.journeyContext, {
66
76
  startWaypoint: waypoint,
67
- stopCondition: () => (true), // stop at the first one
77
+ stopCondition: () => true, // stop at the first one
68
78
  });
69
- res.locals.casa.journeyPreviousUrl = prevRoute.target ? waypointUrl({
70
- mountUrl,
71
- journeyContext: req.casa.journeyContext,
72
- waypoint: prevRoute.target,
73
- routeName: 'prev',
74
- edit: req.casa.editMode,
75
- editOrigin: req.casa.editOrigin,
76
- }) : undefined;
79
+ res.locals.casa.journeyPreviousUrl = prevRoute.target
80
+ ? waypointUrl({
81
+ mountUrl,
82
+ journeyContext: req.casa.journeyContext,
83
+ waypoint: prevRoute.target,
84
+ routeName: "prev",
85
+ edit: req.casa.editMode,
86
+ editOrigin: req.casa.editOrigin,
87
+ })
88
+ : undefined;
77
89
 
78
90
  return next();
79
91
  },
@@ -14,13 +14,11 @@
14
14
  //
15
15
  // See docs in `docs/guides/setup-behind-a-proxy.md`
16
16
 
17
- import logger from '../lib/logger.js';
17
+ import logger from "../lib/logger.js";
18
18
 
19
- const log = logger('casa:middleware:strip-proxy-path');
19
+ const log = logger("casa:middleware:strip-proxy-path");
20
20
 
21
- export default ({
22
- mountUrl = '/',
23
- }) => [
21
+ export default ({ mountUrl = "/" }) => [
24
22
  (req, res, next) => {
25
23
  // TODO:
26
24
  // We _may_ have to start tracking the various prefix in order to differentiate
@@ -28,7 +26,7 @@ export default ({
28
26
 
29
27
  // Assume everything before `mountUrl` is the proxy path prefix and remove it
30
28
  req.originalBaseUrl = req.originalBaseUrl ?? req.baseUrl;
31
- req.baseUrl = mountUrl.replace(/\/$/, '');
29
+ req.baseUrl = mountUrl.replace(/\/$/, "");
32
30
 
33
31
  // If the app has been mounted directly on the specific `mountUrl`, then
34
32
  // there's nothing we need to do and can let this request pass-through.
@@ -43,7 +41,10 @@ export default ({
43
41
  // req.url will already have the proxy prefix and mountUrl removed.
44
42
  /* eslint-disable security/detect-non-literal-regexp */
45
43
  log.trace(`req.originalUrl before proxy stripping: ${req.originalUrl}`);
46
- req.originalUrl = req.originalUrl.replace(new RegExp(`^/.+?${mountUrl}`), mountUrl);
44
+ req.originalUrl = req.originalUrl.replace(
45
+ new RegExp(`^/.+?${mountUrl}`),
46
+ mountUrl,
47
+ );
47
48
  log.trace(`req.originalUrl after proxy stripping: ${req.originalUrl}`);
48
49
  /* eslint-enable security/detect-non-literal-regexp */
49
50
 
@@ -1,6 +1,6 @@
1
1
  // Validate the data captured in the journey context
2
- import JourneyContext from '../lib/JourneyContext.js';
3
- import { REQUEST_PHASE_VALIDATE } from '../lib/constants.js';
2
+ import JourneyContext from "../lib/JourneyContext.js";
3
+ import { REQUEST_PHASE_VALIDATE } from "../lib/constants.js";
4
4
 
5
5
  const updateContext = ({
6
6
  waypoint,
@@ -21,13 +21,9 @@ const updateContext = ({
21
21
  casaRequestPhase: REQUEST_PHASE_VALIDATE,
22
22
  },
23
23
  });
24
- }
24
+ };
25
25
 
26
- export default ({
27
- waypoint,
28
- fields = [],
29
- plan,
30
- }) => [
26
+ export default ({ waypoint, fields = [], plan }) => [
31
27
  (req, res, next) => {
32
28
  const mountUrl = `${req.baseUrl}/`;
33
29
 
@@ -50,10 +46,7 @@ export default ({
50
46
  };
51
47
  /* eslint-enable security/detect-object-injection */
52
48
 
53
- errors = [
54
- ...errors,
55
- ...field.runValidators(context),
56
- ];
49
+ errors = [...errors, ...field.runValidators(context)];
57
50
  }
58
51
 
59
52
  // Validation passed with no errors
@@ -1,4 +1,4 @@
1
- import MutableRouter from '../lib/MutableRouter.js';
1
+ import MutableRouter from "../lib/MutableRouter.js";
2
2
 
3
3
  /**
4
4
  * @typedef {object} AncillaryRouterOptions Options to configure static router
@@ -8,19 +8,17 @@ import MutableRouter from '../lib/MutableRouter.js';
8
8
  /**
9
9
  * Create an instance of the ancillary router.
10
10
  *
11
- * @access private
12
11
  * @param {AncillaryRouterOptions} options Options
13
12
  * @returns {MutableRouter} ExpressJS Router instance
13
+ * @access private
14
14
  */
15
- export default function ancillaryRouter({
16
- sessionTtl,
17
- }) {
15
+ export default function ancillaryRouter({ sessionTtl }) {
18
16
  // Router
19
17
  const router = new MutableRouter();
20
18
 
21
19
  // Session timeout
22
- router.all('/session-timeout', (req, res) => {
23
- res.render('casa/session-timeout.njk', {
20
+ router.all("/session-timeout", (req, res) => {
21
+ res.render("casa/session-timeout.njk", {
24
22
  sessionTtl: Math.floor(sessionTtl / 60),
25
23
  });
26
24
  });
@@ -1,31 +1,31 @@
1
1
  /* eslint-disable object-curly-newline,max-len */
2
- import MutableRouter from '../lib/MutableRouter.js';
3
- import skipWaypointMiddlewareFactory from '../middleware/skip-waypoint.js';
4
- import steerJourneyMiddlewareFactory from '../middleware/steer-journey.js';
5
- import sanitiseFieldsMiddlewareFactory from '../middleware/sanitise-fields.js';
6
- import gatherFieldsMiddlewareFactory from '../middleware/gather-fields.js';
7
- import validateFieldsMiddlewareFactory from '../middleware/validate-fields.js';
8
- import progressJourneyMiddlewareFactory from '../middleware/progress-journey.js';
9
- import waypointUrl from '../lib/waypoint-url.js';
10
- import logger from '../lib/logger.js';
11
- import { resolveMiddlewareHooks } from '../lib/utils.js';
12
- import { CONFIG_ERROR_VISIBILITY_ALWAYS } from '../lib/constants.js';
13
-
14
- const log = logger('routes:journey');
2
+ import MutableRouter from "../lib/MutableRouter.js";
3
+ import skipWaypointMiddlewareFactory from "../middleware/skip-waypoint.js";
4
+ import steerJourneyMiddlewareFactory from "../middleware/steer-journey.js";
5
+ import sanitiseFieldsMiddlewareFactory from "../middleware/sanitise-fields.js";
6
+ import gatherFieldsMiddlewareFactory from "../middleware/gather-fields.js";
7
+ import validateFieldsMiddlewareFactory from "../middleware/validate-fields.js";
8
+ import progressJourneyMiddlewareFactory from "../middleware/progress-journey.js";
9
+ import waypointUrl from "../lib/waypoint-url.js";
10
+ import logger from "../lib/logger.js";
11
+ import { resolveMiddlewareHooks } from "../lib/utils.js";
12
+ import { CONFIG_ERROR_VISIBILITY_ALWAYS } from "../lib/constants.js";
13
+
14
+ const log = logger("routes:journey");
15
15
 
16
16
  /**
17
+ * @param {import("../casa.js").GlobalHook} GlobalHook
17
18
  * @access private
18
- * @param {import('../casa.js').GlobalHook} GlobalHook
19
19
  */
20
20
 
21
21
  /**
22
+ * @param {import("../casa.js").Page} Page
22
23
  * @access private
23
- * @param {import('../casa.js').Page} Page
24
24
  */
25
25
 
26
26
  /**
27
+ * @param {import("../casa.js").Plan} Plan
27
28
  * @access private
28
- * @param {import('../casa.js').Plan} Plan
29
29
  */
30
30
 
31
31
  /**
@@ -38,49 +38,58 @@ const log = logger('routes:journey');
38
38
 
39
39
  const renderMiddlewareFactory = (view, contextFactory) => [
40
40
  (req, res, next) => {
41
- res.render(view, {
42
- // Common template variables for both GET and POST requests
43
- inEditMode: req.casa.editMode,
44
- editOriginUrl: req.casa.editOrigin,
45
- activeContextId: req.casa.journeyContext.identity.id,
46
- ...contextFactory(req),
47
- }, (err, templateString) => {
48
- if (err) {
49
- next(err);
50
- } else {
51
- res.send(templateString);
52
- }
53
- });
41
+ res.render(
42
+ view,
43
+ {
44
+ // Common template variables for both GET and POST requests
45
+ inEditMode: req.casa.editMode,
46
+ editOriginUrl: req.casa.editOrigin,
47
+ activeContextId: req.casa.journeyContext.identity.id,
48
+ ...contextFactory(req),
49
+ },
50
+ (err, templateString) => {
51
+ if (err) {
52
+ next(err);
53
+ } else {
54
+ res.send(templateString);
55
+ }
56
+ },
57
+ );
54
58
  },
55
59
  ];
56
60
 
57
61
  /**
58
- * generate page validation error
62
+ * Generate page validation error
59
63
  *
60
- * @param {object} errors object of page validation error
61
- * @param {object} req casa request object
62
- * @returns {object[]} array of error objects
64
+ * @param {object} errors Object of page validation error
65
+ * @param {object} req Casa request object
66
+ * @returns {object[]} Array of error objects
63
67
  */
64
- const generateGovukErrors = (errors, req) => Object.values(errors || {}).map(([error]) => ({
65
- text: req.t(error.summary, error.variables),
66
- href: error.fieldHref,
67
- }))
68
+ const generateGovukErrors = (errors, req) =>
69
+ Object.values(errors || {}).map(([error]) => ({
70
+ text: req.t(error.summary, error.variables),
71
+ href: error.fieldHref,
72
+ }));
68
73
  /**
69
- * handle errorVisibility flag and function and return boolean
74
+ * Handle errorVisibility flag and function and return boolean
70
75
  *
71
- * @param {symbol | Function} errorVisibility errorVisibility config option
72
- * @param {object} req casa request object
73
- * @returns {boolean} true if errorVisibility is "always" or function condition true
76
+ * @param {object} req Casa request object
77
+ * @param {symbol | Function} errorVisibility ErrorVisibility config option
78
+ * @returns {boolean} True if errorVisibility is "always" or function condition
79
+ * true
74
80
  */
75
- const resolveErrorVisibility = (req, errorVisibility) => (typeof errorVisibility === 'function' ? errorVisibility({ req }) : errorVisibility === CONFIG_ERROR_VISIBILITY_ALWAYS)
81
+ const resolveErrorVisibility = (req, errorVisibility) =>
82
+ typeof errorVisibility === "function"
83
+ ? errorVisibility({ req })
84
+ : errorVisibility === CONFIG_ERROR_VISIBILITY_ALWAYS;
76
85
 
77
86
  /**
78
87
  * Create an instance of the router for all waypoints visited during a Journey
79
88
  * through the Plan.
80
89
  *
81
- * @access private
82
90
  * @param {JourneyRouterOptions} opts Options
83
91
  * @returns {MutableRouter} Router
92
+ * @access private
84
93
  */
85
94
  export default function journeyRouter({
86
95
  globalHooks,
@@ -94,7 +103,7 @@ export default function journeyRouter({
94
103
 
95
104
  // Special "_" route which handles redirecting the user between sub-apps
96
105
  // /app1/_/?refmount=app2&route=prev
97
- router.all('/_', (req, res) => {
106
+ router.all("/_", (req, res) => {
98
107
  const mountUrl = `${req.baseUrl}/`;
99
108
  const refmount = req.query?.refmount;
100
109
  const route = req.query?.route;
@@ -104,7 +113,7 @@ export default function journeyRouter({
104
113
  const fallback = waypointUrl({
105
114
  mountUrl,
106
115
  waypoint: plan.traverse(req.casa.journeyContext, {
107
- stopCondition: () => (true), // we only need one; stop at the first
116
+ stopCondition: () => true, // we only need one; stop at the first
108
117
  })[0],
109
118
  });
110
119
 
@@ -113,37 +122,49 @@ export default function journeyRouter({
113
122
  // the user to our Plan and we don't intend to link back.
114
123
  if (!plan.getWaypoints().includes(refmount)) {
115
124
  redirectTo = fallback;
116
- } else if (route === 'prev') {
117
- const routes = plan.traversePrevRoutes(req.casa.journeyContext, { startWaypoint: refmount });
118
- redirectTo = routes.length ? waypointUrl({ mountUrl, waypoint: routes[0].target }) : fallback;
125
+ } else if (route === "prev") {
126
+ const routes = plan.traversePrevRoutes(req.casa.journeyContext, {
127
+ startWaypoint: refmount,
128
+ });
129
+ redirectTo = routes.length
130
+ ? waypointUrl({ mountUrl, waypoint: routes[0].target })
131
+ : fallback;
119
132
  } else {
120
- const routes = plan.traverseNextRoutes(req.casa.journeyContext, { startWaypoint: refmount });
133
+ const routes = plan.traverseNextRoutes(req.casa.journeyContext, {
134
+ startWaypoint: refmount,
135
+ });
121
136
  if (routes[0].target !== null) {
122
- redirectTo = routes.length ? waypointUrl({ mountUrl, waypoint: routes[0].target }) : fallback;
137
+ redirectTo = routes.length
138
+ ? waypointUrl({ mountUrl, waypoint: routes[0].target })
139
+ : fallback;
123
140
  } else {
124
141
  redirectTo = fallback;
125
142
  }
126
143
  }
127
144
 
128
145
  // Carry over any params
129
- const url = new URL(redirectTo, 'https://placeholder.test/');
146
+ const url = new URL(redirectTo, "https://placeholder.test/");
130
147
  const searchParams = new URLSearchParams(req.query);
131
- searchParams.delete('refmount');
132
- searchParams.delete('route');
148
+ searchParams.delete("refmount");
149
+ searchParams.delete("route");
133
150
  url.search = searchParams.toString();
134
- redirectTo = `${url.pathname.replace(/\/+/g, '/')}${url.search}`;
151
+ redirectTo = `${url.pathname.replace(/\/+/g, "/")}${url.search}`;
135
152
 
136
153
  log.trace(`Redirect to ${redirectTo}`);
137
154
  return res.redirect(redirectTo);
138
155
  });
139
156
 
140
157
  // Create GET / POST routes for each page
141
- const commonMiddleware = [
142
- ...csrfMiddleware,
143
- ];
158
+ const commonMiddleware = [...csrfMiddleware];
144
159
 
145
160
  pages.forEach((page) => {
146
- const { waypoint, view, hooks: pageHooks = [], fields, errorVisibility } = page;
161
+ const {
162
+ waypoint,
163
+ view,
164
+ hooks: pageHooks = [],
165
+ fields,
166
+ errorVisibility,
167
+ } = page;
147
168
  const waypointPath = `/${waypoint}`;
148
169
 
149
170
  let commonWaypointMiddleware = [
@@ -167,22 +188,40 @@ export default function journeyRouter({
167
188
  ...commonMiddleware,
168
189
  ...commonWaypointMiddleware,
169
190
 
170
- ...resolveMiddlewareHooks('journey.presteer', waypointPath, [...globalHooks, ...pageHooks]),
191
+ ...resolveMiddlewareHooks("journey.presteer", waypointPath, [
192
+ ...globalHooks,
193
+ ...pageHooks,
194
+ ]),
171
195
  ...steerJourneyMiddlewareFactory({ waypoint, plan }),
172
- ...resolveMiddlewareHooks('journey.poststeer', waypointPath, [...globalHooks, ...pageHooks]),
173
-
174
- ...resolveMiddlewareHooks('journey.prerender', waypointPath, [...globalHooks, ...pageHooks]),
196
+ ...resolveMiddlewareHooks("journey.poststeer", waypointPath, [
197
+ ...globalHooks,
198
+ ...pageHooks,
199
+ ]),
200
+
201
+ ...resolveMiddlewareHooks("journey.prerender", waypointPath, [
202
+ ...globalHooks,
203
+ ...pageHooks,
204
+ ]),
175
205
  renderMiddlewareFactory(view, (req) => {
176
- const displayErrors = resolveErrorVisibility(req, globalErrorVisibility) || resolveErrorVisibility(req, errorVisibility);
177
- const errors = displayErrors && (req.casa.journeyContext.getValidationErrorsForPageByField(waypoint) ?? Object.create(null));
206
+ const displayErrors =
207
+ resolveErrorVisibility(req, globalErrorVisibility) ||
208
+ resolveErrorVisibility(req, errorVisibility);
209
+ const errors =
210
+ displayErrors &&
211
+ (req.casa.journeyContext.getValidationErrorsForPageByField(
212
+ waypoint,
213
+ ) ??
214
+ Object.create(null));
178
215
  const govukErrors = displayErrors && generateGovukErrors(errors, req);
179
216
 
180
- return ({
217
+ return {
181
218
  formUrl: waypointUrl({ mountUrl: `${req.baseUrl}/`, waypoint }),
182
219
  formData: req.casa.journeyContext.getDataForPage(waypoint),
183
- formErrors: (Object.keys(errors).length && displayErrors) ? errors : null,
184
- formErrorsGovukArray: (govukErrors.length && displayErrors) ? govukErrors : null,
185
- })
220
+ formErrors:
221
+ Object.keys(errors).length && displayErrors ? errors : null,
222
+ formErrorsGovukArray:
223
+ govukErrors.length && displayErrors ? govukErrors : null,
224
+ };
186
225
  }),
187
226
  );
188
227
 
@@ -191,35 +230,70 @@ export default function journeyRouter({
191
230
  ...commonMiddleware,
192
231
  ...commonWaypointMiddleware,
193
232
 
194
- ...resolveMiddlewareHooks('journey.presteer', waypointPath, [...globalHooks, ...pageHooks]),
233
+ ...resolveMiddlewareHooks("journey.presteer", waypointPath, [
234
+ ...globalHooks,
235
+ ...pageHooks,
236
+ ]),
195
237
  ...steerJourneyMiddlewareFactory({ waypoint, plan }),
196
- ...resolveMiddlewareHooks('journey.poststeer', waypointPath, [...globalHooks, ...pageHooks]),
197
-
198
- ...resolveMiddlewareHooks('journey.presanitise', waypointPath, [...globalHooks, ...pageHooks]),
238
+ ...resolveMiddlewareHooks("journey.poststeer", waypointPath, [
239
+ ...globalHooks,
240
+ ...pageHooks,
241
+ ]),
242
+
243
+ ...resolveMiddlewareHooks("journey.presanitise", waypointPath, [
244
+ ...globalHooks,
245
+ ...pageHooks,
246
+ ]),
199
247
  ...sanitiseFieldsMiddlewareFactory({ waypoint, fields }),
200
- ...resolveMiddlewareHooks('journey.postsanitise', waypointPath, [...globalHooks, ...pageHooks]),
201
-
202
- ...resolveMiddlewareHooks('journey.pregather', waypointPath, [...globalHooks, ...pageHooks]),
248
+ ...resolveMiddlewareHooks("journey.postsanitise", waypointPath, [
249
+ ...globalHooks,
250
+ ...pageHooks,
251
+ ]),
252
+
253
+ ...resolveMiddlewareHooks("journey.pregather", waypointPath, [
254
+ ...globalHooks,
255
+ ...pageHooks,
256
+ ]),
203
257
  ...gatherFieldsMiddlewareFactory({ waypoint, fields }),
204
- ...resolveMiddlewareHooks('journey.postgather', waypointPath, [...globalHooks, ...pageHooks]),
205
-
206
- ...resolveMiddlewareHooks('journey.prevalidate', waypointPath, [...globalHooks, ...pageHooks]),
258
+ ...resolveMiddlewareHooks("journey.postgather", waypointPath, [
259
+ ...globalHooks,
260
+ ...pageHooks,
261
+ ]),
262
+
263
+ ...resolveMiddlewareHooks("journey.prevalidate", waypointPath, [
264
+ ...globalHooks,
265
+ ...pageHooks,
266
+ ]),
207
267
  ...validateFieldsMiddlewareFactory({ waypoint, fields, plan }),
208
- ...resolveMiddlewareHooks('journey.postvalidate', waypointPath, [...globalHooks, ...pageHooks]),
268
+ ...resolveMiddlewareHooks("journey.postvalidate", waypointPath, [
269
+ ...globalHooks,
270
+ ...pageHooks,
271
+ ]),
209
272
 
210
273
  // If there were validation errors, jump out of this route and into the
211
274
  // next, where the errors will be rendered
212
- (req, res, next) => (req.casa.journeyContext.hasValidationErrorsForPage(waypoint) ? next('route') : next()),
213
-
214
- ...resolveMiddlewareHooks('journey.preredirect', waypointPath, [...globalHooks, ...pageHooks]),
275
+ (req, res, next) =>
276
+ req.casa.journeyContext.hasValidationErrorsForPage(waypoint)
277
+ ? next("route")
278
+ : next(),
279
+
280
+ ...resolveMiddlewareHooks("journey.preredirect", waypointPath, [
281
+ ...globalHooks,
282
+ ...pageHooks,
283
+ ]),
215
284
  ...progressJourneyMiddlewareFactory({ waypoint, plan }),
216
285
  );
217
286
 
218
287
  router.post(
219
288
  waypointPath,
220
- ...resolveMiddlewareHooks('journey.prerender', waypointPath, [...globalHooks, ...pageHooks]),
289
+ ...resolveMiddlewareHooks("journey.prerender", waypointPath, [
290
+ ...globalHooks,
291
+ ...pageHooks,
292
+ ]),
221
293
  renderMiddlewareFactory(view, (req) => {
222
- const errors = req.casa.journeyContext.getValidationErrorsForPageByField(waypoint) ?? Object.create(null);
294
+ const errors =
295
+ req.casa.journeyContext.getValidationErrorsForPageByField(waypoint) ??
296
+ Object.create(null);
223
297
 
224
298
  // This is a convenience for the template. The `govukErrorSummary` macro
225
299
  // requires the errors be in a particular format, so here we provide our
@@ -228,7 +302,7 @@ export default function journeyRouter({
228
302
  // first one is shown.
229
303
  // Disabling security/detect-object-injection rule because both `errors`
230
304
  // and the `k` property are known entities
231
- const govukErrors = generateGovukErrors(errors, req)
305
+ const govukErrors = generateGovukErrors(errors, req);
232
306
 
233
307
  return {
234
308
  formUrl: waypointUrl({ mountUrl: `${req.baseUrl}/`, waypoint }),