@dwp/govuk-casa 8.0.0-alpha2 → 8.0.0-beta1

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 (49) hide show
  1. package/dist/casa.d.ts +2 -1
  2. package/dist/casa.js +3 -1
  3. package/dist/lib/CasaTemplateLoader.d.ts +6 -2
  4. package/dist/lib/CasaTemplateLoader.js +4 -1
  5. package/dist/lib/JourneyContext.d.ts +37 -6
  6. package/dist/lib/JourneyContext.js +21 -6
  7. package/dist/lib/MutableRouter.js +3 -1
  8. package/dist/lib/Plan.d.ts +37 -4
  9. package/dist/lib/Plan.js +63 -6
  10. package/dist/lib/ValidationError.d.ts +6 -2
  11. package/dist/lib/ValidationError.js +3 -0
  12. package/dist/lib/ValidatorFactory.d.ts +72 -19
  13. package/dist/lib/ValidatorFactory.js +33 -20
  14. package/dist/lib/configuration-ingestor.d.ts +262 -0
  15. package/dist/lib/configuration-ingestor.js +490 -0
  16. package/dist/lib/configure.d.ts +26 -140
  17. package/dist/lib/configure.js +16 -43
  18. package/dist/lib/dirname.d.cts +2 -0
  19. package/dist/lib/end-session.d.ts +2 -1
  20. package/dist/lib/end-session.js +24 -7
  21. package/dist/lib/field.d.ts +38 -45
  22. package/dist/lib/field.js +56 -34
  23. package/dist/lib/index.d.ts +14 -0
  24. package/dist/lib/index.js +54 -0
  25. package/dist/lib/logger.d.ts +2 -1
  26. package/dist/lib/logger.js +2 -3
  27. package/dist/lib/utils.d.ts +18 -2
  28. package/dist/lib/utils.js +54 -2
  29. package/dist/lib/waypoint-url.d.ts +2 -1
  30. package/dist/lib/waypoint-url.js +3 -0
  31. package/dist/middleware/body-parser.js +2 -2
  32. package/dist/middleware/data.d.ts +1 -2
  33. package/dist/middleware/data.js +4 -8
  34. package/dist/middleware/dirname.d.cts +2 -0
  35. package/dist/middleware/gather-fields.d.ts +2 -1
  36. package/dist/middleware/gather-fields.js +3 -0
  37. package/dist/middleware/post.js +6 -6
  38. package/dist/middleware/sanitise-fields.js +4 -4
  39. package/dist/middleware/session.d.ts +2 -1
  40. package/dist/middleware/session.js +2 -2
  41. package/dist/middleware/steer-journey.d.ts +2 -1
  42. package/dist/middleware/steer-journey.js +3 -0
  43. package/dist/routes/ancillary.d.ts +8 -1
  44. package/dist/routes/ancillary.js +7 -0
  45. package/dist/routes/dirname.d.cts +2 -0
  46. package/dist/routes/journey.js +9 -2
  47. package/dist/routes/static.js +4 -3
  48. package/package.json +27 -17
  49. package/views/casa/layouts/main.njk +2 -2
package/dist/casa.d.ts CHANGED
@@ -3,8 +3,9 @@ import validators from "./lib/validators/index.js";
3
3
  import field from "./lib/field.js";
4
4
  import Plan from "./lib/Plan.js";
5
5
  import JourneyContext from "./lib/JourneyContext.js";
6
+ import ValidatorFactory from "./lib/ValidatorFactory.js";
6
7
  import ValidationError from "./lib/ValidationError.js";
7
8
  import waypointUrl from "./lib/waypoint-url.js";
8
9
  import endSession from "./lib/end-session.js";
9
10
  import * as nunjucksFilters from "./lib/nunjucks-filters.js";
