@dwp/govuk-casa 9.4.0 → 9.4.2

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 (122) hide show
  1. package/dist/assets/css/casa.css +1 -1
  2. package/dist/assets/css/casa.css.map +1 -1
  3. package/dist/casa.js +17 -7
  4. package/dist/casa.js.map +1 -1
  5. package/dist/core-plugins/edit-snapshot/src/configure.d.ts +6 -1
  6. package/dist/core-plugins/edit-snapshot/src/configure.js +8 -0
  7. package/dist/core-plugins/edit-snapshot/src/configure.js.map +1 -1
  8. package/dist/core-plugins/edit-snapshot/src/post-steer-hook.js.map +1 -1
  9. package/dist/core-plugins/edit-snapshot/src/pre-steer-hook.js.map +1 -1
  10. package/dist/core-plugins/edit-snapshot/src/utils.js +4 -2
  11. package/dist/core-plugins/edit-snapshot/src/utils.js.map +1 -1
  12. package/dist/lib/CasaTemplateLoader.js +0 -1
  13. package/dist/lib/CasaTemplateLoader.js.map +1 -1
  14. package/dist/lib/JourneyContext.d.ts +10 -6
  15. package/dist/lib/JourneyContext.js +11 -9
  16. package/dist/lib/JourneyContext.js.map +1 -1
  17. package/dist/lib/MutableRouter.d.ts +1 -1
  18. package/dist/lib/MutableRouter.js +0 -1
  19. package/dist/lib/MutableRouter.js.map +1 -1
  20. package/dist/lib/Plan.d.ts +3 -3
  21. package/dist/lib/ValidationError.d.ts +1 -1
  22. package/dist/lib/ValidationError.js +1 -1
  23. package/dist/lib/ValidatorFactory.js +0 -3
  24. package/dist/lib/ValidatorFactory.js.map +1 -1
  25. package/dist/lib/configuration-ingestor.d.ts +74 -14
  26. package/dist/lib/configuration-ingestor.js +115 -26
  27. package/dist/lib/configuration-ingestor.js.map +1 -1
  28. package/dist/lib/configure.js.map +1 -1
  29. package/dist/lib/context-id-generators.js +1 -1
  30. package/dist/lib/context-id-generators.js.map +1 -1
  31. package/dist/lib/field.d.ts +8 -8
  32. package/dist/lib/field.js +6 -10
  33. package/dist/lib/field.js.map +1 -1
  34. package/dist/lib/index.js +17 -7
  35. package/dist/lib/index.js.map +1 -1
  36. package/dist/lib/nunjucks-filters.d.ts +5 -1
  37. package/dist/lib/nunjucks-filters.js +13 -1
  38. package/dist/lib/nunjucks-filters.js.map +1 -1
  39. package/dist/lib/utils.js +8 -5
  40. package/dist/lib/utils.js.map +1 -1
  41. package/dist/lib/validators/dateObject.d.ts +2 -1
  42. package/dist/lib/validators/dateObject.js +0 -2
  43. package/dist/lib/validators/dateObject.js.map +1 -1
  44. package/dist/lib/validators/email.js +1 -2
  45. package/dist/lib/validators/email.js.map +1 -1
  46. package/dist/lib/validators/inArray.js +0 -1
  47. package/dist/lib/validators/inArray.js.map +1 -1
  48. package/dist/lib/validators/nino.js +0 -1
  49. package/dist/lib/validators/nino.js.map +1 -1
  50. package/dist/lib/validators/postalAddressObject.js +5 -5
  51. package/dist/lib/validators/postalAddressObject.js.map +1 -1
  52. package/dist/lib/validators/range.js +0 -1
  53. package/dist/lib/validators/range.js.map +1 -1
  54. package/dist/lib/validators/regex.js +0 -1
  55. package/dist/lib/validators/regex.js.map +1 -1
  56. package/dist/lib/validators/required.js +0 -1
  57. package/dist/lib/validators/required.js.map +1 -1
  58. package/dist/lib/validators/strlen.js +0 -1
  59. package/dist/lib/validators/strlen.js.map +1 -1
  60. package/dist/lib/validators/wordCount.js +0 -1
  61. package/dist/lib/validators/wordCount.js.map +1 -1
  62. package/dist/lib/waypoint-url.d.ts +4 -5
  63. package/dist/lib/waypoint-url.js +4 -5
  64. package/dist/lib/waypoint-url.js.map +1 -1
  65. package/dist/middleware/body-parser.d.ts +26 -4
  66. package/dist/middleware/body-parser.js +31 -0
  67. package/dist/middleware/body-parser.js.map +1 -1
  68. package/dist/middleware/csrf.d.ts +15 -1
  69. package/dist/middleware/csrf.js +13 -3
  70. package/dist/middleware/csrf.js.map +1 -1
  71. package/dist/middleware/data.d.ts +21 -4
  72. package/dist/middleware/data.js +33 -4
  73. package/dist/middleware/data.js.map +1 -1
  74. package/dist/middleware/gather-fields.js +1 -1
  75. package/dist/middleware/i18n.d.ts +11 -2
  76. package/dist/middleware/i18n.js +14 -3
  77. package/dist/middleware/i18n.js.map +1 -1
  78. package/dist/middleware/post.d.ts +3 -1
  79. package/dist/middleware/post.js +5 -0
  80. package/dist/middleware/post.js.map +1 -1
  81. package/dist/middleware/session.d.ts +27 -8
  82. package/dist/middleware/session.js +39 -12
  83. package/dist/middleware/session.js.map +1 -1
  84. package/dist/routes/journey.js +2 -3
  85. package/dist/routes/journey.js.map +1 -1
  86. package/package.json +31 -33
  87. package/src/core-plugins/edit-snapshot/src/configure.js +19 -7
  88. package/src/core-plugins/edit-snapshot/src/post-steer-hook.js +3 -1
  89. package/src/core-plugins/edit-snapshot/src/pre-steer-hook.js +14 -4
  90. package/src/core-plugins/edit-snapshot/src/utils.js +19 -7
  91. package/src/lib/CasaTemplateLoader.js +0 -1
  92. package/src/lib/JourneyContext.js +16 -11
  93. package/src/lib/MutableRouter.js +0 -1
  94. package/src/lib/ValidationError.js +1 -1
  95. package/src/lib/ValidatorFactory.js +0 -3
  96. package/src/lib/configuration-ingestor.js +111 -19
  97. package/src/lib/configure.js +2 -2
  98. package/src/lib/context-id-generators.js +1 -1
  99. package/src/lib/field.js +7 -10
  100. package/src/lib/nunjucks-filters.js +15 -1
  101. package/src/lib/utils.js +9 -5
  102. package/src/lib/validators/dateObject.js +1 -2
  103. package/src/lib/validators/email.js +1 -2
  104. package/src/lib/validators/inArray.js +0 -1
  105. package/src/lib/validators/nino.js +0 -1
  106. package/src/lib/validators/postalAddressObject.js +5 -5
  107. package/src/lib/validators/range.js +0 -2
  108. package/src/lib/validators/regex.js +0 -1
  109. package/src/lib/validators/required.js +0 -1
  110. package/src/lib/validators/strlen.js +0 -1
  111. package/src/lib/validators/wordCount.js +0 -1
  112. package/src/lib/waypoint-url.js +4 -5
  113. package/src/middleware/body-parser.js +34 -0
  114. package/src/middleware/csrf.js +13 -3
  115. package/src/middleware/data.js +37 -5
  116. package/src/middleware/gather-fields.js +1 -1
  117. package/src/middleware/i18n.js +15 -3
  118. package/src/middleware/post.js +6 -0
  119. package/src/middleware/session.js +24 -5
  120. package/src/routes/journey.js +6 -4
  121. package/src/core-plugins/edit-snapshot/readme.md +0 -19
  122. package/src/core-plugins/readme.md +0 -3
