@dwp/govuk-casa 8.2.1 → 8.2.4

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 (67) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +1 -0
  3. package/dist/casa.d.ts +203 -1
  4. package/dist/casa.js +131 -2
  5. package/dist/lib/CasaTemplateLoader.d.ts +4 -0
  6. package/dist/lib/CasaTemplateLoader.js +5 -0
  7. package/dist/lib/JourneyContext.d.ts +85 -13
  8. package/dist/lib/JourneyContext.js +78 -5
  9. package/dist/lib/Plan.d.ts +122 -49
  10. package/dist/lib/Plan.js +161 -37
  11. package/dist/lib/ValidationError.d.ts +38 -48
  12. package/dist/lib/ValidationError.js +30 -42
  13. package/dist/lib/ValidatorFactory.d.ts +42 -52
  14. package/dist/lib/ValidatorFactory.js +37 -48
  15. package/dist/lib/configuration-ingestor.d.ts +18 -4
  16. package/dist/lib/configuration-ingestor.js +23 -10
  17. package/dist/lib/configure.d.ts +4 -0
  18. package/dist/lib/configure.js +20 -52
  19. package/dist/lib/end-session.d.ts +3 -2
  20. package/dist/lib/end-session.js +2 -1
  21. package/dist/lib/field.d.ts +97 -35
  22. package/dist/lib/field.js +90 -41
  23. package/dist/lib/nunjucks-filters.d.ts +12 -2
  24. package/dist/lib/nunjucks-filters.js +11 -1
  25. package/dist/lib/nunjucks.d.ts +1 -0
  26. package/dist/lib/nunjucks.js +1 -0
  27. package/dist/lib/utils.d.ts +46 -14
  28. package/dist/lib/utils.js +43 -26
  29. package/dist/lib/validators/dateObject.d.ts +75 -1
  30. package/dist/lib/validators/dateObject.js +29 -18
  31. package/dist/lib/validators/email.d.ts +28 -1
  32. package/dist/lib/validators/email.js +20 -9
  33. package/dist/lib/validators/inArray.d.ts +34 -1
  34. package/dist/lib/validators/inArray.js +21 -0
  35. package/dist/lib/validators/index.js +3 -0
  36. package/dist/lib/validators/nino.d.ts +34 -1
  37. package/dist/lib/validators/nino.js +17 -7
  38. package/dist/lib/validators/postalAddressObject.d.ts +68 -1
  39. package/dist/lib/validators/postalAddressObject.js +27 -15
  40. package/dist/lib/validators/regex.d.ts +35 -1
  41. package/dist/lib/validators/regex.js +17 -7
  42. package/dist/lib/validators/required.d.ts +28 -1
  43. package/dist/lib/validators/required.js +19 -6
  44. package/dist/lib/validators/strlen.d.ts +40 -1
  45. package/dist/lib/validators/strlen.js +18 -8
  46. package/dist/lib/validators/wordCount.d.ts +40 -1
  47. package/dist/lib/validators/wordCount.js +18 -8
  48. package/dist/lib/waypoint-url.d.ts +1 -0
  49. package/dist/lib/waypoint-url.js +10 -0
  50. package/dist/middleware/data.js +21 -5
  51. package/dist/middleware/gather-fields.js +1 -0
  52. package/dist/middleware/pre.js +1 -0
  53. package/dist/middleware/steer-journey.js +2 -1
  54. package/dist/middleware/strip-proxy-path.d.ts +4 -0
  55. package/dist/middleware/strip-proxy-path.js +56 -0
  56. package/dist/middleware/validate-fields.js +3 -0
  57. package/dist/routes/ancillary.d.ts +16 -5
  58. package/dist/routes/ancillary.js +7 -3
  59. package/dist/routes/journey.d.ts +30 -6
  60. package/dist/routes/journey.js +27 -0
  61. package/dist/routes/static.d.ts +1 -0
  62. package/dist/routes/static.js +2 -1
  63. package/package.json +16 -11
  64. package/views/casa/components/character-count/README.md +1 -1
  65. package/views/casa/components/input/README.md +1 -1
  66. package/views/casa/components/radios/README.md +2 -2
  67. package/views/casa/components/textarea/README.md +1 -1
