@defra/forms-engine-plugin 4.9.2 → 4.11.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 (69) hide show
  1. package/.public/javascripts/shared.min.js +1 -1
  2. package/.public/javascripts/shared.min.js.map +1 -1
  3. package/.server/client/javascripts/geospatial-map.js +34 -3
  4. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  5. package/.server/client/javascripts/map.d.ts +0 -6
  6. package/.server/client/javascripts/map.js +1 -14
  7. package/.server/client/javascripts/map.js.map +1 -1
  8. package/.server/index.js +1 -2
  9. package/.server/index.js.map +1 -1
  10. package/.server/server/common/helpers/logging/logger.d.ts +1 -1
  11. package/.server/server/common/helpers/logging/logger.js +5 -1
  12. package/.server/server/common/helpers/logging/logger.js.map +1 -1
  13. package/.server/server/common/helpers/redis-client.js +1 -2
  14. package/.server/server/common/helpers/redis-client.js.map +1 -1
  15. package/.server/server/plugins/engine/components/GeospatialField.d.ts +1 -0
  16. package/.server/server/plugins/engine/components/GeospatialField.js +6 -2
  17. package/.server/server/plugins/engine/components/GeospatialField.js.map +1 -1
  18. package/.server/server/plugins/engine/components/PaymentField.js +1 -2
  19. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  20. package/.server/server/plugins/engine/components/helpers/geospatial.d.ts +2 -1
  21. package/.server/server/plugins/engine/components/helpers/geospatial.js +32 -1
  22. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
  23. package/.server/server/plugins/engine/components/helpers/geospatial.test.js +21 -1
  24. package/.server/server/plugins/engine/components/helpers/geospatial.test.js.map +1 -1
  25. package/.server/server/plugins/engine/helpers.js +1 -2
  26. package/.server/server/plugins/engine/helpers.js.map +1 -1
  27. package/.server/server/plugins/engine/models/FormModel.js +1 -2
  28. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  29. package/.server/server/plugins/engine/options.js +1 -2
  30. package/.server/server/plugins/engine/options.js.map +1 -1
  31. package/.server/server/plugins/engine/routes/payment.js +1 -2
  32. package/.server/server/plugins/engine/routes/payment.js.map +1 -1
  33. package/.server/server/plugins/engine/views/components/geospatialfield.html +1 -1
  34. package/.server/server/plugins/map/routes/index.d.ts +9 -1
  35. package/.server/server/plugins/map/routes/index.js +51 -2
  36. package/.server/server/plugins/map/routes/index.js.map +1 -1
  37. package/.server/server/plugins/map/routes/vts/countries.geojson +39285 -0
  38. package/.server/server/plugins/map/service.js +1 -2
  39. package/.server/server/plugins/map/service.js.map +1 -1
  40. package/.server/server/plugins/map/types.d.ts +23 -1
  41. package/.server/server/plugins/map/types.js +14 -1
  42. package/.server/server/plugins/map/types.js.map +1 -1
  43. package/.server/server/plugins/nunjucks/context.js +1 -2
  44. package/.server/server/plugins/nunjucks/context.js.map +1 -1
  45. package/.server/server/plugins/payment/service.js +1 -2
  46. package/.server/server/plugins/payment/service.js.map +1 -1
  47. package/.server/server/plugins/postcode-lookup/service.js +1 -2
  48. package/.server/server/plugins/postcode-lookup/service.js.map +1 -1
  49. package/package.json +10 -8
  50. package/src/client/javascripts/geospatial-map.js +39 -3
  51. package/src/client/javascripts/map.js +1 -14
  52. package/src/index.ts +1 -3
  53. package/src/server/common/helpers/logging/logger.ts +5 -1
  54. package/src/server/common/helpers/redis-client.js +1 -3
  55. package/src/server/plugins/engine/components/GeospatialField.ts +8 -2
  56. package/src/server/plugins/engine/components/PaymentField.ts +1 -3
  57. package/src/server/plugins/engine/components/helpers/geospatial.ts +48 -2
  58. package/src/server/plugins/engine/helpers.ts +1 -3
  59. package/src/server/plugins/engine/models/FormModel.ts +1 -3
  60. package/src/server/plugins/engine/options.js +1 -3
  61. package/src/server/plugins/engine/routes/payment.js +1 -3
  62. package/src/server/plugins/engine/views/components/geospatialfield.html +1 -1
  63. package/src/server/plugins/map/routes/index.js +58 -2
  64. package/src/server/plugins/map/routes/vts/countries.geojson +39285 -0
  65. package/src/server/plugins/map/service.js +1 -3
  66. package/src/server/plugins/map/types.js +14 -1
  67. package/src/server/plugins/nunjucks/context.js +1 -3
  68. package/src/server/plugins/payment/service.js +1 -3
  69. package/src/server/plugins/postcode-lookup/service.js +1 -3
