@dwp/govuk-casa 7.0.6 → 8.0.0-alpha1

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 (219) hide show
  1. package/README.md +22 -17
  2. package/dist/{casa → assets}/css/casa-ie8.css +1 -1
  3. package/dist/assets/css/casa.css +1 -0
  4. package/dist/casa.d.ts +10 -0
  5. package/dist/casa.js +44 -0
  6. package/dist/lib/CasaTemplateLoader.d.ts +19 -0
  7. package/dist/lib/CasaTemplateLoader.js +57 -0
  8. package/dist/lib/JourneyContext.d.ts +255 -0
  9. package/dist/lib/JourneyContext.js +681 -0
  10. package/dist/lib/MutableRouter.d.ts +155 -0
  11. package/dist/lib/MutableRouter.js +272 -0
  12. package/dist/lib/Plan.d.ts +119 -0
  13. package/dist/lib/Plan.js +382 -0
  14. package/dist/lib/ValidationError.d.ts +70 -0
  15. package/dist/lib/ValidationError.js +156 -0
  16. package/dist/lib/ValidatorFactory.d.ts +24 -0
  17. package/dist/lib/ValidatorFactory.js +87 -0
  18. package/dist/lib/configure.d.ts +205 -0
  19. package/dist/lib/configure.js +215 -0
  20. package/dist/lib/dirname.cjs +1 -0
  21. package/dist/lib/end-session.d.ts +12 -0
  22. package/dist/lib/end-session.js +24 -0
  23. package/dist/lib/field.d.ts +79 -0
  24. package/dist/lib/field.js +223 -0
  25. package/dist/lib/logger.d.ts +8 -0
  26. package/dist/lib/logger.js +19 -0
  27. package/dist/lib/nunjucks-filters.d.ts +26 -0
  28. package/dist/lib/nunjucks-filters.js +112 -0
  29. package/dist/lib/nunjucks.d.ts +22 -0
  30. package/dist/lib/nunjucks.js +49 -0
  31. package/dist/lib/utils.d.ts +22 -0
  32. package/dist/lib/utils.js +44 -0
  33. package/dist/lib/validators/dateObject.d.ts +4 -0
  34. package/dist/lib/validators/dateObject.js +135 -0
  35. package/dist/lib/validators/email.d.ts +4 -0
  36. package/dist/lib/validators/email.js +46 -0
  37. package/dist/lib/validators/inArray.d.ts +4 -0
  38. package/dist/lib/validators/inArray.js +60 -0
  39. package/dist/lib/validators/index.d.ts +21 -0
  40. package/dist/lib/validators/index.js +47 -0
  41. package/dist/lib/validators/nino.d.ts +4 -0
  42. package/dist/lib/validators/nino.js +46 -0
  43. package/dist/lib/validators/postalAddressObject.d.ts +4 -0
  44. package/dist/lib/validators/postalAddressObject.js +123 -0
  45. package/dist/lib/validators/regex.d.ts +4 -0
  46. package/dist/lib/validators/regex.js +40 -0
  47. package/dist/lib/validators/required.d.ts +4 -0
  48. package/dist/lib/validators/required.js +56 -0
  49. package/dist/lib/validators/strlen.d.ts +4 -0
  50. package/dist/lib/validators/strlen.js +51 -0
  51. package/dist/lib/validators/wordCount.d.ts +5 -0
  52. package/dist/lib/validators/wordCount.js +54 -0
  53. package/dist/lib/waypoint-url.d.ts +17 -0
  54. package/dist/lib/waypoint-url.js +46 -0
  55. package/dist/middleware/body-parser.d.ts +1 -0
  56. package/dist/middleware/body-parser.js +24 -0
  57. package/dist/middleware/csrf.d.ts +1 -0
  58. package/dist/middleware/csrf.js +31 -0
  59. package/dist/middleware/data.d.ts +6 -0
  60. package/dist/middleware/data.js +53 -0
  61. package/dist/middleware/dirname.cjs +1 -0
  62. package/dist/middleware/gather-fields.d.ts +5 -0
  63. package/dist/middleware/gather-fields.js +39 -0
  64. package/dist/middleware/i18n.d.ts +4 -0
  65. package/dist/middleware/i18n.js +87 -0
  66. package/dist/middleware/post.d.ts +1 -0
  67. package/dist/middleware/post.js +42 -0
  68. package/dist/middleware/pre.d.ts +3 -0
  69. package/dist/middleware/pre.js +38 -0
  70. package/dist/middleware/progress-journey.d.ts +6 -0
  71. package/dist/middleware/progress-journey.js +82 -0
  72. package/dist/middleware/sanitise-fields.d.ts +5 -0
  73. package/dist/middleware/sanitise-fields.js +48 -0
  74. package/dist/middleware/session.d.ts +10 -0
  75. package/dist/middleware/session.js +115 -0
  76. package/dist/middleware/skip-waypoint.d.ts +5 -0
  77. package/dist/middleware/skip-waypoint.js +40 -0
  78. package/dist/middleware/steer-journey.d.ts +6 -0
  79. package/dist/middleware/steer-journey.js +44 -0
  80. package/dist/middleware/validate-fields.d.ts +7 -0
  81. package/dist/middleware/validate-fields.js +76 -0
  82. package/dist/mjs/esm-wrapper.js +10 -0
  83. package/dist/mjs/package.json +3 -0
  84. package/dist/package.json +3 -0
  85. package/dist/routes/ancillary.d.ts +4 -0
  86. package/dist/routes/ancillary.js +19 -0
  87. package/dist/routes/dirname.cjs +1 -0
  88. package/dist/routes/journey.d.ts +8 -0
  89. package/dist/routes/journey.js +130 -0
  90. package/dist/routes/static.d.ts +26 -0
  91. package/dist/routes/static.js +67 -0
  92. package/package.json +45 -86
  93. package/views/casa/components/checkboxes/template.njk +4 -1
  94. package/views/casa/components/date-input/template.njk +3 -3
  95. package/views/casa/components/journey-form/README.md +3 -1
  96. package/views/casa/components/journey-form/template.njk +1 -1
  97. package/views/casa/components/postal-address-object/template.njk +5 -5
  98. package/views/casa/components/radios/template.njk +1 -1
  99. package/views/casa/layouts/journey.njk +26 -9
  100. package/views/casa/layouts/main.njk +6 -19
  101. package/views/casa/partials/scripts.njk +8 -3
  102. package/views/casa/partials/styles.njk +2 -2
  103. package/casa.js +0 -208
  104. package/definitions/review-page.js +0 -60
  105. package/dist/casa/css/casa.css +0 -1
  106. package/dist/casa/js/casa.js +0 -1
  107. package/index.d.ts +0 -121
  108. package/lib/ConfigIngestor.js +0 -588
  109. package/lib/GatherModifier.js +0 -14
  110. package/lib/I18n.js +0 -160
  111. package/lib/JourneyContext.d.ts +0 -97
  112. package/lib/JourneyContext.js +0 -552
  113. package/lib/JourneyMap.js +0 -233
  114. package/lib/JourneyRoad.js +0 -330
  115. package/lib/Logger.js +0 -59
  116. package/lib/PageDictionary.d.ts +0 -11
  117. package/lib/PageDirectory.js +0 -77
  118. package/lib/Plan.js +0 -423
  119. package/lib/RoadConverter.js +0 -153
  120. package/lib/UserJourney.js +0 -8
  121. package/lib/Util.js +0 -227
  122. package/lib/Validation.js +0 -20
  123. package/lib/bootstrap/end-session.js +0 -44
  124. package/lib/bootstrap/load-definitions.js +0 -64
  125. package/lib/commonBodyParser.js +0 -15
  126. package/lib/enums.js +0 -6
  127. package/lib/gather-modifiers/index.js +0 -7
  128. package/lib/gather-modifiers/trimPostalAddressObject.js +0 -75
  129. package/lib/gather-modifiers/trimWhitespace.js +0 -16
  130. package/lib/utils/createGetRequest.d.ts +0 -5
  131. package/lib/utils/createGetRequest.js +0 -59
  132. package/lib/utils/index.js +0 -11
  133. package/lib/utils/parseRequest.d.ts +0 -5
  134. package/lib/utils/parseRequest.js +0 -72
  135. package/lib/utils/sanitise.js +0 -74
  136. package/lib/utils/validate.js +0 -32
  137. package/lib/validation/ArrayObjectField.js +0 -49
  138. package/lib/validation/ObjectField.js +0 -53
  139. package/lib/validation/SimpleField.d.ts +0 -11
  140. package/lib/validation/SimpleField.js +0 -46
  141. package/lib/validation/ValidationError.d.ts +0 -14
  142. package/lib/validation/ValidationError.js +0 -170
  143. package/lib/validation/ValidatorFactory.d.ts +0 -32
  144. package/lib/validation/ValidatorFactory.js +0 -91
  145. package/lib/validation/index.js +0 -22
  146. package/lib/validation/processor/flattenErrorArray.js +0 -24
  147. package/lib/validation/processor/queue.js +0 -214
  148. package/lib/validation/processor.js +0 -84
  149. package/lib/validation/rules/README.md +0 -3
  150. package/lib/validation/rules/ValidationRules.d.ts +0 -22
  151. package/lib/validation/rules/dateObject.js +0 -156
  152. package/lib/validation/rules/email.js +0 -44
  153. package/lib/validation/rules/inArray.js +0 -61
  154. package/lib/validation/rules/index.js +0 -23
  155. package/lib/validation/rules/nino.js +0 -48
  156. package/lib/validation/rules/optional.js +0 -14
  157. package/lib/validation/rules/postalAddressObject.js +0 -142
  158. package/lib/validation/rules/regex.js +0 -39
  159. package/lib/validation/rules/required.js +0 -57
  160. package/lib/validation/rules/strlen.js +0 -57
  161. package/lib/validation/rules/wordCount.js +0 -61
  162. package/lib/view-filters/formatDateObject.js +0 -35
  163. package/lib/view-filters/includes.js +0 -10
  164. package/lib/view-filters/index.js +0 -23
  165. package/lib/view-filters/mergeObjectsDeep.js +0 -21
  166. package/lib/view-filters/renderAsAttributes.js +0 -33
  167. package/middleware/errors/404.js +0 -12
  168. package/middleware/errors/catch-all.js +0 -27
  169. package/middleware/errors/index.js +0 -9
  170. package/middleware/headers/config-defaults.js +0 -57
  171. package/middleware/headers/headers.js +0 -40
  172. package/middleware/headers/index.js +0 -9
  173. package/middleware/i18n/i18n.js +0 -56
  174. package/middleware/i18n/index.js +0 -16
  175. package/middleware/index.js +0 -55
  176. package/middleware/mount/index.js +0 -9
  177. package/middleware/mount/mount.js +0 -10
  178. package/middleware/nunjucks/environment.js +0 -57
  179. package/middleware/nunjucks/index.js +0 -8
  180. package/middleware/page/csrf.js +0 -37
  181. package/middleware/page/edit-mode.js +0 -52
  182. package/middleware/page/gather.js +0 -75
  183. package/middleware/page/index.js +0 -103
  184. package/middleware/page/journey-continue.js +0 -157
  185. package/middleware/page/journey-rails.js +0 -102
  186. package/middleware/page/prepare-request.js +0 -77
  187. package/middleware/page/render.js +0 -75
  188. package/middleware/page/skip.js +0 -72
  189. package/middleware/page/utils.js +0 -206
  190. package/middleware/page/validate.js +0 -67
  191. package/middleware/session/expiry.js +0 -95
  192. package/middleware/session/genid.js +0 -18
  193. package/middleware/session/index.js +0 -18
  194. package/middleware/session/init.js +0 -25
  195. package/middleware/session/seed.js +0 -50
  196. package/middleware/session/timeout.js +0 -5
  197. package/middleware/static/asset-versions.js +0 -23
  198. package/middleware/static/index.js +0 -104
  199. package/middleware/static/prepare-assets.js +0 -51
  200. package/middleware/static/serve-assets.js +0 -58
  201. package/middleware/variables/index.js +0 -12
  202. package/middleware/variables/variables.js +0 -35
  203. package/src/browserconfig.xml +0 -5
  204. package/src/js/casa.js +0 -132
  205. package/src/scss/_casaElements.scss +0 -11
  206. package/src/scss/_casaGovukTemplateJinjaPolyfill.scss +0 -39
  207. package/src/scss/_casaMountUrl.scss +0 -8
  208. package/src/scss/casa-ie8.scss +0 -3
  209. package/src/scss/casa.scss +0 -14
  210. package/test/unit/templates/README.md +0 -5
  211. package/test/utils/BaseTestWaypoint.js +0 -106
  212. package/test/utils/concatWaypoints.js +0 -26
  213. package/test/utils/index.js +0 -6
  214. package/test/utils/testTraversal.js +0 -90
  215. package/views/casa/partials/cookie_message.njk +0 -3
  216. package/views/casa/partials/phase_banner_alpha.njk +0 -8
  217. package/views/casa/partials/phase_banner_beta.njk +0 -8
  218. package/views/casa/review/page-block.njk +0 -8
  219. package/views/casa/review/review.njk +0 -47
