@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,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
- */