@defra/forms-engine-plugin 0.0.3 → 0.0.4

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 (328) hide show
  1. package/.public/assets/fonts/bold-affa96571d-v2.woff +0 -0
  2. package/.public/assets/fonts/bold-b542beb274-v2.woff2 +0 -0
  3. package/.public/assets/fonts/light-94a07e06a1-v2.woff2 +0 -0
  4. package/.public/assets/fonts/light-f591b13f7d-v2.woff +0 -0
  5. package/.public/assets/images/favicon.ico +0 -0
  6. package/.public/assets/images/favicon.svg +1 -0
  7. package/.public/assets/images/govuk-crest.svg +1 -0
  8. package/.public/assets/images/govuk-icon-180.png +0 -0
  9. package/.public/assets/images/govuk-icon-192.png +0 -0
  10. package/.public/assets/images/govuk-icon-512.png +0 -0
  11. package/.public/assets/images/govuk-icon-mask.svg +1 -0
  12. package/.public/assets/images/govuk-opengraph-image.png +0 -0
  13. package/.public/assets/manifest.json +39 -0
  14. package/.public/assets-manifest.json +24 -0
  15. package/.public/javascripts/application.0fd8c18.min.js +3 -0
  16. package/.public/javascripts/application.0fd8c18.min.js.LICENSE.txt +58 -0
  17. package/.public/javascripts/application.0fd8c18.min.js.map +1 -0
  18. package/.public/javascripts/file-upload.b2f18f5.min.js +2 -0
  19. package/.public/javascripts/file-upload.b2f18f5.min.js.map +1 -0
  20. package/.public/javascripts/vendor/accessible-autocomplete.275d332.min.js +2 -0
  21. package/.public/javascripts/vendor/accessible-autocomplete.275d332.min.js.map +1 -0
  22. package/.public/stylesheets/application.e340021.min.css +14 -0
  23. package/.public/stylesheets/application.e340021.min.css.map +1 -0
  24. package/package.json +6 -2
  25. package/.browserslistrc +0 -16
  26. package/.editorconfig +0 -9
  27. package/.eslintrc.cjs +0 -266
  28. package/.github/dependabot.yml +0 -85
  29. package/.github/workflows/check-pull-request.yml +0 -209
  30. package/.github/workflows/pr-notifier.yml +0 -98
  31. package/.github/workflows/publish.yml +0 -111
  32. package/.husky/pre-commit +0 -1
  33. package/.lintstagedrc.js +0 -4
  34. package/.nvmrc +0 -1
  35. package/.prettierignore +0 -8
  36. package/.prettierrc.cjs +0 -26
  37. package/Dockerfile +0 -61
  38. package/Procfile +0 -1
  39. package/babel.config.cjs +0 -55
  40. package/compose/aws.env +0 -4
  41. package/compose/start-localstack.sh +0 -26
  42. package/docker-compose.yaml +0 -86
  43. package/globals.d.ts +0 -1
  44. package/jest.config.cjs +0 -54
  45. package/jest.environment.js +0 -4
  46. package/jest.setup.cjs +0 -14
  47. package/postcss.config.js +0 -26
  48. package/sonar-project.properties +0 -17
  49. package/src/client/javascripts/application.js +0 -87
  50. package/src/client/javascripts/file-upload.js +0 -386
  51. package/src/client/stylesheets/_code.scss +0 -33
  52. package/src/client/stylesheets/_govuk-frontend.scss +0 -4
  53. package/src/client/stylesheets/_prose.scss +0 -56
  54. package/src/client/stylesheets/_service-banner.scss +0 -24
  55. package/src/client/stylesheets/_summary-list.scss +0 -28
  56. package/src/client/stylesheets/_tag-env.scss +0 -24
  57. package/src/client/stylesheets/application.scss +0 -14
  58. package/src/common/cookies.js +0 -58
  59. package/src/common/cookies.test.js +0 -23
  60. package/src/common/types.js +0 -5
  61. package/src/config/index.ts +0 -271
  62. package/src/index.ts +0 -31
  63. package/src/server/common/helpers/logging/logger-options.test.ts +0 -50
  64. package/src/server/common/helpers/logging/logger-options.ts +0 -46
  65. package/src/server/common/helpers/logging/logger.ts +0 -7
  66. package/src/server/common/helpers/logging/request-logger.ts +0 -9
  67. package/src/server/common/helpers/logging/request-tracing.js +0 -10
  68. package/src/server/common/helpers/redis-client.js +0 -70
  69. package/src/server/constants.js +0 -1
  70. package/src/server/forms/README.md +0 -10
  71. package/src/server/forms/components.json +0 -1015
  72. package/src/server/forms/report-a-terrorist.json +0 -270
  73. package/src/server/forms/runner-components-test.json +0 -365
  74. package/src/server/forms/test.json +0 -581
  75. package/src/server/index.test.ts +0 -582
  76. package/src/server/index.ts +0 -140
  77. package/src/server/plugins/blankie.test.ts +0 -73
  78. package/src/server/plugins/blankie.ts +0 -48
  79. package/src/server/plugins/crumb.ts +0 -20
  80. package/src/server/plugins/engine/README.md +0 -87
  81. package/src/server/plugins/engine/components/AutocompleteField.test.ts +0 -294
  82. package/src/server/plugins/engine/components/AutocompleteField.ts +0 -49
  83. package/src/server/plugins/engine/components/CheckboxesField.test.ts +0 -379
  84. package/src/server/plugins/engine/components/CheckboxesField.ts +0 -106
  85. package/src/server/plugins/engine/components/ComponentBase.ts +0 -97
  86. package/src/server/plugins/engine/components/ComponentCollection.ts +0 -278
  87. package/src/server/plugins/engine/components/DatePartsField.test.ts +0 -822
  88. package/src/server/plugins/engine/components/DatePartsField.ts +0 -264
  89. package/src/server/plugins/engine/components/Details.test.ts +0 -49
  90. package/src/server/plugins/engine/components/Details.ts +0 -30
  91. package/src/server/plugins/engine/components/EmailAddressField.test.ts +0 -395
  92. package/src/server/plugins/engine/components/EmailAddressField.ts +0 -55
  93. package/src/server/plugins/engine/components/FileUploadField.test.ts +0 -778
  94. package/src/server/plugins/engine/components/FileUploadField.ts +0 -262
  95. package/src/server/plugins/engine/components/FormComponent.ts +0 -249
  96. package/src/server/plugins/engine/components/Html.test.ts +0 -48
  97. package/src/server/plugins/engine/components/Html.ts +0 -29
  98. package/src/server/plugins/engine/components/InsetText.test.ts +0 -48
  99. package/src/server/plugins/engine/components/InsetText.ts +0 -27
  100. package/src/server/plugins/engine/components/List.test.ts +0 -76
  101. package/src/server/plugins/engine/components/List.ts +0 -72
  102. package/src/server/plugins/engine/components/ListFormComponent.ts +0 -140
  103. package/src/server/plugins/engine/components/MonthYearField.test.ts +0 -567
  104. package/src/server/plugins/engine/components/MonthYearField.ts +0 -222
  105. package/src/server/plugins/engine/components/MultilineTextField.test.ts +0 -558
  106. package/src/server/plugins/engine/components/MultilineTextField.ts +0 -138
  107. package/src/server/plugins/engine/components/NumberField.test.ts +0 -701
  108. package/src/server/plugins/engine/components/NumberField.ts +0 -163
  109. package/src/server/plugins/engine/components/RadiosField.test.ts +0 -288
  110. package/src/server/plugins/engine/components/RadiosField.ts +0 -24
  111. package/src/server/plugins/engine/components/SelectField.test.ts +0 -288
  112. package/src/server/plugins/engine/components/SelectField.ts +0 -47
  113. package/src/server/plugins/engine/components/SelectionControlField.ts +0 -43
  114. package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +0 -356
  115. package/src/server/plugins/engine/components/TelephoneNumberField.ts +0 -67
  116. package/src/server/plugins/engine/components/TextField.test.ts +0 -489
  117. package/src/server/plugins/engine/components/TextField.ts +0 -96
  118. package/src/server/plugins/engine/components/UkAddressField.test.ts +0 -623
  119. package/src/server/plugins/engine/components/UkAddressField.ts +0 -172
  120. package/src/server/plugins/engine/components/YesNoField.test.ts +0 -248
  121. package/src/server/plugins/engine/components/YesNoField.ts +0 -31
  122. package/src/server/plugins/engine/components/constants.ts +0 -1
  123. package/src/server/plugins/engine/components/helpers.ts +0 -330
  124. package/src/server/plugins/engine/components/index.ts +0 -24
  125. package/src/server/plugins/engine/components/types.ts +0 -117
  126. package/src/server/plugins/engine/configureEnginePlugin.ts +0 -47
  127. package/src/server/plugins/engine/helpers.test.ts +0 -791
  128. package/src/server/plugins/engine/helpers.ts +0 -379
  129. package/src/server/plugins/engine/index.ts +0 -7
  130. package/src/server/plugins/engine/models/FormModel.test.ts +0 -42
  131. package/src/server/plugins/engine/models/FormModel.ts +0 -443
  132. package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
  133. package/src/server/plugins/engine/models/Section.ts +0 -0
  134. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +0 -209
  135. package/src/server/plugins/engine/models/SummaryViewModel.ts +0 -220
  136. package/src/server/plugins/engine/models/index.ts +0 -2
  137. package/src/server/plugins/engine/models/types.ts +0 -114
  138. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +0 -143
  139. package/src/server/plugins/engine/outputFormatters/human/v1.ts +0 -73
  140. package/src/server/plugins/engine/outputFormatters/index.test.ts +0 -17
  141. package/src/server/plugins/engine/outputFormatters/index.ts +0 -44
  142. package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +0 -229
  143. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +0 -140
  144. package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +0 -229
  145. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +0 -153
  146. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +0 -1108
  147. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +0 -446
  148. package/src/server/plugins/engine/pageControllers/PageController.test.ts +0 -205
  149. package/src/server/plugins/engine/pageControllers/PageController.ts +0 -176
  150. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +0 -1264
  151. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +0 -561
  152. package/src/server/plugins/engine/pageControllers/README.md +0 -28
  153. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +0 -264
  154. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +0 -458
  155. package/src/server/plugins/engine/pageControllers/StartPageController.ts +0 -18
  156. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +0 -50
  157. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +0 -261
  158. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +0 -28
  159. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +0 -19
  160. package/src/server/plugins/engine/pageControllers/helpers.test.ts +0 -198
  161. package/src/server/plugins/engine/pageControllers/helpers.ts +0 -101
  162. package/src/server/plugins/engine/pageControllers/index.ts +0 -10
  163. package/src/server/plugins/engine/pageControllers/validationOptions.ts +0 -89
  164. package/src/server/plugins/engine/plugin.ts +0 -673
  165. package/src/server/plugins/engine/services/formSubmissionService.js +0 -46
  166. package/src/server/plugins/engine/services/formsService.js +0 -46
  167. package/src/server/plugins/engine/services/formsService.test.js +0 -90
  168. package/src/server/plugins/engine/services/index.js +0 -3
  169. package/src/server/plugins/engine/services/notifyService.test.ts +0 -132
  170. package/src/server/plugins/engine/services/notifyService.ts +0 -64
  171. package/src/server/plugins/engine/services/uploadService.js +0 -60
  172. package/src/server/plugins/engine/types.ts +0 -315
  173. package/src/server/plugins/engine/views/components/autocompletefield.html +0 -5
  174. package/src/server/plugins/engine/views/components/checkboxesfield.html +0 -5
  175. package/src/server/plugins/engine/views/components/datepartsfield.html +0 -5
  176. package/src/server/plugins/engine/views/components/details.html +0 -6
  177. package/src/server/plugins/engine/views/components/emailaddressfield.html +0 -5
  178. package/src/server/plugins/engine/views/components/fileuploadfield-key.html +0 -8
  179. package/src/server/plugins/engine/views/components/fileuploadfield-value.html +0 -3
  180. package/src/server/plugins/engine/views/components/fileuploadfield.html +0 -24
  181. package/src/server/plugins/engine/views/components/html.html +0 -3
  182. package/src/server/plugins/engine/views/components/insettext.html +0 -7
  183. package/src/server/plugins/engine/views/components/list.html +0 -36
  184. package/src/server/plugins/engine/views/components/monthyearfield.html +0 -5
  185. package/src/server/plugins/engine/views/components/multilinetextfield.html +0 -10
  186. package/src/server/plugins/engine/views/components/numberfield.html +0 -5
  187. package/src/server/plugins/engine/views/components/radiosfield.html +0 -5
  188. package/src/server/plugins/engine/views/components/selectfield.html +0 -5
  189. package/src/server/plugins/engine/views/components/telephonenumberfield.html +0 -5
  190. package/src/server/plugins/engine/views/components/textfield.html +0 -5
  191. package/src/server/plugins/engine/views/components/ukaddressfield.html +0 -25
  192. package/src/server/plugins/engine/views/components/yesnofield.html +0 -5
  193. package/src/server/plugins/engine/views/file-upload.html +0 -45
  194. package/src/server/plugins/engine/views/index.html +0 -39
  195. package/src/server/plugins/engine/views/item-delete.html +0 -56
  196. package/src/server/plugins/engine/views/partials/components.html +0 -6
  197. package/src/server/plugins/engine/views/partials/conditional-components.html +0 -3
  198. package/src/server/plugins/engine/views/partials/debug.html +0 -44
  199. package/src/server/plugins/engine/views/partials/form.html +0 -15
  200. package/src/server/plugins/engine/views/partials/heading.html +0 -16
  201. package/src/server/plugins/engine/views/partials/preview-banner.html +0 -32
  202. package/src/server/plugins/engine/views/partials/preview-banner.test.js +0 -122
  203. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +0 -10
  204. package/src/server/plugins/engine/views/repeat-list-summary.html +0 -53
  205. package/src/server/plugins/errorPages.ts +0 -58
  206. package/src/server/plugins/nunjucks/context.js +0 -88
  207. package/src/server/plugins/nunjucks/context.test.js +0 -142
  208. package/src/server/plugins/nunjucks/enviroment.test.js +0 -201
  209. package/src/server/plugins/nunjucks/environment.js +0 -116
  210. package/src/server/plugins/nunjucks/filters/answer.js +0 -27
  211. package/src/server/plugins/nunjucks/filters/answer.test.js +0 -89
  212. package/src/server/plugins/nunjucks/filters/evaluate.js +0 -21
  213. package/src/server/plugins/nunjucks/filters/field.js +0 -28
  214. package/src/server/plugins/nunjucks/filters/field.test.js +0 -75
  215. package/src/server/plugins/nunjucks/filters/highlight.js +0 -11
  216. package/src/server/plugins/nunjucks/filters/href.js +0 -30
  217. package/src/server/plugins/nunjucks/filters/href.test.js +0 -80
  218. package/src/server/plugins/nunjucks/filters/index.js +0 -8
  219. package/src/server/plugins/nunjucks/filters/inspect.js +0 -15
  220. package/src/server/plugins/nunjucks/filters/page.js +0 -24
  221. package/src/server/plugins/nunjucks/filters/page.test.js +0 -65
  222. package/src/server/plugins/nunjucks/index.js +0 -3
  223. package/src/server/plugins/nunjucks/plugin.js +0 -40
  224. package/src/server/plugins/nunjucks/render.js +0 -42
  225. package/src/server/plugins/nunjucks/types.js +0 -40
  226. package/src/server/plugins/pulse.ts +0 -11
  227. package/src/server/plugins/router.ts +0 -201
  228. package/src/server/plugins/session.ts +0 -28
  229. package/src/server/routes/health.js +0 -13
  230. package/src/server/routes/health.test.js +0 -35
  231. package/src/server/routes/index.test.ts +0 -125
  232. package/src/server/routes/index.ts +0 -2
  233. package/src/server/routes/public.ts +0 -47
  234. package/src/server/routes/types.ts +0 -48
  235. package/src/server/schemas/index.ts +0 -34
  236. package/src/server/secure-context.js +0 -43
  237. package/src/server/services/cacheService.test.ts +0 -276
  238. package/src/server/services/cacheService.ts +0 -131
  239. package/src/server/services/httpService.test.js +0 -491
  240. package/src/server/services/httpService.ts +0 -50
  241. package/src/server/services/index.ts +0 -1
  242. package/src/server/types.ts +0 -54
  243. package/src/server/utils/notify.test.ts +0 -37
  244. package/src/server/utils/notify.ts +0 -50
  245. package/src/server/utils/secure-context/get-trust-store-certs.js +0 -11
  246. package/src/server/utils/secure-context/get-trust-store-certs.test.js +0 -19
  247. package/src/server/utils/utils.js +0 -24
  248. package/src/server/utils/utils.test.js +0 -54
  249. package/src/server/views/404.html +0 -16
  250. package/src/server/views/500.html +0 -19
  251. package/src/server/views/components/debug/macro.njk +0 -3
  252. package/src/server/views/components/debug/template.njk +0 -13
  253. package/src/server/views/components/service-banner/macro.njk +0 -3
  254. package/src/server/views/components/service-banner/template.njk +0 -20
  255. package/src/server/views/components/service-banner/template.test.js +0 -43
  256. package/src/server/views/components/tag-env/macro.njk +0 -3
  257. package/src/server/views/components/tag-env/template.njk +0 -30
  258. package/src/server/views/components/tag-env/template.test.js +0 -66
  259. package/src/server/views/confirmation.html +0 -19
  260. package/src/server/views/help/accessibility-statement.html +0 -58
  261. package/src/server/views/help/cookie-preferences.html +0 -57
  262. package/src/server/views/help/cookies.html +0 -71
  263. package/src/server/views/help/get-support.html +0 -37
  264. package/src/server/views/help/privacy-notice.html +0 -68
  265. package/src/server/views/help/terms-and-conditions.html +0 -83
  266. package/src/server/views/layout.html +0 -199
  267. package/src/server/views/summary.html +0 -50
  268. package/src/typings/hapi/index.d.ts +0 -95
  269. package/src/typings/hapi-tracing/index.d.ts +0 -6
  270. package/src/typings/index.d.ts +0 -3
  271. package/src/typings/joi/index.d.ts +0 -22
  272. package/stylelint.config.js +0 -10
  273. package/test/client/javascripts/file-upload.test.js +0 -1197
  274. package/test/condition/checkboxes.test.js +0 -112
  275. package/test/condition/radios.test.js +0 -112
  276. package/test/condition/text.test.js +0 -103
  277. package/test/fixtures/assets-manifest.json +0 -4
  278. package/test/fixtures/form.js +0 -86
  279. package/test/fixtures/index.js +0 -2
  280. package/test/fixtures/list.js +0 -92
  281. package/test/form/cookies.test.js +0 -338
  282. package/test/form/csrf.test.js +0 -87
  283. package/test/form/definitions/basic.js +0 -101
  284. package/test/form/definitions/blank.js +0 -10
  285. package/test/form/definitions/checkboxes.json +0 -88
  286. package/test/form/definitions/components.json +0 -452
  287. package/test/form/definitions/conditional-reveal.js +0 -140
  288. package/test/form/definitions/conditions-basic.js +0 -187
  289. package/test/form/definitions/conditions-complex.js +0 -338
  290. package/test/form/definitions/conditions-dates.js +0 -78
  291. package/test/form/definitions/conditions-escaping.js +0 -143
  292. package/test/form/definitions/demo-cph-number.js +0 -3099
  293. package/test/form/definitions/feedback.json +0 -45
  294. package/test/form/definitions/fields-optional.js +0 -402
  295. package/test/form/definitions/fields-required.js +0 -402
  296. package/test/form/definitions/file-upload-basic.js +0 -44
  297. package/test/form/definitions/file-upload.js +0 -66
  298. package/test/form/definitions/minimal.js +0 -39
  299. package/test/form/definitions/phase-alpha.json +0 -33
  300. package/test/form/definitions/phase-default.json +0 -26
  301. package/test/form/definitions/radios.json +0 -88
  302. package/test/form/definitions/repeat-mixed.js +0 -54
  303. package/test/form/definitions/repeat.js +0 -70
  304. package/test/form/definitions/status.json +0 -126
  305. package/test/form/definitions/templates.js +0 -183
  306. package/test/form/definitions/test.json +0 -581
  307. package/test/form/definitions/text.json +0 -75
  308. package/test/form/definitions/titles.json +0 -170
  309. package/test/form/definitions.test.js +0 -47
  310. package/test/form/exit-page.test.js +0 -210
  311. package/test/form/feedback.test.js +0 -68
  312. package/test/form/fields-optional.test.js +0 -237
  313. package/test/form/fields-required.test.js +0 -294
  314. package/test/form/file-upload.test.js +0 -313
  315. package/test/form/govuk-notify.test.js +0 -449
  316. package/test/form/journey-basic.test.js +0 -444
  317. package/test/form/persist-files.test.js +0 -227
  318. package/test/form/phase-banner.test.js +0 -71
  319. package/test/form/repeat.test.js +0 -628
  320. package/test/form/summary-submission-email.test.js +0 -95
  321. package/test/form/template.test.js +0 -288
  322. package/test/form/titles.test.js +0 -204
  323. package/test/helpers/component-helpers.js +0 -74
  324. package/test/utils/get-cookie.js +0 -42
  325. package/test/utils/get-form-definitions.js +0 -18
  326. package/tmp.pdf +0 -1
  327. package/tsconfig.json +0 -28
  328. package/webpack.config.js +0 -208
