@dwp/govuk-casa 7.0.7 → 7.0.8
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/CHANGELOG.md +2 -0
- package/dist/assets/css/casa-ie8.css +1 -0
- package/dist/assets/css/casa.css +1 -0
- package/dist/casa/css/casa-ie8.css +1 -1
- package/dist/casa/css/casa.css +1 -1
- package/dist/casa.d.ts +11 -0
- package/dist/casa.js +46 -0
- package/dist/lib/CasaTemplateLoader.d.ts +29 -0
- package/dist/lib/CasaTemplateLoader.js +74 -0
- package/dist/lib/JourneyContext.d.ts +297 -0
- package/dist/lib/JourneyContext.js +581 -0
- package/dist/lib/MutableRouter.d.ts +155 -0
- package/dist/lib/MutableRouter.js +277 -0
- package/dist/lib/Plan.d.ts +154 -0
- package/dist/lib/Plan.js +442 -0
- package/dist/lib/ValidationError.d.ts +74 -0
- package/dist/lib/ValidationError.js +159 -0
- package/dist/lib/ValidatorFactory.d.ts +83 -0
- package/dist/lib/ValidatorFactory.js +106 -0
- package/dist/lib/configuration-ingestor.d.ts +262 -0
- package/dist/lib/configuration-ingestor.js +490 -0
- package/dist/lib/configure.d.ts +90 -0
- package/dist/lib/configure.js +192 -0
- package/dist/lib/dirname.cjs +1 -0
- package/dist/lib/dirname.d.cts +2 -0
- package/dist/lib/end-session.d.ts +13 -0
- package/dist/lib/end-session.js +43 -0
- package/dist/lib/field.d.ts +77 -0
- package/dist/lib/field.js +255 -0
- package/dist/lib/index.d.ts +14 -0
- package/dist/lib/index.js +54 -0
- package/dist/lib/logger.d.ts +9 -0
- package/dist/lib/logger.js +18 -0
- package/dist/lib/nunjucks-filters.d.ts +26 -0
- package/dist/lib/nunjucks-filters.js +90 -0
- package/dist/lib/nunjucks.d.ts +23 -0
- package/dist/lib/nunjucks.js +49 -0
- package/dist/lib/utils.d.ts +48 -0
- package/dist/lib/utils.js +111 -0
- package/dist/lib/validators/dateObject.d.ts +4 -0
- package/dist/lib/validators/dateObject.js +135 -0
- package/dist/lib/validators/email.d.ts +4 -0
- package/dist/lib/validators/email.js +46 -0
- package/dist/lib/validators/inArray.d.ts +4 -0
- package/dist/lib/validators/inArray.js +60 -0
- package/dist/lib/validators/index.d.ts +21 -0
- package/dist/lib/validators/index.js +47 -0
- package/dist/lib/validators/nino.d.ts +4 -0
- package/dist/lib/validators/nino.js +46 -0
- package/dist/lib/validators/postalAddressObject.d.ts +4 -0
- package/dist/lib/validators/postalAddressObject.js +123 -0
- package/dist/lib/validators/regex.d.ts +4 -0
- package/dist/lib/validators/regex.js +40 -0
- package/dist/lib/validators/required.d.ts +4 -0
- package/dist/lib/validators/required.js +56 -0
- package/dist/lib/validators/strlen.d.ts +4 -0
- package/dist/lib/validators/strlen.js +51 -0
- package/dist/lib/validators/wordCount.d.ts +5 -0
- package/dist/lib/validators/wordCount.js +54 -0
- package/dist/lib/waypoint-url.d.ts +23 -0
- package/dist/lib/waypoint-url.js +52 -0
- package/dist/middleware/body-parser.d.ts +1 -0
- package/dist/middleware/body-parser.js +24 -0
- package/dist/middleware/csrf.d.ts +1 -0
- package/dist/middleware/csrf.js +31 -0
- package/dist/middleware/data.d.ts +5 -0
- package/dist/middleware/data.js +53 -0
- package/dist/middleware/dirname.cjs +1 -0
- package/dist/middleware/dirname.d.cts +2 -0
- package/dist/middleware/gather-fields.d.ts +6 -0
- package/dist/middleware/gather-fields.js +48 -0
- package/dist/middleware/i18n.d.ts +4 -0
- package/dist/middleware/i18n.js +88 -0
- package/dist/middleware/post.d.ts +3 -0
- package/dist/middleware/post.js +57 -0
- package/dist/middleware/pre.d.ts +3 -0
- package/dist/middleware/pre.js +51 -0
- package/dist/middleware/progress-journey.d.ts +6 -0
- package/dist/middleware/progress-journey.js +80 -0
- package/dist/middleware/sanitise-fields.d.ts +5 -0
- package/dist/middleware/sanitise-fields.js +53 -0
- package/dist/middleware/session.d.ts +11 -0
- package/dist/middleware/session.js +121 -0
- package/dist/middleware/skip-waypoint.d.ts +5 -0
- package/dist/middleware/skip-waypoint.js +43 -0
- package/dist/middleware/steer-journey.d.ts +7 -0
- package/dist/middleware/steer-journey.js +62 -0
- package/dist/middleware/validate-fields.d.ts +7 -0
- package/dist/middleware/validate-fields.js +67 -0
- package/dist/mjs/esm-wrapper.js +11 -0
- package/dist/mjs/package.json +3 -0
- package/dist/package.json +3 -0
- package/dist/routes/ancillary.d.ts +11 -0
- package/dist/routes/ancillary.js +27 -0
- package/dist/routes/dirname.cjs +1 -0
- package/dist/routes/dirname.d.cts +2 -0
- package/dist/routes/journey.d.ts +8 -0
- package/dist/routes/journey.js +127 -0
- package/dist/routes/static.d.ts +26 -0
- package/dist/routes/static.js +68 -0
- package/package.json +19 -19
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const dateObject_js_1 = __importDefault(require("./dateObject.js"));
|
|
7
|
+
const email_js_1 = __importDefault(require("./email.js"));
|
|
8
|
+
const inArray_js_1 = __importDefault(require("./inArray.js"));
|
|
9
|
+
const nino_js_1 = __importDefault(require("./nino.js"));
|
|
10
|
+
const postalAddressObject_js_1 = __importDefault(require("./postalAddressObject.js"));
|
|
11
|
+
const regex_js_1 = __importDefault(require("./regex.js"));
|
|
12
|
+
const required_js_1 = __importDefault(require("./required.js"));
|
|
13
|
+
const strlen_js_1 = __importDefault(require("./strlen.js"));
|
|
14
|
+
const wordCount_js_1 = __importDefault(require("./wordCount.js"));
|
|
15
|
+
exports.default = {
|
|
16
|
+
dateObject: dateObject_js_1.default,
|
|
17
|
+
email: email_js_1.default,
|
|
18
|
+
inArray: inArray_js_1.default,
|
|
19
|
+
nino: nino_js_1.default,
|
|
20
|
+
postalAddressObject: postalAddressObject_js_1.default,
|
|
21
|
+
regex: regex_js_1.default,
|
|
22
|
+
required: required_js_1.default,
|
|
23
|
+
strlen: strlen_js_1.default,
|
|
24
|
+
wordCount: wordCount_js_1.default,
|
|
25
|
+
};
|
|
26
|
+
// const dateObject = require('./dateObject.js');
|
|
27
|
+
// const email = require('./email.js');
|
|
28
|
+
// const inArray = require('./inArray.js');
|
|
29
|
+
// const nino = require('./nino.js');
|
|
30
|
+
// const optional = require('./optional.js');
|
|
31
|
+
// const postalAddressObject = require('./postalAddressObject.js');
|
|
32
|
+
// const regex = require('./regex.js');
|
|
33
|
+
// const required = require('./required.js');
|
|
34
|
+
// const strlen = require('./strlen.js');
|
|
35
|
+
// const wordCount = require('./wordCount.js');
|
|
36
|
+
// module.exports = {
|
|
37
|
+
// dateObject,
|
|
38
|
+
// email,
|
|
39
|
+
// inArray,
|
|
40
|
+
// nino,
|
|
41
|
+
// optional,
|
|
42
|
+
// postalAddressObject,
|
|
43
|
+
// regex,
|
|
44
|
+
// required,
|
|
45
|
+
// strlen,
|
|
46
|
+
// wordCount,
|
|
47
|
+
// };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
/**
|
|
8
|
+
* UK National Insurance number.
|
|
9
|
+
*
|
|
10
|
+
* Config options:
|
|
11
|
+
* string|object errorMsg = Error message to use on validation failure
|
|
12
|
+
* boolean allowWhitespace = will permit input values that contain spaces.
|
|
13
|
+
*
|
|
14
|
+
* Ref:
|
|
15
|
+
* https://en.wikipedia.org/wiki/National_Insurance_number#Format
|
|
16
|
+
* https://design-system.service.gov.uk/patterns/national-insurance-numbers/
|
|
17
|
+
*/
|
|
18
|
+
const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
|
|
19
|
+
const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
|
|
20
|
+
const utils_js_1 = require("../utils.js");
|
|
21
|
+
class Nino extends ValidatorFactory_js_1.default {
|
|
22
|
+
constructor() {
|
|
23
|
+
super(...arguments);
|
|
24
|
+
this.name = 'nino';
|
|
25
|
+
}
|
|
26
|
+
validate(value, dataContext = {}) {
|
|
27
|
+
const { allowWhitespace, errorMsg = {
|
|
28
|
+
inline: 'validation:rule.nino.inline',
|
|
29
|
+
summary: 'validation:rule.nino.summary',
|
|
30
|
+
}, } = this.config;
|
|
31
|
+
if (typeof allowWhitespace !== 'undefined' && typeof allowWhitespace !== 'boolean') {
|
|
32
|
+
throw new TypeError(`NINO validation rule option "allowWhitespace" must been a boolean. received ${typeof allowWhitespace}`);
|
|
33
|
+
}
|
|
34
|
+
const valid = typeof value === 'string'
|
|
35
|
+
&& value.replace((typeof allowWhitespace !== 'undefined' && allowWhitespace) ? /\u0020/g : '', '')
|
|
36
|
+
.match(/^(?!BG|GB|NK|KN|TN|NT|ZZ)[ABCEGHJ-PRSTW-Z][ABCEGHJ-NPRSTW-Z]\d{6}[A-D]$/i);
|
|
37
|
+
return valid ? [] : [ValidationError_js_1.default.make({ errorMsg, dataContext })];
|
|
38
|
+
}
|
|
39
|
+
sanitise(value) {
|
|
40
|
+
if (value !== undefined) {
|
|
41
|
+
return (0, utils_js_1.stringifyInput)(value);
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = Nino;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
/**
|
|
8
|
+
* Works hand in hand with the core CASA `postalAddressObject` form macro.
|
|
9
|
+
*
|
|
10
|
+
* The errors sent back from this validator are specific to each subfield. For
|
|
11
|
+
* example, if the field name being tested is "address", any errors related to
|
|
12
|
+
* the "postcode" component would be associated with "address[postcode]".
|
|
13
|
+
*
|
|
14
|
+
* Config options:
|
|
15
|
+
* string|object errorMsg = General error message for the entire address block
|
|
16
|
+
* string|object errorMsgAddress1 = Error message for address1 part
|
|
17
|
+
* string|object errorMsgAddress2 = Error message for address2 part
|
|
18
|
+
* string|object errorMsgAddress3 = Error message for address3 part
|
|
19
|
+
* string|object errorMsgAddress4 = Error message for address4 part
|
|
20
|
+
* string|object errorMsgPostcode = Error message for postcode part
|
|
21
|
+
* int strlenmax = Max. String length for each of the inputs appress[1-4]
|
|
22
|
+
* array requiredFields = Field parts required (others become optional)
|
|
23
|
+
*/
|
|
24
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
25
|
+
const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
|
|
26
|
+
const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
|
|
27
|
+
const utils_js_1 = require("../utils.js");
|
|
28
|
+
const { isPlainObject } = lodash_1.default; // CommonjS
|
|
29
|
+
class PostalAddressObject extends ValidatorFactory_js_1.default {
|
|
30
|
+
constructor() {
|
|
31
|
+
super(...arguments);
|
|
32
|
+
this.name = 'postalAddressObject';
|
|
33
|
+
}
|
|
34
|
+
validate(value, dataContext = {}) {
|
|
35
|
+
const cfg = Object.assign({ requiredFields: ['address1', 'address3', 'postcode'], strlenmax: undefined, errorMsgAddress1: {
|
|
36
|
+
inline: 'validation:rule.postalAddressObject.address1.inline',
|
|
37
|
+
summary: 'validation:rule.postalAddressObject.address1.summary',
|
|
38
|
+
focusSuffix: '[address1]',
|
|
39
|
+
}, errorMsgAddress2: {
|
|
40
|
+
inline: 'validation:rule.postalAddressObject.address2.inline',
|
|
41
|
+
summary: 'validation:rule.postalAddressObject.address2.summary',
|
|
42
|
+
focusSuffix: '[address2]',
|
|
43
|
+
}, errorMsgAddress3: {
|
|
44
|
+
inline: 'validation:rule.postalAddressObject.address3.inline',
|
|
45
|
+
summary: 'validation:rule.postalAddressObject.address3.summary',
|
|
46
|
+
focusSuffix: '[address3]',
|
|
47
|
+
}, errorMsgAddress4: {
|
|
48
|
+
inline: 'validation:rule.postalAddressObject.address4.inline',
|
|
49
|
+
summary: 'validation:rule.postalAddressObject.address4.summary',
|
|
50
|
+
focusSuffix: '[address4]',
|
|
51
|
+
}, errorMsgPostcode: {
|
|
52
|
+
inline: 'validation:rule.postalAddressObject.postcode.inline',
|
|
53
|
+
summary: 'validation:rule.postalAddressObject.postcode.summary',
|
|
54
|
+
focusSuffix: '[postcode]',
|
|
55
|
+
}, errorMsg: {
|
|
56
|
+
inline: 'validation:rule.postalAddressObject.group.inline',
|
|
57
|
+
summary: 'validation:rule.postalAddressObject.group.summary',
|
|
58
|
+
focusSuffix: '[address1]',
|
|
59
|
+
} }, this.config);
|
|
60
|
+
/* eslint-disable-next-line require-jsdoc */
|
|
61
|
+
const objectifyError = (err) => (typeof err === 'string' ? {
|
|
62
|
+
inline: err,
|
|
63
|
+
summary: err,
|
|
64
|
+
} : err);
|
|
65
|
+
// Work out required/optional parts based on config
|
|
66
|
+
const reqF = Object.create(null);
|
|
67
|
+
const reqC = cfg.requiredFields;
|
|
68
|
+
['address1', 'address2', 'address3', 'address4', 'postcode'].forEach((k) => {
|
|
69
|
+
reqF[k] = reqC.indexOf(k) > -1;
|
|
70
|
+
});
|
|
71
|
+
let valid = true;
|
|
72
|
+
const errorMsgs = [];
|
|
73
|
+
if (typeof value === 'object') {
|
|
74
|
+
const reAddr = /^[^\s]+[a-z0-9\-,.&#()/\\:;'" ]+$/i;
|
|
75
|
+
const reAddrLine1 = /^\d+|[^\s]+[a-z0-9\-,.&#()/\\:;'" ]+$/i;
|
|
76
|
+
// UK Postcode regex taken from the dwp java pc checker
|
|
77
|
+
// https://github.com/dwp/postcode-format-validation
|
|
78
|
+
const pc = /^(?![QVX])[A-Z]((?![IJZ])[A-Z][0-9](([0-9]?)|([ABEHMNPRVWXY]?))|([0-9]([0-9]?|[ABCDEFGHJKPSTUW]?))) ?[0-9]((?![CIKMOV])[A-Z]){2}$|^(BFPO)[ ]?[0-9]{1,4}$/i;
|
|
79
|
+
const rePostcode = new RegExp(pc, 'i');
|
|
80
|
+
// [required, regex, strlenmax, error message]
|
|
81
|
+
const attributes = {
|
|
82
|
+
address1: [reqF.address1, reAddrLine1, cfg.strlenmax, cfg.errorMsgAddress1],
|
|
83
|
+
address2: [reqF.address2, reAddr, cfg.strlenmax, cfg.errorMsgAddress2],
|
|
84
|
+
address3: [reqF.address3, reAddr, cfg.strlenmax, cfg.errorMsgAddress3],
|
|
85
|
+
address4: [reqF.address4, reAddr, cfg.strlenmax, cfg.errorMsgAddress4],
|
|
86
|
+
postcode: [reqF.postcode, rePostcode, null, cfg.errorMsgPostcode],
|
|
87
|
+
};
|
|
88
|
+
Object.keys(attributes).forEach((k) => {
|
|
89
|
+
const attr = attributes[k];
|
|
90
|
+
const hasProperty = Object.prototype.hasOwnProperty.call(value, k);
|
|
91
|
+
const hasContent = hasProperty && value[k].length > 0;
|
|
92
|
+
const condMissingOrRegexMismatch = (attr[0] || hasContent)
|
|
93
|
+
&& (!hasProperty || !value[k].match(attr[1]));
|
|
94
|
+
const condExceedStrlen = attr[2] > 0 && hasContent
|
|
95
|
+
&& String(value[k]).length > attr[2];
|
|
96
|
+
if (condMissingOrRegexMismatch || condExceedStrlen) {
|
|
97
|
+
valid = false;
|
|
98
|
+
errorMsgs.push(Object.assign(Object.create(null), objectifyError(attr[3]), {
|
|
99
|
+
fieldKeySuffix: `[${k}]`,
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
valid = false;
|
|
106
|
+
errorMsgs.push(cfg.errorMsg);
|
|
107
|
+
}
|
|
108
|
+
// Build ValidationErrorGroup
|
|
109
|
+
const errorGroup = errorMsgs.map((err) => (ValidationError_js_1.default.make({ errorMsg: err, dataContext })));
|
|
110
|
+
return valid ? [] : [...errorGroup];
|
|
111
|
+
}
|
|
112
|
+
sanitise(value) {
|
|
113
|
+
// Only objects are supported
|
|
114
|
+
if (!isPlainObject(value)) {
|
|
115
|
+
return Object.create(null);
|
|
116
|
+
}
|
|
117
|
+
// Prune unrecognised attributes, and coerce to Strings
|
|
118
|
+
const validKeys = ['address1', 'address2', 'address3', 'address4', 'postcode'];
|
|
119
|
+
const pruned = Object.fromEntries(Object.entries(value).filter(([k]) => (validKeys.includes(k))).map(([k, v]) => ([k, (0, utils_js_1.stringifyInput)(v)])));
|
|
120
|
+
return Object.assign(Object.create(null), pruned);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
exports.default = PostalAddressObject;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
/**
|
|
8
|
+
* Match a string pattern.
|
|
9
|
+
*
|
|
10
|
+
* Config options:
|
|
11
|
+
* string|object errorMsg = Error message to use on validation failure
|
|
12
|
+
* RegExp pattern = Regular expression to test against
|
|
13
|
+
* boolean invert = return reject on positive regex match
|
|
14
|
+
*/
|
|
15
|
+
const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
|
|
16
|
+
const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
|
|
17
|
+
const utils_js_1 = require("../utils.js");
|
|
18
|
+
class Regex extends ValidatorFactory_js_1.default {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments);
|
|
21
|
+
this.name = 'regex';
|
|
22
|
+
}
|
|
23
|
+
validate(value = '', dataContext = {}) {
|
|
24
|
+
const invert = this.config.invert || false;
|
|
25
|
+
const match = value.match(this.config.pattern || /.*/);
|
|
26
|
+
const valid = invert ? !match : match;
|
|
27
|
+
const errorMsg = this.config.errorMsg || {
|
|
28
|
+
inline: 'validation:rule.regex.inline',
|
|
29
|
+
summary: 'validation:rule.regex.summary',
|
|
30
|
+
};
|
|
31
|
+
return valid ? [] : [ValidationError_js_1.default.make({ errorMsg, dataContext })];
|
|
32
|
+
}
|
|
33
|
+
sanitise(value) {
|
|
34
|
+
if (value !== undefined) {
|
|
35
|
+
return (0, utils_js_1.stringifyInput)(value);
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.default = Regex;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
/**
|
|
8
|
+
* Test is value is present.
|
|
9
|
+
*
|
|
10
|
+
* Value is required. The following values will fail this rule:
|
|
11
|
+
* (all values that satisify `isEmpty()`) plus '\s'
|
|
12
|
+
*/
|
|
13
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
14
|
+
const utils_js_1 = require("../utils.js");
|
|
15
|
+
const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
|
|
16
|
+
const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
|
|
17
|
+
const { isPlainObject } = lodash_1.default; // CommonJS
|
|
18
|
+
class Required extends ValidatorFactory_js_1.default {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments);
|
|
21
|
+
this.name = 'required';
|
|
22
|
+
}
|
|
23
|
+
validate(value, dataContext = {}) {
|
|
24
|
+
const { errorMsg = {
|
|
25
|
+
inline: 'validation:rule.required.inline',
|
|
26
|
+
summary: 'validation:rule.required.summary',
|
|
27
|
+
}, } = this.config;
|
|
28
|
+
if (!(0, utils_js_1.isEmpty)(value)) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
return [
|
|
32
|
+
ValidationError_js_1.default.make({ errorMsg, dataContext }),
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
sanitise(value) {
|
|
36
|
+
const coerce = (val) => {
|
|
37
|
+
const s = (0, utils_js_1.stringifyInput)(val, undefined);
|
|
38
|
+
return s === undefined ? undefined : s.replace(/^\s+$/, '');
|
|
39
|
+
};
|
|
40
|
+
if ((0, utils_js_1.isStringable)(value)) {
|
|
41
|
+
return coerce(value);
|
|
42
|
+
}
|
|
43
|
+
// Coerce all elements to Strings.
|
|
44
|
+
// This only supports one dimensional array, with stringable element.
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
return value.map(coerce);
|
|
47
|
+
}
|
|
48
|
+
// Coerce all elements to Strings.
|
|
49
|
+
// This only supports a one dimensional object, with stringable elements.
|
|
50
|
+
if (isPlainObject(value)) {
|
|
51
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => ([k, coerce(v)])));
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.default = Required;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
/**
|
|
8
|
+
* Test the length of a string.
|
|
9
|
+
*
|
|
10
|
+
* Config options:
|
|
11
|
+
* string|object errorMsgMax = Error message to use on max length failure
|
|
12
|
+
* string|object errorMsgMin = Error message to use on min length failure
|
|
13
|
+
* int max = Maximum string length allowed
|
|
14
|
+
* int min = Minimum string length required
|
|
15
|
+
*/
|
|
16
|
+
const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
|
|
17
|
+
const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
|
|
18
|
+
const utils_js_1 = require("../utils.js");
|
|
19
|
+
class Strlen extends ValidatorFactory_js_1.default {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
this.name = 'strlen';
|
|
23
|
+
}
|
|
24
|
+
validate(inputValue = '', dataContext = {}) {
|
|
25
|
+
const { errorMsgMax = {
|
|
26
|
+
inline: 'validation:rule.strlen.max.inline',
|
|
27
|
+
summary: 'validation:rule.strlen.max.summary',
|
|
28
|
+
}, errorMsgMin = {
|
|
29
|
+
inline: 'validation:rule.strlen.min.inline',
|
|
30
|
+
summary: 'validation:rule.strlen.min.summary',
|
|
31
|
+
}, min, max, } = this.config;
|
|
32
|
+
let errorMsg;
|
|
33
|
+
let valid = true;
|
|
34
|
+
if (typeof max !== 'undefined' && inputValue.length > max) {
|
|
35
|
+
valid = false;
|
|
36
|
+
errorMsg = errorMsgMax;
|
|
37
|
+
}
|
|
38
|
+
if (typeof min !== 'undefined' && inputValue.length < min) {
|
|
39
|
+
valid = false;
|
|
40
|
+
errorMsg = errorMsgMin;
|
|
41
|
+
}
|
|
42
|
+
return valid ? [] : [ValidationError_js_1.default.make({ errorMsg, dataContext })];
|
|
43
|
+
}
|
|
44
|
+
sanitise(value) {
|
|
45
|
+
if (value !== undefined) {
|
|
46
|
+
return (0, utils_js_1.stringifyInput)(value);
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.default = Strlen;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable class-methods-use-this */
|
|
7
|
+
/**
|
|
8
|
+
* Test the number of words in a string.
|
|
9
|
+
*
|
|
10
|
+
* Config options:
|
|
11
|
+
* string|object errorMsgMax = Error message to use on max length failure
|
|
12
|
+
* string|object errorMsgMin = Error message to use on min length failure
|
|
13
|
+
* int max = Maximum word count allowed
|
|
14
|
+
* int min = Minimum word count required
|
|
15
|
+
*/
|
|
16
|
+
const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
|
|
17
|
+
const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
|
|
18
|
+
const utils_js_1 = require("../utils.js");
|
|
19
|
+
class WordCount extends ValidatorFactory_js_1.default {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
this.name = 'wordCount';
|
|
23
|
+
}
|
|
24
|
+
count(input) {
|
|
25
|
+
return (input.match(/\S+/g) || []).length;
|
|
26
|
+
}
|
|
27
|
+
validate(inputValue = '', dataContext = {}) {
|
|
28
|
+
const { errorMsgMax = {
|
|
29
|
+
inline: 'validation:rule.wordCount.max.inline',
|
|
30
|
+
summary: 'validation:rule.wordCount.max.summary',
|
|
31
|
+
}, errorMsgMin = {
|
|
32
|
+
inline: 'validation:rule.wordCount.min.inline',
|
|
33
|
+
summary: 'validation:rule.wordCount.min.summary',
|
|
34
|
+
}, min, max, } = this.config;
|
|
35
|
+
let errorMsg;
|
|
36
|
+
let valid = true;
|
|
37
|
+
if (typeof max !== 'undefined' && (inputValue.match(/\S+/g) || []).length > max) {
|
|
38
|
+
valid = false;
|
|
39
|
+
errorMsg = errorMsgMax;
|
|
40
|
+
}
|
|
41
|
+
if (typeof min !== 'undefined' && (inputValue.match(/\S+/g) || []).length < min) {
|
|
42
|
+
valid = false;
|
|
43
|
+
errorMsg = errorMsgMin;
|
|
44
|
+
}
|
|
45
|
+
return valid ? [] : [ValidationError_js_1.default.make({ errorMsg, dataContext })];
|
|
46
|
+
}
|
|
47
|
+
sanitise(value) {
|
|
48
|
+
if (value !== undefined) {
|
|
49
|
+
return (0, utils_js_1.stringifyInput)(value);
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
exports.default = WordCount;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a URL pointing at a particular waypoint.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} obj Options
|
|
5
|
+
* @param {string} obj.waypoint Waypoint
|
|
6
|
+
* @param {string} obj.mountUrl Mount URL
|
|
7
|
+
* @param {JourneyContext} obj.journeyContext JourneyContext
|
|
8
|
+
* @param {boolean} obj.edit Turn edit mode on or off
|
|
9
|
+
* @param {string} obj.editOrigin Edit mode original URL
|
|
10
|
+
* @param {boolean} obj.skipTo Skip to this waypoint from the current one
|
|
11
|
+
* @param {string} obj.routeName Plan route name; next | prev
|
|
12
|
+
* @returns {string} URL
|
|
13
|
+
*/
|
|
14
|
+
export default function waypointUrl({ waypoint, mountUrl, journeyContext, edit, editOrigin, skipTo, routeName, }?: {
|
|
15
|
+
waypoint: string;
|
|
16
|
+
mountUrl: string;
|
|
17
|
+
journeyContext: JourneyContext;
|
|
18
|
+
edit: boolean;
|
|
19
|
+
editOrigin: string;
|
|
20
|
+
skipTo: boolean;
|
|
21
|
+
routeName: string;
|
|
22
|
+
}): string;
|
|
23
|
+
export type JourneyContext = import('./index').JourneyContext;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @typedef {import('./index').JourneyContext} JourneyContext
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const reUrlProtocolExtract = /^url:\/\/(.+)$/i;
|
|
7
|
+
const sanitiseWaypoint = (w) => w.replace(/[^/a-z0-9_-]/ig, '').replace(/\/+/g, '/');
|
|
8
|
+
/**
|
|
9
|
+
* Generate a URL pointing at a particular waypoint.
|
|
10
|
+
*
|
|
11
|
+
* @param {object} obj Options
|
|
12
|
+
* @param {string} obj.waypoint Waypoint
|
|
13
|
+
* @param {string} obj.mountUrl Mount URL
|
|
14
|
+
* @param {JourneyContext} obj.journeyContext JourneyContext
|
|
15
|
+
* @param {boolean} obj.edit Turn edit mode on or off
|
|
16
|
+
* @param {string} obj.editOrigin Edit mode original URL
|
|
17
|
+
* @param {boolean} obj.skipTo Skip to this waypoint from the current one
|
|
18
|
+
* @param {string} obj.routeName Plan route name; next | prev
|
|
19
|
+
* @returns {string} URL
|
|
20
|
+
*/
|
|
21
|
+
function waypointUrl({ waypoint = '', mountUrl = '/', journeyContext, edit = false, editOrigin, skipTo, routeName = 'next', } = Object.create(null)) {
|
|
22
|
+
const url = new URL('https://placeholder.test');
|
|
23
|
+
// Handle url:// protocol
|
|
24
|
+
// - This will generate a link to the root handler "_" for the given mount path
|
|
25
|
+
if (String(waypoint).substr(0, 7) === 'url:///') {
|
|
26
|
+
const m = waypoint.match(reUrlProtocolExtract);
|
|
27
|
+
const u = new URL(m[1], 'https://placeholder.test/');
|
|
28
|
+
url.pathname = `${sanitiseWaypoint(u.pathname)}/_/`;
|
|
29
|
+
url.searchParams.append('refmount', `url://${mountUrl}`);
|
|
30
|
+
url.searchParams.append('route', routeName);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
url.pathname = `${mountUrl}${waypoint}`;
|
|
34
|
+
}
|
|
35
|
+
// Attach context id for non-default contexts
|
|
36
|
+
if (journeyContext && !journeyContext.isDefault() && journeyContext.identity.id) {
|
|
37
|
+
url.searchParams.append('contextid', journeyContext.identity.id);
|
|
38
|
+
}
|
|
39
|
+
// Attach edit mode flag
|
|
40
|
+
if (edit === true) {
|
|
41
|
+
url.searchParams.append('edit', 'true');
|
|
42
|
+
}
|
|
43
|
+
if (edit && editOrigin) {
|
|
44
|
+
url.searchParams.append('editorigin', sanitiseWaypoint(editOrigin));
|
|
45
|
+
}
|
|
46
|
+
// Skipto
|
|
47
|
+
if (skipTo) {
|
|
48
|
+
url.searchParams.append('skipto', sanitiseWaypoint(skipTo));
|
|
49
|
+
}
|
|
50
|
+
return `${sanitiseWaypoint(url.pathname)}${url.search}`;
|
|
51
|
+
}
|
|
52
|
+
exports.default = waypointUrl;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function bodyParserMiddleware(): import("connect").NextHandleFunction[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const express_1 = require("express");
|
|
4
|
+
function bodyParserMiddleware() {
|
|
5
|
+
const rProto = /__proto__/i;
|
|
6
|
+
const rPrototype = /prototype[='"[\]]/i;
|
|
7
|
+
const rConstructor = /constructor[='"[\]]/i;
|
|
8
|
+
return [
|
|
9
|
+
(0, express_1.urlencoded)({
|
|
10
|
+
extended: true,
|
|
11
|
+
type: 'application/x-www-form-urlencoded',
|
|
12
|
+
inflate: true,
|
|
13
|
+
parameterLimit: 25,
|
|
14
|
+
limit: 1024 * 50,
|
|
15
|
+
verify: (req, res, buf, encoding) => {
|
|
16
|
+
const body = decodeURI(buf.toString(encoding));
|
|
17
|
+
if (rProto.test(body) || rPrototype.test(body) || rConstructor.test(body)) {
|
|
18
|
+
throw new Error('Request body verification failed');
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
}),
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
exports.default = bodyParserMiddleware;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function csrfMiddleware(): any[];
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const csurf_1 = __importDefault(require("csurf"));
|
|
7
|
+
// 2 middleware: one to generate the csrf token and check its validity (POST
|
|
8
|
+
// only), and one to provide that token to templates via the `casa.csrfToken`
|
|
9
|
+
// variable.
|
|
10
|
+
function csrfMiddleware() {
|
|
11
|
+
return [
|
|
12
|
+
(0, csurf_1.default)({
|
|
13
|
+
cookie: false,
|
|
14
|
+
sessionKey: 'session',
|
|
15
|
+
// value: (req) => {
|
|
16
|
+
// // Here we clear the token after extracting to maintain cleaner data. It
|
|
17
|
+
// // is only used for this CSRF purpose.
|
|
18
|
+
// const token = String(req.body._csrf);
|
|
19
|
+
// delete req.body._csrf;
|
|
20
|
+
// return token;
|
|
21
|
+
// /* eslint-enable no-underscore-dangle */
|
|
22
|
+
// },
|
|
23
|
+
}),
|
|
24
|
+
(req, res, next) => {
|
|
25
|
+
var _a;
|
|
26
|
+
res.locals.casa = Object.assign(Object.assign({}, (_a = res.locals) === null || _a === void 0 ? void 0 : _a.casa), { csrfToken: req.csrfToken() });
|
|
27
|
+
next();
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
exports.default = csrfMiddleware;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Decorates the request with some contextual data about the user's journey
|
|
3
|
+
// through the application. This is used by downstream middleware and templates.
|
|
4
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
9
|
+
const JourneyContext_js_1 = __importDefault(require("../lib/JourneyContext.js"));
|
|
10
|
+
const waypoint_url_js_1 = __importDefault(require("../lib/waypoint-url.js"));
|
|
11
|
+
const { has } = lodash_1.default;
|
|
12
|
+
const editOrigin = (req) => {
|
|
13
|
+
if (has(req.query, 'editorigin')) {
|
|
14
|
+
return (0, waypoint_url_js_1.default)({ waypoint: req.query.editorigin });
|
|
15
|
+
}
|
|
16
|
+
if (has(req === null || req === void 0 ? void 0 : req.body, 'editorigin')) {
|
|
17
|
+
return (0, waypoint_url_js_1.default)({ waypoint: req.body.editorigin });
|
|
18
|
+
}
|
|
19
|
+
return '';
|
|
20
|
+
};
|
|
21
|
+
function dataMiddleware({ plan, mountUrl, events, }) {
|
|
22
|
+
return [
|
|
23
|
+
(req, res, next) => {
|
|
24
|
+
/* ------------------------------------------------ Request decorations */
|
|
25
|
+
// CASA
|
|
26
|
+
req.casa = Object.assign(Object.assign({}, req === null || req === void 0 ? void 0 : req.casa), {
|
|
27
|
+
// The plan
|
|
28
|
+
plan,
|
|
29
|
+
// Current journey context, loaded from session, specified by
|
|
30
|
+
// `contextid` request parameter
|
|
31
|
+
journeyContext: JourneyContext_js_1.default.extractContextFromRequest(req).addEventListeners(events),
|
|
32
|
+
// Edit mode
|
|
33
|
+
editMode: (has(req === null || req === void 0 ? void 0 : req.query, 'edit') && has(req === null || req === void 0 ? void 0 : req.query, 'editorigin')) || (has(req === null || req === void 0 ? void 0 : req.body, 'edit') && has(req === null || req === void 0 ? void 0 : req.body, 'editorigin')), editOrigin: editOrigin(req) });
|
|
34
|
+
// Grab chosen language from session
|
|
35
|
+
req.casa.journeyContext.nav.language = req.session.language;
|
|
36
|
+
/* ------------------------------------------------- Template variables */
|
|
37
|
+
// CASA and userland templates
|
|
38
|
+
res.locals.casa = {
|
|
39
|
+
mountUrl,
|
|
40
|
+
};
|
|
41
|
+
res.locals.locale = req.language;
|
|
42
|
+
// Used by govuk-frontend template
|
|
43
|
+
// - req.language is provided by i18n-http-middleware
|
|
44
|
+
res.locals.htmlLang = req.language;
|
|
45
|
+
// Function for building URLs. This will be curried with the `mountUrl`
|
|
46
|
+
// and `journeyContext` for convenience
|
|
47
|
+
res.locals.waypointUrl = (args) => (0, waypoint_url_js_1.default)(Object.assign({ mountUrl, journeyContext: req.casa.journeyContext }, args));
|
|
48
|
+
// req.editSearchParams
|
|
49
|
+
next();
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
exports.default = dataMiddleware;
|