@dwp/govuk-casa 7.0.6 → 8.0.0-alpha1

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 (219) hide show
  1. package/README.md +22 -17
  2. package/dist/{casa → assets}/css/casa-ie8.css +1 -1
  3. package/dist/assets/css/casa.css +1 -0
  4. package/dist/casa.d.ts +10 -0
  5. package/dist/casa.js +44 -0
  6. package/dist/lib/CasaTemplateLoader.d.ts +19 -0
  7. package/dist/lib/CasaTemplateLoader.js +57 -0
  8. package/dist/lib/JourneyContext.d.ts +255 -0
  9. package/dist/lib/JourneyContext.js +681 -0
  10. package/dist/lib/MutableRouter.d.ts +155 -0
  11. package/dist/lib/MutableRouter.js +272 -0
  12. package/dist/lib/Plan.d.ts +119 -0
  13. package/dist/lib/Plan.js +382 -0
  14. package/dist/lib/ValidationError.d.ts +70 -0
  15. package/dist/lib/ValidationError.js +156 -0
  16. package/dist/lib/ValidatorFactory.d.ts +24 -0
  17. package/dist/lib/ValidatorFactory.js +87 -0
  18. package/dist/lib/configure.d.ts +205 -0
  19. package/dist/lib/configure.js +215 -0
  20. package/dist/lib/dirname.cjs +1 -0
  21. package/dist/lib/end-session.d.ts +12 -0
  22. package/dist/lib/end-session.js +24 -0
  23. package/dist/lib/field.d.ts +79 -0
  24. package/dist/lib/field.js +223 -0
  25. package/dist/lib/logger.d.ts +8 -0
  26. package/dist/lib/logger.js +19 -0
  27. package/dist/lib/nunjucks-filters.d.ts +26 -0
  28. package/dist/lib/nunjucks-filters.js +112 -0
  29. package/dist/lib/nunjucks.d.ts +22 -0
  30. package/dist/lib/nunjucks.js +49 -0
  31. package/dist/lib/utils.d.ts +22 -0
  32. package/dist/lib/utils.js +44 -0
  33. package/dist/lib/validators/dateObject.d.ts +4 -0
  34. package/dist/lib/validators/dateObject.js +135 -0
  35. package/dist/lib/validators/email.d.ts +4 -0
  36. package/dist/lib/validators/email.js +46 -0
  37. package/dist/lib/validators/inArray.d.ts +4 -0
  38. package/dist/lib/validators/inArray.js +60 -0
  39. package/dist/lib/validators/index.d.ts +21 -0
  40. package/dist/lib/validators/index.js +47 -0
  41. package/dist/lib/validators/nino.d.ts +4 -0
  42. package/dist/lib/validators/nino.js +46 -0
  43. package/dist/lib/validators/postalAddressObject.d.ts +4 -0
  44. package/dist/lib/validators/postalAddressObject.js +123 -0
  45. package/dist/lib/validators/regex.d.ts +4 -0
  46. package/dist/lib/validators/regex.js +40 -0
  47. package/dist/lib/validators/required.d.ts +4 -0
  48. package/dist/lib/validators/required.js +56 -0
  49. package/dist/lib/validators/strlen.d.ts +4 -0
  50. package/dist/lib/validators/strlen.js +51 -0
  51. package/dist/lib/validators/wordCount.d.ts +5 -0
  52. package/dist/lib/validators/wordCount.js +54 -0
  53. package/dist/lib/waypoint-url.d.ts +17 -0
  54. package/dist/lib/waypoint-url.js +46 -0
  55. package/dist/middleware/body-parser.d.ts +1 -0
  56. package/dist/middleware/body-parser.js +24 -0
  57. package/dist/middleware/csrf.d.ts +1 -0
  58. package/dist/middleware/csrf.js +31 -0
  59. package/dist/middleware/data.d.ts +6 -0
  60. package/dist/middleware/data.js +53 -0
  61. package/dist/middleware/dirname.cjs +1 -0
  62. package/dist/middleware/gather-fields.d.ts +5 -0
  63. package/dist/middleware/gather-fields.js +39 -0
  64. package/dist/middleware/i18n.d.ts +4 -0
  65. package/dist/middleware/i18n.js +87 -0
  66. package/dist/middleware/post.d.ts +1 -0
  67. package/dist/middleware/post.js +42 -0
  68. package/dist/middleware/pre.d.ts +3 -0
  69. package/dist/middleware/pre.js +38 -0
  70. package/dist/middleware/progress-journey.d.ts +6 -0
  71. package/dist/middleware/progress-journey.js +82 -0
  72. package/dist/middleware/sanitise-fields.d.ts +5 -0
  73. package/dist/middleware/sanitise-fields.js +48 -0
  74. package/dist/middleware/session.d.ts +10 -0
  75. package/dist/middleware/session.js +115 -0
  76. package/dist/middleware/skip-waypoint.d.ts +5 -0
  77. package/dist/middleware/skip-waypoint.js +40 -0
  78. package/dist/middleware/steer-journey.d.ts +6 -0
  79. package/dist/middleware/steer-journey.js +44 -0
  80. package/dist/middleware/validate-fields.d.ts +7 -0
  81. package/dist/middleware/validate-fields.js +76 -0
  82. package/dist/mjs/esm-wrapper.js +10 -0
  83. package/dist/mjs/package.json +3 -0
  84. package/dist/package.json +3 -0
  85. package/dist/routes/ancillary.d.ts +4 -0
  86. package/dist/routes/ancillary.js +19 -0
  87. package/dist/routes/dirname.cjs +1 -0
  88. package/dist/routes/journey.d.ts +8 -0
  89. package/dist/routes/journey.js +130 -0
  90. package/dist/routes/static.d.ts +26 -0
  91. package/dist/routes/static.js +67 -0
  92. package/package.json +45 -86
  93. package/views/casa/components/checkboxes/template.njk +4 -1
  94. package/views/casa/components/date-input/template.njk +3 -3
  95. package/views/casa/components/journey-form/README.md +3 -1
  96. package/views/casa/components/journey-form/template.njk +1 -1
  97. package/views/casa/components/postal-address-object/template.njk +5 -5
  98. package/views/casa/components/radios/template.njk +1 -1
  99. package/views/casa/layouts/journey.njk +26 -9
  100. package/views/casa/layouts/main.njk +6 -19
  101. package/views/casa/partials/scripts.njk +8 -3
  102. package/views/casa/partials/styles.njk +2 -2
  103. package/casa.js +0 -208
  104. package/definitions/review-page.js +0 -60
  105. package/dist/casa/css/casa.css +0 -1
  106. package/dist/casa/js/casa.js +0 -1
  107. package/index.d.ts +0 -121
  108. package/lib/ConfigIngestor.js +0 -588
  109. package/lib/GatherModifier.js +0 -14
  110. package/lib/I18n.js +0 -160
  111. package/lib/JourneyContext.d.ts +0 -97
  112. package/lib/JourneyContext.js +0 -552
  113. package/lib/JourneyMap.js +0 -233
  114. package/lib/JourneyRoad.js +0 -330
  115. package/lib/Logger.js +0 -59
  116. package/lib/PageDictionary.d.ts +0 -11
  117. package/lib/PageDirectory.js +0 -77
  118. package/lib/Plan.js +0 -423
  119. package/lib/RoadConverter.js +0 -153
  120. package/lib/UserJourney.js +0 -8
  121. package/lib/Util.js +0 -227
  122. package/lib/Validation.js +0 -20
  123. package/lib/bootstrap/end-session.js +0 -44
  124. package/lib/bootstrap/load-definitions.js +0 -64
  125. package/lib/commonBodyParser.js +0 -15
  126. package/lib/enums.js +0 -6
  127. package/lib/gather-modifiers/index.js +0 -7
  128. package/lib/gather-modifiers/trimPostalAddressObject.js +0 -75
  129. package/lib/gather-modifiers/trimWhitespace.js +0 -16
  130. package/lib/utils/createGetRequest.d.ts +0 -5
  131. package/lib/utils/createGetRequest.js +0 -59
  132. package/lib/utils/index.js +0 -11
  133. package/lib/utils/parseRequest.d.ts +0 -5
  134. package/lib/utils/parseRequest.js +0 -72
  135. package/lib/utils/sanitise.js +0 -74
  136. package/lib/utils/validate.js +0 -32
  137. package/lib/validation/ArrayObjectField.js +0 -49
  138. package/lib/validation/ObjectField.js +0 -53
  139. package/lib/validation/SimpleField.d.ts +0 -11
  140. package/lib/validation/SimpleField.js +0 -46
  141. package/lib/validation/ValidationError.d.ts +0 -14
  142. package/lib/validation/ValidationError.js +0 -170
  143. package/lib/validation/ValidatorFactory.d.ts +0 -32
  144. package/lib/validation/ValidatorFactory.js +0 -91
  145. package/lib/validation/index.js +0 -22
  146. package/lib/validation/processor/flattenErrorArray.js +0 -24
  147. package/lib/validation/processor/queue.js +0 -214
  148. package/lib/validation/processor.js +0 -84
  149. package/lib/validation/rules/README.md +0 -3
  150. package/lib/validation/rules/ValidationRules.d.ts +0 -22
  151. package/lib/validation/rules/dateObject.js +0 -156
  152. package/lib/validation/rules/email.js +0 -44
  153. package/lib/validation/rules/inArray.js +0 -61
  154. package/lib/validation/rules/index.js +0 -23
  155. package/lib/validation/rules/nino.js +0 -48
  156. package/lib/validation/rules/optional.js +0 -14
  157. package/lib/validation/rules/postalAddressObject.js +0 -142
  158. package/lib/validation/rules/regex.js +0 -39
  159. package/lib/validation/rules/required.js +0 -57
  160. package/lib/validation/rules/strlen.js +0 -57
  161. package/lib/validation/rules/wordCount.js +0 -61
  162. package/lib/view-filters/formatDateObject.js +0 -35
  163. package/lib/view-filters/includes.js +0 -10
  164. package/lib/view-filters/index.js +0 -23
  165. package/lib/view-filters/mergeObjectsDeep.js +0 -21
  166. package/lib/view-filters/renderAsAttributes.js +0 -33
  167. package/middleware/errors/404.js +0 -12
  168. package/middleware/errors/catch-all.js +0 -27
  169. package/middleware/errors/index.js +0 -9
  170. package/middleware/headers/config-defaults.js +0 -57
  171. package/middleware/headers/headers.js +0 -40
  172. package/middleware/headers/index.js +0 -9
  173. package/middleware/i18n/i18n.js +0 -56
  174. package/middleware/i18n/index.js +0 -16
  175. package/middleware/index.js +0 -55
  176. package/middleware/mount/index.js +0 -9
  177. package/middleware/mount/mount.js +0 -10
  178. package/middleware/nunjucks/environment.js +0 -57
  179. package/middleware/nunjucks/index.js +0 -8
  180. package/middleware/page/csrf.js +0 -37
  181. package/middleware/page/edit-mode.js +0 -52
  182. package/middleware/page/gather.js +0 -75
  183. package/middleware/page/index.js +0 -103
  184. package/middleware/page/journey-continue.js +0 -157
  185. package/middleware/page/journey-rails.js +0 -102
  186. package/middleware/page/prepare-request.js +0 -77
  187. package/middleware/page/render.js +0 -75
  188. package/middleware/page/skip.js +0 -72
  189. package/middleware/page/utils.js +0 -206
  190. package/middleware/page/validate.js +0 -67
  191. package/middleware/session/expiry.js +0 -95
  192. package/middleware/session/genid.js +0 -18
  193. package/middleware/session/index.js +0 -18
  194. package/middleware/session/init.js +0 -25
  195. package/middleware/session/seed.js +0 -50
  196. package/middleware/session/timeout.js +0 -5
  197. package/middleware/static/asset-versions.js +0 -23
  198. package/middleware/static/index.js +0 -104
  199. package/middleware/static/prepare-assets.js +0 -51
  200. package/middleware/static/serve-assets.js +0 -58
  201. package/middleware/variables/index.js +0 -12
  202. package/middleware/variables/variables.js +0 -35
  203. package/src/browserconfig.xml +0 -5
  204. package/src/js/casa.js +0 -132
  205. package/src/scss/_casaElements.scss +0 -11
  206. package/src/scss/_casaGovukTemplateJinjaPolyfill.scss +0 -39
  207. package/src/scss/_casaMountUrl.scss +0 -8
  208. package/src/scss/casa-ie8.scss +0 -3
  209. package/src/scss/casa.scss +0 -14
  210. package/test/unit/templates/README.md +0 -5
  211. package/test/utils/BaseTestWaypoint.js +0 -106
  212. package/test/utils/concatWaypoints.js +0 -26
  213. package/test/utils/index.js +0 -6
  214. package/test/utils/testTraversal.js +0 -90
  215. package/views/casa/partials/cookie_message.njk +0 -3
  216. package/views/casa/partials/phase_banner_alpha.njk +0 -8
  217. package/views/casa/partials/phase_banner_beta.njk +0 -8
  218. package/views/casa/review/page-block.njk +0 -8
  219. package/views/casa/review/review.njk +0 -47
