@dwp/govuk-casa 8.15.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 (201) hide show
  1. package/README.md +9 -9
  2. package/dist/assets/css/casa.css +2 -1
  3. package/dist/assets/css/casa.css.map +1 -0
  4. package/dist/casa.d.ts +122 -99
  5. package/dist/casa.js +120 -88
  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 +89 -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 +24 -29
  40. package/dist/lib/field.js +41 -70
  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 +12 -17
  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 -26
  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 -20
  139. package/dist/routes/static.js.map +1 -1
  140. package/package.json +17 -16
  141. package/src/casa.js +134 -102
  142. package/src/lib/CasaTemplateLoader.js +24 -19
  143. package/src/lib/JourneyContext.js +147 -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 +74 -78
  154. package/src/lib/index.js +12 -12
  155. package/src/lib/logger.js +9 -9
  156. package/src/lib/mount.js +70 -80
  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 -40
  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 -30
  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/partials/scripts.njk +5 -3
  200. package/views/casa/partials/styles.njk +1 -4
  201. package/dist/assets/css/casa-ie8.css +0 -1
package/src/lib/Plan.js CHANGED
@@ -1,91 +1,103 @@
1
- import { Graph } from '@dagrejs/graphlib';
2
- import JourneyContext from './JourneyContext.js';
3
- import logger from './logger.js';
1
+ import { Graph } from "@dagrejs/graphlib";
2
+ import JourneyContext from "./JourneyContext.js";
3
+ import logger from "./logger.js";
4
4
 
5
- const log = logger('lib:plan');
5
+ const log = logger("lib:plan");
6
6
 
7
7
  /**
8
+ * @typedef {import("../casa").PlanRoute} PlanRoute
8
9
  * @access private
9
- * @typedef {import('../casa').PlanRoute} PlanRoute
10
10
  */
11
11
 
12
12
  /**
13
+ * @typedef {import("../casa").PlanRouteCondition} PlanRouteCondition
13
14
  * @access private
14
- * @typedef {import('../casa').PlanRouteCondition} PlanRouteCondition
15
15
  */
16
16
 
17
17
  /**
18
+ * @typedef {import("../casa").PlanTraverseOptions} PlanTraverseOptions
18
19
  * @access private
19
- * @typedef {import('../casa').PlanTraverseOptions} PlanTraverseOptions
20
20
  */
21
21
 
22
22
  /**
23
+ * @typedef {import("../casa").PlanArbiter} PlanArbiter
23
24
  * @access private
24
- * @typedef {import('../casa').PlanArbiter} PlanArbiter
25
25
  */
26
26
 
27
27
  /**
28
28
  * @typedef {object} PlanConstructorOptions
29
- * @property {boolean} [validateBeforeRouteCondition=true] Check page validity before conditions
30
- * @property {string|PlanArbiter} [arbiter=undefined] Arbitration mechanism
29
+ * @property {boolean} [validateBeforeRouteCondition=true] Check page validity
30
+ * before conditions. Default is `true`
31
+ * @property {string | PlanArbiter} [arbiter=undefined] Arbitration mechanism.
32
+ * Default is `undefined`
31
33
  */
32
34
 
33
35
  /**
34
36
  * Will check if the source waypoint has specifically passed validation, i.e
35
37
  * there is a "null" validation entry for the route source.
36
38
  *
37
- * @access private
38
39
  * @type {PlanRouteCondition}
40
+ * @access private
39
41
  */
40
42
  function defaultNextFollow(r, context) {
41
43
  const { validation: v = {} } = context.toObject();
42
- return Object.prototype.hasOwnProperty.call(v, r.source) && v[r.source] === null;
44
+ return (
45
+ Object.prototype.hasOwnProperty.call(v, r.source) && v[r.source] === null
46
+ );
43
47
  }
44
48
 
45
49
  /**
46
50
  * Will check if the target waypoint (the one we're moving back to) has
47
51
  * specifically passed validation.
48
52
  *
49
- * @access private
50
53
  * @type {PlanRouteCondition}
54
+ * @access private
51
55
  */
52
56
  function defaultPrevFollow(r, context) {
53
57
  const { validation: v = {} } = context.toObject();
54
- return Object.prototype.hasOwnProperty.call(v, r.target) && v[r.target] === null;
58
+ return (
59
+ Object.prototype.hasOwnProperty.call(v, r.target) && v[r.target] === null
60
+ );
55
61
  }
