@defra/forms-engine-plugin 4.0.0 → 4.0.1

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 (108) hide show
  1. package/.public/stylesheets/application.min.css +3 -3
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/application.scss +14 -0
  4. package/.server/config/index.d.ts +1 -0
  5. package/.server/config/index.js +7 -0
  6. package/.server/config/index.js.map +1 -1
  7. package/.server/index.js +6 -2
  8. package/.server/index.js.map +1 -1
  9. package/.server/server/constants.d.ts +2 -0
  10. package/.server/server/constants.js +2 -0
  11. package/.server/server/constants.js.map +1 -1
  12. package/.server/server/forms/components.json +7 -0
  13. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +18 -2
  14. package/.server/server/plugins/engine/components/UkAddressField.d.ts +15 -9
  15. package/.server/server/plugins/engine/components/UkAddressField.js +67 -6
  16. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  17. package/.server/server/plugins/engine/configureEnginePlugin.d.ts +1 -1
  18. package/.server/server/plugins/engine/configureEnginePlugin.js +6 -3
  19. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  20. package/.server/server/plugins/engine/models/FormModel.d.ts +2 -0
  21. package/.server/server/plugins/engine/models/FormModel.js +3 -1
  22. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  23. package/.server/server/plugins/engine/options.js +2 -1
  24. package/.server/server/plugins/engine/options.js.map +1 -1
  25. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -0
  26. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +46 -3
  27. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  28. package/.server/server/plugins/engine/plugin.js +13 -1
  29. package/.server/server/plugins/engine/plugin.js.map +1 -1
  30. package/.server/server/plugins/engine/routes/index.js +41 -3
  31. package/.server/server/plugins/engine/routes/index.js.map +1 -1
  32. package/.server/server/plugins/engine/types.d.ts +19 -1
  33. package/.server/server/plugins/engine/types.js.map +1 -1
  34. package/.server/server/plugins/engine/validationHelpers.d.ts +15 -0
  35. package/.server/server/plugins/engine/validationHelpers.js +29 -0
  36. package/.server/server/plugins/engine/validationHelpers.js.map +1 -0
  37. package/.server/server/plugins/engine/views/components/ukaddressfield.html +50 -6
  38. package/.server/server/plugins/engine/vision.js +3 -1
  39. package/.server/server/plugins/engine/vision.js.map +1 -1
  40. package/.server/server/plugins/postcode-lookup/index.d.ts +8 -0
  41. package/.server/server/plugins/postcode-lookup/index.js +21 -0
  42. package/.server/server/plugins/postcode-lookup/index.js.map +1 -0
  43. package/.server/server/plugins/postcode-lookup/models/index.d.ts +255 -0
  44. package/.server/server/plugins/postcode-lookup/models/index.js +517 -0
  45. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -0
  46. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +19 -0
  47. package/.server/server/plugins/postcode-lookup/routes/index.js +267 -0
  48. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -0
  49. package/.server/server/plugins/postcode-lookup/service.d.ts +26 -0
  50. package/.server/server/plugins/postcode-lookup/service.js +148 -0
  51. package/.server/server/plugins/postcode-lookup/service.js.map +1 -0
  52. package/.server/server/plugins/postcode-lookup/service.test.js +144 -0
  53. package/.server/server/plugins/postcode-lookup/service.test.js.map +1 -0
  54. package/.server/server/plugins/postcode-lookup/test/__stubs__/postcode.d.ts +282 -0
  55. package/.server/server/plugins/postcode-lookup/test/__stubs__/postcode.js +370 -0
  56. package/.server/server/plugins/postcode-lookup/test/__stubs__/postcode.js.map +1 -0
  57. package/.server/server/plugins/postcode-lookup/test/__stubs__/query.d.ts +131 -0
  58. package/.server/server/plugins/postcode-lookup/test/__stubs__/query.js +195 -0
  59. package/.server/server/plugins/postcode-lookup/test/__stubs__/query.js.map +1 -0
  60. package/.server/server/plugins/postcode-lookup/test/__stubs__/uprn.d.ts +51 -0
  61. package/.server/server/plugins/postcode-lookup/test/__stubs__/uprn.js +52 -0
  62. package/.server/server/plugins/postcode-lookup/test/__stubs__/uprn.js.map +1 -0
  63. package/.server/server/plugins/postcode-lookup/types.d.ts +204 -0
  64. package/.server/server/plugins/postcode-lookup/types.js +144 -0
  65. package/.server/server/plugins/postcode-lookup/types.js.map +1 -0
  66. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +83 -0
  67. package/.server/server/routes/types.d.ts +6 -1
  68. package/.server/server/routes/types.js +6 -0
  69. package/.server/server/routes/types.js.map +1 -1
  70. package/.server/server/schemas/index.js +1 -1
  71. package/.server/server/schemas/index.js.map +1 -1
  72. package/.server/server/types.d.ts +1 -0
  73. package/.server/server/types.js.map +1 -1
  74. package/package.json +2 -2
  75. package/src/client/stylesheets/application.scss +14 -0
  76. package/src/config/index.ts +9 -1
  77. package/src/index.ts +5 -4
  78. package/src/server/constants.js +2 -0
  79. package/src/server/forms/components.json +7 -0
  80. package/src/server/forms/register-as-a-unicorn-breeder.yaml +18 -2
  81. package/src/server/plugins/engine/components/UkAddressField.test.ts +50 -27
  82. package/src/server/plugins/engine/components/UkAddressField.ts +91 -8
  83. package/src/server/plugins/engine/configureEnginePlugin.ts +5 -3
  84. package/src/server/plugins/engine/models/FormModel.ts +10 -2
  85. package/src/server/plugins/engine/options.js +2 -1
  86. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +1 -0
  87. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +69 -1
  88. package/src/server/plugins/engine/plugin.ts +13 -1
  89. package/src/server/plugins/engine/routes/index.test.ts +1 -0
  90. package/src/server/plugins/engine/routes/index.ts +71 -3
  91. package/src/server/plugins/engine/types.ts +21 -1
  92. package/src/server/plugins/engine/validationHelpers.ts +48 -0
  93. package/src/server/plugins/engine/views/components/ukaddressfield.html +50 -6
  94. package/src/server/plugins/engine/vision.ts +6 -0
  95. package/src/server/plugins/postcode-lookup/index.js +21 -0
  96. package/src/server/plugins/postcode-lookup/models/index.js +549 -0
  97. package/src/server/plugins/postcode-lookup/routes/index.js +258 -0
  98. package/src/server/plugins/postcode-lookup/service.js +188 -0
  99. package/src/server/plugins/postcode-lookup/service.test.js +177 -0
  100. package/src/server/plugins/postcode-lookup/test/__stubs__/postcode.js +382 -0
  101. package/src/server/plugins/postcode-lookup/test/__stubs__/query.js +200 -0
  102. package/src/server/plugins/postcode-lookup/test/__stubs__/uprn.js +53 -0
  103. package/src/server/plugins/postcode-lookup/types.js +143 -0
  104. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +83 -0
  105. package/src/server/postcode-lookup.test.ts +64 -0
  106. package/src/server/routes/types.ts +7 -1
  107. package/src/server/schemas/index.ts +5 -7
  108. package/src/server/types.ts +1 -0
@@ -12,3 +12,17 @@
12
12
  .govuk-header__container {
13
13
  border-bottom: 10px solid #003d16;
14
14
  }
15
+
16
+ .app-hidden {
17
+ display: none;
18
+ visibility: hidden;
19
+ }
20
+
21
+ .govuk-button--link {
22
+ @extend %govuk-link;
23
+ color: $govuk-link-colour;
24
+ border: none;
25
+ cursor: pointer;
26
+ background-color: transparent;
27
+ @include govuk-font($size: 19);
28
+ }
@@ -41,4 +41,5 @@ export declare const config: convict.Config<{
41
41
  safelist: [string];
42
42
  stagingPrefix: string;
43
43
  submissionEmailAddress: string;
44
+ ordnanceSurveyApiKey: string | undefined;
44
45
  }>;
@@ -222,6 +222,13 @@ export const config = convict({
222
222
  format: String,
223
223
  default: '',
224
224
  env: 'SUBMISSION_EMAIL_ADDRESS'
225
+ },
226
+ ordnanceSurveyApiKey: {
227
+ doc: 'The ordnance survey api key use by the postcode lookup plugin',
228
+ format: String,
229
+ nullable: true,
230
+ default: undefined,
231
+ env: 'ORDNANCE_SURVEY_API_KEY'
225
232
  }
226
233
  });
