@dwp/govuk-casa 8.7.9 → 8.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.md +0 -5
  2. package/dist/casa.d.ts +1 -1
  3. package/dist/casa.js +3 -2
  4. package/dist/casa.js.map +1 -0
  5. package/dist/lib/CasaTemplateLoader.d.ts +1 -7
  6. package/dist/lib/CasaTemplateLoader.js +6 -1
  7. package/dist/lib/CasaTemplateLoader.js.map +1 -0
  8. package/dist/lib/JourneyContext.d.ts +1 -1
  9. package/dist/lib/JourneyContext.js +2 -1
  10. package/dist/lib/JourneyContext.js.map +1 -0
  11. package/dist/lib/MutableRouter.js +1 -0
  12. package/dist/lib/MutableRouter.js.map +1 -0
  13. package/dist/lib/Plan.d.ts +2 -0
  14. package/dist/lib/Plan.js +9 -4
  15. package/dist/lib/Plan.js.map +1 -0
  16. package/dist/lib/ValidationError.js +2 -1
  17. package/dist/lib/ValidationError.js.map +1 -0
  18. package/dist/lib/ValidatorFactory.d.ts +2 -2
  19. package/dist/lib/ValidatorFactory.js +3 -2
  20. package/dist/lib/ValidatorFactory.js.map +1 -0
  21. package/dist/lib/configuration-ingestor.d.ts +1 -1
  22. package/dist/lib/configuration-ingestor.js +2 -1
  23. package/dist/lib/configuration-ingestor.js.map +1 -0
  24. package/dist/lib/configure.js +2 -1
  25. package/dist/lib/configure.js.map +1 -0
  26. package/dist/lib/end-session.js +1 -0
  27. package/dist/lib/end-session.js.map +1 -0
  28. package/dist/lib/field.js +1 -0
  29. package/dist/lib/field.js.map +1 -0
  30. package/dist/lib/index.js +1 -0
  31. package/dist/lib/index.js.map +1 -0
  32. package/dist/lib/logger.js +1 -0
  33. package/dist/lib/logger.js.map +1 -0
  34. package/dist/lib/mount.js +3 -2
  35. package/dist/lib/mount.js.map +1 -0
  36. package/dist/lib/nunjucks-filters.js +28 -1
  37. package/dist/lib/nunjucks-filters.js.map +1 -0
  38. package/dist/lib/nunjucks.js +1 -0
  39. package/dist/lib/nunjucks.js.map +1 -0
  40. package/dist/lib/utils.d.ts +46 -28
  41. package/dist/lib/utils.js +105 -67
  42. package/dist/lib/utils.js.map +1 -0
  43. package/dist/lib/validators/dateObject.js +5 -4
  44. package/dist/lib/validators/dateObject.js.map +1 -0
  45. package/dist/lib/validators/email.js +1 -0
  46. package/dist/lib/validators/email.js.map +1 -0
  47. package/dist/lib/validators/inArray.js +1 -0
  48. package/dist/lib/validators/inArray.js.map +1 -0
  49. package/dist/lib/validators/index.js +1 -0
  50. package/dist/lib/validators/index.js.map +1 -0
  51. package/dist/lib/validators/nino.js +1 -0
  52. package/dist/lib/validators/nino.js.map +1 -0
  53. package/dist/lib/validators/postalAddressObject.d.ts +2 -2
  54. package/dist/lib/validators/postalAddressObject.js +2 -1
  55. package/dist/lib/validators/postalAddressObject.js.map +1 -0
  56. package/dist/lib/validators/regex.js +1 -0
  57. package/dist/lib/validators/regex.js.map +1 -0
  58. package/dist/lib/validators/required.d.ts +1 -1
  59. package/dist/lib/validators/required.js +2 -1
  60. package/dist/lib/validators/required.js.map +1 -0
  61. package/dist/lib/validators/strlen.js +1 -0
  62. package/dist/lib/validators/strlen.js.map +1 -0
  63. package/dist/lib/validators/wordCount.js +1 -0
  64. package/dist/lib/validators/wordCount.js.map +1 -0
  65. package/dist/lib/waypoint-url.js +1 -0
  66. package/dist/lib/waypoint-url.js.map +1 -0
  67. package/dist/middleware/body-parser.js +1 -0
  68. package/dist/middleware/body-parser.js.map +1 -0
  69. package/dist/middleware/csrf.js +1 -0
  70. package/dist/middleware/csrf.js.map +1 -0
  71. package/dist/middleware/data.js +1 -0
  72. package/dist/middleware/data.js.map +1 -0
  73. package/dist/middleware/gather-fields.js +2 -1
  74. package/dist/middleware/gather-fields.js.map +1 -0
  75. package/dist/middleware/i18n.js +1 -0
  76. package/dist/middleware/i18n.js.map +1 -0
  77. package/dist/middleware/post.js +1 -0
  78. package/dist/middleware/post.js.map +1 -0
  79. package/dist/middleware/pre.js +1 -0
  80. package/dist/middleware/pre.js.map +1 -0
  81. package/dist/middleware/progress-journey.js +1 -0
  82. package/dist/middleware/progress-journey.js.map +1 -0
  83. package/dist/middleware/sanitise-fields.js +1 -0
  84. package/dist/middleware/sanitise-fields.js.map +1 -0
  85. package/dist/middleware/serve-first-waypoint.js +1 -0
  86. package/dist/middleware/serve-first-waypoint.js.map +1 -0
  87. package/dist/middleware/session.js +1 -0
  88. package/dist/middleware/session.js.map +1 -0
  89. package/dist/middleware/skip-waypoint.js +1 -0
  90. package/dist/middleware/skip-waypoint.js.map +1 -0
  91. package/dist/middleware/steer-journey.js +1 -0
  92. package/dist/middleware/steer-journey.js.map +1 -0
  93. package/dist/middleware/strip-proxy-path.js +2 -1
  94. package/dist/middleware/strip-proxy-path.js.map +1 -0
  95. package/dist/middleware/validate-fields.js +2 -1
  96. package/dist/middleware/validate-fields.js.map +1 -0
  97. package/dist/mjs/esm-wrapper.js +10 -15
  98. package/dist/routes/ancillary.js +1 -0
  99. package/dist/routes/ancillary.js.map +1 -0
  100. package/dist/routes/journey.js +1 -0
  101. package/dist/routes/journey.js.map +1 -0
  102. package/dist/routes/static.js +1 -0
  103. package/dist/routes/static.js.map +1 -0
  104. package/locales/cy/error.json +1 -1
  105. package/locales/en/error.json +1 -1
  106. package/package.json +20 -19
  107. package/src/casa.js +320 -0
  108. package/src/lib/CasaTemplateLoader.js +104 -0
  109. package/src/lib/JourneyContext.js +783 -0
  110. package/src/lib/MutableRouter.js +310 -0
  111. package/src/lib/Plan.js +624 -0
  112. package/src/lib/ValidationError.js +163 -0
  113. package/src/lib/ValidatorFactory.js +105 -0
  114. package/src/lib/configuration-ingestor.js +457 -0
  115. package/src/lib/configure.js +202 -0
  116. package/src/lib/dirname.cjs +1 -0
  117. package/src/lib/end-session.js +45 -0
  118. package/src/lib/field.js +456 -0
  119. package/src/lib/index.js +33 -0
  120. package/src/lib/logger.js +16 -0
  121. package/src/lib/mount.js +127 -0
  122. package/src/lib/nunjucks-filters.js +150 -0
  123. package/src/lib/nunjucks.js +53 -0
  124. package/src/lib/utils.js +232 -0
  125. package/src/lib/validators/dateObject.js +169 -0
  126. package/src/lib/validators/email.js +55 -0
  127. package/src/lib/validators/inArray.js +81 -0
  128. package/src/lib/validators/index.js +24 -0
  129. package/src/lib/validators/nino.js +57 -0
  130. package/src/lib/validators/postalAddressObject.js +162 -0
  131. package/src/lib/validators/regex.js +48 -0
  132. package/src/lib/validators/required.js +74 -0
  133. package/src/lib/validators/strlen.js +66 -0
  134. package/src/lib/validators/wordCount.js +70 -0
  135. package/src/lib/waypoint-url.js +93 -0
  136. package/src/middleware/body-parser.js +31 -0
  137. package/src/middleware/csrf.js +29 -0
  138. package/src/middleware/data.js +105 -0
  139. package/src/middleware/dirname.cjs +1 -0
  140. package/src/middleware/gather-fields.js +51 -0
  141. package/src/middleware/i18n.js +106 -0
  142. package/src/middleware/post.js +61 -0
  143. package/src/middleware/pre.js +91 -0
  144. package/src/middleware/progress-journey.js +92 -0
  145. package/src/middleware/sanitise-fields.js +58 -0
  146. package/src/middleware/serve-first-waypoint.js +28 -0
  147. package/src/middleware/session.js +129 -0
  148. package/src/middleware/skip-waypoint.js +46 -0
  149. package/src/middleware/steer-journey.js +78 -0
  150. package/src/middleware/strip-proxy-path.js +56 -0
  151. package/src/middleware/validate-fields.js +84 -0
  152. package/src/routes/ancillary.js +29 -0
  153. package/src/routes/dirname.cjs +1 -0
  154. package/src/routes/journey.js +212 -0
  155. package/src/routes/static.js +77 -0
  156. package/views/casa/components/character-count/README.md +10 -0
  157. package/views/casa/components/character-count/template.njk +6 -2
  158. package/views/casa/components/checkboxes/README.md +45 -37
  159. package/views/casa/components/checkboxes/template.njk +8 -7
  160. package/views/casa/components/date-input/README.md +15 -3
  161. package/views/casa/components/date-input/template.njk +6 -4
  162. package/views/casa/components/input/README.md +9 -0
  163. package/views/casa/components/input/template.njk +6 -2
  164. package/views/casa/components/journey-form/README.md +3 -2
  165. package/views/casa/components/postal-address-object/README.md +10 -0
  166. package/views/casa/components/postal-address-object/template.njk +20 -5
  167. package/views/casa/components/radios/README.md +51 -26
  168. package/views/casa/components/radios/template.njk +6 -3
  169. package/views/casa/components/select/README.md +65 -0
  170. package/views/casa/components/select/macro.njk +3 -0
  171. package/views/casa/components/select/template.njk +49 -0
  172. package/views/casa/components/textarea/README.md +9 -0
  173. package/views/casa/components/textarea/template.njk +6 -2
  174. package/views/casa/layouts/journey.njk +1 -1
  175. package/views/casa/layouts/main.njk +1 -1