56
62
 
57
63
  /**
58
64
  * Validate a given waypoint ID.
59
65
  *
60
- * @access private
61
66
  * @param {string} val Waypoint ID
62
67
  * @returns {void}
63
68
  * @throws {TypeError} If waypoint ID is not a string
64
69
  * @throws {SyntaxError} If waypoint ID is incorrectly formatted
70
+ * @access private
65
71
  */
66
72
  function validateWaypointId(val) {
67
- if (typeof val !== 'string') {
68
- throw new TypeError(`Expected waypoint id to be a string, got ${typeof val}`);
73
+ if (typeof val !== "string") {
74
+ throw new TypeError(
75
+ `Expected waypoint id to be a string, got ${typeof val}`,
76
+ );
69
77
  }
70
- if (val.substr(0, 6) === 'url://' && !val.endsWith('/')) {
71
- throw new SyntaxError('url:// waypoints must include a trailing /')
78
+ if (val.substr(0, 6) === "url://" && !val.endsWith("/")) {
79
+ throw new SyntaxError("url:// waypoints must include a trailing /");
72
80
  }
73
81
  }
74
82
 
75
83
  /**
76
84
  * Validate a given route name.
77
85
  *
78
- * @access private
79
86
  * @param {string} val Route name
80
87
  * @returns {string} The route name
81
88
  * @throws {TypeError} If route name is not a string
82
89
  * @throws {ReferenceError} If route name is neither "next" or "prev"
90
+ * @access private
83
91
  */
84
92
  function validateRouteName(val) {
85
- if (typeof val !== 'string') {
86
- throw new TypeError(`Expected route name to be a string, got ${typeof val}`);
87
- } else if (!['next', 'prev'].includes(val)) {
88
- throw new ReferenceError(`Expected route name to be one of next or prev. Got ${val}`)
93
+ if (typeof val !== "string") {
94
+ throw new TypeError(
95
+ `Expected route name to be a string, got ${typeof val}`,
96
+ );
97
+ } else if (!["next", "prev"].includes(val)) {
98
+ throw new ReferenceError(
99
+ `Expected route name to be one of next or prev. Got ${val}`,
100
+ );
89
101
  }
90
102
  return val;
91
103
  }
@@ -93,26 +105,28 @@ function validateRouteName(val) {
93
105
  /**
94
106
  * Validate a given route condition.
95
107
  *
96
- * @access private
97
108
  * @param {PlanRouteCondition} val The condition function
98
109
  * @returns {void}
99
110
  * @throws {TypeError} If condition is not a string
111
+ * @access private
100
112
  */
101
113
  function validateRouteCondition(val) {
102
114
  if (!(val instanceof Function)) {
103
- throw new TypeError(`Expected route condition to be a function, got ${typeof val}`);
115
+ throw new TypeError(
116
+ `Expected route condition to be a function, got ${typeof val}`,
117
+ );
104
118
  }
105
119
  }
106
120
 
107
121
  /**
108
- * Creates a user friendly route structure from a given graph edge which will
109
- * be used in userland. This is the object that will be passed into follow
122
+ * Creates a user friendly route structure from a given graph edge which will be
123
+ * used in userland. This is the object that will be passed into follow
110
124
  * functions too as the "route" parameter.
111
125
  *
112
- * @access private
113
126
  * @param {object} dgraph Directed graph instance.
114
127
  * @param {object} edge Graph edge object.
115
128
  * @returns {PlanRoute} Route.
129
+ * @access private
116
130
  */
117
131
  const makeRouteObject = (dgraph, edge) => {
118
132
  const label = dgraph.edge(edge) || {};
@@ -140,13 +154,9 @@ const reExitNodeProtocol = /^[a-z]+:\/\//i;
140
154
  */
141
155
  const priv = new WeakMap();
142
156
 
143
- /**
144
- * @memberof module:@dwp/govuk-casa
145
- */
157
+ /** @memberof module:@dwp/govuk-casa */
146
158
  export default class Plan {
147
- /**
148
- * @type {string[]} These waypoints can be skipped
149
- */
159
+ /** @type {string[]} These Waypoints can be skipped */
150
160
  #skippableWaypoints;
151
161
 
152
162
  /**
@@ -174,14 +184,18 @@ export default class Plan {
174
184
  });
175
185
 
176
186
  // Gather options
177
- const options = Object.assign(Object.create(null), {
178
- // When true, the validation state of the source node must be `null` (i.e.
179
- // no validation errors) before any custom route conditions are evaluated.
180
- validateBeforeRouteCondition: true,
181
-
182
- // Traversal arbitration
183
- arbiter: undefined,
184
- }, opts);
187
+ const options = Object.assign(
188
+ Object.create(null),
189
+ {
190
+ // When true, the validation state of the source node must be `null` (i.e.
191
+ // no validation errors) before any custom route conditions are evaluated.
192
+ validateBeforeRouteCondition: true,
193
+
194
+ // Traversal arbitration
195
+ arbiter: undefined,
196
+ },
197
+ opts,
198
+ );
185
199
  Object.freeze(options);
186
200
 
187
201
  priv.set(this, {
@@ -217,7 +231,7 @@ export default class Plan {
217
231
  /**
218
232
  * Add one or more skippable waypoints.
219
233
  *
220
- * @param {...string} waypoints Waypoints
234
+ * @param {...string} waypoints Waypoints
221
235
  * @returns {Plan} Chain
222
236
  */
223
237
  addSkippables(...waypoints) {
@@ -261,7 +275,9 @@ export default class Plan {
261
275
  */
262
276
  getRoutes() {
263
277
  const self = priv.get(this);
264
- return self.dgraph.edges().map((edge) => makeRouteObject(self.dgraph, edge));
278
+ return self.dgraph
279
+ .edges()
280
+ .map((edge) => makeRouteObject(self.dgraph, edge));
265
281
  }
266
282
 
267
283
  /**
@@ -286,7 +302,9 @@ export default class Plan {
286
302
  */
287
303
  getOutwardRoutes(src, tgt = null) {
288
304
  const self = priv.get(this);
289
- return self.dgraph.outEdges(src, tgt).map((e) => makeRouteObject(self.dgraph, e));
305
+ return self.dgraph
306
+ .outEdges(src, tgt)
307
+ .map((e) => makeRouteObject(self.dgraph, e));
290
308
  }
291
309
 
292
310
  /**
@@ -298,14 +316,14 @@ export default class Plan {
298
316
  * @returns {PlanRoute[]} Route objects found.
299
317
  */
300
318
  getPrevOutwardRoutes(src, tgt = null) {
301
- return this.getOutwardRoutes(src, tgt).filter((r) => r.name === 'prev');
319
+ return this.getOutwardRoutes(src, tgt).filter((r) => r.name === "prev");
302
320
  }
303
321
 
304
322
  /**
305
323
  * Add a sequence of waypoints that will follow on from each other, with no
306
324
  * routing logic between them.
307
325
  *
308
- * @param {...string} waypoints Waypoints to add
326
+ * @param {...string} waypoints Waypoints to add
309
327
  * @returns {void}
310
328
  */
311
329
  addSequence(...waypoints) {
@@ -326,7 +344,7 @@ export default class Plan {
326
344
  * @returns {Plan} Chain
327
345
  */
328
346
  setNextRoute(src, tgt, follow) {
329
- return this.setNamedRoute(src, tgt, 'next', follow);
347
+ return this.setNamedRoute(src, tgt, "next", follow);
330
348
  }
331
349
 
332
350
  /**
@@ -338,7 +356,7 @@ export default class Plan {
338
356
  * @returns {Plan} Chain
339
357
  */
340
358
  setPrevRoute(src, tgt, follow) {
341
- return this.setNamedRoute(src, tgt, 'prev', follow);
359
+ return this.setNamedRoute(src, tgt, "prev", follow);
342
360
  }
343
361
 
344
362
  /**
@@ -349,8 +367,8 @@ export default class Plan {
349
367
  * condition must be true, and so to reverse the direction we also need that
350
368
  * same condition to be true.
351
369
  *
352
- * However, if the condition function uses the `source`/`target` property
353
- * of the route in some way, then we must reverse these before passing to the
370
+ * However, if the condition function uses the `source`/`target` property of
371
+ * the route in some way, then we must reverse these before passing to the
354
372
  * condition on the "prev" route because `source` in the condition will almost
355
373
  * certainly be referring to the source of the "next" route.
356
374
  *
@@ -364,21 +382,24 @@ export default class Plan {
364
382
  * @returns {Plan} Chain
365
383
  */
366
384
  setRoute(src, tgt, followNext = undefined, followPrev = undefined) {
367
- this.setNamedRoute(src, tgt, 'next', followNext);
385
+ this.setNamedRoute(src, tgt, "next", followNext);
368
386
 
369
387
  let followPrevious = followPrev;
370
388
  if (followPrevious === undefined) {
371
- followPrevious = followNext === undefined ? undefined : (r, c) => {
372
- const invertedRoute = {
373
- ...r,
374
- source: r.target,
375
- target: r.source,
376
- };
377
- return followNext(invertedRoute, c);
378
- }
389
+ followPrevious =
390
+ followNext === undefined
391
+ ? undefined
392
+ : (r, c) => {
393
+ const invertedRoute = {
394
+ ...r,
395
+ source: r.target,
396
+ target: r.source,
397
+ };
398
+ return followNext(invertedRoute, c);
399
+ };
379
400
  }
380
401
 
381
- this.setNamedRoute(tgt, src, 'prev', followPrevious);
402
+ this.setNamedRoute(tgt, src, "prev", followPrevious);
382
403
 
383
404
  return this;
384
405
  }
@@ -386,20 +407,22 @@ export default class Plan {
386
407
  /**
387
408
  * Create a named route between two waypoints, and give that route a function
388
409
  * that determine whether it should be followed during traversal operations.
389
- * Note that the source waypoint must be in a successful validation state
390
- * to be considered for traversal, regardless of what the custom function
410
+ * Note that the source waypoint must be in a successful validation state to
411
+ * be considered for traversal, regardless of what the custom function
391
412
  * determines.
392
413
  *
393
414
  * You may also define routes that take the user to any generic URL within the
394
- * same domain by using the `url://` protocol. These are considered
395
- * "exit nodes".
415
+ * same domain by using the `url://` protocol. These are considered "exit
416
+ * nodes".
396
417
  *
397
- * setNamedRoute("my-waypoint", "url:///some/absolute/url");
418
+ * SetNamedRoute("my-waypoint", "url:///some/absolute/url");
398
419
  *
399
420
  * @param {string} src Source waypoint.
400
421
  * @param {string} tgt Target waypoint.
401
- * @param {string} name Name of the route (must be unique for this waypoint pairing).
402
- * @param {PlanRouteCondition} follow Test function to determine if route can be followed.
422
+ * @param {string} name Name of the route (must be unique for this waypoint
423
+ * pairing).
424
+ * @param {PlanRouteCondition} follow Test function to determine if route can
425
+ * be followed.
403
426
  * @returns {Plan} Chain
404
427
  * @throws {Error} If attempting to create a "next" route from an exit node
405
428
  */
@@ -419,7 +442,12 @@ export default class Plan {
419
442
 
420
443
  // Warn if we're overwriting an existing edge on the same name
421
444
  if (self.dgraph.hasEdge(src, tgt, name)) {
422
- log.warn('Setting a route that already exists (%s, %s, %s). Will be overridden', src, tgt, name);
445
+ log.warn(
446
+ "Setting a route that already exists (%s, %s, %s). Will be overridden",
447
+ src,
448
+ tgt,
449
+ name,
450
+ );
423
451
  }
424
452
  self.dgraph.setEdge(src, tgt, { conditionName }, name);
425
453
 
@@ -428,18 +456,18 @@ export default class Plan {
428
456
  if (follow) {
429
457
  if (!self.options.validateBeforeRouteCondition) {
430
458
  followFunc = follow;
431
- } else if (name === 'next') {
459
+ } else if (name === "next") {
432
460
  // Retain the original function name of route condition
433
461
  followFunc = {
434
- [follow.name]: (r, c) => (defaultNextFollow(r, c) && follow(r, c)),
462
+ [follow.name]: (r, c) => defaultNextFollow(r, c) && follow(r, c),
435
463
  }[follow.name];
436
464
  } else {
437
465
  // Retain the original function name of route condition
438
466
  followFunc = {
439
- [follow.name]: (r, c) => (defaultPrevFollow(r, c) && follow(r, c)),
467
+ [follow.name]: (r, c) => defaultPrevFollow(r, c) && follow(r, c),
440
468
  }[follow.name];
441
469
  }
442
- } else if (name === 'next') {
470
+ } else if (name === "next") {
443
471
  followFunc = defaultNextFollow;
444
472
  } else {
445
473
  followFunc = defaultPrevFollow;
@@ -453,8 +481,8 @@ export default class Plan {
453
481
  }
454
482
 
455
483
  /**
456
- * This is a convenience method for traversing all "next" routes, and returning
457
- * the IDs of all waypoints visited along the way.
484
+ * This is a convenience method for traversing all "next" routes, and
485
+ * returning the IDs of all waypoints visited along the way.
458
486
  *
459
487
  * @param {JourneyContext} context Journey Context
460
488
  * @param {PlanTraverseOptions} options Options
@@ -473,7 +501,7 @@ export default class Plan {
473
501
  * @returns {PlanRoute[]} List of traversed waypoints
474
502
  */
475
503
  traverseNextRoutes(context, options = {}) {
476
- return this.traverseRoutes(context, { ...options, routeName: 'next' })
504
+ return this.traverseRoutes(context, { ...options, routeName: "next" });
477
505
  }
478
506
 
479
507
  /**
@@ -485,15 +513,16 @@ export default class Plan {
485
513
  * @returns {PlanRoute[]} List of traversed waypoints
486
514
  */
487
515
  traversePrevRoutes(context, options = {}) {
488
- return this.traverseRoutes(context, { ...options, routeName: 'prev' })
516
+ return this.traverseRoutes(context, { ...options, routeName: "prev" });
489
517
  }
490
518
 
491
519
  /**
492
520
  * Traverse through the plan from a particular starting waypoint. This is a
493
521
  * non-exhaustive Graph Exploration.
494
522
  *
495
- * The last route in the list will contain the source of the last waypoint that
496
- * can be reached, i.e. The waypoint that has no further satisfiable out-edges.
523
+ * The last route in the list will contain the source of the last waypoint
524
+ * that can be reached, i.e. The waypoint that has no further satisfiable
525
+ * out-edges.
497
526
  *
498
527
  * If a cyclical set of routes are encountered, traversal will stop after
499
528
  * reaching the first repeated waypoint.
@@ -505,7 +534,9 @@ export default class Plan {
505
534
  */
506
535
  traverseRoutes(context, options = {}) {
507
536
  if (!(context instanceof JourneyContext)) {
508
- throw new TypeError(`Expected context to be an instance of JourneyContext, got ${typeof context}`);
537
+ throw new TypeError(
538
+ `Expected context to be an instance of JourneyContext, got ${typeof context}`,
539
+ );
509
540
  }
510
541
 
511
542
  const self = priv.get(this);
@@ -513,13 +544,15 @@ export default class Plan {
513
544
  /** @type {PlanTraverseOptions} */
514
545
  const {
515
546
  startWaypoint = this.getWaypoints()[0],
516
- stopCondition = () => (false),
547
+ stopCondition = () => false,
517
548
  arbiter = self.options.arbiter,
518
549
  routeName,
519
550
  } = options;
520
551
 
521
552
  if (!self.dgraph.hasNode(startWaypoint)) {
522
- throw new ReferenceError(`Plan does not contain waypoint '${startWaypoint}'`);
553
+ throw new ReferenceError(
554
+ `Plan does not contain waypoint '${startWaypoint}'`,
555
+ );
523
556
  }
524
557
 
525
558
  validateRouteName(routeName);
@@ -537,7 +570,11 @@ export default class Plan {
537
570
  /* eslint-disable-next-line security/detect-object-injection */
538
571
  return self.follows[routeName][`${e.v}/${e.w}`](route, context);
539
572
  } catch (ex) {
540
- log.warn('Route follow function threw an exception, "%s" (%s)', ex.message, `${e.v} -> ${e.w}`);
573
+ log.warn(
574
+ 'Route follow function threw an exception, "%s" (%s)',
575
+ ex.message,
576
+ `${e.v} -> ${e.w}`,
577
+ );
541
578
  return false;
542
579
  }
543
580
  });
@@ -545,10 +582,12 @@ export default class Plan {
545
582
  // When there's more than one candidate route to take, we need help to choose
546
583
  if (target.length > 1) {
547
584
  const satisfied = target.map((t) => `${t.v} -> ${t.w}`);
548
- log.debug(`Multiple routes were satisfied for "${routeName}" from "${startWP}" (${satisfied.join(' / ')}). Deciding how to resolve ...`);
585
+ log.debug(
586
+ `Multiple routes were satisfied for "${routeName}" from "${startWP}" (${satisfied.join(" / ")}). Deciding how to resolve ...`,
587
+ );
549
588
 
550
- if (arbiter === 'auto') {
551
- log.debug('Using automatic arbitration process');
589
+ if (arbiter === "auto") {
590
+ log.debug("Using automatic arbitration process");
552
591
  const targetNames = target.map(({ w }) => w);
553
592
  const forwardTraversal = this.traverseNextRoutes(context, {
554
593
  stopCondition: ({ source }) => targetNames.includes(source),
@@ -556,7 +595,7 @@ export default class Plan {
556
595
  const resolved = forwardTraversal.pop();
557
596
  target = target.filter((t) => t.w === resolved.source);
558
597
  } else if (arbiter instanceof Function) {
559
- log.debug('Using custom arbitration process');
598
+ log.debug("Using custom arbitration process");
560
599
  // Convert to routeObject and back to edge object so that only the
561
600
  // routeObject is used in the public API
562
601
  target = arbiter({
@@ -564,9 +603,13 @@ export default class Plan {
564
603
  journeyContext: context,
565
604
  travereOptions: options,
566
605
  });
567
- target = target.map((r) => ({ v: r.source, w: r.target, name: r.name }));
606
+ target = target.map((r) => ({
607
+ v: r.source,
608
+ w: r.target,
609
+ name: r.name,
610
+ }));
568
611
  } else {
569
- log.warn('Unable to arbitrate');
612
+ log.warn("Unable to arbitrate");
570
613
  target = [];
571
614
  }
572
615
  }
@@ -593,15 +636,20 @@ export default class Plan {
593
636
 
594
637
  return results;
595
638
  }
596
- log.debug('Encountered loop (%s). Stopping traversal.', `${route.source} -> ${route.target}`);
639
+ log.debug(
640
+ "Encountered loop (%s). Stopping traversal.",
641
+ `${route.source} -> ${route.target}`,
642
+ );
597
643
  }
598
644
 
599
- return [makeRouteObject(self.dgraph, {
600
- v: startWP,
601
- w: null,
602
- name: routeName,
603
- label: {},
604
- })];
645
+ return [
646
+ makeRouteObject(self.dgraph, {
647
+ v: startWP,
648
+ w: null,
649
+ name: routeName,
650
+ label: {},
651
+ }),
652
+ ];
605
653
  };
606
654
 
607
655
  return traverse(startWaypoint);
@@ -1,27 +1,27 @@
1
- import lodash from 'lodash';
1
+ import lodash from "lodash";
2
2
 
3
3
  const { isPlainObject } = lodash; // CommonJS
4
4
 
5
5
  const params = new WeakMap();
6
6
 
7
7
  /**
8
+ * @typedef {import("../casa").ValidateContext} ValidateContext
8
9
  * @access private
9
- * @typedef {import('../casa').ValidateContext} ValidateContext
10
10
  */
11
11
 
12
12
  /**
13
+ * @typedef {import("../casa").ErrorMessageConfig} ErrorMessageConfig
13
14
  * @access private
14
- * @typedef {import('../casa').ErrorMessageConfig} ErrorMessageConfig
15
15
  */
16
16
 
17
17
  /**
18
+ * @typedef {import("../casa").ErrorMessageConfigObject} ErrorMessageConfigObject
18
19
  * @access private
19
- * @typedef {import('../casa').ErrorMessageConfigObject} ErrorMessageConfigObject
20
20
  */
21
21
 
22
22
  /**
23
- * @class
24
23
  * @memberof module:@dwp/govuk-casa
24
+ * @class
25
25
  */
26
26
  export default class ValidationError {
27
27
  /**
@@ -30,24 +30,25 @@ export default class ValidationError {
30
30
  * <br/><br/>
31
31
  *
32
32
  * In the case of `errorMsg` being a function, this will be called at runtime,
33
- * at the point that errors are generated within the `validate()`,
34
- * methods, and will be passed the `dataContext`.
35
- * <br/><br/>
33
+ * at the point that errors are generated within the `validate()`, methods,
34
+ * and will be passed the `dataContext`. <br/><br/>
36
35
  *
37
36
  * `dataContext` is an object containing the same data passed to all
38
- * validators' `validate()` methods. In the case of `errorMsg` being
39
- * a function, this data is passed to that function in order to help resolve to
37
+ * validators' `validate()` methods. In the case of `errorMsg` being a
38
+ * function, this data is passed to that function in order to help resolve to
40
39
  * an error message config object.
41
40
  *
42
41
  * @param {object} args Arguments
43
- * @param {ErrorMessageConfig} args.errorMsg Error message config to seed ValidationError
44
- * @param {ValidateContext} [args.dataContext={}] Data for error msg function
42
+ * @param {ErrorMessageConfig} args.errorMsg Error message config to seed
43
+ * ValidationError
44
+ * @param {ValidateContext} [args.dataContext={}] Data for error msg function.
45
+ * Default is `{}`
45
46
  * @returns {ValidationError} Error instance
46
47
  * @throws {TypeError} If errorMsg is not in a valid type
47
48
  */
48
49
  static make({ errorMsg, dataContext = {} }) {
49
50
  // Convert strings to the most basic object primitive
50
- if (typeof errorMsg === 'string') {
51
+ if (typeof errorMsg === "string") {
51
52
  return new ValidationError({
52
53
  summary: errorMsg,
53
54
  inline: errorMsg,
@@ -63,7 +64,7 @@ export default class ValidationError {
63
64
 
64
65
  // Use the user-defined function to generate an error primitive for the
65
66
  // given context
66
- if (typeof errorMsg === 'function') {
67
+ if (typeof errorMsg === "function") {
67
68
  return new ValidationError(errorMsg.call(null, { ...dataContext }));
68
69
  }
69
70
 
@@ -77,19 +78,22 @@ export default class ValidationError {
77
78
  }
78
79
 
79
80
  // Unsupported
80
- throw new TypeError('errorMsg must be a string, Error, primitive object or function that generates a primitive object');
81
+ throw new TypeError(
82
+ "errorMsg must be a string, Error, primitive object or function that generates a primitive object",
83
+ );
81
84
  }
82
85
 
83
86
  /**
84
87
  * Create a ValidationError.
85
88
  *
86
- * @param {string|ErrorMessageConfigObject} errorParam Error configuration
89
+ * @param {string | ErrorMessageConfigObject} errorParam Error configuration
87
90
  */
88
91
  constructor(errorParam = {}) {
89
- if (!isPlainObject(errorParam) && typeof errorParam !== 'string') {
90
- throw new TypeError('Constructor requires a string or object');
92
+ if (!isPlainObject(errorParam) && typeof errorParam !== "string") {
93
+ throw new TypeError("Constructor requires a string or object");
91
94
  }
92
- const error = typeof errorParam === 'string' ? { summary: errorParam } : errorParam;
95
+ const error =
96
+ typeof errorParam === "string" ? { summary: errorParam } : errorParam;
93
97
 
94
98
  // Store parameters for later use in applying contexts
95
99
  const originals = {
@@ -133,7 +137,7 @@ export default class ValidationError {
133
137
  const originals = params.get(this);
134
138
 
135
139
  // Expand variables
136
- if (typeof originals.variables === 'function') {
140
+ if (typeof originals.variables === "function") {
137
141
  this.variables = originals.variables.call(this, context);
138
142
  }
139
143
 
@@ -150,7 +154,7 @@ export default class ValidationError {
150
154
  fieldHref += focusSuffix[0];
151
155
  }
152
156
 
153
- this.field = context.fieldName + (originals.fieldKeySuffix || '');
157
+ this.field = context.fieldName + (originals.fieldKeySuffix || "");
154
158
  this.fieldHref = fieldHref;
155
159
  this.focusSuffix = focusSuffix || [];
156
160
  }