@@ -0,0 +1,223 @@
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
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _PageField_name, _PageField_processors, _PageField_validators, _PageField_conditions, _PageField_meta;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.PageField = void 0;
19
+ const utils_js_1 = require("./utils.js");
20
+ const lodash_1 = __importDefault(require("lodash"));
21
+ const { isFunction } = lodash_1.default;
22
+ /**
23
+ * @typedef {Object} Validator
24
+ * @property {ValidateFunction} validate Validation function
25
+ * @property {SanitiseFunction} sanitise Sanitise a given value to make it suitable for this validator
26
+ * @property {Object} config Configuration
27
+ * @property {string} name Validator name
28
+ */
29
+ /**
30
+ * @callback ValidateFunction
31
+ * @param {any} value
32
+ * @param {ValidateContext} context
33
+ * @return {ValidationError[]}
34
+ */
35
+ /**
36
+ * @callback SanitiseFunction
37
+ * @param {any} value
38
+ * @returns {any}
39
+ */
40
+ /**
41
+ * @typedef {Object} ValidateContext Context passed to validate function
42
+ * @property {JourneyContext} journeyContext Journey context
43
+ * @property {string} waypoint Waypoint
44
+ * @property {string} fieldName Name of field being processed
45
+ */
46
+ // Quick check to see if the field name corresponds to a non-primitive complex
47
+ // type. For example, `my_field[nested]`.
48
+ const reComplexType = /\[/;
49
+ const reInvalidName = /[^a-z0-9_.\-\[\]]/i;
50
+ // Factory for convenience
51
+ function field(...args) {
52
+ return new PageField(...args);
53
+ }
54
+ exports.default = field;
55
+ // This is never exposed via a public API, and instead users are encouraged to
56
+ // use the `field()` factory instead
57
+ class PageField {
58
+ constructor(name, { optional = false, persist = true } = Object.create(null)) {
59
+ /*
60
+ * @type {string}
61
+ */
62
+ _PageField_name.set(this, void 0);
63
+ /**
64
+ * @type {function[]}
65
+ */
66
+ _PageField_processors.set(this, void 0);
67
+ /**
68
+ * @type {Validator[]}
69
+ */
70
+ _PageField_validators.set(this, void 0);
71
+ /**
72
+ * @type {function[]}
73
+ */
74
+ _PageField_conditions.set(this, void 0);
75
+ /**
76
+ * @type {Object}
77
+ */
78
+ _PageField_meta.set(this, void 0);
79
+ if (!name) {
80
+ throw new SyntaxError('A name for this field is required, i.e. "field(\'myField\')".');
81
+ }
82
+ else if (reInvalidName.test(String(name))) {
83
+ throw new SyntaxError(`Field '${String(name)}' name contains invalid characters.`);
84
+ }
85
+ __classPrivateFieldSet(this, _PageField_name, String(name), "f");
86
+ __classPrivateFieldSet(this, _PageField_validators, [], "f");
87
+ __classPrivateFieldSet(this, _PageField_processors, [], "f");
88
+ __classPrivateFieldSet(this, _PageField_conditions, [], "f");
89
+ __classPrivateFieldSet(this, _PageField_meta, {
90
+ optional,
91
+ persist,
92
+ complex: reComplexType.test(name),
93
+ }, "f");
94
+ }
95
+ /**
96
+ * For complex fields, we need may need to drill into an object to extract the
97
+ * value.
98
+ *
99
+ * @param {Object} obj Object from which to extract the value
100
+ * @returns {any}
101
+ */
102
+ getValue(obj = Object.create(null)) {
103
+ if (!__classPrivateFieldGet(this, _PageField_meta, "f").complex) {
104
+ return obj[__classPrivateFieldGet(this, _PageField_name, "f")];
105
+ }
106
+ throw new Error('Not yet supporting complex field types');
107
+ }
108
+ putValue(obj = Object.create(null), value) {
109
+ if (!__classPrivateFieldGet(this, _PageField_meta, "f").complex) {
110
+ obj[__classPrivateFieldGet(this, _PageField_name, "f")] = value;
111
+ return this;
112
+ }
113
+ throw new Error('Not yet supporting complex field types');
114
+ }
115
+ /* -------------------------------------------------------------- configure */
116
+ get name() {
117
+ return __classPrivateFieldGet(this, _PageField_name, "f");
118
+ }
119
+ get meta() {
120
+ return __classPrivateFieldGet(this, _PageField_meta, "f");
121
+ }
122
+ // Add/get value validators
123
+ // Some validators might include their own processors on
124
+ validators(...items) {
125
+ // TODO: prepend any sanitisers these validators may have onto the #processors array
126
+ if (!items.length)
127
+ return __classPrivateFieldGet(this, _PageField_validators, "f");
128
+ __classPrivateFieldSet(this, _PageField_validators, [...__classPrivateFieldGet(this, _PageField_validators, "f"), ...(items.flat())], "f");
129
+ return this;
130
+ }
131
+ // Add/get value pre-processors
132
+ // This is most often used to sanitise values to a particular data type
133
+ processors(...items) {
134
+ if (!items.length)
135
+ return __classPrivateFieldGet(this, _PageField_processors, "f");
136
+ __classPrivateFieldSet(this, _PageField_processors, [...__classPrivateFieldGet(this, _PageField_processors, "f"), ...(items.flat())], "f");
137
+ return this;
138
+ }
139
+ // Add/get conditions
140
+ // All conditions must be met in order for this field to be considered "actionable"
141
+ conditions(...items) {
142
+ if (!items.length)
143
+ return __classPrivateFieldGet(this, _PageField_conditions, "f");
144
+ __classPrivateFieldSet(this, _PageField_conditions, [...__classPrivateFieldGet(this, _PageField_conditions, "f"), ...(items.flat())], "f");
145
+ return this;
146
+ }
147
+ /* ---------------------------------------------------------------- execute */
148
+ /**
149
+ * Run all validators and return array of errors, if applicable.
150
+ *
151
+ * @param {any} value Value to validate
152
+ * @param {ValidateContext} context Contextual information
153
+ * @returns {ValidationError[]} Errors, or an empty array if all valid
154
+ */
155
+ runValidators(value, context) {
156
+ // Skip validation if the field is empty and optional
157
+ if (__classPrivateFieldGet(this, _PageField_meta, "f").optional && (0, utils_js_1.isEmpty)(value)) {
158
+ return [];
159
+ }
160
+ let errors = [];
161
+ for (let i = 0, l = __classPrivateFieldGet(this, _PageField_validators, "f").length; i < l; i++) {
162
+ const fieldErrors = __classPrivateFieldGet(this, _PageField_validators, "f")[i].validate(value, context).map(e => e.withContext(Object.assign(Object.assign({}, context), { validator: __classPrivateFieldGet(this, _PageField_validators, "f")[i].name })));
163
+ errors = [
164
+ ...errors,
165
+ ...(fieldErrors !== null && fieldErrors !== void 0 ? fieldErrors : []),
166
+ ];
167
+ }
168
+ return errors;
169
+ }
170
+ // Apply all the processors to the given value
171
+ applyProcessors(value) {
172
+ let processedValue = value;
173
+ // Some of the validators may have their own "sanitise()" methods. These
174
+ // should be run before any other processors
175
+ for (let i = 0, l = __classPrivateFieldGet(this, _PageField_validators, "f").length; i < l; i++) {
176
+ if (isFunction(__classPrivateFieldGet(this, _PageField_validators, "f")[i].sanitise)) {
177
+ processedValue = __classPrivateFieldGet(this, _PageField_validators, "f")[i].sanitise(processedValue);
178
+ }
179
+ }
180
+ for (let i = 0, l = __classPrivateFieldGet(this, _PageField_processors, "f").length; i < l; i++) {
181
+ processedValue = __classPrivateFieldGet(this, _PageField_processors, "f")[i](processedValue);
182
+ }
183
+ return processedValue;
184
+ }
185
+ /**
186
+ * Apply all conditions to get the resulting boolean
187
+ *
188
+ * @param {Object} params Parameters
189
+ * @param {string} fieldValue Field value
190
+ * @param {string} waypoint Waypoint
191
+ * @param {object} journeyContext JourneyContext
192
+ * @returns {boolean}
193
+ */
194
+ testConditions({ fieldValue, waypoint, journeyContext }) {
195
+ const context = {
196
+ fieldName: __classPrivateFieldGet(this, _PageField_name, "f"),
197
+ fieldValue,
198
+ waypoint,
199
+ waypointId: waypoint,
200
+ journeyContext,
201
+ };
202
+ let result = true;
203
+ for (let i = 0, l = __classPrivateFieldGet(this, _PageField_conditions, "f").length; i < l; i++) {
204
+ result = result && __classPrivateFieldGet(this, _PageField_conditions, "f")[i](context);
205
+ }
206
+ return result;
207
+ }
208
+ /* ---------------------------------------------------------------- aliases */
209
+ validator(...args) {
210
+ return this.validators(...args);
211
+ }
212
+ processor(...args) {
213
+ return this.processors(...args);
214
+ }
215
+ condition(...args) {
216
+ return this.conditions(...args);
217
+ }
218
+ if(...args) {
219
+ return this.conditions(...args);
220
+ }
221
+ }
222
+ exports.PageField = PageField;
223
+ _PageField_name = new WeakMap(), _PageField_processors = new WeakMap(), _PageField_validators = new WeakMap(), _PageField_conditions = new WeakMap(), _PageField_meta = new WeakMap();
@@ -0,0 +1,8 @@
1
+ export default function _default(ns: any): {
2
+ trace: any;
3
+ debug: any;
4
+ info: any;
5
+ warn: any;
6
+ error: any;
7
+ fatal: any;
8
+ };
@@ -0,0 +1,19 @@
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 debug_1 = __importDefault(require("debug"));
7
+ const casaDebugger = (0, debug_1.default)('casa');
8
+ function default_1(ns) {
9
+ const logger = casaDebugger.extend(ns);
10
+ return {
11
+ trace: logger.extend('trace'),
12
+ debug: logger.extend('debug'),
13
+ info: logger.extend('info'),
14
+ warn: logger.extend('warn'),
15
+ error: logger.extend('error'),
16
+ fatal: logger.extend('fatal'),
17
+ };
18
+ }
19
+ exports.default = default_1;
@@ -0,0 +1,26 @@
1
+ export function mergeObjects(...objects: any[]): object;
2
+ export function includes(source?: any[], search?: string): boolean;
3
+ /**
4
+ * Format a given date.
5
+ *
6
+ * Requires NodeJS >= 14 to make use of bundled date locale data.
7
+ *
8
+ * `date` may be any of the following types:
9
+ * object - {dd:'', mm:'', yyyy:''}
10
+ *
11
+ * @param {object} date Date (see supported formats above)
12
+ * @param {object} config Holds locale
13
+ * @returns {string} Formatted date
14
+ */
15
+ export function formatDateObject(date: object, config?: object): string;
16
+ /**
17
+ * Attribute values will be HTML/attribute escaped.
18
+ *
19
+ * Example:
20
+ * Given: {class: 'basic', 'data-ga': 3}
21
+ * Output: class="basic" data-ga="3"
22
+ *
23
+ * @param {object} attrsObject Attributes object (in name:value pairs)
24
+ * @returns {string} Formatted
25
+ */
26
+ export function renderAsAttributes(attrsObject: object): string;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.renderAsAttributes = exports.formatDateObject = exports.includes = exports.mergeObjects = void 0;
26
+ const deepmerge_1 = __importStar(require("deepmerge"));
27
+ const luxon_1 = require("luxon");
28
+ const nunjucks_1 = __importDefault(require("nunjucks"));
29
+ // Arrays will be merged such that elements at the same index will be merged
30
+ // into each other
31
+ // ref: https://www.npmjs.com/package/deepmerge
32
+ const combineMerge = (target, source, options) => {
33
+ const destination = target.slice();
34
+ source.forEach((item, index) => {
35
+ if (typeof destination[index] === 'undefined') {
36
+ destination[index] = options.cloneUnlessOtherwiseSpecified(item, options);
37
+ }
38
+ else if (options.isMergeableObject(item)) {
39
+ destination[index] = (0, deepmerge_1.default)(target[index], item, options);
40
+ }
41
+ else if (target.indexOf(item) === -1) {
42
+ destination.push(item);
43
+ }
44
+ });
45
+ return destination;
46
+ };
47
+ function mergeObjects(...objects) {
48
+ return (0, deepmerge_1.all)([Object.create(null), ...objects], { arrayMerge: combineMerge });
49
+ }
50
+ exports.mergeObjects = mergeObjects;
51
+ ;
52
+ function includes(source = [], search = '') {
53
+ return source.includes(search);
54
+ }
55
+ exports.includes = includes;
56
+ ;
57
+ /**
58
+ * Format a given date.
59
+ *
60
+ * Requires NodeJS >= 14 to make use of bundled date locale data.
61
+ *
62
+ * `date` may be any of the following types:
63
+ * object - {dd:'', mm:'', yyyy:''}
64
+ *
65
+ * @param {object} date Date (see supported formats above)
66
+ * @param {object} config Holds locale
67
+ * @returns {string} Formatted date
68
+ */
69
+ function formatDateObject(date, config = {}) {
70
+ const { locale = 'en' } = config;
71
+ if (Object.prototype.toString.call(date) === '[object Object]'
72
+ && 'yyyy' in date
73
+ && 'mm' in date
74
+ && 'dd' in date) {
75
+ return luxon_1.DateTime.fromObject({
76
+ year: Math.max(0, parseInt(date.yyyy, 10)),
77
+ month: Math.max(0, parseInt(date.mm, 10)),
78
+ day: Math.max(1, parseInt(date.dd, 10)),
79
+ }).setLocale(locale).toFormat('d MMMM yyyy');
80
+ }
81
+ return 'INVALID DATE OBJECT';
82
+ }
83
+ exports.formatDateObject = formatDateObject;
84
+ ;
85
+ /**
86
+ * Attribute values will be HTML/attribute escaped.
87
+ *
88
+ * Example:
89
+ * Given: {class: 'basic', 'data-ga': 3}
90
+ * Output: class="basic" data-ga="3"
91
+ *
92
+ * @param {object} attrsObject Attributes object (in name:value pairs)
93
+ * @returns {string} Formatted
94
+ */
95
+ function renderAsAttributes(attrsObject) {
96
+ const attrsList = [];
97
+ if (typeof attrsObject === 'object') {
98
+ Object.keys(attrsObject).forEach((key) => {
99
+ const value = String(attrsObject[key]).replace(/[<>"'&]/g, (m) => ({
100
+ '<': '&lt;',
101
+ '>': '&gt;',
102
+ '"': '&quot;',
103
+ '\'': '&#039;',
104
+ '&': '&amp;',
105
+ }[m]));
106
+ attrsList.push(`${key}="${value}"`);
107
+ });
108
+ }
109
+ return new nunjucks_1.default.runtime.SafeString(attrsList.join(' '));
110
+ }
111
+ exports.renderAsAttributes = renderAsAttributes;
112
+ ;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @typedef {Object} NunjucksOptions
3
+ * @property {string} [mountUrl=/] Mount URL. This i made available as a `casa.mountUrl` template variable (optional, default /)
4
+ * @property {string[]} [views=[]] List of directories to look for template files (optional, default [])
5
+ */
6
+ /**
7
+ * Create a Nunjucks environment.
8
+ *
9
+ * @param {NunjucksOptions} options Nunjucks options
10
+ * @returns {nunjucks.Environment} Nunjucks Environment instance
11
+ */
12
+ export default function _default({ mountUrl, views, }: NunjucksOptions): any;
13
+ export type NunjucksOptions = {
14
+ /**
15
+ * )
16
+ */
17
+ mountUrl?: string | undefined;
18
+ /**
19
+ * List of directories to look for template files (optional, default [])
20
+ */
21
+ views?: string[] | undefined;
22
+ };
@@ -0,0 +1,49 @@
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 fs_1 = require("fs");
7
+ const path_1 = require("path");
8
+ const nunjucks_1 = require("nunjucks");
9
+ const dirname_cjs_1 = __importDefault(require("./dirname.cjs"));
10
+ const CasaTemplateLoader_js_1 = __importDefault(require("./CasaTemplateLoader.js"));
11
+ const nunjucks_filters_js_1 = require("./nunjucks-filters.js");
12
+ /**
13
+ * @typedef {Object} NunjucksOptions
14
+ * @property {string} [mountUrl=/] Mount URL. This i made available as a `casa.mountUrl` template variable (optional, default /)
15
+ * @property {string[]} [views=[]] List of directories to look for template files (optional, default [])
16
+ */
17
+ /**
18
+ * Create a Nunjucks environment.
19
+ *
20
+ * @param {NunjucksOptions} options Nunjucks options
21
+ * @returns {nunjucks.Environment} Nunjucks Environment instance
22
+ */
23
+ function default_1({ mountUrl = '/', views = [], }) {
24
+ // Prepare a single Nunjucks environment for all responses to use. Note that
25
+ // we cannot prepare response-specific global functions/filters if we use a
26
+ // single environment, but the performance gains of doing so are significant.
27
+ const loader = new CasaTemplateLoader_js_1.default(views, {
28
+ watch: false,
29
+ noCache: false,
30
+ });
31
+ const env = new nunjucks_1.Environment(loader, {
32
+ autoescape: true,
33
+ throwOnUndefined: false,
34
+ trimBlocks: false,
35
+ lstripBlocks: false,
36
+ });
37
+ // Enhancement to expose loader functions
38
+ env.modifyBlock = loader.modifyBlock.bind(loader);
39
+ // Globals
40
+ // These can't be modified once set. But they can be overridden by res.locals.
41
+ env.addGlobal('assetPath', `${mountUrl}govuk/assets`); // Required by govuk-frontend layout template
42
+ env.addGlobal('casaVersion', JSON.parse((0, fs_1.readFileSync)((0, path_1.resolve)(dirname_cjs_1.default, '../../package.json'))).version);
43
+ env.addGlobal('mergeObjects', nunjucks_filters_js_1.mergeObjects);
44
+ env.addGlobal('includes', nunjucks_filters_js_1.includes);
45
+ env.addGlobal('formatDateObject', nunjucks_filters_js_1.formatDateObject);
46
+ env.addGlobal('renderAsAttributes', nunjucks_filters_js_1.renderAsAttributes);
47
+ return env;
48
+ }
49
+ exports.default = default_1;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Test is a value can be stringifed (numbers or strings)
3
+ *
4
+ * @param {any} value Item to test
5
+ * @returns {boolean} Whether the value is stringable or not
6
+ */
7
+ export function isStringable(value: any): boolean;
8
+ /**
9
+ * Coerce an input to a string.
10
+ *
11
+ * @param {any} input Input to be stringified
12
+ * @param {string} fallback Fallback to use if input can't be stringified
13
+ * @returns {string} The stringified input
14
+ */
15
+ export function stringifyInput(input: any, fallback: string, ...args: any[]): string;
16
+ /**
17
+ * Determine if value is empty. Recurse over objects.
18
+ *
19
+ * @param {any} val Value to check
20
+ * @returns {boolean} True if the object is empty
21
+ */
22
+ export function isEmpty(val: any): boolean;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEmpty = exports.stringifyInput = exports.isStringable = void 0;
4
+ /**
5
+ * Test is a value can be stringifed (numbers or strings)
6
+ *
7
+ * @param {any} value Item to test
8
+ * @returns {boolean} Whether the value is stringable or not
9
+ */
10
+ function isStringable(value) {
11
+ return typeof value === 'string' || typeof value === 'number';
12
+ }
13
+ exports.isStringable = isStringable;
14
+ /**
15
+ * Coerce an input to a string.
16
+ *
17
+ * @param {any} input Input to be stringified
18
+ * @param {string} fallback Fallback to use if input can't be stringified
19
+ * @returns {string} The stringified input
20
+ */
21
+ function stringifyInput(input, fallback) {
22
+ // Not using param defaults here as the fallback may be explicitly "undefined"
23
+ const fb = arguments.length === 2 && (isStringable(fallback) || fallback === undefined) ? fallback : '';
24
+ return isStringable(input) ? String(input) : fb;
25
+ }
26
+ exports.stringifyInput = stringifyInput;
27
+ /**
28
+ * Determine if value is empty. Recurse over objects.
29
+ *
30
+ * @param {any} val Value to check
31
+ * @returns {boolean} True if the object is empty
32
+ */
33
+ function isEmpty(val) {
34
+ if (val === null
35
+ || typeof val === 'undefined'
36
+ || (typeof val === 'string' && val === '')) {
37
+ return true;
38
+ }
39
+ if (Array.isArray(val) || typeof val === 'object') {
40
+ return Object.keys(val).filter((k) => !isEmpty(val[k])).length === 0;
41
+ }
42
+ return false;
43
+ }
44
+ exports.isEmpty = isEmpty;
@@ -0,0 +1,4 @@
1
+ export default class DateObject extends ValidatorFactory {
2
+ name: string;
3
+ }
4
+ import ValidatorFactory from "../ValidatorFactory.js";
@@ -0,0 +1,135 @@
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
+ * Date object format:
9
+ * {
10
+ * dd: <string>,
11
+ * mm: <string>,
12
+ * yyyy: <string>
13
+ * }.
14
+ *
15
+ * Note that the time part of any injected "DateTime" objects will be zero'ed, as
16
+ * we are only interested in the date component (minimum day resolution).
17
+ *
18
+ * Config options:
19
+ * string|object errorMsg = Error message to use on validation failure
20
+ * object|luxon.Duration afterOffsetFromNow = Date must be after offset from now
21
+ * string|object errorMsgAfterOffset = Error for afterOffsetFromNow failure
22
+ * object|luxon.Duration beforeOffsetFromNow = Date must be before offset from now
23
+ * string|object errorMsgBeforeOffset = Error for beforeOffsetFromNow failure
24
+ * bool allowMonthNames = Allow "Jan", "January", etc (default = false)
25
+ * bool allowSingleDigitDay = Allow "1" rather than "01" (default = false)
26
+ * bool allowSingleDigitMonth = Allow "1" rather than "01" (default = false)
27
+ * luxon.DateTime now = Override the notion of "now" (useful for testing)
28
+ */
29
+ const luxon_1 = require("luxon");
30
+ const ValidationError_js_1 = __importDefault(require("../ValidationError.js"));
31
+ const ValidatorFactory_js_1 = __importDefault(require("../ValidatorFactory.js"));
32
+ const utils_js_1 = require("../utils.js");
33
+ const lodash_1 = __importDefault(require("lodash"));
34
+ const { isPlainObject } = lodash_1.default;
35
+ class DateObject extends ValidatorFactory_js_1.default {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.name = 'dateObject';
39
+ }
40
+ validate(value, dataContext = {}) {
41
+ const config = Object.assign({ errorMsg: {
42
+ inline: 'validation:rule.dateObject.inline',
43
+ summary: 'validation:rule.dateObject.summary',
44
+ }, errorMsgAfterOffset: {
45
+ inline: 'validation:rule.dateObject.afterOffset.inline',
46
+ summary: 'validation:rule.dateObject.afterOffset.summary',
47
+ }, errorMsgBeforeOffset: {
48
+ inline: 'validation:rule.dateObject.beforeOffset.inline',
49
+ summary: 'validation:rule.dateObject.beforeOffset.summary',
50
+ }, now: luxon_1.DateTime.local(), allowSingleDigitDay: false, allowSingleDigitMonth: false, allowMonthNames: false, afterOffsetFromNow: undefined, beforeOffsetFromNow: undefined }, this.config);
51
+ let valid = false;
52
+ let { errorMsg } = config;
53
+ let luxonDate;
54
+ const NOW = config.now.startOf('day');
55
+ // Accepted formats
56
+ let formats = ['dd-MM-yyyy'];
57
+ const formatTests = [{
58
+ flags: [config.allowSingleDigitDay],
59
+ formats: ['d-MM-yyyy'],
60
+ }, {
61
+ flags: [config.allowSingleDigitDay, config.allowSingleDigitMonth],
62
+ formats: ['d-M-yyyy'],
63
+ }, {
64
+ flags: [config.allowSingleDigitDay, config.allowMonthNames],
65
+ formats: ['d-MMM-yyyy', 'd-MMMM-yyyy'],
66
+ }, {
67
+ flags: [config.allowSingleDigitMonth],
68
+ formats: ['dd-M-yyyy'],
69
+ }, {
70
+ flags: [config.allowMonthNames],
71
+ formats: ['dd-MMM-yyyy', 'dd-MMMM-yyyy'],
72
+ }];
73
+ formatTests.forEach((test) => {
74
+ if (test.flags.every((v) => v === true)) {
75
+ formats = [...formats, ...test.formats];
76
+ }
77
+ });
78
+ if (typeof value === 'object') {
79
+ formats.find((format) => {
80
+ luxonDate = luxon_1.DateTime.fromFormat([value.dd, value.mm, value.yyyy].join('-'), format).startOf('day');
81
+ valid = luxonDate.isValid;
82
+ return valid;
83
+ });
84
+ if (luxonDate) {
85
+ // Check date is after the specified duration from now.
86
+ // Need to use UTC() otherwise DST shifts can affect the calculated offset
87
+ if (config.afterOffsetFromNow) {
88
+ const offsetDate = NOW.plus(config.afterOffsetFromNow).startOf('day');
89
+ if (luxonDate <= offsetDate) {
90
+ valid = false;
91
+ errorMsg = config.errorMsgAfterOffset;
92
+ }
93
+ }
94
+ // Check date is before the specified duration from now
95
+ // Need to use UTC() otherwise DST shifts can affect the calculated offset
96
+ if (config.beforeOffsetFromNow) {
97
+ const offsetDate = NOW.plus(config.beforeOffsetFromNow).startOf('day');
98
+ if (luxonDate >= offsetDate) {
99
+ valid = false;
100
+ errorMsg = config.errorMsgBeforeOffset;
101
+ }
102
+ }
103
+ }
104
+ // Check presence of each object component (dd, mm, yyyy) in order to log
105
+ // which specific parts are in error
106
+ errorMsg.focusSuffix = [];
107
+ if (!Object.prototype.hasOwnProperty.call(value, 'dd') || !value.dd) {
108
+ errorMsg.focusSuffix.push('[dd]');
109
+ }
110
+ if (!Object.prototype.hasOwnProperty.call(value, 'mm') || !value.mm) {
111
+ errorMsg.focusSuffix.push('[mm]');
112
+ }
113
+ if (!Object.prototype.hasOwnProperty.call(value, 'yyyy') || !value.yyyy) {
114
+ errorMsg.focusSuffix.push('[yyyy]');
115
+ }
116
+ // If the date is invalid, but not specific parts have been highighted in
117
+ // error, then highlight all inputs, focusing on the [dd] first
118
+ if (!valid && !errorMsg.focusSuffix.length) {
119
+ errorMsg.focusSuffix = ['[dd]', '[mm]', '[yyyy]'];
120
+ }
121
+ }
122
+ return valid ? [] : [ValidationError_js_1.default.make({ errorMsg, dataContext })];
123
+ }
124
+ sanitise(value) {
125
+ if (value !== undefined) {
126
+ return isPlainObject(value) ? {
127
+ dd: (0, utils_js_1.stringifyInput)(value.dd),
128
+ mm: (0, utils_js_1.stringifyInput)(value.mm),
129
+ yyyy: (0, utils_js_1.stringifyInput)(value.yyyy),
130
+ } : Object.create(null);
131
+ }
132
+ return undefined;
133
+ }
134
+ }
135
+ exports.default = DateObject;