@defra/forms-engine-plugin 0.0.2 → 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 (330) 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/.server/server/plugins/nunjucks/environment.js +3 -3
  25. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  26. package/package.json +6 -2
  27. package/.browserslistrc +0 -16
  28. package/.editorconfig +0 -9
  29. package/.eslintrc.cjs +0 -266
  30. package/.github/dependabot.yml +0 -85
  31. package/.github/workflows/check-pull-request.yml +0 -209
  32. package/.github/workflows/pr-notifier.yml +0 -98
  33. package/.github/workflows/publish.yml +0 -111
  34. package/.husky/pre-commit +0 -1
  35. package/.lintstagedrc.js +0 -4
  36. package/.nvmrc +0 -1
  37. package/.prettierignore +0 -8
  38. package/.prettierrc.cjs +0 -26
  39. package/Dockerfile +0 -61
  40. package/Procfile +0 -1
  41. package/babel.config.cjs +0 -55
  42. package/compose/aws.env +0 -4
  43. package/compose/start-localstack.sh +0 -26
  44. package/docker-compose.yaml +0 -86
  45. package/globals.d.ts +0 -1
  46. package/jest.config.cjs +0 -54
  47. package/jest.environment.js +0 -4
  48. package/jest.setup.cjs +0 -14
  49. package/postcss.config.js +0 -26
  50. package/sonar-project.properties +0 -17
  51. package/src/client/javascripts/application.js +0 -87
  52. package/src/client/javascripts/file-upload.js +0 -386
  53. package/src/client/stylesheets/_code.scss +0 -33
  54. package/src/client/stylesheets/_govuk-frontend.scss +0 -4
  55. package/src/client/stylesheets/_prose.scss +0 -56
  56. package/src/client/stylesheets/_service-banner.scss +0 -24
  57. package/src/client/stylesheets/_summary-list.scss +0 -28
  58. package/src/client/stylesheets/_tag-env.scss +0 -24
  59. package/src/client/stylesheets/application.scss +0 -14
  60. package/src/common/cookies.js +0 -58
  61. package/src/common/cookies.test.js +0 -23
  62. package/src/common/types.js +0 -5
  63. package/src/config/index.ts +0 -271
  64. package/src/index.ts +0 -31
  65. package/src/server/common/helpers/logging/logger-options.test.ts +0 -50
  66. package/src/server/common/helpers/logging/logger-options.ts +0 -46
  67. package/src/server/common/helpers/logging/logger.ts +0 -7
  68. package/src/server/common/helpers/logging/request-logger.ts +0 -9
  69. package/src/server/common/helpers/logging/request-tracing.js +0 -10
  70. package/src/server/common/helpers/redis-client.js +0 -70
  71. package/src/server/constants.js +0 -1
  72. package/src/server/forms/README.md +0 -10
  73. package/src/server/forms/components.json +0 -1015
  74. package/src/server/forms/report-a-terrorist.json +0 -270
  75. package/src/server/forms/runner-components-test.json +0 -365
  76. package/src/server/forms/test.json +0 -581
  77. package/src/server/index.test.ts +0 -582
  78. package/src/server/index.ts +0 -140
  79. package/src/server/plugins/blankie.test.ts +0 -73
  80. package/src/server/plugins/blankie.ts +0 -48
  81. package/src/server/plugins/crumb.ts +0 -20
  82. package/src/server/plugins/engine/README.md +0 -87
  83. package/src/server/plugins/engine/components/AutocompleteField.test.ts +0 -294
  84. package/src/server/plugins/engine/components/AutocompleteField.ts +0 -49
  85. package/src/server/plugins/engine/components/CheckboxesField.test.ts +0 -379
  86. package/src/server/plugins/engine/components/CheckboxesField.ts +0 -106
  87. package/src/server/plugins/engine/components/ComponentBase.ts +0 -97
  88. package/src/server/plugins/engine/components/ComponentCollection.ts +0 -278
  89. package/src/server/plugins/engine/components/DatePartsField.test.ts +0 -822
  90. package/src/server/plugins/engine/components/DatePartsField.ts +0 -264
  91. package/src/server/plugins/engine/components/Details.test.ts +0 -49
  92. package/src/server/plugins/engine/components/Details.ts +0 -30
  93. package/src/server/plugins/engine/components/EmailAddressField.test.ts +0 -395
  94. package/src/server/plugins/engine/components/EmailAddressField.ts +0 -55
  95. package/src/server/plugins/engine/components/FileUploadField.test.ts +0 -778
  96. package/src/server/plugins/engine/components/FileUploadField.ts +0 -262
  97. package/src/server/plugins/engine/components/FormComponent.ts +0 -249
  98. package/src/server/plugins/engine/components/Html.test.ts +0 -48
  99. package/src/server/plugins/engine/components/Html.ts +0 -29
  100. package/src/server/plugins/engine/components/InsetText.test.ts +0 -48
  101. package/src/server/plugins/engine/components/InsetText.ts +0 -27
  102. package/src/server/plugins/engine/components/List.test.ts +0 -76
  103. package/src/server/plugins/engine/components/List.ts +0 -72
  104. package/src/server/plugins/engine/components/ListFormComponent.ts +0 -140
  105. package/src/server/plugins/engine/components/MonthYearField.test.ts +0 -567
  106. package/src/server/plugins/engine/components/MonthYearField.ts +0 -222
  107. package/src/server/plugins/engine/components/MultilineTextField.test.ts +0 -558
  108. package/src/server/plugins/engine/components/MultilineTextField.ts +0 -138
  109. package/src/server/plugins/engine/components/NumberField.test.ts +0 -701
  110. package/src/server/plugins/engine/components/NumberField.ts +0 -163
  111. package/src/server/plugins/engine/components/RadiosField.test.ts +0 -288
  112. package/src/server/plugins/engine/components/RadiosField.ts +0 -24
  113. package/src/server/plugins/engine/components/SelectField.test.ts +0 -288
  114. package/src/server/plugins/engine/components/SelectField.ts +0 -47
  115. package/src/server/plugins/engine/components/SelectionControlField.ts +0 -43
  116. package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +0 -356
  117. package/src/server/plugins/engine/components/TelephoneNumberField.ts +0 -67
  118. package/src/server/plugins/engine/components/TextField.test.ts +0 -489
  119. package/src/server/plugins/engine/components/TextField.ts +0 -96
  120. package/src/server/plugins/engine/components/UkAddressField.test.ts +0 -623
  121. package/src/server/plugins/engine/components/UkAddressField.ts +0 -172
  122. package/src/server/plugins/engine/components/YesNoField.test.ts +0 -248
  123. package/src/server/plugins/engine/components/YesNoField.ts +0 -31
  124. package/src/server/plugins/engine/components/constants.ts +0 -1
  125. package/src/server/plugins/engine/components/helpers.ts +0 -330
  126. package/src/server/plugins/engine/components/index.ts +0 -24
  127. package/src/server/plugins/engine/components/types.ts +0 -117
  128. package/src/server/plugins/engine/configureEnginePlugin.ts +0 -47
  129. package/src/server/plugins/engine/helpers.test.ts +0 -791
  130. package/src/server/plugins/engine/helpers.ts +0 -379
  131. package/src/server/plugins/engine/index.ts +0 -7
  132. package/src/server/plugins/engine/models/FormModel.test.ts +0 -42
  133. package/src/server/plugins/engine/models/FormModel.ts +0 -443
  134. package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
  135. package/src/server/plugins/engine/models/Section.ts +0 -0
  136. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +0 -209
  137. package/src/server/plugins/engine/models/SummaryViewModel.ts +0 -220
  138. package/src/server/plugins/engine/models/index.ts +0 -2
  139. package/src/server/plugins/engine/models/types.ts +0 -114
  140. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +0 -143
  141. package/src/server/plugins/engine/outputFormatters/human/v1.ts +0 -73
  142. package/src/server/plugins/engine/outputFormatters/index.test.ts +0 -17
  143. package/src/server/plugins/engine/outputFormatters/index.ts +0 -44
  144. package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +0 -229
  145. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +0 -140
  146. package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +0 -229
  147. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +0 -153
  148. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +0 -1108
  149. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +0 -446
  150. package/src/server/plugins/engine/pageControllers/PageController.test.ts +0 -205
  151. package/src/server/plugins/engine/pageControllers/PageController.ts +0 -176
  152. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +0 -1264
  153. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +0 -561
  154. package/src/server/plugins/engine/pageControllers/README.md +0 -28
  155. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +0 -264
  156. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +0 -458
  157. package/src/server/plugins/engine/pageControllers/StartPageController.ts +0 -18
  158. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +0 -50
  159. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +0 -261
  160. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +0 -28
  161. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +0 -19
  162. package/src/server/plugins/engine/pageControllers/helpers.test.ts +0 -198
  163. package/src/server/plugins/engine/pageControllers/helpers.ts +0 -101
  164. package/src/server/plugins/engine/pageControllers/index.ts +0 -10
  165. package/src/server/plugins/engine/pageControllers/validationOptions.ts +0 -89
  166. package/src/server/plugins/engine/plugin.ts +0 -673
  167. package/src/server/plugins/engine/services/formSubmissionService.js +0 -46
  168. package/src/server/plugins/engine/services/formsService.js +0 -46
  169. package/src/server/plugins/engine/services/formsService.test.js +0 -90
  170. package/src/server/plugins/engine/services/index.js +0 -3
  171. package/src/server/plugins/engine/services/notifyService.test.ts +0 -132
  172. package/src/server/plugins/engine/services/notifyService.ts +0 -64
  173. package/src/server/plugins/engine/services/uploadService.js +0 -60
  174. package/src/server/plugins/engine/types.ts +0 -315
  175. package/src/server/plugins/engine/views/components/autocompletefield.html +0 -5
  176. package/src/server/plugins/engine/views/components/checkboxesfield.html +0 -5
  177. package/src/server/plugins/engine/views/components/datepartsfield.html +0 -5
  178. package/src/server/plugins/engine/views/components/details.html +0 -6
  179. package/src/server/plugins/engine/views/components/emailaddressfield.html +0 -5
  180. package/src/server/plugins/engine/views/components/fileuploadfield-key.html +0 -8
  181. package/src/server/plugins/engine/views/components/fileuploadfield-value.html +0 -3
  182. package/src/server/plugins/engine/views/components/fileuploadfield.html +0 -24
  183. package/src/server/plugins/engine/views/components/html.html +0 -3
  184. package/src/server/plugins/engine/views/components/insettext.html +0 -7
  185. package/src/server/plugins/engine/views/components/list.html +0 -36
  186. package/src/server/plugins/engine/views/components/monthyearfield.html +0 -5
  187. package/src/server/plugins/engine/views/components/multilinetextfield.html +0 -10
  188. package/src/server/plugins/engine/views/components/numberfield.html +0 -5
  189. package/src/server/plugins/engine/views/components/radiosfield.html +0 -5
  190. package/src/server/plugins/engine/views/components/selectfield.html +0 -5
  191. package/src/server/plugins/engine/views/components/telephonenumberfield.html +0 -5
  192. package/src/server/plugins/engine/views/components/textfield.html +0 -5
  193. package/src/server/plugins/engine/views/components/ukaddressfield.html +0 -25
  194. package/src/server/plugins/engine/views/components/yesnofield.html +0 -5
  195. package/src/server/plugins/engine/views/file-upload.html +0 -45
  196. package/src/server/plugins/engine/views/index.html +0 -39
  197. package/src/server/plugins/engine/views/item-delete.html +0 -56
  198. package/src/server/plugins/engine/views/partials/components.html +0 -6
  199. package/src/server/plugins/engine/views/partials/conditional-components.html +0 -3
  200. package/src/server/plugins/engine/views/partials/debug.html +0 -44
  201. package/src/server/plugins/engine/views/partials/form.html +0 -15
  202. package/src/server/plugins/engine/views/partials/heading.html +0 -16
  203. package/src/server/plugins/engine/views/partials/preview-banner.html +0 -32
  204. package/src/server/plugins/engine/views/partials/preview-banner.test.js +0 -122
  205. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +0 -10
  206. package/src/server/plugins/engine/views/repeat-list-summary.html +0 -53
  207. package/src/server/plugins/errorPages.ts +0 -58
  208. package/src/server/plugins/nunjucks/context.js +0 -88
  209. package/src/server/plugins/nunjucks/context.test.js +0 -142
  210. package/src/server/plugins/nunjucks/enviroment.test.js +0 -201
  211. package/src/server/plugins/nunjucks/environment.js +0 -116
  212. package/src/server/plugins/nunjucks/filters/answer.js +0 -27
  213. package/src/server/plugins/nunjucks/filters/answer.test.js +0 -89
  214. package/src/server/plugins/nunjucks/filters/evaluate.js +0 -21
  215. package/src/server/plugins/nunjucks/filters/field.js +0 -28
  216. package/src/server/plugins/nunjucks/filters/field.test.js +0 -75
  217. package/src/server/plugins/nunjucks/filters/highlight.js +0 -11
  218. package/src/server/plugins/nunjucks/filters/href.js +0 -30
  219. package/src/server/plugins/nunjucks/filters/href.test.js +0 -80
  220. package/src/server/plugins/nunjucks/filters/index.js +0 -8
  221. package/src/server/plugins/nunjucks/filters/inspect.js +0 -15
  222. package/src/server/plugins/nunjucks/filters/page.js +0 -24
  223. package/src/server/plugins/nunjucks/filters/page.test.js +0 -65
  224. package/src/server/plugins/nunjucks/index.js +0 -3
  225. package/src/server/plugins/nunjucks/plugin.js +0 -40
  226. package/src/server/plugins/nunjucks/render.js +0 -42
  227. package/src/server/plugins/nunjucks/types.js +0 -40
  228. package/src/server/plugins/pulse.ts +0 -11
  229. package/src/server/plugins/router.ts +0 -201
  230. package/src/server/plugins/session.ts +0 -28
  231. package/src/server/routes/health.js +0 -13
  232. package/src/server/routes/health.test.js +0 -35
  233. package/src/server/routes/index.test.ts +0 -125
  234. package/src/server/routes/index.ts +0 -2
  235. package/src/server/routes/public.ts +0 -47
  236. package/src/server/routes/types.ts +0 -48
  237. package/src/server/schemas/index.ts +0 -34
  238. package/src/server/secure-context.js +0 -43
  239. package/src/server/services/cacheService.test.ts +0 -276
  240. package/src/server/services/cacheService.ts +0 -131
  241. package/src/server/services/httpService.test.js +0 -491
  242. package/src/server/services/httpService.ts +0 -50
  243. package/src/server/services/index.ts +0 -1
  244. package/src/server/types.ts +0 -54
  245. package/src/server/utils/notify.test.ts +0 -37
  246. package/src/server/utils/notify.ts +0 -50
  247. package/src/server/utils/secure-context/get-trust-store-certs.js +0 -11
  248. package/src/server/utils/secure-context/get-trust-store-certs.test.js +0 -19
  249. package/src/server/utils/utils.js +0 -24
  250. package/src/server/utils/utils.test.js +0 -54
  251. package/src/server/views/404.html +0 -16
  252. package/src/server/views/500.html +0 -19
  253. package/src/server/views/components/debug/macro.njk +0 -3
  254. package/src/server/views/components/debug/template.njk +0 -13
  255. package/src/server/views/components/service-banner/macro.njk +0 -3
  256. package/src/server/views/components/service-banner/template.njk +0 -20
  257. package/src/server/views/components/service-banner/template.test.js +0 -43
  258. package/src/server/views/components/tag-env/macro.njk +0 -3
  259. package/src/server/views/components/tag-env/template.njk +0 -30
  260. package/src/server/views/components/tag-env/template.test.js +0 -66
  261. package/src/server/views/confirmation.html +0 -19
  262. package/src/server/views/help/accessibility-statement.html +0 -58
  263. package/src/server/views/help/cookie-preferences.html +0 -57
  264. package/src/server/views/help/cookies.html +0 -71
  265. package/src/server/views/help/get-support.html +0 -37
  266. package/src/server/views/help/privacy-notice.html +0 -68
  267. package/src/server/views/help/terms-and-conditions.html +0 -83
  268. package/src/server/views/layout.html +0 -199
  269. package/src/server/views/summary.html +0 -50
  270. package/src/typings/hapi/index.d.ts +0 -95
  271. package/src/typings/hapi-tracing/index.d.ts +0 -6
  272. package/src/typings/index.d.ts +0 -3
  273. package/src/typings/joi/index.d.ts +0 -22
  274. package/stylelint.config.js +0 -10
  275. package/test/client/javascripts/file-upload.test.js +0 -1197
  276. package/test/condition/checkboxes.test.js +0 -112
  277. package/test/condition/radios.test.js +0 -112
  278. package/test/condition/text.test.js +0 -103
  279. package/test/fixtures/assets-manifest.json +0 -4
  280. package/test/fixtures/form.js +0 -86
  281. package/test/fixtures/index.js +0 -2
  282. package/test/fixtures/list.js +0 -92
  283. package/test/form/cookies.test.js +0 -338
  284. package/test/form/csrf.test.js +0 -87
  285. package/test/form/definitions/basic.js +0 -101
  286. package/test/form/definitions/blank.js +0 -10
  287. package/test/form/definitions/checkboxes.json +0 -88
  288. package/test/form/definitions/components.json +0 -452
  289. package/test/form/definitions/conditional-reveal.js +0 -140
  290. package/test/form/definitions/conditions-basic.js +0 -187
  291. package/test/form/definitions/conditions-complex.js +0 -338
  292. package/test/form/definitions/conditions-dates.js +0 -78
  293. package/test/form/definitions/conditions-escaping.js +0 -143
  294. package/test/form/definitions/demo-cph-number.js +0 -3099
  295. package/test/form/definitions/feedback.json +0 -45
  296. package/test/form/definitions/fields-optional.js +0 -402
  297. package/test/form/definitions/fields-required.js +0 -402
  298. package/test/form/definitions/file-upload-basic.js +0 -44
  299. package/test/form/definitions/file-upload.js +0 -66
  300. package/test/form/definitions/minimal.js +0 -39
  301. package/test/form/definitions/phase-alpha.json +0 -33
  302. package/test/form/definitions/phase-default.json +0 -26
  303. package/test/form/definitions/radios.json +0 -88
  304. package/test/form/definitions/repeat-mixed.js +0 -54
  305. package/test/form/definitions/repeat.js +0 -70
  306. package/test/form/definitions/status.json +0 -126
  307. package/test/form/definitions/templates.js +0 -183
  308. package/test/form/definitions/test.json +0 -581
  309. package/test/form/definitions/text.json +0 -75
  310. package/test/form/definitions/titles.json +0 -170
  311. package/test/form/definitions.test.js +0 -47
  312. package/test/form/exit-page.test.js +0 -210
  313. package/test/form/feedback.test.js +0 -68
  314. package/test/form/fields-optional.test.js +0 -237
  315. package/test/form/fields-required.test.js +0 -294
  316. package/test/form/file-upload.test.js +0 -313
  317. package/test/form/govuk-notify.test.js +0 -449
  318. package/test/form/journey-basic.test.js +0 -444
  319. package/test/form/persist-files.test.js +0 -227
  320. package/test/form/phase-banner.test.js +0 -71
  321. package/test/form/repeat.test.js +0 -628
  322. package/test/form/summary-submission-email.test.js +0 -95
  323. package/test/form/template.test.js +0 -288
  324. package/test/form/titles.test.js +0 -204
  325. package/test/helpers/component-helpers.js +0 -74
  326. package/test/utils/get-cookie.js +0 -42
  327. package/test/utils/get-form-definitions.js +0 -18
  328. package/tmp.pdf +0 -1
  329. package/tsconfig.json +0 -28
  330. package/webpack.config.js +0 -208
