@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
@@ -43,14 +43,21 @@ const utils_js_1 = require("./utils.js");
43
43
  const { cloneDeep, isPlainObject, isObject, has, isEqual, } = lodash_1.default; // CommonJS
44
44
  const log = (0, logger_js_1.default)('lib:journey-context');
45
45
  /**
46
+ * @access private
46
47
  * @typedef {import('../casa').Page} Page
47
48
  */
48
49
  /**
50
+ * @access private
49
51
  * @typedef {import('../casa').ContextEventHandler} ContextEventHandler
50
52
  */
51
53
  /**
54
+ * @access private
52
55
  * @typedef {import('../casa').ContextEvent} ContextEvent
53
56
  */
57
+ /**
58
+ * @access private
59
+ * @typedef {import('express').Request} ExpressRequest
60
+ */
54
61
  function validateObjectKey(key = '') {
55
62
  const keyLower = String.prototype.toLowerCase.call(key);
56
63
  if (keyLower === 'prototype' || keyLower === '__proto__' || keyLower === 'constructor') {
@@ -59,6 +66,9 @@ function validateObjectKey(key = '') {
59
66
  return String(key);
60
67
  }
61
68
  exports.validateObjectKey = validateObjectKey;
69
+ /**
70
+ * @memberof module:@dwp/govuk-casa
71
+ */
62
72
  class JourneyContext {
63
73
  /**
64
74
  * Constructor.
@@ -165,6 +175,11 @@ class JourneyContext {
165
175
  }
166
176
  throw new TypeError(`Page must be a string or Page object. Got ${typeof page}`);
167
177
  }
178
+ /**
179
+ * Get all data.
180
+ *
181
+ * @returns {object} Page data
182
+ */
168
183
  getData() {
169
184
  return __classPrivateFieldGet(this, _JourneyContext_data, "f");
170
185
  }
@@ -181,11 +196,6 @@ class JourneyContext {
181
196
  /**
182
197
  * Write field form data from a page HTML form, into the `data` model.
183
198
  *
184
- * By default this will store the data as-is, keyed against the page's
185
- * waypoint ID. However, when passing a `Page` instance, its
186
- * `fieldWriter()` method will be called to transform the provided formData
187
- * before storing in `data`
188
- *
189
199
  * @param {string | Page} page Page waypoint ID, or Page object
190
200
  * @param {object} webFormData Data to overwrite with
191
201
  * @returns {JourneyContext} Chain
@@ -268,6 +278,14 @@ class JourneyContext {
268
278
  var _a;
269
279
  return (_a = __classPrivateFieldGet(this, _JourneyContext_validation, "f")[validateObjectKey(pageId)]) !== null && _a !== void 0 ? _a : [];
270
280
  }
281
+ /**
282
+ * Same as `getValidationErrorsForPage()`, but the return value is
283
+ * an object whose keys are the field names, and values are the list of errors
284
+ * associated with that particular field.
285
+ *
286
+ * @param {string} pageId Page ID.
287
+ * @returns {object} Object indexed by field names; values containing list of errors
288
+ */
271
289
  getValidationErrorsForPageByField(pageId) {
272
290
  const errors = this.getValidationErrorsForPage(pageId);
273
291
  const obj = Object.create(null);
@@ -362,6 +380,14 @@ class JourneyContext {
362
380
  __classPrivateFieldSet(this, _JourneyContext_eventListenerPreState, this.toObject(), "f");
363
381
  return this;
364
382
  }
383
+ /**
384
+ * Execute all listeners for the given event.
385
+ *
386
+ * @param {object} params Params
387
+ * @param {string} params.event Event (waypoint-change | context-change)
388
+ * @param {object} params.session Session
389
+ * @returns {JourneyContext} Chain
390
+ */
365
391
  applyEventListeners({ event, session }) {
366
392
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
367
393
  if (!__classPrivateFieldGet(this, _JourneyContext_eventListeners, "f").length) {
@@ -471,6 +497,16 @@ class JourneyContext {
471
497
  }
472
498
  return id;
473
499
  }
500
+ /**
501
+ * Retrieve the default Journey Context. This is just a convenient wrapper
502
+ * around `getContextById()`.
503
+ *
504
+ * @param {object} session Request session
505
+ * @returns {JourneyContext} The default Journey Context
506
+ */
507
+ static getDefaultContext(session) {
508
+ return JourneyContext.getContextById(session, JourneyContext.DEFAULT_CONTEXT_ID);
509
+ }
474
510
  /**
475
511
  * Lookup context from session using the ID.
476
512
  *
@@ -573,6 +609,13 @@ class JourneyContext {
573
609
  JourneyContext.removeContextById(session, context.identity.id);
574
610
  }
575
611
  }
612
+ /**
613
+ * Remove context from session using the ID.
614
+ *
615
+ * @param {object} session Request session
616
+ * @param {string} id Context ID
617
+ * @returns {void}
618
+ */
576
619
  static removeContextById(session, id) {
577
620
  if (session && has(session.journeyContextList, id)) {
578
621
  // ESLint disabled as `id` has been verified as an "own" property
@@ -580,15 +623,45 @@ class JourneyContext {
580
623
  delete session.journeyContextList[id];
581
624
  }
582
625
  }
626
+ /**
627
+ * Remove context from session using the name.
628
+ *
629
+ * @param {object} session Request session
630
+ * @param {string} name Context name
631
+ * @returns {void}
632
+ */
583
633
  static removeContextByName(session, name) {
584
634
  JourneyContext.removeContext(session, JourneyContext.getContextByName(session, name));
585
635
  }
636
+ /**
637
+ * Remove context from session using the tag.
638
+ *
639
+ * @param {object} session Request session
640
+ * @param {string} tag Context tag
641
+ * @returns {void}
642
+ */
586
643
  static removeContextsByTag(session, tag) {
587
644
  JourneyContext.getContextsByTag(session, tag).forEach((c) => JourneyContext.removeContext(session, c));
588
645
  }
646
+ /**
647
+ * Remove call contexts.
648
+ *
649
+ * @param {object} session Request session
650
+ * @returns {void}
651
+ */
589
652
  static removeContexts(session) {
590
653
  JourneyContext.getContexts(session).forEach((c) => JourneyContext.removeContext(session, c));
591
654
  }
655
+ /**
656
+ * Extract the Journey Context referred to in the incoming request.
657
+ *
658
+ * This will look in `req.params`, `req.query` and
659
+ * `req.body` for a `contextid` parameter, and use that
660
+ * to load the correct Journey Context from the session.
661
+ *
662
+ * @param {ExpressRequest} req ExpressJS incoming request
663
+ * @returns {JourneyContext} The Journey Context
664
+ */
592
665
  static extractContextFromRequest(req) {
593
666
  JourneyContext.initContextStore(req.session);
594
667
  let contextId;
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @memberof module:@dwp/govuk-casa
3
+ */
1
4
  export default class Plan {
2
5
  /**
3
6
  * Waypoints using the url:// protocol are known as "exit nodes" as they
@@ -10,15 +13,15 @@ export default class Plan {
10
13
  /**
11
14
  * Create a Plan.
12
15
  *
13
- * @param {object} opts Options
14
- * @param {boolean} [opts.validateBeforeRouteCondition=true] Check page validity before conditions
15
- * @param {Function|string} [opts.arbiter=undefined] Arbitration mechanism
16
+ * @param {PlanConstructorOptions} opts Options
16
17
  */
17
- constructor(opts?: {
18
- validateBeforeRouteCondition?: boolean | undefined;
19
- arbiter?: string | Function | undefined;
20
- });
21
- getOptions(): any;
18
+ constructor(opts?: PlanConstructorOptions);
19
+ /**
20
+ * Retrieve the options set on this Plan.
21
+ *
22
+ * @returns {PlanConstructorOptions} Options map
23
+ */
24
+ getOptions(): PlanConstructorOptions;
22
25
  /**
23
26
  * Retrieve the list of skippable waypoints.
24
27
  *
@@ -29,7 +32,7 @@ export default class Plan {
29
32
  * Add one or more skippable waypoints.
30
33
  *
31
34
  * @param {...string} waypoints Waypoints
32
- * @returns {Plan}{ Chain}
35
+ * @returns {Plan} Chain
33
36
  */
34
37
  addSkippables(...waypoints: string[]): Plan;
35
38
  /**
@@ -39,40 +42,87 @@ export default class Plan {
39
42
  * @returns {boolean} True if waypoint can be skipped
40
43
  */
41
44
  isSkippable(waypoint: string): boolean;
42
- getWaypoints(): any;
43
- containsWaypoint(waypoint: any): any;
44
- getRoutes(): any;
45
- getRouteCondition(src: any, tgt: any, name: any): any;
45
+ /**
46
+ * Retrieve all waypoints in this Plan (order is arbitrary).
47
+ *
48
+ * @returns {string[]} List of waypoints
49
+ */
50
+ getWaypoints(): string[];
51
+ /**
52
+ * Determine if the given waypoint exists in this Plan.
53
+ *
54
+ * @param {string} waypoint Waypoint to search for
55
+ * @returns {boolean} Result
56
+ */
57
+ containsWaypoint(waypoint: string): boolean;
58
+ /**
59
+ * Get all route information.
60
+ *
61
+ * @returns {PlanRoute[]} Routes
62
+ */
63
+ getRoutes(): PlanRoute[];
64
+ /**
65
+ * Get the condition function for the given parameters.
66
+ *
67
+ * @param {string} src Source waypoint
68
+ * @param {string} tgt Target waypoint
69
+ * @param {string} name Route name
70
+ * @returns {PlanRouteCondition} Route condition function
71
+ */
72
+ getRouteCondition(src: string, tgt: string, name: string): PlanRouteCondition;
46
73
  /**
47
74
  * Return all outward routes (out-edges) from the given waypoint, to the
48
75
  * optional target waypoint.
49
76
  *
50
77
  * @param {string} src Source waypoint.
51
- * @param {string} tgt Target waypoint (optional).
52
- * @returns {Array<object>} Route objects found.
78
+ * @param {string} [tgt] Target waypoint.
79
+ * @returns {PlanRoute[]} Route objects found.
53
80
  */
54
- getOutwardRoutes(src: string, tgt?: string): Array<object>;
81
+ getOutwardRoutes(src: string, tgt?: string | undefined): PlanRoute[];
55
82
  /**
56
83
  * Return all outward routes (out-edges) from the given waypoint, to the
57
84
  * optional target waypoint, matching the "prev" name.
58
85
  *
59
86
  * @param {string} src Source waypoint.
60
- * @param {string} tgt Target waypoint (optional).
61
- * @returns {Array<object>} Route objects found.
87
+ * @param {string} [tgt] Target waypoint.
88
+ * @returns {PlanRoute[]} Route objects found.
62
89
  */
63
- getPrevOutwardRoutes(src: string, tgt?: string): Array<object>;
64
- addSequence(...waypoints: any[]): void;
65
- setNextRoute(src: any, tgt: any, follow: any): Plan;
66
- setPrevRoute(src: any, tgt: any, follow: any): Plan;
90
+ getPrevOutwardRoutes(src: string, tgt?: string | undefined): PlanRoute[];
91
+ /**
92
+ * Add a sequence of waypoints that will follow on from each other, with no
93
+ * routing logic between them.
94
+ *
95
+ * @param {...string} waypoints Waypoints to add
96
+ * @returns {void}
97
+ */
98
+ addSequence(...waypoints: string[]): void;
99
+ /**
100
+ * Create a new directed route between two waypoints, labelled as "next".
101
+ *
102
+ * @param {string} src Source waypoint
103
+ * @param {string} tgt Target waypoint
104
+ * @param {PlanRouteCondition} follow Route condition function
105
+ * @returns {Plan} Chain
106
+ */
107
+ setNextRoute(src: string, tgt: string, follow: PlanRouteCondition): Plan;
108
+ /**
109
+ * Create a new directed route between two waypoints, labelled as "prev".
110
+ *
111
+ * @param {string} src Source waypoint
112
+ * @param {string} tgt Target waypoint
113
+ * @param {PlanRouteCondition} follow Route condition function
114
+ * @returns {Plan} Chain
115
+ */
116
+ setPrevRoute(src: string, tgt: string, follow: PlanRouteCondition): Plan;
67
117
  /**
68
118
  * Adds both a "next" and "prev" route between the two waypoints.
69
119
  *
70
- * By default, the "prev" route will use the same "follow" test as the "next"
71
- * route. This makes sense in that in order to get the target, the test must
72
- * have been true, and so to reverse the direction we also need that same test
73
- * to be true.
120
+ * By default, the "prev" route will use the same "follow" condition as the
121
+ * "next" route. This makes sense in that in order to get to the target, the
122
+ * condition must be true, and so to reverse the direction we also need that
123
+ * same condition to be true.
74
124
  *
75
- * However, if the condition function uses the `source`/`target`
125
+ * However, if the condition function uses the `source`/`target` property
76
126
  * of the route in some way, then we must reverse these before passing to the
77
127
  * condition on the "prev" route because `source` in the condition will almost
78
128
  * certainly be referring to the source of the "next" route.
@@ -82,11 +132,11 @@ export default class Plan {
82
132
  *
83
133
  * @param {string} src Source waypoint.
84
134
  * @param {string} tgt Target waypoint.
85
- * @param {Function} followNext Follow test function.
86
- * @param {Function} followPrev Follow test function.
87
- * @returns {Plan} Self.
135
+ * @param {PlanRouteCondition} [followNext] Follow test function.
136
+ * @param {PlanRouteCondition} [followPrev] Follow test function.
137
+ * @returns {Plan} Chain
88
138
  */
89
- setRoute(src: string, tgt: string, followNext?: Function, followPrev?: Function): Plan;
139
+ setRoute(src: string, tgt: string, followNext?: import("../casa").PlanRouteCondition | undefined, followPrev?: import("../casa").PlanRouteCondition | undefined): Plan;
90
140
  /**
91
141
  * Create a named route between two waypoints, and give that route a function
92
142
  * that determine whether it should be followed during traversal operations.
@@ -103,22 +153,38 @@ export default class Plan {
103
153
  * @param {string} src Source waypoint.
104
154
  * @param {string} tgt Target waypoint.
105
155
  * @param {string} name Name of the route (must be unique for this waypoint pairing).
106
- * @param {Function} follow Test function to determine if route can be followed.
156
+ * @param {PlanRouteCondition} follow Test function to determine if route can be followed.
107
157
  * @returns {Plan} Chain
108
158
  * @throws {Error} If attempting to create a "next" route from an exit node
109
159
  */
110
- setNamedRoute(src: string, tgt: string, name: string, follow: Function): Plan;
160
+ setNamedRoute(src: string, tgt: string, name: string, follow: PlanRouteCondition): Plan;
111
161
  /**
112
162
  * This is a convenience method for traversing all "next" routes, and returning
113
163
  * the IDs of all waypoints visited along the way.
114
164
  *
115
- * @param {JourneyContext} context Journey Context.
116
- * @param {object} options Options.
117
- * @returns {Array<string>} List of traversed waypoints.
165
+ * @param {JourneyContext} context Journey Context
166
+ * @param {PlanTraverseOptions} options Options
167
+ * @returns {string[]} List of traversed waypoints
118
168
  */
119
- traverse(context: JourneyContext, options?: object): Array<string>;
120
- traverseNextRoutes(context: any, options?: {}): object[];
121
- traversePrevRoutes(context: any, options?: {}): object[];
169
+ traverse(context: JourneyContext, options?: PlanTraverseOptions): string[];
170
+ /**
171
+ * Traverse the Plan by following all "next" routes, and returning the IDs of
172
+ * all waypoints visited along the way.
173
+ *
174
+ * @param {JourneyContext} context Journey Context
175
+ * @param {PlanTraverseOptions} options Options
176
+ * @returns {PlanRoute[]} List of traversed waypoints
177
+ */
178
+ traverseNextRoutes(context: JourneyContext, options?: PlanTraverseOptions): PlanRoute[];
179
+ /**
180
+ * Traverse the Plan by following all "prev" routes, and returning the IDs of
181
+ * all waypoints visited along the way.
182
+ *
183
+ * @param {JourneyContext} context Journey Context
184
+ * @param {PlanTraverseOptions} options Options
185
+ * @returns {PlanRoute[]} List of traversed waypoints
186
+ */
187
+ traversePrevRoutes(context: JourneyContext, options?: PlanTraverseOptions): PlanRoute[];
122
188
  /**
123
189
  * Traverse through the plan from a particular starting waypoint. This is a
124
190
  * non-exhaustive Graph Exploration.
@@ -129,19 +195,12 @@ export default class Plan {
129
195
  * If a cyclical set of routes are encountered, traversal will stop after
130
196
  * reaching the first repeated waypoint.
131
197
  *
132
- * Options:
133
- * string startWaypoint = Waypoint from which to start traversal
134
- * string routeName = Follow routes matching this name (next | prev)
135
- * Map history = Used to detect loops in traversal (internal use)
136
- * function stopCondition = Condition that, if true, will stop traversal (useful for performance)
137
- * function|string arbiter = If mutliple target routes found, this decides which to use (if any)
138
- *
139
198
  * @param {JourneyContext} context Journey context
140
- * @param {object} options Options
141
- * @returns {Array<object>} Routes that were traversed
199
+ * @param {PlanTraverseOptions} options Options
200
+ * @returns {PlanRoute[]} Routes that were traversed
142
201
  * @throws {TypeError} When context is not a JourneyContext
143
202
  */
144
- traverseRoutes(context: JourneyContext, options?: object): Array<object>;
203
+ traverseRoutes(context: JourneyContext, options?: PlanTraverseOptions): PlanRoute[];
145
204
  /**
146
205
  * Get raw graph data structure. This can be used with other libraries to
147
206
  * generate graph visualisations, for example.
@@ -151,4 +210,18 @@ export default class Plan {
151
210
  getGraphStructure(): Graph;
152
211
  #private;
153
212
  }
213
+ export type PlanRoute = import('../casa').PlanRoute;
214
+ export type PlanRouteCondition = import('../casa').PlanRouteCondition;
215
+ export type PlanTraverseOptions = import('../casa').PlanTraverseOptions;
216
+ export type PlanArbiter = import('../casa').PlanArbiter;
217
+ export type PlanConstructorOptions = {
218
+ /**
219
+ * Check page validity before conditions
220
+ */
221
+ validateBeforeRouteCondition?: boolean | undefined;
222
+ /**
223
+ * Arbitration mechanism
224
+ */
225
+ arbiter?: string | import("../casa").PlanArbiter | undefined;
226
+ };
154
227
  import JourneyContext from "./JourneyContext.js";