package/dist/lib/Plan.js CHANGED
@@ -19,13 +19,33 @@ const graphlib_1 = require("graphlib");
19
19
  const JourneyContext_js_1 = __importDefault(require("./JourneyContext.js"));
20
20
  const logger_js_1 = __importDefault(require("./logger.js"));
21
21
  const log = (0, logger_js_1.default)('lib:plan');
22
+ /**
23
+ * @access private
24
+ * @typedef {import('../casa').PlanRoute} PlanRoute
25
+ */
26
+ /**
27
+ * @access private
28
+ * @typedef {import('../casa').PlanRouteCondition} PlanRouteCondition
29
+ */
30
+ /**
31
+ * @access private
32
+ * @typedef {import('../casa').PlanTraverseOptions} PlanTraverseOptions
33
+ */
34
+ /**
35
+ * @access private
36
+ * @typedef {import('../casa').PlanArbiter} PlanArbiter
37
+ */
38
+ /**
39
+ * @typedef {object} PlanConstructorOptions
40
+ * @property {boolean} [validateBeforeRouteCondition=true] Check page validity before conditions
41
+ * @property {string|PlanArbiter} [arbiter=undefined] Arbitration mechanism
42
+ */
22
43
  /**
23
44
  * Will check if the source waypoint has specifically passed validation, i.e
24
45
  * there is a "null" validation entry for the route source.
25
46
  *
26
- * @param {object} r Route meta.
27
- * @param {JourneyContext} context Journey Context.
28
- * @returns {boolean} Condition result.
47
+ * @access private
48
+ * @type {PlanRouteCondition}
29
49
  */