@@ -1,18 +0,0 @@
1
- import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
2
- import { type FormContext } from '~/src/server/plugins/engine/types.js'
3
- import { type FormRequest } from '~/src/server/routes/types.js'
4
-
5
- export class StartPageController extends QuestionPageController {
6
- /**
7
- * The controller which is used when Page["controller"] is defined as "./pages/start.js"
8
- * This page should not be used in production. This page is helpful for prototyping start pages within the app,
9
- * but start pages should really live on gov.uk (whitehall publisher) so a user can be properly signposted.
10
- */
11
-
12
- getViewModel(request: FormRequest, context: FormContext) {
13
- return {
14
- ...super.getViewModel(request, context),
15
- isStartPage: true
16
- }
17
- }
18
- }
@@ -1,50 +0,0 @@
1
- import { type PageStatus } from '@defra/forms-model'
2
- import { type ResponseToolkit } from '@hapi/hapi'
3
-
4
- import { type FormModel } from '~/src/server/plugins/engine/models/index.js'
5
- import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
6
- import { type FormContext } from '~/src/server/plugins/engine/types.js'
7
- import { type FormRequest } from '~/src/server/routes/types.js'
8
-
9
- export class StatusPageController extends QuestionPageController {
10
- declare pageDef: PageStatus
11
-
12
- constructor(model: FormModel, pageDef: PageStatus) {
13
- super(model, pageDef)
14
- this.viewName = 'confirmation'
15
- }
16
-
17
- getRelevantPath() {
18
- return this.getStatusPath()
19
- }
20
-
21
- makeGetRouteHandler() {
22
- return async (
23
- request: FormRequest,
24
- context: FormContext,
25
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
26
- ) => {
27
- const { viewModel, viewName } = this
28
-
29
- const { cacheService } = request.services([])
30
- const confirmationState = await cacheService.getConfirmationState(request)
31
-
32
- // If there's no confirmation state, then
33
- // redirect the user back to the start of the form
34
- if (!confirmationState.confirmed) {
35
- return this.proceed(request, h, this.getStartPath())
36
- }
37
-
38
- const slug = request.params.slug
39
- const { formsService } = this.model.services
40
- const { getFormMetadata } = formsService
41
-
42
- const { submissionGuidance } = await getFormMetadata(slug)
43
-
44
- return h.view(viewName, {
45
- ...viewModel,
46
- submissionGuidance
47
- })
48
- }
49
- }
50
- }
@@ -1,261 +0,0 @@
1
- import { type PageSummary, type SubmitPayload } from '@defra/forms-model'
2
- import Boom from '@hapi/boom'
3
- import { type ResponseToolkit, type RouteOptions } from '@hapi/hapi'
4
-
5
- import { FileUploadField } from '~/src/server/plugins/engine/components/FileUploadField.js'
6
- import { getAnswer } from '~/src/server/plugins/engine/components/helpers.js'
7
- import {
8
- checkEmailAddressForLiveFormSubmission,
9
- checkFormStatus
10
- } from '~/src/server/plugins/engine/helpers.js'
11
- import {
12
- SummaryViewModel,
13
- type FormModel
14
- } from '~/src/server/plugins/engine/models/index.js'
15
- import {
16
- type Detail,
17
- type DetailItem
18
- } from '~/src/server/plugins/engine/models/types.js'
19
- import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
20
- import {
21
- type FormContext,
22
- type FormContextRequest,
23
- type FormSubmissionState
24
- } from '~/src/server/plugins/engine/types.js'
25
- import {
26
- type FormRequest,
27
- type FormRequestPayload,
28
- type FormRequestPayloadRefs
29
- } from '~/src/server/routes/types.js'
30
-
31
- export class SummaryPageController extends QuestionPageController {
32
- declare pageDef: PageSummary
33
-
34
- /**
35
- * The controller which is used when Page["controller"] is defined as "./pages/summary.js"
36
- */
37
-
38
- constructor(model: FormModel, pageDef: PageSummary) {
39
- super(model, pageDef)
40
- this.viewName = 'summary'
41
- }
42
-
43
- getSummaryViewModel(
44
- request: FormContextRequest,
45
- context: FormContext
46
- ): SummaryViewModel {
47
- const viewModel = new SummaryViewModel(request, this, context)
48
-
49
- // We already figure these out in the base page controller. Take them and apply them to our page-specific model.
50
- // This is a stop-gap until we can add proper inheritance in place.
51
- viewModel.backLink = this.getBackLink(request, context)
52
- viewModel.feedbackLink = this.feedbackLink
53
- viewModel.phaseTag = this.phaseTag
54
-
55
- return viewModel
56
- }
57
-
58
- /**
59
- * Returns an async function. This is called in plugin.ts when there is a GET request at `/{id}/{path*}`,
60
- */
61
- makeGetRouteHandler() {
62
- return async (
63
- request: FormRequest,
64
- context: FormContext,
65
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
66
- ) => {
67
- const { viewName } = this
68
-
69
- const viewModel = this.getSummaryViewModel(request, context)
70
-
71
- viewModel.hasMissingNotificationEmail =
72
- await this.hasMissingNotificationEmail(request, context)
73
-
74
- return h.view(viewName, viewModel)
75
- }
76
- }
77
-
78
- /**
79
- * Returns an async function. This is called in plugin.ts when there is a POST request at `/{id}/{path*}`.
80
- * If a form is incomplete, a user will be redirected to the start page.
81
- */
82
- makePostRouteHandler() {
83
- return async (
84
- request: FormRequestPayload,
85
- context: FormContext,
86
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
87
- ) => {
88
- const { model } = this
89
- const { params } = request
90
- const { state } = context
91
-
92
- const { cacheService } = request.services([])
93
- const { formsService } = this.model.services
94
- const { getFormMetadata } = formsService
95
-
96
- // Get the form metadata using the `slug` param
97
- const { notificationEmail } = await getFormMetadata(params.slug)
98
- const { isPreview } = checkFormStatus(request.path)
99
- const emailAddress = notificationEmail ?? this.model.def.outputEmail
100
-
101
- checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)
102
-
103
- // Send submission email
104
- if (emailAddress) {
105
- const viewModel = this.getSummaryViewModel(request, context)
106
- await submitForm(request, viewModel, model, state, emailAddress)
107
- }
108
-
109
- await cacheService.setConfirmationState(request, { confirmed: true })
110
-
111
- // Clear all form data
112
- await cacheService.clearState(request)
113
-
114
- return this.proceed(request, h, this.getStatusPath())
115
- }
116
- }
117
-
118
- get postRouteOptions(): RouteOptions<FormRequestPayloadRefs> {
119
- return {
120
- ext: {
121
- onPreHandler: {
122
- method(request, h) {
123
- return h.continue
124
- }
125
- }
126
- }
127
- }
128
- }
129
- }
130
-
131
- async function submitForm(
132
- request: FormRequestPayload,
133
- summaryViewModel: SummaryViewModel,
134
- model: FormModel,
135
- state: FormSubmissionState,
136
- emailAddress: string
137
- ) {
138
- await extendFileRetention(model, state, emailAddress)
139
-
140
- const { path } = request
141
- const formStatus = checkFormStatus(path)
142
- const logTags = ['submit', 'submissionApi']
143
-
144
- request.logger.info(logTags, 'Preparing email', formStatus)
145
-
146
- // Get detail items
147
- const items = getFormSubmissionData(
148
- summaryViewModel.context,
149
- summaryViewModel.details
150
- )
151
-
152
- // Submit data
153
- request.logger.info(logTags, 'Submitting data')
154
- const submitResponse = await submitData(
155
- model,
156
- items,
157
- emailAddress,
158
- request.yar.id
159
- )
160
-
161
- if (submitResponse === undefined) {
162
- throw Boom.badRequest('Unexpected empty response from submit api')
163
- }
164
-
165
- return model.services.outputService.submit(
166
- request,
167
- model,
168
- emailAddress,
169
- items,
170
- submitResponse
171
- )
172
- }
173
-
174
- async function extendFileRetention(
175
- model: FormModel,
176
- state: FormSubmissionState,
177
- updatedRetrievalKey: string
178
- ) {
179
- const { formSubmissionService } = model.services
180
- const { persistFiles } = formSubmissionService
181
- const files: { fileId: string; initiatedRetrievalKey: string }[] = []
182
-
183
- // For each file upload component with files in
184
- // state, add the files to the batch getting persisted
185
- model.pages.forEach((page) => {
186
- const fileUploadComponents = page.collection.fields.filter(
187
- (component) => component instanceof FileUploadField
188
- )
189
-
190
- fileUploadComponents.forEach((component) => {
191
- const values = component.getFormValueFromState(state)
192
- if (!values?.length) {
193
- return
194
- }
195
-
196
- files.push(
197
- ...values.map(({ status }) => ({
198
- fileId: status.form.file.fileId,
199
- initiatedRetrievalKey: status.metadata.retrievalKey
200
- }))
201
- )
202
- })
203
- })
204
-
205
- if (files.length) {
206
- return persistFiles(files, updatedRetrievalKey)
207
- }
208
- }
209
-
210
- function submitData(
211
- model: FormModel,
212
- items: DetailItem[],
213
- retrievalKey: string,
214
- sessionId: string
215
- ) {
216
- const { formSubmissionService } = model.services
217
- const { submit } = formSubmissionService
218
-
219
- const payload: SubmitPayload = {
220
- sessionId,
221
- retrievalKey,
222
-
223
- // Main form answers
224
- main: items
225
- .filter((item) => 'field' in item)
226
- .map((item) => ({
227
- name: item.name,
228
- title: item.label,
229
- value: getAnswer(item.field, item.state, { format: 'data' })
230
- })),
231
-
232
- // Repeater form answers
233
- repeaters: items
234
- .filter((item) => 'subItems' in item)
235
- .map((item) => ({
236
- name: item.name,
237
- title: item.label,
238
-
239
- // Repeater item values
240
- value: item.subItems.map((detailItems) =>
241
- detailItems.map((subItem) => ({
242
- name: subItem.name,
243
- title: subItem.label,
244
- value: getAnswer(subItem.field, subItem.state, { format: 'data' })
245
- }))
246
- )
247
- }))
248
- }
249
-
250
- return submit(payload)
251
- }
252
-
253
- export function getFormSubmissionData(context: FormContext, details: Detail[]) {
254
- return context.relevantPages
255
- .map(({ href }) =>
256
- details.flatMap(({ items }) =>
257
- items.filter(({ page }) => page.href === href)
258
- )
259
- )
260
- .flat()
261
- }
@@ -1,28 +0,0 @@
1
- import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
2
- import { TerminalPageController } from '~/src/server/plugins/engine/pageControllers/TerminalPageController.js'
3
- import definition from '~/test/form/definitions/basic.js'
4
-
5
- describe('TerminalController', () => {
6
- let model: FormModel
7
- let controller1: TerminalPageController
8
-
9
- beforeEach(() => {
10
- const { pages } = definition
11
-
12
- const page1 = pages[0]
13
-
14
- model = new FormModel(definition, {
15
- basePath: 'test'
16
- })
17
-
18
- controller1 = new TerminalPageController(model, page1)
19
- })
20
-
21
- describe('Route handlers', () => {
22
- it('does not support POST route handler', () => {
23
- expect(() => controller1.makePostRouteHandler()).toThrow(
24
- 'POST method not allowed for terminal pages'
25
- )
26
- })
27
- })
28
- })
@@ -1,19 +0,0 @@
1
- import { type PageTerminal } from '@defra/forms-model'
2
- import Boom from '@hapi/boom'
3
- import { type ResponseObject, type ResponseToolkit } from '@hapi/hapi'
4
-
5
- import { QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
6
- import { type FormContext } from '~/src/server/plugins/engine/types.js'
7
- import { type FormRequestPayload } from '~/src/server/routes/types.js'
8
-
9
- export class TerminalPageController extends QuestionPageController {
10
- declare pageDef: PageTerminal
11
-
12
- makePostRouteHandler(): (
13
- request: FormRequestPayload,
14
- context: FormContext,
15
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
16
- ) => Promise<ResponseObject> {
17
- throw Boom.methodNotAllowed('POST method not allowed for terminal pages')
18
- }
19
- }
@@ -1,198 +0,0 @@
1
- import {
2
- ComponentType,
3
- ControllerType,
4
- ControllerTypes,
5
- PageTypes,
6
- type Page
7
- } from '@defra/forms-model'
8
-
9
- import { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
10
- import { PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'
11
- import {
12
- createPage,
13
- getProxyUrlForLocalDevelopment,
14
- isPageController,
15
- type PageControllerType
16
- } from '~/src/server/plugins/engine/pageControllers/helpers.js'
17
- import {
18
- FileUploadPageController,
19
- QuestionPageController,
20
- RepeatPageController,
21
- StartPageController,
22
- StatusPageController,
23
- SummaryPageController,
24
- TerminalPageController
25
- } from '~/src/server/plugins/engine/pageControllers/index.js'
26
- import definition from '~/test/form/definitions/blank.js'
27
-
28
- describe('Page controller helpers', () => {
29
- const examples = PageTypes.map((pageType) => {
30
- const pageDef = structuredClone(pageType)
31
-
32
- let controller: PageControllerType | undefined
33
-
34
- switch (pageDef.controller) {
35
- case ControllerType.Start:
36
- controller = StartPageController
37
- break
38
-
39
- case ControllerType.Page:
40
- controller = QuestionPageController
41
- break
42
-
43
- case ControllerType.Terminal:
44
- controller = TerminalPageController
45
- break
46
-
47
- case ControllerType.Repeat:
48
- controller = RepeatPageController
49
- break
50
-
51
- case ControllerType.FileUpload:
52
- controller = FileUploadPageController
53
-
54
- // Avoid minimum component requirements
55
- pageDef.components = [
56
- {
57
- type: ComponentType.FileUploadField,
58
- name: 'fileUpload',
59
- title: 'Upload something',
60
- options: {},
61
- schema: {}
62
- }
63
- ]
64
- break
65
-
66
- case ControllerType.Summary:
67
- controller = SummaryPageController
68
- break
69
-
70
- case ControllerType.Status:
71
- controller = StatusPageController
72
- break
73
- }
74
-
75
- return {
76
- controller,
77
- pageDef
78
- }
79
- })
80
-
81
- describe('Helper: createPage', () => {
82
- const model = new FormModel(definition, {
83
- basePath: 'test'
84
- })
85
-
86
- it.each([...examples])(
87
- "creates page for controller '$pageDef.controller'",
88
- ({ controller, pageDef }) => {
89
- const pageDef1 = structuredClone(pageDef)
90
- const pageDef2 = structuredClone(pageDef)
91
-
92
- expect(createPage(model, pageDef1)).toBeInstanceOf(controller)
93
-
94
- const controllerType = ControllerTypes.find(
95
- ({ name }) => name === pageDef1.controller
96
- )
97
-
98
- // @ts-expect-error - Allow invalid property for test
99
- pageDef2.controller = controllerType?.path
100
-
101
- // Check for legacy path support
102
- expect(createPage(model, pageDef2)).toBeInstanceOf(controller)
103
- }
104
- )
105
-
106
- describe('Helper: createPage (custom controllers)', () => {
107
- it('uses custom controllers from model.controllers', () => {
108
- class CustomPageController extends PageController {
109
- customProperty: string
110
-
111
- constructor(model: FormModel, pageDef: Page) {
112
- super(model, pageDef)
113
- this.customProperty = 'some-value'
114
- }
115
- }
116
-
117
- const customPageDef = {
118
- path: '/custom-page',
119
- title: 'Custom Page',
120
- controller: 'CustomController',
121
- components: []
122
- }
123
-
124
- const testModel = new FormModel(definition, {
125
- basePath: 'test'
126
- })
127
-
128
- type ControllerMap = Record<string, typeof PageController>
129
- testModel.controllers = {
130
- CustomController: CustomPageController
131
- } as ControllerMap
132
-
133
- const controller = createPage(testModel, customPageDef as Page)
134
-
135
- expect(controller).toBeInstanceOf(CustomPageController)
136
- expect(controller).toHaveProperty('customProperty', 'some-value')
137
- })
138
- })
139
-
140
- it('throws if page controller is unknown', () => {
141
- const pageDef: Page = {
142
- title: 'Unknown page',
143
- path: '/unknown-page',
144
- // @ts-expect-error - Allow invalid property for test
145
- controller: 'UnknownPageController'
146
- }
147
-
148
- expect(() => createPage(model, pageDef)).toThrow(
149
- `Page controller ${pageDef.controller} does not exist`
150
- )
151
- })
152
- })
153
-
154
- describe('Helper: isPageController', () => {
155
- it.each([...examples])(
156
- "allows valid page controller '$pageDef.controller'",
157
- ({ pageDef }) => {
158
- expect(isPageController(pageDef.controller)).toBe(true)
159
- }
160
- )
161
-
162
- it.each([
163
- { name: './pages/unknown.js' },
164
- { name: 'UnknownPageController' },
165
- { name: undefined },
166
- { name: '' }
167
- ])("rejects invalid page controller '$name'", ({ name }) => {
168
- expect(isPageController(name)).toBe(false)
169
- })
170
- })
171
-
172
- describe('Helper: getProxyUrlForLocalDevelopment', () => {
173
- it('returns null if uploadUrl is undefined', () => {
174
- expect(getProxyUrlForLocalDevelopment(undefined)).toBeNull()
175
- })
176
-
177
- it('returns null if uploadUrl does not include localhost:7337', () => {
178
- expect(getProxyUrlForLocalDevelopment('https://some-url.com')).toBeNull()
179
- expect(getProxyUrlForLocalDevelopment('http://localhost:8080')).toBeNull()
180
- })
181
-
182
- it('replaces localhost:7337 with uploader.127.0.0.1.sslip.io:7300', () => {
183
- const originalUrl = 'http://localhost:7337/upload'
184
- const expectedUrl = 'http://uploader.127.0.0.1.sslip.io:7300/upload'
185
-
186
- expect(getProxyUrlForLocalDevelopment(originalUrl)).toBe(expectedUrl)
187
- })
188
-
189
- it('handles multiple occurrences of localhost:7337', () => {
190
- const originalUrl =
191
- 'http://localhost:7337/path?redirect=http://localhost:7337/callback'
192
- const expectedUrl =
193
- 'http://uploader.127.0.0.1.sslip.io:7300/path?redirect=http://uploader.127.0.0.1.sslip.io:7300/callback'
194
-
195
- expect(getProxyUrlForLocalDevelopment(originalUrl)).toBe(expectedUrl)
196
- })
197
- })
198
- })
@@ -1,101 +0,0 @@
1
- import {
2
- ControllerType,
3
- controllerNameFromPath,
4
- isControllerName,
5
- type Page
6
- } from '@defra/forms-model'
7
-
8
- import { type FormModel } from '~/src/server/plugins/engine/models/FormModel.js'
9
- import * as PageControllers from '~/src/server/plugins/engine/pageControllers/index.js'
10
-
11
- export function isPageController(
12
- controllerName?: string | ControllerType
13
- ): controllerName is keyof typeof PageControllers {
14
- return isControllerName(controllerName) && controllerName in PageControllers
15
- }
16
-
17
- export type PageControllerClass = InstanceType<PageControllerType>
18
- export type PageControllerType =
19
- (typeof PageControllers)[keyof typeof PageControllers]
20
-
21
- /**
22
- * Creates page instance for each {@link Page} type
23
- */
24
- export function createPage(model: FormModel, pageDef: Page) {
25
- const controllerName = controllerNameFromPath(pageDef.controller)
26
-
27
- if (!pageDef.controller) {
28
- return new PageControllers.QuestionPageController(model, pageDef)
29
- }
30
-
31
- // Patch legacy controllers
32
- if (controllerName && pageDef.controller !== controllerName) {
33
- pageDef.controller = controllerName
34
- }
35
-
36
- let controller: PageControllerClass | undefined
37
-
38
- switch (pageDef.controller) {
39
- case ControllerType.Start:
40
- controller = new PageControllers.StartPageController(model, pageDef)
41
- break
42
-
43
- case ControllerType.Page:
44
- controller = new PageControllers.QuestionPageController(model, pageDef)
45
- break
46
-
47
- case ControllerType.Terminal:
48
- controller = new PageControllers.TerminalPageController(model, pageDef)
49
- break
50
-
51
- case ControllerType.Summary:
52
- controller = new PageControllers.SummaryPageController(model, pageDef)
53
- break
54
-
55
- case ControllerType.Status:
56
- controller = new PageControllers.StatusPageController(model, pageDef)
57
- break
58
-
59
- case ControllerType.FileUpload:
60
- controller = new PageControllers.FileUploadPageController(model, pageDef)
61
- break
62
-
63
- case ControllerType.Repeat:
64
- controller = new PageControllers.RepeatPageController(model, pageDef)
65
- break
66
- }
67
-
68
- if (typeof controller === 'undefined') {
69
- if (model.controllers?.[pageDef.controller]) {
70
- const Ctrl = model.controllers[pageDef.controller]
71
- controller = new Ctrl(model, pageDef) as unknown as PageControllerClass // type assertion needed because TS can't verify custom controller structure
72
- }
73
- }
74
-
75
- if (typeof controller === 'undefined') {
76
- throw new Error(`Page controller ${pageDef.controller} does not exist`)
77
- }
78
-
79
- return controller
80
- }
81
-
82
- /**
83
- * In local development environments, we sometimes need to rewrite the
84
- * CDP upload URL to work with CSP/CORS restrictions.
85
- * This helper function rewrites localhost URLs to use the sslip.io proxy
86
- * This is only used when running locally with a development proxy.
87
- * In non-local environments, this function returns null
88
- * @param uploadUrl - The original upload URL from CDP
89
- */
90
- export function getProxyUrlForLocalDevelopment(
91
- uploadUrl?: string
92
- ): string | null {
93
- if (!uploadUrl?.includes('localhost:7337')) {
94
- return null
95
- }
96
-
97
- return uploadUrl.replace(
98
- /localhost:7337/g,
99
- 'uploader.127.0.0.1.sslip.io:7300'
100
- )
101
- }
@@ -1,10 +0,0 @@
1
- export { StartPageController } from '~/src/server/plugins/engine/pageControllers/StartPageController.js'
2
- export {
3
- QuestionPageController, // Export alongside alias
4
- QuestionPageController as PageController
5
- } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'
6
- export { TerminalPageController } from '~/src/server/plugins/engine/pageControllers/TerminalPageController.js'
7
- export { SummaryPageController } from '~/src/server/plugins/engine/pageControllers/SummaryPageController.js'
8
- export { StatusPageController } from '~/src/server/plugins/engine/pageControllers/StatusPageController.js'
9
- export { FileUploadPageController } from '~/src/server/plugins/engine/pageControllers/FileUploadPageController.js'
10
- export { RepeatPageController } from '~/src/server/plugins/engine/pageControllers/RepeatPageController.js'