@dwp/govuk-casa 8.0.2 → 8.2.0

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 (54) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +2 -0
  3. package/dist/assets/css/casa-ie8.css +1 -1
  4. package/dist/assets/css/casa.css +1 -1
  5. package/dist/casa.d.ts +210 -0
  6. package/dist/casa.js +107 -1
  7. package/dist/lib/CasaTemplateLoader.d.ts +7 -0
  8. package/dist/lib/JourneyContext.d.ts +15 -27
  9. package/dist/lib/JourneyContext.js +37 -16
  10. package/dist/lib/configuration-ingestor.d.ts +21 -139
  11. package/dist/lib/configuration-ingestor.js +39 -84
  12. package/dist/lib/configure.d.ts +6 -77
  13. package/dist/lib/configure.js +82 -40
  14. package/dist/lib/index.js +5 -1
  15. package/dist/lib/nunjucks.d.ts +1 -6
  16. package/dist/lib/nunjucks.js +1 -3
  17. package/dist/lib/utils.d.ts +21 -10
  18. package/dist/lib/utils.js +54 -8
  19. package/dist/lib/validators/dateObject.d.ts +1 -0
  20. package/dist/lib/validators/email.d.ts +2 -0
  21. package/dist/lib/validators/inArray.d.ts +2 -0
  22. package/dist/lib/validators/nino.d.ts +2 -0
  23. package/dist/lib/validators/postalAddressObject.d.ts +1 -0
  24. package/dist/lib/validators/regex.d.ts +2 -0
  25. package/dist/lib/validators/required.d.ts +4 -0
  26. package/dist/lib/validators/strlen.d.ts +2 -0
  27. package/dist/lib/validators/wordCount.d.ts +2 -0
  28. package/dist/lib/waypoint-url.js +8 -2
  29. package/dist/middleware/body-parser.js +1 -1
  30. package/dist/middleware/data.d.ts +1 -2
  31. package/dist/middleware/data.js +12 -2
  32. package/dist/middleware/post.d.ts +1 -3
  33. package/dist/middleware/post.js +3 -3
  34. package/dist/middleware/pre.d.ts +4 -2
  35. package/dist/middleware/pre.js +24 -5
  36. package/dist/middleware/progress-journey.d.ts +1 -2
  37. package/dist/middleware/progress-journey.js +2 -2
  38. package/dist/middleware/session.d.ts +1 -2
  39. package/dist/middleware/session.js +12 -6
  40. package/dist/middleware/skip-waypoint.d.ts +1 -2
  41. package/dist/middleware/skip-waypoint.js +2 -2
  42. package/dist/middleware/steer-journey.d.ts +1 -2
  43. package/dist/middleware/steer-journey.js +2 -2
  44. package/dist/middleware/validate-fields.d.ts +1 -2
  45. package/dist/middleware/validate-fields.js +2 -1
  46. package/dist/routes/journey.d.ts +1 -2
  47. package/dist/routes/journey.js +8 -8
  48. package/dist/routes/static.d.ts +1 -6
  49. package/dist/routes/static.js +6 -6
  50. package/package.json +32 -30
  51. package/views/casa/components/journey-form/README.md +3 -0
  52. package/views/casa/components/journey-form/template.njk +1 -1
  53. package/views/casa/partials/scripts.njk +1 -1
  54. package/views/casa/partials/styles.njk +2 -2