@@ -1,9 +1,34 @@
1
1
  import { urlencoded as expressBodyParser } from "express";
2
2
 
3
+ /**
4
+ * @typedef {import("express").RequestHandler} RequestHandler
5
+ * @access private
6
+ */
7
+
8
+ /**
9
+ * @typedef {import("express").Request} Request
10
+ * @access private
11
+ */
12
+
13
+ /**
14
+ * @typedef {import("express").Response} Response
15
+ * @access private
16
+ */
17
+
3
18
  const rProto = /__proto__/i;
4
19
  const rPrototype = /prototype[='"[\]]/i;
5
20
  const rConstructor = /constructor[='"[\]]/i;
6
21
 
22
+ /**
23
+ * Verify request body.
24
+ *
25
+ * @param {Request} req HTTP request
26
+ * @param {Response} res HTTP response
27
+ * @param {Buffer} buf Buffer
28
+ * @param {string} encoding Character encoding
29
+ * @returns {void}
30
+ * @throws {Error} For invalid bodies
31
+ */
7
32
  export function verifyBody(req, res, buf, encoding) {
8
33
  const body = decodeURI(buf.toString(encoding)).replace(
9
34
  /[\s\u200B-\u200D\uFEFF]/g,
@@ -20,6 +45,15 @@ export function verifyBody(req, res, buf, encoding) {
20
45
  }
21
46
  }
22
47
 
48
+ /**
49
+ * Body parsing middleware.
50
+ *
51
+ * @param {object} opts Options
52
+ * @param {number} opts.formMaxParams Max number of parameters that should be
53
+ * parsed
54
+ * @param {number} opts.formMaxBytes Max bytes that should be read
55
+ * @returns {RequestHandler[]} Middleware functions
56
+ */
23
57
  export default function bodyParserMiddleware({ formMaxParams, formMaxBytes }) {
24
58
  return [
25
59
  expressBodyParser({
@@ -1,9 +1,19 @@
1
1
  import { csrfSync } from "csrf-sync";
2
2
 
3
- // 2 middleware: one to generate the csrf token and check its validity (POST
4
- // only), and one to provide that token to templates via the `casa.csrfToken`
5
- // variable.
3
+ /**
4
+ * @typedef {import("express").RequestHandler} RequestHandler
5
+ * @access private
6
+ */
6
7
 
8
+ /**
9
+ * Data middleware.
10
+ *
11
+ * 2 middleware: one to generate the csrf token and check its validity (POST
12
+ * only), and one to provide that token to templates via the `casa.csrfToken`
13
+ * variable.
14
+ *
15
+ * @returns {RequestHandler[]} Middleware functions
16
+ */
7
17
  export default function csrfMiddleware() {
8
18
  const { csrfSynchronisedProtection } = csrfSync({
9
19
  getTokenFromRequest: (req) => req.body._csrf,
@@ -1,10 +1,27 @@
1
- // Decorates the request with some contextual data about the user's journey
2
- // through the application. This is used by downstream middleware and templates.
3
-
4
1
  import JourneyContext from "../lib/JourneyContext.js";
5
2
  import { validateUrlPath } from "../lib/utils.js";
6
3
  import waypointUrl from "../lib/waypoint-url.js";
7
4
 
5
+ /**
6
+ * @typedef {import("express").RequestHandler} RequestHandler
7
+ * @access private
8
+ */
9
+
10
+ /**
11
+ * @typedef {import("../casa.js").Plan} Plan
12
+ * @access private
13
+ */
14
+
15
+ /**
16
+ * @typedef {import("../casa.js").ContextEventHandler} ContextEventHandler
17
+ * @access private
18
+ */
19
+
20
+ /**
21
+ * @typedef {import("../casa.js").ContextIdGenerator} ContextIdGenerator
22
+ * @access private
23
+ */
24
+
8
25
  const editOrigin = (req) => {
9
26
  if (Object.hasOwn(req.query, "editorigin")) {
10
27
  return waypointUrl({ waypoint: req.query.editorigin });
@@ -15,6 +32,19 @@ const editOrigin = (req) => {
15
32
  return "";
16
33
  };
17
34
 
35
+ /**
36
+ * Data middleware.
37
+ *
38
+ * Decorates the request with some contextual data about the user's journey
39
+ * through the application. This is used by downstream middleware and
40
+ * templates.
41
+ *
42
+ * @param {object} opts Options
43
+ * @param {Plan} opts.plan CASA Plan
44
+ * @param {ContextEventHandler[]} opts.events Event handlers
45
+ * @param {ContextIdGenerator} opts.contextIdGenerator Content ID generator
46
+ * @returns {RequestHandler[]} Middleware functions
47
+ */
18
48
  export default function dataMiddleware({ plan, events, contextIdGenerator }) {
19
49
  return [
20
50
  (req, res, next) => {
@@ -36,8 +66,10 @@ export default function dataMiddleware({ plan, events, contextIdGenerator }) {
36
66
 
37
67
  // Edit mode
38
68
  editMode:
39
- (Object.hasOwn(req.query, "edit") && Object.hasOwn(req.query, "editorigin")) ||
40
- (Object.hasOwn(req.body, "edit") && Object.hasOwn(req.body, "editorigin")),
69
+ (Object.hasOwn(req.query, "edit") &&
70
+ Object.hasOwn(req.query, "editorigin")) ||
71
+ (Object.hasOwn(req.body, "edit") &&
72
+ Object.hasOwn(req.body, "editorigin")),
41
73
  editOrigin: editOrigin(req),
42
74
  };
43
75
 
@@ -20,7 +20,7 @@ import { REQUEST_PHASE_GATHER } from "../lib/constants.js";
20
20
  *
21
21
  * @param {object} obj Options
22
22
  * @param {string} obj.waypoint Waypoint
23
- * @param {PageField[]} [obj.fields=[]] Fields. Default is `[]`
23
+ * @param {PageField[]} [obj.fields] Fields. Default is `[]`
24
24
  * @returns {Array} Array of middleware
25
25
  */
26
26
  export default ({ waypoint, fields = [] }) => [
@@ -3,9 +3,14 @@ import { LanguageDetector, handle } from "i18next-http-middleware";
3
3
  import { resolve, basename } from "node:path";
4
4
  import { existsSync, readFileSync, readdirSync } from "node:fs";
5
5
  import deepmerge from "deepmerge";
6
- import yaml from "js-yaml";
6
+ import { load as jsYamlLoad } from "js-yaml";
7
7
  import logger from "../lib/logger.js";
8
8
 
9
+ /**
10
+ * @typedef {import("express").RequestHandler} RequestHandler
11
+ * @access private
12
+ */
13
+
9
14
  const log = logger("middleware:i18n");
10
15
 
11
16
  const loadJson = (file) => {
@@ -17,7 +22,7 @@ const loadJson = (file) => {
17
22
  };
18
23
 
19
24
  /* eslint-disable-next-line security/detect-non-literal-fs-filename */
20
- const loadYaml = (file) => yaml.load(readFileSync(file, "utf8"));
25
+ const loadYaml = (file) => jsYamlLoad(readFileSync(file, "utf8"));
21
26
 
22
27
  const extract = (file) => {
23
28
  const ext = /.yaml$/i.test(file) ? ".yaml" : ".json";
@@ -63,6 +68,14 @@ const loadResources = (languages, directories) => {
63
68
  return store;
64
69
  };
65
70
 
71
+ /**
72
+ * Internationalisation middleware.
73
+ *
74
+ * @param {object} opts Options
75
+ * @param {string[]} [opts.languages] Language codes
76
+ * @param {string[]} [opts.directories] Source translations directories
77
+ * @returns {RequestHandler[]} Middleware functions
78
+ */
66
79
  export default function i18nMiddleware({
67
80
  languages = ["en", "cy"],
68
81
  directories = [],
@@ -95,7 +108,6 @@ export default function i18nMiddleware({
95
108
  return [
96
109
  (req, res, next) => {
97
110
  if (!req.session.language) {
98
- /* eslint-disable-next-line prefer-destructuring */
99
111
  req.session.language = languages[0];
100
112
  }
101
113
  if (req?.query.lang && languages.includes(req.query.lang)) {
@@ -1,8 +1,14 @@
1
1
  // 2 middleware: one as a fallback 404 handler, one to handle thrown errors
2
2
  import logger from "../lib/logger.js";
3
3
 
4
+ /**
5
+ * @typedef {import("express").RequestHandler} RequestHandler
6
+ * @access private
7
+ */
8
+
4
9
  const log = logger("middleware:post");
5
10
 
11
+ /** @returns {RequestHandler[]} Middleware functions */
6
12
  export default function postMiddleware() {
7
13
  return [
8
14
  (req, res) => {
@@ -5,6 +5,11 @@ import expressSession, { MemoryStore } from "express-session";
5
5
  import logger from "../lib/logger.js";
6
6
  import { validateUrlPath } from "../lib/utils.js";
7
7
 
8
+ /**
9
+ * @typedef {import("express").RequestHandler} RequestHandler
10
+ * @access private
11
+ */
12
+
8
13
  const log = logger("middleware:session");
9
14
 
10
15
  const sessionExpiryMiddleware =
@@ -51,7 +56,7 @@ const sessionExpiryMiddleware =
51
56
  referrer: req.originalUrl,
52
57
  lang: language,
53
58
  });
54
- /* eslint-disable-next-line prefer-template */
59
+
55
60
  res.redirect(
56
61
  302,
57
62
  validateUrlPath(`${req.baseUrl}/session-timeout`) +
@@ -66,10 +71,24 @@ const sessionExpiryMiddleware =
66
71
  }
67
72
  };
68
73
 
69
- // 3 middleware:
70
- // - set the session cookie
71
- // - parse request cookies
72
- // - handle expiry of server-side session
74
+ /**
75
+ * Produces three middleware functions:
76
+ *
77
+ * - Set the session cookie
78
+ * - Parse request cookies
79
+ * - Handle expiry of server-side session
80
+ *
81
+ * @param {object} opts Options
82
+ * @param {RequestHandler} opts.cookieParserMiddleware Cookie parsing middleware
83
+ * @param {string} opts.secret Session encryption secret
84
+ * @param {string} opts.name Session cookie name
85
+ * @param {boolean} opts.secure Secure cookies only
86
+ * @param {number} opts.ttl Session data time-to-live
87
+ * @param {boolean | string} [opts.cookieSameSite] Cooke SameSite setting
88
+ * @param {string} [opts.cookiePath] Cookie path
89
+ * @param {object} [opts.store] Storage instance
90
+ * @returns {RequestHandler[]} Middleware functions
91
+ */
73
92
  export default function sessionMiddleware({
74
93
  cookieParserMiddleware,
75
94
  secret,
@@ -1,4 +1,3 @@
1
- /* eslint-disable object-curly-newline,max-len */
2
1
  import MutableRouter from "../lib/MutableRouter.js";
3
2
  import skipWaypointMiddlewareFactory from "../middleware/skip-waypoint.js";
4
3
  import steerJourneyMiddlewareFactory from "../middleware/steer-journey.js";
@@ -44,7 +43,10 @@ const renderMiddlewareFactory = (view, contextFactory) => [
44
43
  // Common template variables for both GET and POST requests
45
44
  inEditMode: req.casa.editMode,
46
45
  editOriginUrl: req.casa.editOrigin,
47
- editCancelUrl: generateEditCancelUrl(req.casa.editOrigin, req.casa.waypoint),
46
+ editCancelUrl: generateEditCancelUrl(
47
+ req.casa.editOrigin,
48
+ req.casa.waypoint,
49
+ ),
48
50
  activeContextId: req.casa.journeyContext.identity.id,
49
51
  ...contextFactory(req),
50
52
  },
@@ -73,8 +75,8 @@ const generateGovukErrors = (errors, req) =>
73
75
  }));
74
76
 
75
77
  const generateEditCancelUrl = (editOrigin, waypoint) => {
76
- const url = new URL(editOrigin, 'https://placeholder.test/');
77
- url.searchParams.set('editcancel', waypoint);
78
+ const url = new URL(editOrigin, "https://placeholder.test/");
79
+ url.searchParams.set("editcancel", waypoint);
78
80
  return `${url.pathname}${url.search}`;
79
81
  };
80
82
 
@@ -1,19 +0,0 @@
1
- # Edit snapshots plugin
2
-
3
- Include the `editSnapshot` core plugin to use this feature:
4
-
5
- ```js
6
- import { configure, corePlugins } from "@dwp/govuk/casa";
7
-
8
- configure({
9
- plugins: [
10
- corePlugins.editSnapshot(),
11
- ],
12
- });
13
- ```
14
-
15
- This feature will alter the default behaviour of the "cancel" links during an editing workflow.
16
-
17
- When the user clicks "cancel", all changes made during the current editing session will be dropped, and the state of the current journey context will be restored to a point just before editing started.
18
-
19
- The same will also happen if the user navigates away from the editing workflow, i.e. the `edit` URL paramater is removed.
@@ -1,3 +0,0 @@
1
- # Internal plugins
2
-
3
- These are isolated bits of functionality that may be candidates for exatracting into their own external plugins at some point.