227
234
  config.validate({
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["resolve","convict","isProduction","process","env","NODE_ENV","isDev","isTest","oneMinute","oneHour","config","appDir","format","String","default","import","meta","dirname","publicDir","port","doc","cdpEnvironment","enforceCsrf","Boolean","isDevelopment","serviceName","serviceVersion","nullable","feedbackLink","phaseTag","sessionTimeout","Number","confirmationSessionTimeout","sessionCookiePassword","sensitive","redis","host","username","password","keyPrefix","tracing","header","notifyTemplateId","notifyAPIKey","designerUrl","submissionUrl","uploaderUrl","uploaderBucketName","log","enabled","level","redact","Array","safelist","stagingPrefix","submissionEmailAddress","validate","allowed"],"sources":["../../src/config/index.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport convict, { type SchemaObj } from 'convict'\nimport { type LevelWithSilent } from 'pino'\n\nimport 'dotenv/config'\n\nconst isProduction = process.env.NODE_ENV === 'production'\nconst isDev = process.env.NODE_ENV !== 'production'\nconst isTest = process.env.NODE_ENV === 'test'\n\nconst oneMinute = 1000 * 60\nconst oneHour = oneMinute * 60\n\nexport const config = convict({\n appDir: {\n format: String,\n default: resolve(import.meta.dirname, '../server')\n },\n publicDir: {\n format: String,\n default: isTest\n ? resolve(import.meta.dirname, '../../test/fixtures')\n : resolve(import.meta.dirname, '../../.public')\n },\n\n /**\n * Server\n */\n port: {\n format: 'port',\n default: 3009,\n env: 'PORT'\n },\n env: {\n doc: 'The application environment.',\n format: ['production', 'development', 'test'],\n default: 'development',\n env: 'NODE_ENV'\n },\n cdpEnvironment: {\n doc: 'The CDP environment the app is currently in, with the addition of \"local\"',\n format: [\n 'local',\n 'infra-dev',\n 'management',\n 'dev',\n 'test',\n 'perf-test',\n 'ext-test',\n 'prod'\n ],\n default: 'local',\n env: 'ENVIRONMENT'\n },\n enforceCsrf: {\n format: Boolean,\n default: isProduction,\n env: 'ENFORCE_CSRF'\n },\n\n /**\n * Helper flags\n */\n isProduction: {\n doc: 'If this application running in the production environment',\n format: Boolean,\n default: isProduction\n },\n isDevelopment: {\n doc: 'If this application running in the development environment',\n format: Boolean,\n default: isDev\n },\n isTest: {\n doc: 'If this application running in the test environment',\n format: Boolean,\n default: isTest\n },\n\n /**\n * Service\n */\n serviceName: {\n doc: 'Applications Service Name',\n format: String,\n default: 'Digital Express Toolkit'\n },\n serviceVersion: {\n doc: 'The service version, this variable is injected into your docker container in CDP environments',\n format: String,\n nullable: true,\n default: '',\n env: 'SERVICE_VERSION'\n } as SchemaObj<string>,\n feedbackLink: {\n doc: 'Used in your phase banner. Can be a URL or more commonly mailto mailto:feedback@department.gov.uk',\n format: String,\n default: '',\n env: 'FEEDBACK_LINK'\n } as SchemaObj<string>,\n phaseTag: {\n format: String,\n default: 'beta', // Accepts \"alpha\" |\"beta\" | \"\"\n env: 'PHASE_TAG'\n },\n\n /**\n * Session storage\n * Redis integration is optional, but recommended for production environments.\n */\n sessionTimeout: {\n format: Number,\n default: oneHour * 24, // 1 day\n env: 'SESSION_TIMEOUT'\n },\n confirmationSessionTimeout: {\n format: Number,\n default: oneMinute * 20,\n env: 'CONFIRMATION_SESSION_TIMEOUT'\n },\n sessionCookiePassword: {\n format: String,\n default: '',\n sensitive: true,\n env: 'SESSION_COOKIE_PASSWORD'\n } as SchemaObj<string>,\n redis: {\n host: {\n doc: 'Redis cache host',\n format: String,\n default: '',\n env: 'REDIS_HOST'\n } as SchemaObj<string>,\n username: {\n doc: 'Redis cache username',\n format: String,\n default: '',\n env: 'REDIS_USERNAME'\n } as SchemaObj<string>,\n password: {\n doc: 'Redis cache password',\n format: '*',\n default: '',\n sensitive: true,\n env: 'REDIS_PASSWORD'\n } as SchemaObj<string>,\n keyPrefix: {\n doc: 'Redis cache key prefix name used to isolate the cached results across multiple clients',\n format: String,\n default: '',\n env: 'REDIS_KEY_PREFIX'\n } as SchemaObj<string>\n },\n tracing: {\n header: {\n doc: 'Tracing header name',\n format: String,\n default: 'x-cdp-request-id',\n env: 'TRACING_HEADER'\n } as SchemaObj<string>\n },\n\n /**\n * Email outputs\n * Email outputs will use notify to send an email to a single inbox.\n */\n notifyTemplateId: {\n format: String,\n default: '',\n env: 'NOTIFY_TEMPLATE_ID'\n } as SchemaObj<string>,\n notifyAPIKey: {\n format: String,\n default: '',\n env: 'NOTIFY_API_KEY'\n } as SchemaObj<string>,\n\n /**\n * API integrations\n */\n designerUrl: {\n format: String,\n default: 'http://localhost:3000',\n env: 'DESIGNER_URL'\n } as SchemaObj<string>,\n\n submissionUrl: {\n format: String,\n default: 'http://localhost:3002',\n env: 'SUBMISSION_URL'\n } as SchemaObj<string>,\n\n uploaderUrl: {\n format: String,\n default: 'http://localhost:7337',\n env: 'UPLOADER_URL'\n } as SchemaObj<string>,\n\n uploaderBucketName: {\n format: String,\n default: 'files',\n env: 'UPLOADER_BUCKET_NAME'\n },\n\n /**\n * Logging\n */\n log: {\n enabled: {\n doc: 'Is logging enabled',\n format: Boolean,\n default: !isTest,\n env: 'LOG_ENABLED'\n },\n level: {\n doc: 'Logging level',\n format: ['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'],\n default: 'info',\n env: 'LOG_LEVEL'\n } as SchemaObj<LevelWithSilent>,\n format: {\n doc: 'Format to output logs in.',\n format: ['ecs', 'pino-pretty'],\n default: isProduction ? 'ecs' : 'pino-pretty',\n env: 'LOG_FORMAT'\n } as SchemaObj<'ecs' | 'pino-pretty'>,\n redact: {\n doc: 'Log paths to redact',\n format: Array,\n default: isProduction\n ? ['req.headers.authorization', 'req.headers.cookie', 'res.headers']\n : ['req', 'res', 'responseTime']\n }\n },\n\n safelist: {\n format: Array,\n default: ['61bca17e-fe74-40e0-9c15-a901ad120eca.mock.pstmn.io'],\n env: 'SAFELIST'\n },\n\n stagingPrefix: {\n doc: 'Prefix for staging files in S3',\n format: String,\n default: 'staging',\n env: 'STAGING_PREFIX'\n },\n\n submissionEmailAddress: {\n doc: 'Email address to send the form to (local devtool only)',\n format: String,\n default: '',\n env: 'SUBMISSION_EMAIL_ADDRESS'\n } as SchemaObj<string>\n})\n\nconfig.validate({ allowed: 'strict' })\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["resolve","convict","isProduction","process","env","NODE_ENV","isDev","isTest","oneMinute","oneHour","config","appDir","format","String","default","import","meta","dirname","publicDir","port","doc","cdpEnvironment","enforceCsrf","Boolean","isDevelopment","serviceName","serviceVersion","nullable","feedbackLink","phaseTag","sessionTimeout","Number","confirmationSessionTimeout","sessionCookiePassword","sensitive","redis","host","username","password","keyPrefix","tracing","header","notifyTemplateId","notifyAPIKey","designerUrl","submissionUrl","uploaderUrl","uploaderBucketName","log","enabled","level","redact","Array","safelist","stagingPrefix","submissionEmailAddress","ordnanceSurveyApiKey","undefined","validate","allowed"],"sources":["../../src/config/index.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport convict, { type SchemaObj } from 'convict'\nimport { type LevelWithSilent } from 'pino'\n\nimport 'dotenv/config'\n\nconst isProduction = process.env.NODE_ENV === 'production'\nconst isDev = process.env.NODE_ENV !== 'production'\nconst isTest = process.env.NODE_ENV === 'test'\n\nconst oneMinute = 1000 * 60\nconst oneHour = oneMinute * 60\n\nexport const config = convict({\n appDir: {\n format: String,\n default: resolve(import.meta.dirname, '../server')\n },\n publicDir: {\n format: String,\n default: isTest\n ? resolve(import.meta.dirname, '../../test/fixtures')\n : resolve(import.meta.dirname, '../../.public')\n },\n\n /**\n * Server\n */\n port: {\n format: 'port',\n default: 3009,\n env: 'PORT'\n },\n env: {\n doc: 'The application environment.',\n format: ['production', 'development', 'test'],\n default: 'development',\n env: 'NODE_ENV'\n },\n cdpEnvironment: {\n doc: 'The CDP environment the app is currently in, with the addition of \"local\"',\n format: [\n 'local',\n 'infra-dev',\n 'management',\n 'dev',\n 'test',\n 'perf-test',\n 'ext-test',\n 'prod'\n ],\n default: 'local',\n env: 'ENVIRONMENT'\n },\n enforceCsrf: {\n format: Boolean,\n default: isProduction,\n env: 'ENFORCE_CSRF'\n },\n\n /**\n * Helper flags\n */\n isProduction: {\n doc: 'If this application running in the production environment',\n format: Boolean,\n default: isProduction\n },\n isDevelopment: {\n doc: 'If this application running in the development environment',\n format: Boolean,\n default: isDev\n },\n isTest: {\n doc: 'If this application running in the test environment',\n format: Boolean,\n default: isTest\n },\n\n /**\n * Service\n */\n serviceName: {\n doc: 'Applications Service Name',\n format: String,\n default: 'Digital Express Toolkit'\n },\n serviceVersion: {\n doc: 'The service version, this variable is injected into your docker container in CDP environments',\n format: String,\n nullable: true,\n default: '',\n env: 'SERVICE_VERSION'\n } as SchemaObj<string>,\n feedbackLink: {\n doc: 'Used in your phase banner. Can be a URL or more commonly mailto mailto:feedback@department.gov.uk',\n format: String,\n default: '',\n env: 'FEEDBACK_LINK'\n } as SchemaObj<string>,\n phaseTag: {\n format: String,\n default: 'beta', // Accepts \"alpha\" |\"beta\" | \"\"\n env: 'PHASE_TAG'\n },\n\n /**\n * Session storage\n * Redis integration is optional, but recommended for production environments.\n */\n sessionTimeout: {\n format: Number,\n default: oneHour * 24, // 1 day\n env: 'SESSION_TIMEOUT'\n },\n confirmationSessionTimeout: {\n format: Number,\n default: oneMinute * 20,\n env: 'CONFIRMATION_SESSION_TIMEOUT'\n },\n sessionCookiePassword: {\n format: String,\n default: '',\n sensitive: true,\n env: 'SESSION_COOKIE_PASSWORD'\n } as SchemaObj<string>,\n redis: {\n host: {\n doc: 'Redis cache host',\n format: String,\n default: '',\n env: 'REDIS_HOST'\n } as SchemaObj<string>,\n username: {\n doc: 'Redis cache username',\n format: String,\n default: '',\n env: 'REDIS_USERNAME'\n } as SchemaObj<string>,\n password: {\n doc: 'Redis cache password',\n format: '*',\n default: '',\n sensitive: true,\n env: 'REDIS_PASSWORD'\n } as SchemaObj<string>,\n keyPrefix: {\n doc: 'Redis cache key prefix name used to isolate the cached results across multiple clients',\n format: String,\n default: '',\n env: 'REDIS_KEY_PREFIX'\n } as SchemaObj<string>\n },\n tracing: {\n header: {\n doc: 'Tracing header name',\n format: String,\n default: 'x-cdp-request-id',\n env: 'TRACING_HEADER'\n } as SchemaObj<string>\n },\n\n /**\n * Email outputs\n * Email outputs will use notify to send an email to a single inbox.\n */\n notifyTemplateId: {\n format: String,\n default: '',\n env: 'NOTIFY_TEMPLATE_ID'\n } as SchemaObj<string>,\n notifyAPIKey: {\n format: String,\n default: '',\n env: 'NOTIFY_API_KEY'\n } as SchemaObj<string>,\n\n /**\n * API integrations\n */\n designerUrl: {\n format: String,\n default: 'http://localhost:3000',\n env: 'DESIGNER_URL'\n } as SchemaObj<string>,\n\n submissionUrl: {\n format: String,\n default: 'http://localhost:3002',\n env: 'SUBMISSION_URL'\n } as SchemaObj<string>,\n\n uploaderUrl: {\n format: String,\n default: 'http://localhost:7337',\n env: 'UPLOADER_URL'\n } as SchemaObj<string>,\n\n uploaderBucketName: {\n format: String,\n default: 'files',\n env: 'UPLOADER_BUCKET_NAME'\n },\n\n /**\n * Logging\n */\n log: {\n enabled: {\n doc: 'Is logging enabled',\n format: Boolean,\n default: !isTest,\n env: 'LOG_ENABLED'\n },\n level: {\n doc: 'Logging level',\n format: ['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'],\n default: 'info',\n env: 'LOG_LEVEL'\n } as SchemaObj<LevelWithSilent>,\n format: {\n doc: 'Format to output logs in.',\n format: ['ecs', 'pino-pretty'],\n default: isProduction ? 'ecs' : 'pino-pretty',\n env: 'LOG_FORMAT'\n } as SchemaObj<'ecs' | 'pino-pretty'>,\n redact: {\n doc: 'Log paths to redact',\n format: Array,\n default: isProduction\n ? ['req.headers.authorization', 'req.headers.cookie', 'res.headers']\n : ['req', 'res', 'responseTime']\n }\n },\n\n safelist: {\n format: Array,\n default: ['61bca17e-fe74-40e0-9c15-a901ad120eca.mock.pstmn.io'],\n env: 'SAFELIST'\n },\n\n stagingPrefix: {\n doc: 'Prefix for staging files in S3',\n format: String,\n default: 'staging',\n env: 'STAGING_PREFIX'\n },\n\n submissionEmailAddress: {\n doc: 'Email address to send the form to (local devtool only)',\n format: String,\n default: '',\n env: 'SUBMISSION_EMAIL_ADDRESS'\n } as SchemaObj<string>,\n\n ordnanceSurveyApiKey: {\n doc: 'The ordnance survey api key use by the postcode lookup plugin',\n format: String,\n nullable: true,\n default: undefined,\n env: 'ORDNANCE_SURVEY_API_KEY'\n } as SchemaObj<string | undefined>\n})\n\nconfig.validate({ allowed: 'strict' })\n"],"mappings":"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","ignoreList":[]}
package/.server/index.js CHANGED
@@ -9,16 +9,20 @@ process.on('unhandledRejection', error => {
9
9
  logger.error(err, `[unhandledRejection] Unhandled promise rejection: ${err}`);
10
10
  throw error;
11
11
  });
12
+ const port = config.get('port');
13
+ const ordnanceSurveyApiKey = config.get('ordnanceSurveyApiKey');
12
14
 
13
15
  /**
14
16
  * Main entrypoint to the application.
15
17
  */
16
18
  async function startServer() {
17
- const server = await createServer();
19
+ const server = await createServer({
20
+ ordnanceSurveyApiKey
21
+ });
18
22
  await server.start();
19
23
  process.send?.('online');
20
24
  server.logger.info('Server started successfully');
21
- server.logger.info(`Access your frontend on http://localhost:${config.get('port')}`);
25
+ server.logger.info(`Access your frontend on http://localhost:${port}`);
22
26
  }
23
27
  startServer().catch(error => {
24
28
  const err = getErrorMessage(error);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["getErrorMessage","config","createLogger","createServer","logger","process","on","error","err","info","startServer","server","start","send","get","catch"],"sources":["../src/index.ts"],"sourcesContent":["import { getErrorMessage } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\nimport { createServer } from '~/src/server/index.js'\n\nconst logger = createLogger()\n\nprocess.on('unhandledRejection', (error) => {\n const err = getErrorMessage(error)\n logger.info('Unhandled rejection')\n logger.error(err, `[unhandledRejection] Unhandled promise rejection: ${err}`)\n throw error\n})\n\n/**\n * Main entrypoint to the application.\n */\nasync function startServer() {\n const server = await createServer()\n await server.start()\n\n process.send?.('online')\n\n server.logger.info('Server started successfully')\n server.logger.info(\n `Access your frontend on http://localhost:${config.get('port')}`\n )\n}\n\nstartServer().catch((error: unknown) => {\n const err = getErrorMessage(error)\n logger.info('Server failed to start :(')\n logger.error(err, `[serverStartup] Server failed to start: ${err}`)\n throw error\n})\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,oBAAoB;AAEpD,SAASC,MAAM;AACf,SAASC,YAAY;AACrB,SAASC,YAAY;AAErB,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;AAE7BG,OAAO,CAACC,EAAE,CAAC,oBAAoB,EAAGC,KAAK,IAAK;EAC1C,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,qBAAqB,CAAC;EAClCL,MAAM,CAACG,KAAK,CAACC,GAAG,EAAE,qDAAqDA,GAAG,EAAE,CAAC;EAC7E,MAAMD,KAAK;AACb,CAAC,CAAC;;AAEF;AACA;AACA;AACA,eAAeG,WAAWA,CAAA,EAAG;EAC3B,MAAMC,MAAM,GAAG,MAAMR,YAAY,CAAC,CAAC;EACnC,MAAMQ,MAAM,CAACC,KAAK,CAAC,CAAC;EAEpBP,OAAO,CAACQ,IAAI,GAAG,QAAQ,CAAC;EAExBF,MAAM,CAACP,MAAM,CAACK,IAAI,CAAC,6BAA6B,CAAC;EACjDE,MAAM,CAACP,MAAM,CAACK,IAAI,CAChB,4CAA4CR,MAAM,CAACa,GAAG,CAAC,MAAM,CAAC,EAChE,CAAC;AACH;AAEAJ,WAAW,CAAC,CAAC,CAACK,KAAK,CAAER,KAAc,IAAK;EACtC,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,2BAA2B,CAAC;EACxCL,MAAM,CAACG,KAAK,CAACC,GAAG,EAAE,2CAA2CA,GAAG,EAAE,CAAC;EACnE,MAAMD,KAAK;AACb,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["getErrorMessage","config","createLogger","createServer","logger","process","on","error","err","info","port","get","ordnanceSurveyApiKey","startServer","server","start","send","catch"],"sources":["../src/index.ts"],"sourcesContent":["import { getErrorMessage } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\nimport { createServer } from '~/src/server/index.js'\n\nconst logger = createLogger()\n\nprocess.on('unhandledRejection', (error) => {\n const err = getErrorMessage(error)\n logger.info('Unhandled rejection')\n logger.error(err, `[unhandledRejection] Unhandled promise rejection: ${err}`)\n throw error\n})\n\nconst port = config.get('port')\nconst ordnanceSurveyApiKey = config.get('ordnanceSurveyApiKey')\n\n/**\n * Main entrypoint to the application.\n */\nasync function startServer() {\n const server = await createServer({ ordnanceSurveyApiKey })\n await server.start()\n\n process.send?.('online')\n\n server.logger.info('Server started successfully')\n server.logger.info(`Access your frontend on http://localhost:${port}`)\n}\n\nstartServer().catch((error: unknown) => {\n const err = getErrorMessage(error)\n logger.info('Server failed to start :(')\n logger.error(err, `[serverStartup] Server failed to start: ${err}`)\n throw error\n})\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,oBAAoB;AAEpD,SAASC,MAAM;AACf,SAASC,YAAY;AACrB,SAASC,YAAY;AAErB,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;AAE7BG,OAAO,CAACC,EAAE,CAAC,oBAAoB,EAAGC,KAAK,IAAK;EAC1C,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,qBAAqB,CAAC;EAClCL,MAAM,CAACG,KAAK,CAACC,GAAG,EAAE,qDAAqDA,GAAG,EAAE,CAAC;EAC7E,MAAMD,KAAK;AACb,CAAC,CAAC;AAEF,MAAMG,IAAI,GAAGT,MAAM,CAACU,GAAG,CAAC,MAAM,CAAC;AAC/B,MAAMC,oBAAoB,GAAGX,MAAM,CAACU,GAAG,CAAC,sBAAsB,CAAC;;AAE/D;AACA;AACA;AACA,eAAeE,WAAWA,CAAA,EAAG;EAC3B,MAAMC,MAAM,GAAG,MAAMX,YAAY,CAAC;IAAES;EAAqB,CAAC,CAAC;EAC3D,MAAME,MAAM,CAACC,KAAK,CAAC,CAAC;EAEpBV,OAAO,CAACW,IAAI,GAAG,QAAQ,CAAC;EAExBF,MAAM,CAACV,MAAM,CAACK,IAAI,CAAC,6BAA6B,CAAC;EACjDK,MAAM,CAACV,MAAM,CAACK,IAAI,CAAC,4CAA4CC,IAAI,EAAE,CAAC;AACxE;AAEAG,WAAW,CAAC,CAAC,CAACI,KAAK,CAAEV,KAAc,IAAK;EACtC,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,2BAA2B,CAAC;EACxCL,MAAM,CAACG,KAAK,CAACC,GAAG,EAAE,2CAA2CA,GAAG,EAAE,CAAC;EACnE,MAAMD,KAAK;AACb,CAAC,CAAC","ignoreList":[]}
@@ -1,2 +1,4 @@
1
1
  export const PREVIEW_PATH_PREFIX: "/preview";
2
2
  export const FORM_PREFIX: "";
3
+ export const EXTERNAL_STATE_PAYLOAD: "EXTERNAL_STATE_PAYLOAD";
4
+ export const EXTERNAL_STATE_APPENDAGE: "EXTERNAL_STATE_APPENDAGE";
@@ -1,3 +1,5 @@
1
1
  export const PREVIEW_PATH_PREFIX = '/preview';
2
2
  export const FORM_PREFIX = '';
3
+ export const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD';
4
+ export const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE';
3
5
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":["PREVIEW_PATH_PREFIX","FORM_PREFIX"],"sources":["../../src/server/constants.js"],"sourcesContent":["export const PREVIEW_PATH_PREFIX = '/preview'\nexport const FORM_PREFIX = ''\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,UAAU;AAC7C,OAAO,MAAMC,WAAW,GAAG,EAAE","ignoreList":[]}
1
+ {"version":3,"file":"constants.js","names":["PREVIEW_PATH_PREFIX","FORM_PREFIX","EXTERNAL_STATE_PAYLOAD","EXTERNAL_STATE_APPENDAGE"],"sources":["../../src/server/constants.js"],"sourcesContent":["export const PREVIEW_PATH_PREFIX = '/preview'\nexport const FORM_PREFIX = ''\nexport const EXTERNAL_STATE_PAYLOAD = 'EXTERNAL_STATE_PAYLOAD'\nexport const EXTERNAL_STATE_APPENDAGE = 'EXTERNAL_STATE_APPENDAGE'\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,UAAU;AAC7C,OAAO,MAAMC,WAAW,GAAG,EAAE;AAC7B,OAAO,MAAMC,sBAAsB,GAAG,wBAAwB;AAC9D,OAAO,MAAMC,wBAAwB,GAAG,0BAA0B","ignoreList":[]}
@@ -120,6 +120,13 @@
120
120
  "content": "### This is a H3 in markdown\n\n[An internal link](http://localhost:3009/fictional-page)\n\n[An external link](https://defra.gov.uk/fictional-page)",
121
121
  "options": {},
122
122
  "schema": {}
123
+ },
124
+ {
125
+ "title": "Summary",
126
+ "path": "/summary",
127
+ "controller": "SummaryPageController",
128
+ "components": [],
129
+ "next": []
123
130
  }
124
131
  ]
125
132
  }
@@ -56,10 +56,26 @@ pages:
56
56
  - name: wZLWPy
57
57
  options:
58
58
  required: true
59
+ usePostcodeLookup: true
59
60
  type: UkAddressField
60
- title: Address
61
+ title: What is your billing address
62
+ shortDescription: Billing address
61
63
  schema: {}
62
- hint: This is a UK address. Users must enter address line 1, town and a postcode
64
+ hint: This is a UK billing address. Users must enter address line 1, town and a postcode
65
+ - name: dfTGhD
66
+ options: {}
67
+ schema: {}
68
+ type: MultilineTextField
69
+ title: Delivery notes
70
+ hint:
71
+ Enter some instructions for the delivery person
72
+ - name: drGHuj
73
+ options:
74
+ required: true
75
+ type: UkAddressField
76
+ title: What is your delivery address
77
+ schema: {}
78
+ hint: This is a UK delivery address. Users must enter address line 1, town and a postcode
63
79
  next:
64
80
  - path: '/do-you-want-your-unicorn-breeder-certificate-sent-to-this-address'
65
81
  section: section
@@ -1,13 +1,15 @@
1
- import { type UkAddressFieldComponent } from '@defra/forms-model';
1
+ import { type FormComponentsDef, type UkAddressFieldComponent } from '@defra/forms-model';
2
2
  import { type ObjectSchema } from 'joi';
3
3
  import { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js';
4
4
  import { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js';
5
- import { type ErrorMessageTemplateList, type FormPayload, type FormState, type FormStateValue, type FormSubmissionError, type FormSubmissionState } from '~/src/server/plugins/engine/types.js';
5
+ import { type FormRequestPayload, type FormResponseToolkit } from '~/src/server/plugins/engine/types/index.js';
6
+ import { type ErrorMessageTemplateList, type FormPayload, type FormState, type FormStateValue, type FormSubmissionError, type FormSubmissionState, type PostcodeLookupExternalArgs } from '~/src/server/plugins/engine/types.js';
6
7
  export declare class UkAddressField extends FormComponent {
7
8
  options: UkAddressFieldComponent['options'];
8
9
  formSchema: ObjectSchema<FormPayload>;
9
10
  stateSchema: ObjectSchema<FormState>;
10
11
  collection: ComponentCollection;
12
+ shortDescription: FormComponentsDef['shortDescription'];
11
13
  constructor(def: UkAddressFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
12
14
  getFormValueFromState(state: FormSubmissionState): UkAddressState | undefined;
13
15
  getContextValueFromFormValue(value: UkAddressState | undefined): string[] | null;
@@ -19,24 +21,25 @@ export declare class UkAddressField extends FormComponent {
19
21
  */
20
22
  getViewErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined;
21
23
  getViewModel(payload: FormPayload, errors?: FormSubmissionError[]): {
24
+ value: string | undefined;
22
25
  fieldset: {
23
26
  attributes?: string | Record<string, string>;
24
- legend?: import("./types.js").Label;
27
+ legend?: import("~/src/server/plugins/engine/types/index.js").Label;
25
28
  };
26
- components: import("./types.js").ComponentViewModel[];
29
+ components: import("~/src/server/plugins/engine/types/index.js").ComponentViewModel[];
30
+ usePostcodeLookup: boolean;
27
31
  label: {
28
32
  text: string;
29
33
  };
30
34
  id: string;
31
35
  name: string;
32
- value: import("~/src/server/plugins/engine/types.js").FormValue;
33
36
  type?: string;
34
37
  hint?: {
35
38
  id?: string;
36
39
  text: string;
37
40
  };
38
- prefix?: import("./types.js").ComponentText;
39
- suffix?: import("./types.js").ComponentText;
41
+ prefix?: import("~/src/server/plugins/engine/types/index.js").ComponentText;
42
+ suffix?: import("~/src/server/plugins/engine/types/index.js").ComponentText;
40
43
  classes?: string;
41
44
  condition?: string;
42
45
  errors?: FormSubmissionError[];
@@ -52,11 +55,11 @@ export declare class UkAddressField extends FormComponent {
52
55
  accept?: string;
53
56
  inputmode?: string;
54
57
  };
55
- content?: import("./types.js").Content | import("./types.js").Content[] | string;
58
+ content?: import("~/src/server/plugins/engine/types/index.js").Content | import("~/src/server/plugins/engine/types/index.js").Content[] | string;
56
59
  maxlength?: number;
57
60
  maxwords?: number;
58
61
  rows?: number;
59
- items?: import("./types.js").ListItem[] | import("./types.js").DateInputItem[];
62
+ items?: import("~/src/server/plugins/engine/types/index.js").ListItem[] | import("~/src/server/plugins/engine/types/index.js").DateInputItem[];
60
63
  formGroup?: {
61
64
  classes?: string;
62
65
  attributes?: string | Record<string, string>;
@@ -71,13 +74,16 @@ export declare class UkAddressField extends FormComponent {
71
74
  * For error preview page that shows all possible errors on a component
72
75
  */
73
76
  getAllPossibleErrors(): ErrorMessageTemplateList;
77
+ private shouldUsePostcodeLookup;
74
78
  /**
75
79
  * Static version of getAllPossibleErrors that doesn't require a component instance.
76
80
  */
77
81
  static getAllPossibleErrors(): ErrorMessageTemplateList;
78
82
  static isUkAddress(value?: FormStateValue | FormState): value is UkAddressState;
83
+ static dispatcher(request: FormRequestPayload, h: FormResponseToolkit, args: PostcodeLookupExternalArgs): import("@hapi/hapi").ResponseObject;
79
84
  }
80
85
  export interface UkAddressState extends Record<string, string> {
86
+ uprn: string;
81
87
  addressLine1: string;
82
88
  addressLine2: string;
83
89
  town: string;
@@ -1,18 +1,31 @@
1
1
  import { ComponentType } from '@defra/forms-model';
2
+ import lowerFirst from 'lodash/lowerFirst.js';
2
3
  import { ComponentCollection } from "./ComponentCollection.js";
3
4
  import { FormComponent, isFormState } from "./FormComponent.js";
4
5
  import { TextField } from "./TextField.js";
6
+ import { dispatch } from "../../postcode-lookup/routes/index.js";
5
7
  export class UkAddressField extends FormComponent {
8
+ shortDescription;
6
9
  constructor(def, props) {
7
10
  super(def, props);
8
11
  const {
9
12
  name,
10
- options
13
+ options,
14
+ shortDescription
11
15
  } = def;
12
16
  const isRequired = options.required !== false;
13
17
  const hideOptional = !!options.optionalText;
14
18
  const hideTitle = !!options.hideTitle;
15
19
  this.collection = new ComponentCollection([{
20
+ type: ComponentType.TextField,
21
+ name: `${name}__uprn`,
22
+ title: 'UPRN',
23
+ schema: {},
24
+ options: {
25
+ required: false,
26
+ classes: 'hidden'
27
+ }
28
+ }, {
16
29
  type: ComponentType.TextField,
17
30
  name: `${name}__addressLine1`,
18
31
  title: 'Address line 1',
@@ -81,6 +94,7 @@ export class UkAddressField extends FormComponent {
81
94
  this.options = options;
82
95
  this.formSchema = this.collection.formSchema;
83
96
  this.stateSchema = this.collection.stateSchema;
97
+ this.shortDescription = shortDescription;
84
98
  }
85
99
  getFormValueFromState(state) {
86
100
  const value = super.getFormValueFromState(state);
@@ -90,7 +104,7 @@ export class UkAddressField extends FormComponent {
90
104
  if (!value) {
91
105
  return null;
92
106
  }
93
- return Object.values(value).filter(Boolean);
107
+ return Object.entries(value).filter(([key, value]) => key !== 'uprn' && Boolean(value)).map(([, value]) => value);
94
108
  }
95
109
  getContextValueFromState(state) {
96
110
  const value = this.getFormValueFromState(state);
@@ -108,7 +122,23 @@ export class UkAddressField extends FormComponent {
108
122
  * Returns one error per child field
109
123
  */
110
124
  getViewErrors(errors) {
111
- return this.getErrors(errors)?.filter((error, index, self) => index === self.findIndex(err => err.name === error.name));
125
+ const uniqueErrors = this.getErrors(errors)?.filter((error, index, self) => index === self.findIndex(err => err.name === error.name));
126
+
127
+ // When using postcode lookup, the address fields are hidden
128
+ // so we replace any individual validation messages with a single one
129
+ if (this.shouldUsePostcodeLookup() && uniqueErrors?.length) {
130
+ const {
131
+ name,
132
+ shortDescription
133
+ } = this;
134
+ return [{
135
+ name,
136
+ path: [name],
137
+ href: `#${name}`,
138
+ text: `Enter ${lowerFirst(shortDescription)}`
139
+ }];
140
+ }
141
+ return uniqueErrors;
112
142
  }
113
143
  getViewModel(payload, errors) {
114
144
  const {
@@ -118,7 +148,6 @@ export class UkAddressField extends FormComponent {
118
148
  } = this;
119
149
  const viewModel = super.getViewModel(payload, errors);
120
150
  let {
121
- components,
122
151
  fieldset,
123
152
  hint,
124
153
  label
@@ -139,11 +168,26 @@ export class UkAddressField extends FormComponent {
139
168
  'aria-describedby': hint.id
140
169
  };
141
170
  }
142
- components = collection.getViewModel(payload, errors);
171
+ const components = collection.getViewModel(payload, errors);
172
+
173
+ // Hide UPRN
174
+ const uprn = components.at(0);
175
+ if (!uprn) {
176
+ throw new Error('No UPRN');
177
+ }
178
+ uprn.model.formGroup = {
179
+ classes: 'app-hidden'
180
+ };
181
+
182
+ // Postcode lookup
183
+ const usePostcodeLookup = this.shouldUsePostcodeLookup();
184
+ const value = usePostcodeLookup ? this.getDisplayStringFromState(payload) : undefined;
143
185
  return {
144
186
  ...viewModel,
187
+ value,
145
188
  fieldset,
146
- components
189
+ components,
190
+ usePostcodeLookup
147
191
  };
148
192
  }
149
193
  isState(value) {
@@ -156,6 +200,9 @@ export class UkAddressField extends FormComponent {
156
200
  getAllPossibleErrors() {
157
201
  return UkAddressField.getAllPossibleErrors();
158
202
  }
203
+ shouldUsePostcodeLookup() {
204
+ return !!(this.options.usePostcodeLookup && this.model.ordnanceSurveyApiKey);
205
+ }
159
206
 
160
207
  /**
161
208
  * Static version of getAllPossibleErrors that doesn't require a component instance.
@@ -181,5 +228,19 @@ export class UkAddressField extends FormComponent {
181
228
  static isUkAddress(value) {
182
229
  return isFormState(value) && TextField.isText(value.addressLine1) && TextField.isText(value.town) && TextField.isText(value.postcode);
183
230
  }
231
+ static dispatcher(request, h, args) {
232
+ const {
233
+ controller,
234
+ component
235
+ } = args;
236
+ return dispatch(request, h, {
237
+ formName: controller.model.name,
238
+ componentName: component.name,
239
+ componentHint: component.hint,
240
+ componentTitle: component.title || controller.title,
241
+ step: args.actionArgs.step,
242
+ sourceUrl: args.sourceUrl
243
+ });
244
+ }
184
245
  }
185
246
  //# sourceMappingURL=UkAddressField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UkAddressField.js","names":["ComponentType","ComponentCollection","FormComponent","isFormState","TextField","UkAddressField","constructor","def","props","name","options","isRequired","required","hideOptional","optionalText","hideTitle","collection","type","title","schema","max","autocomplete","classes","regex","parent","formSchema","stateSchema","getFormValueFromState","state","value","isState","undefined","getContextValueFromFormValue","Object","values","filter","Boolean","getContextValueFromState","getDisplayStringFromFormValue","join","getDisplayStringFromState","getViewErrors","errors","getErrors","error","index","self","findIndex","err","getViewModel","payload","viewModel","components","fieldset","hint","label","legend","text","id","attributes","isUkAddress","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","isText","addressLine1","town","postcode"],"sources":["../../../../../src/server/plugins/engine/components/UkAddressField.ts"],"sourcesContent":["import { ComponentType, type UkAddressFieldComponent } from '@defra/forms-model'\nimport { type ObjectSchema } from 'joi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport {\n FormComponent,\n isFormState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { TextField } from '~/src/server/plugins/engine/components/TextField.js'\nimport { type QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class UkAddressField extends FormComponent {\n declare options: UkAddressFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: UkAddressFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { name, options } = def\n\n const isRequired = options.required !== false\n const hideOptional = !!options.optionalText\n const hideTitle = !!options.hideTitle\n\n this.collection = new ComponentCollection(\n [\n {\n type: ComponentType.TextField,\n name: `${name}__addressLine1`,\n title: 'Address line 1',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-line1',\n required: isRequired,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__addressLine2`,\n title: 'Address line 2',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-line2',\n required: false,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__town`,\n title: 'Town or city',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-level2',\n classes: 'govuk-!-width-two-thirds',\n required: isRequired,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__county`,\n title: 'County',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-level1',\n required: false,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__postcode`,\n title: 'Postcode',\n schema: {\n regex: '^[a-zA-Z]{1,2}\\\\d[a-zA-Z\\\\d]?\\\\s?\\\\d[a-zA-Z]{2}$'\n },\n options: {\n autocomplete: 'postal-code',\n classes: 'govuk-input--width-10',\n required: isRequired,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n }\n ],\n { ...props, parent: this }\n )\n\n this.options = options\n this.formSchema = this.collection.formSchema\n this.stateSchema = this.collection.stateSchema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const value = super.getFormValueFromState(state)\n return this.isState(value) ? value : undefined\n }\n\n getContextValueFromFormValue(value: UkAddressState | undefined) {\n if (!value) {\n return null\n }\n\n return Object.values(value).filter(Boolean)\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n getDisplayStringFromFormValue(value: UkAddressState | undefined): string {\n return this.getContextValueFromFormValue(value)?.join(', ') ?? ''\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n /**\n * Returns one error per child field\n */\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n return this.getErrors(errors)?.filter(\n (error, index, self) =>\n index === self.findIndex((err) => err.name === error.name)\n )\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { collection, name, options } = this\n\n const viewModel = super.getViewModel(payload, errors)\n let { components, fieldset, hint, label } = viewModel\n\n fieldset ??= {\n legend: {\n text: label.text,\n\n /**\n * For screen readers, only hide legend visually. This can be overridden\n * by single component {@link QuestionPageController | `showTitle` handling}\n */\n classes: options.hideTitle\n ? 'govuk-visually-hidden'\n : 'govuk-fieldset__legend--m'\n }\n }\n\n if (hint) {\n hint.id ??= `${name}-hint`\n fieldset.attributes ??= {\n 'aria-describedby': hint.id\n }\n }\n\n components = collection.getViewModel(payload, errors)\n\n return {\n ...viewModel,\n fieldset,\n components\n }\n }\n\n isState(value?: FormStateValue | FormState): value is UkAddressState {\n return UkAddressField.isUkAddress(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return UkAddressField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: 'Enter address line 1' },\n { type: 'required', template: 'Enter town or city' },\n { type: 'required', template: 'Enter postcode' },\n { type: 'format', template: 'Enter valid postcode' }\n ],\n advancedSettingsErrors: []\n }\n }\n\n static isUkAddress(\n value?: FormStateValue | FormState\n ): value is UkAddressState {\n return (\n isFormState(value) &&\n TextField.isText(value.addressLine1) &&\n TextField.isText(value.town) &&\n TextField.isText(value.postcode)\n )\n }\n}\n\nexport interface UkAddressState extends Record<string, string> {\n addressLine1: string\n addressLine2: string\n town: string\n county: string\n postcode: string\n}\n"],"mappings":"AAAA,SAASA,aAAa,QAAsC,oBAAoB;AAGhF,SAASC,mBAAmB;AAC5B,SACEC,aAAa,EACbC,WAAW;AAEb,SAASC,SAAS;AAWlB,OAAO,MAAMC,cAAc,SAASH,aAAa,CAAC;EAMhDI,WAAWA,CACTC,GAA4B,EAC5BC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC,IAAI;MAAEC;IAAQ,CAAC,GAAGH,GAAG;IAE7B,MAAMI,UAAU,GAAGD,OAAO,CAACE,QAAQ,KAAK,KAAK;IAC7C,MAAMC,YAAY,GAAG,CAAC,CAACH,OAAO,CAACI,YAAY;IAC3C,MAAMC,SAAS,GAAG,CAAC,CAACL,OAAO,CAACK,SAAS;IAErC,IAAI,CAACC,UAAU,GAAG,IAAIf,mBAAmB,CACvC,CACE;MACEgB,IAAI,EAAEjB,aAAa,CAACI,SAAS;MAC7BK,IAAI,EAAE,GAAGA,IAAI,gBAAgB;MAC7BS,KAAK,EAAE,gBAAgB;MACvBC,MAAM,EAAE;QAAEC,GAAG,EAAE;MAAI,CAAC;MACpBV,OAAO,EAAE;QACPW,YAAY,EAAE,eAAe;QAC7BT,QAAQ,EAAED,UAAU;QACpBG,YAAY,EAAE,CAACH,UAAU,KAAKE,YAAY,IAAI,CAACE,SAAS;MAC1D;IACF,CAAC,EACD;MACEE,IAAI,EAAEjB,aAAa,CAACI,SAAS;MAC7BK,IAAI,EAAE,GAAGA,IAAI,gBAAgB;MAC7BS,KAAK,EAAE,gBAAgB;MACvBC,MAAM,EAAE;QAAEC,GAAG,EAAE;MAAI,CAAC;MACpBV,OAAO,EAAE;QACPW,YAAY,EAAE,eAAe;QAC7BT,QAAQ,EAAE,KAAK;QACfE,YAAY,EAAE,CAACH,UAAU,KAAKE,YAAY,IAAI,CAACE,SAAS;MAC1D;IACF,CAAC,EACD;MACEE,IAAI,EAAEjB,aAAa,CAACI,SAAS;MAC7BK,IAAI,EAAE,GAAGA,IAAI,QAAQ;MACrBS,KAAK,EAAE,cAAc;MACrBC,MAAM,EAAE;QAAEC,GAAG,EAAE;MAAI,CAAC;MACpBV,OAAO,EAAE;QACPW,YAAY,EAAE,gBAAgB;QAC9BC,OAAO,EAAE,0BAA0B;QACnCV,QAAQ,EAAED,UAAU;QACpBG,YAAY,EAAE,CAACH,UAAU,KAAKE,YAAY,IAAI,CAACE,SAAS;MAC1D;IACF,CAAC,EACD;MACEE,IAAI,EAAEjB,aAAa,CAACI,SAAS;MAC7BK,IAAI,EAAE,GAAGA,IAAI,UAAU;MACvBS,KAAK,EAAE,QAAQ;MACfC,MAAM,EAAE;QAAEC,GAAG,EAAE;MAAI,CAAC;MACpBV,OAAO,EAAE;QACPW,YAAY,EAAE,gBAAgB;QAC9BT,QAAQ,EAAE,KAAK;QACfE,YAAY,EAAE,CAACH,UAAU,KAAKE,YAAY,IAAI,CAACE,SAAS;MAC1D;IACF,CAAC,EACD;MACEE,IAAI,EAAEjB,aAAa,CAACI,SAAS;MAC7BK,IAAI,EAAE,GAAGA,IAAI,YAAY;MACzBS,KAAK,EAAE,UAAU;MACjBC,MAAM,EAAE;QACNI,KAAK,EAAE;MACT,CAAC;MACDb,OAAO,EAAE;QACPW,YAAY,EAAE,aAAa;QAC3BC,OAAO,EAAE,uBAAuB;QAChCV,QAAQ,EAAED,UAAU;QACpBG,YAAY,EAAE,CAACH,UAAU,KAAKE,YAAY,IAAI,CAACE,SAAS;MAC1D;IACF,CAAC,CACF,EACD;MAAE,GAAGP,KAAK;MAAEgB,MAAM,EAAE;IAAK,CAC3B,CAAC;IAED,IAAI,CAACd,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACe,UAAU,GAAG,IAAI,CAACT,UAAU,CAACS,UAAU;IAC5C,IAAI,CAACC,WAAW,GAAG,IAAI,CAACV,UAAU,CAACU,WAAW;EAChD;EAEAC,qBAAqBA,CAACC,KAA0B,EAAE;IAChD,MAAMC,KAAK,GAAG,KAAK,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAChD,OAAO,IAAI,CAACE,OAAO,CAACD,KAAK,CAAC,GAAGA,KAAK,GAAGE,SAAS;EAChD;EAEAC,4BAA4BA,CAACH,KAAiC,EAAE;IAC9D,IAAI,CAACA,KAAK,EAAE;MACV,OAAO,IAAI;IACb;IAEA,OAAOI,MAAM,CAACC,MAAM,CAACL,KAAK,CAAC,CAACM,MAAM,CAACC,OAAO,CAAC;EAC7C;EAEAC,wBAAwBA,CAACT,KAA0B,EAAE;IACnD,MAAMC,KAAK,GAAG,IAAI,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAE/C,OAAO,IAAI,CAACI,4BAA4B,CAACH,KAAK,CAAC;EACjD;EAEAS,6BAA6BA,CAACT,KAAiC,EAAU;IACvE,OAAO,IAAI,CAACG,4BAA4B,CAACH,KAAK,CAAC,EAAEU,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;EACnE;EAEAC,yBAAyBA,CAACZ,KAA0B,EAAE;IACpD,MAAMC,KAAK,GAAG,IAAI,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAE/C,OAAO,IAAI,CAACU,6BAA6B,CAACT,KAAK,CAAC;EAClD;;EAEA;AACF;AACA;EACEY,aAAaA,CACXC,MAA8B,EACK;IACnC,OAAO,IAAI,CAACC,SAAS,CAACD,MAAM,CAAC,EAAEP,MAAM,CACnC,CAACS,KAAK,EAAEC,KAAK,EAAEC,IAAI,KACjBD,KAAK,KAAKC,IAAI,CAACC,SAAS,CAAEC,GAAG,IAAKA,GAAG,CAACvC,IAAI,KAAKmC,KAAK,CAACnC,IAAI,CAC7D,CAAC;EACH;EAEAwC,YAAYA,CAACC,OAAoB,EAAER,MAA8B,EAAE;IACjE,MAAM;MAAE1B,UAAU;MAAEP,IAAI;MAAEC;IAAQ,CAAC,GAAG,IAAI;IAE1C,MAAMyC,SAAS,GAAG,KAAK,CAACF,YAAY,CAACC,OAAO,EAAER,MAAM,CAAC;IACrD,IAAI;MAAEU,UAAU;MAAEC,QAAQ;MAAEC,IAAI;MAAEC;IAAM,CAAC,GAAGJ,SAAS;IAErDE,QAAQ,KAAK;MACXG,MAAM,EAAE;QACNC,IAAI,EAAEF,KAAK,CAACE,IAAI;QAEhB;AACR;AACA;AACA;QACQnC,OAAO,EAAEZ,OAAO,CAACK,SAAS,GACtB,uBAAuB,GACvB;MACN;IACF,CAAC;IAED,IAAIuC,IAAI,EAAE;MACRA,IAAI,CAACI,EAAE,KAAK,GAAGjD,IAAI,OAAO;MAC1B4C,QAAQ,CAACM,UAAU,KAAK;QACtB,kBAAkB,EAAEL,IAAI,CAACI;MAC3B,CAAC;IACH;IAEAN,UAAU,GAAGpC,UAAU,CAACiC,YAAY,CAACC,OAAO,EAAER,MAAM,CAAC;IAErD,OAAO;MACL,GAAGS,SAAS;MACZE,QAAQ;MACRD;IACF,CAAC;EACH;EAEAtB,OAAOA,CAACD,KAAkC,EAA2B;IACnE,OAAOxB,cAAc,CAACuD,WAAW,CAAC/B,KAAK,CAAC;EAC1C;;EAEA;AACF;AACA;EACEgC,oBAAoBA,CAAA,EAA6B;IAC/C,OAAOxD,cAAc,CAACwD,oBAAoB,CAAC,CAAC;EAC9C;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QAAE7C,IAAI,EAAE,UAAU;QAAE8C,QAAQ,EAAE;MAAuB,CAAC,EACtD;QAAE9C,IAAI,EAAE,UAAU;QAAE8C,QAAQ,EAAE;MAAqB,CAAC,EACpD;QAAE9C,IAAI,EAAE,UAAU;QAAE8C,QAAQ,EAAE;MAAiB,CAAC,EAChD;QAAE9C,IAAI,EAAE,QAAQ;QAAE8C,QAAQ,EAAE;MAAuB,CAAC,CACrD;MACDC,sBAAsB,EAAE;IAC1B,CAAC;EACH;EAEA,OAAOJ,WAAWA,CAChB/B,KAAkC,EACT;IACzB,OACE1B,WAAW,CAAC0B,KAAK,CAAC,IAClBzB,SAAS,CAAC6D,MAAM,CAACpC,KAAK,CAACqC,YAAY,CAAC,IACpC9D,SAAS,CAAC6D,MAAM,CAACpC,KAAK,CAACsC,IAAI,CAAC,IAC5B/D,SAAS,CAAC6D,MAAM,CAACpC,KAAK,CAACuC,QAAQ,CAAC;EAEpC;AACF","ignoreList":[]}
1
+ {"version":3,"file":"UkAddressField.js","names":["ComponentType","lowerFirst","ComponentCollection","FormComponent","isFormState","TextField","dispatch","UkAddressField","shortDescription","constructor","def","props","name","options","isRequired","required","hideOptional","optionalText","hideTitle","collection","type","title","schema","classes","max","autocomplete","regex","parent","formSchema","stateSchema","getFormValueFromState","state","value","isState","undefined","getContextValueFromFormValue","Object","entries","filter","key","Boolean","map","getContextValueFromState","getDisplayStringFromFormValue","join","getDisplayStringFromState","getViewErrors","errors","uniqueErrors","getErrors","error","index","self","findIndex","err","shouldUsePostcodeLookup","length","path","href","text","getViewModel","payload","viewModel","fieldset","hint","label","legend","id","attributes","components","uprn","at","Error","model","formGroup","usePostcodeLookup","isUkAddress","getAllPossibleErrors","ordnanceSurveyApiKey","baseErrors","template","advancedSettingsErrors","isText","addressLine1","town","postcode","dispatcher","request","h","args","controller","component","formName","componentName","componentHint","componentTitle","step","actionArgs","sourceUrl"],"sources":["../../../../../src/server/plugins/engine/components/UkAddressField.ts"],"sourcesContent":["import {\n ComponentType,\n type FormComponentsDef,\n type UkAddressFieldComponent\n} from '@defra/forms-model'\nimport { type ObjectSchema } from 'joi'\nimport lowerFirst from 'lodash/lowerFirst.js'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport {\n FormComponent,\n isFormState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { TextField } from '~/src/server/plugins/engine/components/TextField.js'\nimport { type QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n type FormRequestPayload,\n type FormResponseToolkit\n} from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type PostcodeLookupExternalArgs\n} from '~/src/server/plugins/engine/types.js'\nimport { dispatch } from '~/src/server/plugins/postcode-lookup/routes/index.js'\n\nexport class UkAddressField extends FormComponent {\n declare options: UkAddressFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n shortDescription: FormComponentsDef['shortDescription']\n\n constructor(\n def: UkAddressFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { name, options, shortDescription } = def\n\n const isRequired = options.required !== false\n const hideOptional = !!options.optionalText\n const hideTitle = !!options.hideTitle\n\n this.collection = new ComponentCollection(\n [\n {\n type: ComponentType.TextField,\n name: `${name}__uprn`,\n title: 'UPRN',\n schema: {},\n options: {\n required: false,\n classes: 'hidden'\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__addressLine1`,\n title: 'Address line 1',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-line1',\n required: isRequired,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__addressLine2`,\n title: 'Address line 2',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-line2',\n required: false,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__town`,\n title: 'Town or city',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-level2',\n classes: 'govuk-!-width-two-thirds',\n required: isRequired,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__county`,\n title: 'County',\n schema: { max: 100 },\n options: {\n autocomplete: 'address-level1',\n required: false,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n },\n {\n type: ComponentType.TextField,\n name: `${name}__postcode`,\n title: 'Postcode',\n schema: {\n regex: '^[a-zA-Z]{1,2}\\\\d[a-zA-Z\\\\d]?\\\\s?\\\\d[a-zA-Z]{2}$'\n },\n options: {\n autocomplete: 'postal-code',\n classes: 'govuk-input--width-10',\n required: isRequired,\n optionalText: !isRequired && (hideOptional || !hideTitle)\n }\n }\n ],\n { ...props, parent: this }\n )\n\n this.options = options\n this.formSchema = this.collection.formSchema\n this.stateSchema = this.collection.stateSchema\n this.shortDescription = shortDescription\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const value = super.getFormValueFromState(state)\n return this.isState(value) ? value : undefined\n }\n\n getContextValueFromFormValue(value: UkAddressState | undefined) {\n if (!value) {\n return null\n }\n\n return Object.entries(value)\n .filter(([key, value]) => key !== 'uprn' && Boolean(value))\n .map(([, value]) => value)\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n getDisplayStringFromFormValue(value: UkAddressState | undefined): string {\n return this.getContextValueFromFormValue(value)?.join(', ') ?? ''\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n /**\n * Returns one error per child field\n */\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const uniqueErrors = this.getErrors(errors)?.filter(\n (error, index, self) =>\n index === self.findIndex((err) => err.name === error.name)\n )\n\n // When using postcode lookup, the address fields are hidden\n // so we replace any individual validation messages with a single one\n if (this.shouldUsePostcodeLookup() && uniqueErrors?.length) {\n const { name, shortDescription } = this\n\n return [\n {\n name,\n path: [name],\n href: `#${name}`,\n text: `Enter ${lowerFirst(shortDescription)}`\n }\n ]\n }\n\n return uniqueErrors\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { collection, name, options } = this\n\n const viewModel = super.getViewModel(payload, errors)\n let { fieldset, hint, label } = viewModel\n\n fieldset ??= {\n legend: {\n text: label.text,\n\n /**\n * For screen readers, only hide legend visually. This can be overridden\n * by single component {@link QuestionPageController | `showTitle` handling}\n */\n classes: options.hideTitle\n ? 'govuk-visually-hidden'\n : 'govuk-fieldset__legend--m'\n }\n }\n\n if (hint) {\n hint.id ??= `${name}-hint`\n fieldset.attributes ??= {\n 'aria-describedby': hint.id\n }\n }\n\n const components = collection.getViewModel(payload, errors)\n\n // Hide UPRN\n const uprn = components.at(0)\n\n if (!uprn) {\n throw new Error('No UPRN')\n }\n\n uprn.model.formGroup = { classes: 'app-hidden' }\n\n // Postcode lookup\n const usePostcodeLookup = this.shouldUsePostcodeLookup()\n\n const value = usePostcodeLookup\n ? this.getDisplayStringFromState(payload)\n : undefined\n\n return {\n ...viewModel,\n value,\n fieldset,\n components,\n usePostcodeLookup\n }\n }\n\n isState(value?: FormStateValue | FormState): value is UkAddressState {\n return UkAddressField.isUkAddress(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return UkAddressField.getAllPossibleErrors()\n }\n\n private shouldUsePostcodeLookup() {\n return !!(this.options.usePostcodeLookup && this.model.ordnanceSurveyApiKey)\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: 'Enter address line 1' },\n { type: 'required', template: 'Enter town or city' },\n { type: 'required', template: 'Enter postcode' },\n { type: 'format', template: 'Enter valid postcode' }\n ],\n advancedSettingsErrors: []\n }\n }\n\n static isUkAddress(\n value?: FormStateValue | FormState\n ): value is UkAddressState {\n return (\n isFormState(value) &&\n TextField.isText(value.addressLine1) &&\n TextField.isText(value.town) &&\n TextField.isText(value.postcode)\n )\n }\n\n static dispatcher(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n args: PostcodeLookupExternalArgs\n ) {\n const { controller, component } = args\n\n return dispatch(request, h, {\n formName: controller.model.name,\n componentName: component.name,\n componentHint: component.hint,\n componentTitle: component.title || controller.title,\n step: args.actionArgs.step,\n sourceUrl: args.sourceUrl\n })\n }\n}\n\nexport interface UkAddressState extends Record<string, string> {\n uprn: string\n addressLine1: string\n addressLine2: string\n town: string\n county: string\n postcode: string\n}\n"],"mappings":"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","ignoreList":[]}
@@ -3,7 +3,7 @@ import { plugin } from '~/src/server/plugins/engine/plugin.js';
3
3
  import { type PluginOptions } from '~/src/server/plugins/engine/types.js';
4
4
  import { type CacheService } from '~/src/server/services/cacheService.js';
5
5
  import { type RouteConfig } from '~/src/server/types.js';
6
- export declare const configureEnginePlugin: ({ formFileName, formFilePath, services, controllers, preparePageEventRequestOptions, onRequest, saveAndExit }?: RouteConfig, cache?: CacheService) => Promise<{
6
+ export declare const configureEnginePlugin: ({ formFileName, formFilePath, services, controllers, preparePageEventRequestOptions, onRequest, saveAndExit, ordnanceSurveyApiKey }?: RouteConfig, cache?: CacheService) => Promise<{
7
7
  plugin: typeof plugin;
8
8
  options: PluginOptions;
9
9
  }>;
@@ -13,7 +13,8 @@ export const configureEnginePlugin = async ({
13
13
  controllers,
14
14
  preparePageEventRequestOptions,
15
15
  onRequest,
16
- saveAndExit
16
+ saveAndExit,
17
+ ordnanceSurveyApiKey
17
18
  } = {}, cache) => {
18
19
  let model;
19
20
  if (formFileName && formFilePath) {
@@ -23,7 +24,8 @@ export const configureEnginePlugin = async ({
23
24
  } = parse(formFileName);
24
25
  const initialBasePath = `${FORM_PREFIX}${name}`;
25
26
  model = new FormModel(definition, {
26
- basePath: initialBasePath
27
+ basePath: initialBasePath,
28
+ ordnanceSurveyApiKey
27
29
  }, services, controllers);
28
30
  }
29
31
  return {
@@ -46,7 +48,8 @@ export const configureEnginePlugin = async ({
46
48
  onRequest,
47
49
  baseUrl: 'http://localhost:3009',
48
50
  // always runs locally
49
- saveAndExit
51
+ saveAndExit,
52
+ ordnanceSurveyApiKey
50
53
  }
51
54
  };
52
55
  };
@@ -1 +1 @@
1
- {"version":3,"file":"configureEnginePlugin.js","names":["join","parse","FORM_PREFIX","FormModel","plugin","defaultServices","formsService","findPackageRoot","devtoolContext","configureEnginePlugin","formFileName","formFilePath","services","controllers","preparePageEventRequestOptions","onRequest","saveAndExit","cache","model","definition","getForm","name","initialBasePath","basePath","options","nunjucks","baseLayoutPath","paths","viewContext","baseUrl","importPath","ext","attributes","type","formImport","with","default"],"sources":["../../../../src/server/plugins/engine/configureEnginePlugin.ts"],"sourcesContent":["import { join, parse } from 'node:path'\n\nimport { type FormDefinition } from '@defra/forms-model'\n\nimport { FORM_PREFIX } from '~/src/server/constants.js'\nimport { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'\nimport { plugin } from '~/src/server/plugins/engine/plugin.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport { formsService } from '~/src/server/plugins/engine/services/localFormsService.js'\nimport { type PluginOptions } from '~/src/server/plugins/engine/types.js'\nimport { findPackageRoot } from '~/src/server/plugins/engine/vision.js'\nimport { devtoolContext } from '~/src/server/plugins/nunjucks/context.js'\nimport { type CacheService } from '~/src/server/services/cacheService.js'\nimport { type RouteConfig } from '~/src/server/types.js'\n\nexport const configureEnginePlugin = async (\n {\n formFileName,\n formFilePath,\n services,\n controllers,\n preparePageEventRequestOptions,\n onRequest,\n saveAndExit\n }: RouteConfig = {},\n cache?: CacheService\n): Promise<{\n plugin: typeof plugin\n options: PluginOptions\n}> => {\n let model: FormModel | undefined\n\n if (formFileName && formFilePath) {\n const definition = await getForm(join(formFilePath, formFileName))\n const { name } = parse(formFileName)\n\n const initialBasePath = `${FORM_PREFIX}${name}`\n\n model = new FormModel(\n definition,\n { basePath: initialBasePath },\n services,\n controllers\n )\n }\n\n return {\n plugin,\n options: {\n model,\n services: services ?? {\n // services for testing, else use the disk loader option for running this service locally\n ...defaultServices,\n formsService: await formsService()\n },\n controllers,\n cache: cache ?? 'session',\n nunjucks: {\n baseLayoutPath: 'dxt-devtool-baselayout.html',\n paths: [join(findPackageRoot(), 'src/server/devserver')] // custom layout to make it really clear this is not the same as the runner\n },\n viewContext: devtoolContext,\n preparePageEventRequestOptions,\n onRequest,\n baseUrl: 'http://localhost:3009', // always runs locally\n saveAndExit\n }\n }\n}\n\nexport async function getForm(importPath: string) {\n const { ext } = parse(importPath)\n\n const attributes: ImportAttributes = {\n type: ext === '.json' ? 'json' : 'module'\n }\n\n const formImport = import(importPath, { with: attributes }) as Promise<{\n default: FormDefinition\n }>\n\n const { default: definition } = await formImport\n return definition\n}\n"],"mappings":"AAAA,SAASA,IAAI,EAAEC,KAAK,QAAQ,WAAW;AAIvC,SAASC,WAAW;AACpB,SAASC,SAAS;AAClB,SAASC,MAAM;AACf,OAAO,KAAKC,eAAe;AAC3B,SAASC,YAAY;AAErB,SAASC,eAAe;AACxB,SAASC,cAAc;AAIvB,OAAO,MAAMC,qBAAqB,GAAG,MAAAA,CACnC;EACEC,YAAY;EACZC,YAAY;EACZC,QAAQ;EACRC,WAAW;EACXC,8BAA8B;EAC9BC,SAAS;EACTC;AACW,CAAC,GAAG,CAAC,CAAC,EACnBC,KAAoB,KAIhB;EACJ,IAAIC,KAA4B;EAEhC,IAAIR,YAAY,IAAIC,YAAY,EAAE;IAChC,MAAMQ,UAAU,GAAG,MAAMC,OAAO,CAACpB,IAAI,CAACW,YAAY,EAAED,YAAY,CAAC,CAAC;IAClE,MAAM;MAAEW;IAAK,CAAC,GAAGpB,KAAK,CAACS,YAAY,CAAC;IAEpC,MAAMY,eAAe,GAAG,GAAGpB,WAAW,GAAGmB,IAAI,EAAE;IAE/CH,KAAK,GAAG,IAAIf,SAAS,CACnBgB,UAAU,EACV;MAAEI,QAAQ,EAAED;IAAgB,CAAC,EAC7BV,QAAQ,EACRC,WACF,CAAC;EACH;EAEA,OAAO;IACLT,MAAM;IACNoB,OAAO,EAAE;MACPN,KAAK;MACLN,QAAQ,EAAEA,QAAQ,IAAI;QACpB;QACA,GAAGP,eAAe;QAClBC,YAAY,EAAE,MAAMA,YAAY,CAAC;MACnC,CAAC;MACDO,WAAW;MACXI,KAAK,EAAEA,KAAK,IAAI,SAAS;MACzBQ,QAAQ,EAAE;QACRC,cAAc,EAAE,6BAA6B;QAC7CC,KAAK,EAAE,CAAC3B,IAAI,CAACO,eAAe,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC;MAC3D,CAAC;MACDqB,WAAW,EAAEpB,cAAc;MAC3BM,8BAA8B;MAC9BC,SAAS;MACTc,OAAO,EAAE,uBAAuB;MAAE;MAClCb;IACF;EACF,CAAC;AACH,CAAC;AAED,OAAO,eAAeI,OAAOA,CAACU,UAAkB,EAAE;EAChD,MAAM;IAAEC;EAAI,CAAC,GAAG9B,KAAK,CAAC6B,UAAU,CAAC;EAEjC,MAAME,UAA4B,GAAG;IACnCC,IAAI,EAAEF,GAAG,KAAK,OAAO,GAAG,MAAM,GAAG;EACnC,CAAC;EAED,MAAMG,UAAU,GAAG,MAAM,CAACJ,UAAU,EAAE;IAAEK,IAAI,EAAEH;EAAW,CAAC,CAExD;EAEF,MAAM;IAAEI,OAAO,EAAEjB;EAAW,CAAC,GAAG,MAAMe,UAAU;EAChD,OAAOf,UAAU;AACnB","ignoreList":[]}
1
+ {"version":3,"file":"configureEnginePlugin.js","names":["join","parse","FORM_PREFIX","FormModel","plugin","defaultServices","formsService","findPackageRoot","devtoolContext","configureEnginePlugin","formFileName","formFilePath","services","controllers","preparePageEventRequestOptions","onRequest","saveAndExit","ordnanceSurveyApiKey","cache","model","definition","getForm","name","initialBasePath","basePath","options","nunjucks","baseLayoutPath","paths","viewContext","baseUrl","importPath","ext","attributes","type","formImport","with","default"],"sources":["../../../../src/server/plugins/engine/configureEnginePlugin.ts"],"sourcesContent":["import { join, parse } from 'node:path'\n\nimport { type FormDefinition } from '@defra/forms-model'\n\nimport { FORM_PREFIX } from '~/src/server/constants.js'\nimport { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'\nimport { plugin } from '~/src/server/plugins/engine/plugin.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport { formsService } from '~/src/server/plugins/engine/services/localFormsService.js'\nimport { type PluginOptions } from '~/src/server/plugins/engine/types.js'\nimport { findPackageRoot } from '~/src/server/plugins/engine/vision.js'\nimport { devtoolContext } from '~/src/server/plugins/nunjucks/context.js'\nimport { type CacheService } from '~/src/server/services/cacheService.js'\nimport { type RouteConfig } from '~/src/server/types.js'\n\nexport const configureEnginePlugin = async (\n {\n formFileName,\n formFilePath,\n services,\n controllers,\n preparePageEventRequestOptions,\n onRequest,\n saveAndExit,\n ordnanceSurveyApiKey\n }: RouteConfig = {},\n cache?: CacheService\n): Promise<{\n plugin: typeof plugin\n options: PluginOptions\n}> => {\n let model: FormModel | undefined\n\n if (formFileName && formFilePath) {\n const definition = await getForm(join(formFilePath, formFileName))\n const { name } = parse(formFileName)\n\n const initialBasePath = `${FORM_PREFIX}${name}`\n\n model = new FormModel(\n definition,\n { basePath: initialBasePath, ordnanceSurveyApiKey },\n services,\n controllers\n )\n }\n\n return {\n plugin,\n options: {\n model,\n services: services ?? {\n // services for testing, else use the disk loader option for running this service locally\n ...defaultServices,\n formsService: await formsService()\n },\n controllers,\n cache: cache ?? 'session',\n nunjucks: {\n baseLayoutPath: 'dxt-devtool-baselayout.html',\n paths: [join(findPackageRoot(), 'src/server/devserver')] // custom layout to make it really clear this is not the same as the runner\n },\n viewContext: devtoolContext,\n preparePageEventRequestOptions,\n onRequest,\n baseUrl: 'http://localhost:3009', // always runs locally\n saveAndExit,\n ordnanceSurveyApiKey\n }\n }\n}\n\nexport async function getForm(importPath: string) {\n const { ext } = parse(importPath)\n\n const attributes: ImportAttributes = {\n type: ext === '.json' ? 'json' : 'module'\n }\n\n const formImport = import(importPath, { with: attributes }) as Promise<{\n default: FormDefinition\n }>\n\n const { default: definition } = await formImport\n return definition\n}\n"],"mappings":"AAAA,SAASA,IAAI,EAAEC,KAAK,QAAQ,WAAW;AAIvC,SAASC,WAAW;AACpB,SAASC,SAAS;AAClB,SAASC,MAAM;AACf,OAAO,KAAKC,eAAe;AAC3B,SAASC,YAAY;AAErB,SAASC,eAAe;AACxB,SAASC,cAAc;AAIvB,OAAO,MAAMC,qBAAqB,GAAG,MAAAA,CACnC;EACEC,YAAY;EACZC,YAAY;EACZC,QAAQ;EACRC,WAAW;EACXC,8BAA8B;EAC9BC,SAAS;EACTC,WAAW;EACXC;AACW,CAAC,GAAG,CAAC,CAAC,EACnBC,KAAoB,KAIhB;EACJ,IAAIC,KAA4B;EAEhC,IAAIT,YAAY,IAAIC,YAAY,EAAE;IAChC,MAAMS,UAAU,GAAG,MAAMC,OAAO,CAACrB,IAAI,CAACW,YAAY,EAAED,YAAY,CAAC,CAAC;IAClE,MAAM;MAAEY;IAAK,CAAC,GAAGrB,KAAK,CAACS,YAAY,CAAC;IAEpC,MAAMa,eAAe,GAAG,GAAGrB,WAAW,GAAGoB,IAAI,EAAE;IAE/CH,KAAK,GAAG,IAAIhB,SAAS,CACnBiB,UAAU,EACV;MAAEI,QAAQ,EAAED,eAAe;MAAEN;IAAqB,CAAC,EACnDL,QAAQ,EACRC,WACF,CAAC;EACH;EAEA,OAAO;IACLT,MAAM;IACNqB,OAAO,EAAE;MACPN,KAAK;MACLP,QAAQ,EAAEA,QAAQ,IAAI;QACpB;QACA,GAAGP,eAAe;QAClBC,YAAY,EAAE,MAAMA,YAAY,CAAC;MACnC,CAAC;MACDO,WAAW;MACXK,KAAK,EAAEA,KAAK,IAAI,SAAS;MACzBQ,QAAQ,EAAE;QACRC,cAAc,EAAE,6BAA6B;QAC7CC,KAAK,EAAE,CAAC5B,IAAI,CAACO,eAAe,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC;MAC3D,CAAC;MACDsB,WAAW,EAAErB,cAAc;MAC3BM,8BAA8B;MAC9BC,SAAS;MACTe,OAAO,EAAE,uBAAuB;MAAE;MAClCd,WAAW;MACXC;IACF;EACF,CAAC;AACH,CAAC;AAED,OAAO,eAAeI,OAAOA,CAACU,UAAkB,EAAE;EAChD,MAAM;IAAEC;EAAI,CAAC,GAAG/B,KAAK,CAAC8B,UAAU,CAAC;EAEjC,MAAME,UAA4B,GAAG;IACnCC,IAAI,EAAEF,GAAG,KAAK,OAAO,GAAG,MAAM,GAAG;EACnC,CAAC;EAED,MAAMG,UAAU,GAAG,MAAM,CAACJ,UAAU,EAAE;IAAEK,IAAI,EAAEH;EAAW,CAAC,CAExD;EAEF,MAAM;IAAEI,OAAO,EAAEjB;EAAW,CAAC,GAAG,MAAMe,UAAU;EAChD,OAAOf,UAAU;AACnB","ignoreList":[]}
@@ -19,6 +19,7 @@ export declare class FormModel {
19
19
  values: FormDefinition;
20
20
  basePath: string;
21
21
  versionNumber?: number;
22
+ ordnanceSurveyApiKey?: string;
22
23
  conditions: Partial<Record<string, ExecutableCondition>>;
23
24
  pages: PageControllerClass[];
24
25
  services: Services;
@@ -33,6 +34,7 @@ export declare class FormModel {
33
34
  constructor(def: typeof this.def, options: {
34
35
  basePath: string;
35
36
  versionNumber?: number;
37
+ ordnanceSurveyApiKey?: string;
36
38
  }, services?: Services, controllers?: Record<string, typeof PageController>);
37
39
  /**
38
40
  * build the entire model schema from individual pages/sections and filter out answers
@@ -26,6 +26,7 @@ export class FormModel {
26
26
  values;
27
27
  basePath;
28
28
  versionNumber;
29
+ ordnanceSurveyApiKey;
29
30
  conditions;
30
31
  pages;
31
32
  services;
@@ -82,6 +83,7 @@ export class FormModel {
82
83
  this.values = result.value;
83
84
  this.basePath = options.basePath;
84
85
  this.versionNumber = options.versionNumber;
86
+ this.ordnanceSurveyApiKey = options.ordnanceSurveyApiKey;
85
87
  this.conditions = {};
86
88
  this.services = services;
87
89
  this.controllers = controllers;
@@ -396,7 +398,7 @@ function validateFormPayload(request, page, context) {
396
398
  } = page.getFormParams(request);
397
399
 
398
400
  // Skip validation GET requests or other actions
399
- if (!request.payload || action && ![FormAction.Validate, FormAction.SaveAndExit].includes(action)) {
401
+ if (!request.payload || action && ![FormAction.Validate, FormAction.SaveAndExit].includes(action) && !action.startsWith(FormAction.External)) {
400
402
  return context;
401
403
  }
402
404