@dwp/govuk-casa 8.16.2 → 8.16.3
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.
- package/dist/assets/css/casa-ie8.css +1 -1
- package/dist/assets/css/casa.css +1 -1
- package/dist/casa.d.ts +13 -13
- package/dist/casa.js +17 -7
- package/dist/casa.js.map +1 -1
- package/dist/lib/CasaTemplateLoader.d.ts +1 -1
- package/dist/lib/CasaTemplateLoader.js +13 -14
- package/dist/lib/CasaTemplateLoader.js.map +1 -1
- package/dist/lib/JourneyContext.d.ts +10 -4
- package/dist/lib/JourneyContext.js +57 -47
- package/dist/lib/JourneyContext.js.map +1 -1
- package/dist/lib/MutableRouter.d.ts +1 -1
- package/dist/lib/MutableRouter.js +22 -23
- package/dist/lib/MutableRouter.js.map +1 -1
- package/dist/lib/Plan.d.ts +5 -5
- package/dist/lib/Plan.js +49 -36
- package/dist/lib/Plan.js.map +1 -1
- package/dist/lib/ValidationError.d.ts +1 -1
- package/dist/lib/ValidationError.js +9 -9
- package/dist/lib/ValidationError.js.map +1 -1
- package/dist/lib/ValidatorFactory.js +4 -7
- package/dist/lib/ValidatorFactory.js.map +1 -1
- package/dist/lib/configuration-ingestor.d.ts +75 -14
- package/dist/lib/configuration-ingestor.js +156 -64
- package/dist/lib/configuration-ingestor.js.map +1 -1
- package/dist/lib/configure.js +11 -10
- package/dist/lib/configure.js.map +1 -1
- package/dist/lib/constants.js +8 -8
- package/dist/lib/context-id-generators.d.ts +1 -1
- package/dist/lib/context-id-generators.js +7 -4
- package/dist/lib/context-id-generators.js.map +1 -1
- package/dist/lib/end-session.js +2 -2
- package/dist/lib/field.d.ts +6 -6
- package/dist/lib/field.js +15 -21
- package/dist/lib/field.js.map +1 -1
- package/dist/lib/index.d.ts +13 -13
- package/dist/lib/index.js +17 -7
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/logger.js +7 -7
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/mount.js +3 -3
- package/dist/lib/mount.js.map +1 -1
- package/dist/lib/nunjucks-filters.d.ts +5 -1
- package/dist/lib/nunjucks-filters.js +37 -23
- package/dist/lib/nunjucks-filters.js.map +1 -1
- package/dist/lib/nunjucks.d.ts +2 -2
- package/dist/lib/nunjucks.js +6 -7
- package/dist/lib/nunjucks.js.map +1 -1
- package/dist/lib/utils.js +52 -42
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/validators/dateObject.d.ts +3 -3
- package/dist/lib/validators/dateObject.js +44 -37
- package/dist/lib/validators/dateObject.js.map +1 -1
- package/dist/lib/validators/email.d.ts +2 -2
- package/dist/lib/validators/email.js +4 -5
- package/dist/lib/validators/email.js.map +1 -1
- package/dist/lib/validators/inArray.d.ts +2 -2
- package/dist/lib/validators/inArray.js +5 -6
- package/dist/lib/validators/inArray.js.map +1 -1
- package/dist/lib/validators/index.d.ts +10 -10
- package/dist/lib/validators/index.js.map +1 -1
- package/dist/lib/validators/nino.d.ts +2 -2
- package/dist/lib/validators/nino.js +10 -7
- package/dist/lib/validators/nino.js.map +1 -1
- package/dist/lib/validators/postalAddressObject.d.ts +2 -2
- package/dist/lib/validators/postalAddressObject.js +52 -39
- package/dist/lib/validators/postalAddressObject.js.map +1 -1
- package/dist/lib/validators/range.d.ts +2 -2
- package/dist/lib/validators/range.js +6 -7
- package/dist/lib/validators/range.js.map +1 -1
- package/dist/lib/validators/regex.d.ts +2 -2
- package/dist/lib/validators/regex.js +4 -5
- package/dist/lib/validators/regex.js.map +1 -1
- package/dist/lib/validators/required.d.ts +2 -2
- package/dist/lib/validators/required.js +6 -9
- package/dist/lib/validators/required.js.map +1 -1
- package/dist/lib/validators/strlen.d.ts +2 -2
- package/dist/lib/validators/strlen.js +8 -9
- package/dist/lib/validators/strlen.js.map +1 -1
- package/dist/lib/validators/wordCount.d.ts +2 -2
- package/dist/lib/validators/wordCount.js +10 -9
- package/dist/lib/validators/wordCount.js.map +1 -1
- package/dist/lib/waypoint-url.d.ts +4 -4
- package/dist/lib/waypoint-url.js +23 -23
- package/dist/lib/waypoint-url.js.map +1 -1
- package/dist/middleware/body-parser.d.ts +27 -5
- package/dist/middleware/body-parser.js +37 -6
- package/dist/middleware/body-parser.js.map +1 -1
- package/dist/middleware/csrf.d.ts +3 -0
- package/dist/middleware/csrf.js +3 -0
- package/dist/middleware/csrf.js.map +1 -1
- package/dist/middleware/data.d.ts +22 -5
- package/dist/middleware/data.js +37 -7
- package/dist/middleware/data.js.map +1 -1
- package/dist/middleware/gather-fields.d.ts +1 -1
- package/dist/middleware/gather-fields.js +4 -3
- package/dist/middleware/gather-fields.js.map +1 -1
- package/dist/middleware/i18n.d.ts +11 -2
- package/dist/middleware/i18n.js +26 -17
- package/dist/middleware/i18n.js.map +1 -1
- package/dist/middleware/post.d.ts +3 -1
- package/dist/middleware/post.js +35 -18
- package/dist/middleware/post.js.map +1 -1
- package/dist/middleware/pre.d.ts +1 -1
- package/dist/middleware/pre.js +44 -21
- package/dist/middleware/pre.js.map +1 -1
- package/dist/middleware/progress-journey.d.ts +1 -1
- package/dist/middleware/progress-journey.js +5 -5
- package/dist/middleware/progress-journey.js.map +1 -1
- package/dist/middleware/sanitise-fields.d.ts +2 -2
- package/dist/middleware/sanitise-fields.js +13 -11
- package/dist/middleware/sanitise-fields.js.map +1 -1
- package/dist/middleware/serve-first-waypoint.d.ts +1 -1
- package/dist/middleware/serve-first-waypoint.js +6 -4
- package/dist/middleware/serve-first-waypoint.js.map +1 -1
- package/dist/middleware/session.d.ts +27 -8
- package/dist/middleware/session.js +53 -25
- package/dist/middleware/session.js.map +1 -1
- package/dist/middleware/skip-waypoint.d.ts +1 -1
- package/dist/middleware/skip-waypoint.js +3 -3
- package/dist/middleware/skip-waypoint.js.map +1 -1
- package/dist/middleware/steer-journey.d.ts +1 -1
- package/dist/middleware/steer-journey.js +15 -13
- package/dist/middleware/steer-journey.js.map +1 -1
- package/dist/middleware/strip-proxy-path.d.ts +1 -1
- package/dist/middleware/strip-proxy-path.js +3 -3
- package/dist/middleware/strip-proxy-path.js.map +1 -1
- package/dist/middleware/validate-fields.d.ts +2 -2
- package/dist/middleware/validate-fields.js +2 -5
- package/dist/middleware/validate-fields.js.map +1 -1
- package/dist/routes/ancillary.d.ts +2 -2
- package/dist/routes/ancillary.js +3 -3
- package/dist/routes/ancillary.js.map +1 -1
- package/dist/routes/journey.d.ts +1 -1
- package/dist/routes/journey.js +85 -31
- package/dist/routes/journey.js.map +1 -1
- package/dist/routes/static.d.ts +2 -2
- package/dist/routes/static.js +18 -18
- package/dist/routes/static.js.map +1 -1
- package/package.json +33 -36
- package/src/casa.js +13 -13
- package/src/lib/CasaTemplateLoader.js +21 -17
- package/src/lib/JourneyContext.js +118 -79
- package/src/lib/MutableRouter.js +30 -26
- package/src/lib/Plan.js +109 -62
- package/src/lib/ValidationError.js +13 -10
- package/src/lib/ValidatorFactory.js +7 -8
- package/src/lib/configuration-ingestor.js +200 -74
- package/src/lib/configure.js +31 -30
- package/src/lib/constants.js +8 -8
- package/src/lib/context-id-generators.js +39 -38
- package/src/lib/end-session.js +3 -3
- package/src/lib/field.js +48 -32
- package/src/lib/index.js +12 -12
- package/src/lib/logger.js +9 -9
- package/src/lib/mount.js +68 -73
- package/src/lib/nunjucks-filters.js +57 -44
- package/src/lib/nunjucks.js +20 -16
- package/src/lib/utils.js +69 -44
- package/src/lib/validators/dateObject.js +57 -48
- package/src/lib/validators/email.js +8 -9
- package/src/lib/validators/inArray.js +8 -9
- package/src/lib/validators/index.js +11 -11
- package/src/lib/validators/nino.js +25 -12
- package/src/lib/validators/postalAddressObject.js +73 -55
- package/src/lib/validators/range.js +9 -11
- package/src/lib/validators/regex.js +7 -8
- package/src/lib/validators/required.js +13 -14
- package/src/lib/validators/strlen.js +11 -12
- package/src/lib/validators/wordCount.js +17 -12
- package/src/lib/waypoint-url.js +48 -33
- package/src/middleware/body-parser.js +44 -10
- package/src/middleware/csrf.js +4 -1
- package/src/middleware/data.js +62 -25
- package/src/middleware/gather-fields.js +8 -8
- package/src/middleware/i18n.js +49 -39
- package/src/middleware/post.js +47 -21
- package/src/middleware/pre.js +60 -35
- package/src/middleware/progress-journey.js +32 -18
- package/src/middleware/sanitise-fields.js +43 -20
- package/src/middleware/serve-first-waypoint.js +12 -10
- package/src/middleware/session.js +97 -65
- package/src/middleware/skip-waypoint.js +7 -9
- package/src/middleware/steer-journey.js +39 -27
- package/src/middleware/strip-proxy-path.js +8 -7
- package/src/middleware/validate-fields.js +5 -12
- package/src/routes/ancillary.js +4 -6
- package/src/routes/journey.js +158 -78
- package/src/routes/static.js +61 -28
package/src/lib/MutableRouter.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { Router } from 'express';
|
|
1
|
+
import { Router } from "express";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* @memberof module:@dwp/govuk-casa
|
|
@@ -35,7 +34,7 @@ export default class MutableRouter {
|
|
|
35
34
|
|
|
36
35
|
#append(method, path, ...callbacks) {
|
|
37
36
|
if (this.#sealed) {
|
|
38
|
-
throw new Error(
|
|
37
|
+
throw new Error("Cannot alter middleware in a sealed mutable router");
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
this.#stack.push({
|
|
@@ -47,7 +46,7 @@ export default class MutableRouter {
|
|
|
47
46
|
|
|
48
47
|
#prepend(method, path, ...callbacks) {
|
|
49
48
|
if (this.#sealed) {
|
|
50
|
-
throw new Error(
|
|
49
|
+
throw new Error("Cannot alter middleware in a sealed mutable router");
|
|
51
50
|
}
|
|
52
51
|
|
|
53
52
|
this.#stack.splice(0, 0, {
|
|
@@ -61,10 +60,11 @@ export default class MutableRouter {
|
|
|
61
60
|
// given path
|
|
62
61
|
#replace(method, path, ...callbacks) {
|
|
63
62
|
if (this.#sealed) {
|
|
64
|
-
throw new Error(
|
|
63
|
+
throw new Error("Cannot alter middleware in a sealed mutable router");
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
const finder = (command) =>
|
|
66
|
+
const finder = (command) =>
|
|
67
|
+
`${command.method}|${command.path}` === `${method}|${path}`;
|
|
68
68
|
const index = this.#stack.findIndex(finder);
|
|
69
69
|
|
|
70
70
|
if (index > -1) {
|
|
@@ -74,7 +74,9 @@ export default class MutableRouter {
|
|
|
74
74
|
args: [path, ...callbacks],
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
this.#stack = this.#stack.filter(
|
|
77
|
+
this.#stack = this.#stack.filter(
|
|
78
|
+
(command, idx) => idx <= index || !finder(command),
|
|
79
|
+
);
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -110,7 +112,7 @@ export default class MutableRouter {
|
|
|
110
112
|
* @returns {void}
|
|
111
113
|
*/
|
|
112
114
|
prependAll(path, ...callbacks) {
|
|
113
|
-
this.#prepend(
|
|
115
|
+
this.#prepend("all", path, ...callbacks);
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
/**
|
|
@@ -121,7 +123,7 @@ export default class MutableRouter {
|
|
|
121
123
|
* @returns {void}
|
|
122
124
|
*/
|
|
123
125
|
prependGet(path, ...callbacks) {
|
|
124
|
-
this.#prepend(
|
|
126
|
+
this.#prepend("get", path, ...callbacks);
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
/**
|
|
@@ -132,7 +134,7 @@ export default class MutableRouter {
|
|
|
132
134
|
* @returns {void}
|
|
133
135
|
*/
|
|
134
136
|
prependPost(path, ...callbacks) {
|
|
135
|
-
this.#prepend(
|
|
137
|
+
this.#prepend("post", path, ...callbacks);
|
|
136
138
|
}
|
|
137
139
|
|
|
138
140
|
/**
|
|
@@ -143,7 +145,7 @@ export default class MutableRouter {
|
|
|
143
145
|
* @returns {void}
|
|
144
146
|
*/
|
|
145
147
|
prependDelete(path, ...callbacks) {
|
|
146
|
-
this.#prepend(
|
|
148
|
+
this.#prepend("delete", path, ...callbacks);
|
|
147
149
|
}
|
|
148
150
|
|
|
149
151
|
/**
|
|
@@ -154,7 +156,7 @@ export default class MutableRouter {
|
|
|
154
156
|
* @returns {void}
|
|
155
157
|
*/
|
|
156
158
|
prependPut(path, ...callbacks) {
|
|
157
|
-
this.#prepend(
|
|
159
|
+
this.#prepend("put", path, ...callbacks);
|
|
158
160
|
}
|
|
159
161
|
|
|
160
162
|
/**
|
|
@@ -165,7 +167,7 @@ export default class MutableRouter {
|
|
|
165
167
|
* @returns {void}
|
|
166
168
|
*/
|
|
167
169
|
prependUse(path, ...callbacks) {
|
|
168
|
-
this.#prepend(
|
|
170
|
+
this.#prepend("use", path, ...callbacks);
|
|
169
171
|
}
|
|
170
172
|
|
|
171
173
|
/* -------------------------------------------------------------- replacers */
|
|
@@ -178,7 +180,7 @@ export default class MutableRouter {
|
|
|
178
180
|
* @returns {void}
|
|
179
181
|
*/
|
|
180
182
|
replaceAll(path, ...callbacks) {
|
|
181
|
-
this.#replace(
|
|
183
|
+
this.#replace("all", path, ...callbacks);
|
|
182
184
|
}
|
|
183
185
|
|
|
184
186
|
/**
|
|
@@ -189,7 +191,7 @@ export default class MutableRouter {
|
|
|
189
191
|
* @returns {void}
|
|
190
192
|
*/
|
|
191
193
|
replaceGet(path, ...callbacks) {
|
|
192
|
-
this.#replace(
|
|
194
|
+
this.#replace("get", path, ...callbacks);
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
/**
|
|
@@ -200,7 +202,7 @@ export default class MutableRouter {
|
|
|
200
202
|
* @returns {void}
|
|
201
203
|
*/
|
|
202
204
|
replacePost(path, ...callbacks) {
|
|
203
|
-
this.#replace(
|
|
205
|
+
this.#replace("post", path, ...callbacks);
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
/**
|
|
@@ -211,7 +213,7 @@ export default class MutableRouter {
|
|
|
211
213
|
* @returns {void}
|
|
212
214
|
*/
|
|
213
215
|
replaceDelete(path, ...callbacks) {
|
|
214
|
-
this.#replace(
|
|
216
|
+
this.#replace("delete", path, ...callbacks);
|
|
215
217
|
}
|
|
216
218
|
|
|
217
219
|
/**
|
|
@@ -222,7 +224,7 @@ export default class MutableRouter {
|
|
|
222
224
|
* @returns {void}
|
|
223
225
|
*/
|
|
224
226
|
replacePut(path, ...callbacks) {
|
|
225
|
-
this.#replace(
|
|
227
|
+
this.#replace("put", path, ...callbacks);
|
|
226
228
|
}
|
|
227
229
|
|
|
228
230
|
/**
|
|
@@ -233,7 +235,7 @@ export default class MutableRouter {
|
|
|
233
235
|
* @returns {void}
|
|
234
236
|
*/
|
|
235
237
|
replaceUse(path, ...callbacks) {
|
|
236
|
-
this.#replace(
|
|
238
|
+
this.#replace("use", path, ...callbacks);
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
/* ---------------------------------------------- express.Router() wrappers */
|
|
@@ -246,7 +248,7 @@ export default class MutableRouter {
|
|
|
246
248
|
* @returns {void}
|
|
247
249
|
*/
|
|
248
250
|
all(path, ...callbacks) {
|
|
249
|
-
this.#append(
|
|
251
|
+
this.#append("all", path, ...callbacks);
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
/**
|
|
@@ -257,7 +259,7 @@ export default class MutableRouter {
|
|
|
257
259
|
* @returns {void}
|
|
258
260
|
*/
|
|
259
261
|
get(path, ...callbacks) {
|
|
260
|
-
this.#append(
|
|
262
|
+
this.#append("get", path, ...callbacks);
|
|
261
263
|
}
|
|
262
264
|
|
|
263
265
|
/**
|
|
@@ -268,7 +270,7 @@ export default class MutableRouter {
|
|
|
268
270
|
* @returns {void}
|
|
269
271
|
*/
|
|
270
272
|
post(path, ...callbacks) {
|
|
271
|
-
this.#append(
|
|
273
|
+
this.#append("post", path, ...callbacks);
|
|
272
274
|
}
|
|
273
275
|
|
|
274
276
|
/**
|
|
@@ -279,7 +281,7 @@ export default class MutableRouter {
|
|
|
279
281
|
* @returns {void}
|
|
280
282
|
*/
|
|
281
283
|
delete(path, ...callbacks) {
|
|
282
|
-
this.#append(
|
|
284
|
+
this.#append("delete", path, ...callbacks);
|
|
283
285
|
}
|
|
284
286
|
|
|
285
287
|
/**
|
|
@@ -290,7 +292,7 @@ export default class MutableRouter {
|
|
|
290
292
|
* @returns {void}
|
|
291
293
|
*/
|
|
292
294
|
put(path, ...callbacks) {
|
|
293
|
-
this.#append(
|
|
295
|
+
this.#append("put", path, ...callbacks);
|
|
294
296
|
}
|
|
295
297
|
|
|
296
298
|
/**
|
|
@@ -301,10 +303,12 @@ export default class MutableRouter {
|
|
|
301
303
|
* @returns {void}
|
|
302
304
|
*/
|
|
303
305
|
use(path, ...callbacks) {
|
|
304
|
-
this.#append(
|
|
306
|
+
this.#append("use", path, ...callbacks);
|
|
305
307
|
}
|
|
306
308
|
|
|
307
309
|
route() {
|
|
308
|
-
throw new Error(
|
|
310
|
+
throw new Error(
|
|
311
|
+
"route() method is not supported on MutableRouter. Use verb methods for now.",
|
|
312
|
+
);
|
|
309
313
|
}
|
|
310
314
|
}
|
package/src/lib/Plan.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Graph } from
|
|
2
|
-
import JourneyContext from
|
|
3
|
-
import logger from
|
|
1
|
+
import { Graph } from "@dagrejs/graphlib";
|
|
2
|
+
import JourneyContext from "./JourneyContext.js";
|
|
3
|
+
import logger from "./logger.js";
|
|
4
4
|
|
|
5
|
-
const log = logger(
|
|
5
|
+
const log = logger("lib:plan");
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @access private
|
|
@@ -39,7 +39,9 @@ const log = logger('lib:plan');
|
|
|
39
39
|
*/
|
|
40
40
|
function defaultNextFollow(r, context) {
|
|
41
41
|
const { validation: v = {} } = context.toObject();
|
|
42
|
-
return
|
|
42
|
+
return (
|
|
43
|
+
Object.prototype.hasOwnProperty.call(v, r.source) && v[r.source] === null
|
|
44
|
+
);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/**
|
|
@@ -51,7 +53,9 @@ function defaultNextFollow(r, context) {
|
|
|
51
53
|
*/
|
|
52
54
|
function defaultPrevFollow(r, context) {
|
|
53
55
|
const { validation: v = {} } = context.toObject();
|
|
54
|
-
return
|
|
56
|
+
return (
|
|
57
|
+
Object.prototype.hasOwnProperty.call(v, r.target) && v[r.target] === null
|
|
58
|
+
);
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
/**
|
|
@@ -64,11 +68,13 @@ function defaultPrevFollow(r, context) {
|
|
|
64
68
|
* @throws {SyntaxError} If waypoint ID is incorrectly formatted
|
|
65
69
|
*/
|
|
66
70
|
function validateWaypointId(val) {
|
|
67
|
-
if (typeof val !==
|
|
68
|
-
throw new TypeError(
|
|
71
|
+
if (typeof val !== "string") {
|
|
72
|
+
throw new TypeError(
|
|
73
|
+
`Expected waypoint id to be a string, got ${typeof val}`,
|
|
74
|
+
);
|
|
69
75
|
}
|
|
70
|
-
if (val.substr(0, 6) ===
|
|
71
|
-
throw new SyntaxError(
|
|
76
|
+
if (val.substr(0, 6) === "url://" && !val.endsWith("/")) {
|
|
77
|
+
throw new SyntaxError("url:// waypoints must include a trailing /");
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
|
|
@@ -82,10 +88,14 @@ function validateWaypointId(val) {
|
|
|
82
88
|
* @throws {ReferenceError} If route name is neither "next" or "prev"
|
|
83
89
|
*/
|
|
84
90
|
function validateRouteName(val) {
|
|
85
|
-
if (typeof val !==
|
|
86
|
-
throw new TypeError(
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
if (typeof val !== "string") {
|
|
92
|
+
throw new TypeError(
|
|
93
|
+
`Expected route name to be a string, got ${typeof val}`,
|
|
94
|
+
);
|
|
95
|
+
} else if (!["next", "prev"].includes(val)) {
|
|
96
|
+
throw new ReferenceError(
|
|
97
|
+
`Expected route name to be one of next or prev. Got ${val}`,
|
|
98
|
+
);
|
|
89
99
|
}
|
|
90
100
|
return val;
|
|
91
101
|
}
|
|
@@ -100,7 +110,9 @@ function validateRouteName(val) {
|
|
|
100
110
|
*/
|
|
101
111
|
function validateRouteCondition(val) {
|
|
102
112
|
if (!(val instanceof Function)) {
|
|
103
|
-
throw new TypeError(
|
|
113
|
+
throw new TypeError(
|
|
114
|
+
`Expected route condition to be a function, got ${typeof val}`,
|
|
115
|
+
);
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
|
|
@@ -174,14 +186,18 @@ export default class Plan {
|
|
|
174
186
|
});
|
|
175
187
|
|
|
176
188
|
// Gather options
|
|
177
|
-
const options = Object.assign(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
189
|
+
const options = Object.assign(
|
|
190
|
+
Object.create(null),
|
|
191
|
+
{
|
|
192
|
+
// When true, the validation state of the source node must be `null` (i.e.
|
|
193
|
+
// no validation errors) before any custom route conditions are evaluated.
|
|
194
|
+
validateBeforeRouteCondition: true,
|
|
195
|
+
|
|
196
|
+
// Traversal arbitration
|
|
197
|
+
arbiter: undefined,
|
|
198
|
+
},
|
|
199
|
+
opts,
|
|
200
|
+
);
|
|
185
201
|
Object.freeze(options);
|
|
186
202
|
|
|
187
203
|
priv.set(this, {
|
|
@@ -261,7 +277,9 @@ export default class Plan {
|
|
|
261
277
|
*/
|
|
262
278
|
getRoutes() {
|
|
263
279
|
const self = priv.get(this);
|
|
264
|
-
return self.dgraph
|
|
280
|
+
return self.dgraph
|
|
281
|
+
.edges()
|
|
282
|
+
.map((edge) => makeRouteObject(self.dgraph, edge));
|
|
265
283
|
}
|
|
266
284
|
|
|
267
285
|
/**
|
|
@@ -286,7 +304,9 @@ export default class Plan {
|
|
|
286
304
|
*/
|
|
287
305
|
getOutwardRoutes(src, tgt = null) {
|
|
288
306
|
const self = priv.get(this);
|
|
289
|
-
return self.dgraph
|
|
307
|
+
return self.dgraph
|
|
308
|
+
.outEdges(src, tgt)
|
|
309
|
+
.map((e) => makeRouteObject(self.dgraph, e));
|
|
290
310
|
}
|
|
291
311
|
|
|
292
312
|
/**
|
|
@@ -298,7 +318,7 @@ export default class Plan {
|
|
|
298
318
|
* @returns {PlanRoute[]} Route objects found.
|
|
299
319
|
*/
|
|
300
320
|
getPrevOutwardRoutes(src, tgt = null) {
|
|
301
|
-
return this.getOutwardRoutes(src, tgt).filter((r) => r.name ===
|
|
321
|
+
return this.getOutwardRoutes(src, tgt).filter((r) => r.name === "prev");
|
|
302
322
|
}
|
|
303
323
|
|
|
304
324
|
/**
|
|
@@ -326,7 +346,7 @@ export default class Plan {
|
|
|
326
346
|
* @returns {Plan} Chain
|
|
327
347
|
*/
|
|
328
348
|
setNextRoute(src, tgt, follow) {
|
|
329
|
-
return this.setNamedRoute(src, tgt,
|
|
349
|
+
return this.setNamedRoute(src, tgt, "next", follow);
|
|
330
350
|
}
|
|
331
351
|
|
|
332
352
|
/**
|
|
@@ -338,7 +358,7 @@ export default class Plan {
|
|
|
338
358
|
* @returns {Plan} Chain
|
|
339
359
|
*/
|
|
340
360
|
setPrevRoute(src, tgt, follow) {
|
|
341
|
-
return this.setNamedRoute(src, tgt,
|
|
361
|
+
return this.setNamedRoute(src, tgt, "prev", follow);
|
|
342
362
|
}
|
|
343
363
|
|
|
344
364
|
/**
|
|
@@ -364,21 +384,24 @@ export default class Plan {
|
|
|
364
384
|
* @returns {Plan} Chain
|
|
365
385
|
*/
|
|
366
386
|
setRoute(src, tgt, followNext = undefined, followPrev = undefined) {
|
|
367
|
-
this.setNamedRoute(src, tgt,
|
|
387
|
+
this.setNamedRoute(src, tgt, "next", followNext);
|
|
368
388
|
|
|
369
389
|
let followPrevious = followPrev;
|
|
370
390
|
if (followPrevious === undefined) {
|
|
371
|
-
followPrevious =
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
391
|
+
followPrevious =
|
|
392
|
+
followNext === undefined
|
|
393
|
+
? undefined
|
|
394
|
+
: (r, c) => {
|
|
395
|
+
const invertedRoute = {
|
|
396
|
+
...r,
|
|
397
|
+
source: r.target,
|
|
398
|
+
target: r.source,
|
|
399
|
+
};
|
|
400
|
+
return followNext(invertedRoute, c);
|
|
401
|
+
};
|
|
379
402
|
}
|
|
380
403
|
|
|
381
|
-
this.setNamedRoute(tgt, src,
|
|
404
|
+
this.setNamedRoute(tgt, src, "prev", followPrevious);
|
|
382
405
|
|
|
383
406
|
return this;
|
|
384
407
|
}
|
|
@@ -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(
|
|
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 ===
|
|
459
|
+
} else if (name === "next") {
|
|
432
460
|
// Retain the original function name of route condition
|
|
433
461
|
followFunc = {
|
|
434
|
-
[follow.name]: (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) =>
|
|
467
|
+
[follow.name]: (r, c) => defaultPrevFollow(r, c) && follow(r, c),
|
|
440
468
|
}[follow.name];
|
|
441
469
|
}
|
|
442
|
-
} else if (name ===
|
|
470
|
+
} else if (name === "next") {
|
|
443
471
|
followFunc = defaultNextFollow;
|
|
444
472
|
} else {
|
|
445
473
|
followFunc = defaultPrevFollow;
|
|
@@ -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:
|
|
504
|
+
return this.traverseRoutes(context, { ...options, routeName: "next" });
|
|
477
505
|
}
|
|
478
506
|
|
|
479
507
|
/**
|
|
@@ -485,7 +513,7 @@ 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:
|
|
516
|
+
return this.traverseRoutes(context, { ...options, routeName: "prev" });
|
|
489
517
|
}
|
|
490
518
|
|
|
491
519
|
/**
|
|
@@ -505,7 +533,9 @@ export default class Plan {
|
|
|
505
533
|
*/
|
|
506
534
|
traverseRoutes(context, options = {}) {
|
|
507
535
|
if (!(context instanceof JourneyContext)) {
|
|
508
|
-
throw new TypeError(
|
|
536
|
+
throw new TypeError(
|
|
537
|
+
`Expected context to be an instance of JourneyContext, got ${typeof context}`,
|
|
538
|
+
);
|
|
509
539
|
}
|
|
510
540
|
|
|
511
541
|
const self = priv.get(this);
|
|
@@ -513,13 +543,15 @@ export default class Plan {
|
|
|
513
543
|
/** @type {PlanTraverseOptions} */
|
|
514
544
|
const {
|
|
515
545
|
startWaypoint = this.getWaypoints()[0],
|
|
516
|
-
stopCondition = () =>
|
|
546
|
+
stopCondition = () => false,
|
|
517
547
|
arbiter = self.options.arbiter,
|
|
518
548
|
routeName,
|
|
519
549
|
} = options;
|
|
520
550
|
|
|
521
551
|
if (!self.dgraph.hasNode(startWaypoint)) {
|
|
522
|
-
throw new ReferenceError(
|
|
552
|
+
throw new ReferenceError(
|
|
553
|
+
`Plan does not contain waypoint '${startWaypoint}'`,
|
|
554
|
+
);
|
|
523
555
|
}
|
|
524
556
|
|
|
525
557
|
validateRouteName(routeName);
|
|
@@ -537,7 +569,11 @@ export default class Plan {
|
|
|
537
569
|
/* eslint-disable-next-line security/detect-object-injection */
|
|
538
570
|
return self.follows[routeName][`${e.v}/${e.w}`](route, context);
|
|
539
571
|
} catch (ex) {
|
|
540
|
-
log.warn(
|
|
572
|
+
log.warn(
|
|
573
|
+
'Route follow function threw an exception, "%s" (%s)',
|
|
574
|
+
ex.message,
|
|
575
|
+
`${e.v} -> ${e.w}`,
|
|
576
|
+
);
|
|
541
577
|
return false;
|
|
542
578
|
}
|
|
543
579
|
});
|
|
@@ -545,10 +581,12 @@ export default class Plan {
|
|
|
545
581
|
// When there's more than one candidate route to take, we need help to choose
|
|
546
582
|
if (target.length > 1) {
|
|
547
583
|
const satisfied = target.map((t) => `${t.v} -> ${t.w}`);
|
|
548
|
-
log.debug(
|
|
584
|
+
log.debug(
|
|
585
|
+
`Multiple routes were satisfied for "${routeName}" from "${startWP}" (${satisfied.join(" / ")}). Deciding how to resolve ...`,
|
|
586
|
+
);
|
|
549
587
|
|
|
550
|
-
if (arbiter ===
|
|
551
|
-
log.debug(
|
|
588
|
+
if (arbiter === "auto") {
|
|
589
|
+
log.debug("Using automatic arbitration process");
|
|
552
590
|
const targetNames = target.map(({ w }) => w);
|
|
553
591
|
const forwardTraversal = this.traverseNextRoutes(context, {
|
|
554
592
|
stopCondition: ({ source }) => targetNames.includes(source),
|
|
@@ -556,7 +594,7 @@ export default class Plan {
|
|
|
556
594
|
const resolved = forwardTraversal.pop();
|
|
557
595
|
target = target.filter((t) => t.w === resolved.source);
|
|
558
596
|
} else if (arbiter instanceof Function) {
|
|
559
|
-
log.debug(
|
|
597
|
+
log.debug("Using custom arbitration process");
|
|
560
598
|
// Convert to routeObject and back to edge object so that only the
|
|
561
599
|
// routeObject is used in the public API
|
|
562
600
|
target = arbiter({
|
|
@@ -564,9 +602,13 @@ export default class Plan {
|
|
|
564
602
|
journeyContext: context,
|
|
565
603
|
travereOptions: options,
|
|
566
604
|
});
|
|
567
|
-
target = target.map((r) => ({
|
|
605
|
+
target = target.map((r) => ({
|
|
606
|
+
v: r.source,
|
|
607
|
+
w: r.target,
|
|
608
|
+
name: r.name,
|
|
609
|
+
}));
|
|
568
610
|
} else {
|
|
569
|
-
log.warn(
|
|
611
|
+
log.warn("Unable to arbitrate");
|
|
570
612
|
target = [];
|
|
571
613
|
}
|
|
572
614
|
}
|
|
@@ -593,15 +635,20 @@ export default class Plan {
|
|
|
593
635
|
|
|
594
636
|
return results;
|
|
595
637
|
}
|
|
596
|
-
log.debug(
|
|
638
|
+
log.debug(
|
|
639
|
+
"Encountered loop (%s). Stopping traversal.",
|
|
640
|
+
`${route.source} -> ${route.target}`,
|
|
641
|
+
);
|
|
597
642
|
}
|
|
598
643
|
|
|
599
|
-
return [
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
644
|
+
return [
|
|
645
|
+
makeRouteObject(self.dgraph, {
|
|
646
|
+
v: startWP,
|
|
647
|
+
w: null,
|
|
648
|
+
name: routeName,
|
|
649
|
+
label: {},
|
|
650
|
+
}),
|
|
651
|
+
];
|
|
605
652
|
};
|
|
606
653
|
|
|
607
654
|
return traverse(startWaypoint);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import lodash from
|
|
1
|
+
import lodash from "lodash";
|
|
2
2
|
|
|
3
3
|
const { isPlainObject } = lodash; // CommonJS
|
|
4
4
|
|
|
@@ -41,13 +41,13 @@ export default class ValidationError {
|
|
|
41
41
|
*
|
|
42
42
|
* @param {object} args Arguments
|
|
43
43
|
* @param {ErrorMessageConfig} args.errorMsg Error message config to seed ValidationError
|
|
44
|
-
* @param {ValidateContext} [args.dataContext
|
|
44
|
+
* @param {ValidateContext} [args.dataContext] Data for error msg function
|
|
45
45
|
* @returns {ValidationError} Error instance
|
|
46
46
|
* @throws {TypeError} If errorMsg is not in a valid type
|
|
47
47
|
*/
|
|
48
48
|
static make({ errorMsg, dataContext = {} }) {
|
|
49
49
|
// Convert strings to the most basic object primitive
|
|
50
|
-
if (typeof errorMsg ===
|
|
50
|
+
if (typeof errorMsg === "string") {
|
|
51
51
|
return new ValidationError({
|
|
52
52
|
summary: errorMsg,
|
|
53
53
|
inline: errorMsg,
|
|
@@ -63,7 +63,7 @@ export default class ValidationError {
|
|
|
63
63
|
|
|
64
64
|
// Use the user-defined function to generate an error primitive for the
|
|
65
65
|
// given context
|
|
66
|
-
if (typeof errorMsg ===
|
|
66
|
+
if (typeof errorMsg === "function") {
|
|
67
67
|
return new ValidationError(errorMsg.call(null, { ...dataContext }));
|
|
68
68
|
}
|
|
69
69
|
|
|
@@ -77,7 +77,9 @@ export default class ValidationError {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Unsupported
|
|
80
|
-
throw new TypeError(
|
|
80
|
+
throw new TypeError(
|
|
81
|
+
"errorMsg must be a string, Error, primitive object or function that generates a primitive object",
|
|
82
|
+
);
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
/**
|
|
@@ -86,10 +88,11 @@ export default class ValidationError {
|
|
|
86
88
|
* @param {string|ErrorMessageConfigObject} errorParam Error configuration
|
|
87
89
|
*/
|
|
88
90
|
constructor(errorParam = {}) {
|
|
89
|
-
if (!isPlainObject(errorParam) && typeof errorParam !==
|
|
90
|
-
throw new TypeError(
|
|
91
|
+
if (!isPlainObject(errorParam) && typeof errorParam !== "string") {
|
|
92
|
+
throw new TypeError("Constructor requires a string or object");
|
|
91
93
|
}
|
|
92
|
-
const error =
|
|
94
|
+
const error =
|
|
95
|
+
typeof errorParam === "string" ? { summary: errorParam } : errorParam;
|
|
93
96
|
|
|
94
97
|
// Store parameters for later use in applying contexts
|
|
95
98
|
const originals = {
|
|
@@ -133,7 +136,7 @@ export default class ValidationError {
|
|
|
133
136
|
const originals = params.get(this);
|
|
134
137
|
|
|
135
138
|
// Expand variables
|
|
136
|
-
if (typeof originals.variables ===
|
|
139
|
+
if (typeof originals.variables === "function") {
|
|
137
140
|
this.variables = originals.variables.call(this, context);
|
|
138
141
|
}
|
|
139
142
|
|
|
@@ -150,7 +153,7 @@ export default class ValidationError {
|
|
|
150
153
|
fieldHref += focusSuffix[0];
|
|
151
154
|
}
|
|
152
155
|
|
|
153
|
-
this.field = context.fieldName + (originals.fieldKeySuffix ||
|
|
156
|
+
this.field = context.fieldName + (originals.fieldKeySuffix || "");
|
|
154
157
|
this.fieldHref = fieldHref;
|
|
155
158
|
this.focusSuffix = focusSuffix || [];
|
|
156
159
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import lodash from 'lodash';
|
|
1
|
+
import lodash from "lodash";
|
|
3
2
|
|
|
4
3
|
const { isPlainObject } = lodash; // CommonJS
|
|
5
4
|
|
|
@@ -48,14 +47,13 @@ export default class ValidatorFactory {
|
|
|
48
47
|
*/
|
|
49
48
|
static make(config = {}) {
|
|
50
49
|
if (!isPlainObject(config)) {
|
|
51
|
-
throw new TypeError(
|
|
50
|
+
throw new TypeError("Configuration must be an object");
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
const validator = Reflect.construct(this, [config]);
|
|
55
54
|
|
|
56
|
-
/* eslint-disable-next-line sonarjs/prefer-object-literal */
|
|
57
55
|
const instance = {};
|
|
58
|
-
instance.name = validator.name ||
|
|
56
|
+
instance.name = validator.name || "unknown";
|
|
59
57
|
instance.config = config;
|
|
60
58
|
instance.validate = validator.validate.bind(instance);
|
|
61
59
|
instance.sanitise = validator.sanitise.bind(instance);
|
|
@@ -72,7 +70,9 @@ export default class ValidatorFactory {
|
|
|
72
70
|
*/
|
|
73
71
|
constructor(config = {}) {
|
|
74
72
|
if (new.target === ValidatorFactory) {
|
|
75
|
-
throw new TypeError(
|
|
73
|
+
throw new TypeError(
|
|
74
|
+
"Cannot instantiate the abstract class, ValidatorFactory",
|
|
75
|
+
);
|
|
76
76
|
}
|
|
77
77
|
this.config = config;
|
|
78
78
|
}
|
|
@@ -89,10 +89,9 @@ export default class ValidatorFactory {
|
|
|
89
89
|
* @throws {Error}
|
|
90
90
|
*/
|
|
91
91
|
validate(fieldValue, context) {
|
|
92
|
-
throw new Error(
|
|
92
|
+
throw new Error("validate() method has not been implemented");
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
-
/* eslint-disable-next-line jsdoc/require-returns-check */
|
|
96
95
|
/**
|
|
97
96
|
* Sanitise the given value.
|
|
98
97
|
*
|