@@ -1,5 +1,10 @@
1
+ import {
2
+ GeospatialFieldOptionsCountryEnum,
3
+ type GeospatialFieldOptionsCountry
4
+ } from '@defra/forms-model'
1
5
  import Bourne from '@hapi/bourne'
2
- import JoiBase from 'joi'
6
+ import { booleanWithin } from '@turf/boolean-within'
7
+ import JoiBase, { type CustomValidator } from 'joi'
3
8
 
4
9
  import {
5
10
  type Coordinates,
@@ -7,6 +12,14 @@ import {
7
12
  type FeatureProperties,
8
13
  type Geometry
9
14
  } from '../../types.js'
15
+ import { countries } from '../../../map/routes/index.js'
16
+
17
+ const countriesDesc: Record<GeospatialFieldOptionsCountryEnum, string> = {
18
+ [GeospatialFieldOptionsCountryEnum.England]: 'England',
19
+ [GeospatialFieldOptionsCountryEnum.NorthernIreland]: 'Northern Ireland',
20
+ [GeospatialFieldOptionsCountryEnum.Scotland]: 'Scotland',
21
+ [GeospatialFieldOptionsCountryEnum.Wales]: 'Wales'
22
+ }
10
23
 
11
24
  const Joi = JoiBase.extend({
12
25
  type: 'array',
@@ -83,11 +96,44 @@ const featureSchema = Joi.object<Feature>().keys({
83
96
  geometry: featureGeometrySchema
84
97
  })
85
98
 
86
- export const geospatialSchema = Joi.array<Feature[]>()
99
+ const geospatialSchema = Joi.array<Feature[]>()
87
100
  .items(featureSchema)
88
101
  .unique('id')
89
102
  .required()
90
103
 
104
+ export function getGeospatialSchema(country?: GeospatialFieldOptionsCountry) {
105
+ if (!country) {
106
+ return geospatialSchema
107
+ }
108
+
109
+ const validateCountryBounds: CustomValidator = (value, helpers) => {
110
+ const countryFeature = countries.features.find(
111
+ (feature) => feature.id === country
112
+ )
113
+
114
+ if (!countryFeature) {
115
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
116
+ return value
117
+ }
118
+
119
+ const result = booleanWithin(value, countryFeature)
120
+
121
+ if (!result) {
122
+ return helpers.error('any.custom', {
123
+ country: countriesDesc[country as GeospatialFieldOptionsCountryEnum]
124
+ })
125
+ }
126
+
127
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
128
+ return value
129
+ }
130
+
131
+ return Joi.array<Feature[]>()
132
+ .items(featureSchema.custom(validateCountryBounds))
133
+ .unique('id')
134
+ .required()
135
+ }
136
+
91
137
  /**
92
138
  * @import { CustomHelpers } from 'joi'
93
139
  */
@@ -15,7 +15,7 @@ import { StatusCodes } from 'http-status-codes'
15
15
  import { type Schema, type ValidationErrorItem } from 'joi'
16
16
  import { Liquid } from 'liquidjs'
17
17
 
18
- import { createLogger } from '../../common/helpers/logging/logger.js'
18
+ import { logger } from '../../common/helpers/logging/logger.js'
19
19
  import { FORM_VERSION_METADATA_KEY } from '../../constants.js'
20
20
  import {
21
21
  getAnswer,
@@ -37,8 +37,6 @@ import {
37
37
  type FormResponseToolkit
38
38
  } from '../../routes/types.js'
39
39
 
40
- const logger = createLogger()
41
-
42
40
  export const engine = new Liquid({
43
41
  outputEscape: 'escape',
44
42
  jsTruthy: true,
@@ -28,7 +28,7 @@ import { add, format } from 'date-fns'
28
28
  import { Parser, type Value } from 'expr-eval-fork'
29
29
  import joi from 'joi'
30
30
 
31
- import { createLogger } from '../../../common/helpers/logging/logger.js'
31
+ import { logger } from '../../../common/helpers/logging/logger.js'
32
32
  import { type ListFormComponent } from '../components/ListFormComponent.js'
33
33
  import {} from '../components/YesNoField.js'
34
34
  import {
@@ -61,8 +61,6 @@ import { FormAction } from '../../../routes/types.js'
61
61
  import { merge } from '../../../services/cacheService.js'
62
62
  import { type Services } from '../../../types.js'
63
63
 
64
- const logger = createLogger()
65
-
66
64
  export class FormModel {
67
65
  /** The runtime engine that should be used */
68
66
  engine?: Engine
@@ -1,11 +1,9 @@
1
1
  import { getErrorMessage } from '@defra/forms-model'
2
2
  import Joi from 'joi'
3
3
 
4
- import { createLogger } from '../../common/helpers/logging/logger.js'
4
+ import { logger } from '../../common/helpers/logging/logger.js'
5
5
  import { CacheService } from '../../services/index.js'
6
6
 
7
- const logger = createLogger()
8
-
9
7
  const pluginRegistrationOptionsSchema = Joi.object({
10
8
  model: Joi.object().optional(),
11
9
  services: Joi.object().optional(),
@@ -2,7 +2,7 @@ import Boom from '@hapi/boom'
2
2
  import { StatusCodes } from 'http-status-codes'
3
3
  import Joi from 'joi'
4
4
 
5
- import { createLogger } from '../../../common/helpers/logging/logger.js'
5
+ import { logger } from '../../../common/helpers/logging/logger.js'
6
6
  import { EXTERNAL_STATE_APPENDAGE } from '../../../constants.js'
7
7
  import { getPluginOptions } from '../helpers.js'
8
8
  import {
@@ -14,8 +14,6 @@ import {
14
14
  export const PAYMENT_RETURN_PATH = '/payment-callback'
15
15
  export const PAYMENT_SESSION_PREFIX = 'payment-'
16
16
 
17
- const logger = createLogger()
18
-
19
17
  /**
20
18
  * Flash form component state after successful payment
21
19
  * @param {Request} request - the request
@@ -1,7 +1,7 @@
1
1
  {% from "govuk/components/textarea/macro.njk" import govukTextarea %}
2
2
 
3
3
  {% macro GeospatialField(component) %}
4
- <div class="app-geospatial-field">
4
+ <div class="app-geospatial-field" data-country="{{component.model.country}}">
5
5
  {{ govukTextarea(component.model) }}
6
6
  </div>
7
7
  {% endmacro %}
@@ -1,5 +1,7 @@
1
+ import fs from 'node:fs'
1
2
  import { resolve } from 'node:path'
2
3
 
4
+ import { GeospatialFieldOptionsCountryEnum } from '@defra/forms-model'
3
5
  import { StatusCodes } from 'http-status-codes'
4
6
  import Joi from 'joi'
5
7
 
@@ -10,6 +12,18 @@ import {
10
12
  request as httpRequest
11
13
  } from '../../../services/httpService.js'
12
14
 
15
+ const filePath = resolve(import.meta.dirname, './vts/countries.geojson')
16
+
17
+ /**
18
+ * @type {FeatureCollection}
19
+ */
20
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
21
+ export const countries = JSON.parse(fs.readFileSync(filePath, 'utf8'))
22
+
23
+ export const countrySchema = Joi.string().valid(
24
+ ...Object.values(GeospatialFieldOptionsCountryEnum)
25
+ )
26
+
13
27
  /**
14
28
  * Gets the map support routes
15
29
  * @param {MapConfiguration} options - ordnance survey names api key
@@ -20,7 +34,8 @@ export function getRoutes(options) {
20
34
  mapProxyRoute(options),
21
35
  tileProxyRoute(options),
22
36
  geocodeProxyRoute(options),
23
- reverseGeocodeProxyRoute(options)
37
+ reverseGeocodeProxyRoute(options),
38
+ getGeospatialCountries()
24
39
  ]
25
40
  }
26
41
 
@@ -188,7 +203,48 @@ function mapStyleResourceRoutes() {
188
203
  }
189
204
  }
190
205
 
206
+ /**
207
+ * Resource routes to return sprites and glyphs
208
+ * @returns {ServerRoute<GeospatialCountriesGetRequestRefs>}
209
+ */
210
+ function getGeospatialCountries() {
211
+ return {
212
+ method: 'GET',
213
+ path: '/api/maps/countries.geojson',
214
+ handler: (request) => {
215
+ const { omit, only } = request.query
216
+
217
+ if (omit) {
218
+ return {
219
+ ...countries,
220
+ features: countries.features.filter((feature) => feature.id !== omit)
221
+ }
222
+ }
223
+
224
+ if (only) {
225
+ return {
226
+ ...countries,
227
+ features: countries.features.filter((feature) => feature.id === only)
228
+ }
229
+ }
230
+
231
+ return countries
232
+ },
233
+ options: {
234
+ validate: {
235
+ query: Joi.object()
236
+ .keys({
237
+ omit: countrySchema.optional(),
238
+ only: countrySchema.optional()
239
+ })
240
+ .optional()
241
+ }
242
+ }
243
+ }
244
+ }
245
+
191
246
  /**
192
247
  * @import { ServerRoute } from '@hapi/hapi'
193
- * @import { MapConfiguration, MapProxyGetRequestRefs, MapGeocodeGetRequestRefs, MapReverseGeocodeGetRequestRefs } from '../types.js'
248
+ * @import { FeatureCollection } from 'geojson'
249
+ * @import { MapConfiguration, MapProxyGetRequestRefs, MapGeocodeGetRequestRefs, MapReverseGeocodeGetRequestRefs, GeospatialCountriesGetRequestRefs } from '../types.js'
194
250
  */