@dwp/govuk-casa 8.11.0 → 8.12.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.
- package/README.md +1 -1
- package/dist/assets/css/casa-ie8.css +1 -1
- package/dist/assets/css/casa.css +1 -1
- package/dist/casa.d.ts +25 -1
- package/dist/casa.js +23 -1
- package/dist/casa.js.map +1 -1
- package/dist/lib/CasaTemplateLoader.js +1 -1
- package/dist/lib/CasaTemplateLoader.js.map +1 -1
- package/dist/lib/JourneyContext.d.ts +32 -6
- package/dist/lib/JourneyContext.js +70 -11
- package/dist/lib/JourneyContext.js.map +1 -1
- package/dist/lib/MutableRouter.js +1 -1
- package/dist/lib/MutableRouter.js.map +1 -1
- package/dist/lib/Plan.js +1 -1
- package/dist/lib/Plan.js.map +1 -1
- package/dist/lib/configuration-ingestor.d.ts +1 -0
- package/dist/lib/configuration-ingestor.js +37 -1
- package/dist/lib/configuration-ingestor.js.map +1 -1
- package/dist/lib/configure.js +2 -1
- package/dist/lib/configure.js.map +1 -1
- package/dist/lib/context-id-generators.d.ts +27 -0
- package/dist/lib/context-id-generators.js +54 -0
- package/dist/lib/context-id-generators.js.map +1 -0
- package/dist/lib/validators/range.js +2 -1
- package/dist/lib/validators/range.js.map +1 -1
- package/dist/middleware/data.d.ts +2 -1
- package/dist/middleware/data.js +7 -1
- package/dist/middleware/data.js.map +1 -1
- package/dist/middleware/gather-fields.js +1 -1
- package/dist/middleware/gather-fields.js.map +1 -1
- package/dist/middleware/sanitise-fields.js +1 -1
- package/dist/middleware/sanitise-fields.js.map +1 -1
- package/dist/mjs/esm-wrapper.js +1 -0
- package/package.json +21 -22
- package/src/casa.js +26 -0
- package/src/lib/JourneyContext.js +79 -11
- package/src/lib/configuration-ingestor.js +16 -0
- package/src/lib/configure.js +2 -0
- package/src/lib/context-id-generators.js +71 -0
- package/src/lib/validators/range.js +2 -1
- package/src/middleware/data.js +8 -0
- package/src/middleware/gather-fields.js +4 -1
- package/src/middleware/sanitise-fields.js +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* eslint-disable import/no-cycle */
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../casa.js').ContextIdGenerator} ContextIdGenerator
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of a UUID generator.
|
|
10
|
+
*
|
|
11
|
+
* @returns {ContextIdGenerator} Generator function
|
|
12
|
+
*/
|
|
13
|
+
const uuid = () => () => randomUUID();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Returns a generator that returns the next incremental integer in a sequence.
|
|
17
|
+
*
|
|
18
|
+
* This generator does not take into account the removal of any contexts from
|
|
19
|
+
* session that were previously assigned a sequential ID. This means that IDs
|
|
20
|
+
* will be re-used when they are freed up.
|
|
21
|
+
*
|
|
22
|
+
* @returns {ContextIdGenerator} Generator function
|
|
23
|
+
*/
|
|
24
|
+
const sequentialInteger = () => ({ reservedIds }) => {
|
|
25
|
+
const contextIds = Array.from(reservedIds).sort();
|
|
26
|
+
|
|
27
|
+
if (!contextIds.length) {
|
|
28
|
+
return '1';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Find the first numeric ID that we can increment
|
|
32
|
+
let lastInSequence;
|
|
33
|
+
do {
|
|
34
|
+
lastInSequence = Number.parseInt(contextIds.pop(), 10);
|
|
35
|
+
} while (contextIds.length && Number.isNaN(lastInSequence));
|
|
36
|
+
|
|
37
|
+
return String(!Number.isNaN(lastInSequence) ? lastInSequence + 1 : 1);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const shortGuid = ({
|
|
41
|
+
length = 5,
|
|
42
|
+
prefix = '',
|
|
43
|
+
pool = 'abcdefhkmnprtwxy346789',
|
|
44
|
+
} = {}) => ({ reservedIds }) => {
|
|
45
|
+
// Ambiguous characters excluded
|
|
46
|
+
const poolSize = pool.length;
|
|
47
|
+
|
|
48
|
+
const maxAttempts = 10;
|
|
49
|
+
let attempts = maxAttempts;
|
|
50
|
+
let id;
|
|
51
|
+
|
|
52
|
+
do {
|
|
53
|
+
id = Array(length).fill(0).map(() => pool.charAt(Math.floor(Math.random() * poolSize))).join('');
|
|
54
|
+
attempts--;
|
|
55
|
+
} while (attempts > 0 && reservedIds.includes(id));
|
|
56
|
+
|
|
57
|
+
if (attempts === 0) {
|
|
58
|
+
throw new Error(`Failed to generate GUID after ${maxAttempts} iterations`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return `${prefix}${id}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @namespace ContextIdGenerators
|
|
66
|
+
*/
|
|
67
|
+
export {
|
|
68
|
+
uuid,
|
|
69
|
+
sequentialInteger,
|
|
70
|
+
shortGuid,
|
|
71
|
+
};
|
|
@@ -62,7 +62,8 @@ export default class Range extends ValidatorFactory {
|
|
|
62
62
|
// treat an empty string as undefined
|
|
63
63
|
// when user submits empty form, it stores an empty string
|
|
64
64
|
if (value !== '' && value !== undefined) {
|
|
65
|
-
// add to custom validator docs to ensure not to return a falsy value as
|
|
65
|
+
// add to custom validator docs to ensure not to return a falsy value as
|
|
66
|
+
// it doesn't show on screen
|
|
66
67
|
return coerceInputToInteger(value)?.toString();
|
|
67
68
|
}
|
|
68
69
|
return undefined;
|
package/src/middleware/data.js
CHANGED
|
@@ -21,6 +21,7 @@ const editOrigin = (req) => {
|
|
|
21
21
|
export default function dataMiddleware({
|
|
22
22
|
plan,
|
|
23
23
|
events,
|
|
24
|
+
contextIdGenerator,
|
|
24
25
|
}) {
|
|
25
26
|
return [
|
|
26
27
|
(req, res, next) => {
|
|
@@ -45,6 +46,13 @@ export default function dataMiddleware({
|
|
|
45
46
|
// Grab chosen language from session
|
|
46
47
|
req.casa.journeyContext.nav.language = req.session.language;
|
|
47
48
|
|
|
49
|
+
// Context ID generator
|
|
50
|
+
Object.defineProperty(req, JourneyContext.ID_GENERATOR_REQ_KEY, {
|
|
51
|
+
value: contextIdGenerator,
|
|
52
|
+
enumerable: false,
|
|
53
|
+
writable: false,
|
|
54
|
+
});
|
|
55
|
+
|
|
48
56
|
/* ------------------------------------------------- Template variables */
|
|
49
57
|
|
|
50
58
|
// Capture mount URL that will be used in generating all browser URLs
|
|
@@ -29,7 +29,10 @@ export default ({
|
|
|
29
29
|
(req, res, next) => {
|
|
30
30
|
// Store a copy of the journey context before modifying it. This is useful
|
|
31
31
|
// for any comparison work that may be done in subsequent middleware.
|
|
32
|
-
req.casa.archivedJourneyContext = JourneyContext.fromContext(
|
|
32
|
+
req.casa.archivedJourneyContext = JourneyContext.fromContext(
|
|
33
|
+
req.casa.journeyContext,
|
|
34
|
+
req,
|
|
35
|
+
);
|
|
33
36
|
|
|
34
37
|
// Ignore data for any non-persistent fields
|
|
35
38
|
// ESLint disabled as `fields`, `i` and `name` are dev-controlled
|
|
@@ -31,7 +31,7 @@ export default ({
|
|
|
31
31
|
}
|
|
32
32
|
/* eslint-enable security/detect-object-injection */
|
|
33
33
|
|
|
34
|
-
const journeyContext = JourneyContext.fromContext(req.casa.journeyContext);
|
|
34
|
+
const journeyContext = JourneyContext.fromContext(req.casa.journeyContext, req);
|
|
35
35
|
journeyContext.setDataForPage(waypoint, prunedBody);
|
|
36
36
|
|
|
37
37
|
// Second, prune any fields that do not pass the validation conditional,
|