10
- export { configure, validators, field, Plan, JourneyContext, ValidationError, waypointUrl, endSession, nunjucksFilters };
11
+ export { configure, validators, field, Plan, JourneyContext, ValidatorFactory, ValidationError, waypointUrl, endSession, nunjucksFilters };
package/dist/casa.js CHANGED
@@ -22,7 +22,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
22
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
23
23
  };
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
- exports.nunjucksFilters = exports.endSession = exports.waypointUrl = exports.ValidationError = exports.JourneyContext = exports.Plan = exports.field = exports.validators = exports.configure = void 0;
25
+ exports.nunjucksFilters = exports.endSession = exports.waypointUrl = exports.ValidationError = exports.ValidatorFactory = exports.JourneyContext = exports.Plan = exports.field = exports.validators = exports.configure = void 0;
26
26
  // NOTE: Any changes made here must be reflected in `scripts/esm-wrapper.js`
27
27
  const configure_js_1 = __importDefault(require("./lib/configure.js"));
28
28
  exports.configure = configure_js_1.default;
@@ -34,6 +34,8 @@ const Plan_js_1 = __importDefault(require("./lib/Plan.js"));
34
34
  exports.Plan = Plan_js_1.default;
35
35
  const JourneyContext_js_1 = __importDefault(require("./lib/JourneyContext.js"));
36
36
  exports.JourneyContext = JourneyContext_js_1.default;
37
+ const ValidatorFactory_js_1 = __importDefault(require("./lib/ValidatorFactory.js"));
38
+ exports.ValidatorFactory = ValidatorFactory_js_1.default;
37
39
  const ValidationError_js_1 = __importDefault(require("./lib/ValidationError.js"));
38
40
  exports.ValidationError = ValidationError_js_1.default;
39
41
  const waypoint_url_js_1 = __importDefault(require("./lib/waypoint-url.js"));
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @typedef {import('nunjucks').FileSystemLoaderOptions} FileSystemLoaderOptions
3
+ */
1
4
  /**
2
5
  * @callback BlockModifier
3
6
  * @param {string} templateName Path to the template being modified
@@ -8,9 +11,9 @@ export default class CasaTemplateLoader extends FileSystemLoader {
8
11
  * Constructor.
9
12
  *
10
13
  * @param {string[]} searchPaths Template directories
11
- * @param {import('nunjucks').FileSystemLoaderOptions} opts Loader options
14
+ * @param {FileSystemLoaderOptions} opts Loader options
12
15
  */
13
- constructor(searchPaths: string[], opts: import('nunjucks').FileSystemLoaderOptions);
16
+ constructor(searchPaths: string[], opts: FileSystemLoaderOptions);
14
17
  /**
15
18
  * Add a modification function to the loader.
16
19
  *
@@ -21,5 +24,6 @@ export default class CasaTemplateLoader extends FileSystemLoader {
21
24
  modifyBlock(block: string, modifier: BlockModifier): void;
22
25
  #private;
23
26
  }
27
+ export type FileSystemLoaderOptions = import('nunjucks').FileSystemLoaderOptions;
24
28
  export type BlockModifier = (templateName: string) => string;
25
29
  import { FileSystemLoader } from "nunjucks";
@@ -13,6 +13,9 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var _CasaTemplateLoader_instances, _CasaTemplateLoader_blockModifiers, _CasaTemplateLoader_applyBlockModifiers;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const nunjucks_1 = require("nunjucks");
16
+ /**
17
+ * @typedef {import('nunjucks').FileSystemLoaderOptions} FileSystemLoaderOptions
18
+ */
16
19
  /**
17
20
  * @callback BlockModifier
18
21
  * @param {string} templateName Path to the template being modified
@@ -23,7 +26,7 @@ class CasaTemplateLoader extends nunjucks_1.FileSystemLoader {
23
26
  * Constructor.
24
27
  *
25
28
  * @param {string[]} searchPaths Template directories
26
- * @param {import('nunjucks').FileSystemLoaderOptions} opts Loader options
29
+ * @param {FileSystemLoaderOptions} opts Loader options
27
30
  */