package/dist/casa.d.ts CHANGED
@@ -1,3 +1,213 @@
1
+ export type PageField = import('./lib/field').PageField;
2
+ export type ContextEventHandler = (journeyContext: JourneyContext, previousContext: JourneyContext) => void;
3
+ export type ContextEvent = {
4
+ /**
5
+ * Waypoint to watch for changes
6
+ */
7
+ waypoint: string;
8
+ /**
9
+ * Field to watch for changes
10
+ */
11
+ field?: string | undefined;
12
+ /**
13
+ * Handler to invoke when change happens
14
+ */
15
+ handler: ContextEventHandler;
16
+ };
17
+ /**
18
+ * Page configuration. A Page is the interactive representation of a waypoint
19
+ */
20
+ export type Page = {
21
+ /**
22
+ * The waypoint with which this page is associated
23
+ */
24
+ waypoint: string;
25
+ /**
26
+ * Template path
27
+ */
28
+ view: string;
29
+ /**
30
+ * Page-specific hooks (optional, default [])
31
+ */
32
+ hooks?: PageHook[] | undefined;
33
+ /**
34
+ * Fields to be managed on this page (optional, default [])
35
+ */
36
+ fields?: import("./lib/field.js").PageField[] | undefined;
37
+ };
38
+ export type I18nOptions = {
39
+ /**
40
+ * Directories to search for locale dictionaries
41
+ */
42
+ dirs: string[];
43
+ /**
44
+ * Supported locales
45
+ */
46
+ locales?: string[] | undefined;
47
+ };
48
+ /**
49
+ * Hook configuration
50
+ */
51
+ export type GlobalHook = {
52
+ /**
53
+ * Hook name in format `<router>.<hook>`
54
+ */
55
+ hook: string;
56
+ /**
57
+ * Middleware function to insert at the hook point
58
+ */
59
+ middleware: Function;
60
+ /**
61
+ * Only run if route path matches this string/regexp
62
+ */
63
+ path?: string | RegExp | undefined;
64
+ };
65
+ /**
66
+ * (extends GlobalHook)
67
+ */
68
+ export type PageHook = {
69
+ /**
70
+ * Hook name (without a scope prefix)
71
+ */
72
+ hook: string;
73
+ /**
74
+ * Middleware function to insert at the hook point
75
+ */
76
+ middleware: Function;
77
+ };
78
+ export type SessionOptions = {
79
+ /**
80
+ * Session name
81
+ */
82
+ name?: string | undefined;
83
+ /**
84
+ * Encryption secret
85
+ */
86
+ secret?: string | undefined;
87
+ /**
88
+ * Session ttl (seconds)
89
+ */
90
+ ttl?: number | undefined;
91
+ /**
92
+ * Whether to use secure session cookies
93
+ */
94
+ secure?: boolean | undefined;
95
+ /**
96
+ * SameSite (true = Strict)
97
+ */
98
+ cookieSameSite?: string | boolean | undefined;
99
+ /**
100
+ * Session store (default MemoryStore)
101
+ */
102
+ store?: object | undefined;
103
+ };
104
+ /**
105
+ * Plugin interface
106
+ */
107
+ export type IPlugin = {
108
+ /**
109
+ * Modify the app config
110
+ */
111
+ configure?: Function | undefined;
112
+ /**
113
+ * Modify post-configuration artifacts
114
+ */
115
+ bootstrap?: Function | undefined;
116
+ };
117
+ export type PluginConfigureFunction = (con: object, : any) => any;
118
+ export type HelmetConfigurator = (config: object) => object;
119
+ export type Mounter = (app: import('express').Express, opts: object, route?: string | undefined) => import('express').Express;
120
+ export type MutableRouter = import('./lib/index').MutableRouter;
121
+ /**
122
+ * Configuration options
123
+ */
124
+ export type ConfigurationOptions = {
125
+ /**
126
+ * Template directories
127
+ */
128
+ views?: string[] | undefined;
129
+ /**
130
+ * Session configuration
131
+ */
132
+ session?: SessionOptions | undefined;
133
+ /**
134
+ * Pages the represent waypoints
135
+ */
136
+ pages?: Page[] | undefined;
137
+ /**
138
+ * Hooks to apply
139
+ */
140
+ hooks?: GlobalHook[] | undefined;
141
+ /**
142
+ * Plugins
143
+ */
144
+ plugins?: IPlugin[] | undefined;
145
+ /**
146
+ * I18n configuration
147
+ */
148
+ i18n?: I18nOptions[] | undefined;
149
+ /**
150
+ * CASA Plan
151
+ */
152
+ plan: Plan;
153
+ /**
154
+ * Handlers for JourneyContext events
155
+ */
156
+ events?: ContextEvent[] | undefined;
157
+ };
158
+ /**
159
+ * Result of a call to configure() function
160
+ */
161
+ export type ConfigureResult = {
162
+ /**
163
+ * Nunjucks environment
164
+ */
165
+ nunjucksEnv: import('nunjucks').Environment;
166
+ /**
167
+ * Router handling all static assets
168
+ */
169
+ staticRouter: MutableRouter;
170
+ /**
171
+ * Router handling ancillary routes
172
+ */
173
+ ancillaryRouter: MutableRouter;
174
+ /**
175
+ * Router handling all waypoint requests
176
+ */
177
+ journeyRouter: MutableRouter;
178
+ /**
179
+ * Middleware mounted before everything
180
+ */
181
+ preMiddleware: import('express').RequestHandler[];
182
+ /**
183
+ * Middleware mounted after everything
184
+ */
185
+ postMiddleware: import('express').RequestHandler[];
186
+ /**
187
+ * CSRF get/set form middleware
188
+ */
189
+ csrfMiddleware: import('express').RequestHandler[];
190
+ /**
191
+ * Session middleware
192
+ */
193
+ sessionMiddleware: import('express').RequestHandler;
194
+ /**
195
+ * Cookie-parsing middleware
196
+ */
197
+ cookieParserMiddleware: import('express').RequestHandler[];
198
+ /**
199
+ * I18n preparation middleware
200
+ */
201
+ i18nMiddleware: import('express').RequestHandler[];
202
+ /**
203
+ * Body parsing middleware
204
+ */
205
+ bodyParserMiddleware: import('express').RequestHandler;
206
+ /**
207
+ * Function used to mount all CASA artifacts onto an ExpressJS app
208
+ */
209
+ mount: Mounter;
210
+ };
1
211
  import configure from "./lib/configure.js";