30
50
  function defaultNextFollow(r, context) {
31
51
  const { validation: v = {} } = context.toObject();
@@ -35,14 +55,22 @@ function defaultNextFollow(r, context) {
35
55
  * Will check if the target waypoint (the one we're moving back to) has
36
56
  * specifically passed validation.
37
57
  *
38
- * @param {object} r Route meta.
39
- * @param {JourneyContext} context Journey context.
40
- * @returns {boolean} Condition result.
58
+ * @access private
59
+ * @type {PlanRouteCondition}
41
60
  */
42
61
  function defaultPrevFollow(r, context) {
43
62
  const { validation: v = {} } = context.toObject();
44
63
  return Object.prototype.hasOwnProperty.call(v, r.target) && v[r.target] === null;
45
64
  }
65
+ /**
66
+ * Validate a given waypoint ID.
67
+ *
68
+ * @access private
69
+ * @param {string} val Waypoint ID
70
+ * @returns {void}
71
+ * @throws {TypeError} If waypoint ID is not a string
72
+ * @throws {SyntaxError} If waypoint ID is incorrectly formatted
73
+ */
46
74
  function validateWaypointId(val) {
47
75
  if (typeof val !== 'string') {
48
76
  throw new TypeError(`Expected waypoint id to be a string, got ${typeof val}`);
@@ -51,6 +79,15 @@ function validateWaypointId(val) {
51
79
  throw new SyntaxError('url:// waypoints must include a trailing /');
52
80
  }
53
81
  }
82
+ /**
83
+ * Validate a given route name.
84
+ *
85
+ * @access private
86
+ * @param {string} val Route name
87
+ * @returns {string} The route name
88
+ * @throws {TypeError} If route name is not a string
89
+ * @throws {ReferenceError} If route name is neither "next" or "prev"
90
+ */
54
91
  function validateRouteName(val) {
55
92
  if (typeof val !== 'string') {
56
93
  throw new TypeError(`Expected route name to be a string, got ${typeof val}`);
@@ -60,6 +97,14 @@ function validateRouteName(val) {
60
97
  }
61
98
  return val;
62
99
  }
100
+ /**
101
+ * Validate a given route condition.
102
+ *
103
+ * @access private
104
+ * @param {PlanRouteCondition} val The condition function
105
+ * @returns {void}
106
+ * @throws {TypeError} If condition is not a string
107
+ */
63
108
  function validateRouteCondition(val) {
64
109
  if (!(val instanceof Function)) {
65
110
  throw new TypeError(`Expected route condition to be a function, got ${typeof val}`);
@@ -70,9 +115,10 @@ function validateRouteCondition(val) {
70
115
  * be used in userland. This is the object that will be passed into follow
71
116
  * functions too as the "route" parameter.
72
117
  *
118
+ * @access private
73
119
  * @param {object} dgraph Directed graph instance.
74
120
  * @param {object} edge Graph edge object.
75
- * @returns {object} Route.
121
+ * @returns {PlanRoute} Route.
76
122
  */
77
123
  const makeRouteObject = (dgraph, edge) => {
78
124
  const label = dgraph.edge(edge) || {};
@@ -86,16 +132,25 @@ const makeRouteObject = (dgraph, edge) => {
86
132
  };
87
133
  /**
88
134
  * Exit nodes begin with a protocol format, such as `url://`, `http://`, etc
135
+ *
136
+ * @access private
89
137
  */
90
138
  const reExitNodeProtocol = /^[a-z]+:\/\//i;
139
+ /**
140
+ * For storing private properties for each instance
141
+ *
142
+ * @access private
143
+ * @todo Use property private class properties.
144
+ */
91
145
  const priv = new WeakMap();
146
+ /**
147
+ * @memberof module:@dwp/govuk-casa
148
+ */
92
149
  class Plan {
93
150
  /**
94
151
  * Create a Plan.
95
152
  *
96
- * @param {object} opts Options
97
- * @param {boolean} [opts.validateBeforeRouteCondition=true] Check page validity before conditions
98
- * @param {Function|string} [opts.arbiter=undefined] Arbitration mechanism
153
+ * @param {PlanConstructorOptions} opts Options
99
154
  */
100
155
  constructor(opts = {}) {
101
156
  /**
@@ -137,6 +192,11 @@ class Plan {
137
192
  static isExitNode(name) {
138
193
  return reExitNodeProtocol.test(name);
139
194
  }
195
+ /**
196
+ * Retrieve the options set on this Plan.
197
+ *
198
+ * @returns {PlanConstructorOptions} Options map
199
+ */
140
200
  getOptions() {
141
201
  return priv.get(this).options;
142
202
  }
@@ -152,7 +212,7 @@ class Plan {
152
212
  * Add one or more skippable waypoints.
153
213
  *
154
214
  * @param {...string} waypoints Waypoints
155
- * @returns {Plan}{ Chain}
215
+ * @returns {Plan} Chain
156
216
  */
157
217
  addSkippables(...waypoints) {
158
218
  __classPrivateFieldSet(this, _Plan_skippableWaypoints, [...__classPrivateFieldGet(this, _Plan_skippableWaypoints, "f"), ...waypoints], "f");
@@ -167,16 +227,40 @@ class Plan {
167
227
  isSkippable(waypoint) {
168
228
  return __classPrivateFieldGet(this, _Plan_skippableWaypoints, "f").indexOf(waypoint) > -1;
169
229
  }
230
+ /**
231
+ * Retrieve all waypoints in this Plan (order is arbitrary).
232
+ *
233
+ * @returns {string[]} List of waypoints
234
+ */
170
235
  getWaypoints() {
171
236
  return priv.get(this).dgraph.nodes();
172
237
  }
238
+ /**
239
+ * Determine if the given waypoint exists in this Plan.
240
+ *
241
+ * @param {string} waypoint Waypoint to search for
242
+ * @returns {boolean} Result
243
+ */
173
244
  containsWaypoint(waypoint) {
174
245
  return this.getWaypoints().includes(waypoint);
175
246
  }
247
+ /**
248
+ * Get all route information.
249
+ *
250
+ * @returns {PlanRoute[]} Routes
251
+ */
176
252
  getRoutes() {
177
253
  const self = priv.get(this);
178
254
  return self.dgraph.edges().map((edge) => makeRouteObject(self.dgraph, edge));
179
255
  }
256
+ /**
257
+ * Get the condition function for the given parameters.
258
+ *
259
+ * @param {string} src Source waypoint
260
+ * @param {string} tgt Target waypoint
261
+ * @param {string} name Route name
262
+ * @returns {PlanRouteCondition} Route condition function
263
+ */
180
264
  getRouteCondition(src, tgt, name) {
181
265
  return priv.get(this).follows[validateRouteName(name)][`${src}/${tgt}`];
182
266
  }
@@ -185,8 +269,8 @@ class Plan {
185
269
  * optional target waypoint.
186
270
  *
187
271
  * @param {string} src Source waypoint.
188
- * @param {string} tgt Target waypoint (optional).
189
- * @returns {Array<object>} Route objects found.
272
+ * @param {string} [tgt] Target waypoint.
273
+ * @returns {PlanRoute[]} Route objects found.
190
274
  */
191
275
  getOutwardRoutes(src, tgt = null) {
192
276
  const self = priv.get(this);
@@ -197,12 +281,19 @@ class Plan {
197
281
  * optional target waypoint, matching the "prev" name.
198
282
  *
199
283
  * @param {string} src Source waypoint.
200
- * @param {string} tgt Target waypoint (optional).
201
- * @returns {Array<object>} Route objects found.
284
+ * @param {string} [tgt] Target waypoint.
285
+ * @returns {PlanRoute[]} Route objects found.
202
286
  */
203
287
  getPrevOutwardRoutes(src, tgt = null) {
204
288
  return this.getOutwardRoutes(src, tgt).filter((r) => r.name === 'prev');
205
289
  }
290
+ /**
291
+ * Add a sequence of waypoints that will follow on from each other, with no
292
+ * routing logic between them.
293
+ *
294
+ * @param {...string} waypoints Waypoints to add
295
+ * @returns {void}
296
+ */
206
297
  addSequence(...waypoints) {
207
298
  // Setup simple double routes (next/prev) between all waypoints in this list
208
299
  for (let i = 0, l = waypoints.length - 1; i < l; i += 1) {
@@ -211,21 +302,37 @@ class Plan {
211
302
  this.setRoute(waypoints[i], waypoints[i + 1]);
212
303
  }
213
304
  }
305
+ /**
306
+ * Create a new directed route between two waypoints, labelled as "next".
307
+ *
308
+ * @param {string} src Source waypoint
309
+ * @param {string} tgt Target waypoint
310
+ * @param {PlanRouteCondition} follow Route condition function
311
+ * @returns {Plan} Chain
312
+ */
214
313
  setNextRoute(src, tgt, follow) {
215
314
  return this.setNamedRoute(src, tgt, 'next', follow);
216
315
  }
316
+ /**
317
+ * Create a new directed route between two waypoints, labelled as "prev".
318
+ *
319
+ * @param {string} src Source waypoint
320
+ * @param {string} tgt Target waypoint
321
+ * @param {PlanRouteCondition} follow Route condition function
322
+ * @returns {Plan} Chain
323
+ */
217
324
  setPrevRoute(src, tgt, follow) {
218
325
  return this.setNamedRoute(src, tgt, 'prev', follow);
219
326
  }
220
327
  /**
221
328
  * Adds both a "next" and "prev" route between the two waypoints.
222
329
  *
223
- * By default, the "prev" route will use the same "follow" test as the "next"
224
- * route. This makes sense in that in order to get the target, the test must
225
- * have been true, and so to reverse the direction we also need that same test
226
- * to be true.
330
+ * By default, the "prev" route will use the same "follow" condition as the
331
+ * "next" route. This makes sense in that in order to get to the target, the
332
+ * condition must be true, and so to reverse the direction we also need that
333
+ * same condition to be true.
227
334
  *
228
- * However, if the condition function uses the `source`/`target`
335
+ * However, if the condition function uses the `source`/`target` property
229
336
  * of the route in some way, then we must reverse these before passing to the
230
337
  * condition on the "prev" route because `source` in the condition will almost
231
338
  * certainly be referring to the source of the "next" route.
@@ -235,9 +342,9 @@ class Plan {
235
342
  *
236
343
  * @param {string} src Source waypoint.
237
344
  * @param {string} tgt Target waypoint.
238
- * @param {Function} followNext Follow test function.
239
- * @param {Function} followPrev Follow test function.
240
- * @returns {Plan} Self.
345
+ * @param {PlanRouteCondition} [followNext] Follow test function.
346
+ * @param {PlanRouteCondition} [followPrev] Follow test function.
347
+ * @returns {Plan} Chain
241
348
  */
242
349
  setRoute(src, tgt, followNext = undefined, followPrev = undefined) {
243
350
  this.setNamedRoute(src, tgt, 'next', followNext);
@@ -267,7 +374,7 @@ class Plan {
267
374
  * @param {string} src Source waypoint.
268
375
  * @param {string} tgt Target waypoint.
269
376
  * @param {string} name Name of the route (must be unique for this waypoint pairing).
270
- * @param {Function} follow Test function to determine if route can be followed.
377
+ * @param {PlanRouteCondition} follow Test function to determine if route can be followed.
271
378
  * @returns {Plan} Chain
272
379
  * @throws {Error} If attempting to create a "next" route from an exit node
273
380
  */
@@ -321,16 +428,32 @@ class Plan {
321
428
  * This is a convenience method for traversing all "next" routes, and returning
322
429
  * the IDs of all waypoints visited along the way.
323
430
  *
324
- * @param {JourneyContext} context Journey Context.
325
- * @param {object} options Options.
326
- * @returns {Array<string>} List of traversed waypoints.
431
+ * @param {JourneyContext} context Journey Context
432
+ * @param {PlanTraverseOptions} options Options
433
+ * @returns {string[]} List of traversed waypoints
327
434
  */
328
435
  traverse(context, options = {}) {
329
436
  return this.traverseNextRoutes(context, options).map((e) => e.source);
330
437
  }
438
+ /**
439
+ * Traverse the Plan by following all "next" routes, and returning the IDs of
440
+ * all waypoints visited along the way.
441
+ *
442
+ * @param {JourneyContext} context Journey Context
443
+ * @param {PlanTraverseOptions} options Options
444
+ * @returns {PlanRoute[]} List of traversed waypoints
445
+ */
331
446
  traverseNextRoutes(context, options = {}) {
332
447
  return this.traverseRoutes(context, Object.assign(Object.assign({}, options), { routeName: 'next' }));
333
448
  }
449
+ /**
450
+ * Traverse the Plan by following all "prev" routes, and returning the IDs of
451
+ * all waypoints visited along the way.
452
+ *
453
+ * @param {JourneyContext} context Journey Context
454
+ * @param {PlanTraverseOptions} options Options
455
+ * @returns {PlanRoute[]} List of traversed waypoints
456
+ */
334
457
  traversePrevRoutes(context, options = {}) {
335
458
  return this.traverseRoutes(context, Object.assign(Object.assign({}, options), { routeName: 'prev' }));
336
459
  }
@@ -344,16 +467,9 @@ class Plan {
344
467
  * If a cyclical set of routes are encountered, traversal will stop after
345
468
  * reaching the first repeated waypoint.
346
469
  *
347
- * Options:
348
- * string startWaypoint = Waypoint from which to start traversal
349
- * string routeName = Follow routes matching this name (next | prev)
350
- * Map history = Used to detect loops in traversal (internal use)
351
- * function stopCondition = Condition that, if true, will stop traversal (useful for performance)
352
- * function|string arbiter = If mutliple target routes found, this decides which to use (if any)
353
- *
354
470
  * @param {JourneyContext} context Journey context
355
- * @param {object} options Options
356
- * @returns {Array<object>} Routes that were traversed
471
+ * @param {PlanTraverseOptions} options Options
472
+ * @returns {PlanRoute[]} Routes that were traversed
357
473
  * @throws {TypeError} When context is not a JourneyContext
358
474
  */
359
475
  traverseRoutes(context, options = {}) {
@@ -361,6 +477,7 @@ class Plan {
361
477
  throw new TypeError(`Expected context to be an instance of JourneyContext, got ${typeof context}`);
362
478
  }
363
479
  const self = priv.get(this);
480
+ /** @type {PlanTraverseOptions} */
364
481
  const { startWaypoint = this.getWaypoints()[0], stopCondition = () => (false), arbiter = self.options.arbiter, routeName, } = options;
365
482
  if (!self.dgraph.hasNode(startWaypoint)) {
366
483
  throw new ReferenceError(`Plan does not contain waypoint '${startWaypoint}'`);
@@ -398,7 +515,14 @@ class Plan {
398
515
  }
399
516
  else if (arbiter instanceof Function) {
400
517
  log.debug('Using custom arbitration process');
401
- target = arbiter(target, Object.assign({ context }, options));
518
+ // Convert to routeObject and back to edge object so that only the
519
+ // routeObject is used in the public API
520
+ target = arbiter({
521
+ targets: target.map((t) => makeRouteObject(self.dgraph, t)),
522
+ journeyContext: context,
523
+ travereOptions: options,
524
+ });
525
+ target = target.map((r) => ({ v: r.source, w: r.target, name: r.name }));
402
526
  }
403
527
  else {
404
528
  log.warn('Unable to arbitrate');
@@ -1,65 +1,53 @@
1
1
  /**
2
- * @typedef {import('./ValidatorFactory').ValidateContext} ValidateContext
2
+ * @access private
3
+ * @typedef {import('../casa').ValidateContext} ValidateContext
4
+ */
5
+ /**
6
+ * @access private
7
+ * @typedef {import('../casa').ErrorMessageConfig} ErrorMessageConfig
8
+ */
9
+ /**
10
+ * @access private
11
+ * @typedef {import('../casa').ErrorMessageConfigObject} ErrorMessageConfigObject
12
+ */
13
+ /**
14
+ * @class
15
+ * @memberof module:@dwp/govuk-casa
3
16
  */
4
17
  export default class ValidationError {
5
18
  /**
6
19
  * Make a ValidationError instance from a primitive object (or a function that
7
20
  * returns a primitive object) that is specific to the given journey context.
21
+ * <br/><br/>
8
22
  *
9
- * The returned `error` (or the function that returns the equivalent) must
10
- * match the structure required by the ValidationError constructor.
11
- *
12
- * `errorMsg` can be one of these formats:
13
- * String => 'common:errors.my-error-message'
14
- * Object => (see constructor argument for structure of this object)
15
- * Function => Function returns object suitable for constructor (see example below)
16
- * Error => A JavaScript error. It's `message` will be used as the error.
17
- *
18
- * `dataContext` is an object containing the same data passed to all validator
19
- * functions, and contains:
20
- * waypointId => The current waypoint being requested
21
- * fieldName => Name of the field being validated
22
- * journeyContext => The full JourneyContext of the current request.
23
+ * In the case of `errorMsg` being a function, this will be called at runtime,
24
+ * at the point that errors are generated within the `validate()`,
25
+ * methods, and will be passed the `dataContext`.
26
+ * <br/><br/>
23
27
  *
24
- * Example function signature that can be used for `errorMsg`:
25
- * ({ waypointId, fieldName, journeyContext }) => ({
26
- * summary: 'my-waypoint:some.key.to.say.hello',
27
- * variables: {
28
- * name: journeyContext.getDataForPage(waypointId).name,
29
- * }
30
- * });
28
+ * `dataContext` is an object containing the same data passed to all
29
+ * validators' `validate()` methods. In the case of `errorMsg` being
30
+ * a function, this data is passed to that function in order to help resolve to
31
+ * an error message config object.
31
32
  *
32
- * @param {object} args See args above
33
- * @param {any} args.errorMsg Error message to seed the ValidationError
34
- * @param {object} args.dataContext Validation context
35
- * @returns {object} Primitive error matching structure above
33
+ * @param {object} args Arguments
34
+ * @param {ErrorMessageConfig} args.errorMsg Error message config to seed ValidationError
35
+ * @param {ValidateContext} [args.dataContext={}] Data for error msg function
36
+ * @returns {ValidationError} Error instance
36
37
  * @throws {TypeError} If errorMsg is not in a valid type
37
38
  */
38
39
  static make({ errorMsg, dataContext }: {
39
- errorMsg: any;
40
- dataContext: object;
41
- }): object;
40
+ errorMsg: ErrorMessageConfig;
41
+ dataContext?: import("../casa").ValidateContext | undefined;
42
+ }): ValidationError;
42
43
  /**
43
- * `error` may be a simple string, in which case that string reppresents the
44
- * error mesaage (equivalent to `error.summary` in the structure below).
45
- *
46
- * `error`, when passed as an object, must match this structure:
47
- *
48
- * {
49
- * summary: "", // required
50
- * inline: "", // optional, may be deprecated in future
51
- * focusSuffix: "", // optional
52
- * fieldKeySuffix: "", // optional
53
- * variables: { // optional
54
- * myVariable: 'a value'
55
- * }
56
- * }
44
+ * Create a ValidationError.
57
45
  *
58
- * @param {object|string} errorParam See object structure above
46
+ * @param {string|ErrorMessageConfigObject} errorParam Error configuration
59
47
  */
60
- constructor(errorParam?: object | string);
48
+ constructor(errorParam?: string | ErrorMessageConfigObject);
61
49
  /**
62
- * Modifies the error to reflect the given context.
50
+ * Modifies this instance to reflect the given validation context.
63
51
  *
64
52
  * @param {ValidateContext} context See structure above
65
53
  * @returns {ValidationError} Chain
@@ -69,6 +57,8 @@ export default class ValidationError {
69
57
  field: string | undefined;
70
58
  fieldHref: string | undefined;
71
59
  focusSuffix: any;
72
- validator: any;
60
+ validator: string | undefined;
73
61
  }
74
- export type ValidateContext = import('./ValidatorFactory').ValidateContext;
62
+ export type ValidateContext = import('../casa').ValidateContext;
63
+ export type ErrorMessageConfig = import('../casa').ErrorMessageConfig;
64
+ export type ErrorMessageConfigObject = import('../casa').ErrorMessageConfigObject;
@@ -7,40 +7,41 @@ const lodash_1 = __importDefault(require("lodash"));
7
7
  const { isPlainObject } = lodash_1.default; // CommonJS
8
8
  const params = new WeakMap();
9
9
  /**
10
- * @typedef {import('./ValidatorFactory').ValidateContext} ValidateContext
10
+ * @access private
11
+ * @typedef {import('../casa').ValidateContext} ValidateContext
12
+ */
13
+ /**
14
+ * @access private
15
+ * @typedef {import('../casa').ErrorMessageConfig} ErrorMessageConfig
16
+ */
17
+ /**
18
+ * @access private
19
+ * @typedef {import('../casa').ErrorMessageConfigObject} ErrorMessageConfigObject
20
+ */
21
+ /**
22
+ * @class
23
+ * @memberof module:@dwp/govuk-casa
11
24
  */
12
25
  class ValidationError {
13
26
  /**
14
27
  * Make a ValidationError instance from a primitive object (or a function that
15
28
  * returns a primitive object) that is specific to the given journey context.
29
+ * <br/><br/>
16
30
  *
17
- * The returned `error` (or the function that returns the equivalent) must
18
- * match the structure required by the ValidationError constructor.
19
- *
20
- * `errorMsg` can be one of these formats:
21
- * String => 'common:errors.my-error-message'
22
- * Object => (see constructor argument for structure of this object)
23
- * Function => Function returns object suitable for constructor (see example below)
24
- * Error => A JavaScript error. It's `message` will be used as the error.
25
- *
26
- * `dataContext` is an object containing the same data passed to all validator
27
- * functions, and contains:
28
- * waypointId => The current waypoint being requested
29
- * fieldName => Name of the field being validated
30
- * journeyContext => The full JourneyContext of the current request.
31
+ * In the case of `errorMsg` being a function, this will be called at runtime,
32
+ * at the point that errors are generated within the `validate()`,
33
+ * methods, and will be passed the `dataContext`.
34
+ * <br/><br/>
31
35
  *
32
- * Example function signature that can be used for `errorMsg`:
33
- * ({ waypointId, fieldName, journeyContext }) => ({
34
- * summary: 'my-waypoint:some.key.to.say.hello',
35
- * variables: {
36
- * name: journeyContext.getDataForPage(waypointId).name,
37
- * }
38
- * });
36
+ * `dataContext` is an object containing the same data passed to all
37
+ * validators' `validate()` methods. In the case of `errorMsg` being
38
+ * a function, this data is passed to that function in order to help resolve to
39
+ * an error message config object.
39
40
  *
40
- * @param {object} args See args above
41
- * @param {any} args.errorMsg Error message to seed the ValidationError
42
- * @param {object} args.dataContext Validation context
43
- * @returns {object} Primitive error matching structure above
41
+ * @param {object} args Arguments
42
+ * @param {ErrorMessageConfig} args.errorMsg Error message config to seed ValidationError
43
+ * @param {ValidateContext} [args.dataContext={}] Data for error msg function
44
+ * @returns {ValidationError} Error instance
44
45
  * @throws {TypeError} If errorMsg is not in a valid type
45
46
  */
46
47
  static make({ errorMsg, dataContext = {} }) {
@@ -74,22 +75,9 @@ class ValidationError {
74
75
  throw new TypeError('errorMsg must be a string, Error, primitive object or function that generates a primitive object');
75
76
  }
76
77
  /**
77
- * `error` may be a simple string, in which case that string reppresents the
78
- * error mesaage (equivalent to `error.summary` in the structure below).
79
- *
80
- * `error`, when passed as an object, must match this structure:
81
- *
82
- * {
83
- * summary: "", // required
84
- * inline: "", // optional, may be deprecated in future
85
- * focusSuffix: "", // optional
86
- * fieldKeySuffix: "", // optional
87
- * variables: { // optional
88
- * myVariable: 'a value'
89
- * }
90
- * }
78
+ * Create a ValidationError.
91
79
  *
92
- * @param {object|string} errorParam See object structure above
80
+ * @param {string|ErrorMessageConfigObject} errorParam Error configuration
93
81
  */
94
82
  constructor(errorParam = {}) {
95
83
  if (!isPlainObject(errorParam) && typeof errorParam !== 'string') {
@@ -126,7 +114,7 @@ class ValidationError {
126
114
  });
127
115
  }
128
116
  /**
129
- * Modifies the error to reflect the given context.
117
+ * Modifies this instance to reflect the given validation context.
130
118
  *
131
119
  * @param {ValidateContext} context See structure above
132
120
  * @returns {ValidationError} Chain