@defra/forms-engine-plugin 5.0.0-alpha.7 → 5.0.0-alpha.9

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 (178) hide show
  1. package/.public/javascripts/application.min.js.map +1 -1
  2. package/.public/javascripts/shared.min.js +1 -1
  3. package/.public/javascripts/shared.min.js.map +1 -1
  4. package/.public/stylesheets/application.min.css.map +1 -1
  5. package/.server/client/javascripts/maps.d.ts +5 -0
  6. package/.server/client/javascripts/maps.js +6 -0
  7. package/.server/client/javascripts/maps.js.map +1 -0
  8. package/.server/client/javascripts/shared.d.ts +1 -4
  9. package/.server/client/javascripts/shared.js +1 -4
  10. package/.server/client/javascripts/shared.js.map +1 -1
  11. package/.server/client/stylesheets/maps.scss +4 -0
  12. package/.server/client/stylesheets/shared.scss +1 -5
  13. package/.server/server/constants.d.ts +1 -0
  14. package/.server/server/constants.js +2 -1
  15. package/.server/server/constants.js.map +1 -1
  16. package/.server/server/plugins/engine/components/ComponentCollection.js +10 -6
  17. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  18. package/.server/server/plugins/engine/components/DatePartsField.d.ts +4 -2
  19. package/.server/server/plugins/engine/components/DatePartsField.js +14 -11
  20. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  21. package/.server/server/plugins/engine/components/DeclarationField.d.ts +4 -2
  22. package/.server/server/plugins/engine/components/DeclarationField.js +5 -3
  23. package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
  24. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +24 -2
  25. package/.server/server/plugins/engine/components/EastingNorthingField.js +93 -52
  26. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
  27. package/.server/server/plugins/engine/components/FormComponent.d.ts +4 -1
  28. package/.server/server/plugins/engine/components/FormComponent.js +3 -0
  29. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
  30. package/.server/server/plugins/engine/components/LatLongField.d.ts +24 -2
  31. package/.server/server/plugins/engine/components/LatLongField.js +85 -46
  32. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
  33. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +3 -2
  34. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +10 -11
  35. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
  36. package/.server/server/plugins/engine/components/MonthYearField.d.ts +4 -2
  37. package/.server/server/plugins/engine/components/MonthYearField.js +16 -13
  38. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  39. package/.server/server/plugins/engine/components/PaymentField.d.ts +1 -0
  40. package/.server/server/plugins/engine/components/PaymentField.js +9 -5
  41. package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
  42. package/.server/server/plugins/engine/components/UkAddressField.js +22 -7
  43. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
  44. package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -2
  45. package/.server/server/plugins/engine/components/YesNoField.js +5 -3
  46. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  47. package/.server/server/plugins/engine/components/helpers/components.js +1 -2
  48. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  49. package/.server/server/plugins/engine/components/helpers/index.d.ts +7 -0
  50. package/.server/server/plugins/engine/components/helpers/index.js +13 -1
  51. package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
  52. package/.server/server/plugins/engine/helpers.d.ts +21 -2
  53. package/.server/server/plugins/engine/helpers.js +43 -5
  54. package/.server/server/plugins/engine/helpers.js.map +1 -1
  55. package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
  56. package/.server/server/plugins/engine/i18n/createFormTranslator.js +27 -5
  57. package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
  58. package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
  59. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
  60. package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
  61. package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
  62. package/.server/server/plugins/engine/i18n/form.js +35 -0
  63. package/.server/server/plugins/engine/i18n/form.js.map +1 -0
  64. package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
  65. package/.server/server/plugins/engine/i18n/languages.js +19 -0
  66. package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
  67. package/.server/server/plugins/engine/i18n/translations/cy.json +3 -1
  68. package/.server/server/plugins/engine/i18n/translations/en-GB.json +3 -1
  69. package/.server/server/plugins/engine/index.d.ts +3 -0
  70. package/.server/server/plugins/engine/index.js +3 -0
  71. package/.server/server/plugins/engine/index.js.map +1 -1
  72. package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
  73. package/.server/server/plugins/engine/models/FormModel.js +9 -15
  74. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  75. package/.server/server/plugins/engine/models/SummaryViewModel.js +2 -1
  76. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
  77. package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
  78. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
  79. package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
  80. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
  81. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  82. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +1 -1
  83. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +2 -2
  84. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  85. package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
  86. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -2
  87. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
  88. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +6 -3
  89. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
  90. package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +1 -1
  91. package/.server/server/plugins/engine/pageControllers/helpers/submission.js +3 -3
  92. package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
  93. package/.server/server/plugins/engine/types/schema.js +1 -0
  94. package/.server/server/plugins/engine/types/schema.js.map +1 -1
  95. package/.server/server/plugins/engine/types.d.ts +1 -0
  96. package/.server/server/plugins/engine/types.js.map +1 -1
  97. package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  98. package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
  99. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  100. package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
  101. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
  102. package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
  103. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  104. package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
  105. package/.server/server/plugins/nunjucks/filters/index.js +1 -0
  106. package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
  107. package/.server/server/plugins/payment/helper.d.ts +11 -1
  108. package/.server/server/plugins/payment/helper.js +18 -2
  109. package/.server/server/plugins/payment/helper.js.map +1 -1
  110. package/.server/server/plugins/payment/helper.test.js +2 -1
  111. package/.server/server/plugins/payment/helper.test.js.map +1 -1
  112. package/.server/server/plugins/payment/service.d.ts +2 -1
  113. package/.server/server/plugins/payment/service.js +5 -2
  114. package/.server/server/plugins/payment/service.js.map +1 -1
  115. package/.server/server/plugins/payment/service.test.js +7 -3
  116. package/.server/server/plugins/payment/service.test.js.map +1 -1
  117. package/.server/server/plugins/payment/types.d.ts +4 -0
  118. package/.server/server/plugins/payment/types.js +1 -0
  119. package/.server/server/plugins/payment/types.js.map +1 -1
  120. package/.server/server/plugins/postcode-lookup/models/index.d.ts +247 -3
  121. package/.server/server/plugins/postcode-lookup/models/index.js +86 -33
  122. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  123. package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
  124. package/.server/server/plugins/postcode-lookup/routes/index.js +47 -15
  125. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  126. package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
  127. package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
  128. package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
  129. package/.server/server/plugins/postcode-lookup/types.js +6 -1
  130. package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
  131. package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
  132. package/package.json +7 -1
  133. package/src/client/javascripts/maps.js +5 -0
  134. package/src/client/javascripts/shared.js +1 -4
  135. package/src/client/stylesheets/maps.scss +4 -0
  136. package/src/client/stylesheets/shared.scss +1 -5
  137. package/src/server/constants.js +2 -1
  138. package/src/server/plugins/engine/components/ComponentCollection.ts +15 -9
  139. package/src/server/plugins/engine/components/DatePartsField.ts +16 -12
  140. package/src/server/plugins/engine/components/DeclarationField.ts +6 -4
  141. package/src/server/plugins/engine/components/EastingNorthingField.ts +156 -88
  142. package/src/server/plugins/engine/components/FormComponent.ts +4 -1
  143. package/src/server/plugins/engine/components/LatLongField.ts +129 -57
  144. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +14 -11
  145. package/src/server/plugins/engine/components/MonthYearField.ts +16 -11
  146. package/src/server/plugins/engine/components/PaymentField.ts +9 -4
  147. package/src/server/plugins/engine/components/UkAddressField.ts +29 -6
  148. package/src/server/plugins/engine/components/YesNoField.ts +6 -5
  149. package/src/server/plugins/engine/components/helpers/components.ts +1 -2
  150. package/src/server/plugins/engine/components/helpers/index.ts +19 -0
  151. package/src/server/plugins/engine/helpers.ts +51 -5
  152. package/src/server/plugins/engine/i18n/createFormTranslator.ts +43 -12
  153. package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
  154. package/src/server/plugins/engine/i18n/form.ts +54 -0
  155. package/src/server/plugins/engine/i18n/languages.ts +19 -0
  156. package/src/server/plugins/engine/i18n/translations/cy.json +3 -1
  157. package/src/server/plugins/engine/i18n/translations/en-GB.json +3 -1
  158. package/src/server/plugins/engine/index.ts +6 -0
  159. package/src/server/plugins/engine/models/FormModel.ts +9 -15
  160. package/src/server/plugins/engine/models/SummaryViewModel.ts +2 -1
  161. package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
  162. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
  163. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +2 -2
  164. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -2
  165. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +9 -3
  166. package/src/server/plugins/engine/pageControllers/helpers/submission.ts +6 -3
  167. package/src/server/plugins/engine/types/schema.ts +1 -0
  168. package/src/server/plugins/engine/types.ts +1 -0
  169. package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
  170. package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
  171. package/src/server/plugins/nunjucks/filters/index.js +1 -0
  172. package/src/server/plugins/payment/helper.js +22 -2
  173. package/src/server/plugins/payment/service.js +6 -2
  174. package/src/server/plugins/payment/types.js +1 -0
  175. package/src/server/plugins/postcode-lookup/models/index.js +75 -43
  176. package/src/server/plugins/postcode-lookup/routes/index.js +73 -16
  177. package/src/server/plugins/postcode-lookup/types.js +6 -1
  178. package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"FileUploadPageController.js","names":["ComponentType","Boom","wait","StatusCodes","FileUploadField","tempItemSchema","getCacheService","getError","getExponentialBackoffDelay","QuestionPageController","getProxyUrlForLocalDevelopment","getUploadStatus","initiateUpload","FileStatus","UploadStatus","MAX_UPLOADS","CDP_UPLOAD_TIMEOUT_MS","prepareStatus","status","file","form","isPending","fileStatus","pending","errorMessage","prepareFileState","fileState","FileUploadPageController","fileUpload","fileDeleteViewName","constructor","model","pageDef","collection","fileUploads","fields","filter","field","type","at","length","badImplementation","path","indexOf","name","viewName","getStateKeys","component","pagePath","page","getFormDataFromState","request","state","payload","files","getFilesFromState","undefined","getState","refreshUpload","uploadState","upload","getUploadFromState","makeGetItemDeleteRouteHandler","context","h","viewModel","params","fileToRemove","find","fileId","itemId","notFound","filename","translator","getTranslator","t","view","backLink","getBackLink","pageTitle","itemTitle","confirmation","text","buttonConfirm","buttonCancel","makePostItemDeleteRouteHandler","confirm","getFormParams","checkRemovedFiles","proceed","getErrors","details","errors","forEach","error","isUploadError","isUploadRootError","push","value","href","getViewModel","components","formComponent","id","count","summaryList","rows","uploadingLabel","index","proxyUrl","uploadUrl","formAction","uploadId","componentsBefore","slice","checkUploadStatus","depth","initiateAndStoreNewUpload","statusResponse","err","isBoom","output","statusCode","NOT_FOUND","valueOf","badRequest","uploadStatus","initiated","Error","logger","gatewayTimeout","toFixed","delay","info","validationResult","validate","stripUnknown","processUploadedFiles","validatedItem","validatedStatus","rawFile","uploadedFiles","Array","isArray","allErrors","complete","perFileState","unshift","cacheService","server","setFlash","some","f","mergeState","filesUpdated","options","schema","getFormMetadata","services","formsService","max","Math","min","formMetadata","slug","notificationEmail","newUpload","accept"],"sources":["../../../../../src/server/plugins/engine/pageControllers/FileUploadPageController.ts"],"sourcesContent":["import { ComponentType, type PageFileUpload } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { wait } from '@hapi/hoek'\nimport { StatusCodes } from 'http-status-codes'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n FileUploadField,\n tempItemSchema\n} from '~/src/server/plugins/engine/components/FileUploadField.js'\nimport { type FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n getCacheService,\n getError,\n getExponentialBackoffDelay\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { getProxyUrlForLocalDevelopment } from '~/src/server/plugins/engine/pageControllers/helpers/index.js'\nimport {\n getUploadStatus,\n initiateUpload\n} from '~/src/server/plugins/engine/services/uploadService.js'\nimport {\n FileStatus,\n UploadStatus,\n type AnyFormRequest,\n type FeaturedFormPageViewModel,\n type FileState,\n type FileUpload,\n type FormContext,\n type FormContextRequest,\n type FormSubmissionError,\n type FormSubmissionState,\n type ItemDeletePageViewModel,\n type UploadInitiateResponse,\n type UploadStatusFileResponse\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\n\nconst MAX_UPLOADS = 25\nconst CDP_UPLOAD_TIMEOUT_MS = 60000 // 1 minute\n\nexport function prepareStatus(status: UploadStatusFileResponse) {\n const file = status.form.file\n const isPending = file.fileStatus === FileStatus.pending\n\n if (!file.errorMessage && isPending) {\n file.errorMessage = 'The selected file has not fully uploaded'\n }\n\n return status\n}\n\nfunction prepareFileState(fileState: FileState) {\n prepareStatus(fileState.status)\n\n return fileState\n}\n\nexport class FileUploadPageController extends QuestionPageController {\n declare pageDef: PageFileUpload\n\n fileUpload: FileUploadField\n fileDeleteViewName = 'item-delete'\n\n constructor(model: FormModel, pageDef: PageFileUpload) {\n super(model, pageDef)\n\n const { collection } = this\n\n // Get the file upload fields from the collection\n const fileUploads = collection.fields.filter(\n (field): field is FileUploadField =>\n field.type === ComponentType.FileUploadField\n )\n\n const fileUpload = fileUploads.at(0)\n\n // Assert we have exactly 1 file upload component\n if (!fileUpload || fileUploads.length > 1) {\n throw Boom.badImplementation(\n `Expected 1 FileUploadFieldComponent in FileUploadPageController '${pageDef.path}'`\n )\n }\n\n // Assert the file upload component is the first form component\n if (collection.fields.indexOf(fileUpload) !== 0) {\n throw Boom.badImplementation(\n `Expected '${fileUpload.name}' to be the first form component in FileUploadPageController '${pageDef.path}'`\n )\n }\n\n // Assign the file upload component to the controller\n this.fileUpload = fileUpload\n this.viewName = 'file-upload'\n }\n\n /**\n * Get supplementary state keys for clearing file upload state.\n * Returns the nested upload path for FileUploadField components only.\n * @param component - The component to get supplementary state keys for\n * @returns Array containing the nested upload path, e.g., [\"upload['/page-path']\"]\n * or ['upload'] if no page path is available. Returns empty array for non-FileUploadField components.\n */\n getStateKeys(component: FormComponent): string[] {\n // Only return upload keys for FileUploadField components\n if (!(component instanceof FileUploadField)) {\n return []\n }\n\n const pagePath = component.page?.path\n return pagePath ? [`upload['${pagePath}']`] : ['upload']\n }\n\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ) {\n const { fileUpload } = this\n\n const payload = super.getFormDataFromState(request, state)\n const files = this.getFilesFromState(state)\n\n // Append the files to the payload\n payload[fileUpload.name] = files.length ? files : undefined\n\n return payload\n }\n\n async getState(request: AnyFormRequest) {\n const { fileUpload } = this\n\n // Get the actual state\n const state = await super.getState(request)\n const files = this.getFilesFromState(state)\n\n // Overwrite the files with those in the upload state\n state[fileUpload.name] = files\n\n return this.refreshUpload(request, state)\n }\n\n /**\n * Get the uploaded files from state.\n */\n getFilesFromState(state: FormSubmissionState) {\n const { path } = this\n\n const uploadState = state.upload?.[path]\n return uploadState?.files ?? []\n }\n\n /**\n * Get the initiated upload from state.\n */\n getUploadFromState(state: FormSubmissionState) {\n const { path } = this\n\n const uploadState = state.upload?.[path]\n return uploadState?.upload\n }\n\n makeGetItemDeleteRouteHandler() {\n return (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { viewModel } = this\n const { params } = request\n const { state } = context\n\n const files = this.getFilesFromState(state)\n\n const fileToRemove = files.find(\n ({ status }) => status.form.file.fileId === params.itemId\n )\n\n if (!fileToRemove) {\n throw Boom.notFound('File to delete not found')\n }\n\n const { filename } = fileToRemove.status.form.file\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n return h.view(this.fileDeleteViewName, {\n ...viewModel,\n context,\n backLink: this.getBackLink(request, context, t),\n pageTitle: t('pages.fileUpload.removeFileTitle'),\n itemTitle: filename,\n confirmation: { text: t('pages.fileUpload.removeFileBody') },\n buttonConfirm: { text: t('pages.fileUpload.removeFileButton') },\n buttonCancel: { text: t('pages.fileUpload.cancel') },\n t\n } satisfies ItemDeletePageViewModel)\n }\n }\n\n makePostItemDeleteRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { path } = this\n const { state } = context\n\n const { confirm } = this.getFormParams(request)\n\n // Check for any removed files in the POST payload\n if (confirm) {\n await this.checkRemovedFiles(request, state)\n return this.proceed(request, h, path)\n }\n\n return this.proceed(request, h)\n }\n }\n\n getErrors(details?: ValidationErrorItem[]) {\n const { fileUpload } = this\n\n if (details) {\n const errors: FormSubmissionError[] = []\n\n details.forEach((error) => {\n const isUploadError = error.path[0] === fileUpload.name\n const isUploadRootError = isUploadError && error.path.length === 1\n\n if (!isUploadError || isUploadRootError) {\n // The error is for the root of the upload or another\n // field on the page so defer to the getError helper\n errors.push(getError(error))\n } else {\n const { context, path, type } = error\n\n if (type === 'object.unknown' && path.at(-1) === 'errorMessage') {\n const value = context?.value as string | undefined\n\n if (value) {\n const name = fileUpload.name\n const text = typeof value === 'string' ? value : 'Unknown error'\n const href = `#${name}`\n\n errors.push({ path, href, name, text })\n }\n }\n }\n })\n\n return errors\n }\n }\n\n getViewModel(\n request: FormContextRequest,\n context: FormContext,\n translator: Translator\n ): FeaturedFormPageViewModel {\n const { fileUpload } = this\n const { state } = context\n const { t } = translator\n\n const upload = this.getUploadFromState(state)\n\n const viewModel = super.getViewModel(request, context, translator)\n const { components } = viewModel\n\n // Featured form component\n const [formComponent] = components.filter(\n ({ model }) => model.id === fileUpload.name\n )\n\n formComponent.model.upload = {\n count: formComponent.model.upload?.count ?? 0,\n summaryList: formComponent.model.upload?.summaryList ?? { rows: [] },\n uploadingLabel: t('components.fileUploadField.uploading')\n }\n\n const index = components.indexOf(formComponent)\n\n const proxyUrl = getProxyUrlForLocalDevelopment(upload?.uploadUrl)\n\n return {\n ...viewModel,\n formAction: upload?.uploadUrl,\n uploadId: upload?.uploadId,\n formComponent,\n\n // Split out components before/after\n componentsBefore: components.slice(0, index),\n components: components.slice(index),\n proxyUrl,\n t\n }\n }\n\n /**\n * Refreshes the CDP upload and files in the\n * state and checks for any removed files.\n *\n * If an upload exists and hasn't been consumed\n * it gets re-used, otherwise we initiate a new one.\n * @param request - the hapi request\n * @param state - the form state\n */\n private async refreshUpload(\n request: AnyFormRequest,\n state: FormSubmissionState\n ) {\n state = await this.checkUploadStatus(request, state)\n\n return state\n }\n\n /**\n * If an upload exists and hasn't been consumed\n * it gets re-used, otherwise a new one is initiated.\n * @param request - the hapi request\n * @param state - the form state\n * @param depth - the number of retries so far\n */\n private async checkUploadStatus(\n request: AnyFormRequest,\n state: FormSubmissionState,\n depth = 1\n ): Promise<FormSubmissionState> {\n const upload = this.getUploadFromState(state)\n const files = this.getFilesFromState(state)\n\n // If no upload exists, initiate a new one.\n if (!upload?.uploadId) {\n return this.initiateAndStoreNewUpload(request, state)\n }\n\n const uploadId = upload.uploadId\n\n let statusResponse\n\n try {\n statusResponse = await getUploadStatus(uploadId)\n } catch (err) {\n // if the user loads a file upload page and queries the cached upload, after the upload has\n // expired in CDP, we will get a 404 from the getUploadStatus endpoint.\n // In this case we want to initiate a new upload and return that state, so the form\n // doesn't blow up for the end user.\n if (\n Boom.isBoom(err) &&\n err.output.statusCode === StatusCodes.NOT_FOUND.valueOf()\n ) {\n return this.initiateAndStoreNewUpload(request, state)\n }\n throw err\n }\n\n if (!statusResponse) {\n throw Boom.badRequest(\n `Unexpected empty response from getUploadStatus for ${uploadId}`\n )\n }\n\n // Re-use the upload if it is still in the \"initiated\" state.\n if (statusResponse.uploadStatus === UploadStatus.initiated) {\n return state\n }\n\n if (statusResponse.uploadStatus === UploadStatus.pending) {\n // Using exponential backoff delays:\n // Depth 1: 2000ms, Depth 2: 4000ms, Depth 3: 8000ms, Depth 4: 16000ms, Depth 5+: 30000ms (capped)\n // A depth of 5 (or more) implies cumulative delays roughly reaching 55 seconds.\n if (depth >= 5) {\n const err = new Error(\n `Exceeded cumulative retry delay for ${uploadId} (depth: ${depth}). Re-initiating a new upload.`\n )\n request.logger.error(\n err,\n `[uploadTimeout] Exceeded cumulative retry delay for uploadId: ${uploadId} at depth: ${depth} - re-initiating new upload`\n )\n await this.initiateAndStoreNewUpload(request, state)\n throw Boom.gatewayTimeout(\n `Timed out waiting for ${uploadId} after cumulative retries exceeding ${((CDP_UPLOAD_TIMEOUT_MS - 5000) / 1000).toFixed(0)} seconds`\n )\n }\n const delay = getExponentialBackoffDelay(depth)\n request.logger.info(\n `[uploadRetry] Waiting ${delay / 1000} seconds for uploadId: ${uploadId} to complete (retry depth: ${depth})`\n )\n await wait(delay)\n return this.checkUploadStatus(request, state, depth + 1)\n }\n\n // Only add to files state if the file validates.\n // This secures against html tampering of the file input\n // (e.g. changing it to a simple text field or similar).\n const validationResult = tempItemSchema.validate(\n { uploadId, status: statusResponse },\n { stripUnknown: true }\n )\n const error = validationResult.error\n\n if (error) {\n return this.initiateAndStoreNewUpload(request, state)\n }\n\n // CDP returns form.file as a single object for one file,\n // or an array for multiple files. The Joi schema normalises\n // both to an array via .single().\n await this.processUploadedFiles(\n request,\n state,\n validationResult.value,\n files,\n upload\n )\n\n return this.initiateAndStoreNewUpload(request, state)\n }\n\n /**\n * Processes the uploaded files from a CDP status response.\n * Complete files are added to state, rejected/pending files\n * have their error messages flashed.\n * @param request - the hapi request\n * @param state - the form state\n * @param validatedItem - the Joi-validated upload item\n * @param files - the current files array from state\n * @param upload - the current upload initiation response\n */\n private async processUploadedFiles(\n request: AnyFormRequest,\n state: FormSubmissionState,\n validatedItem: FileState,\n files: FileState[],\n upload: UploadInitiateResponse | undefined\n ) {\n const { uploadId } = validatedItem\n const validatedStatus = validatedItem.status\n const rawFile = validatedStatus.form.file as unknown as\n | FileUpload\n | FileUpload[]\n const uploadedFiles = Array.isArray(rawFile) ? rawFile : [rawFile]\n\n const allErrors: FormSubmissionError[] = []\n\n for (const file of uploadedFiles) {\n if (file.fileStatus === FileStatus.complete) {\n const perFileState: FileState = {\n uploadId,\n status: {\n ...validatedStatus,\n form: { file }\n } as FileState['status']\n }\n files.unshift(prepareFileState(perFileState))\n } else {\n // Collect the error for rejected/pending files.\n const { fileUpload } = this\n const name = fileUpload.name\n const text = file.errorMessage ?? 'Unknown error'\n allErrors.push({ path: [name], href: `#${name}`, name, text })\n }\n }\n\n if (allErrors.length) {\n const cacheService = getCacheService(request.server)\n cacheService.setFlash(request, { errors: allErrors })\n }\n\n if (uploadedFiles.some((f) => f.fileStatus === FileStatus.complete)) {\n await this.mergeState(request, state, {\n upload: { [this.path]: { files, upload } }\n })\n }\n }\n\n /**\n * Checks the payload for a file getting removed\n * and removes it from the upload files if found\n * @param request - the hapi request\n * @param state - the form state\n * @returns updated state if any files have been removed\n */\n private async checkRemovedFiles(\n request: FormRequestPayload,\n state: FormSubmissionState\n ) {\n const { path } = this\n const { params } = request\n\n const upload = this.getUploadFromState(state)\n const files = this.getFilesFromState(state)\n\n const filesUpdated = files.filter(\n ({ status }) => status.form.file.fileId !== params.itemId\n )\n\n if (filesUpdated.length === files.length) {\n return\n }\n\n await this.mergeState(request, state, {\n upload: { [path]: { files: filesUpdated, upload } }\n })\n }\n\n /**\n * Initiates a CDP file upload and stores in the upload state\n * @param request - the hapi request\n * @param state - the form state\n */\n private async initiateAndStoreNewUpload(\n request: AnyFormRequest,\n state: FormSubmissionState\n ) {\n const { fileUpload, href, path } = this\n const { options, schema } = fileUpload\n const { getFormMetadata } = this.model.services.formsService\n\n const files = this.getFilesFromState(state)\n\n // Reset the upload in state\n let upload: UploadInitiateResponse | undefined\n\n // Don't initiate anymore after minimum of `schema.max` or MAX_UPLOADS\n const max = Math.min(schema.max ?? MAX_UPLOADS, MAX_UPLOADS)\n\n if (files.length < max) {\n const formMetadata = await getFormMetadata(request.params.slug)\n const notificationEmail =\n formMetadata.notificationEmail ?? 'defraforms@defra.gov.uk'\n\n const newUpload = await initiateUpload(\n href,\n notificationEmail,\n options.accept\n )\n\n if (newUpload === undefined) {\n throw Boom.badRequest('Unexpected empty response from initiateUpload')\n }\n\n upload = newUpload\n }\n\n return this.mergeState(request, state, {\n upload: { [path]: { files, upload } }\n })\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FileUploadPageController.js","names":["ComponentType","Boom","wait","StatusCodes","FileUploadField","tempItemSchema","getCacheService","getError","getExponentialBackoffDelay","QuestionPageController","getProxyUrlForLocalDevelopment","getUploadStatus","initiateUpload","FileStatus","UploadStatus","MAX_UPLOADS","CDP_UPLOAD_TIMEOUT_MS","prepareStatus","status","file","form","isPending","fileStatus","pending","errorMessage","prepareFileState","fileState","FileUploadPageController","fileUpload","fileDeleteViewName","constructor","model","pageDef","collection","fileUploads","fields","filter","field","type","at","length","badImplementation","path","indexOf","name","viewName","getStateKeys","component","pagePath","page","getFormDataFromState","request","state","payload","files","getFilesFromState","undefined","getState","refreshUpload","uploadState","upload","getUploadFromState","makeGetItemDeleteRouteHandler","context","h","viewModel","params","fileToRemove","find","fileId","itemId","notFound","filename","translator","getTranslator","t","view","backLink","getBackLink","pageTitle","itemTitle","confirmation","text","buttonConfirm","buttonCancel","makePostItemDeleteRouteHandler","confirm","getFormParams","checkRemovedFiles","proceed","getErrors","details","language","errors","forEach","error","isUploadError","isUploadRootError","push","value","href","getViewModel","components","formComponent","id","count","summaryList","rows","uploadingLabel","index","proxyUrl","uploadUrl","formAction","uploadId","componentsBefore","slice","checkUploadStatus","depth","initiateAndStoreNewUpload","statusResponse","err","isBoom","output","statusCode","NOT_FOUND","valueOf","badRequest","uploadStatus","initiated","Error","logger","gatewayTimeout","toFixed","delay","info","validationResult","validate","stripUnknown","processUploadedFiles","validatedItem","validatedStatus","rawFile","uploadedFiles","Array","isArray","allErrors","complete","perFileState","unshift","cacheService","server","setFlash","some","f","mergeState","filesUpdated","options","schema","getFormMetadata","services","formsService","max","Math","min","formMetadata","slug","notificationEmail","newUpload","accept"],"sources":["../../../../../src/server/plugins/engine/pageControllers/FileUploadPageController.ts"],"sourcesContent":["import { ComponentType, type PageFileUpload } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { wait } from '@hapi/hoek'\nimport { StatusCodes } from 'http-status-codes'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n FileUploadField,\n tempItemSchema\n} from '~/src/server/plugins/engine/components/FileUploadField.js'\nimport { type FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n getCacheService,\n getError,\n getExponentialBackoffDelay\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport { getProxyUrlForLocalDevelopment } from '~/src/server/plugins/engine/pageControllers/helpers/index.js'\nimport {\n getUploadStatus,\n initiateUpload\n} from '~/src/server/plugins/engine/services/uploadService.js'\nimport {\n FileStatus,\n UploadStatus,\n type AnyFormRequest,\n type FeaturedFormPageViewModel,\n type FileState,\n type FileUpload,\n type FormContext,\n type FormContextRequest,\n type FormSubmissionError,\n type FormSubmissionState,\n type ItemDeletePageViewModel,\n type UploadInitiateResponse,\n type UploadStatusFileResponse\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\n\nconst MAX_UPLOADS = 25\nconst CDP_UPLOAD_TIMEOUT_MS = 60000 // 1 minute\n\nexport function prepareStatus(status: UploadStatusFileResponse) {\n const file = status.form.file\n const isPending = file.fileStatus === FileStatus.pending\n\n if (!file.errorMessage && isPending) {\n file.errorMessage = 'The selected file has not fully uploaded'\n }\n\n return status\n}\n\nfunction prepareFileState(fileState: FileState) {\n prepareStatus(fileState.status)\n\n return fileState\n}\n\nexport class FileUploadPageController extends QuestionPageController {\n declare pageDef: PageFileUpload\n\n fileUpload: FileUploadField\n fileDeleteViewName = 'item-delete'\n\n constructor(model: FormModel, pageDef: PageFileUpload) {\n super(model, pageDef)\n\n const { collection } = this\n\n // Get the file upload fields from the collection\n const fileUploads = collection.fields.filter(\n (field): field is FileUploadField =>\n field.type === ComponentType.FileUploadField\n )\n\n const fileUpload = fileUploads.at(0)\n\n // Assert we have exactly 1 file upload component\n if (!fileUpload || fileUploads.length > 1) {\n throw Boom.badImplementation(\n `Expected 1 FileUploadFieldComponent in FileUploadPageController '${pageDef.path}'`\n )\n }\n\n // Assert the file upload component is the first form component\n if (collection.fields.indexOf(fileUpload) !== 0) {\n throw Boom.badImplementation(\n `Expected '${fileUpload.name}' to be the first form component in FileUploadPageController '${pageDef.path}'`\n )\n }\n\n // Assign the file upload component to the controller\n this.fileUpload = fileUpload\n this.viewName = 'file-upload'\n }\n\n /**\n * Get supplementary state keys for clearing file upload state.\n * Returns the nested upload path for FileUploadField components only.\n * @param component - The component to get supplementary state keys for\n * @returns Array containing the nested upload path, e.g., [\"upload['/page-path']\"]\n * or ['upload'] if no page path is available. Returns empty array for non-FileUploadField components.\n */\n getStateKeys(component: FormComponent): string[] {\n // Only return upload keys for FileUploadField components\n if (!(component instanceof FileUploadField)) {\n return []\n }\n\n const pagePath = component.page?.path\n return pagePath ? [`upload['${pagePath}']`] : ['upload']\n }\n\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ) {\n const { fileUpload } = this\n\n const payload = super.getFormDataFromState(request, state)\n const files = this.getFilesFromState(state)\n\n // Append the files to the payload\n payload[fileUpload.name] = files.length ? files : undefined\n\n return payload\n }\n\n async getState(request: AnyFormRequest) {\n const { fileUpload } = this\n\n // Get the actual state\n const state = await super.getState(request)\n const files = this.getFilesFromState(state)\n\n // Overwrite the files with those in the upload state\n state[fileUpload.name] = files\n\n return this.refreshUpload(request, state)\n }\n\n /**\n * Get the uploaded files from state.\n */\n getFilesFromState(state: FormSubmissionState) {\n const { path } = this\n\n const uploadState = state.upload?.[path]\n return uploadState?.files ?? []\n }\n\n /**\n * Get the initiated upload from state.\n */\n getUploadFromState(state: FormSubmissionState) {\n const { path } = this\n\n const uploadState = state.upload?.[path]\n return uploadState?.upload\n }\n\n makeGetItemDeleteRouteHandler() {\n return (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { viewModel } = this\n const { params } = request\n const { state } = context\n\n const files = this.getFilesFromState(state)\n\n const fileToRemove = files.find(\n ({ status }) => status.form.file.fileId === params.itemId\n )\n\n if (!fileToRemove) {\n throw Boom.notFound('File to delete not found')\n }\n\n const { filename } = fileToRemove.status.form.file\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n return h.view(this.fileDeleteViewName, {\n ...viewModel,\n context,\n backLink: this.getBackLink(request, context, t),\n pageTitle: t('pages.fileUpload.removeFileTitle'),\n itemTitle: filename,\n confirmation: { text: t('pages.fileUpload.removeFileBody') },\n buttonConfirm: { text: t('pages.fileUpload.removeFileButton') },\n buttonCancel: { text: t('pages.fileUpload.cancel') },\n t\n } satisfies ItemDeletePageViewModel)\n }\n }\n\n makePostItemDeleteRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { path } = this\n const { state } = context\n\n const { confirm } = this.getFormParams(request)\n\n // Check for any removed files in the POST payload\n if (confirm) {\n await this.checkRemovedFiles(request, state)\n return this.proceed(request, h, path)\n }\n\n return this.proceed(request, h)\n }\n }\n\n getErrors(details?: ValidationErrorItem[], language?: string) {\n const { fileUpload } = this\n\n if (details) {\n const errors: FormSubmissionError[] = []\n\n details.forEach((error) => {\n const isUploadError = error.path[0] === fileUpload.name\n const isUploadRootError = isUploadError && error.path.length === 1\n\n if (!isUploadError || isUploadRootError) {\n // The error is for the root of the upload or another\n // field on the page so defer to the getError helper\n errors.push(getError(language, error))\n } else {\n const { context, path, type } = error\n\n if (type === 'object.unknown' && path.at(-1) === 'errorMessage') {\n const value = context?.value as string | undefined\n\n if (value) {\n const name = fileUpload.name\n const text = typeof value === 'string' ? value : 'Unknown error'\n const href = `#${name}`\n\n errors.push({ path, href, name, text })\n }\n }\n }\n })\n\n return errors\n }\n }\n\n getViewModel(\n request: FormContextRequest,\n context: FormContext,\n translator: Translator\n ): FeaturedFormPageViewModel {\n const { fileUpload } = this\n const { state } = context\n const { t } = translator\n\n const upload = this.getUploadFromState(state)\n\n const viewModel = super.getViewModel(request, context, translator)\n const { components } = viewModel\n\n // Featured form component\n const [formComponent] = components.filter(\n ({ model }) => model.id === fileUpload.name\n )\n\n formComponent.model.upload = {\n count: formComponent.model.upload?.count ?? 0,\n summaryList: formComponent.model.upload?.summaryList ?? { rows: [] },\n uploadingLabel: t('components.fileUploadField.uploading')\n }\n\n const index = components.indexOf(formComponent)\n\n const proxyUrl = getProxyUrlForLocalDevelopment(upload?.uploadUrl)\n\n return {\n ...viewModel,\n formAction: upload?.uploadUrl,\n uploadId: upload?.uploadId,\n formComponent,\n\n // Split out components before/after\n componentsBefore: components.slice(0, index),\n components: components.slice(index),\n proxyUrl,\n t\n }\n }\n\n /**\n * Refreshes the CDP upload and files in the\n * state and checks for any removed files.\n *\n * If an upload exists and hasn't been consumed\n * it gets re-used, otherwise we initiate a new one.\n * @param request - the hapi request\n * @param state - the form state\n */\n private async refreshUpload(\n request: AnyFormRequest,\n state: FormSubmissionState\n ) {\n state = await this.checkUploadStatus(request, state)\n\n return state\n }\n\n /**\n * If an upload exists and hasn't been consumed\n * it gets re-used, otherwise a new one is initiated.\n * @param request - the hapi request\n * @param state - the form state\n * @param depth - the number of retries so far\n */\n private async checkUploadStatus(\n request: AnyFormRequest,\n state: FormSubmissionState,\n depth = 1\n ): Promise<FormSubmissionState> {\n const upload = this.getUploadFromState(state)\n const files = this.getFilesFromState(state)\n\n // If no upload exists, initiate a new one.\n if (!upload?.uploadId) {\n return this.initiateAndStoreNewUpload(request, state)\n }\n\n const uploadId = upload.uploadId\n\n let statusResponse\n\n try {\n statusResponse = await getUploadStatus(uploadId)\n } catch (err) {\n // if the user loads a file upload page and queries the cached upload, after the upload has\n // expired in CDP, we will get a 404 from the getUploadStatus endpoint.\n // In this case we want to initiate a new upload and return that state, so the form\n // doesn't blow up for the end user.\n if (\n Boom.isBoom(err) &&\n err.output.statusCode === StatusCodes.NOT_FOUND.valueOf()\n ) {\n return this.initiateAndStoreNewUpload(request, state)\n }\n throw err\n }\n\n if (!statusResponse) {\n throw Boom.badRequest(\n `Unexpected empty response from getUploadStatus for ${uploadId}`\n )\n }\n\n // Re-use the upload if it is still in the \"initiated\" state.\n if (statusResponse.uploadStatus === UploadStatus.initiated) {\n return state\n }\n\n if (statusResponse.uploadStatus === UploadStatus.pending) {\n // Using exponential backoff delays:\n // Depth 1: 2000ms, Depth 2: 4000ms, Depth 3: 8000ms, Depth 4: 16000ms, Depth 5+: 30000ms (capped)\n // A depth of 5 (or more) implies cumulative delays roughly reaching 55 seconds.\n if (depth >= 5) {\n const err = new Error(\n `Exceeded cumulative retry delay for ${uploadId} (depth: ${depth}). Re-initiating a new upload.`\n )\n request.logger.error(\n err,\n `[uploadTimeout] Exceeded cumulative retry delay for uploadId: ${uploadId} at depth: ${depth} - re-initiating new upload`\n )\n await this.initiateAndStoreNewUpload(request, state)\n throw Boom.gatewayTimeout(\n `Timed out waiting for ${uploadId} after cumulative retries exceeding ${((CDP_UPLOAD_TIMEOUT_MS - 5000) / 1000).toFixed(0)} seconds`\n )\n }\n const delay = getExponentialBackoffDelay(depth)\n request.logger.info(\n `[uploadRetry] Waiting ${delay / 1000} seconds for uploadId: ${uploadId} to complete (retry depth: ${depth})`\n )\n await wait(delay)\n return this.checkUploadStatus(request, state, depth + 1)\n }\n\n // Only add to files state if the file validates.\n // This secures against html tampering of the file input\n // (e.g. changing it to a simple text field or similar).\n const validationResult = tempItemSchema.validate(\n { uploadId, status: statusResponse },\n { stripUnknown: true }\n )\n const error = validationResult.error\n\n if (error) {\n return this.initiateAndStoreNewUpload(request, state)\n }\n\n // CDP returns form.file as a single object for one file,\n // or an array for multiple files. The Joi schema normalises\n // both to an array via .single().\n await this.processUploadedFiles(\n request,\n state,\n validationResult.value,\n files,\n upload\n )\n\n return this.initiateAndStoreNewUpload(request, state)\n }\n\n /**\n * Processes the uploaded files from a CDP status response.\n * Complete files are added to state, rejected/pending files\n * have their error messages flashed.\n * @param request - the hapi request\n * @param state - the form state\n * @param validatedItem - the Joi-validated upload item\n * @param files - the current files array from state\n * @param upload - the current upload initiation response\n */\n private async processUploadedFiles(\n request: AnyFormRequest,\n state: FormSubmissionState,\n validatedItem: FileState,\n files: FileState[],\n upload: UploadInitiateResponse | undefined\n ) {\n const { uploadId } = validatedItem\n const validatedStatus = validatedItem.status\n const rawFile = validatedStatus.form.file as unknown as\n | FileUpload\n | FileUpload[]\n const uploadedFiles = Array.isArray(rawFile) ? rawFile : [rawFile]\n\n const allErrors: FormSubmissionError[] = []\n\n for (const file of uploadedFiles) {\n if (file.fileStatus === FileStatus.complete) {\n const perFileState: FileState = {\n uploadId,\n status: {\n ...validatedStatus,\n form: { file }\n } as FileState['status']\n }\n files.unshift(prepareFileState(perFileState))\n } else {\n // Collect the error for rejected/pending files.\n const { fileUpload } = this\n const name = fileUpload.name\n const text = file.errorMessage ?? 'Unknown error'\n allErrors.push({ path: [name], href: `#${name}`, name, text })\n }\n }\n\n if (allErrors.length) {\n const cacheService = getCacheService(request.server)\n cacheService.setFlash(request, { errors: allErrors })\n }\n\n if (uploadedFiles.some((f) => f.fileStatus === FileStatus.complete)) {\n await this.mergeState(request, state, {\n upload: { [this.path]: { files, upload } }\n })\n }\n }\n\n /**\n * Checks the payload for a file getting removed\n * and removes it from the upload files if found\n * @param request - the hapi request\n * @param state - the form state\n * @returns updated state if any files have been removed\n */\n private async checkRemovedFiles(\n request: FormRequestPayload,\n state: FormSubmissionState\n ) {\n const { path } = this\n const { params } = request\n\n const upload = this.getUploadFromState(state)\n const files = this.getFilesFromState(state)\n\n const filesUpdated = files.filter(\n ({ status }) => status.form.file.fileId !== params.itemId\n )\n\n if (filesUpdated.length === files.length) {\n return\n }\n\n await this.mergeState(request, state, {\n upload: { [path]: { files: filesUpdated, upload } }\n })\n }\n\n /**\n * Initiates a CDP file upload and stores in the upload state\n * @param request - the hapi request\n * @param state - the form state\n */\n private async initiateAndStoreNewUpload(\n request: AnyFormRequest,\n state: FormSubmissionState\n ) {\n const { fileUpload, href, path } = this\n const { options, schema } = fileUpload\n const { getFormMetadata } = this.model.services.formsService\n\n const files = this.getFilesFromState(state)\n\n // Reset the upload in state\n let upload: UploadInitiateResponse | undefined\n\n // Don't initiate anymore after minimum of `schema.max` or MAX_UPLOADS\n const max = Math.min(schema.max ?? MAX_UPLOADS, MAX_UPLOADS)\n\n if (files.length < max) {\n const formMetadata = await getFormMetadata(request.params.slug)\n const notificationEmail =\n formMetadata.notificationEmail ?? 'defraforms@defra.gov.uk'\n\n const newUpload = await initiateUpload(\n href,\n notificationEmail,\n options.accept\n )\n\n if (newUpload === undefined) {\n throw Boom.badRequest('Unexpected empty response from initiateUpload')\n }\n\n upload = newUpload\n }\n\n return this.mergeState(request, state, {\n upload: { [path]: { files, upload } }\n })\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -37,7 +37,7 @@ export declare class QuestionPageController extends PageController {
37
37
  */
38
38
  getFormParams(request?: FormContextRequest): FormPayloadParams;
39
39
  getStateFromValidForm(request: FormContextRequest, state: FormSubmissionState, payload: FormPayload): FormState;
40
- getErrors(details?: ValidationErrorItem[]): import("../../../../server/plugins/engine/types.js").FormSubmissionError[] | undefined;
40
+ getErrors(details?: ValidationErrorItem[], language?: string): import("../../../../server/plugins/engine/types.js").FormSubmissionError[] | undefined;
41
41
  getState(request: AnyFormRequest): Promise<FormSubmissionState>;
42
42
  setState(request: AnyFormRequest, state: FormSubmissionState): Promise<FormSubmissionState>;
43
43
  mergeState(request: AnyFormRequest, state: FormSubmissionState, update: object): Promise<FormSubmissionState>;
@@ -296,8 +296,8 @@ export class QuestionPageController extends PageController {
296
296
  getStateFromValidForm(request, state, payload) {
297
297
  return this.collection.getStateFromValidForm(payload);
298
298
  }
299
- getErrors(details) {
300
- return getErrors(details);
299
+ getErrors(details, language) {
300
+ return getErrors(language, details);
301
301
  }
302
302
  async getState(request) {
303
303
  const {
@@ -1 +1 @@
1
- {"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","isPaymentPage","Boom","COMPONENT_STATE_ERROR","EXTERNAL_STATE_APPENDAGE","EXTERNAL_STATE_PAYLOAD","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","PaymentField","checkFormStatus","getCacheService","getErrors","getSaveAndExitHelpers","normalisePath","proceed","PageController","prefillStateFromQueryParameters","getComponentsByType","formatCurrency","FormAction","FormStatus","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndExit","constructor","model","pageDef","components","page","formSchema","keys","crumb","action","next","def","filter","path","linkPath","pages","some","pagePath","allowContinue","engine","V2","controller","Terminal","length","getItemId","request","itemId","getFormParams","params","getViewModel","context","translator","viewModel","payload","errors","t","tPage","tSection","showTitle","sectionTitle","pageTitle","title","section","hideTitle","formComponents","isFormComponent","fieldset","label","isPageHeading","labelOrLegend","legend","size","classes","isOptional","fields","at","options","required","text","optionalWord","optionalAlreadyAppended","endsWith","comp","paymentField","find","f","resolvedAmount","resolveAmount","evaluationState","amount","hasIncompletePayment","paymentState","preAuth","status","backLink","getBackLink","shouldShowSaveAndExit","server","showSubmitButton","getRelevantPath","paths","startPath","getStartPath","relevantPath","getNextPath","summaryPath","getSummaryPath","statusPath","getStatusPath","defaultPath","undefined","pageIndex","indexOf","nextPage","slice","condition","conditionResult","fn","nextLink","link","conditions","getFormDataFromState","state","result","validate","abortEarly","stripUnknown","value","getStateFromValidForm","details","getState","query","cacheService","setState","mergeState","update","updated","filterConditionalComponents","filtered","component","content","type","Details","map","evaluatedComponent","Array","isArray","item","items","makeGetRouteHandler","h","viewName","getTranslator","redirect","url","pathname","getViewErrors","flashedError","yar","flash","flashedErrors","concat","paymentExpiredFlash","showPaymentExpiredNotification","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","getHref","makePostRouteHandler","startsWith","External","dispatchExternal","SaveAndExit","handleSaveAndExit","externalComponents","externalActionsWithArgs","split","externalActionArgs","arg","args","Object","fromEntries","componentName","componentDefMap","get","componentType","internal","selectedComponent","stashedPayload","clear","isPreview","isLive","Live","dispatcher","sourceUrl","search","actionArgs","nextPath","nextUrl","saveAndExit","getRouteOptions","ext","onPostHandler","method","_request","continue","postRouteOptions","parse","maxBytes","Number","MAX_SAFE_INTEGER","failAction"],"sources":["../../../../../src/server/plugins/engine/pageControllers/QuestionPageController.ts"],"sourcesContent":["import {\n ComponentType,\n ControllerType,\n Engine,\n hasComponents,\n hasNext,\n hasRepeater,\n isPaymentPage,\n type Link,\n type Page\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n COMPONENT_STATE_ERROR,\n EXTERNAL_STATE_APPENDAGE,\n EXTERNAL_STATE_PAYLOAD,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport { type BackLink } from '~/src/server/plugins/engine/components/types.js'\nimport {\n checkFormStatus,\n getCacheService,\n getErrors,\n getSaveAndExitHelpers,\n normalisePath,\n proceed\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { prefillStateFromQueryParameters } from '~/src/server/plugins/engine/pageControllers/helpers/state.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type FormContextRequest,\n type FormPageViewModel,\n type FormPayload,\n type FormPayloadParams,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { getComponentsByType } from '~/src/server/plugins/engine/validationHelpers.js'\nimport { formatCurrency } from '~/src/server/plugins/payment/helper.js'\nimport {\n FormAction,\n FormStatus,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n paramsSchema\n} from '~/src/server/schemas/index.js'\nimport { merge } from '~/src/server/services/cacheService.js'\n\nexport class QuestionPageController extends PageController {\n collection: ComponentCollection\n errorSummaryTitle = 'There is a problem'\n allowSaveAndExit = true\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponents(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n\n this.collection.formSchema = this.collection.formSchema.keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n }\n\n get next(): Link[] {\n const { def, pageDef } = this\n\n if (!hasNext(pageDef)) {\n return []\n }\n\n // Remove stale links\n return pageDef.next.filter(({ path }) => {\n const linkPath = normalisePath(path)\n\n return def.pages.some((page) => {\n const pagePath = normalisePath(page.path)\n return pagePath === linkPath\n })\n })\n }\n\n get allowContinue(): boolean {\n if (this.model.engine === Engine.V2) {\n return this.pageDef.controller !== ControllerType.Terminal\n }\n\n return this.next.length > 0\n }\n\n getItemId(request?: FormContextRequest) {\n const { itemId } = this.getFormParams(request)\n return itemId ?? request?.params.itemId\n }\n\n /**\n * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered\n * @param request - the hapi request\n * @param context - the form context\n * @param translator - optional per-request translator pair\n */\n getViewModel(\n request: FormContextRequest,\n context: FormContext,\n translator: Translator\n ): FormPageViewModel {\n const { collection, viewModel } = this\n const { payload, errors } = context\n\n const { t, tPage, tSection } = translator\n\n let { showTitle, sectionTitle } = viewModel\n\n let pageTitle = this.pageDef.title ? tPage(this.pageDef, 'title') : ''\n\n if (this.section) {\n sectionTitle =\n this.section.hideTitle !== true ? tSection(this.section, 'title') : ''\n }\n\n const components = collection.getViewModel({ payload, errors, translator })\n const formComponents = components.filter(\n ({ isFormComponent }) => isFormComponent\n )\n\n // Single form component? Hide title and customise label or legend instead\n if (formComponents.length === 1) {\n const { model } = formComponents[0]\n const { fieldset, label } = model\n\n // Set as page heading when not following other content\n const isPageHeading = formComponents[0] === components[0]\n\n // Check for legend or label\n const labelOrLegend = fieldset?.legend ?? label\n\n // Use legend or label as page heading\n if (labelOrLegend) {\n const size = isPageHeading ? 'l' : 'm'\n\n labelOrLegend.classes =\n labelOrLegend === label\n ? `govuk-label--${size}`\n : `govuk-fieldset__legend--${size}`\n\n if (isPageHeading) {\n labelOrLegend.isPageHeading = isPageHeading\n\n // Check for optional in label\n const isOptional =\n this.collection.fields.at(0)?.options.required === false\n\n if (!pageTitle) {\n pageTitle = labelOrLegend.text\n }\n\n // The question text may have already appended 'optional' in the relevant language\n const optionalWord = t('common.optional')\n const optionalAlreadyAppended = pageTitle.endsWith(` ${optionalWord}`)\n labelOrLegend.text =\n isOptional && !optionalAlreadyAppended\n ? `${pageTitle} ${optionalWord}`\n : pageTitle\n }\n\n // Fallback if still no pageTitle set\n if (!pageTitle) {\n pageTitle = labelOrLegend.text\n }\n }\n\n showTitle = !isPageHeading\n } else if (formComponents.length > 1) {\n // When there is more than one form component,\n // adjust the label/legends to give equal prominence\n for (const { model } of formComponents) {\n if (model.fieldset?.legend) {\n model.fieldset.legend.classes = 'govuk-fieldset__legend--m'\n }\n if (model.label) {\n model.label.classes = 'govuk-label--m'\n }\n }\n }\n\n // Override payment amount display with resolved conditional amount\n // getViewModel() only has the current page's payload, not full form state.\n // The full state is available via context.evaluationState.\n for (const comp of components) {\n if ('amount' in comp.model && 'paymentState' in comp.model) {\n const paymentField = this.collection.fields.find(\n (f): f is PaymentField => f instanceof PaymentField\n )\n if (paymentField) {\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n context.evaluationState\n )\n comp.model.amount = formatCurrency(resolvedAmount)\n }\n }\n }\n\n const hasIncompletePayment = components.some(({ model }) => {\n if ('paymentState' in model) {\n const paymentState = model.paymentState as\n | { preAuth?: { status?: string } }\n | undefined\n return !paymentState?.preAuth?.status\n }\n return false\n })\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context, t),\n context,\n pageTitle,\n sectionTitle,\n showTitle,\n components,\n errors,\n allowSaveAndExit:\n this.shouldShowSaveAndExit(request.server) &&\n !isPaymentPage(this.pageDef),\n showSubmitButton: !hasIncompletePayment\n }\n }\n\n getRelevantPath(request: AnyFormRequest, context: FormContext) {\n const { paths } = context\n\n const startPath = this.getStartPath()\n const relevantPath = paths.at(-1) ?? startPath\n\n return !paths.length\n ? startPath // First possible path\n : relevantPath // Last possible path\n }\n\n /**\n * Apply conditions to evaluation state to determine next page path\n */\n getNextPath(context: FormContext) {\n const { model, next, path } = this\n const { evaluationState } = context\n\n const summaryPath = this.getSummaryPath()\n const statusPath = this.getStatusPath()\n\n // Walk from summary page (no next links) to status page\n let defaultPath = path === summaryPath ? statusPath : undefined\n\n if (model.engine === Engine.V2) {\n if (this.pageDef.controller !== ControllerType.Terminal) {\n const { pages } = this.model\n const pageIndex = pages.indexOf(this)\n\n // The \"next\" page is the first found after the current which is\n // either unconditional or has a condition that evaluates to \"true\"\n const nextPage = pages.slice(pageIndex + 1).find((page) => {\n const { condition } = page\n\n if (condition) {\n const conditionResult = condition.fn(evaluationState)\n\n if (!conditionResult) {\n return false\n }\n }\n\n // Skip payment pages in the normal page walk.\n // Users reach the payment page via \"Pay and submit\" on CYA,\n // not by navigating forward through the form.\n if (isPaymentPage(page.pageDef)) {\n return false\n }\n\n return true\n })\n\n return nextPage?.path ?? defaultPath\n } else {\n return defaultPath\n }\n }\n\n const nextLink = next.find((link) => {\n const { condition } = link\n\n if (condition) {\n return model.conditions[condition]?.fn(evaluationState) ?? false\n }\n\n defaultPath = link.path\n return false\n })\n\n return nextLink?.path ?? defaultPath\n }\n\n /**\n * Gets the form payload (from state) for this page only\n */\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ): FormPayload {\n const { collection } = this\n\n // Form params from request\n const params = this.getFormParams(request)\n\n // Form payload from state\n const payload = collection.getFormDataFromState(state)\n\n return {\n ...params,\n ...payload\n }\n }\n\n /**\n * Gets form params (from payload) for this page only\n */\n getFormParams(request?: FormContextRequest): FormPayloadParams {\n const { payload } = request ?? {}\n\n const result = paramsSchema.validate(payload, {\n abortEarly: false,\n stripUnknown: true\n })\n\n return result.value as FormPayloadParams\n }\n\n getStateFromValidForm(\n request: FormContextRequest,\n state: FormSubmissionState,\n payload: FormPayload\n ): FormState {\n return this.collection.getStateFromValidForm(payload)\n }\n\n getErrors(details?: ValidationErrorItem[]) {\n return getErrors(details)\n }\n\n async getState(request: AnyFormRequest) {\n const { query } = request\n\n // Skip get for preview URL direct access\n if ('force' in query) {\n return {}\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.getState(request)\n }\n\n async setState(request: AnyFormRequest, state: FormSubmissionState) {\n const { query } = request\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return state\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, state)\n }\n\n async mergeState(\n request: AnyFormRequest,\n state: FormSubmissionState,\n update: object\n ) {\n const { query } = request\n\n // Merge state before set\n const updated = merge(state, update)\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return updated\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, updated)\n }\n\n filterConditionalComponents(\n viewModel: FormPageViewModel,\n model: FormModel,\n evaluationState: Partial<Record<string, FormStateValue>>\n ) {\n // Filter our components based on their conditions using our evaluated state\n let filtered = viewModel.components.filter((component) => {\n if (\n (!!component.model.content ||\n component.type === ComponentType.Details) &&\n component.model.condition\n ) {\n const condition = model.conditions[component.model.condition]\n return condition?.fn(evaluationState)\n }\n return true\n })\n\n /**\n * For conditional reveal components (which we no longer support until GDS resolves the related accessibility issues {@link https://github.com/alphagov/govuk-frontend/issues/1991}\n */\n filtered = filtered.map((component) => {\n const evaluatedComponent = component\n const content = evaluatedComponent.model.content\n if (Array.isArray(content)) {\n evaluatedComponent.model.content = content.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n // apply condition to items for radios, checkboxes etc\n const items = evaluatedComponent.model.items\n\n if (Array.isArray(items)) {\n evaluatedComponent.model.items = items.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n\n return evaluatedComponent\n })\n\n return filtered\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n // Copy any URL params into the form state (if not already done so)\n if (await prefillStateFromQueryParameters(request, this)) {\n // Forward to same page without query string\n return h.redirect(request.url.pathname)\n }\n\n const viewModel = this.getViewModel(request, context, translator)\n viewModel.errors = collection.getViewErrors(translator, viewModel.errors)\n\n const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)\n const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []\n\n viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)\n\n const paymentExpiredFlash = request.yar.flash(\n PAYMENT_EXPIRED_NOTIFICATION\n )\n viewModel.showPaymentExpiredNotification =\n !Array.isArray(paymentExpiredFlash)\n\n /**\n * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it\n */\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, {\n ...viewModel,\n t\n })\n }\n }\n\n async hasMissingNotificationEmail(\n request: FormRequest,\n context: FormContext\n ) {\n const { path } = this\n const { params } = request\n const { isForceAccess } = context\n\n const startPath = this.getStartPath()\n const summaryPath = this.getSummaryPath()\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Warn the user if the form has no notification email set only on start page and summary page\n if ([startPath, summaryPath].includes(path) && !isForceAccess) {\n const { notificationEmail } = await getFormMetadata(params.slug)\n return !notificationEmail\n }\n\n return false\n }\n\n /**\n * Get the back link for a given progress.\n */\n protected getBackLink(\n request: FormContextRequest,\n context: FormContext,\n t: (key: string, opts?: Record<string, unknown>) => string\n ): BackLink | undefined {\n const { pageDef } = this\n const { path, query } = request\n const { returnUrl } = query\n const { paths } = context\n\n const itemId = this.getItemId(request)\n\n // Check answers back link\n if (returnUrl) {\n return {\n text:\n hasRepeater(pageDef) && itemId\n ? t('pages.question.backToAddAnother')\n : t('pages.question.backToCheckAnswers'),\n href: returnUrl\n }\n }\n\n // Item delete pages etc\n const backPath =\n itemId && !path.endsWith(itemId)\n ? paths.at(-1) // Back to main page\n : paths.at(-2) // Back to previous page\n\n // No back link\n if (!backPath) {\n return\n }\n\n // Default back link\n return {\n text: t('common.back'),\n href: this.getHref(backPath)\n }\n }\n\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n const action = request.payload.action\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n if (action?.startsWith(FormAction.External)) {\n return await this.dispatchExternal(request, h, context)\n }\n\n /**\n * If there are any errors, render the page with the parsed errors\n * @todo Refactor to match POST REDIRECT GET pattern\n */\n if (context.errors || isForceAccess) {\n const viewModel = this.getViewModel(request, context, translator)\n viewModel.errors = collection.getViewErrors(\n translator,\n viewModel.errors\n )\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n return h.view(viewName, {\n ...viewModel,\n t\n })\n }\n\n // Save state\n await this.setState(request, state)\n\n // Check if this is a save-and-exit action\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n // Proceed to the next page\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n private async dispatchExternal(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n ) {\n const { externalComponents } = getComponentsByType()\n const action = request.payload.action ?? ''\n\n // Find the external action and arguments\n // `external-{componentName}--{argname1}:{argvalue1}--{argname2}:{argvalue2}`\n // E.g. external-abcdef--amount:10--step:manual\n const externalActionsWithArgs = action\n .slice(`${FormAction.External}-`.length)\n .split('--')\n\n const externalActionArgs = externalActionsWithArgs\n .slice(1)\n .map((arg) => arg.split(':'))\n\n const args = Object.fromEntries(externalActionArgs) as Record<\n string,\n string\n >\n\n const componentName = externalActionsWithArgs[0]\n const component = this.model.componentDefMap.get(componentName)\n const componentType = component?.type\n\n if (!componentType) {\n throw Boom.internal(\n `External component of type ${componentType} not found`\n )\n }\n\n const selectedComponent = externalComponents.get(componentType)\n\n if (!selectedComponent) {\n throw Boom.internal(`External component ${componentName} not found`)\n }\n\n // Stash payload without crumb and action\n const stashedPayload = {\n ...context.payload,\n crumb: undefined,\n action: undefined\n }\n request.yar.flash(EXTERNAL_STATE_PAYLOAD, stashedPayload, true)\n\n // Clear any previous state appendage\n request.yar.clear(EXTERNAL_STATE_APPENDAGE)\n\n // Determine if this is a live form (not preview/draft)\n const { state, isPreview } = checkFormStatus(request.params)\n const isLive = state === FormStatus.Live\n\n return await selectedComponent.dispatcher(request, h, {\n component,\n controller: this,\n sourceUrl: `${request.url.pathname}${request.url.search}`,\n actionArgs: args,\n isLive,\n isPreview\n })\n }\n\n proceed(\n request: FormContextRequest,\n h: FormResponseToolkit,\n nextPath?: string\n ) {\n const nextUrl = nextPath\n ? this.getHref(nextPath) // Redirect to next page\n : this.href // Redirect to current page (refresh)\n\n return proceed(request, h, nextUrl)\n }\n\n /**\n * Handle save-and-exit action\n */\n handleSaveAndExit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const saveAndExit = getSaveAndExitHelpers(request.server)\n\n if (!saveAndExit) {\n throw Boom.internal('Server misconfigured for save and exit')\n }\n\n return saveAndExit(request, h, context)\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get getRouteOptions(): RouteOptions<FormRequestRefs> {\n return {\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n payload: {\n parse: true,\n maxBytes: Number.MAX_SAFE_INTEGER,\n failAction: 'ignore'\n },\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"QuestionPageController.js","names":["ComponentType","ControllerType","Engine","hasComponents","hasNext","hasRepeater","isPaymentPage","Boom","COMPONENT_STATE_ERROR","EXTERNAL_STATE_APPENDAGE","EXTERNAL_STATE_PAYLOAD","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","PaymentField","checkFormStatus","getCacheService","getErrors","getSaveAndExitHelpers","normalisePath","proceed","PageController","prefillStateFromQueryParameters","getComponentsByType","formatCurrency","FormAction","FormStatus","actionSchema","crumbSchema","paramsSchema","merge","QuestionPageController","collection","errorSummaryTitle","allowSaveAndExit","constructor","model","pageDef","components","page","formSchema","keys","crumb","action","next","def","filter","path","linkPath","pages","some","pagePath","allowContinue","engine","V2","controller","Terminal","length","getItemId","request","itemId","getFormParams","params","getViewModel","context","translator","viewModel","payload","errors","t","tPage","tSection","showTitle","sectionTitle","pageTitle","title","section","hideTitle","formComponents","isFormComponent","fieldset","label","isPageHeading","labelOrLegend","legend","size","classes","isOptional","fields","at","options","required","text","optionalWord","optionalAlreadyAppended","endsWith","comp","paymentField","find","f","resolvedAmount","resolveAmount","evaluationState","amount","hasIncompletePayment","paymentState","preAuth","status","backLink","getBackLink","shouldShowSaveAndExit","server","showSubmitButton","getRelevantPath","paths","startPath","getStartPath","relevantPath","getNextPath","summaryPath","getSummaryPath","statusPath","getStatusPath","defaultPath","undefined","pageIndex","indexOf","nextPage","slice","condition","conditionResult","fn","nextLink","link","conditions","getFormDataFromState","state","result","validate","abortEarly","stripUnknown","value","getStateFromValidForm","details","language","getState","query","cacheService","setState","mergeState","update","updated","filterConditionalComponents","filtered","component","content","type","Details","map","evaluatedComponent","Array","isArray","item","items","makeGetRouteHandler","h","viewName","getTranslator","redirect","url","pathname","getViewErrors","flashedError","yar","flash","flashedErrors","concat","paymentExpiredFlash","showPaymentExpiredNotification","hasMissingNotificationEmail","view","isForceAccess","formsService","services","getFormMetadata","includes","notificationEmail","slug","returnUrl","href","backPath","getHref","makePostRouteHandler","startsWith","External","dispatchExternal","SaveAndExit","handleSaveAndExit","externalComponents","externalActionsWithArgs","split","externalActionArgs","arg","args","Object","fromEntries","componentName","componentDefMap","get","componentType","internal","selectedComponent","stashedPayload","clear","isPreview","isLive","Live","dispatcher","sourceUrl","search","actionArgs","nextPath","nextUrl","saveAndExit","getRouteOptions","ext","onPostHandler","method","_request","continue","postRouteOptions","parse","maxBytes","Number","MAX_SAFE_INTEGER","failAction"],"sources":["../../../../../src/server/plugins/engine/pageControllers/QuestionPageController.ts"],"sourcesContent":["import {\n ComponentType,\n ControllerType,\n Engine,\n hasComponents,\n hasNext,\n hasRepeater,\n isPaymentPage,\n type Link,\n type Page\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { type ValidationErrorItem } from 'joi'\n\nimport {\n COMPONENT_STATE_ERROR,\n EXTERNAL_STATE_APPENDAGE,\n EXTERNAL_STATE_PAYLOAD,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport { type BackLink } from '~/src/server/plugins/engine/components/types.js'\nimport {\n checkFormStatus,\n getCacheService,\n getErrors,\n getSaveAndExitHelpers,\n normalisePath,\n proceed\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { prefillStateFromQueryParameters } from '~/src/server/plugins/engine/pageControllers/helpers/state.js'\nimport {\n type AnyFormRequest,\n type FormContext,\n type FormContextRequest,\n type FormPageViewModel,\n type FormPayload,\n type FormPayloadParams,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { getComponentsByType } from '~/src/server/plugins/engine/validationHelpers.js'\nimport { formatCurrency } from '~/src/server/plugins/payment/helper.js'\nimport {\n FormAction,\n FormStatus,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n crumbSchema,\n paramsSchema\n} from '~/src/server/schemas/index.js'\nimport { merge } from '~/src/server/services/cacheService.js'\n\nexport class QuestionPageController extends PageController {\n collection: ComponentCollection\n errorSummaryTitle = 'There is a problem'\n allowSaveAndExit = true\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponents(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n\n this.collection.formSchema = this.collection.formSchema.keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n }\n\n get next(): Link[] {\n const { def, pageDef } = this\n\n if (!hasNext(pageDef)) {\n return []\n }\n\n // Remove stale links\n return pageDef.next.filter(({ path }) => {\n const linkPath = normalisePath(path)\n\n return def.pages.some((page) => {\n const pagePath = normalisePath(page.path)\n return pagePath === linkPath\n })\n })\n }\n\n get allowContinue(): boolean {\n if (this.model.engine === Engine.V2) {\n return this.pageDef.controller !== ControllerType.Terminal\n }\n\n return this.next.length > 0\n }\n\n getItemId(request?: FormContextRequest) {\n const { itemId } = this.getFormParams(request)\n return itemId ?? request?.params.itemId\n }\n\n /**\n * Used for mapping form payloads and errors to govuk-frontend's template api, so a page can be rendered\n * @param request - the hapi request\n * @param context - the form context\n * @param translator - optional per-request translator pair\n */\n getViewModel(\n request: FormContextRequest,\n context: FormContext,\n translator: Translator\n ): FormPageViewModel {\n const { collection, viewModel } = this\n const { payload, errors } = context\n\n const { t, tPage, tSection } = translator\n\n let { showTitle, sectionTitle } = viewModel\n\n let pageTitle = this.pageDef.title ? tPage(this.pageDef, 'title') : ''\n\n if (this.section) {\n sectionTitle =\n this.section.hideTitle !== true ? tSection(this.section, 'title') : ''\n }\n\n const components = collection.getViewModel({ payload, errors, translator })\n const formComponents = components.filter(\n ({ isFormComponent }) => isFormComponent\n )\n\n // Single form component? Hide title and customise label or legend instead\n if (formComponents.length === 1) {\n const { model } = formComponents[0]\n const { fieldset, label } = model\n\n // Set as page heading when not following other content\n const isPageHeading = formComponents[0] === components[0]\n\n // Check for legend or label\n const labelOrLegend = fieldset?.legend ?? label\n\n // Use legend or label as page heading\n if (labelOrLegend) {\n const size = isPageHeading ? 'l' : 'm'\n\n labelOrLegend.classes =\n labelOrLegend === label\n ? `govuk-label--${size}`\n : `govuk-fieldset__legend--${size}`\n\n if (isPageHeading) {\n labelOrLegend.isPageHeading = isPageHeading\n\n // Check for optional in label\n const isOptional =\n this.collection.fields.at(0)?.options.required === false\n\n if (!pageTitle) {\n pageTitle = labelOrLegend.text\n }\n\n // The question text may have already appended 'optional' in the relevant language\n const optionalWord = t('common.optional')\n const optionalAlreadyAppended = pageTitle.endsWith(` ${optionalWord}`)\n labelOrLegend.text =\n isOptional && !optionalAlreadyAppended\n ? `${pageTitle} ${optionalWord}`\n : pageTitle\n }\n\n // Fallback if still no pageTitle set\n if (!pageTitle) {\n pageTitle = labelOrLegend.text\n }\n }\n\n showTitle = !isPageHeading\n } else if (formComponents.length > 1) {\n // When there is more than one form component,\n // adjust the label/legends to give equal prominence\n for (const { model } of formComponents) {\n if (model.fieldset?.legend) {\n model.fieldset.legend.classes = 'govuk-fieldset__legend--m'\n }\n if (model.label) {\n model.label.classes = 'govuk-label--m'\n }\n }\n }\n\n // Override payment amount display with resolved conditional amount\n // getViewModel() only has the current page's payload, not full form state.\n // The full state is available via context.evaluationState.\n for (const comp of components) {\n if ('amount' in comp.model && 'paymentState' in comp.model) {\n const paymentField = this.collection.fields.find(\n (f): f is PaymentField => f instanceof PaymentField\n )\n if (paymentField) {\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n context.evaluationState\n )\n comp.model.amount = formatCurrency(resolvedAmount)\n }\n }\n }\n\n const hasIncompletePayment = components.some(({ model }) => {\n if ('paymentState' in model) {\n const paymentState = model.paymentState as\n | { preAuth?: { status?: string } }\n | undefined\n return !paymentState?.preAuth?.status\n }\n return false\n })\n\n return {\n ...viewModel,\n backLink: this.getBackLink(request, context, t),\n context,\n pageTitle,\n sectionTitle,\n showTitle,\n components,\n errors,\n allowSaveAndExit:\n this.shouldShowSaveAndExit(request.server) &&\n !isPaymentPage(this.pageDef),\n showSubmitButton: !hasIncompletePayment\n }\n }\n\n getRelevantPath(request: AnyFormRequest, context: FormContext) {\n const { paths } = context\n\n const startPath = this.getStartPath()\n const relevantPath = paths.at(-1) ?? startPath\n\n return !paths.length\n ? startPath // First possible path\n : relevantPath // Last possible path\n }\n\n /**\n * Apply conditions to evaluation state to determine next page path\n */\n getNextPath(context: FormContext) {\n const { model, next, path } = this\n const { evaluationState } = context\n\n const summaryPath = this.getSummaryPath()\n const statusPath = this.getStatusPath()\n\n // Walk from summary page (no next links) to status page\n let defaultPath = path === summaryPath ? statusPath : undefined\n\n if (model.engine === Engine.V2) {\n if (this.pageDef.controller !== ControllerType.Terminal) {\n const { pages } = this.model\n const pageIndex = pages.indexOf(this)\n\n // The \"next\" page is the first found after the current which is\n // either unconditional or has a condition that evaluates to \"true\"\n const nextPage = pages.slice(pageIndex + 1).find((page) => {\n const { condition } = page\n\n if (condition) {\n const conditionResult = condition.fn(evaluationState)\n\n if (!conditionResult) {\n return false\n }\n }\n\n // Skip payment pages in the normal page walk.\n // Users reach the payment page via \"Pay and submit\" on CYA,\n // not by navigating forward through the form.\n if (isPaymentPage(page.pageDef)) {\n return false\n }\n\n return true\n })\n\n return nextPage?.path ?? defaultPath\n } else {\n return defaultPath\n }\n }\n\n const nextLink = next.find((link) => {\n const { condition } = link\n\n if (condition) {\n return model.conditions[condition]?.fn(evaluationState) ?? false\n }\n\n defaultPath = link.path\n return false\n })\n\n return nextLink?.path ?? defaultPath\n }\n\n /**\n * Gets the form payload (from state) for this page only\n */\n getFormDataFromState(\n request: FormContextRequest | undefined,\n state: FormSubmissionState\n ): FormPayload {\n const { collection } = this\n\n // Form params from request\n const params = this.getFormParams(request)\n\n // Form payload from state\n const payload = collection.getFormDataFromState(state)\n\n return {\n ...params,\n ...payload\n }\n }\n\n /**\n * Gets form params (from payload) for this page only\n */\n getFormParams(request?: FormContextRequest): FormPayloadParams {\n const { payload } = request ?? {}\n\n const result = paramsSchema.validate(payload, {\n abortEarly: false,\n stripUnknown: true\n })\n\n return result.value as FormPayloadParams\n }\n\n getStateFromValidForm(\n request: FormContextRequest,\n state: FormSubmissionState,\n payload: FormPayload\n ): FormState {\n return this.collection.getStateFromValidForm(payload)\n }\n\n getErrors(details?: ValidationErrorItem[], language?: string) {\n return getErrors(language, details)\n }\n\n async getState(request: AnyFormRequest) {\n const { query } = request\n\n // Skip get for preview URL direct access\n if ('force' in query) {\n return {}\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.getState(request)\n }\n\n async setState(request: AnyFormRequest, state: FormSubmissionState) {\n const { query } = request\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return state\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, state)\n }\n\n async mergeState(\n request: AnyFormRequest,\n state: FormSubmissionState,\n update: object\n ) {\n const { query } = request\n\n // Merge state before set\n const updated = merge(state, update)\n\n // Skip set for preview URL direct access\n if ('force' in query) {\n return updated\n }\n\n const cacheService = getCacheService(request.server)\n\n return cacheService.setState(request, updated)\n }\n\n filterConditionalComponents(\n viewModel: FormPageViewModel,\n model: FormModel,\n evaluationState: Partial<Record<string, FormStateValue>>\n ) {\n // Filter our components based on their conditions using our evaluated state\n let filtered = viewModel.components.filter((component) => {\n if (\n (!!component.model.content ||\n component.type === ComponentType.Details) &&\n component.model.condition\n ) {\n const condition = model.conditions[component.model.condition]\n return condition?.fn(evaluationState)\n }\n return true\n })\n\n /**\n * For conditional reveal components (which we no longer support until GDS resolves the related accessibility issues {@link https://github.com/alphagov/govuk-frontend/issues/1991}\n */\n filtered = filtered.map((component) => {\n const evaluatedComponent = component\n const content = evaluatedComponent.model.content\n if (Array.isArray(content)) {\n evaluatedComponent.model.content = content.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n // apply condition to items for radios, checkboxes etc\n const items = evaluatedComponent.model.items\n\n if (Array.isArray(items)) {\n evaluatedComponent.model.items = items.filter((item) =>\n item.condition\n ? model.conditions[item.condition]?.fn(evaluationState)\n : true\n )\n }\n\n return evaluatedComponent\n })\n\n return filtered\n }\n\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, model, viewName } = this\n const { evaluationState } = context\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n // Copy any URL params into the form state (if not already done so)\n if (await prefillStateFromQueryParameters(request, this)) {\n // Forward to same page without query string\n return h.redirect(request.url.pathname)\n }\n\n const viewModel = this.getViewModel(request, context, translator)\n viewModel.errors = collection.getViewErrors(translator, viewModel.errors)\n\n const flashedError = request.yar.flash(COMPONENT_STATE_ERROR)\n const flashedErrors = !Array.isArray(flashedError) ? [flashedError] : []\n\n viewModel.errors = (viewModel.errors ?? []).concat(flashedErrors)\n\n const paymentExpiredFlash = request.yar.flash(\n PAYMENT_EXPIRED_NOTIFICATION\n )\n viewModel.showPaymentExpiredNotification =\n !Array.isArray(paymentExpiredFlash)\n\n /**\n * Content components can be hidden based on a condition. If the condition evaluates to true, it is safe to be kept, otherwise discard it\n */\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n return h.view(viewName, {\n ...viewModel,\n t\n })\n }\n }\n\n async hasMissingNotificationEmail(\n request: FormRequest,\n context: FormContext\n ) {\n const { path } = this\n const { params } = request\n const { isForceAccess } = context\n\n const startPath = this.getStartPath()\n const summaryPath = this.getSummaryPath()\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n // Warn the user if the form has no notification email set only on start page and summary page\n if ([startPath, summaryPath].includes(path) && !isForceAccess) {\n const { notificationEmail } = await getFormMetadata(params.slug)\n return !notificationEmail\n }\n\n return false\n }\n\n /**\n * Get the back link for a given progress.\n */\n protected getBackLink(\n request: FormContextRequest,\n context: FormContext,\n t: (key: string, opts?: Record<string, unknown>) => string\n ): BackLink | undefined {\n const { pageDef } = this\n const { path, query } = request\n const { returnUrl } = query\n const { paths } = context\n\n const itemId = this.getItemId(request)\n\n // Check answers back link\n if (returnUrl) {\n return {\n text:\n hasRepeater(pageDef) && itemId\n ? t('pages.question.backToAddAnother')\n : t('pages.question.backToCheckAnswers'),\n href: returnUrl\n }\n }\n\n // Item delete pages etc\n const backPath =\n itemId && !path.endsWith(itemId)\n ? paths.at(-1) // Back to main page\n : paths.at(-2) // Back to previous page\n\n // No back link\n if (!backPath) {\n return\n }\n\n // Default back link\n return {\n text: t('common.back'),\n href: this.getHref(backPath)\n }\n }\n\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { collection, viewName, model } = this\n const { isForceAccess, state, evaluationState } = context\n const action = request.payload.action\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n if (action?.startsWith(FormAction.External)) {\n return await this.dispatchExternal(request, h, context)\n }\n\n /**\n * If there are any errors, render the page with the parsed errors\n * @todo Refactor to match POST REDIRECT GET pattern\n */\n if (context.errors || isForceAccess) {\n const viewModel = this.getViewModel(request, context, translator)\n viewModel.errors = collection.getViewErrors(\n translator,\n viewModel.errors\n )\n\n // Filter our components based on their conditions using our evaluated state\n viewModel.components = this.filterConditionalComponents(\n viewModel,\n model,\n evaluationState\n )\n\n return h.view(viewName, {\n ...viewModel,\n t\n })\n }\n\n // Save state\n await this.setState(request, state)\n\n // Check if this is a save-and-exit action\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n // Proceed to the next page\n return this.proceed(request, h, this.getNextPath(context))\n }\n }\n\n private async dispatchExternal(\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n ) {\n const { externalComponents } = getComponentsByType()\n const action = request.payload.action ?? ''\n\n // Find the external action and arguments\n // `external-{componentName}--{argname1}:{argvalue1}--{argname2}:{argvalue2}`\n // E.g. external-abcdef--amount:10--step:manual\n const externalActionsWithArgs = action\n .slice(`${FormAction.External}-`.length)\n .split('--')\n\n const externalActionArgs = externalActionsWithArgs\n .slice(1)\n .map((arg) => arg.split(':'))\n\n const args = Object.fromEntries(externalActionArgs) as Record<\n string,\n string\n >\n\n const componentName = externalActionsWithArgs[0]\n const component = this.model.componentDefMap.get(componentName)\n const componentType = component?.type\n\n if (!componentType) {\n throw Boom.internal(\n `External component of type ${componentType} not found`\n )\n }\n\n const selectedComponent = externalComponents.get(componentType)\n\n if (!selectedComponent) {\n throw Boom.internal(`External component ${componentName} not found`)\n }\n\n // Stash payload without crumb and action\n const stashedPayload = {\n ...context.payload,\n crumb: undefined,\n action: undefined\n }\n request.yar.flash(EXTERNAL_STATE_PAYLOAD, stashedPayload, true)\n\n // Clear any previous state appendage\n request.yar.clear(EXTERNAL_STATE_APPENDAGE)\n\n // Determine if this is a live form (not preview/draft)\n const { state, isPreview } = checkFormStatus(request.params)\n const isLive = state === FormStatus.Live\n\n return await selectedComponent.dispatcher(request, h, {\n component,\n controller: this,\n sourceUrl: `${request.url.pathname}${request.url.search}`,\n actionArgs: args,\n isLive,\n isPreview\n })\n }\n\n proceed(\n request: FormContextRequest,\n h: FormResponseToolkit,\n nextPath?: string\n ) {\n const nextUrl = nextPath\n ? this.getHref(nextPath) // Redirect to next page\n : this.href // Redirect to current page (refresh)\n\n return proceed(request, h, nextUrl)\n }\n\n /**\n * Handle save-and-exit action\n */\n handleSaveAndExit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const saveAndExit = getSaveAndExitHelpers(request.server)\n\n if (!saveAndExit) {\n throw Boom.internal('Server misconfigured for save and exit')\n }\n\n return saveAndExit(request, h, context)\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get getRouteOptions(): RouteOptions<FormRequestRefs> {\n return {\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n\n /**\n * {@link https://hapi.dev/api/?v=20.1.2#route-options}\n */\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n payload: {\n parse: true,\n maxBytes: Number.MAX_SAFE_INTEGER,\n failAction: 'ignore'\n },\n ext: {\n onPostHandler: {\n method(_request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n"],"mappings":"AAAA,SACEA,aAAa,EACbC,cAAc,EACdC,MAAM,EACNC,aAAa,EACbC,OAAO,EACPC,WAAW,EACXC,aAAa,QAGR,oBAAoB;AAC3B,OAAOC,IAAI,MAAM,YAAY;AAI7B,SACEC,qBAAqB,EACrBC,wBAAwB,EACxBC,sBAAsB,EACtBC,4BAA4B;AAE9B,SAASC,mBAAmB;AAC5B,SAASC,YAAY;AAErB,SACEC,eAAe,EACfC,eAAe,EACfC,SAAS,EACTC,qBAAqB,EACrBC,aAAa,EACbC,OAAO;AAIT,SAASC,cAAc;AACvB,SAASC,+BAA+B;AAYxC,SAASC,mBAAmB;AAC5B,SAASC,cAAc;AACvB,SACEC,UAAU,EACVC,UAAU;AAOZ,SACEC,YAAY,EACZC,WAAW,EACXC,YAAY;AAEd,SAASC,KAAK;AAEd,OAAO,MAAMC,sBAAsB,SAASV,cAAc,CAAC;EACzDW,UAAU;EACVC,iBAAiB,GAAG,oBAAoB;EACxCC,gBAAgB,GAAG,IAAI;EAEvBC,WAAWA,CAACC,KAAgB,EAAEC,OAAa,EAAE;IAC3C,KAAK,CAACD,KAAK,EAAEC,OAAO,CAAC;;IAErB;IACA,IAAI,CAACL,UAAU,GAAG,IAAInB,mBAAmB,CACvCT,aAAa,CAACiC,OAAO,CAAC,GAAGA,OAAO,CAACC,UAAU,GAAG,EAAE,EAChD;MAAEF,KAAK;MAAEG,IAAI,EAAE;IAAK,CACtB,CAAC;IAED,IAAI,CAACP,UAAU,CAACQ,UAAU,GAAG,IAAI,CAACR,UAAU,CAACQ,UAAU,CAACC,IAAI,CAAC;MAC3DC,KAAK,EAAEd,WAAW;MAClBe,MAAM,EAAEhB;IACV,CAAC,CAAC;EACJ;EAEA,IAAIiB,IAAIA,CAAA,EAAW;IACjB,MAAM;MAAEC,GAAG;MAAER;IAAQ,CAAC,GAAG,IAAI;IAE7B,IAAI,CAAChC,OAAO,CAACgC,OAAO,CAAC,EAAE;MACrB,OAAO,EAAE;IACX;;IAEA;IACA,OAAOA,OAAO,CAACO,IAAI,CAACE,MAAM,CAAC,CAAC;MAAEC;IAAK,CAAC,KAAK;MACvC,MAAMC,QAAQ,GAAG7B,aAAa,CAAC4B,IAAI,CAAC;MAEpC,OAAOF,GAAG,CAACI,KAAK,CAACC,IAAI,CAAEX,IAAI,IAAK;QAC9B,MAAMY,QAAQ,GAAGhC,aAAa,CAACoB,IAAI,CAACQ,IAAI,CAAC;QACzC,OAAOI,QAAQ,KAAKH,QAAQ;MAC9B,CAAC,CAAC;IACJ,CAAC,CAAC;EACJ;EAEA,IAAII,aAAaA,CAAA,EAAY;IAC3B,IAAI,IAAI,CAAChB,KAAK,CAACiB,MAAM,KAAKlD,MAAM,CAACmD,EAAE,EAAE;MACnC,OAAO,IAAI,CAACjB,OAAO,CAACkB,UAAU,KAAKrD,cAAc,CAACsD,QAAQ;IAC5D;IAEA,OAAO,IAAI,CAACZ,IAAI,CAACa,MAAM,GAAG,CAAC;EAC7B;EAEAC,SAASA,CAACC,OAA4B,EAAE;IACtC,MAAM;MAAEC;IAAO,CAAC,GAAG,IAAI,CAACC,aAAa,CAACF,OAAO,CAAC;IAC9C,OAAOC,MAAM,IAAID,OAAO,EAAEG,MAAM,CAACF,MAAM;EACzC;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEG,YAAYA,CACVJ,OAA2B,EAC3BK,OAAoB,EACpBC,UAAsB,EACH;IACnB,MAAM;MAAEjC,UAAU;MAAEkC;IAAU,CAAC,GAAG,IAAI;IACtC,MAAM;MAAEC,OAAO;MAAEC;IAAO,CAAC,GAAGJ,OAAO;IAEnC,MAAM;MAAEK,CAAC;MAAEC,KAAK;MAAEC;IAAS,CAAC,GAAGN,UAAU;IAEzC,IAAI;MAAEO,SAAS;MAAEC;IAAa,CAAC,GAAGP,SAAS;IAE3C,IAAIQ,SAAS,GAAG,IAAI,CAACrC,OAAO,CAACsC,KAAK,GAAGL,KAAK,CAAC,IAAI,CAACjC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE;IAEtE,IAAI,IAAI,CAACuC,OAAO,EAAE;MAChBH,YAAY,GACV,IAAI,CAACG,OAAO,CAACC,SAAS,KAAK,IAAI,GAAGN,QAAQ,CAAC,IAAI,CAACK,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE;IAC1E;IAEA,MAAMtC,UAAU,GAAGN,UAAU,CAAC+B,YAAY,CAAC;MAAEI,OAAO;MAAEC,MAAM;MAAEH;IAAW,CAAC,CAAC;IAC3E,MAAMa,cAAc,GAAGxC,UAAU,CAACQ,MAAM,CACtC,CAAC;MAAEiC;IAAgB,CAAC,KAAKA,eAC3B,CAAC;;IAED;IACA,IAAID,cAAc,CAACrB,MAAM,KAAK,CAAC,EAAE;MAC/B,MAAM;QAAErB;MAAM,CAAC,GAAG0C,cAAc,CAAC,CAAC,CAAC;MACnC,MAAM;QAAEE,QAAQ;QAAEC;MAAM,CAAC,GAAG7C,KAAK;;MAEjC;MACA,MAAM8C,aAAa,GAAGJ,cAAc,CAAC,CAAC,CAAC,KAAKxC,UAAU,CAAC,CAAC,CAAC;;MAEzD;MACA,MAAM6C,aAAa,GAAGH,QAAQ,EAAEI,MAAM,IAAIH,KAAK;;MAE/C;MACA,IAAIE,aAAa,EAAE;QACjB,MAAME,IAAI,GAAGH,aAAa,GAAG,GAAG,GAAG,GAAG;QAEtCC,aAAa,CAACG,OAAO,GACnBH,aAAa,KAAKF,KAAK,GACnB,gBAAgBI,IAAI,EAAE,GACtB,2BAA2BA,IAAI,EAAE;QAEvC,IAAIH,aAAa,EAAE;UACjBC,aAAa,CAACD,aAAa,GAAGA,aAAa;;UAE3C;UACA,MAAMK,UAAU,GACd,IAAI,CAACvD,UAAU,CAACwD,MAAM,CAACC,EAAE,CAAC,CAAC,CAAC,EAAEC,OAAO,CAACC,QAAQ,KAAK,KAAK;UAE1D,IAAI,CAACjB,SAAS,EAAE;YACdA,SAAS,GAAGS,aAAa,CAACS,IAAI;UAChC;;UAEA;UACA,MAAMC,YAAY,GAAGxB,CAAC,CAAC,iBAAiB,CAAC;UACzC,MAAMyB,uBAAuB,GAAGpB,SAAS,CAACqB,QAAQ,CAAC,IAAIF,YAAY,EAAE,CAAC;UACtEV,aAAa,CAACS,IAAI,GAChBL,UAAU,IAAI,CAACO,uBAAuB,GAClC,GAAGpB,SAAS,IAAImB,YAAY,EAAE,GAC9BnB,SAAS;QACjB;;QAEA;QACA,IAAI,CAACA,SAAS,EAAE;UACdA,SAAS,GAAGS,aAAa,CAACS,IAAI;QAChC;MACF;MAEApB,SAAS,GAAG,CAACU,aAAa;IAC5B,CAAC,MAAM,IAAIJ,cAAc,CAACrB,MAAM,GAAG,CAAC,EAAE;MACpC;MACA;MACA,KAAK,MAAM;QAAErB;MAAM,CAAC,IAAI0C,cAAc,EAAE;QACtC,IAAI1C,KAAK,CAAC4C,QAAQ,EAAEI,MAAM,EAAE;UAC1BhD,KAAK,CAAC4C,QAAQ,CAACI,MAAM,CAACE,OAAO,GAAG,2BAA2B;QAC7D;QACA,IAAIlD,KAAK,CAAC6C,KAAK,EAAE;UACf7C,KAAK,CAAC6C,KAAK,CAACK,OAAO,GAAG,gBAAgB;QACxC;MACF;IACF;;IAEA;IACA;IACA;IACA,KAAK,MAAMU,IAAI,IAAI1D,UAAU,EAAE;MAC7B,IAAI,QAAQ,IAAI0D,IAAI,CAAC5D,KAAK,IAAI,cAAc,IAAI4D,IAAI,CAAC5D,KAAK,EAAE;QAC1D,MAAM6D,YAAY,GAAG,IAAI,CAACjE,UAAU,CAACwD,MAAM,CAACU,IAAI,CAC7CC,CAAC,IAAwBA,CAAC,YAAYrF,YACzC,CAAC;QACD,IAAImF,YAAY,EAAE;UAChB,MAAMG,cAAc,GAAGtF,YAAY,CAACuF,aAAa,CAC/CJ,YAAY,CAACP,OAAO,EACpB,IAAI,CAACtD,KAAK,EACV4B,OAAO,CAACsC,eACV,CAAC;UACDN,IAAI,CAAC5D,KAAK,CAACmE,MAAM,GAAG/E,cAAc,CAAC4E,cAAc,CAAC;QACpD;MACF;IACF;IAEA,MAAMI,oBAAoB,GAAGlE,UAAU,CAACY,IAAI,CAAC,CAAC;MAAEd;IAAM,CAAC,KAAK;MAC1D,IAAI,cAAc,IAAIA,KAAK,EAAE;QAC3B,MAAMqE,YAAY,GAAGrE,KAAK,CAACqE,YAEd;QACb,OAAO,CAACA,YAAY,EAAEC,OAAO,EAAEC,MAAM;MACvC;MACA,OAAO,KAAK;IACd,CAAC,CAAC;IAEF,OAAO;MACL,GAAGzC,SAAS;MACZ0C,QAAQ,EAAE,IAAI,CAACC,WAAW,CAAClD,OAAO,EAAEK,OAAO,EAAEK,CAAC,CAAC;MAC/CL,OAAO;MACPU,SAAS;MACTD,YAAY;MACZD,SAAS;MACTlC,UAAU;MACV8B,MAAM;MACNlC,gBAAgB,EACd,IAAI,CAAC4E,qBAAqB,CAACnD,OAAO,CAACoD,MAAM,CAAC,IAC1C,CAACxG,aAAa,CAAC,IAAI,CAAC8B,OAAO,CAAC;MAC9B2E,gBAAgB,EAAE,CAACR;IACrB,CAAC;EACH;EAEAS,eAAeA,CAACtD,OAAuB,EAAEK,OAAoB,EAAE;IAC7D,MAAM;MAAEkD;IAAM,CAAC,GAAGlD,OAAO;IAEzB,MAAMmD,SAAS,GAAG,IAAI,CAACC,YAAY,CAAC,CAAC;IACrC,MAAMC,YAAY,GAAGH,KAAK,CAACzB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI0B,SAAS;IAE9C,OAAO,CAACD,KAAK,CAACzD,MAAM,GAChB0D,SAAS,CAAC;IAAA,EACVE,YAAY,EAAC;EACnB;;EAEA;AACF;AACA;EACEC,WAAWA,CAACtD,OAAoB,EAAE;IAChC,MAAM;MAAE5B,KAAK;MAAEQ,IAAI;MAAEG;IAAK,CAAC,GAAG,IAAI;IAClC,MAAM;MAAEuD;IAAgB,CAAC,GAAGtC,OAAO;IAEnC,MAAMuD,WAAW,GAAG,IAAI,CAACC,cAAc,CAAC,CAAC;IACzC,MAAMC,UAAU,GAAG,IAAI,CAACC,aAAa,CAAC,CAAC;;IAEvC;IACA,IAAIC,WAAW,GAAG5E,IAAI,KAAKwE,WAAW,GAAGE,UAAU,GAAGG,SAAS;IAE/D,IAAIxF,KAAK,CAACiB,MAAM,KAAKlD,MAAM,CAACmD,EAAE,EAAE;MAC9B,IAAI,IAAI,CAACjB,OAAO,CAACkB,UAAU,KAAKrD,cAAc,CAACsD,QAAQ,EAAE;QACvD,MAAM;UAAEP;QAAM,CAAC,GAAG,IAAI,CAACb,KAAK;QAC5B,MAAMyF,SAAS,GAAG5E,KAAK,CAAC6E,OAAO,CAAC,IAAI,CAAC;;QAErC;QACA;QACA,MAAMC,QAAQ,GAAG9E,KAAK,CAAC+E,KAAK,CAACH,SAAS,GAAG,CAAC,CAAC,CAAC3B,IAAI,CAAE3D,IAAI,IAAK;UACzD,MAAM;YAAE0F;UAAU,CAAC,GAAG1F,IAAI;UAE1B,IAAI0F,SAAS,EAAE;YACb,MAAMC,eAAe,GAAGD,SAAS,CAACE,EAAE,CAAC7B,eAAe,CAAC;YAErD,IAAI,CAAC4B,eAAe,EAAE;cACpB,OAAO,KAAK;YACd;UACF;;UAEA;UACA;UACA;UACA,IAAI3H,aAAa,CAACgC,IAAI,CAACF,OAAO,CAAC,EAAE;YAC/B,OAAO,KAAK;UACd;UAEA,OAAO,IAAI;QACb,CAAC,CAAC;QAEF,OAAO0F,QAAQ,EAAEhF,IAAI,IAAI4E,WAAW;MACtC,CAAC,MAAM;QACL,OAAOA,WAAW;MACpB;IACF;IAEA,MAAMS,QAAQ,GAAGxF,IAAI,CAACsD,IAAI,CAAEmC,IAAI,IAAK;MACnC,MAAM;QAAEJ;MAAU,CAAC,GAAGI,IAAI;MAE1B,IAAIJ,SAAS,EAAE;QACb,OAAO7F,KAAK,CAACkG,UAAU,CAACL,SAAS,CAAC,EAAEE,EAAE,CAAC7B,eAAe,CAAC,IAAI,KAAK;MAClE;MAEAqB,WAAW,GAAGU,IAAI,CAACtF,IAAI;MACvB,OAAO,KAAK;IACd,CAAC,CAAC;IAEF,OAAOqF,QAAQ,EAAErF,IAAI,IAAI4E,WAAW;EACtC;;EAEA;AACF;AACA;EACEY,oBAAoBA,CAClB5E,OAAuC,EACvC6E,KAA0B,EACb;IACb,MAAM;MAAExG;IAAW,CAAC,GAAG,IAAI;;IAE3B;IACA,MAAM8B,MAAM,GAAG,IAAI,CAACD,aAAa,CAACF,OAAO,CAAC;;IAE1C;IACA,MAAMQ,OAAO,GAAGnC,UAAU,CAACuG,oBAAoB,CAACC,KAAK,CAAC;IAEtD,OAAO;MACL,GAAG1E,MAAM;MACT,GAAGK;IACL,CAAC;EACH;;EAEA;AACF;AACA;EACEN,aAAaA,CAACF,OAA4B,EAAqB;IAC7D,MAAM;MAAEQ;IAAQ,CAAC,GAAGR,OAAO,IAAI,CAAC,CAAC;IAEjC,MAAM8E,MAAM,GAAG5G,YAAY,CAAC6G,QAAQ,CAACvE,OAAO,EAAE;MAC5CwE,UAAU,EAAE,KAAK;MACjBC,YAAY,EAAE;IAChB,CAAC,CAAC;IAEF,OAAOH,MAAM,CAACI,KAAK;EACrB;EAEAC,qBAAqBA,CACnBnF,OAA2B,EAC3B6E,KAA0B,EAC1BrE,OAAoB,EACT;IACX,OAAO,IAAI,CAACnC,UAAU,CAAC8G,qBAAqB,CAAC3E,OAAO,CAAC;EACvD;EAEAlD,SAASA,CAAC8H,OAA+B,EAAEC,QAAiB,EAAE;IAC5D,OAAO/H,SAAS,CAAC+H,QAAQ,EAAED,OAAO,CAAC;EACrC;EAEA,MAAME,QAAQA,CAACtF,OAAuB,EAAE;IACtC,MAAM;MAAEuF;IAAM,CAAC,GAAGvF,OAAO;;IAEzB;IACA,IAAI,OAAO,IAAIuF,KAAK,EAAE;MACpB,OAAO,CAAC,CAAC;IACX;IAEA,MAAMC,YAAY,GAAGnI,eAAe,CAAC2C,OAAO,CAACoD,MAAM,CAAC;IAEpD,OAAOoC,YAAY,CAACF,QAAQ,CAACtF,OAAO,CAAC;EACvC;EAEA,MAAMyF,QAAQA,CAACzF,OAAuB,EAAE6E,KAA0B,EAAE;IAClE,MAAM;MAAEU;IAAM,CAAC,GAAGvF,OAAO;;IAEzB;IACA,IAAI,OAAO,IAAIuF,KAAK,EAAE;MACpB,OAAOV,KAAK;IACd;IAEA,MAAMW,YAAY,GAAGnI,eAAe,CAAC2C,OAAO,CAACoD,MAAM,CAAC;IAEpD,OAAOoC,YAAY,CAACC,QAAQ,CAACzF,OAAO,EAAE6E,KAAK,CAAC;EAC9C;EAEA,MAAMa,UAAUA,CACd1F,OAAuB,EACvB6E,KAA0B,EAC1Bc,MAAc,EACd;IACA,MAAM;MAAEJ;IAAM,CAAC,GAAGvF,OAAO;;IAEzB;IACA,MAAM4F,OAAO,GAAGzH,KAAK,CAAC0G,KAAK,EAAEc,MAAM,CAAC;;IAEpC;IACA,IAAI,OAAO,IAAIJ,KAAK,EAAE;MACpB,OAAOK,OAAO;IAChB;IAEA,MAAMJ,YAAY,GAAGnI,eAAe,CAAC2C,OAAO,CAACoD,MAAM,CAAC;IAEpD,OAAOoC,YAAY,CAACC,QAAQ,CAACzF,OAAO,EAAE4F,OAAO,CAAC;EAChD;EAEAC,2BAA2BA,CACzBtF,SAA4B,EAC5B9B,KAAgB,EAChBkE,eAAwD,EACxD;IACA;IACA,IAAImD,QAAQ,GAAGvF,SAAS,CAAC5B,UAAU,CAACQ,MAAM,CAAE4G,SAAS,IAAK;MACxD,IACE,CAAC,CAAC,CAACA,SAAS,CAACtH,KAAK,CAACuH,OAAO,IACxBD,SAAS,CAACE,IAAI,KAAK3J,aAAa,CAAC4J,OAAO,KAC1CH,SAAS,CAACtH,KAAK,CAAC6F,SAAS,EACzB;QACA,MAAMA,SAAS,GAAG7F,KAAK,CAACkG,UAAU,CAACoB,SAAS,CAACtH,KAAK,CAAC6F,SAAS,CAAC;QAC7D,OAAOA,SAAS,EAAEE,EAAE,CAAC7B,eAAe,CAAC;MACvC;MACA,OAAO,IAAI;IACb,CAAC,CAAC;;IAEF;AACJ;AACA;IACImD,QAAQ,GAAGA,QAAQ,CAACK,GAAG,CAAEJ,SAAS,IAAK;MACrC,MAAMK,kBAAkB,GAAGL,SAAS;MACpC,MAAMC,OAAO,GAAGI,kBAAkB,CAAC3H,KAAK,CAACuH,OAAO;MAChD,IAAIK,KAAK,CAACC,OAAO,CAACN,OAAO,CAAC,EAAE;QAC1BI,kBAAkB,CAAC3H,KAAK,CAACuH,OAAO,GAAGA,OAAO,CAAC7G,MAAM,CAAEoH,IAAI,IACrDA,IAAI,CAACjC,SAAS,GACV7F,KAAK,CAACkG,UAAU,CAAC4B,IAAI,CAACjC,SAAS,CAAC,EAAEE,EAAE,CAAC7B,eAAe,CAAC,GACrD,IACN,CAAC;MACH;MACA;MACA,MAAM6D,KAAK,GAAGJ,kBAAkB,CAAC3H,KAAK,CAAC+H,KAAK;MAE5C,IAAIH,KAAK,CAACC,OAAO,CAACE,KAAK,CAAC,EAAE;QACxBJ,kBAAkB,CAAC3H,KAAK,CAAC+H,KAAK,GAAGA,KAAK,CAACrH,MAAM,CAAEoH,IAAI,IACjDA,IAAI,CAACjC,SAAS,GACV7F,KAAK,CAACkG,UAAU,CAAC4B,IAAI,CAACjC,SAAS,CAAC,EAAEE,EAAE,CAAC7B,eAAe,CAAC,GACrD,IACN,CAAC;MACH;MAEA,OAAOyD,kBAAkB;IAC3B,CAAC,CAAC;IAEF,OAAON,QAAQ;EACjB;EAEAW,mBAAmBA,CAAA,EAAG;IACpB,OAAO,OACLzG,OAAoB,EACpBK,OAAoB,EACpBqG,CAAsB,KACnB;MACH,MAAM;QAAErI,UAAU;QAAEI,KAAK;QAAEkI;MAAS,CAAC,GAAG,IAAI;MAC5C,MAAM;QAAEhE;MAAgB,CAAC,GAAGtC,OAAO;MAEnC,MAAMC,UAAU,GAAG,IAAI,CAACsG,aAAa,CAAC5G,OAAO,CAAC;MAC9C,MAAM;QAAEU;MAAE,CAAC,GAAGJ,UAAU;;MAExB;MACA,IAAI,MAAM3C,+BAA+B,CAACqC,OAAO,EAAE,IAAI,CAAC,EAAE;QACxD;QACA,OAAO0G,CAAC,CAACG,QAAQ,CAAC7G,OAAO,CAAC8G,GAAG,CAACC,QAAQ,CAAC;MACzC;MAEA,MAAMxG,SAAS,GAAG,IAAI,CAACH,YAAY,CAACJ,OAAO,EAAEK,OAAO,EAAEC,UAAU,CAAC;MACjEC,SAAS,CAACE,MAAM,GAAGpC,UAAU,CAAC2I,aAAa,CAAC1G,UAAU,EAAEC,SAAS,CAACE,MAAM,CAAC;MAEzE,MAAMwG,YAAY,GAAGjH,OAAO,CAACkH,GAAG,CAACC,KAAK,CAACrK,qBAAqB,CAAC;MAC7D,MAAMsK,aAAa,GAAG,CAACf,KAAK,CAACC,OAAO,CAACW,YAAY,CAAC,GAAG,CAACA,YAAY,CAAC,GAAG,EAAE;MAExE1G,SAAS,CAACE,MAAM,GAAG,CAACF,SAAS,CAACE,MAAM,IAAI,EAAE,EAAE4G,MAAM,CAACD,aAAa,CAAC;MAEjE,MAAME,mBAAmB,GAAGtH,OAAO,CAACkH,GAAG,CAACC,KAAK,CAC3ClK,4BACF,CAAC;MACDsD,SAAS,CAACgH,8BAA8B,GACtC,CAAClB,KAAK,CAACC,OAAO,CAACgB,mBAAmB,CAAC;;MAErC;AACN;AACA;;MAEM;MACA/G,SAAS,CAAC5B,UAAU,GAAG,IAAI,CAACkH,2BAA2B,CACrDtF,SAAS,EACT9B,KAAK,EACLkE,eACF,CAAC;MAEDpC,SAAS,CAACiH,2BAA2B,GACnC,MAAM,IAAI,CAACA,2BAA2B,CAACxH,OAAO,EAAEK,OAAO,CAAC;MAE1D,OAAOqG,CAAC,CAACe,IAAI,CAACd,QAAQ,EAAE;QACtB,GAAGpG,SAAS;QACZG;MACF,CAAC,CAAC;IACJ,CAAC;EACH;EAEA,MAAM8G,2BAA2BA,CAC/BxH,OAAoB,EACpBK,OAAoB,EACpB;IACA,MAAM;MAAEjB;IAAK,CAAC,GAAG,IAAI;IACrB,MAAM;MAAEe;IAAO,CAAC,GAAGH,OAAO;IAC1B,MAAM;MAAE0H;IAAc,CAAC,GAAGrH,OAAO;IAEjC,MAAMmD,SAAS,GAAG,IAAI,CAACC,YAAY,CAAC,CAAC;IACrC,MAAMG,WAAW,GAAG,IAAI,CAACC,cAAc,CAAC,CAAC;IACzC,MAAM;MAAE8D;IAAa,CAAC,GAAG,IAAI,CAAClJ,KAAK,CAACmJ,QAAQ;IAC5C,MAAM;MAAEC;IAAgB,CAAC,GAAGF,YAAY;;IAExC;IACA,IAAI,CAACnE,SAAS,EAAEI,WAAW,CAAC,CAACkE,QAAQ,CAAC1I,IAAI,CAAC,IAAI,CAACsI,aAAa,EAAE;MAC7D,MAAM;QAAEK;MAAkB,CAAC,GAAG,MAAMF,eAAe,CAAC1H,MAAM,CAAC6H,IAAI,CAAC;MAChE,OAAO,CAACD,iBAAiB;IAC3B;IAEA,OAAO,KAAK;EACd;;EAEA;AACF;AACA;EACY7E,WAAWA,CACnBlD,OAA2B,EAC3BK,OAAoB,EACpBK,CAA0D,EACpC;IACtB,MAAM;MAAEhC;IAAQ,CAAC,GAAG,IAAI;IACxB,MAAM;MAAEU,IAAI;MAAEmG;IAAM,CAAC,GAAGvF,OAAO;IAC/B,MAAM;MAAEiI;IAAU,CAAC,GAAG1C,KAAK;IAC3B,MAAM;MAAEhC;IAAM,CAAC,GAAGlD,OAAO;IAEzB,MAAMJ,MAAM,GAAG,IAAI,CAACF,SAAS,CAACC,OAAO,CAAC;;IAEtC;IACA,IAAIiI,SAAS,EAAE;MACb,OAAO;QACLhG,IAAI,EACFtF,WAAW,CAAC+B,OAAO,CAAC,IAAIuB,MAAM,GAC1BS,CAAC,CAAC,iCAAiC,CAAC,GACpCA,CAAC,CAAC,mCAAmC,CAAC;QAC5CwH,IAAI,EAAED;MACR,CAAC;IACH;;IAEA;IACA,MAAME,QAAQ,GACZlI,MAAM,IAAI,CAACb,IAAI,CAACgD,QAAQ,CAACnC,MAAM,CAAC,GAC5BsD,KAAK,CAACzB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAAA,EACbyB,KAAK,CAACzB,EAAE,CAAC,CAAC,CAAC,CAAC,EAAC;;IAEnB;IACA,IAAI,CAACqG,QAAQ,EAAE;MACb;IACF;;IAEA;IACA,OAAO;MACLlG,IAAI,EAAEvB,CAAC,CAAC,aAAa,CAAC;MACtBwH,IAAI,EAAE,IAAI,CAACE,OAAO,CAACD,QAAQ;IAC7B,CAAC;EACH;EAEAE,oBAAoBA,CAAA,EAAG;IACrB,OAAO,OACLrI,OAA2B,EAC3BK,OAAoB,EACpBqG,CAAsB,KACnB;MACH,MAAM;QAAErI,UAAU;QAAEsI,QAAQ;QAAElI;MAAM,CAAC,GAAG,IAAI;MAC5C,MAAM;QAAEiJ,aAAa;QAAE7C,KAAK;QAAElC;MAAgB,CAAC,GAAGtC,OAAO;MACzD,MAAMrB,MAAM,GAAGgB,OAAO,CAACQ,OAAO,CAACxB,MAAM;MAErC,MAAMsB,UAAU,GAAG,IAAI,CAACsG,aAAa,CAAC5G,OAAO,CAAC;MAC9C,MAAM;QAAEU;MAAE,CAAC,GAAGJ,UAAU;MAExB,IAAItB,MAAM,EAAEsJ,UAAU,CAACxK,UAAU,CAACyK,QAAQ,CAAC,EAAE;QAC3C,OAAO,MAAM,IAAI,CAACC,gBAAgB,CAACxI,OAAO,EAAE0G,CAAC,EAAErG,OAAO,CAAC;MACzD;;MAEA;AACN;AACA;AACA;MACM,IAAIA,OAAO,CAACI,MAAM,IAAIiH,aAAa,EAAE;QACnC,MAAMnH,SAAS,GAAG,IAAI,CAACH,YAAY,CAACJ,OAAO,EAAEK,OAAO,EAAEC,UAAU,CAAC;QACjEC,SAAS,CAACE,MAAM,GAAGpC,UAAU,CAAC2I,aAAa,CACzC1G,UAAU,EACVC,SAAS,CAACE,MACZ,CAAC;;QAED;QACAF,SAAS,CAAC5B,UAAU,GAAG,IAAI,CAACkH,2BAA2B,CACrDtF,SAAS,EACT9B,KAAK,EACLkE,eACF,CAAC;QAED,OAAO+D,CAAC,CAACe,IAAI,CAACd,QAAQ,EAAE;UACtB,GAAGpG,SAAS;UACZG;QACF,CAAC,CAAC;MACJ;;MAEA;MACA,MAAM,IAAI,CAAC+E,QAAQ,CAACzF,OAAO,EAAE6E,KAAK,CAAC;;MAEnC;MACA,IAAI7F,MAAM,KAAKlB,UAAU,CAAC2K,WAAW,EAAE;QACrC,OAAO,IAAI,CAACC,iBAAiB,CAAC1I,OAAO,EAAEK,OAAO,EAAEqG,CAAC,CAAC;MACpD;;MAEA;MACA,OAAO,IAAI,CAACjJ,OAAO,CAACuC,OAAO,EAAE0G,CAAC,EAAE,IAAI,CAAC/C,WAAW,CAACtD,OAAO,CAAC,CAAC;IAC5D,CAAC;EACH;EAEA,MAAcmI,gBAAgBA,CAC5BxI,OAA2B,EAC3B0G,CAAsB,EACtBrG,OAAoB,EACpB;IACA,MAAM;MAAEsI;IAAmB,CAAC,GAAG/K,mBAAmB,CAAC,CAAC;IACpD,MAAMoB,MAAM,GAAGgB,OAAO,CAACQ,OAAO,CAACxB,MAAM,IAAI,EAAE;;IAE3C;IACA;IACA;IACA,MAAM4J,uBAAuB,GAAG5J,MAAM,CACnCqF,KAAK,CAAC,GAAGvG,UAAU,CAACyK,QAAQ,GAAG,CAACzI,MAAM,CAAC,CACvC+I,KAAK,CAAC,IAAI,CAAC;IAEd,MAAMC,kBAAkB,GAAGF,uBAAuB,CAC/CvE,KAAK,CAAC,CAAC,CAAC,CACR8B,GAAG,CAAE4C,GAAG,IAAKA,GAAG,CAACF,KAAK,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAMG,IAAI,GAAGC,MAAM,CAACC,WAAW,CAACJ,kBAAkB,CAGjD;IAED,MAAMK,aAAa,GAAGP,uBAAuB,CAAC,CAAC,CAAC;IAChD,MAAM7C,SAAS,GAAG,IAAI,CAACtH,KAAK,CAAC2K,eAAe,CAACC,GAAG,CAACF,aAAa,CAAC;IAC/D,MAAMG,aAAa,GAAGvD,SAAS,EAAEE,IAAI;IAErC,IAAI,CAACqD,aAAa,EAAE;MAClB,MAAMzM,IAAI,CAAC0M,QAAQ,CACjB,8BAA8BD,aAAa,YAC7C,CAAC;IACH;IAEA,MAAME,iBAAiB,GAAGb,kBAAkB,CAACU,GAAG,CAACC,aAAa,CAAC;IAE/D,IAAI,CAACE,iBAAiB,EAAE;MACtB,MAAM3M,IAAI,CAAC0M,QAAQ,CAAC,sBAAsBJ,aAAa,YAAY,CAAC;IACtE;;IAEA;IACA,MAAMM,cAAc,GAAG;MACrB,GAAGpJ,OAAO,CAACG,OAAO;MAClBzB,KAAK,EAAEkF,SAAS;MAChBjF,MAAM,EAAEiF;IACV,CAAC;IACDjE,OAAO,CAACkH,GAAG,CAACC,KAAK,CAACnK,sBAAsB,EAAEyM,cAAc,EAAE,IAAI,CAAC;;IAE/D;IACAzJ,OAAO,CAACkH,GAAG,CAACwC,KAAK,CAAC3M,wBAAwB,CAAC;;IAE3C;IACA,MAAM;MAAE8H,KAAK;MAAE8E;IAAU,CAAC,GAAGvM,eAAe,CAAC4C,OAAO,CAACG,MAAM,CAAC;IAC5D,MAAMyJ,MAAM,GAAG/E,KAAK,KAAK9G,UAAU,CAAC8L,IAAI;IAExC,OAAO,MAAML,iBAAiB,CAACM,UAAU,CAAC9J,OAAO,EAAE0G,CAAC,EAAE;MACpDX,SAAS;MACTnG,UAAU,EAAE,IAAI;MAChBmK,SAAS,EAAE,GAAG/J,OAAO,CAAC8G,GAAG,CAACC,QAAQ,GAAG/G,OAAO,CAAC8G,GAAG,CAACkD,MAAM,EAAE;MACzDC,UAAU,EAAEjB,IAAI;MAChBY,MAAM;MACND;IACF,CAAC,CAAC;EACJ;EAEAlM,OAAOA,CACLuC,OAA2B,EAC3B0G,CAAsB,EACtBwD,QAAiB,EACjB;IACA,MAAMC,OAAO,GAAGD,QAAQ,GACpB,IAAI,CAAC9B,OAAO,CAAC8B,QAAQ,CAAC,CAAC;IAAA,EACvB,IAAI,CAAChC,IAAI,EAAC;;IAEd,OAAOzK,OAAO,CAACuC,OAAO,EAAE0G,CAAC,EAAEyD,OAAO,CAAC;EACrC;;EAEA;AACF;AACA;EACEzB,iBAAiBA,CACf1I,OAA2B,EAC3BK,OAAoB,EACpBqG,CAAsB,EACtB;IACA,MAAM0D,WAAW,GAAG7M,qBAAqB,CAACyC,OAAO,CAACoD,MAAM,CAAC;IAEzD,IAAI,CAACgH,WAAW,EAAE;MAChB,MAAMvN,IAAI,CAAC0M,QAAQ,CAAC,wCAAwC,CAAC;IAC/D;IAEA,OAAOa,WAAW,CAACpK,OAAO,EAAE0G,CAAC,EAAErG,OAAO,CAAC;EACzC;;EAEA;AACF;AACA;EACE,IAAIgK,eAAeA,CAAA,EAAkC;IACnD,OAAO;MACLC,GAAG,EAAE;QACHC,aAAa,EAAE;UACbC,MAAMA,CAACC,QAAQ,EAAE/D,CAAC,EAAE;YAClB,OAAOA,CAAC,CAACgE,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;;EAEA;AACF;AACA;EACE,IAAIC,gBAAgBA,CAAA,EAAyC;IAC3D,OAAO;MACLnK,OAAO,EAAE;QACPoK,KAAK,EAAE,IAAI;QACXC,QAAQ,EAAEC,MAAM,CAACC,gBAAgB;QACjCC,UAAU,EAAE;MACd,CAAC;MACDV,GAAG,EAAE;QACHC,aAAa,EAAE;UACbC,MAAMA,CAACC,QAAQ,EAAE/D,CAAC,EAAE;YAClB,OAAOA,CAAC,CAACgE,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;AACF","ignoreList":[]}
@@ -51,7 +51,7 @@ export class SummaryPageController extends QuestionPageController {
51
51
  const paymentState = paymentField.getPaymentStateFromState(state);
52
52
  if (paymentState?.amount === resolvedAmount) {
53
53
  viewModel.paymentState = paymentState;
54
- viewModel.paymentDetails = this.buildPaymentDetails(paymentField, paymentState, t);
54
+ viewModel.paymentDetails = this.buildPaymentDetails(paymentField, paymentState, translator);
55
55
  }
56
56
  if (resolvedAmount > 0) {
57
57
  viewModel.paymentRequired = true;
@@ -73,7 +73,10 @@ export class SummaryPageController extends QuestionPageController {
73
73
  viewModel.errors = errors;
74
74
  return viewModel;
75
75
  }
76
- buildPaymentDetails(paymentField, paymentState, t) {
76
+ buildPaymentDetails(paymentField, paymentState, translator) {
77
+ const {
78
+ t
79
+ } = translator;
77
80
  const rows = [{
78
81
  key: {
79
82
  text: t('pages.summary.paymentFor')
@@ -102,7 +105,7 @@ export class SummaryPageController extends QuestionPageController {
102
105
  text: t('pages.summary.dateOfPayment')
103
106
  },
104
107
  value: {
105
- text: formatPaymentDate(paymentState.preAuth.createdAt)
108
+ text: formatPaymentDate(paymentState.preAuth.createdAt, translator.language)
106
109
  }
107
110
  });
108
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SummaryPageController.js","names":["hasComponentsEvenIfNoNext","Boom","StatusCodes","COMPONENT_STATE_ERROR","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","PaymentField","checkEmailAddressForLiveFormSubmission","checkFormStatus","createError","getCacheService","SummaryViewModel","QuestionPageController","InvalidComponentStateError","PaymentErrorTypes","PaymentPreAuthError","PaymentSubmissionError","buildMainRecords","buildRepeaterRecords","DEFAULT_PAYMENT_HELP_URL","formatCurrency","formatPaymentDate","FormAction","SummaryPageController","allowSaveAndExit","findPaymentField","model","pages","flatMap","page","collection","fields","find","field","constructor","pageDef","viewName","components","getSummaryViewModel","request","context","translator","t","viewModel","payload","errors","state","paymentField","resolvedAmount","resolveAmount","options","paymentState","getPaymentStateFromState","amount","paymentDetails","buildPaymentDetails","paymentRequired","preAuth","status","paymentPreAuthorized","getViewModel","backLink","getBackLink","feedbackLink","phaseTag","shouldShowSaveAndExit","server","rows","key","text","value","description","reference","createdAt","push","title","summaryList","makeGetRouteHandler","h","getTranslator","query","paymentComplete","handleFormSubmit","reconcilePaymentState","hasMissingNotificationEmail","view","cacheService","resetComponentStates","name","makePostRouteHandler","action","SaveAndExit","handleSaveAndExit","params","formsService","services","getFormMetadata","formMetadata","slug","notificationEmail","isPreview","submitForm","error","handleSubmissionError","setConfirmationState","confirmed","formId","referenceNumber","clearState","proceed","getStatusPath","handleInvalidComponentStateError","handlePaymentPreAuthError","handlePaymentSubmissionError","govukError","component","userMessage","yar","flash","getStateKeys","path","shouldResetState","errorType","PaymentExpired","PaymentIncomplete","redirect","getHref","code","SEE_OTHER","redirectPath","undefined","helpUrl","helpLink","contactUsLink","helpLinkHtml","postRouteOptions","ext","onPreHandler","method","continue","summaryViewModel","emailAddress","finaliseComponents","paymentWasCaptured","hasPaymentBeenCaptured","formStatus","logTags","logger","info","items","getFormSubmissionData","details","submitResponse","submitData","id","badRequest","outputService","submit","err","contact","online","url","capture","metadata","allFields","Set","relevantPages","filter","onSubmit","retrievalKey","sessionId","formSubmissionService","main","repeaters","language","def","translations","cy","map","href","flat","paymentItems","getPaymentFieldItems","label","summaryLabel","getDisplayStringFromState"],"sources":["../../../../../src/server/plugins/engine/pageControllers/SummaryPageController.ts"],"sourcesContent":["import {\n hasComponentsEvenIfNoNext,\n type FormMetadata,\n type Page,\n type SubmitPayload\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { StatusCodes } from 'http-status-codes'\n\nimport {\n COMPONENT_STATE_ERROR,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n createError,\n getCacheService\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport {\n type Detail,\n type DetailItem,\n type DetailItemField\n} from '~/src/server/plugins/engine/models/types.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n InvalidComponentStateError,\n PaymentErrorTypes,\n PaymentPreAuthError,\n PaymentSubmissionError\n} from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport {\n buildMainRecords,\n buildRepeaterRecords\n} from '~/src/server/plugins/engine/pageControllers/helpers/submission.js'\nimport {\n type FormConfirmationState,\n type FormContext,\n type FormContextRequest\n} from '~/src/server/plugins/engine/types.js'\nimport {\n DEFAULT_PAYMENT_HELP_URL,\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\n\nexport class SummaryPageController extends QuestionPageController {\n declare pageDef: Page\n allowSaveAndExit = true\n\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/summary.js\"\n */\n\n /**\n * Finds the PaymentField component across all pages in the model.\n * Payment pages are skipped in the normal page walk\n */\n private findPaymentField(): PaymentField | undefined {\n return this.model.pages\n .flatMap((page) => page.collection.fields)\n .find((field): field is PaymentField => field instanceof PaymentField)\n }\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n this.viewName = 'summary'\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n }\n\n getSummaryViewModel(\n request: FormContextRequest,\n context: FormContext,\n translator: Translator\n ): SummaryViewModel {\n const { t } = translator\n\n const viewModel = new SummaryViewModel(request, this, context, translator)\n\n const { payload, errors, state } = context\n\n const paymentField = this.findPaymentField()\n\n if (paymentField) {\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n state\n )\n const paymentState = paymentField.getPaymentStateFromState(state)\n\n if (paymentState?.amount === resolvedAmount) {\n viewModel.paymentState = paymentState\n viewModel.paymentDetails = this.buildPaymentDetails(\n paymentField,\n paymentState,\n t\n )\n }\n\n if (resolvedAmount > 0) {\n viewModel.paymentRequired = true\n }\n if (\n paymentState &&\n paymentState.preAuth?.status === 'success' &&\n paymentState.amount === resolvedAmount\n ) {\n viewModel.paymentPreAuthorized = true\n }\n }\n\n const components = this.collection.getViewModel({\n payload,\n errors,\n translator\n })\n\n viewModel.backLink = this.getBackLink(request, context, t)\n viewModel.feedbackLink = this.feedbackLink\n viewModel.phaseTag = this.phaseTag\n viewModel.components = components\n viewModel.allowSaveAndExit = this.shouldShowSaveAndExit(request.server)\n viewModel.errors = errors\n\n return viewModel\n }\n\n private buildPaymentDetails(\n paymentField: PaymentField,\n paymentState: NonNullable<\n ReturnType<PaymentField['getPaymentStateFromState']>\n >,\n t: (key: string, opts?: Record<string, unknown>) => string\n ) {\n const rows = [\n {\n key: { text: t('pages.summary.paymentFor') },\n value: { text: paymentState.description }\n },\n {\n key: { text: t('pages.summary.totalAmount') },\n value: { text: formatCurrency(paymentState.amount) }\n },\n {\n key: { text: t('pages.summary.reference') },\n value: { text: paymentState.reference }\n }\n ]\n\n if (paymentState.preAuth?.createdAt) {\n rows.push({\n key: { text: t('pages.summary.dateOfPayment') },\n value: { text: formatPaymentDate(paymentState.preAuth.createdAt) }\n })\n }\n\n return {\n title: { text: t('pages.summary.paymentDetailsTitle') },\n summaryList: { rows }\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,\n */\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { viewName } = this\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n // After GOV.UK Pay callback, auto-submit the form instead of\n // showing CYA again. The payment is already pre-authorized.\n if (request.query.paymentComplete === 'true') {\n return this.handleFormSubmit(\n request as unknown as FormRequestPayload,\n context,\n h\n )\n }\n\n await this.reconcilePaymentState(request, context)\n\n const viewModel = this.getSummaryViewModel(request, context, translator)\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n viewModel.t = t\n return h.view(viewName, viewModel)\n }\n }\n\n /**\n * Checks if the resolved payment amount has changed since pre-auth\n * and invalidates stale payment state if so.\n */\n private async reconcilePaymentState(\n request: FormRequest,\n context: FormContext\n ) {\n const paymentField = this.findPaymentField()\n\n if (!paymentField) {\n return\n }\n\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n context.state\n )\n const paymentState = paymentField.getPaymentStateFromState(context.state)\n\n if (paymentState && paymentState.amount !== resolvedAmount) {\n const cacheService = getCacheService(request.server)\n await cacheService.resetComponentStates(request, [paymentField.name])\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.\n * If a form is incomplete, a user will be redirected to the start page.\n */\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { action } = request.payload\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n return this.handleFormSubmit(request, context, h)\n }\n }\n\n async handleFormSubmit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const { model } = this\n const { params } = request\n\n const cacheService = getCacheService(request.server)\n\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n const formMetadata = await getFormMetadata(params.slug)\n const { notificationEmail } = formMetadata\n const { isPreview } = checkFormStatus(request.params)\n\n checkEmailAddressForLiveFormSubmission(notificationEmail, isPreview)\n\n if (notificationEmail) {\n const translator = this.getTranslator(request)\n const viewModel = this.getSummaryViewModel(request, context, translator)\n\n try {\n await submitForm(\n context,\n formMetadata,\n request,\n viewModel,\n model,\n notificationEmail,\n translator\n )\n } catch (error) {\n return this.handleSubmissionError(error, request, h)\n }\n }\n\n await cacheService.setConfirmationState(request, {\n confirmed: true,\n formId: context.state.formId,\n referenceNumber: context.referenceNumber\n } as FormConfirmationState)\n\n await cacheService.clearState(request)\n\n return this.proceed(request, h, this.getStatusPath())\n }\n\n /**\n * Handles errors during form submission\n */\n private async handleSubmissionError(\n error: unknown,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n if (error instanceof InvalidComponentStateError) {\n return this.handleInvalidComponentStateError(error, request, h)\n }\n\n if (error instanceof PaymentPreAuthError) {\n return this.handlePaymentPreAuthError(error, request, h)\n }\n\n if (error instanceof PaymentSubmissionError) {\n return this.handlePaymentSubmissionError(error, request, h)\n }\n\n throw error\n }\n\n /**\n * Handles InvalidComponentStateError during submission\n */\n private async handleInvalidComponentStateError(\n error: InvalidComponentStateError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n const govukError = createError(error.component.name, error.userMessage)\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n return this.proceed(request, h, error.component.page?.path)\n }\n\n /**\n * Handles PaymentPreAuthError during submission\n */\n private async handlePaymentPreAuthError(\n error: PaymentPreAuthError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n if (error.shouldResetState) {\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n if (error.errorType === PaymentErrorTypes.PaymentExpired) {\n request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION, true, true)\n return this.proceed(request, h, error.component.page?.path)\n }\n }\n\n // Payment page is skipped in the page walk, so proceed() would redirect\n // to an earlier page. For PaymentIncomplete, redirect directly to the\n // payment page using its href.\n if (\n error.errorType === PaymentErrorTypes.PaymentIncomplete &&\n error.component.page\n ) {\n return h\n .redirect(error.component.page.getHref(error.component.page.path))\n .code(StatusCodes.SEE_OTHER)\n }\n\n const govukError = createError(error.component.name, error.userMessage)\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n const redirectPath = error.shouldResetState\n ? error.component.page?.path\n : undefined\n\n return this.proceed(request, h, redirectPath)\n }\n\n /**\n * Handles PaymentSubmissionError during submission\n */\n private handlePaymentSubmissionError(\n error: PaymentSubmissionError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const { t } = this.getTranslator(request)\n\n const helpUrl = error.helpLink ?? DEFAULT_PAYMENT_HELP_URL\n const contactUsLink = `<a href=\"${helpUrl}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"govuk-link\">${t('pages.summary.contactUsLinkText')}</a>`\n const helpLinkHtml = t('pages.summary.submissionFailedContactSuffix', {\n contactUsLink\n })\n\n const govukError = createError(\n 'submission',\n `${t('pages.summary.submissionFailed')}${helpLinkHtml}.`\n )\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n return this.proceed(request, h)\n }\n\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n ext: {\n onPreHandler: {\n method(request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n\nexport async function submitForm(\n context: FormContext,\n formMetadata: FormMetadata,\n request: FormRequestPayload,\n summaryViewModel: SummaryViewModel,\n model: FormModel,\n emailAddress: string,\n translator: Translator\n) {\n await finaliseComponents(request, formMetadata, context, model)\n\n const paymentWasCaptured = hasPaymentBeenCaptured(context, model)\n\n const formStatus = checkFormStatus(request.params)\n const logTags = ['submit', 'submissionApi']\n\n request.logger.info(logTags, 'Preparing email', formStatus)\n\n const items = getFormSubmissionData(\n summaryViewModel.context,\n summaryViewModel.details,\n translator,\n model\n )\n\n try {\n request.logger.info(logTags, 'Submitting data')\n const submitResponse = await submitData(\n model,\n items,\n emailAddress,\n request.yar.id,\n translator,\n summaryViewModel.context.referenceNumber\n )\n\n if (submitResponse === undefined) {\n throw Boom.badRequest('Unexpected empty response from submit api')\n }\n\n await model.services.outputService.submit(\n context,\n request,\n model,\n emailAddress,\n items,\n submitResponse,\n formMetadata\n )\n } catch (err) {\n if (paymentWasCaptured) {\n throw new PaymentSubmissionError(\n context.referenceNumber,\n formMetadata.contact?.online?.url\n )\n }\n throw err\n }\n}\n\n/**\n * Checks if any payment component has been captured\n */\nfunction hasPaymentBeenCaptured(\n context: FormContext,\n model: FormModel\n): boolean {\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n const paymentState = field.getPaymentStateFromState(context.state)\n if (paymentState?.capture?.status === 'success') {\n return true\n }\n }\n }\n }\n return false\n}\n\n/**\n * Finalises any components that need post-processing before form submission. Candidates usually involve\n * those that have external state.\n * Examples include:\n * - file uploads which are 'persisted' before submission\n * - payments which are 'captured' before submission\n */\nasync function finaliseComponents(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext,\n model: FormModel\n) {\n // Get fields from relevant pages (normal components)\n // plus PaymentField from all pages (payment page is skipped in the page walk)\n const allFields = new Set([\n ...context.relevantPages.flatMap((page) => page.collection.fields),\n ...model.pages\n .flatMap((page) => page.collection.fields)\n .filter((field) => field instanceof PaymentField)\n ])\n\n for (const component of allFields) {\n await component.onSubmit(request, metadata, context)\n }\n}\n\nfunction submitData(\n model: FormModel,\n items: DetailItem[],\n retrievalKey: string,\n sessionId: string,\n translator: Translator,\n referenceNumber: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n referenceNumber,\n main: buildMainRecords(items, translator),\n repeaters: buildRepeaterRecords(items, translator),\n // Only populate the language property if the form is multi-language enabled\n // @ts-expect-error - dynamic language property\n language: model.def.metadata?.translations?.cy\n ? translator.language\n : undefined\n }\n return submit(payload)\n}\n\nexport function getFormSubmissionData(\n context: FormContext,\n details: Detail[],\n translator: Translator,\n model: FormModel\n) {\n const items = context.relevantPages\n .map(({ href }) =>\n details.flatMap(({ items }) =>\n items.filter(({ page }) => page.href === href)\n )\n )\n .flat()\n\n const paymentItems = getPaymentFieldItems(context, translator, model)\n\n return [...items, ...paymentItems]\n}\n\n/**\n * Gets DetailItems for PaymentField components\n * PaymentField is excluded from summaryDetails for UI but needs to be in submission data\n */\nfunction getPaymentFieldItems(\n context: FormContext,\n translator: Translator,\n model: FormModel\n): DetailItemField[] {\n const items: DetailItemField[] = []\n\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n items.push({\n name: field.name,\n page,\n title: field.title,\n label: field.summaryLabel,\n field,\n state: context.state,\n href: page.href,\n value: field.getDisplayStringFromState(context.state, translator)\n })\n }\n }\n }\n\n return items\n}\n"],"mappings":"AAAA,SACEA,yBAAyB,QAIpB,oBAAoB;AAC3B,OAAOC,IAAI,MAAM,YAAY;AAE7B,SAASC,WAAW,QAAQ,mBAAmB;AAE/C,SACEC,qBAAqB,EACrBC,4BAA4B;AAE9B,SAASC,mBAAmB;AAC5B,SAASC,YAAY;AACrB,SACEC,sCAAsC,EACtCC,eAAe,EACfC,WAAW,EACXC,eAAe;AAGjB,SACEC,gBAAgB;AAQlB,SAASC,sBAAsB;AAC/B,SACEC,0BAA0B,EAC1BC,iBAAiB,EACjBC,mBAAmB,EACnBC,sBAAsB;AAExB,SACEC,gBAAgB,EAChBC,oBAAoB;AAOtB,SACEC,wBAAwB,EACxBC,cAAc,EACdC,iBAAiB;AAEnB,SACEC,UAAU;AAOZ,OAAO,MAAMC,qBAAqB,SAASX,sBAAsB,CAAC;EAEhEY,gBAAgB,GAAG,IAAI;;EAEvB;AACF;AACA;;EAEE;AACF;AACA;AACA;EACUC,gBAAgBA,CAAA,EAA6B;IACnD,OAAO,IAAI,CAACC,KAAK,CAACC,KAAK,CACpBC,OAAO,CAAEC,IAAI,IAAKA,IAAI,CAACC,UAAU,CAACC,MAAM,CAAC,CACzCC,IAAI,CAAEC,KAAK,IAA4BA,KAAK,YAAY3B,YAAY,CAAC;EAC1E;EAEA4B,WAAWA,CAACR,KAAgB,EAAES,OAAa,EAAE;IAC3C,KAAK,CAACT,KAAK,EAAES,OAAO,CAAC;IACrB,IAAI,CAACC,QAAQ,GAAG,SAAS;;IAEzB;IACA,IAAI,CAACN,UAAU,GAAG,IAAIzB,mBAAmB,CACvCL,yBAAyB,CAACmC,OAAO,CAAC,GAAGA,OAAO,CAACE,UAAU,GAAG,EAAE,EAC5D;MAAEX,KAAK;MAAEG,IAAI,EAAE;IAAK,CACtB,CAAC;EACH;EAEAS,mBAAmBA,CACjBC,OAA2B,EAC3BC,OAAoB,EACpBC,UAAsB,EACJ;IAClB,MAAM;MAAEC;IAAE,CAAC,GAAGD,UAAU;IAExB,MAAME,SAAS,GAAG,IAAIhC,gBAAgB,CAAC4B,OAAO,EAAE,IAAI,EAAEC,OAAO,EAAEC,UAAU,CAAC;IAE1E,MAAM;MAAEG,OAAO;MAAEC,MAAM;MAAEC;IAAM,CAAC,GAAGN,OAAO;IAE1C,MAAMO,YAAY,GAAG,IAAI,CAACtB,gBAAgB,CAAC,CAAC;IAE5C,IAAIsB,YAAY,EAAE;MAChB,MAAMC,cAAc,GAAG1C,YAAY,CAAC2C,aAAa,CAC/CF,YAAY,CAACG,OAAO,EACpB,IAAI,CAACxB,KAAK,EACVoB,KACF,CAAC;MACD,MAAMK,YAAY,GAAGJ,YAAY,CAACK,wBAAwB,CAACN,KAAK,CAAC;MAEjE,IAAIK,YAAY,EAAEE,MAAM,KAAKL,cAAc,EAAE;QAC3CL,SAAS,CAACQ,YAAY,GAAGA,YAAY;QACrCR,SAAS,CAACW,cAAc,GAAG,IAAI,CAACC,mBAAmB,CACjDR,YAAY,EACZI,YAAY,EACZT,CACF,CAAC;MACH;MAEA,IAAIM,cAAc,GAAG,CAAC,EAAE;QACtBL,SAAS,CAACa,eAAe,GAAG,IAAI;MAClC;MACA,IACEL,YAAY,IACZA,YAAY,CAACM,OAAO,EAAEC,MAAM,KAAK,SAAS,IAC1CP,YAAY,CAACE,MAAM,KAAKL,cAAc,EACtC;QACAL,SAAS,CAACgB,oBAAoB,GAAG,IAAI;MACvC;IACF;IAEA,MAAMtB,UAAU,GAAG,IAAI,CAACP,UAAU,CAAC8B,YAAY,CAAC;MAC9ChB,OAAO;MACPC,MAAM;MACNJ;IACF,CAAC,CAAC;IAEFE,SAAS,CAACkB,QAAQ,GAAG,IAAI,CAACC,WAAW,CAACvB,OAAO,EAAEC,OAAO,EAAEE,CAAC,CAAC;IAC1DC,SAAS,CAACoB,YAAY,GAAG,IAAI,CAACA,YAAY;IAC1CpB,SAAS,CAACqB,QAAQ,GAAG,IAAI,CAACA,QAAQ;IAClCrB,SAAS,CAACN,UAAU,GAAGA,UAAU;IACjCM,SAAS,CAACnB,gBAAgB,GAAG,IAAI,CAACyC,qBAAqB,CAAC1B,OAAO,CAAC2B,MAAM,CAAC;IACvEvB,SAAS,CAACE,MAAM,GAAGA,MAAM;IAEzB,OAAOF,SAAS;EAClB;EAEQY,mBAAmBA,CACzBR,YAA0B,EAC1BI,YAEC,EACDT,CAA0D,EAC1D;IACA,MAAMyB,IAAI,GAAG,CACX;MACEC,GAAG,EAAE;QAAEC,IAAI,EAAE3B,CAAC,CAAC,0BAA0B;MAAE,CAAC;MAC5C4B,KAAK,EAAE;QAAED,IAAI,EAAElB,YAAY,CAACoB;MAAY;IAC1C,CAAC,EACD;MACEH,GAAG,EAAE;QAAEC,IAAI,EAAE3B,CAAC,CAAC,2BAA2B;MAAE,CAAC;MAC7C4B,KAAK,EAAE;QAAED,IAAI,EAAEjD,cAAc,CAAC+B,YAAY,CAACE,MAAM;MAAE;IACrD,CAAC,EACD;MACEe,GAAG,EAAE;QAAEC,IAAI,EAAE3B,CAAC,CAAC,yBAAyB;MAAE,CAAC;MAC3C4B,KAAK,EAAE;QAAED,IAAI,EAAElB,YAAY,CAACqB;MAAU;IACxC,CAAC,CACF;IAED,IAAIrB,YAAY,CAACM,OAAO,EAAEgB,SAAS,EAAE;MACnCN,IAAI,CAACO,IAAI,CAAC;QACRN,GAAG,EAAE;UAAEC,IAAI,EAAE3B,CAAC,CAAC,6BAA6B;QAAE,CAAC;QAC/C4B,KAAK,EAAE;UAAED,IAAI,EAAEhD,iBAAiB,CAAC8B,YAAY,CAACM,OAAO,CAACgB,SAAS;QAAE;MACnE,CAAC,CAAC;IACJ;IAEA,OAAO;MACLE,KAAK,EAAE;QAAEN,IAAI,EAAE3B,CAAC,CAAC,mCAAmC;MAAE,CAAC;MACvDkC,WAAW,EAAE;QAAET;MAAK;IACtB,CAAC;EACH;;EAEA;AACF;AACA;EACEU,mBAAmBA,CAAA,EAAG;IACpB,OAAO,OACLtC,OAAoB,EACpBC,OAAoB,EACpBsC,CAAsB,KACnB;MACH,MAAM;QAAE1C;MAAS,CAAC,GAAG,IAAI;MAEzB,MAAMK,UAAU,GAAG,IAAI,CAACsC,aAAa,CAACxC,OAAO,CAAC;MAC9C,MAAM;QAAEG;MAAE,CAAC,GAAGD,UAAU;;MAExB;MACA;MACA,IAAIF,OAAO,CAACyC,KAAK,CAACC,eAAe,KAAK,MAAM,EAAE;QAC5C,OAAO,IAAI,CAACC,gBAAgB,CAC1B3C,OAAO,EACPC,OAAO,EACPsC,CACF,CAAC;MACH;MAEA,MAAM,IAAI,CAACK,qBAAqB,CAAC5C,OAAO,EAAEC,OAAO,CAAC;MAElD,MAAMG,SAAS,GAAG,IAAI,CAACL,mBAAmB,CAACC,OAAO,EAAEC,OAAO,EAAEC,UAAU,CAAC;MAExEE,SAAS,CAACyC,2BAA2B,GACnC,MAAM,IAAI,CAACA,2BAA2B,CAAC7C,OAAO,EAAEC,OAAO,CAAC;MAE1DG,SAAS,CAACD,CAAC,GAAGA,CAAC;MACf,OAAOoC,CAAC,CAACO,IAAI,CAACjD,QAAQ,EAAEO,SAAS,CAAC;IACpC,CAAC;EACH;;EAEA;AACF;AACA;AACA;EACE,MAAcwC,qBAAqBA,CACjC5C,OAAoB,EACpBC,OAAoB,EACpB;IACA,MAAMO,YAAY,GAAG,IAAI,CAACtB,gBAAgB,CAAC,CAAC;IAE5C,IAAI,CAACsB,YAAY,EAAE;MACjB;IACF;IAEA,MAAMC,cAAc,GAAG1C,YAAY,CAAC2C,aAAa,CAC/CF,YAAY,CAACG,OAAO,EACpB,IAAI,CAACxB,KAAK,EACVc,OAAO,CAACM,KACV,CAAC;IACD,MAAMK,YAAY,GAAGJ,YAAY,CAACK,wBAAwB,CAACZ,OAAO,CAACM,KAAK,CAAC;IAEzE,IAAIK,YAAY,IAAIA,YAAY,CAACE,MAAM,KAAKL,cAAc,EAAE;MAC1D,MAAMsC,YAAY,GAAG5E,eAAe,CAAC6B,OAAO,CAAC2B,MAAM,CAAC;MACpD,MAAMoB,YAAY,CAACC,oBAAoB,CAAChD,OAAO,EAAE,CAACQ,YAAY,CAACyC,IAAI,CAAC,CAAC;IACvE;EACF;;EAEA;AACF;AACA;AACA;EACEC,oBAAoBA,CAAA,EAAG;IACrB,OAAO,OACLlD,OAA2B,EAC3BC,OAAoB,EACpBsC,CAAsB,KACnB;MACH,MAAM;QAAEY;MAAO,CAAC,GAAGnD,OAAO,CAACK,OAAO;MAClC,IAAI8C,MAAM,KAAKpE,UAAU,CAACqE,WAAW,EAAE;QACrC,OAAO,IAAI,CAACC,iBAAiB,CAACrD,OAAO,EAAEC,OAAO,EAAEsC,CAAC,CAAC;MACpD;MAEA,OAAO,IAAI,CAACI,gBAAgB,CAAC3C,OAAO,EAAEC,OAAO,EAAEsC,CAAC,CAAC;IACnD,CAAC;EACH;EAEA,MAAMI,gBAAgBA,CACpB3C,OAA2B,EAC3BC,OAAoB,EACpBsC,CAAsB,EACtB;IACA,MAAM;MAAEpD;IAAM,CAAC,GAAG,IAAI;IACtB,MAAM;MAAEmE;IAAO,CAAC,GAAGtD,OAAO;IAE1B,MAAM+C,YAAY,GAAG5E,eAAe,CAAC6B,OAAO,CAAC2B,MAAM,CAAC;IAEpD,MAAM;MAAE4B;IAAa,CAAC,GAAG,IAAI,CAACpE,KAAK,CAACqE,QAAQ;IAC5C,MAAM;MAAEC;IAAgB,CAAC,GAAGF,YAAY;IAExC,MAAMG,YAAY,GAAG,MAAMD,eAAe,CAACH,MAAM,CAACK,IAAI,CAAC;IACvD,MAAM;MAAEC;IAAkB,CAAC,GAAGF,YAAY;IAC1C,MAAM;MAAEG;IAAU,CAAC,GAAG5F,eAAe,CAAC+B,OAAO,CAACsD,MAAM,CAAC;IAErDtF,sCAAsC,CAAC4F,iBAAiB,EAAEC,SAAS,CAAC;IAEpE,IAAID,iBAAiB,EAAE;MACrB,MAAM1D,UAAU,GAAG,IAAI,CAACsC,aAAa,CAACxC,OAAO,CAAC;MAC9C,MAAMI,SAAS,GAAG,IAAI,CAACL,mBAAmB,CAACC,OAAO,EAAEC,OAAO,EAAEC,UAAU,CAAC;MAExE,IAAI;QACF,MAAM4D,UAAU,CACd7D,OAAO,EACPyD,YAAY,EACZ1D,OAAO,EACPI,SAAS,EACTjB,KAAK,EACLyE,iBAAiB,EACjB1D,UACF,CAAC;MACH,CAAC,CAAC,OAAO6D,KAAK,EAAE;QACd,OAAO,IAAI,CAACC,qBAAqB,CAACD,KAAK,EAAE/D,OAAO,EAAEuC,CAAC,CAAC;MACtD;IACF;IAEA,MAAMQ,YAAY,CAACkB,oBAAoB,CAACjE,OAAO,EAAE;MAC/CkE,SAAS,EAAE,IAAI;MACfC,MAAM,EAAElE,OAAO,CAACM,KAAK,CAAC4D,MAAM;MAC5BC,eAAe,EAAEnE,OAAO,CAACmE;IAC3B,CAA0B,CAAC;IAE3B,MAAMrB,YAAY,CAACsB,UAAU,CAACrE,OAAO,CAAC;IAEtC,OAAO,IAAI,CAACsE,OAAO,CAACtE,OAAO,EAAEuC,CAAC,EAAE,IAAI,CAACgC,aAAa,CAAC,CAAC,CAAC;EACvD;;EAEA;AACF;AACA;EACE,MAAcP,qBAAqBA,CACjCD,KAAc,EACd/D,OAA2B,EAC3BuC,CAAsB,EACtB;IACA,IAAIwB,KAAK,YAAYzF,0BAA0B,EAAE;MAC/C,OAAO,IAAI,CAACkG,gCAAgC,CAACT,KAAK,EAAE/D,OAAO,EAAEuC,CAAC,CAAC;IACjE;IAEA,IAAIwB,KAAK,YAAYvF,mBAAmB,EAAE;MACxC,OAAO,IAAI,CAACiG,yBAAyB,CAACV,KAAK,EAAE/D,OAAO,EAAEuC,CAAC,CAAC;IAC1D;IAEA,IAAIwB,KAAK,YAAYtF,sBAAsB,EAAE;MAC3C,OAAO,IAAI,CAACiG,4BAA4B,CAACX,KAAK,EAAE/D,OAAO,EAAEuC,CAAC,CAAC;IAC7D;IAEA,MAAMwB,KAAK;EACb;;EAEA;AACF;AACA;EACE,MAAcS,gCAAgCA,CAC5CT,KAAiC,EACjC/D,OAA2B,EAC3BuC,CAAsB,EACtB;IACA,MAAMQ,YAAY,GAAG5E,eAAe,CAAC6B,OAAO,CAAC2B,MAAM,CAAC;IAEpD,MAAMgD,UAAU,GAAGzG,WAAW,CAAC6F,KAAK,CAACa,SAAS,CAAC3B,IAAI,EAAEc,KAAK,CAACc,WAAW,CAAC;IAEvE7E,OAAO,CAAC8E,GAAG,CAACC,KAAK,CAACnH,qBAAqB,EAAE+G,UAAU,EAAE,IAAI,CAAC;IAE1D,MAAM5B,YAAY,CAACC,oBAAoB,CAAChD,OAAO,EAAE+D,KAAK,CAACiB,YAAY,CAAC,CAAC,CAAC;IAEtE,OAAO,IAAI,CAACV,OAAO,CAACtE,OAAO,EAAEuC,CAAC,EAAEwB,KAAK,CAACa,SAAS,CAACtF,IAAI,EAAE2F,IAAI,CAAC;EAC7D;;EAEA;AACF;AACA;EACE,MAAcR,yBAAyBA,CACrCV,KAA0B,EAC1B/D,OAA2B,EAC3BuC,CAAsB,EACtB;IACA,MAAMQ,YAAY,GAAG5E,eAAe,CAAC6B,OAAO,CAAC2B,MAAM,CAAC;IAEpD,IAAIoC,KAAK,CAACmB,gBAAgB,EAAE;MAC1B,MAAMnC,YAAY,CAACC,oBAAoB,CAAChD,OAAO,EAAE+D,KAAK,CAACiB,YAAY,CAAC,CAAC,CAAC;MAEtE,IAAIjB,KAAK,CAACoB,SAAS,KAAK5G,iBAAiB,CAAC6G,cAAc,EAAE;QACxDpF,OAAO,CAAC8E,GAAG,CAACC,KAAK,CAAClH,4BAA4B,EAAE,IAAI,EAAE,IAAI,CAAC;QAC3D,OAAO,IAAI,CAACyG,OAAO,CAACtE,OAAO,EAAEuC,CAAC,EAAEwB,KAAK,CAACa,SAAS,CAACtF,IAAI,EAAE2F,IAAI,CAAC;MAC7D;IACF;;IAEA;IACA;IACA;IACA,IACElB,KAAK,CAACoB,SAAS,KAAK5G,iBAAiB,CAAC8G,iBAAiB,IACvDtB,KAAK,CAACa,SAAS,CAACtF,IAAI,EACpB;MACA,OAAOiD,CAAC,CACL+C,QAAQ,CAACvB,KAAK,CAACa,SAAS,CAACtF,IAAI,CAACiG,OAAO,CAACxB,KAAK,CAACa,SAAS,CAACtF,IAAI,CAAC2F,IAAI,CAAC,CAAC,CACjEO,IAAI,CAAC7H,WAAW,CAAC8H,SAAS,CAAC;IAChC;IAEA,MAAMd,UAAU,GAAGzG,WAAW,CAAC6F,KAAK,CAACa,SAAS,CAAC3B,IAAI,EAAEc,KAAK,CAACc,WAAW,CAAC;IACvE7E,OAAO,CAAC8E,GAAG,CAACC,KAAK,CAACnH,qBAAqB,EAAE+G,UAAU,EAAE,IAAI,CAAC;IAE1D,MAAMe,YAAY,GAAG3B,KAAK,CAACmB,gBAAgB,GACvCnB,KAAK,CAACa,SAAS,CAACtF,IAAI,EAAE2F,IAAI,GAC1BU,SAAS;IAEb,OAAO,IAAI,CAACrB,OAAO,CAACtE,OAAO,EAAEuC,CAAC,EAAEmD,YAAY,CAAC;EAC/C;;EAEA;AACF;AACA;EACUhB,4BAA4BA,CAClCX,KAA6B,EAC7B/D,OAA2B,EAC3BuC,CAAsB,EACtB;IACA,MAAM;MAAEpC;IAAE,CAAC,GAAG,IAAI,CAACqC,aAAa,CAACxC,OAAO,CAAC;IAEzC,MAAM4F,OAAO,GAAG7B,KAAK,CAAC8B,QAAQ,IAAIjH,wBAAwB;IAC1D,MAAMkH,aAAa,GAAG,YAAYF,OAAO,kEAAkEzF,CAAC,CAAC,iCAAiC,CAAC,MAAM;IACrJ,MAAM4F,YAAY,GAAG5F,CAAC,CAAC,6CAA6C,EAAE;MACpE2F;IACF,CAAC,CAAC;IAEF,MAAMnB,UAAU,GAAGzG,WAAW,CAC5B,YAAY,EACZ,GAAGiC,CAAC,CAAC,gCAAgC,CAAC,GAAG4F,YAAY,GACvD,CAAC;IAED/F,OAAO,CAAC8E,GAAG,CAACC,KAAK,CAACnH,qBAAqB,EAAE+G,UAAU,EAAE,IAAI,CAAC;IAE1D,OAAO,IAAI,CAACL,OAAO,CAACtE,OAAO,EAAEuC,CAAC,CAAC;EACjC;EAEA,IAAIyD,gBAAgBA,CAAA,EAAyC;IAC3D,OAAO;MACLC,GAAG,EAAE;QACHC,YAAY,EAAE;UACZC,MAAMA,CAACnG,OAAO,EAAEuC,CAAC,EAAE;YACjB,OAAOA,CAAC,CAAC6D,QAAQ;UACnB;QACF;MACF;IACF,CAAC;EACH;AACF;AAEA,OAAO,eAAetC,UAAUA,CAC9B7D,OAAoB,EACpByD,YAA0B,EAC1B1D,OAA2B,EAC3BqG,gBAAkC,EAClClH,KAAgB,EAChBmH,YAAoB,EACpBpG,UAAsB,EACtB;EACA,MAAMqG,kBAAkB,CAACvG,OAAO,EAAE0D,YAAY,EAAEzD,OAAO,EAAEd,KAAK,CAAC;EAE/D,MAAMqH,kBAAkB,GAAGC,sBAAsB,CAACxG,OAAO,EAAEd,KAAK,CAAC;EAEjE,MAAMuH,UAAU,GAAGzI,eAAe,CAAC+B,OAAO,CAACsD,MAAM,CAAC;EAClD,MAAMqD,OAAO,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC;EAE3C3G,OAAO,CAAC4G,MAAM,CAACC,IAAI,CAACF,OAAO,EAAE,iBAAiB,EAAED,UAAU,CAAC;EAE3D,MAAMI,KAAK,GAAGC,qBAAqB,CACjCV,gBAAgB,CAACpG,OAAO,EACxBoG,gBAAgB,CAACW,OAAO,EACxB9G,UAAU,EACVf,KACF,CAAC;EAED,IAAI;IACFa,OAAO,CAAC4G,MAAM,CAACC,IAAI,CAACF,OAAO,EAAE,iBAAiB,CAAC;IAC/C,MAAMM,cAAc,GAAG,MAAMC,UAAU,CACrC/H,KAAK,EACL2H,KAAK,EACLR,YAAY,EACZtG,OAAO,CAAC8E,GAAG,CAACqC,EAAE,EACdjH,UAAU,EACVmG,gBAAgB,CAACpG,OAAO,CAACmE,eAC3B,CAAC;IAED,IAAI6C,cAAc,KAAKtB,SAAS,EAAE;MAChC,MAAMjI,IAAI,CAAC0J,UAAU,CAAC,2CAA2C,CAAC;IACpE;IAEA,MAAMjI,KAAK,CAACqE,QAAQ,CAAC6D,aAAa,CAACC,MAAM,CACvCrH,OAAO,EACPD,OAAO,EACPb,KAAK,EACLmH,YAAY,EACZQ,KAAK,EACLG,cAAc,EACdvD,YACF,CAAC;EACH,CAAC,CAAC,OAAO6D,GAAG,EAAE;IACZ,IAAIf,kBAAkB,EAAE;MACtB,MAAM,IAAI/H,sBAAsB,CAC9BwB,OAAO,CAACmE,eAAe,EACvBV,YAAY,CAAC8D,OAAO,EAAEC,MAAM,EAAEC,GAChC,CAAC;IACH;IACA,MAAMH,GAAG;EACX;AACF;;AAEA;AACA;AACA;AACA,SAASd,sBAAsBA,CAC7BxG,OAAoB,EACpBd,KAAgB,EACP;EACT,KAAK,MAAMG,IAAI,IAAIH,KAAK,CAACC,KAAK,EAAE;IAC9B,KAAK,MAAMM,KAAK,IAAIJ,IAAI,CAACC,UAAU,CAACC,MAAM,EAAE;MAC1C,IAAIE,KAAK,YAAY3B,YAAY,EAAE;QACjC,MAAM6C,YAAY,GAAGlB,KAAK,CAACmB,wBAAwB,CAACZ,OAAO,CAACM,KAAK,CAAC;QAClE,IAAIK,YAAY,EAAE+G,OAAO,EAAExG,MAAM,KAAK,SAAS,EAAE;UAC/C,OAAO,IAAI;QACb;MACF;IACF;EACF;EACA,OAAO,KAAK;AACd;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAeoF,kBAAkBA,CAC/BvG,OAA2B,EAC3B4H,QAAsB,EACtB3H,OAAoB,EACpBd,KAAgB,EAChB;EACA;EACA;EACA,MAAM0I,SAAS,GAAG,IAAIC,GAAG,CAAC,CACxB,GAAG7H,OAAO,CAAC8H,aAAa,CAAC1I,OAAO,CAAEC,IAAI,IAAKA,IAAI,CAACC,UAAU,CAACC,MAAM,CAAC,EAClE,GAAGL,KAAK,CAACC,KAAK,CACXC,OAAO,CAAEC,IAAI,IAAKA,IAAI,CAACC,UAAU,CAACC,MAAM,CAAC,CACzCwI,MAAM,CAAEtI,KAAK,IAAKA,KAAK,YAAY3B,YAAY,CAAC,CACpD,CAAC;EAEF,KAAK,MAAM6G,SAAS,IAAIiD,SAAS,EAAE;IACjC,MAAMjD,SAAS,CAACqD,QAAQ,CAACjI,OAAO,EAAE4H,QAAQ,EAAE3H,OAAO,CAAC;EACtD;AACF;AAEA,SAASiH,UAAUA,CACjB/H,KAAgB,EAChB2H,KAAmB,EACnBoB,YAAoB,EACpBC,SAAiB,EACjBjI,UAAsB,EACtBkE,eAAuB,EACvB;EACA,MAAM;IAAEgE;EAAsB,CAAC,GAAGjJ,KAAK,CAACqE,QAAQ;EAChD,MAAM;IAAE8D;EAAO,CAAC,GAAGc,qBAAqB;EAExC,MAAM/H,OAAsB,GAAG;IAC7B8H,SAAS;IACTD,YAAY;IACZ9D,eAAe;IACfiE,IAAI,EAAE3J,gBAAgB,CAACoI,KAAK,EAAE5G,UAAU,CAAC;IACzCoI,SAAS,EAAE3J,oBAAoB,CAACmI,KAAK,EAAE5G,UAAU,CAAC;IAClD;IACA;IACAqI,QAAQ,EAAEpJ,KAAK,CAACqJ,GAAG,CAACZ,QAAQ,EAAEa,YAAY,EAAEC,EAAE,GAC1CxI,UAAU,CAACqI,QAAQ,GACnB5C;EACN,CAAC;EACD,OAAO2B,MAAM,CAACjH,OAAO,CAAC;AACxB;AAEA,OAAO,SAAS0G,qBAAqBA,CACnC9G,OAAoB,EACpB+G,OAAiB,EACjB9G,UAAsB,EACtBf,KAAgB,EAChB;EACA,MAAM2H,KAAK,GAAG7G,OAAO,CAAC8H,aAAa,CAChCY,GAAG,CAAC,CAAC;IAAEC;EAAK,CAAC,KACZ5B,OAAO,CAAC3H,OAAO,CAAC,CAAC;IAAEyH;EAAM,CAAC,KACxBA,KAAK,CAACkB,MAAM,CAAC,CAAC;IAAE1I;EAAK,CAAC,KAAKA,IAAI,CAACsJ,IAAI,KAAKA,IAAI,CAC/C,CACF,CAAC,CACAC,IAAI,CAAC,CAAC;EAET,MAAMC,YAAY,GAAGC,oBAAoB,CAAC9I,OAAO,EAAEC,UAAU,EAAEf,KAAK,CAAC;EAErE,OAAO,CAAC,GAAG2H,KAAK,EAAE,GAAGgC,YAAY,CAAC;AACpC;;AAEA;AACA;AACA;AACA;AACA,SAASC,oBAAoBA,CAC3B9I,OAAoB,EACpBC,UAAsB,EACtBf,KAAgB,EACG;EACnB,MAAM2H,KAAwB,GAAG,EAAE;EAEnC,KAAK,MAAMxH,IAAI,IAAIH,KAAK,CAACC,KAAK,EAAE;IAC9B,KAAK,MAAMM,KAAK,IAAIJ,IAAI,CAACC,UAAU,CAACC,MAAM,EAAE;MAC1C,IAAIE,KAAK,YAAY3B,YAAY,EAAE;QACjC+I,KAAK,CAAC3E,IAAI,CAAC;UACTc,IAAI,EAAEvD,KAAK,CAACuD,IAAI;UAChB3D,IAAI;UACJ8C,KAAK,EAAE1C,KAAK,CAAC0C,KAAK;UAClB4G,KAAK,EAAEtJ,KAAK,CAACuJ,YAAY;UACzBvJ,KAAK;UACLa,KAAK,EAAEN,OAAO,CAACM,KAAK;UACpBqI,IAAI,EAAEtJ,IAAI,CAACsJ,IAAI;UACf7G,KAAK,EAAErC,KAAK,CAACwJ,yBAAyB,CAACjJ,OAAO,CAACM,KAAK,EAAEL,UAAU;QAClE,CAAC,CAAC;MACJ;IACF;EACF;EAEA,OAAO4G,KAAK;AACd","ignoreList":[]}
1
+ {"version":3,"file":"SummaryPageController.js","names":["hasComponentsEvenIfNoNext","Boom","StatusCodes","COMPONENT_STATE_ERROR","PAYMENT_EXPIRED_NOTIFICATION","ComponentCollection","PaymentField","checkEmailAddressForLiveFormSubmission","checkFormStatus","createError","getCacheService","SummaryViewModel","QuestionPageController","InvalidComponentStateError","PaymentErrorTypes","PaymentPreAuthError","PaymentSubmissionError","buildMainRecords","buildRepeaterRecords","DEFAULT_PAYMENT_HELP_URL","formatCurrency","formatPaymentDate","FormAction","SummaryPageController","allowSaveAndExit","findPaymentField","model","pages","flatMap","page","collection","fields","find","field","constructor","pageDef","viewName","components","getSummaryViewModel","request","context","translator","t","viewModel","payload","errors","state","paymentField","resolvedAmount","resolveAmount","options","paymentState","getPaymentStateFromState","amount","paymentDetails","buildPaymentDetails","paymentRequired","preAuth","status","paymentPreAuthorized","getViewModel","backLink","getBackLink","feedbackLink","phaseTag","shouldShowSaveAndExit","server","rows","key","text","value","description","reference","createdAt","push","language","title","summaryList","makeGetRouteHandler","h","getTranslator","query","paymentComplete","handleFormSubmit","reconcilePaymentState","hasMissingNotificationEmail","view","cacheService","resetComponentStates","name","makePostRouteHandler","action","SaveAndExit","handleSaveAndExit","params","formsService","services","getFormMetadata","formMetadata","slug","notificationEmail","isPreview","submitForm","error","handleSubmissionError","setConfirmationState","confirmed","formId","referenceNumber","clearState","proceed","getStatusPath","handleInvalidComponentStateError","handlePaymentPreAuthError","handlePaymentSubmissionError","govukError","component","userMessage","yar","flash","getStateKeys","path","shouldResetState","errorType","PaymentExpired","PaymentIncomplete","redirect","getHref","code","SEE_OTHER","redirectPath","undefined","helpUrl","helpLink","contactUsLink","helpLinkHtml","postRouteOptions","ext","onPreHandler","method","continue","summaryViewModel","emailAddress","finaliseComponents","paymentWasCaptured","hasPaymentBeenCaptured","formStatus","logTags","logger","info","items","getFormSubmissionData","details","submitResponse","submitData","id","badRequest","outputService","submit","err","contact","online","url","capture","metadata","allFields","Set","relevantPages","filter","onSubmit","retrievalKey","sessionId","formSubmissionService","main","repeaters","def","translations","cy","map","href","flat","paymentItems","getPaymentFieldItems","label","summaryLabel","getDisplayStringFromState"],"sources":["../../../../../src/server/plugins/engine/pageControllers/SummaryPageController.ts"],"sourcesContent":["import {\n hasComponentsEvenIfNoNext,\n type FormMetadata,\n type Page,\n type SubmitPayload\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type RouteOptions } from '@hapi/hapi'\nimport { StatusCodes } from 'http-status-codes'\n\nimport {\n COMPONENT_STATE_ERROR,\n PAYMENT_EXPIRED_NOTIFICATION\n} from '~/src/server/constants.js'\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n createError,\n getCacheService\n} from '~/src/server/plugins/engine/helpers.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport {\n SummaryViewModel,\n type FormModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport {\n type Detail,\n type DetailItem,\n type DetailItemField\n} from '~/src/server/plugins/engine/models/types.js'\nimport { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n InvalidComponentStateError,\n PaymentErrorTypes,\n PaymentPreAuthError,\n PaymentSubmissionError\n} from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport {\n buildMainRecords,\n buildRepeaterRecords\n} from '~/src/server/plugins/engine/pageControllers/helpers/submission.js'\nimport {\n type FormConfirmationState,\n type FormContext,\n type FormContextRequest\n} from '~/src/server/plugins/engine/types.js'\nimport {\n DEFAULT_PAYMENT_HELP_URL,\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\nimport {\n FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormResponseToolkit\n} from '~/src/server/routes/types.js'\n\nexport class SummaryPageController extends QuestionPageController {\n declare pageDef: Page\n allowSaveAndExit = true\n\n /**\n * The controller which is used when Page[\"controller\"] is defined as \"./pages/summary.js\"\n */\n\n /**\n * Finds the PaymentField component across all pages in the model.\n * Payment pages are skipped in the normal page walk\n */\n private findPaymentField(): PaymentField | undefined {\n return this.model.pages\n .flatMap((page) => page.collection.fields)\n .find((field): field is PaymentField => field instanceof PaymentField)\n }\n\n constructor(model: FormModel, pageDef: Page) {\n super(model, pageDef)\n this.viewName = 'summary'\n\n // Components collection\n this.collection = new ComponentCollection(\n hasComponentsEvenIfNoNext(pageDef) ? pageDef.components : [],\n { model, page: this }\n )\n }\n\n getSummaryViewModel(\n request: FormContextRequest,\n context: FormContext,\n translator: Translator\n ): SummaryViewModel {\n const { t } = translator\n\n const viewModel = new SummaryViewModel(request, this, context, translator)\n\n const { payload, errors, state } = context\n\n const paymentField = this.findPaymentField()\n\n if (paymentField) {\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n state\n )\n const paymentState = paymentField.getPaymentStateFromState(state)\n\n if (paymentState?.amount === resolvedAmount) {\n viewModel.paymentState = paymentState\n viewModel.paymentDetails = this.buildPaymentDetails(\n paymentField,\n paymentState,\n translator\n )\n }\n\n if (resolvedAmount > 0) {\n viewModel.paymentRequired = true\n }\n if (\n paymentState &&\n paymentState.preAuth?.status === 'success' &&\n paymentState.amount === resolvedAmount\n ) {\n viewModel.paymentPreAuthorized = true\n }\n }\n\n const components = this.collection.getViewModel({\n payload,\n errors,\n translator\n })\n\n viewModel.backLink = this.getBackLink(request, context, t)\n viewModel.feedbackLink = this.feedbackLink\n viewModel.phaseTag = this.phaseTag\n viewModel.components = components\n viewModel.allowSaveAndExit = this.shouldShowSaveAndExit(request.server)\n viewModel.errors = errors\n\n return viewModel\n }\n\n private buildPaymentDetails(\n paymentField: PaymentField,\n paymentState: NonNullable<\n ReturnType<PaymentField['getPaymentStateFromState']>\n >,\n translator: Translator\n ) {\n const { t } = translator\n const rows = [\n {\n key: { text: t('pages.summary.paymentFor') },\n value: { text: paymentState.description }\n },\n {\n key: { text: t('pages.summary.totalAmount') },\n value: { text: formatCurrency(paymentState.amount) }\n },\n {\n key: { text: t('pages.summary.reference') },\n value: { text: paymentState.reference }\n }\n ]\n\n if (paymentState.preAuth?.createdAt) {\n rows.push({\n key: { text: t('pages.summary.dateOfPayment') },\n value: {\n text: formatPaymentDate(\n paymentState.preAuth.createdAt,\n translator.language\n )\n }\n })\n }\n\n return {\n title: { text: t('pages.summary.paymentDetailsTitle') },\n summaryList: { rows }\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,\n */\n makeGetRouteHandler() {\n return async (\n request: FormRequest,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { viewName } = this\n\n const translator = this.getTranslator(request)\n const { t } = translator\n\n // After GOV.UK Pay callback, auto-submit the form instead of\n // showing CYA again. The payment is already pre-authorized.\n if (request.query.paymentComplete === 'true') {\n return this.handleFormSubmit(\n request as unknown as FormRequestPayload,\n context,\n h\n )\n }\n\n await this.reconcilePaymentState(request, context)\n\n const viewModel = this.getSummaryViewModel(request, context, translator)\n\n viewModel.hasMissingNotificationEmail =\n await this.hasMissingNotificationEmail(request, context)\n\n viewModel.t = t\n return h.view(viewName, viewModel)\n }\n }\n\n /**\n * Checks if the resolved payment amount has changed since pre-auth\n * and invalidates stale payment state if so.\n */\n private async reconcilePaymentState(\n request: FormRequest,\n context: FormContext\n ) {\n const paymentField = this.findPaymentField()\n\n if (!paymentField) {\n return\n }\n\n const resolvedAmount = PaymentField.resolveAmount(\n paymentField.options,\n this.model,\n context.state\n )\n const paymentState = paymentField.getPaymentStateFromState(context.state)\n\n if (paymentState && paymentState.amount !== resolvedAmount) {\n const cacheService = getCacheService(request.server)\n await cacheService.resetComponentStates(request, [paymentField.name])\n }\n }\n\n /**\n * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.\n * If a form is incomplete, a user will be redirected to the start page.\n */\n makePostRouteHandler() {\n return async (\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) => {\n const { action } = request.payload\n if (action === FormAction.SaveAndExit) {\n return this.handleSaveAndExit(request, context, h)\n }\n\n return this.handleFormSubmit(request, context, h)\n }\n }\n\n async handleFormSubmit(\n request: FormRequestPayload,\n context: FormContext,\n h: FormResponseToolkit\n ) {\n const { model } = this\n const { params } = request\n\n const cacheService = getCacheService(request.server)\n\n const { formsService } = this.model.services\n const { getFormMetadata } = formsService\n\n const formMetadata = await getFormMetadata(params.slug)\n const { notificationEmail } = formMetadata\n const { isPreview } = checkFormStatus(request.params)\n\n checkEmailAddressForLiveFormSubmission(notificationEmail, isPreview)\n\n if (notificationEmail) {\n const translator = this.getTranslator(request)\n const viewModel = this.getSummaryViewModel(request, context, translator)\n\n try {\n await submitForm(\n context,\n formMetadata,\n request,\n viewModel,\n model,\n notificationEmail,\n translator\n )\n } catch (error) {\n return this.handleSubmissionError(error, request, h)\n }\n }\n\n await cacheService.setConfirmationState(request, {\n confirmed: true,\n formId: context.state.formId,\n referenceNumber: context.referenceNumber\n } as FormConfirmationState)\n\n await cacheService.clearState(request)\n\n return this.proceed(request, h, this.getStatusPath())\n }\n\n /**\n * Handles errors during form submission\n */\n private async handleSubmissionError(\n error: unknown,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n if (error instanceof InvalidComponentStateError) {\n return this.handleInvalidComponentStateError(error, request, h)\n }\n\n if (error instanceof PaymentPreAuthError) {\n return this.handlePaymentPreAuthError(error, request, h)\n }\n\n if (error instanceof PaymentSubmissionError) {\n return this.handlePaymentSubmissionError(error, request, h)\n }\n\n throw error\n }\n\n /**\n * Handles InvalidComponentStateError during submission\n */\n private async handleInvalidComponentStateError(\n error: InvalidComponentStateError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n const govukError = createError(error.component.name, error.userMessage)\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n return this.proceed(request, h, error.component.page?.path)\n }\n\n /**\n * Handles PaymentPreAuthError during submission\n */\n private async handlePaymentPreAuthError(\n error: PaymentPreAuthError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const cacheService = getCacheService(request.server)\n\n if (error.shouldResetState) {\n await cacheService.resetComponentStates(request, error.getStateKeys())\n\n if (error.errorType === PaymentErrorTypes.PaymentExpired) {\n request.yar.flash(PAYMENT_EXPIRED_NOTIFICATION, true, true)\n return this.proceed(request, h, error.component.page?.path)\n }\n }\n\n // Payment page is skipped in the page walk, so proceed() would redirect\n // to an earlier page. For PaymentIncomplete, redirect directly to the\n // payment page using its href.\n if (\n error.errorType === PaymentErrorTypes.PaymentIncomplete &&\n error.component.page\n ) {\n return h\n .redirect(error.component.page.getHref(error.component.page.path))\n .code(StatusCodes.SEE_OTHER)\n }\n\n const govukError = createError(error.component.name, error.userMessage)\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n const redirectPath = error.shouldResetState\n ? error.component.page?.path\n : undefined\n\n return this.proceed(request, h, redirectPath)\n }\n\n /**\n * Handles PaymentSubmissionError during submission\n */\n private handlePaymentSubmissionError(\n error: PaymentSubmissionError,\n request: FormRequestPayload,\n h: FormResponseToolkit\n ) {\n const { t } = this.getTranslator(request)\n\n const helpUrl = error.helpLink ?? DEFAULT_PAYMENT_HELP_URL\n const contactUsLink = `<a href=\"${helpUrl}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"govuk-link\">${t('pages.summary.contactUsLinkText')}</a>`\n const helpLinkHtml = t('pages.summary.submissionFailedContactSuffix', {\n contactUsLink\n })\n\n const govukError = createError(\n 'submission',\n `${t('pages.summary.submissionFailed')}${helpLinkHtml}.`\n )\n\n request.yar.flash(COMPONENT_STATE_ERROR, govukError, true)\n\n return this.proceed(request, h)\n }\n\n get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {\n return {\n ext: {\n onPreHandler: {\n method(request, h) {\n return h.continue\n }\n }\n }\n }\n }\n}\n\nexport async function submitForm(\n context: FormContext,\n formMetadata: FormMetadata,\n request: FormRequestPayload,\n summaryViewModel: SummaryViewModel,\n model: FormModel,\n emailAddress: string,\n translator: Translator\n) {\n await finaliseComponents(request, formMetadata, context, model)\n\n const paymentWasCaptured = hasPaymentBeenCaptured(context, model)\n\n const formStatus = checkFormStatus(request.params)\n const logTags = ['submit', 'submissionApi']\n\n request.logger.info(logTags, 'Preparing email', formStatus)\n\n const items = getFormSubmissionData(\n summaryViewModel.context,\n summaryViewModel.details,\n translator,\n model\n )\n\n try {\n request.logger.info(logTags, 'Submitting data')\n const submitResponse = await submitData(\n model,\n items,\n emailAddress,\n request.yar.id,\n translator,\n summaryViewModel.context.referenceNumber\n )\n\n if (submitResponse === undefined) {\n throw Boom.badRequest('Unexpected empty response from submit api')\n }\n\n await model.services.outputService.submit(\n context,\n request,\n model,\n emailAddress,\n items,\n submitResponse,\n formMetadata\n )\n } catch (err) {\n if (paymentWasCaptured) {\n throw new PaymentSubmissionError(\n context.referenceNumber,\n formMetadata.contact?.online?.url\n )\n }\n throw err\n }\n}\n\n/**\n * Checks if any payment component has been captured\n */\nfunction hasPaymentBeenCaptured(\n context: FormContext,\n model: FormModel\n): boolean {\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n const paymentState = field.getPaymentStateFromState(context.state)\n if (paymentState?.capture?.status === 'success') {\n return true\n }\n }\n }\n }\n return false\n}\n\n/**\n * Finalises any components that need post-processing before form submission. Candidates usually involve\n * those that have external state.\n * Examples include:\n * - file uploads which are 'persisted' before submission\n * - payments which are 'captured' before submission\n */\nasync function finaliseComponents(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext,\n model: FormModel\n) {\n // Get fields from relevant pages (normal components)\n // plus PaymentField from all pages (payment page is skipped in the page walk)\n const allFields = new Set([\n ...context.relevantPages.flatMap((page) => page.collection.fields),\n ...model.pages\n .flatMap((page) => page.collection.fields)\n .filter((field) => field instanceof PaymentField)\n ])\n\n for (const component of allFields) {\n await component.onSubmit(request, metadata, context)\n }\n}\n\nfunction submitData(\n model: FormModel,\n items: DetailItem[],\n retrievalKey: string,\n sessionId: string,\n translator: Translator,\n referenceNumber: string\n) {\n const { formSubmissionService } = model.services\n const { submit } = formSubmissionService\n\n const payload: SubmitPayload = {\n sessionId,\n retrievalKey,\n referenceNumber,\n main: buildMainRecords(items, translator),\n repeaters: buildRepeaterRecords(items, translator),\n // Only populate the language property if the form is multi-language enabled\n // @ts-expect-error - dynamic language property\n language: model.def.metadata?.translations?.cy\n ? translator.language\n : undefined\n }\n return submit(payload)\n}\n\nexport function getFormSubmissionData(\n context: FormContext,\n details: Detail[],\n translator: Translator,\n model: FormModel\n) {\n const items = context.relevantPages\n .map(({ href }) =>\n details.flatMap(({ items }) =>\n items.filter(({ page }) => page.href === href)\n )\n )\n .flat()\n\n const paymentItems = getPaymentFieldItems(context, translator, model)\n\n return [...items, ...paymentItems]\n}\n\n/**\n * Gets DetailItems for PaymentField components\n * PaymentField is excluded from summaryDetails for UI but needs to be in submission data\n */\nfunction getPaymentFieldItems(\n context: FormContext,\n translator: Translator,\n model: FormModel\n): DetailItemField[] {\n const items: DetailItemField[] = []\n\n for (const page of model.pages) {\n for (const field of page.collection.fields) {\n if (field instanceof PaymentField) {\n items.push({\n name: field.name,\n page,\n title: field.title,\n label: field.summaryLabel,\n field,\n state: context.state,\n href: page.href,\n value: field.getDisplayStringFromState(context.state, translator)\n })\n }\n }\n }\n\n return items\n}\n"],"mappings":"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","ignoreList":[]}