28
31
  constructor(searchPaths, opts) {
29
32
  super(searchPaths, opts);
@@ -1,3 +1,18 @@
1
+ /**
2
+ * @typedef {import('./configuration-ingestor').Page} Page
3
+ */
4
+ /**
5
+ * @callback ContextEventHandler
6
+ * @param {JourneyContext} journeyContext Context including changes
7
+ * @param {JourneyContext} previousContext Context prior to changes
8
+ * @returns {void}
9
+ */
10
+ /**
11
+ * @typedef {object} ContextEvent
12
+ * @property {string} waypoint Waypoint to watch for changes
13
+ * @property {string} [field] Field to watch for changes
14
+ * @property {ContextEventHandler} handler Handler to invoke when change happens
15
+ */
1
16
  export default class JourneyContext {
2
17
  static DEFAULT_CONTEXT_ID: string;
3
18
  /**
@@ -133,11 +148,11 @@ export default class JourneyContext {
133
148
  /**
134
149
  * Get data context for a specific a specific page.
135
150
  *
136
- * @param {string | PageMeta} page Page waypoint ID, or Page object.
151
+ * @param {string | Page} page Page waypoint ID, or Page object.
137
152
  * @returns {object} Page data.
138
153
  * @throws {TypeError} When page is invalid.
139
154
  */
140
- getDataForPage(page: string | any): object;
155
+ getDataForPage(page: string | Page): object;
141
156
  getData(): object;
142
157
  /**
143
158
  * Overwrite the data context with a new object.
@@ -150,16 +165,16 @@ export default class JourneyContext {
150
165
  * Write field form data from a page HTML form, into the `data` model.
151
166
  *
152
167
  * By default this will store the data as-is, keyed against the page's
153
- * waypoint ID. However, when passing a `PageMeta` instance, its
168
+ * waypoint ID. However, when passing a `Page` instance, its
154
169
  * `fieldWriter()` method will be called to transform the provided formData
155
170
  * before storing in `data`
156
171
  *
157
- * @param {string | PageMeta} page Page waypoint ID, or PageMeta object
172
+ * @param {string | Page} page Page waypoint ID, or Page object
158
173
  * @param {object} webFormData Data to overwrite with
159
174
  * @returns {JourneyContext} Chain
160
175
  * @throws {TypeError} When page is invalid.
161
176
  */
162
- setDataForPage(page: string | any, webFormData: object): JourneyContext;
177
+ setDataForPage(page: string | Page, webFormData: object): JourneyContext;
163
178
  /**
164
179
  * Return validation errors for all pages.
165
180
  *
@@ -251,7 +266,7 @@ export default class JourneyContext {
251
266
  * @param {ContextEvent[]} events Event listeners
252
267
  * @returns {JourneyContext} Chain
253
268
  */
254
- addEventListeners(events: any[]): JourneyContext;
269
+ addEventListeners(events: ContextEvent[]): JourneyContext;
255
270
  applyEventListeners({ event }: {
256
271
  event: any;
257
272
  }): JourneyContext;
@@ -263,4 +278,20 @@ export default class JourneyContext {
263
278
  isDefault(): boolean;
264
279
  #private;
265
280
  }
281
+ export type Page = import('./configuration-ingestor').Page;
282
+ export type ContextEventHandler = (journeyContext: JourneyContext, previousContext: JourneyContext) => void;
283
+ export type ContextEvent = {
284
+ /**
285
+ * Waypoint to watch for changes
286
+ */
287
+ waypoint: string;
288
+ /**
289
+ * Field to watch for changes
290
+ */
291
+ field?: string | undefined;
292
+ /**
293
+ * Handler to invoke when change happens
294
+ */
295
+ handler: ContextEventHandler;
296
+ };
266
297
  import ValidationError from "./ValidationError.js";
@@ -40,6 +40,21 @@ const ValidationError_js_1 = __importDefault(require("./ValidationError.js"));
40
40
  const logger_js_1 = __importDefault(require("./logger.js"));
41
41
  const { cloneDeep, isPlainObject, isObject, has, isEqual, } = lodash_1.default; // CommonJS
42
42
  const log = (0, logger_js_1.default)('class:journey-context');
43
+ /**
44
+ * @typedef {import('./configuration-ingestor').Page} Page
45
+ */
46
+ /**
47
+ * @callback ContextEventHandler
48
+ * @param {JourneyContext} journeyContext Context including changes
49
+ * @param {JourneyContext} previousContext Context prior to changes
50
+ * @returns {void}
51
+ */
52
+ /**
53
+ * @typedef {object} ContextEvent
54
+ * @property {string} waypoint Waypoint to watch for changes
55
+ * @property {string} [field] Field to watch for changes
56
+ * @property {ContextEventHandler} handler Handler to invoke when change happens
57
+ */
43
58
  class JourneyContext {
44
59
  /**
45
60
  * Constructor.
@@ -123,7 +138,7 @@ class JourneyContext {
123
138
  /**
124
139
  * Get data context for a specific a specific page.
125
140
  *
126
- * @param {string | PageMeta} page Page waypoint ID, or Page object.
141
+ * @param {string | Page} page Page waypoint ID, or Page object.
127
142
  * @returns {object} Page data.
128
143
  * @throws {TypeError} When page is invalid.
129
144
  */
@@ -153,11 +168,11 @@ class JourneyContext {
153
168
  * Write field form data from a page HTML form, into the `data` model.
154
169
  *
155
170
  * By default this will store the data as-is, keyed against the page's
156
- * waypoint ID. However, when passing a `PageMeta` instance, its
171
+ * waypoint ID. However, when passing a `Page` instance, its
157
172
  * `fieldWriter()` method will be called to transform the provided formData
158
173
  * before storing in `data`
159
174
  *
160
- * @param {string | PageMeta} page Page waypoint ID, or PageMeta object
175
+ * @param {string | Page} page Page waypoint ID, or Page object
161
176
  * @param {object} webFormData Data to overwrite with
162
177
  * @returns {JourneyContext} Chain
163
178
  * @throws {TypeError} When page is invalid.
@@ -325,7 +340,7 @@ class JourneyContext {
325
340
  return this;
326
341
  }
327
342
  applyEventListeners({ event }) {
328
- var _a, _b, _c, _d, _e, _f;
343
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
329
344
  if (!__classPrivateFieldGet(this, _JourneyContext_eventListeners, "f").length) {
330
345
  return this;
331
346
  }
@@ -341,11 +356,11 @@ class JourneyContext {
341
356
  }
342
357
  else if (waypoint && !field) {
343
358
  logMessage = `Calling waypoint-specific event handler on "${waypoint}"`;
344
- runHandler = !isEqual((_a = this.data) === null || _a === void 0 ? void 0 : _a[waypoint], (_b = previousContext.data) === null || _b === void 0 ? void 0 : _b[waypoint]);
359
+ runHandler = ((_a = previousContext.data) === null || _a === void 0 ? void 0 : _a[waypoint]) !== undefined && !isEqual((_b = this.data) === null || _b === void 0 ? void 0 : _b[waypoint], (_c = previousContext.data) === null || _c === void 0 ? void 0 : _c[waypoint]);
345
360
  }
346
361
  else if (waypoint && field) {
347
362
  logMessage = `Calling field-specific event handler on "${waypoint} : ${field}"`;
348
- runHandler = !isEqual((_d = (_c = this.data) === null || _c === void 0 ? void 0 : _c[waypoint]) === null || _d === void 0 ? void 0 : _d[field], (_f = (_e = previousContext.data) === null || _e === void 0 ? void 0 : _e[waypoint]) === null || _f === void 0 ? void 0 : _f[field]);
363
+ runHandler = ((_e = (_d = previousContext.data) === null || _d === void 0 ? void 0 : _d[waypoint]) === null || _e === void 0 ? void 0 : _e[field]) !== undefined && !isEqual((_g = (_f = this.data) === null || _f === void 0 ? void 0 : _f[waypoint]) === null || _g === void 0 ? void 0 : _g[field], (_j = (_h = previousContext.data) === null || _h === void 0 ? void 0 : _h[waypoint]) === null || _j === void 0 ? void 0 : _j[field]);
349
364
  }
350
365
  if (runHandler) {
351
366
  log.trace(logMessage);
@@ -264,12 +264,14 @@ _MutableRouter_stack = new WeakMap(), _MutableRouter_router = new WeakMap(), _Mu
264
264
  if (__classPrivateFieldGet(this, _MutableRouter_sealed, "f")) {
265
265
  throw new Error('Cannot alter middleware in a sealed mutable router');
266
266
  }
267
- const index = __classPrivateFieldGet(this, _MutableRouter_stack, "f").findIndex((command) => `${command.method}|${command.path}` === `${method}|${path}`);
267
+ const finder = (command) => `${command.method}|${command.path}` === `${method}|${path}`;
268
+ const index = __classPrivateFieldGet(this, _MutableRouter_stack, "f").findIndex(finder);
268
269
  if (index > -1) {
269
270
  __classPrivateFieldGet(this, _MutableRouter_stack, "f").splice(index, 1, {
270
271
  method,
271
272
  path,
272
273
  args: [path, ...callbacks],
273
274
  });
275
+ __classPrivateFieldSet(this, _MutableRouter_stack, __classPrivateFieldGet(this, _MutableRouter_stack, "f").filter((command, idx) => idx <= index || !finder(command)), "f");
274
276
  }
275
277
  };
@@ -1,12 +1,44 @@
1
1
  export default class Plan {
2
- static isExitNode(name: any): boolean;
2
+ /**
3
+ * Waypoints using the url:// protocol are known as "exit nodes" as they
4
+ * indicate an exit point to another Plan.
5
+ *
6
+ * @param {string} name Waypoint name
7
+ * @returns {boolean} True if the waypoint is a url:// type
8
+ */
9
+ static isExitNode(name: string): boolean;
3
10
  /**
4
11
  * Create a Plan.
5
12
  *
6
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
7
16
  */
8
- constructor(opts?: object);
17
+ constructor(opts?: {
18
+ validateBeforeRouteCondition?: boolean | undefined;
19
+ arbiter?: string | Function | undefined;
20
+ });
9
21
  getOptions(): any;
22
+ /**
23
+ * Retrieve the list of skippable waypoints.
24
+ *
25
+ * @returns {string[]} List of skippable waypoints
26
+ */
27
+ getSkippables(): string[];
28
+ /**
29
+ * Add one or more skippable waypoints.
30
+ *
31
+ * @param {...string} waypoints Waypoints
32
+ * @returns {Plan}{ Chain}
33
+ */
34
+ addSkippables(...waypoints: string[]): Plan;
35
+ /**
36
+ * Check if the user can skip the named waypoint.
37
+ *
38
+ * @param {string} waypoint Waypoint
39
+ * @returns {boolean} True if waypoint can be skipped
40
+ */
41
+ isSkippable(waypoint: string): boolean;
10
42
  getWaypoints(): any;
11
43
  containsWaypoint(waypoint: any): any;
12
44
  getRoutes(): any;
@@ -114,8 +146,9 @@ export default class Plan {
114
146
  * Get raw graph data structure. This can be used with other libraries to
115
147
  * generate graph visualisations, for example.
116
148
  *
117
- * @returns {graphlib.Graph} Graph data structure.
149
+ * @returns {Graph} Graph data structure.
118
150
  */
119
- getGraphStructure(): any;
151
+ getGraphStructure(): Graph;
152
+ #private;
120
153
  }
121
154
  import JourneyContext from "./JourneyContext.js";
package/dist/lib/Plan.js CHANGED
@@ -1,7 +1,19 @@
1
1
  "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
2
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
15
  };
16
+ var _Plan_skippableWaypoints;
5
17
  Object.defineProperty(exports, "__esModule", { value: true });
6
18
  const graphlib_1 = require("graphlib");
7
19
  const JourneyContext_js_1 = __importDefault(require("./JourneyContext.js"));
@@ -35,6 +47,9 @@ function validateWaypointId(val) {
35
47
  if (typeof val !== 'string') {
36
48
  throw new TypeError(`Expected waypoint id to be a string, got ${typeof val}`);
37
49
  }
50
+ if (val.substr(0, 6) === 'url://' && !val.endsWith('/')) {
51
+ throw new SyntaxError('url:// waypoints must include a trailing /');
52
+ }
38
53
  }
39
54
  function validateRouteName(val) {
40
55
  if (typeof val !== 'string') {
@@ -74,15 +89,18 @@ const makeRouteObject = (dgraph, edge) => {
74
89
  const reExitNodeProtocol = /^[a-z]+:\/\//i;
75
90
  const priv = new WeakMap();
76
91
  class Plan {
77
- static isExitNode(name) {
78
- return reExitNodeProtocol.test(name);
79
- }
80
92
  /**
81
93
  * Create a Plan.
82
94
  *
83
95
  * @param {object} opts Options
96
+ * @param {boolean} [opts.validateBeforeRouteCondition=true] Check page validity before conditions
97
+ * @param {Function|string} [opts.arbiter=undefined] Arbitration mechanism
84
98
  */
85
99
  constructor(opts = {}) {
100
+ /**
101
+ * @type {string[]} These waypoints can be skipped
102
+ */
103
+ _Plan_skippableWaypoints.set(this, void 0);
86
104
  // This is our directed, multigraph representation
87
105
  const dgraph = new graphlib_1.Graph({
88
106
  directed: true,
@@ -106,10 +124,48 @@ class Plan {
106
124
  },
107
125
  options,
108
126
  });
127
+ __classPrivateFieldSet(this, _Plan_skippableWaypoints, [], "f");
128
+ }
129
+ /**
130
+ * Waypoints using the url:// protocol are known as "exit nodes" as they
131
+ * indicate an exit point to another Plan.
132
+ *
133
+ * @param {string} name Waypoint name
134
+ * @returns {boolean} True if the waypoint is a url:// type
135
+ */
136
+ static isExitNode(name) {
137
+ return reExitNodeProtocol.test(name);
109
138
  }
110
139
  getOptions() {
111
140
  return priv.get(this).options;
112
141
  }
142
+ /**
143
+ * Retrieve the list of skippable waypoints.
144
+ *
145
+ * @returns {string[]} List of skippable waypoints
146
+ */
147
+ getSkippables() {
148
+ return __classPrivateFieldGet(this, _Plan_skippableWaypoints, "f");
149
+ }
150
+ /**
151
+ * Add one or more skippable waypoints.
152
+ *
153
+ * @param {...string} waypoints Waypoints
154
+ * @returns {Plan}{ Chain}
155
+ */
156
+ addSkippables(...waypoints) {
157
+ __classPrivateFieldSet(this, _Plan_skippableWaypoints, [...__classPrivateFieldGet(this, _Plan_skippableWaypoints, "f"), ...waypoints], "f");
158
+ return this;
159
+ }
160
+ /**
161
+ * Check if the user can skip the named waypoint.
162
+ *
163
+ * @param {string} waypoint Waypoint
164
+ * @returns {boolean} True if waypoint can be skipped
165
+ */
166
+ isSkippable(waypoint) {
167
+ return __classPrivateFieldGet(this, _Plan_skippableWaypoints, "f").indexOf(waypoint) > -1;
168
+ }
113
169
  getWaypoints() {
114
170
  return priv.get(this).dgraph.nodes();
115
171
  }
@@ -222,12 +278,12 @@ class Plan {
222
278
  validateRouteCondition(follow);
223
279
  }
224
280
  // Get routing function name to label edge
225
- const label = follow && follow.name;
281
+ const conditionName = follow && follow.name;
226
282
  // Warn if we're overwriting an existing edge on the same name
227
283
  if (self.dgraph.hasEdge(src, tgt, name)) {
228
284
  log.warn('Setting a route that already exists (%s, %s, %s). Will be overridden', src, tgt, name);
229
285
  }
230
- self.dgraph.setEdge(src, tgt, { label }, name);
286
+ self.dgraph.setEdge(src, tgt, { conditionName }, name);
231
287
  // Determine which follow function to use
232
288
  let followFunc;
233
289
  if (follow) {
@@ -376,10 +432,11 @@ class Plan {
376
432
  * Get raw graph data structure. This can be used with other libraries to
377
433
  * generate graph visualisations, for example.
378
434
  *
379
- * @returns {graphlib.Graph} Graph data structure.
435
+ * @returns {Graph} Graph data structure.
380
436
  */
381
437
  getGraphStructure() {
382
438
  return priv.get(this).dgraph;
383
439
  }
384
440
  }
385
441
  exports.default = Plan;
442
+ _Plan_skippableWaypoints = new WeakMap();
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @typedef {import('./ValidatorFactory').ValidateContext} ValidateContext
3
+ */
1
4
  export default class ValidationError {
2
5
  /**
3
6
  * Make a ValidationError instance from a primitive object (or a function that
@@ -61,10 +64,11 @@ export default class ValidationError {
61
64
  * @param {ValidateContext} context See structure above
62
65
  * @returns {ValidationError} Chain
63
66
  */
64
- withContext(context: any): ValidationError;
67
+ withContext(context: ValidateContext): ValidationError;
65
68
  variables: any;
66
- field: any;
69
+ field: string | undefined;
67
70
  fieldHref: string | undefined;
68
71
  focusSuffix: any;
69
72
  validator: any;
70
73
  }
74
+ export type ValidateContext = import('./ValidatorFactory').ValidateContext;
@@ -6,6 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const lodash_1 = __importDefault(require("lodash"));
7
7
  const { isPlainObject } = lodash_1.default; // CommonJS
8
8
  const params = new WeakMap();
9
+ /**
10
+ * @typedef {import('./ValidatorFactory').ValidateContext} ValidateContext
11
+ */
9
12
  class ValidationError {
10
13
  /**
11
14
  * Make a ValidationError instance from a primitive object (or a function that
@@ -1,30 +1,83 @@
1
+ /**
2
+ * @typedef {import('./index').ProcessorFunction} ProcessorFunction
3
+ */
4
+ /**
5
+ * @typedef {import('./index').JourneyContext} JourneyContext
6
+ */
7
+ /**
8
+ * @typedef {import('./index').ValidationError} ValidationError
9
+ */
10
+ /**
11
+ * @typedef {object} Validator
12
+ * @property {ValidateFunction} validate Validation function
13
+ * @property {ProcessorFunction} sanitise Sanitise a given value prior to validation
14
+ * @property {object} config Configuration
15
+ * @property {string} name Validator name
16
+ */
17
+ /**
18
+ * @callback ValidateFunction
19
+ * @param {any} value
20
+ * @param {ValidateContext} context
21
+ * @returns {ValidationError[]}
22
+ */
23
+ /**
24
+ * @typedef {object} ValidateContext Context passed to validate function
25
+ * @property {JourneyContext} journeyContext Journey context
26
+ * @property {string} waypoint Waypoint
27
+ * @property {string} fieldName Name of field being processed
28
+ */
1
29
  export default class ValidatorFactory {
2
30
  /**
3
- * This is a convenience method that will bind and return this class'
4
- * `validate()` function, so you can call it directly rather than calling the
5
- * method. i.e.
31
+ * This is a convenience method that will return a consistently object
32
+ * structure containing validation and sanitisation methods.
6
33
  *
7
- * MyValidator.make()('value to validate')
8
- * versus
9
- * (new MyValidator()).validate('value to validate')
10
- *
11
- * It also attaches the `sanitise()` method as a static property to that
12
- * function.
13
- *
14
- * @param {object} config Validator config
15
- * @returns {object} Validator object
34
+ * @param {object} config Validator config (custom to the validator being created)
35
+ * @returns {Validator} Validator object
16
36
  * @throws {TypeError} When configurarion is invalid.
17
37
  */
18
- static make(config?: object): object;
38
+ static make(config?: object): Validator;
19
39
  static coerceToValidatorObject(input: any): any;
20
40
  constructor(config?: {});
21
41
  config: {};
22
- /**
23
- * Validate the field value.
24
- *
25
- * @param {any} fieldValue Field value
26
- * @param {ValidateContext} context Validation context
27
- */
28
42
  validate(fieldValue: any, context: any): void;
29
43
  sanitise(fieldValue: any): any;
30
44
  }
45
+ export type ProcessorFunction = import('./index').ProcessorFunction;
46
+ export type JourneyContext = import('./index').JourneyContext;
47
+ export type ValidationError = import('./index').ValidationError;
48
+ export type Validator = {
49
+ /**
50
+ * Validation function
51
+ */
52
+ validate: ValidateFunction;
53
+ /**
54
+ * Sanitise a given value prior to validation
55
+ */
56
+ sanitise: any;
57
+ /**
58
+ * Configuration
59
+ */
60
+ config: object;
61
+ /**
62
+ * Validator name
63
+ */
64
+ name: string;
65
+ };
66
+ export type ValidateFunction = (value: any, context: ValidateContext) => ValidationError[];
67
+ /**
68
+ * Context passed to validate function
69
+ */
70
+ export type ValidateContext = {
71
+ /**
72
+ * Journey context
73
+ */
74
+ journeyContext: JourneyContext;
75
+ /**
76
+ * Waypoint
77
+ */
78
+ waypoint: string;
79
+ /**
80
+ * Name of field being processed
81
+ */
82
+ fieldName: string;
83
+ };
@@ -4,24 +4,43 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  /* eslint-disable class-methods-use-this */
7
- // const { isPlainObject } = require('../Util.js');
8
7
  const lodash_1 = __importDefault(require("lodash"));
9
8
  const { isPlainObject } = lodash_1.default; // CommonJS
9
+ /**
10
+ * @typedef {import('./index').ProcessorFunction} ProcessorFunction
11
+ */
12
+ /**
13
+ * @typedef {import('./index').JourneyContext} JourneyContext
14
+ */
15
+ /**
16
+ * @typedef {import('./index').ValidationError} ValidationError
17
+ */
18
+ /**
19
+ * @typedef {object} Validator
20
+ * @property {ValidateFunction} validate Validation function
21
+ * @property {ProcessorFunction} sanitise Sanitise a given value prior to validation
22
+ * @property {object} config Configuration
23
+ * @property {string} name Validator name
24
+ */
25
+ /**
26
+ * @callback ValidateFunction
27
+ * @param {any} value
28
+ * @param {ValidateContext} context
29
+ * @returns {ValidationError[]}
30
+ */
31
+ /**
32
+ * @typedef {object} ValidateContext Context passed to validate function
33
+ * @property {JourneyContext} journeyContext Journey context
34
+ * @property {string} waypoint Waypoint
35
+ * @property {string} fieldName Name of field being processed
36
+ */
10
37
  class ValidatorFactory {
11
38
  /**
12
- * This is a convenience method that will bind and return this class'
13
- * `validate()` function, so you can call it directly rather than calling the
14
- * method. i.e.
39
+ * This is a convenience method that will return a consistently object
40
+ * structure containing validation and sanitisation methods.
15
41
  *
16
- * MyValidator.make()('value to validate')
17
- * versus
18
- * (new MyValidator()).validate('value to validate')
19
- *
20
- * It also attaches the `sanitise()` method as a static property to that
21
- * function.
22
- *
23
- * @param {object} config Validator config
24
- * @returns {object} Validator object
42
+ * @param {object} config Validator config (custom to the validator being created)
43
+ * @returns {Validator} Validator object
25
44
  * @throws {TypeError} When configurarion is invalid.
26
45
  */
27
46
  static make(config = {}) {
@@ -31,7 +50,7 @@ class ValidatorFactory {
31
50
  const validator = Reflect.construct(this, [config]);
32
51
  /* eslint-disable-next-line sonarjs/prefer-object-literal */
33
52
  const instance = {};
34
- instance.name = validator.name || validator.constructor.name;
53
+ instance.name = validator.name || 'unknown';
35
54
  instance.config = config;
36
55
  instance.validate = validator.validate.bind(instance);
37
56
  instance.sanitise = validator.sanitise.bind(instance);
@@ -75,12 +94,6 @@ class ValidatorFactory {
75
94
  }
76
95
  this.config = config;
77
96
  }
78
- /**
79
- * Validate the field value.
80
- *
81
- * @param {any} fieldValue Field value
82
- * @param {ValidateContext} context Validation context
83
- */
84
97
  /* eslint-disable-next-line no-unused-vars */
85
98
  validate(fieldValue, context) {
86
99
  throw new Error('validate() method has not been implemented');