package/lib/JourneyMap.js DELETED
@@ -1,233 +0,0 @@
1
- const JourneyRoad = require('./JourneyRoad.js');
2
- const Plan = require('./Plan.js');
3
- const RoadConverter = require('./RoadConverter.js');
4
-
5
- const ERR_START_UNDEFINED = 'Start of journey has not been defined!';
6
- const privates = new WeakMap();
7
-
8
- class JourneyMap {
9
- /**
10
- * The `guid` is only required if you are using multiple journeys, as each one
11
- * must have a unique identifier. This identifier will be used to prefix
12
- * waypoints in order to help CASA identify which journey the user is
13
- * requesting. Thefore, if used, then it must be a valid URL slug.
14
- *
15
- * @class
16
- * @param {string} guid An ID that uniquely represents this journey.
17
- * @throws {TypeError} When guid is invalid
18
- * @throws {SyntaxError} When guid is misformatted
19
- */
20
- constructor(guid = null) {
21
- if (guid !== null) {
22
- if (typeof guid !== 'string') {
23
- throw new TypeError('guid must be a string');
24
- } else if (!guid.match(/^[0-9a-z-]+$/)) {
25
- throw new SyntaxError('guid must contain only 0-9, a-z, -');
26
- }
27
- }
28
-
29
- privates.set(this, {
30
- guid,
31
- startRoad: undefined,
32
- });
33
- }
34
-
35
- /**
36
- * Get guid
37
- *
38
- * @returns {string} Journey GUID
39
- */
40
- get guid() {
41
- return privates.get(this).guid;
42
- }
43
-
44
- /**
45
- * Define the starting point for this map - the first road that will be
46
- * traversed.
47
- *
48
- * @param {JourneyRoad} road First road on the journey.
49
- * @returns {ujMap} (chain).
50
- * @throws {Error} When a non-Road is given as the starting point
51
- */
52
- startAt(road) {
53
- const priv = privates.get(this);
54
- if (!(road instanceof JourneyRoad)) {
55
- throw new Error('Only Roads may be defined as starting points');
56
- }
57
- priv.startRoad = road;
58
-
59
- privates.set(this, priv);
60
- return this;
61
- }
62
-
63
- /**
64
- * Return all possible waypoints on this map. This will follow all roads, and
65
- * all forks to build up an exhaustive list of registered waypoints.
66
- *
67
- * The order of the returned array is insignificant. The purpose of this method
68
- * is to provide a means of determining if a waypoint exists on the map.
69
- *
70
- * @returns {Array} List of all waypoints on the map.
71
- * @throws {Error} When a starting waypoint is undefined.
72
- */
73
- allWaypoints() {
74
- const priv = privates.get(this);
75
-
76
- if (typeof priv.startRoad === 'undefined') {
77
- throw new Error(ERR_START_UNDEFINED);
78
- }
79
-
80
- const waypoints = [];
81
-
82
- // Used to keep track of which roads have already been followed so we don't
83
- // end up with recursions when roads loop back on themselves.
84
- const followedRoads = [];
85
-
86
- /**
87
- * Follow a road.
88
- *
89
- * @param {JourneyRoad} road Road to follow.
90
- * @returns {void}
91
- * @throws {Error} For invalid POI type.
92
- */
93
- function followRoad(road) {
94
- if (followedRoads.indexOf(road) > -1) {
95
- return;
96
- }
97
- followedRoads.push(road);
98
-
99
- const pois = road.getPOIs();
100
- for (let i = 0, l = pois.length; i < l; i += 1) {
101
- const poi = pois[i];
102
- switch (poi.type) {
103
- case JourneyRoad.POI_WAYPOINT:
104
- waypoints.push(poi.id);
105
- break;
106
- case JourneyRoad.POI_FORK:
107
- for (let ri = 0, rl = poi.roads.length; ri < rl; ri += 1) {
108
- followRoad(poi.roads[ri]);
109
- }
110
- break;
111
- case JourneyRoad.POI_MERGE:
112
- followRoad(poi.road);
113
- break;
114
- case JourneyRoad.POI_END:
115
- break;
116
- default:
117
- throw new Error('Invalid POI type');
118
- }
119
- }
120
- }
121
-
122
- followRoad(priv.startRoad);
123
-
124
- return waypoints;
125
- }
126
-
127
- /**
128
- * Determine if the map contains the specified waypoint at all. This will look
129
- * at _all_ waypoints in the map.
130
- *
131
- * @param {string} waypointId Waypoint ID to find.
132
- * @returns {boolean} Whether waypoint is present in the map or not.
133
- */
134
- containsWaypoint(waypointId) {
135
- return this.allWaypoints().indexOf(waypointId) > -1;
136
- }
137
-
138
- /**
139
- * Traverse the map, using the provided context to make decisions on
140
- * visiting/forking/merging along the way.
141
- *
142
- * The resulting list of waypoints include those that either a) have related
143
- * data in context (i.e. Context[waypoint.id] exists and is not empty) and there
144
- * are no validation errors on that waypoint, or b) exhaust the list of possible
145
- * waypoints (we reach the end of the journey).
146
- *
147
- * The context associated with a waypoint is considered not-empty if it is an
148
- * object, and it has at least one attribute specified within that object.
149
- *
150
- * If the traversed journey loops back on itself at any point, then the
151
- * traversal will stop at the last good waypoint.
152
- *
153
- * Data and validation contexts are provided separately (rather than passing in
154
- * a JourneyContext instance, for example) so that caller can arbitrarily decide
155
- * whether or not to include a validation context whilst traversing.
156
- *
157
- * @param {object} dataContext Data for each waypoint in the journey.
158
- * @param {object} validationContext Validation errors for each waypoint in the journey.
159
- * @returns {Array} List of waypoint IDs that have been traversed (in order).
160
- * @throws {Error} When start point is undefined.
161
- */
162
- traverse(dataContext = {}, validationContext = {}) {
163
- const priv = privates.get(this);
164
-
165
- if (typeof priv.startRoad === 'undefined') {
166
- throw new Error(ERR_START_UNDEFINED);
167
- }
168
-
169
- let poi = priv.startRoad.getPOIs()[0];
170
- const waypoints = [];
171
-
172
- do {
173
- // Preventative measure against a looping journey
174
- if (waypoints.indexOf(poi.id) > -1) {
175
- break;
176
- }
177
- if (typeof poi.show !== 'function' || poi.show(dataContext)) {
178
- waypoints.push(poi.id);
179
- if (typeof poi.passable !== 'function' || !poi.passable(dataContext, validationContext)) {
180
- break;
181
- }
182
- }
183
- poi = poi.nextWaypoint(dataContext);
184
- } while (poi);
185
-
186
- return waypoints;
187
- }
188
-
189
- /**
190
- * Traverse the whole journey, including future waypoints, based on the given
191
- * data context. This is a useful function to look ahead and see which waypoints
192
- * will feature in the user's journey given the current context state.
193
- *
194
- * Any forking and conditional logic that features in your UserJourney, must be
195
- * careful to check that data exists prior to testing it, because this method
196
- * will not necessarily provide the expected data when executing that logic
197
- * (because it may not have been gathered yet).
198
- *
199
- * @param {object} dataContext Data for each waypoint in the journey.
200
- * @returns {Array} List of waypoint IDs that have been traversed (in order).
201
- * @throws {Error} When a starting point is undefined
202
- */
203
- traverseAhead(dataContext = {}) {
204
- const priv = privates.get(this);
205
-
206
- if (typeof priv.startRoad === 'undefined') {
207
- throw new Error(ERR_START_UNDEFINED);
208
- }
209
-
210
- let poi = priv.startRoad.getPOIs()[0];
211
- const waypoints = [];
212
-
213
- do {
214
- // Preventative measure against a looping journey
215
- if (waypoints.indexOf(poi.id) > -1) {
216
- break;
217
- }
218
- waypoints.push(poi.id);
219
- poi = poi.nextWaypoint(dataContext);
220
- } while (poi);
221
-
222
- return waypoints;
223
- }
224
-
225
- convertToPlan() {
226
- const plan = new Plan();
227
- const { startRoad } = privates.get(this);
228
- plan.addOrigin('main', startRoad.getPOIs()[0].id);
229
- return new RoadConverter(plan, startRoad).convert().plan;
230
- }
231
- }
232
-
233
- module.exports = JourneyMap;
@@ -1,330 +0,0 @@
1
- const privates = new WeakMap();
2
-
3
- /* --------------------------------------------------------------------- Road */
4
-
5
- /**
6
- * Road.
7
- */
8
- class JourneyRoad {
9
- /**
10
- * JourneyRoad.
11
- *
12
- * @class
13
- */
14
- constructor() {
15
- // "Points of Interest" along our journey.
16
- // All points of interest will have a `nextWaypoint()` method that attempts
17
- // to determine the next waypoint in the journey after each POI.
18
- privates.set(this, {
19
- pois: [],
20
- });
21
- }
22
-
23
- /** ..
24
- * Add a new waypoint(s) to the journey. A waypoint is simply a string (or a
25
- * function - see below) that uniquely identifies a stopping point on the
26
- * journey. Typically this will be the URL slug of a single page.
27
- *
28
- * You can also use a function to describe a specific waypoint, in which case
29
- * the function will be executed (at runtime) to determine if the waypoint
30
- * should be included or not (based on a given data context). In this case, pass
31
- * the waypoint ID and function as an array:
32
- * AddWaypoints([
33
- * 'normal-waypoint',
34
- * ['conditional-waypoint', (context) => {...return bool...}]
35
- * ]);
36
- *
37
- * You can also define waypoints as objects, which supports additional
38
- * functionality. E.g.
39
- * AddWaypoints([
40
- * 'normal-waypoint',
41
- * {
42
- * id: 'conditional-waypoint',
43
- * is_present: (context) => {...return bool...},
44
- * is_passable: (dataContext, validationContext) => {...return bool...},
45
- * }
46
- * ]);
47
- *
48
- * The `is_passable` function here determines if the waypoint should be
49
- * considered complete. By default this checks for a) the presence of data
50
- * held against that waypoint, and b) an absence of validation errors
51
- * associated with the waypoint.
52
- *
53
- * @param {Array | string} points Add these waypoint(s) in the order defined.
54
- * @returns {JourneyRoad} (chain).
55
- * @throws {Error} When waypoint ordering is invalid
56
- * @throws {TypeError} When any waypoint definitions are invalid
57
- */
58
- addWaypoints(points) {
59
- const priv = privates.get(this);
60
-
61
- // Waypoints can only be added after other waypoints; never after forks or
62
- // merges
63
- if (
64
- priv.pois.length
65
- && priv.pois[priv.pois.length - 1].type !== JourneyRoad.POI_WAYPOINT
66
- ) {
67
- throw new Error('Waypoints can only follow other waypoints.');
68
- }
69
-
70
- // Convert to array
71
- const waypoints = Array.isArray(points) ? points : [points];
72
-
73
- // Validate each waypoint
74
- // If an Array, it must be [<String>, <Function>]
75
- // If an Object it must contain at least an `id` attribute
76
- waypoints.forEach((w) => {
77
- if (Array.isArray(w)) {
78
- if (w.length !== 2) {
79
- throw new SyntaxError('Array waypoints must contain 2 elements');
80
- } else if (typeof w[0] !== 'string') {
81
- throw new TypeError('The first element in an Array waypoint must be a string');
82
- } else if (typeof w[1] !== 'function') {
83
- throw new TypeError('The second element in an Array waypoint must be a function');
84
- }
85
- } else if (Object.prototype.toString.call(w) === '[object Object]') {
86
- if (!Object.prototype.hasOwnProperty.call(w, 'id')) {
87
- throw new SyntaxError('Object waypoints must contain an id element');
88
- } else if (typeof w.id !== 'string') {
89
- throw new TypeError('Object waypoint id must be a string');
90
- }
91
- if (Object.prototype.hasOwnProperty.call(w, 'is_present') && typeof w.is_present !== 'function') {
92
- throw new TypeError('Object waypoint is_present condition must be a function');
93
- }
94
- if (Object.prototype.hasOwnProperty.call(w, 'is_passable') && typeof w.is_passable !== 'function') {
95
- throw new TypeError('Object waypoint is_passable condition must be a function');
96
- }
97
- } else if (typeof w !== 'string') {
98
- throw new TypeError('Waypoint must be a string, object or array');
99
- }
100
- });
101
-
102
- /**
103
- * This is the condition that will be executed, by default, to test whether
104
- * a waypoint is "passable" during traversal calls. It must be bind-able as
105
- * we attach the waypoint ID as `this.id`.
106
- * This can be overriden per-waypoint by passing in a custom `is_passable`
107
- * function.
108
- *
109
- * @param {object} dc Data context.
110
- * @param {object} vc Validation context.
111
- * @returns {bool} True if the waypoint is passable.
112
- */
113
- function defaultPassableCondition(dc, vc) {
114
- return (dc
115
- && Object.prototype.hasOwnProperty.call(dc, this.id)
116
- && typeof dc[this.id] === 'object'
117
- && Object.keys(dc[this.id]).length !== 0
118
- && (
119
- !Object.prototype.hasOwnProperty.call(vc, this.id)
120
- || Object.keys(vc[this.id]).length === 0
121
- )
122
- );
123
- }
124
-
125
- // Store all waypoints
126
- for (let index = 0, l = waypoints.length; index < l; index += 1) {
127
- let waypointId;
128
- let waypointShowConditional;
129
- let waypointPassableConditional;
130
-
131
- if (Array.isArray(waypoints[index])) {
132
- waypointId = String(waypoints[index][0]);
133
- /* eslint-disable-next-line prefer-destructuring */
134
- waypointShowConditional = waypoints[index][1];
135
- waypointPassableConditional = defaultPassableCondition.bind({ id: waypointId });
136
- } else if (Object.prototype.toString.call(waypoints[index]) === '[object Object]') {
137
- waypointId = String(waypoints[index].id);
138
- waypointShowConditional = waypoints[index].is_present || (() => (true));
139
- waypointPassableConditional = waypoints[index].is_passable
140
- || defaultPassableCondition.bind({ id: waypointId });
141
- } else {
142
- waypointId = waypoints[index];
143
- waypointShowConditional = () => (true);
144
- waypointPassableConditional = defaultPassableCondition.bind({ id: waypointId });
145
- }
146
-
147
- priv.pois.push({
148
- id: waypointId,
149
- type: JourneyRoad.POI_WAYPOINT,
150
- show: waypointShowConditional,
151
- passable: waypointPassableConditional,
152
- nextWaypoint: (context) => {
153
- const nextPOI = this.getPOIs()[index + 1];
154
- if (
155
- typeof nextPOI === 'undefined'
156
- || nextPOI === null
157
- || nextPOI.type === JourneyRoad.POI_END
158
- ) {
159
- return null;
160
- }
161
- // Handle potential exceptions in the userland `show()` function
162
- try {
163
- if (
164
- nextPOI.type === JourneyRoad.POI_WAYPOINT
165
- && nextPOI.show(context)
166
- ) {
167
- return nextPOI;
168
- }
169
- return nextPOI.nextWaypoint(context);
170
- } catch (ex) {
171
- return JourneyRoad.WAYPOINT_FAULT_OBJ;
172
- }
173
- },
174
- });
175
- }
176
-
177
- // Chain
178
- privates.set(this, priv);
179
- return this;
180
- }
181
-
182
- /**
183
- * Add a fork in the road. The `test()` function is executed to determine which
184
- * of the specified `roads` should be taken, given some context about the user's
185
- * journey.
186
- *
187
- * Function interface for `test()`:
188
- * function (roads, context) {
189
- * ... return one of the roads based on context ...
190
- * }
191
- *
192
- * @param {Array} roads Array of road choices (order is important)
193
- * @param {Function} test Function used to determine which of the roads to take
194
- * @returns {JourneyRoad} (chain)
195
- * @throws {Error} When a fork is created prematurely
196
- */
197
- fork(roads, test) {
198
- const priv = privates.get(this);
199
-
200
- // A fork can only follow a waypoint on the journey
201
- if (
202
- priv.pois.length
203
- && priv.pois[priv.pois.length - 1].type !== JourneyRoad.POI_WAYPOINT
204
- ) {
205
- throw new Error('Forks can only follow waypoints.');
206
- }
207
-
208
- // Store fork
209
- priv.pois.push({
210
- type: JourneyRoad.POI_FORK,
211
- test,
212
- roads,
213
- nextWaypoint: (context) => {
214
- // Fork logic functions are from userland so we need to handle
215
- // exceptions cleanly in case they are not handled correctly within
216
- // those functions. In such scenarios, a `journey-fault` waypoint is
217
- // returned, after which no other waypoints can be accessed.
218
- // This will fall through to a 404 response, but the application should
219
- // add an Express route to handle this more specifically.
220
- try {
221
- const road = test.call(this, roads, context);
222
- const pois = road ? road.getPOIs() : [];
223
- if (pois.length && typeof pois[0].show === 'function') {
224
- return pois[0].show(context) ? pois[0] : pois[0].nextWaypoint(context);
225
- }
226
- return null;
227
- } catch (ex) {
228
- return JourneyRoad.WAYPOINT_FAULT_OBJ;
229
- }
230
- },
231
- });
232
-
233
- // Chain
234
- privates.set(this, priv);
235
- return this;
236
- }
237
-
238
- /**
239
- * Merge this road into another road.
240
- *
241
- * @param {JourneyRoad} road Road into which this one will merge.
242
- * @returns {JourneyRoad} (chain).
243
- * @throws {Error} When merge is create prematurely.
244
- */
245
- mergeWith(road) {
246
- const priv = privates.get(this);
247
-
248
- // A merge can only follow a waypoint on the journey
249
- if (
250
- priv.pois.length
251
- && priv.pois[priv.pois.length - 1].type !== JourneyRoad.POI_WAYPOINT
252
- ) {
253
- throw new Error('Merges can only follow waypoints.');
254
- }
255
-
256
- // Store merge
257
- priv.pois.push({
258
- type: JourneyRoad.POI_MERGE,
259
- road,
260
- nextWaypoint: (context) => {
261
- // Handle potential exceptions in userland `show()` function.
262
- try {
263
- const pois = road.getPOIs();
264
- if (pois.length && typeof pois[0].show === 'function') {
265
- return pois[0].show(context) ? pois[0] : pois[0].nextWaypoint(context);
266
- }
267
- return null;
268
- } catch (ex) {
269
- return JourneyRoad.WAYPOINT_FAULT_OBJ;
270
- }
271
- },
272
- });
273
-
274
- // Chain
275
- privates.set(this, priv);
276
- return this;
277
- }
278
-
279
- /**
280
- * Road ends here.
281
- *
282
- * @returns {JourneyRoad} (chain).
283
- * @throws {Error} When the road ends prematurely.
284
- */
285
- end() {
286
- const priv = privates.get(this);
287
-
288
- // A merge can only follow a waypoint on the journey
289
- if (
290
- priv.pois.length
291
- && priv.pois[priv.pois.length - 1].type !== JourneyRoad.POI_WAYPOINT
292
- ) {
293
- throw new Error('Roads can only finish after a waypoint.');
294
- }
295
-
296
- // Store merge
297
- priv.pois.push({
298
- id: '__END__',
299
- type: JourneyRoad.POI_END,
300
- });
301
-
302
- // Chain
303
- privates.set(this, priv);
304
- return this;
305
- }
306
-
307
- /**
308
- * Return a copy of all POIs along this road.
309
- *
310
- * @returns {Array} POI objects.
311
- */
312
- getPOIs() {
313
- const priv = privates.get(this);
314
- return Array.prototype.slice.call(priv.pois);
315
- }
316
- }
317
-
318
- JourneyRoad.POI_WAYPOINT = 'waypoint';
319
- JourneyRoad.POI_FORK = 'fork';
320
- JourneyRoad.POI_MERGE = 'merge';
321
- JourneyRoad.POI_END = 'end';
322
-
323
- JourneyRoad.WAYPOINT_FAULT_ID = 'journey-fault';
324
- JourneyRoad.WAYPOINT_FAULT_OBJ = {
325
- id: JourneyRoad.WAYPOINT_FAULT_ID,
326
- type: JourneyRoad.POI_WAYPOINT,
327
- nextWaypoint: () => (null),
328
- };
329
-
330
- module.exports = JourneyRoad;
package/lib/Logger.js DELETED
@@ -1,59 +0,0 @@
1
- /**
2
- * CASA logging wrapper. Provide a series of convenient logging functions, ready
3
- * pre-fixed with the CASA namespace.
4
- */
5
-
6
- global.GOVUK_CASA_DEBUG_NS = 'casa';
7
-
8
- const colors = require('colors/safe');
9
- const ndebug = require('debug');
10
-
11
- module.exports = function Logger(suffix) {
12
- const ns = GOVUK_CASA_DEBUG_NS + (suffix ? `:${suffix}` : '');
13
-
14
- let sessionId = '';
15
-
16
- const error = ndebug(`${ns}:error`);
17
- const fatal = ndebug(`${ns}:fatal`);
18
-
19
- const info = ndebug(`${ns}:info`);
20
- const warn = ndebug(`${ns}:warn`);
21
- const debug = ndebug(`${ns}:debug`);
22
- const trace = ndebug(`${ns}:trace`);
23
- info.log = console.info.bind(console); /* eslint-disable-line no-console */
24
- warn.log = console.warn.bind(console); /* eslint-disable-line no-console */
25
- debug.log = console.log.bind(console); /* eslint-disable-line no-console */
26
- trace.log = console.log.bind(console); /* eslint-disable-line no-console */
27
-
28
- /**
29
- * Set the session ID for all messages in this debugger.
30
- *
31
- * @param {string} sid Session ID].
32
- * @returns {void}
33
- */
34
- function setSessionId(sid) {
35
- sessionId = sid;
36
- }
37
-
38
- /**
39
- * Wrapper for appending the session ID to all messages.
40
- *
41
- * @param {...string} args Message(s).
42
- * @returns {void}
43
- */
44
- function writer(...args) {
45
- const logArgs = args;
46
- logArgs[0] += sessionId ? colors.blue(` [session: ${sessionId}]`) : '';
47
- this(...logArgs);
48
- }
49
-
50
- return {
51
- trace: writer.bind(trace),
52
- info: writer.bind(info),
53
- debug: writer.bind(debug),
54
- warn: writer.bind(warn),
55
- error: writer.bind(error),
56
- fatal: writer.bind(fatal),
57
- setSessionId,
58
- };
59
- };
@@ -1,11 +0,0 @@
1
- export = PageDictionary;
2
-
3
- declare class PageDictionary {
4
- constructor(pages: { [key: string]: PageMeta });
5
-
6
- getAllPageIds(): Array<string>;
7
-
8
- getPageMeta(pageId: string): PageMeta;
9
-
10
- getPages(): PageMetaMap;
11
- }
@@ -1,77 +0,0 @@
1
- /**
2
- * Simple wrapper around all the page definitions.
3
- */
4
-
5
- const privates = new WeakMap();
6
-
7
- /**
8
- * PageDirectory class.
9
- */
10
- class PageDirectory {
11
- /**
12
- * Constructor
13
- *
14
- * @param {object} pages Page meta data object (indexed by the page id)
15
- * @throws {Error} If page id is invalid url component, or meta not an object
16
- */
17
- constructor(pages = {}) {
18
- // Set `id` property for each page so we don't need to keep a separate list
19
- // of object keys
20
- const seededPages = Object.create(null);
21
- Object.keys(pages).forEach((pid) => {
22
- seededPages[pid] = Object.assign(pages[pid], {
23
- id: pid,
24
- });
25
- })
26
-
27
- privates.set(this, {
28
- pages: seededPages,
29
- });
30
-
31
- // Validate:
32
- // - Check if page IDs are appropriate for use as part of URLs
33
- // - Check that required attributes are present
34
- Object.keys(pages).forEach((pid) => {
35
- if (!pid.match(/^[0-9a-z-/]+$/)) {
36
- throw new Error(`Page ID '${pid}' must contain only 0-9, a-z, -, /`);
37
- } else if (typeof pages[pid] !== 'object') {
38
- throw new Error('Page metadata must be an object');
39
- } else if (typeof pages[pid].view === 'undefined') {
40
- throw new Error(`Page metadata view is missing for '${pid}'`);
41
- }
42
- });
43
- }
44
-
45
- /**
46
- * Get all page IDs in the directory.
47
- *
48
- * @returns {Array} Page IDs.
49
- */
50
- getAllPageIds() {
51
- const priv = privates.get(this);
52
- return Object.keys(priv.pages);
53
- }
54
-
55
- /**
56
- * Get page metadata for specific page
57
- *
58
- * @param {string} pageId Page ID
59
- * @returns {object} Page metadata
60
- */
61
- getPageMeta(pageId) {
62
- const priv = privates.get(this);
63
- return priv.pages[pageId];
64
- }
65
-
66
- /**
67
- * Get all pages.
68
- *
69
- * @returns {object} All pages indexed by waypoint ID.
70
- */
71
- getPages() {
72
- const priv = privates.get(this);
73
- return priv.pages;
74
- }
75
- }
76
-
77
- module.exports = PageDirectory;