2
212
  import validators from "./lib/validators/index.js";
3
213
  import field from "./lib/field.js";
package/dist/casa.js CHANGED
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -44,3 +48,105 @@ const end_session_js_1 = __importDefault(require("./lib/end-session.js"));
44
48
  exports.endSession = end_session_js_1.default;
45
49
  const nunjucksFilters = __importStar(require("./lib/nunjucks-filters.js"));
46
50
  exports.nunjucksFilters = nunjucksFilters;
51
+ /* ----------------------------------------------------------------- Typedefs */
52
+ // These exist here so that consumer can import CASA's internal types
53
+ /**
54
+ * @typedef {import('./lib/field').PageField} PageField
55
+ */
56
+ /**
57
+ * @callback ContextEventHandler
58
+ * @param {JourneyContext} journeyContext Context including changes
59
+ * @param {JourneyContext} previousContext Context prior to changes
60
+ * @returns {void}
61
+ */
62
+ /**
63
+ * @typedef {object} ContextEvent
64
+ * @property {string} waypoint Waypoint to watch for changes
65
+ * @property {string} [field] Field to watch for changes
66
+ * @property {ContextEventHandler} handler Handler to invoke when change happens
67
+ */
68
+ /**
69
+ * @typedef {object} Page Page configuration. A Page is the interactive representation of a waypoint
70
+ * @property {string} waypoint The waypoint with which this page is associated
71
+ * @property {string} view Template path
72
+ * @property {PageHook[]} [hooks=[]] Page-specific hooks (optional, default [])
73
+ * @property {PageField[]} [fields=[]] Fields to be managed on this page (optional, default [])
74
+ */
75
+ /**
76
+ * @typedef {object} I18nOptions
77
+ * @property {string[]} dirs Directories to search for locale dictionaries
78
+ * @property {string[]} [locales=['en', 'cy']] Supported locales
79
+ */
80
+ /**
81
+ * @typedef {object} GlobalHook Hook configuration
82
+ * @property {string} hook Hook name in format `<router>.<hook>`
83
+ * @property {Function} middleware Middleware function to insert at the hook point
84
+ * @property {string|RegExp} [path=undefined] Only run if route path matches this string/regexp
85
+ */
86
+ /**
87
+ * @typedef {object} PageHook (extends GlobalHook)
88
+ * @property {string} hook Hook name (without a scope prefix)
89
+ * @property {Function} middleware Middleware function to insert at the hook point
90
+ */
91
+ /**
92
+ * @typedef {object} SessionOptions
93
+ * @property {string} [name=casasession] Session name
94
+ * @property {string} [secret=secret] Encryption secret
95
+ * @property {number} [ttl=3600] Session ttl (seconds)
96
+ * @property {boolean} [secure=false] Whether to use secure session cookies
97
+ * @property {boolean|string} [cookieSameSite=true] SameSite (true = Strict)
98
+ * @property {object} [store] Session store (default MemoryStore)
99
+ */
100
+ /**
101
+ * @typedef {object} IPlugin Plugin interface
102
+ * @property {Function} [configure] Modify the app config
103
+ * @property {Function} [bootstrap] Modify post-configuration artifacts
104
+ */
105
+ /**
106
+ * @callback PluginConfigureFunction
107
+ * @param {object} con Options
108
+ * @param {}
109
+ */
110
+ /**
111
+ * @callback HelmetConfigurator
112
+ * @param {object} config A default Helmet configuration provided by CASA
113
+ * @returns {object} The modified configuration object
114
+ */
115
+ /**
116
+ * @callback Mounter
117
+ * @param {import('express').Express} app Express application
118
+ * @param {object} opts Mounting options
119
+ * @param {string} [opts.route=/] Optional route to attach all middleware/routers too
120
+ * @returns {import('express').Express} The prepared ExpressJS app instance
121
+ */
122
+ /**
123
+ * @typedef {import('./lib/index').MutableRouter} MutableRouter
124
+ */
125
+ /**
126
+ * Configure some middleware for use in creating a new CASA app.
127
+ *
128
+ * @typedef {object} ConfigurationOptions Configuration options
129
+ * @property {string[]} [views=[]] Template directories
130
+ * @property {SessionOptions} [session] Session configuration
131
+ * @property {Page[]} [pages=[]] Pages the represent waypoints
132
+ * @property {GlobalHook[]} [hooks=[]] Hooks to apply
133
+ * @property {IPlugin[]} [plugins=[]] Plugins
134
+ * @property {I18nOptions[]} [i18n] I18n configuration
135
+ * @property {Plan} plan CASA Plan
136
+ * @property {ContextEvent[]} [events=[]] Handlers for JourneyContext events
137
+ */
138
+ /**
139
+ * @typedef {object} ConfigureResult Result of a call to configure() function
140
+ * @property {import('nunjucks').Environment} nunjucksEnv Nunjucks environment
141
+ * @property {MutableRouter} staticRouter Router handling all static assets
142
+ * @property {MutableRouter} ancillaryRouter Router handling ancillary routes
143
+ * @property {MutableRouter} journeyRouter Router handling all waypoint requests
144
+ * @property {import('express').RequestHandler[]} preMiddleware Middleware mounted before everything
145
+ * @property {import('express').RequestHandler[]} postMiddleware Middleware mounted after everything
146
+ * @property {import('express').RequestHandler[]} csrfMiddleware CSRF get/set form middleware
147
+ * @property {import('express').RequestHandler} sessionMiddleware Session middleware
148
+ * @property {import('express').RequestHandler[]} cookieParserMiddleware Cookie-parsing middleware
149
+ * @property {import('express').RequestHandler[]} i18nMiddleware I18n preparation middleware
150
+ * @property {import('express').RequestHandler} bodyParserMiddleware Body parsing middleware
151
+ * @property {Mounter} mount Function used to mount all CASA artifacts onto an ExpressJS app
152
+ */
@@ -11,6 +11,13 @@ export default class CasaTemplateLoader extends FileSystemLoader {
11
11
  * @param {FileSystemLoaderOptions} opts Loader options
12
12
  */
13
13
  constructor(searchPaths: string[], opts: FileSystemLoaderOptions);
14
+ /**
15
+ * Extract the source from the given template file.
16
+ *
17
+ * @param {string} name Source file path
18
+ * @returns {string} Source contents of template
19
+ */
20
+ getSource(name: string): string;
14
21
  /**
15
22
  * Add a modification function to the loader.
16
23
  *
@@ -1,17 +1,11 @@
1
1
  /**
2
- * @typedef {import('./configuration-ingestor').Page} Page
2
+ * @typedef {import('../casa').Page} Page
3
3
  */
4
4
  /**
5
- * @callback ContextEventHandler
6
- * @param {JourneyContext} journeyContext Context including changes
7
- * @param {JourneyContext} previousContext Context prior to changes
8
- * @returns {void}
5
+ * @typedef {import('../casa').ContextEventHandler} ContextEventHandler
9
6
  */
10
7
  /**
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
8
+ * @typedef {import('../casa').ContextEvent} ContextEvent
15
9
  */
16
10
  export function validateObjectKey(key?: string): string;
17
11
  export default class JourneyContext {
@@ -33,7 +27,13 @@ export default class JourneyContext {
33
27
  identity: object;
34
28
  }): JourneyContext;
35
29
  /**
36
- * Construct a new JourneyContext instance frmo another instance.
30
+ * Construct a new ephemeral JourneyContext instance with a unique ID.
31
+ *
32
+ * @returns {JourneyContext} Constructed JourneyContext instance
33
+ */
34
+ static createEphemeralContext(): JourneyContext;
35
+ /**
36
+ * Construct a new JourneyContext instance from another instance.
37
37
  *
38
38
  * @param {JourneyContext} context Context to copy from
39
39
  * @returns {JourneyContext} Constructed JourneyContext instance
@@ -268,8 +268,9 @@ export default class JourneyContext {
268
268
  * @returns {JourneyContext} Chain
269
269
  */
270
270
  addEventListeners(events: ContextEvent[]): JourneyContext;
271
- applyEventListeners({ event }: {
271
+ applyEventListeners({ event, session }: {
272
272
  event: any;
273
+ session: any;
273
274
  }): JourneyContext;
274
275
  /**
275
276
  * Convenience method to determine if this is the default context.
@@ -279,20 +280,7 @@ export default class JourneyContext {
279
280
  isDefault(): boolean;
280
281
  #private;
281
282
  }
282
- export type Page = import('./configuration-ingestor').Page;
283
- export type ContextEventHandler = (journeyContext: JourneyContext, previousContext: JourneyContext) => void;
284
- export type ContextEvent = {
285
- /**
286
- * Waypoint to watch for changes
287
- */
288
- waypoint: string;
289
- /**
290
- * Field to watch for changes
291
- */
292
- field?: string | undefined;
293
- /**
294
- * Handler to invoke when change happens
295
- */
296
- handler: ContextEventHandler;
297
- };
283
+ export type Page = import('../casa').Page;
284
+ export type ContextEventHandler = import('../casa').ContextEventHandler;
285
+ export type ContextEvent = import('../casa').ContextEvent;
298
286
  import ValidationError from "./ValidationError.js";
@@ -39,22 +39,17 @@ const uuid_1 = require("uuid");
39
39
  const lodash_1 = __importDefault(require("lodash"));
40
40
  const ValidationError_js_1 = __importDefault(require("./ValidationError.js"));
41
41
  const logger_js_1 = __importDefault(require("./logger.js"));
42
+ const utils_js_1 = require("./utils.js");
42
43
  const { cloneDeep, isPlainObject, isObject, has, isEqual, } = lodash_1.default; // CommonJS
43
44
  const log = (0, logger_js_1.default)('lib:journey-context');
44
45
  /**
45
- * @typedef {import('./configuration-ingestor').Page} Page
46
+ * @typedef {import('../casa').Page} Page
46
47
  */
47
48
  /**
48
- * @callback ContextEventHandler
49
- * @param {JourneyContext} journeyContext Context including changes
50
- * @param {JourneyContext} previousContext Context prior to changes
51
- * @returns {void}
49
+ * @typedef {import('../casa').ContextEventHandler} ContextEventHandler
52
50
  */
53
51
  /**
54
- * @typedef {object} ContextEvent
55
- * @property {string} waypoint Waypoint to watch for changes
56
- * @property {string} [field] Field to watch for changes
57
- * @property {ContextEventHandler} handler Handler to invoke when change happens
52
+ * @typedef {import('../casa').ContextEvent} ContextEvent
58
53
  */
59
54
  function validateObjectKey(key = '') {
60
55
  const keyLower = String.prototype.toLowerCase.call(key);
@@ -127,7 +122,17 @@ class JourneyContext {
127
122
  * @returns {JourneyContext} Instance.
128
123
  */
129
124
  static fromObject({ data = Object.create(null), validation = Object.create(null), nav = Object.create(null), identity = Object.create(null), } = {}) {
130
- return new JourneyContext(data, validation, nav, identity);
125
+ // As we're constructing a JourneyContext from a plain JS object, we need to
126
+ // ensure any validation errors are instances of ValidationError.
127
+ const deserialisedValidation = Object.create(null);
128
+ for (const [waypoint, errors] of Object.entries(validation)) {
129
+ let dErrors = errors;
130
+ if (Array.isArray(errors)) {
131
+ dErrors = errors.map((e) => (e instanceof ValidationError_js_1.default ? e : new ValidationError_js_1.default(e)));
132
+ }
133
+ deserialisedValidation[(0, utils_js_1.notProto)(waypoint)] = dErrors;
134
+ }
135
+ return new JourneyContext(data, deserialisedValidation, nav, identity);
131
136
  }
132
137
  get data() {
133
138
  return __classPrivateFieldGet(this, _JourneyContext_data, "f");
@@ -357,7 +362,7 @@ class JourneyContext {
357
362
  __classPrivateFieldSet(this, _JourneyContext_eventListenerPreState, this.toObject(), "f");
358
363
  return this;
359
364
  }
360
- applyEventListeners({ event }) {
365
+ applyEventListeners({ event, session }) {
361
366
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
362
367
  if (!__classPrivateFieldGet(this, _JourneyContext_eventListeners, "f").length) {
363
368
  return this;
@@ -386,7 +391,7 @@ class JourneyContext {
386
391
  }
387
392
  if (runHandler) {
388
393
  log.trace(logMessage);
389
- handler({ journeyContext: this, previousContext });
394
+ handler({ journeyContext: this, previousContext, session });
390
395
  }
391
396
  }
392
397
  /* eslint-enable security/detect-object-injection */
@@ -394,7 +399,19 @@ class JourneyContext {
394
399
  }
395
400
  /* ----------------------------------------------- session context handling */
396
401
  /**
397
- * Construct a new JourneyContext instance frmo another instance.
402
+ * Construct a new ephemeral JourneyContext instance with a unique ID.
403
+ *
404
+ * @returns {JourneyContext} Constructed JourneyContext instance
405
+ */
406
+ static createEphemeralContext() {
407
+ return JourneyContext.fromObject({
408
+ identity: {
409
+ id: (0, uuid_1.v4)(),
410
+ },
411
+ });
412
+ }
413
+ /**
414
+ * Construct a new JourneyContext instance from another instance.
398
415
  *
399
416
  * @param {JourneyContext} context Context to copy from
400
417
  * @returns {JourneyContext} Constructed JourneyContext instance
@@ -535,11 +552,11 @@ class JourneyContext {
535
552
  // Apply context events
536
553
  context.applyEventListeners({
537
554
  event: 'waypoint-change',
538
- previousContextObject: session.journeyContextList[context.identity.id],
555
+ session,
539
556
  });
540
557
  context.applyEventListeners({
541
558
  event: 'context-change',
542
- previousContextObject: session.journeyContextList[context.identity.id],
559
+ session,
543
560
  });
544
561
  /* eslint-disable-next-line no-param-reassign */
545
562
  session.journeyContextList[context.identity.id] = context.toObject();
@@ -575,7 +592,11 @@ class JourneyContext {
575
592
  static extractContextFromRequest(req) {
576
593
  JourneyContext.initContextStore(req.session);
577
594
  let contextId;
578
- if (has(req.query, 'contextid')) {
595
+ if (has(req === null || req === void 0 ? void 0 : req.params, 'contextid')) {
596
+ log.trace('Context ID found in req.params.contextid');
597
+ contextId = String(req.params.contextid);
598
+ }
599
+ else if (has(req.query, 'contextid')) {
579
600
  log.trace('Context ID found in req.query.contextid');
580
601
  contextId = String(req.query.contextid);
581
602
  }