@@ -0,0 +1,163 @@
1
+ import lodash from 'lodash';
2
+
3
+ const { isPlainObject } = lodash; // CommonJS
4
+
5
+ const params = new WeakMap();
6
+
7
+ /**
8
+ * @access private
9
+ * @typedef {import('../casa').ValidateContext} ValidateContext
10
+ */
11
+
12
+ /**
13
+ * @access private
14
+ * @typedef {import('../casa').ErrorMessageConfig} ErrorMessageConfig
15
+ */
16
+
17
+ /**
18
+ * @access private
19
+ * @typedef {import('../casa').ErrorMessageConfigObject} ErrorMessageConfigObject
20
+ */
21
+
22
+ /**
23
+ * @class
24
+ * @memberof module:@dwp/govuk-casa
25
+ */
26
+ export default class ValidationError {
27
+ /**
28
+ * Make a ValidationError instance from a primitive object (or a function that
29
+ * returns a primitive object) that is specific to the given journey context.
30
+ * <br/><br/>
31
+ *
32
+ * In the case of `errorMsg` being a function, this will be called at runtime,
33
+ * at the point that errors are generated within the `validate()`,
34
+ * methods, and will be passed the `dataContext`.
35
+ * <br/><br/>
36
+ *
37
+ * `dataContext` is an object containing the same data passed to all
38
+ * validators' `validate()` methods. In the case of `errorMsg` being
39
+ * a function, this data is passed to that function in order to help resolve to
40
+ * an error message config object.
41
+ *
42
+ * @param {object} args Arguments
43
+ * @param {ErrorMessageConfig} args.errorMsg Error message config to seed ValidationError
44
+ * @param {ValidateContext} [args.dataContext={}] Data for error msg function
45
+ * @returns {ValidationError} Error instance
46
+ * @throws {TypeError} If errorMsg is not in a valid type
47
+ */
48
+ static make({ errorMsg, dataContext = {} }) {
49
+ // Convert strings to the most basic object primitive
50
+ if (typeof errorMsg === 'string') {
51
+ return new ValidationError({
52
+ summary: errorMsg,
53
+ inline: errorMsg,
54
+ focusSuffix: [],
55
+ });
56
+ }
57
+
58
+ // No contextual changes applicable; return ValidationError made from the
59
+ // original object
60
+ if (isPlainObject(errorMsg)) {
61
+ return new ValidationError(errorMsg);
62
+ }
63
+
64
+ // Use the user-defined function to generate an error primitive for the
65
+ // given context
66
+ if (typeof errorMsg === 'function') {
67
+ return new ValidationError(errorMsg.call(null, { ...dataContext }));
68
+ }
69
+
70
+ // Core Error
71
+ if (errorMsg instanceof Error) {
72
+ return new ValidationError({
73
+ summary: errorMsg.message,
74
+ inline: errorMsg.message,
75
+ focusSuffix: errorMsg.focusSuffix || [],
76
+ });
77
+ }
78
+
79
+ // Unsupported
80
+ throw new TypeError('errorMsg must be a string, Error, primitive object or function that generates a primitive object');
81
+ }
82
+
83
+ /**
84
+ * Create a ValidationError.
85
+ *
86
+ * @param {string|ErrorMessageConfigObject} errorParam Error configuration
87
+ */
88
+ constructor(errorParam = {}) {
89
+ if (!isPlainObject(errorParam) && typeof errorParam !== 'string') {
90
+ throw new TypeError('Constructor requires a string or object');
91
+ }
92
+ const error = typeof errorParam === 'string' ? { summary: errorParam } : errorParam;
93
+
94
+ // Store parameters for later use in applying contexts
95
+ const originals = {
96
+ summary: error.summary,
97
+ // may be deprecated; summary and inline should always match
98
+ inline: error.inline || error.summary,
99
+ focusSuffix: error.focusSuffix || [],
100
+ fieldKeySuffix: error.fieldKeySuffix || undefined,
101
+ variables: error.variables || {},
102
+ message: error.summary,
103
+ field: error.field || undefined,
104
+ fieldHref: error.fieldHref || undefined,
105
+ validator: error.validator || undefined,
106
+ };
107
+ params.set(this, originals);
108
+
109
+ // Duplicate parameters to make them available in public scope. These are
110
+ // the values that will be readable, and reflect any context that may have
111
+ // been applied
112
+ Object.keys(originals).forEach((o) => {
113
+ // ESLint disabled as `o` is an "own" property of `originals`, which is
114
+ // dev-controlled
115
+ /* eslint-disable security/detect-object-injection */
116
+ Object.defineProperty(this, o, {
117
+ value: originals[o],
118
+ enumerable: true,
119
+ writable: true,
120
+ });
121
+ /* eslint-enable security/detect-object-injection */
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Modifies this instance to reflect the given validation context.
127
+ *
128
+ * @param {ValidateContext} context See structure above
129
+ * @returns {ValidationError} Chain
130
+ */
131
+ withContext(context) {
132
+ // Get original constructor parameters
133
+ const originals = params.get(this);
134
+
135
+ // Expand variables
136
+ if (typeof originals.variables === 'function') {
137
+ this.variables = originals.variables.call(this, context);
138
+ }
139
+
140
+ // Set field name
141
+ if (context.fieldName) {
142
+ let focusSuffix;
143
+ let fieldHref = `#f-${context.fieldName}`;
144
+ if (originals.fieldKeySuffix) {
145
+ fieldHref += originals.fieldKeySuffix;
146
+ } else if (originals.focusSuffix && originals.focusSuffix.length) {
147
+ focusSuffix = Array.isArray(originals.focusSuffix)
148
+ ? originals.focusSuffix
149
+ : [originals.focusSuffix];
150
+ fieldHref += focusSuffix[0];
151
+ }
152
+
153
+ this.field = context.fieldName + (originals.fieldKeySuffix || '');
154
+ this.fieldHref = fieldHref;
155
+ this.focusSuffix = focusSuffix || [];
156
+ }
157
+
158
+ // Set validator name
159
+ this.validator = context.validator || undefined;
160
+
161
+ return this;
162
+ }
163
+ }
@@ -0,0 +1,105 @@
1
+ /* eslint-disable class-methods-use-this */
2
+ import lodash from 'lodash';
3
+
4
+ const { isPlainObject } = lodash; // CommonJS
5
+
6
+ /**
7
+ * @access private
8
+ * @typedef {import('../casa').ErrorMessageConfig} ErrorMessageConfig
9
+ */
10
+
11
+ /**
12
+ * @access private
13
+ * @typedef {import('./index').JourneyContext} JourneyContext
14
+ */
15
+
16
+ /**
17
+ * @access private
18
+ * @typedef {import('./index').ValidationError} ValidationError
19
+ */
20
+
21
+ /**
22
+ * @access private
23
+ * @typedef {import('../casa').ValidateContext} ValidateContext
24
+ */
25
+
26
+ /**
27
+ * @access private
28
+ * @typedef {import('../casa').Validator} Validator
29
+ */
30
+
31
+ /**
32
+ * @typedef {Object<string, unknown>} ValidatorFactoryOptions
33
+ * @property {ErrorMessageConfig} errorMsg Error message
34
+ */
35
+
36
+ /**
37
+ * @class
38
+ * @memberof module:@dwp/govuk-casa
39
+ */
40
+ export default class ValidatorFactory {
41
+ /**
42
+ * This is a convenience method that will return a consistently object
43
+ * structure containing validation and sanitisation methods.
44
+ *
45
+ * @param {ValidatorFactoryOptions} config Validator config (custom to each validator)
46
+ * @returns {Validator} Validator object
47
+ * @throws {TypeError} When configuration is invalid.
48
+ */
49
+ static make(config = {}) {
50
+ if (!isPlainObject(config)) {
51
+ throw new TypeError('Configuration must be an object');
52
+ }
53
+
54
+ const validator = Reflect.construct(this, [config]);
55
+
56
+ /* eslint-disable-next-line sonarjs/prefer-object-literal */
57
+ const instance = {};
58
+ instance.name = validator.name || 'unknown';
59
+ instance.config = config;
60
+ instance.validate = validator.validate.bind(instance);
61
+ instance.sanitise = validator.sanitise.bind(instance);
62
+
63
+ Object.freeze(instance);
64
+
65
+ return instance;
66
+ }
67
+
68
+ /**
69
+ * NEVER CALL THIS DIRECTLY. USE `make()`.
70
+ *
71
+ * @param {ValidatorFactoryOptions} config Validator config (custom to each validator)
72
+ */
73
+ constructor(config = {}) {
74
+ if (new.target === ValidatorFactory) {
75
+ throw new TypeError('Cannot instantiate the abstract class, ValidatorFactory');
76
+ }
77
+ this.config = config;
78
+ }
79
+
80
+ /* eslint-disable no-unused-vars */
81
+
82
+ /* eslint-disable-next-line jsdoc/require-returns-check */
83
+ /**
84
+ * Validate the given value.
85
+ *
86
+ * @param {any} fieldValue Value to validate
87
+ * @param {ValidateContext} context Contextual information
88
+ * @returns {ValidationError[]} A list of errors (empty if no errors found)
89
+ * @throws {Error}
90
+ */
91
+ validate(fieldValue, context) {
92
+ throw new Error('validate() method has not been implemented');
93
+ }
94
+
95
+ /* eslint-disable-next-line jsdoc/require-returns-check */
96
+ /**
97
+ * Sanitise the given value.
98
+ *
99
+ * @param {any} fieldValue Value to validate
100
+ * @returns {any} The sanitised value
101
+ */
102
+ sanitise(fieldValue) {
103
+ return fieldValue;
104
+ }
105
+ }