@@ -1,673 +0,0 @@
1
- import { hasFormComponents, slugSchema } from '@defra/forms-model'
2
- import Boom from '@hapi/boom'
3
- import {
4
- type Plugin,
5
- type ResponseObject,
6
- type ResponseToolkit,
7
- type RouteOptions
8
- } from '@hapi/hapi'
9
- import { isEqual } from 'date-fns'
10
- import Joi from 'joi'
11
-
12
- import { PREVIEW_PATH_PREFIX } from '~/src/server/constants.js'
13
- import {
14
- checkEmailAddressForLiveFormSubmission,
15
- checkFormStatus,
16
- findPage,
17
- getPage,
18
- getStartPath,
19
- normalisePath,
20
- proceed,
21
- redirectPath
22
- } from '~/src/server/plugins/engine/helpers.js'
23
- import {
24
- FormModel,
25
- SummaryViewModel
26
- } from '~/src/server/plugins/engine/models/index.js'
27
- import { format } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'
28
- import { FileUploadPageController } from '~/src/server/plugins/engine/pageControllers/FileUploadPageController.js'
29
- import { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'
30
- import { RepeatPageController } from '~/src/server/plugins/engine/pageControllers/RepeatPageController.js'
31
- import { getFormSubmissionData } from '~/src/server/plugins/engine/pageControllers/SummaryPageController.js'
32
- import { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers.js'
33
- import * as defaultServices from '~/src/server/plugins/engine/services/index.js'
34
- import { getUploadStatus } from '~/src/server/plugins/engine/services/uploadService.js'
35
- import { type FormContext } from '~/src/server/plugins/engine/types.js'
36
- import {
37
- type FormRequest,
38
- type FormRequestPayload,
39
- type FormRequestPayloadRefs,
40
- type FormRequestRefs
41
- } from '~/src/server/routes/types.js'
42
- import {
43
- actionSchema,
44
- confirmSchema,
45
- crumbSchema,
46
- itemIdSchema,
47
- pathSchema,
48
- stateSchema
49
- } from '~/src/server/schemas/index.js'
50
- import * as httpService from '~/src/server/services/httpService.js'
51
- import { type Services } from '~/src/server/types.js'
52
-
53
- export interface PluginOptions {
54
- model?: FormModel
55
- services?: Services
56
- controllers?: Record<string, typeof PageController>
57
- }
58
-
59
- export const plugin = {
60
- name: '@defra/forms-engine-plugin',
61
- dependencies: ['@hapi/vision', '@hapi/crumb', '@hapi/yar', 'hapi-pino'],
62
- multiple: true,
63
- register(server, options) {
64
- const { model, services = defaultServices, controllers } = options
65
- const { formsService } = services
66
-
67
- server.app.model = model
68
-
69
- // In-memory cache of FormModel items, exposed
70
- // (for testing purposes) through `server.app.models`
71
- const itemCache = new Map<string, { model: FormModel; updatedAt: Date }>()
72
- server.app.models = itemCache
73
-
74
- const loadFormPreHandler = async (
75
- request: FormRequest | FormRequestPayload,
76
- h: Pick<ResponseToolkit, 'continue'>
77
- ) => {
78
- if (server.app.model) {
79
- request.app.model = server.app.model
80
-
81
- return h.continue
82
- }
83
-
84
- const { params, path } = request
85
- const { slug } = params
86
- const { isPreview, state: formState } = checkFormStatus(path)
87
-
88
- // Get the form metadata using the `slug` param
89
- const metadata = await formsService.getFormMetadata(slug)
90
-
91
- const { id, [formState]: state } = metadata
92
-
93
- // Check the metadata supports the requested state
94
- if (!state) {
95
- throw Boom.notFound(`No '${formState}' state for form metadata ${id}`)
96
- }
97
-
98
- // Cache the models based on id, state and whether
99
- // it's a preview or not. There could be up to 3 models
100
- // cached for a single form:
101
- // "{id}_live_false" (live/live)
102
- // "{id}_live_true" (live/preview)
103
- // "{id}_draft_true" (draft/preview)
104
- const key = `${id}_${formState}_${isPreview}`
105
- let item = itemCache.get(key)
106
-
107
- if (!item || !isEqual(item.updatedAt, state.updatedAt)) {
108
- server.logger.info(
109
- `Getting form definition ${id} (${slug}) ${formState}`
110
- )
111
-
112
- // Get the form definition using the `id` from the metadata
113
- const definition = await formsService.getFormDefinition(id, formState)
114
-
115
- if (!definition) {
116
- throw Boom.notFound(
117
- `No definition found for form metadata ${id} (${slug}) ${formState}`
118
- )
119
- }
120
-
121
- const emailAddress =
122
- metadata.notificationEmail ?? definition.outputEmail
123
-
124
- checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)
125
-
126
- // Build the form model
127
- server.logger.info(
128
- `Building model for form definition ${id} (${slug}) ${formState}`
129
- )
130
-
131
- // Set up the basePath for the model
132
- const basePath = isPreview
133
- ? `${PREVIEW_PATH_PREFIX.substring(1)}/${formState}/${slug}`
134
- : slug
135
-
136
- // Construct the form model
137
- const model = new FormModel(
138
- definition,
139
- { basePath },
140
- services,
141
- controllers
142
- )
143
-
144
- // Create new item and add it to the item cache
145
- item = { model, updatedAt: state.updatedAt }
146
- itemCache.set(key, item)
147
- }
148
-
149
- // Assign the model to the request data
150
- // for use in the downstream handler
151
- request.app.model = item.model
152
-
153
- return h.continue
154
- }
155
-
156
- const dispatchHandler = (
157
- request: FormRequest,
158
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
159
- ) => {
160
- const { model } = request.app
161
-
162
- const servicePath = model ? `/${model.basePath}` : ''
163
- return proceed(request, h, `${servicePath}${getStartPath(model)}`)
164
- }
165
-
166
- const redirectOrMakeHandler = async (
167
- request: FormRequest | FormRequestPayload,
168
- h: Pick<ResponseToolkit, 'redirect' | 'view'>,
169
- makeHandler: (
170
- page: PageControllerClass,
171
- context: FormContext
172
- ) => ResponseObject | Promise<ResponseObject>
173
- ) => {
174
- const { app, params } = request
175
- const { model } = app
176
-
177
- if (!model) {
178
- throw Boom.notFound(`No model found for /${params.path}`)
179
- }
180
-
181
- const { cacheService } = request.services([])
182
- const page = getPage(model, request)
183
- const state = await page.getState(request)
184
- const flash = cacheService.getFlash(request)
185
- const context = model.getFormContext(request, state, flash?.errors)
186
- const relevantPath = page.getRelevantPath(request, context)
187
- const summaryPath = page.getSummaryPath()
188
-
189
- // Return handler for relevant pages or preview URL direct access
190
- if (relevantPath.startsWith(page.path) || context.isForceAccess) {
191
- return makeHandler(page, context)
192
- }
193
-
194
- // Redirect back to last relevant page
195
- const redirectTo = findPage(model, relevantPath)
196
-
197
- // Set the return URL unless an exit page
198
- if (redirectTo?.next.length) {
199
- request.query.returnUrl = page.getHref(summaryPath)
200
- }
201
-
202
- return proceed(request, h, page.getHref(relevantPath))
203
- }
204
-
205
- const getHandler = (
206
- request: FormRequest,
207
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
208
- ) => {
209
- const { params } = request
210
-
211
- if (normalisePath(params.path) === '') {
212
- return dispatchHandler(request, h)
213
- }
214
-
215
- return redirectOrMakeHandler(request, h, async (page, context) => {
216
- // Check for a page onLoad HTTP event and if one exists,
217
- // call it and assign the response to the context data
218
- const { events } = page
219
- const { model } = request.app
220
-
221
- if (!model) {
222
- throw Boom.notFound(`No model found for /${params.path}`)
223
- }
224
-
225
- if (events?.onLoad && events.onLoad.type === 'http') {
226
- const { options } = events.onLoad
227
- const { url } = options
228
-
229
- // TODO: Update structured data POST payload with when helper
230
- // is updated to removing the dependency on `SummaryViewModel` etc.
231
- const viewModel = new SummaryViewModel(request, page, context)
232
- const items = getFormSubmissionData(
233
- viewModel.context,
234
- viewModel.details
235
- )
236
-
237
- // @ts-expect-error - function signature will be refactored in the next iteration of the formatter
238
- const payload = format(items, model, undefined, undefined)
239
-
240
- const { payload: response } = await httpService.postJson(url, {
241
- payload
242
- })
243
-
244
- Object.assign(context.data, response)
245
- }
246
-
247
- return page.makeGetRouteHandler()(request, context, h)
248
- })
249
- }
250
-
251
- const postHandler = (
252
- request: FormRequestPayload,
253
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
254
- ) => {
255
- const { query } = request
256
-
257
- return redirectOrMakeHandler(request, h, (page, context) => {
258
- const { pageDef } = page
259
- const { isForceAccess } = context
260
-
261
- // Redirect to GET for preview URL direct access
262
- if (isForceAccess && !hasFormComponents(pageDef)) {
263
- return proceed(request, h, redirectPath(page.href, query))
264
- }
265
-
266
- return page.makePostRouteHandler()(request, context, h)
267
- })
268
- }
269
-
270
- const dispatchRouteOptions: RouteOptions<FormRequestRefs> = {
271
- pre: [
272
- {
273
- method: loadFormPreHandler
274
- }
275
- ]
276
- }
277
-
278
- server.route({
279
- method: 'get',
280
- path: '/{slug}',
281
- handler: dispatchHandler,
282
- options: {
283
- ...dispatchRouteOptions,
284
- validate: {
285
- params: Joi.object().keys({
286
- slug: slugSchema
287
- })
288
- }
289
- }
290
- })
291
-
292
- server.route({
293
- method: 'get',
294
- path: '/preview/{state}/{slug}',
295
- handler: dispatchHandler,
296
- options: {
297
- ...dispatchRouteOptions,
298
- validate: {
299
- params: Joi.object().keys({
300
- state: stateSchema,
301
- slug: slugSchema
302
- })
303
- }
304
- }
305
- })
306
-
307
- const getRouteOptions: RouteOptions<FormRequestRefs> = {
308
- pre: [
309
- {
310
- method: loadFormPreHandler
311
- }
312
- ]
313
- }
314
-
315
- server.route({
316
- method: 'get',
317
- path: '/{slug}/{path}/{itemId?}',
318
- handler: getHandler,
319
- options: {
320
- ...getRouteOptions,
321
- validate: {
322
- params: Joi.object().keys({
323
- slug: slugSchema,
324
- path: pathSchema,
325
- itemId: itemIdSchema.optional()
326
- })
327
- }
328
- }
329
- })
330
-
331
- server.route({
332
- method: 'get',
333
- path: '/preview/{state}/{slug}/{path}/{itemId?}',
334
- handler: getHandler,
335
- options: {
336
- ...getRouteOptions,
337
- validate: {
338
- params: Joi.object().keys({
339
- state: stateSchema,
340
- slug: slugSchema,
341
- path: pathSchema,
342
- itemId: itemIdSchema.optional()
343
- })
344
- }
345
- }
346
- })
347
-
348
- const postRouteOptions: RouteOptions<FormRequestPayloadRefs> = {
349
- payload: {
350
- parse: true
351
- },
352
- pre: [{ method: loadFormPreHandler }]
353
- }
354
-
355
- server.route({
356
- method: 'post',
357
- path: '/{slug}/{path}/{itemId?}',
358
- handler: postHandler,
359
- options: {
360
- ...postRouteOptions,
361
- validate: {
362
- params: Joi.object().keys({
363
- slug: slugSchema,
364
- path: pathSchema,
365
- itemId: itemIdSchema.optional()
366
- }),
367
- payload: Joi.object()
368
- .keys({
369
- crumb: crumbSchema,
370
- action: actionSchema
371
- })
372
- .unknown(true)
373
- .required()
374
- }
375
- }
376
- })
377
-
378
- server.route({
379
- method: 'post',
380
- path: '/preview/{state}/{slug}/{path}/{itemId?}',
381
- handler: postHandler,
382
- options: {
383
- ...postRouteOptions,
384
- validate: {
385
- params: Joi.object().keys({
386
- state: stateSchema,
387
- slug: slugSchema,
388
- path: pathSchema,
389
- itemId: itemIdSchema.optional()
390
- }),
391
- payload: Joi.object()
392
- .keys({
393
- crumb: crumbSchema,
394
- action: actionSchema
395
- })
396
- .unknown(true)
397
- .required()
398
- }
399
- }
400
- })
401
-
402
- /**
403
- * "AddAnother" repeat routes
404
- */
405
-
406
- // List summary GET route
407
- const getListSummaryHandler = (
408
- request: FormRequest,
409
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
410
- ) => {
411
- const { params } = request
412
-
413
- return redirectOrMakeHandler(request, h, (page, context) => {
414
- if (!(page instanceof RepeatPageController)) {
415
- throw Boom.notFound(`No repeater page found for /${params.path}`)
416
- }
417
-
418
- return page.makeGetListSummaryRouteHandler()(request, context, h)
419
- })
420
- }
421
-
422
- server.route({
423
- method: 'get',
424
- path: '/{slug}/{path}/summary',
425
- handler: getListSummaryHandler,
426
- options: {
427
- ...getRouteOptions,
428
- validate: {
429
- params: Joi.object().keys({
430
- slug: slugSchema,
431
- path: pathSchema
432
- })
433
- }
434
- }
435
- })
436
-
437
- server.route({
438
- method: 'get',
439
- path: '/preview/{state}/{slug}/{path}/summary',
440
- handler: getListSummaryHandler,
441
- options: {
442
- ...getRouteOptions,
443
- validate: {
444
- params: Joi.object().keys({
445
- state: stateSchema,
446
- slug: slugSchema,
447
- path: pathSchema
448
- })
449
- }
450
- }
451
- })
452
-
453
- // List summary POST route
454
- const postListSummaryHandler = (
455
- request: FormRequestPayload,
456
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
457
- ) => {
458
- const { params } = request
459
-
460
- return redirectOrMakeHandler(request, h, (page, context) => {
461
- const { isForceAccess } = context
462
-
463
- if (isForceAccess || !(page instanceof RepeatPageController)) {
464
- throw Boom.notFound(`No repeater page found for /${params.path}`)
465
- }
466
-
467
- return page.makePostListSummaryRouteHandler()(request, context, h)
468
- })
469
- }
470
-
471
- server.route({
472
- method: 'post',
473
- path: '/{slug}/{path}/summary',
474
- handler: postListSummaryHandler,
475
- options: {
476
- ...postRouteOptions,
477
- validate: {
478
- params: Joi.object().keys({
479
- slug: slugSchema,
480
- path: pathSchema
481
- }),
482
- payload: Joi.object()
483
- .keys({
484
- crumb: crumbSchema,
485
- action: actionSchema
486
- })
487
- .required()
488
- }
489
- }
490
- })
491
-
492
- server.route({
493
- method: 'post',
494
- path: '/preview/{state}/{slug}/{path}/summary',
495
- handler: postListSummaryHandler,
496
- options: {
497
- ...postRouteOptions,
498
- validate: {
499
- params: Joi.object().keys({
500
- state: stateSchema,
501
- slug: slugSchema,
502
- path: pathSchema
503
- }),
504
- payload: Joi.object()
505
- .keys({
506
- crumb: crumbSchema,
507
- action: actionSchema
508
- })
509
- .required()
510
- }
511
- }
512
- })
513
-
514
- // Item delete GET route
515
- const getItemDeleteHandler = (
516
- request: FormRequest,
517
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
518
- ) => {
519
- const { params } = request
520
-
521
- return redirectOrMakeHandler(request, h, (page, context) => {
522
- if (
523
- !(
524
- page instanceof RepeatPageController ||
525
- page instanceof FileUploadPageController
526
- )
527
- ) {
528
- throw Boom.notFound(`No page found for /${params.path}`)
529
- }
530
-
531
- return page.makeGetItemDeleteRouteHandler()(request, context, h)
532
- })
533
- }
534
-
535
- server.route({
536
- method: 'get',
537
- path: '/{slug}/{path}/{itemId}/confirm-delete',
538
- handler: getItemDeleteHandler,
539
- options: {
540
- ...getRouteOptions,
541
- validate: {
542
- params: Joi.object().keys({
543
- slug: slugSchema,
544
- path: pathSchema,
545
- itemId: itemIdSchema
546
- })
547
- }
548
- }
549
- })
550
-
551
- server.route({
552
- method: 'get',
553
- path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',
554
- handler: getItemDeleteHandler,
555
- options: {
556
- ...getRouteOptions,
557
- validate: {
558
- params: Joi.object().keys({
559
- state: stateSchema,
560
- slug: slugSchema,
561
- path: pathSchema,
562
- itemId: itemIdSchema
563
- })
564
- }
565
- }
566
- })
567
-
568
- // Item delete POST route
569
- const postItemDeleteHandler = (
570
- request: FormRequestPayload,
571
- h: Pick<ResponseToolkit, 'redirect' | 'view'>
572
- ) => {
573
- const { params } = request
574
-
575
- return redirectOrMakeHandler(request, h, (page, context) => {
576
- const { isForceAccess } = context
577
-
578
- if (
579
- isForceAccess ||
580
- !(
581
- page instanceof RepeatPageController ||
582
- page instanceof FileUploadPageController
583
- )
584
- ) {
585
- throw Boom.notFound(`No page found for /${params.path}`)
586
- }
587
-
588
- return page.makePostItemDeleteRouteHandler()(request, context, h)
589
- })
590
- }
591
-
592
- server.route({
593
- method: 'post',
594
- path: '/{slug}/{path}/{itemId}/confirm-delete',
595
- handler: postItemDeleteHandler,
596
- options: {
597
- ...postRouteOptions,
598
- validate: {
599
- params: Joi.object().keys({
600
- slug: slugSchema,
601
- path: pathSchema,
602
- itemId: itemIdSchema
603
- }),
604
- payload: Joi.object()
605
- .keys({
606
- crumb: crumbSchema,
607
- action: actionSchema,
608
- confirm: confirmSchema
609
- })
610
- .required()
611
- }
612
- }
613
- })
614
-
615
- server.route({
616
- method: 'post',
617
- path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',
618
- handler: postItemDeleteHandler,
619
- options: {
620
- ...postRouteOptions,
621
- validate: {
622
- params: Joi.object().keys({
623
- state: stateSchema,
624
- slug: slugSchema,
625
- path: pathSchema,
626
- itemId: itemIdSchema
627
- }),
628
- payload: Joi.object()
629
- .keys({
630
- crumb: crumbSchema,
631
- action: actionSchema,
632
- confirm: confirmSchema
633
- })
634
- .required()
635
- }
636
- }
637
- })
638
-
639
- server.route({
640
- method: 'get',
641
- path: '/upload-status/{uploadId}',
642
- handler: async (request, h) => {
643
- try {
644
- const { uploadId } = request.params as { uploadId: string }
645
- const status = await getUploadStatus(uploadId)
646
-
647
- if (!status) {
648
- return h.response({ error: 'Status check failed' }).code(400)
649
- }
650
-
651
- return h.response(status)
652
- } catch (error) {
653
- request.logger.error(
654
- ['upload-status'],
655
- 'Upload status check failed',
656
- error
657
- )
658
- return h.response({ error: 'Status check error' }).code(500)
659
- }
660
- },
661
- options: {
662
- plugins: {
663
- crumb: false
664
- },
665
- validate: {
666
- params: Joi.object().keys({
667
- uploadId: Joi.string().guid().required()
668
- })
669
- }
670
- }
671
- })
672
- }
673
- } satisfies Plugin<PluginOptions>
@@ -1,46 +0,0 @@
1
- import { config } from '~/src/config/index.js'
2
- import { postJson } from '~/src/server/services/httpService.js'
3
-
4
- const submissionUrl = config.get('submissionUrl')
5
-
6
- /**
7
- * Persist files by extending the time-to-live to 30 days
8
- * @param {{fileId: string, initiatedRetrievalKey: string}[]} files - batch of files to persist
9
- * @param {string} persistedRetrievalKey - final retrieval key when submitting
10
- */
11
- export async function persistFiles(files, persistedRetrievalKey) {
12
- const postJsonByType = /** @type {typeof postJson<object>} */ (postJson)
13
-
14
- const payload = {
15
- files,
16
- persistedRetrievalKey
17
- }
18
-
19
- const result = await postJsonByType(`${submissionUrl}/files/persist`, {
20
- payload
21
- })
22
-
23
- return result
24
- }
25
-
26
- /**
27
- * Submit form
28
- * @param {SubmitPayload} data - submission data
29
- */
30
- export async function submit(data) {
31
- const postJsonByType = /** @type {typeof postJson<SubmitResponsePayload>} */ (
32
- postJson
33
- )
34
-
35
- const payload = data
36
-
37
- const result = await postJsonByType(`${submissionUrl}/submit`, {
38
- payload
39
- })
40
-
41
- return result.payload
42
- }
43
-
44
- /**
45
- * @import { SubmitPayload, SubmitResponsePayload } from '@defra/forms-model'
46
- */