@defra/forms-engine-plugin 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (615) hide show
  1. package/.browserslistrc +16 -0
  2. package/.editorconfig +9 -0
  3. package/.eslintrc.cjs +266 -0
  4. package/.github/dependabot.yml +85 -0
  5. package/.github/workflows/check-pull-request.yml +209 -0
  6. package/.github/workflows/pr-notifier.yml +98 -0
  7. package/.github/workflows/publish.yml +111 -0
  8. package/.husky/pre-commit +1 -0
  9. package/.lintstagedrc.js +4 -0
  10. package/.nvmrc +1 -0
  11. package/.prettierignore +8 -0
  12. package/.prettierrc.cjs +26 -0
  13. package/.server/client/javascripts/application.js +68 -0
  14. package/.server/client/javascripts/application.js.map +1 -0
  15. package/.server/client/javascripts/file-upload.js +292 -0
  16. package/.server/client/javascripts/file-upload.js.map +1 -0
  17. package/.server/client/stylesheets/_code.scss +33 -0
  18. package/.server/client/stylesheets/_govuk-frontend.scss +4 -0
  19. package/.server/client/stylesheets/_prose.scss +56 -0
  20. package/.server/client/stylesheets/_service-banner.scss +24 -0
  21. package/.server/client/stylesheets/_summary-list.scss +28 -0
  22. package/.server/client/stylesheets/_tag-env.scss +24 -0
  23. package/.server/client/stylesheets/application.scss +14 -0
  24. package/.server/common/cookies.js +55 -0
  25. package/.server/common/cookies.js.map +1 -0
  26. package/.server/common/cookies.test.js +15 -0
  27. package/.server/common/cookies.test.js.map +1 -0
  28. package/.server/common/types.js +6 -0
  29. package/.server/common/types.js.map +1 -0
  30. package/.server/config/index.js +241 -0
  31. package/.server/config/index.js.map +1 -0
  32. package/.server/index.js +25 -0
  33. package/.server/index.js.map +1 -0
  34. package/.server/server/common/helpers/logging/logger-options.js +44 -0
  35. package/.server/server/common/helpers/logging/logger-options.js.map +1 -0
  36. package/.server/server/common/helpers/logging/logger.js +6 -0
  37. package/.server/server/common/helpers/logging/logger.js.map +1 -0
  38. package/.server/server/common/helpers/logging/request-logger.js +7 -0
  39. package/.server/server/common/helpers/logging/request-logger.js.map +1 -0
  40. package/.server/server/common/helpers/logging/request-tracing.js +12 -0
  41. package/.server/server/common/helpers/logging/request-tracing.js.map +1 -0
  42. package/.server/server/common/helpers/redis-client.js +55 -0
  43. package/.server/server/common/helpers/redis-client.js.map +1 -0
  44. package/.server/server/constants.js +2 -0
  45. package/.server/server/constants.js.map +1 -0
  46. package/.server/server/forms/README.md +10 -0
  47. package/.server/server/forms/components.json +1015 -0
  48. package/.server/server/forms/report-a-terrorist.json +270 -0
  49. package/.server/server/forms/runner-components-test.json +365 -0
  50. package/.server/server/forms/test.json +581 -0
  51. package/.server/server/index.js +116 -0
  52. package/.server/server/index.js.map +1 -0
  53. package/.server/server/plugins/blankie.js +29 -0
  54. package/.server/server/plugins/blankie.js.map +1 -0
  55. package/.server/server/plugins/crumb.js +15 -0
  56. package/.server/server/plugins/crumb.js.map +1 -0
  57. package/.server/server/plugins/engine/README.md +87 -0
  58. package/.server/server/plugins/engine/components/AutocompleteField.js +37 -0
  59. package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -0
  60. package/.server/server/plugins/engine/components/CheckboxesField.js +79 -0
  61. package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -0
  62. package/.server/server/plugins/engine/components/ComponentBase.js +55 -0
  63. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -0
  64. package/.server/server/plugins/engine/components/ComponentCollection.js +198 -0
  65. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -0
  66. package/.server/server/plugins/engine/components/DatePartsField.js +208 -0
  67. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -0
  68. package/.server/server/plugins/engine/components/Details.js +26 -0
  69. package/.server/server/plugins/engine/components/Details.js.map +1 -0
  70. package/.server/server/plugins/engine/components/EmailAddressField.js +40 -0
  71. package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -0
  72. package/.server/server/plugins/engine/components/FileUploadField.js +195 -0
  73. package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -0
  74. package/.server/server/plugins/engine/components/FormComponent.js +210 -0
  75. package/.server/server/plugins/engine/components/FormComponent.js.map +1 -0
  76. package/.server/server/plugins/engine/components/Html.js +24 -0
  77. package/.server/server/plugins/engine/components/Html.js.map +1 -0
  78. package/.server/server/plugins/engine/components/InsetText.js +22 -0
  79. package/.server/server/plugins/engine/components/InsetText.js.map +1 -0
  80. package/.server/server/plugins/engine/components/List.js +65 -0
  81. package/.server/server/plugins/engine/components/List.js.map +1 -0
  82. package/.server/server/plugins/engine/components/ListFormComponent.js +87 -0
  83. package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -0
  84. package/.server/server/plugins/engine/components/MonthYearField.js +172 -0
  85. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -0
  86. package/.server/server/plugins/engine/components/MultilineTextField.js +115 -0
  87. package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -0
  88. package/.server/server/plugins/engine/components/NumberField.js +137 -0
  89. package/.server/server/plugins/engine/components/NumberField.js.map +1 -0
  90. package/.server/server/plugins/engine/components/RadiosField.js +18 -0
  91. package/.server/server/plugins/engine/components/RadiosField.js.map +1 -0
  92. package/.server/server/plugins/engine/components/SelectField.js +33 -0
  93. package/.server/server/plugins/engine/components/SelectField.js.map +1 -0
  94. package/.server/server/plugins/engine/components/SelectionControlField.js +43 -0
  95. package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -0
  96. package/.server/server/plugins/engine/components/TelephoneNumberField.js +43 -0
  97. package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -0
  98. package/.server/server/plugins/engine/components/TextField.js +63 -0
  99. package/.server/server/plugins/engine/components/TextField.js.map +1 -0
  100. package/.server/server/plugins/engine/components/UkAddressField.js +130 -0
  101. package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -0
  102. package/.server/server/plugins/engine/components/YesNoField.js +28 -0
  103. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -0
  104. package/.server/server/plugins/engine/components/constants.js +2 -0
  105. package/.server/server/plugins/engine/components/constants.js.map +1 -0
  106. package/.server/server/plugins/engine/components/helpers.js +219 -0
  107. package/.server/server/plugins/engine/components/helpers.js.map +1 -0
  108. package/.server/server/plugins/engine/components/index.js +25 -0
  109. package/.server/server/plugins/engine/components/index.js.map +1 -0
  110. package/.server/server/plugins/engine/components/types.js +2 -0
  111. package/.server/server/plugins/engine/components/types.js.map +1 -0
  112. package/.server/server/plugins/engine/configureEnginePlugin.js +44 -0
  113. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -0
  114. package/.server/server/plugins/engine/helpers.js +268 -0
  115. package/.server/server/plugins/engine/helpers.js.map +1 -0
  116. package/.server/server/plugins/engine/index.js +6 -0
  117. package/.server/server/plugins/engine/index.js.map +1 -0
  118. package/.server/server/plugins/engine/models/FormModel.js +363 -0
  119. package/.server/server/plugins/engine/models/FormModel.js.map +1 -0
  120. package/.server/server/plugins/engine/models/RepeatingSummaryViewModel.js +2 -0
  121. package/.server/server/plugins/engine/models/RepeatingSummaryViewModel.js.map +1 -0
  122. package/.server/server/plugins/engine/models/Section.js +2 -0
  123. package/.server/server/plugins/engine/models/Section.js.map +1 -0
  124. package/.server/server/plugins/engine/models/SummaryViewModel.js +183 -0
  125. package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -0
  126. package/.server/server/plugins/engine/models/index.js +3 -0
  127. package/.server/server/plugins/engine/models/index.js.map +1 -0
  128. package/.server/server/plugins/engine/models/types.js +2 -0
  129. package/.server/server/plugins/engine/models/types.js.map +1 -0
  130. package/.server/server/plugins/engine/outputFormatters/human/v1.js +44 -0
  131. package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -0
  132. package/.server/server/plugins/engine/outputFormatters/index.js +24 -0
  133. package/.server/server/plugins/engine/outputFormatters/index.js.map +1 -0
  134. package/.server/server/plugins/engine/outputFormatters/machine/v1.js +104 -0
  135. package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -0
  136. package/.server/server/plugins/engine/outputFormatters/machine/v2.js +110 -0
  137. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -0
  138. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +401 -0
  139. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -0
  140. package/.server/server/plugins/engine/pageControllers/PageController.js +133 -0
  141. package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -0
  142. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +482 -0
  143. package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -0
  144. package/.server/server/plugins/engine/pageControllers/README.md +28 -0
  145. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +372 -0
  146. package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -0
  147. package/.server/server/plugins/engine/pageControllers/StartPageController.js +16 -0
  148. package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -0
  149. package/.server/server/plugins/engine/pageControllers/StatusPageController.js +43 -0
  150. package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -0
  151. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +195 -0
  152. package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -0
  153. package/.server/server/plugins/engine/pageControllers/TerminalPageController.js +8 -0
  154. package/.server/server/plugins/engine/pageControllers/TerminalPageController.js.map +1 -0
  155. package/.server/server/plugins/engine/pageControllers/helpers.js +69 -0
  156. package/.server/server/plugins/engine/pageControllers/helpers.js.map +1 -0
  157. package/.server/server/plugins/engine/pageControllers/index.js +10 -0
  158. package/.server/server/plugins/engine/pageControllers/index.js.map +1 -0
  159. package/.server/server/plugins/engine/pageControllers/validationOptions.js +78 -0
  160. package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -0
  161. package/.server/server/plugins/engine/plugin.js +562 -0
  162. package/.server/server/plugins/engine/plugin.js.map +1 -0
  163. package/.server/server/plugins/engine/services/formSubmissionService.js +39 -0
  164. package/.server/server/plugins/engine/services/formSubmissionService.js.map +1 -0
  165. package/.server/server/plugins/engine/services/formsService.js +41 -0
  166. package/.server/server/plugins/engine/services/formsService.js.map +1 -0
  167. package/.server/server/plugins/engine/services/formsService.test.js +71 -0
  168. package/.server/server/plugins/engine/services/formsService.test.js.map +1 -0
  169. package/.server/server/plugins/engine/services/index.js +4 -0
  170. package/.server/server/plugins/engine/services/index.js.map +1 -0
  171. package/.server/server/plugins/engine/services/notifyService.js +45 -0
  172. package/.server/server/plugins/engine/services/notifyService.js.map +1 -0
  173. package/.server/server/plugins/engine/services/uploadService.js +51 -0
  174. package/.server/server/plugins/engine/services/uploadService.js.map +1 -0
  175. package/.server/server/plugins/engine/types.js +53 -0
  176. package/.server/server/plugins/engine/types.js.map +1 -0
  177. package/.server/server/plugins/engine/views/components/autocompletefield.html +5 -0
  178. package/.server/server/plugins/engine/views/components/checkboxesfield.html +5 -0
  179. package/.server/server/plugins/engine/views/components/datepartsfield.html +5 -0
  180. package/.server/server/plugins/engine/views/components/details.html +6 -0
  181. package/.server/server/plugins/engine/views/components/emailaddressfield.html +5 -0
  182. package/.server/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
  183. package/.server/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
  184. package/.server/server/plugins/engine/views/components/fileuploadfield.html +24 -0
  185. package/.server/server/plugins/engine/views/components/html.html +3 -0
  186. package/.server/server/plugins/engine/views/components/insettext.html +7 -0
  187. package/.server/server/plugins/engine/views/components/list.html +36 -0
  188. package/.server/server/plugins/engine/views/components/monthyearfield.html +5 -0
  189. package/.server/server/plugins/engine/views/components/multilinetextfield.html +10 -0
  190. package/.server/server/plugins/engine/views/components/numberfield.html +5 -0
  191. package/.server/server/plugins/engine/views/components/radiosfield.html +5 -0
  192. package/.server/server/plugins/engine/views/components/selectfield.html +5 -0
  193. package/.server/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
  194. package/.server/server/plugins/engine/views/components/textfield.html +5 -0
  195. package/.server/server/plugins/engine/views/components/ukaddressfield.html +25 -0
  196. package/.server/server/plugins/engine/views/components/yesnofield.html +5 -0
  197. package/.server/server/plugins/engine/views/file-upload.html +45 -0
  198. package/.server/server/plugins/engine/views/index.html +39 -0
  199. package/.server/server/plugins/engine/views/item-delete.html +56 -0
  200. package/.server/server/plugins/engine/views/partials/components.html +6 -0
  201. package/.server/server/plugins/engine/views/partials/conditional-components.html +3 -0
  202. package/.server/server/plugins/engine/views/partials/debug.html +44 -0
  203. package/.server/server/plugins/engine/views/partials/form.html +15 -0
  204. package/.server/server/plugins/engine/views/partials/heading.html +16 -0
  205. package/.server/server/plugins/engine/views/partials/preview-banner.html +32 -0
  206. package/.server/server/plugins/engine/views/partials/preview-banner.test.js +108 -0
  207. package/.server/server/plugins/engine/views/partials/preview-banner.test.js.map +1 -0
  208. package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
  209. package/.server/server/plugins/engine/views/repeat-list-summary.html +53 -0
  210. package/.server/server/plugins/errorPages.js +49 -0
  211. package/.server/server/plugins/errorPages.js.map +1 -0
  212. package/.server/server/plugins/nunjucks/context.js +79 -0
  213. package/.server/server/plugins/nunjucks/context.js.map +1 -0
  214. package/.server/server/plugins/nunjucks/context.test.js +134 -0
  215. package/.server/server/plugins/nunjucks/context.test.js.map +1 -0
  216. package/.server/server/plugins/nunjucks/enviroment.test.js +166 -0
  217. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -0
  218. package/.server/server/plugins/nunjucks/environment.js +95 -0
  219. package/.server/server/plugins/nunjucks/environment.js.map +1 -0
  220. package/.server/server/plugins/nunjucks/filters/answer.js +26 -0
  221. package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -0
  222. package/.server/server/plugins/nunjucks/filters/answer.test.js +70 -0
  223. package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -0
  224. package/.server/server/plugins/nunjucks/filters/evaluate.js +22 -0
  225. package/.server/server/plugins/nunjucks/filters/evaluate.js.map +1 -0
  226. package/.server/server/plugins/nunjucks/filters/field.js +26 -0
  227. package/.server/server/plugins/nunjucks/filters/field.js.map +1 -0
  228. package/.server/server/plugins/nunjucks/filters/field.test.js +64 -0
  229. package/.server/server/plugins/nunjucks/filters/field.test.js.map +1 -0
  230. package/.server/server/plugins/nunjucks/filters/highlight.js +14 -0
  231. package/.server/server/plugins/nunjucks/filters/highlight.js.map +1 -0
  232. package/.server/server/plugins/nunjucks/filters/href.js +28 -0
  233. package/.server/server/plugins/nunjucks/filters/href.js.map +1 -0
  234. package/.server/server/plugins/nunjucks/filters/href.test.js +63 -0
  235. package/.server/server/plugins/nunjucks/filters/href.test.js.map +1 -0
  236. package/.server/server/plugins/nunjucks/filters/index.js +9 -0
  237. package/.server/server/plugins/nunjucks/filters/index.js.map +1 -0
  238. package/.server/server/plugins/nunjucks/filters/inspect.js +16 -0
  239. package/.server/server/plugins/nunjucks/filters/inspect.js.map +1 -0
  240. package/.server/server/plugins/nunjucks/filters/page.js +23 -0
  241. package/.server/server/plugins/nunjucks/filters/page.js.map +1 -0
  242. package/.server/server/plugins/nunjucks/filters/page.test.js +51 -0
  243. package/.server/server/plugins/nunjucks/filters/page.test.js.map +1 -0
  244. package/.server/server/plugins/nunjucks/index.js +4 -0
  245. package/.server/server/plugins/nunjucks/index.js.map +1 -0
  246. package/.server/server/plugins/nunjucks/plugin.js +38 -0
  247. package/.server/server/plugins/nunjucks/plugin.js.map +1 -0
  248. package/.server/server/plugins/nunjucks/render.js +41 -0
  249. package/.server/server/plugins/nunjucks/render.js.map +1 -0
  250. package/.server/server/plugins/nunjucks/types.js +41 -0
  251. package/.server/server/plugins/nunjucks/types.js.map +1 -0
  252. package/.server/server/plugins/pulse.js +8 -0
  253. package/.server/server/plugins/pulse.js.map +1 -0
  254. package/.server/server/plugins/router.js +169 -0
  255. package/.server/server/plugins/router.js.map +1 -0
  256. package/.server/server/plugins/session.js +28 -0
  257. package/.server/server/plugins/session.js.map +1 -0
  258. package/.server/server/routes/health.js +15 -0
  259. package/.server/server/routes/health.js.map +1 -0
  260. package/.server/server/routes/health.test.js +32 -0
  261. package/.server/server/routes/health.test.js.map +1 -0
  262. package/.server/server/routes/index.js +3 -0
  263. package/.server/server/routes/index.js.map +1 -0
  264. package/.server/server/routes/public.js +37 -0
  265. package/.server/server/routes/public.js.map +1 -0
  266. package/.server/server/routes/types.js +14 -0
  267. package/.server/server/routes/types.js.map +1 -0
  268. package/.server/server/schemas/index.js +15 -0
  269. package/.server/server/schemas/index.js.map +1 -0
  270. package/.server/server/secure-context.js +36 -0
  271. package/.server/server/secure-context.js.map +1 -0
  272. package/.server/server/services/cacheService.js +85 -0
  273. package/.server/server/services/cacheService.js.map +1 -0
  274. package/.server/server/services/httpService.js +44 -0
  275. package/.server/server/services/httpService.js.map +1 -0
  276. package/.server/server/services/httpService.test.js +504 -0
  277. package/.server/server/services/httpService.test.js.map +1 -0
  278. package/.server/server/services/index.js +2 -0
  279. package/.server/server/services/index.js.map +1 -0
  280. package/.server/server/types.js +2 -0
  281. package/.server/server/types.js.map +1 -0
  282. package/.server/server/utils/notify.js +40 -0
  283. package/.server/server/utils/notify.js.map +1 -0
  284. package/.server/server/utils/secure-context/get-trust-store-certs.js +7 -0
  285. package/.server/server/utils/secure-context/get-trust-store-certs.js.map +1 -0
  286. package/.server/server/utils/secure-context/get-trust-store-certs.test.js +14 -0
  287. package/.server/server/utils/secure-context/get-trust-store-certs.test.js.map +1 -0
  288. package/.server/server/utils/utils.js +20 -0
  289. package/.server/server/utils/utils.js.map +1 -0
  290. package/.server/server/utils/utils.test.js +49 -0
  291. package/.server/server/utils/utils.test.js.map +1 -0
  292. package/.server/server/views/404.html +16 -0
  293. package/.server/server/views/500.html +19 -0
  294. package/.server/server/views/components/debug/macro.njk +3 -0
  295. package/.server/server/views/components/debug/template.njk +13 -0
  296. package/.server/server/views/components/service-banner/macro.njk +3 -0
  297. package/.server/server/views/components/service-banner/template.njk +20 -0
  298. package/.server/server/views/components/service-banner/template.test.js +36 -0
  299. package/.server/server/views/components/service-banner/template.test.js.map +1 -0
  300. package/.server/server/views/components/tag-env/macro.njk +3 -0
  301. package/.server/server/views/components/tag-env/template.njk +30 -0
  302. package/.server/server/views/components/tag-env/template.test.js +59 -0
  303. package/.server/server/views/components/tag-env/template.test.js.map +1 -0
  304. package/.server/server/views/confirmation.html +19 -0
  305. package/.server/server/views/help/accessibility-statement.html +58 -0
  306. package/.server/server/views/help/cookie-preferences.html +57 -0
  307. package/.server/server/views/help/cookies.html +71 -0
  308. package/.server/server/views/help/get-support.html +37 -0
  309. package/.server/server/views/help/privacy-notice.html +68 -0
  310. package/.server/server/views/help/terms-and-conditions.html +83 -0
  311. package/.server/server/views/layout.html +199 -0
  312. package/.server/server/views/summary.html +50 -0
  313. package/.server/typings/hapi/index.d.js +2 -0
  314. package/.server/typings/hapi/index.d.js.map +1 -0
  315. package/.server/typings/hapi-tracing/index.d.js +2 -0
  316. package/.server/typings/hapi-tracing/index.d.js.map +1 -0
  317. package/.server/typings/index.d.js +2 -0
  318. package/.server/typings/index.d.js.map +1 -0
  319. package/.server/typings/joi/index.d.js +2 -0
  320. package/.server/typings/joi/index.d.js.map +1 -0
  321. package/Dockerfile +61 -0
  322. package/LICENCE +8 -0
  323. package/Procfile +1 -0
  324. package/README.md +87 -0
  325. package/babel.config.cjs +55 -0
  326. package/compose/aws.env +4 -0
  327. package/compose/start-localstack.sh +26 -0
  328. package/docker-compose.yaml +86 -0
  329. package/globals.d.ts +1 -0
  330. package/jest.config.cjs +54 -0
  331. package/jest.environment.js +4 -0
  332. package/jest.setup.cjs +14 -0
  333. package/package.json +163 -0
  334. package/postcss.config.js +26 -0
  335. package/sonar-project.properties +17 -0
  336. package/src/client/javascripts/application.js +87 -0
  337. package/src/client/javascripts/file-upload.js +386 -0
  338. package/src/client/stylesheets/_code.scss +33 -0
  339. package/src/client/stylesheets/_govuk-frontend.scss +4 -0
  340. package/src/client/stylesheets/_prose.scss +56 -0
  341. package/src/client/stylesheets/_service-banner.scss +24 -0
  342. package/src/client/stylesheets/_summary-list.scss +28 -0
  343. package/src/client/stylesheets/_tag-env.scss +24 -0
  344. package/src/client/stylesheets/application.scss +14 -0
  345. package/src/common/cookies.js +58 -0
  346. package/src/common/cookies.test.js +23 -0
  347. package/src/common/types.js +5 -0
  348. package/src/config/index.ts +271 -0
  349. package/src/index.ts +31 -0
  350. package/src/server/common/helpers/logging/logger-options.test.ts +50 -0
  351. package/src/server/common/helpers/logging/logger-options.ts +46 -0
  352. package/src/server/common/helpers/logging/logger.ts +7 -0
  353. package/src/server/common/helpers/logging/request-logger.ts +9 -0
  354. package/src/server/common/helpers/logging/request-tracing.js +10 -0
  355. package/src/server/common/helpers/redis-client.js +70 -0
  356. package/src/server/constants.js +1 -0
  357. package/src/server/forms/README.md +10 -0
  358. package/src/server/forms/components.json +1015 -0
  359. package/src/server/forms/report-a-terrorist.json +270 -0
  360. package/src/server/forms/runner-components-test.json +365 -0
  361. package/src/server/forms/test.json +581 -0
  362. package/src/server/index.test.ts +582 -0
  363. package/src/server/index.ts +140 -0
  364. package/src/server/plugins/blankie.test.ts +73 -0
  365. package/src/server/plugins/blankie.ts +48 -0
  366. package/src/server/plugins/crumb.ts +20 -0
  367. package/src/server/plugins/engine/README.md +87 -0
  368. package/src/server/plugins/engine/components/AutocompleteField.test.ts +294 -0
  369. package/src/server/plugins/engine/components/AutocompleteField.ts +49 -0
  370. package/src/server/plugins/engine/components/CheckboxesField.test.ts +379 -0
  371. package/src/server/plugins/engine/components/CheckboxesField.ts +106 -0
  372. package/src/server/plugins/engine/components/ComponentBase.ts +97 -0
  373. package/src/server/plugins/engine/components/ComponentCollection.ts +278 -0
  374. package/src/server/plugins/engine/components/DatePartsField.test.ts +822 -0
  375. package/src/server/plugins/engine/components/DatePartsField.ts +264 -0
  376. package/src/server/plugins/engine/components/Details.test.ts +49 -0
  377. package/src/server/plugins/engine/components/Details.ts +30 -0
  378. package/src/server/plugins/engine/components/EmailAddressField.test.ts +395 -0
  379. package/src/server/plugins/engine/components/EmailAddressField.ts +55 -0
  380. package/src/server/plugins/engine/components/FileUploadField.test.ts +778 -0
  381. package/src/server/plugins/engine/components/FileUploadField.ts +262 -0
  382. package/src/server/plugins/engine/components/FormComponent.ts +249 -0
  383. package/src/server/plugins/engine/components/Html.test.ts +48 -0
  384. package/src/server/plugins/engine/components/Html.ts +29 -0
  385. package/src/server/plugins/engine/components/InsetText.test.ts +48 -0
  386. package/src/server/plugins/engine/components/InsetText.ts +27 -0
  387. package/src/server/plugins/engine/components/List.test.ts +76 -0
  388. package/src/server/plugins/engine/components/List.ts +72 -0
  389. package/src/server/plugins/engine/components/ListFormComponent.ts +140 -0
  390. package/src/server/plugins/engine/components/MonthYearField.test.ts +567 -0
  391. package/src/server/plugins/engine/components/MonthYearField.ts +222 -0
  392. package/src/server/plugins/engine/components/MultilineTextField.test.ts +558 -0
  393. package/src/server/plugins/engine/components/MultilineTextField.ts +138 -0
  394. package/src/server/plugins/engine/components/NumberField.test.ts +701 -0
  395. package/src/server/plugins/engine/components/NumberField.ts +163 -0
  396. package/src/server/plugins/engine/components/RadiosField.test.ts +288 -0
  397. package/src/server/plugins/engine/components/RadiosField.ts +24 -0
  398. package/src/server/plugins/engine/components/SelectField.test.ts +288 -0
  399. package/src/server/plugins/engine/components/SelectField.ts +47 -0
  400. package/src/server/plugins/engine/components/SelectionControlField.ts +43 -0
  401. package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +356 -0
  402. package/src/server/plugins/engine/components/TelephoneNumberField.ts +67 -0
  403. package/src/server/plugins/engine/components/TextField.test.ts +489 -0
  404. package/src/server/plugins/engine/components/TextField.ts +96 -0
  405. package/src/server/plugins/engine/components/UkAddressField.test.ts +623 -0
  406. package/src/server/plugins/engine/components/UkAddressField.ts +172 -0
  407. package/src/server/plugins/engine/components/YesNoField.test.ts +248 -0
  408. package/src/server/plugins/engine/components/YesNoField.ts +31 -0
  409. package/src/server/plugins/engine/components/constants.ts +1 -0
  410. package/src/server/plugins/engine/components/helpers.ts +330 -0
  411. package/src/server/plugins/engine/components/index.ts +24 -0
  412. package/src/server/plugins/engine/components/types.ts +117 -0
  413. package/src/server/plugins/engine/configureEnginePlugin.ts +47 -0
  414. package/src/server/plugins/engine/helpers.test.ts +791 -0
  415. package/src/server/plugins/engine/helpers.ts +379 -0
  416. package/src/server/plugins/engine/index.ts +7 -0
  417. package/src/server/plugins/engine/models/FormModel.test.ts +42 -0
  418. package/src/server/plugins/engine/models/FormModel.ts +443 -0
  419. package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
  420. package/src/server/plugins/engine/models/Section.ts +0 -0
  421. package/src/server/plugins/engine/models/SummaryViewModel.test.ts +209 -0
  422. package/src/server/plugins/engine/models/SummaryViewModel.ts +220 -0
  423. package/src/server/plugins/engine/models/index.ts +2 -0
  424. package/src/server/plugins/engine/models/types.ts +114 -0
  425. package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +143 -0
  426. package/src/server/plugins/engine/outputFormatters/human/v1.ts +73 -0
  427. package/src/server/plugins/engine/outputFormatters/index.test.ts +17 -0
  428. package/src/server/plugins/engine/outputFormatters/index.ts +44 -0
  429. package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +229 -0
  430. package/src/server/plugins/engine/outputFormatters/machine/v1.ts +140 -0
  431. package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +229 -0
  432. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +153 -0
  433. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +1108 -0
  434. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +446 -0
  435. package/src/server/plugins/engine/pageControllers/PageController.test.ts +205 -0
  436. package/src/server/plugins/engine/pageControllers/PageController.ts +176 -0
  437. package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +1264 -0
  438. package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +561 -0
  439. package/src/server/plugins/engine/pageControllers/README.md +28 -0
  440. package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +264 -0
  441. package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +458 -0
  442. package/src/server/plugins/engine/pageControllers/StartPageController.ts +18 -0
  443. package/src/server/plugins/engine/pageControllers/StatusPageController.ts +50 -0
  444. package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +261 -0
  445. package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +28 -0
  446. package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +19 -0
  447. package/src/server/plugins/engine/pageControllers/helpers.test.ts +198 -0
  448. package/src/server/plugins/engine/pageControllers/helpers.ts +101 -0
  449. package/src/server/plugins/engine/pageControllers/index.ts +10 -0
  450. package/src/server/plugins/engine/pageControllers/validationOptions.ts +89 -0
  451. package/src/server/plugins/engine/plugin.ts +673 -0
  452. package/src/server/plugins/engine/services/formSubmissionService.js +46 -0
  453. package/src/server/plugins/engine/services/formsService.js +46 -0
  454. package/src/server/plugins/engine/services/formsService.test.js +90 -0
  455. package/src/server/plugins/engine/services/index.js +3 -0
  456. package/src/server/plugins/engine/services/notifyService.test.ts +132 -0
  457. package/src/server/plugins/engine/services/notifyService.ts +64 -0
  458. package/src/server/plugins/engine/services/uploadService.js +60 -0
  459. package/src/server/plugins/engine/types.ts +315 -0
  460. package/src/server/plugins/engine/views/components/autocompletefield.html +5 -0
  461. package/src/server/plugins/engine/views/components/checkboxesfield.html +5 -0
  462. package/src/server/plugins/engine/views/components/datepartsfield.html +5 -0
  463. package/src/server/plugins/engine/views/components/details.html +6 -0
  464. package/src/server/plugins/engine/views/components/emailaddressfield.html +5 -0
  465. package/src/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
  466. package/src/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
  467. package/src/server/plugins/engine/views/components/fileuploadfield.html +24 -0
  468. package/src/server/plugins/engine/views/components/html.html +3 -0
  469. package/src/server/plugins/engine/views/components/insettext.html +7 -0
  470. package/src/server/plugins/engine/views/components/list.html +36 -0
  471. package/src/server/plugins/engine/views/components/monthyearfield.html +5 -0
  472. package/src/server/plugins/engine/views/components/multilinetextfield.html +10 -0
  473. package/src/server/plugins/engine/views/components/numberfield.html +5 -0
  474. package/src/server/plugins/engine/views/components/radiosfield.html +5 -0
  475. package/src/server/plugins/engine/views/components/selectfield.html +5 -0
  476. package/src/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
  477. package/src/server/plugins/engine/views/components/textfield.html +5 -0
  478. package/src/server/plugins/engine/views/components/ukaddressfield.html +25 -0
  479. package/src/server/plugins/engine/views/components/yesnofield.html +5 -0
  480. package/src/server/plugins/engine/views/file-upload.html +45 -0
  481. package/src/server/plugins/engine/views/index.html +39 -0
  482. package/src/server/plugins/engine/views/item-delete.html +56 -0
  483. package/src/server/plugins/engine/views/partials/components.html +6 -0
  484. package/src/server/plugins/engine/views/partials/conditional-components.html +3 -0
  485. package/src/server/plugins/engine/views/partials/debug.html +44 -0
  486. package/src/server/plugins/engine/views/partials/form.html +15 -0
  487. package/src/server/plugins/engine/views/partials/heading.html +16 -0
  488. package/src/server/plugins/engine/views/partials/preview-banner.html +32 -0
  489. package/src/server/plugins/engine/views/partials/preview-banner.test.js +122 -0
  490. package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
  491. package/src/server/plugins/engine/views/repeat-list-summary.html +53 -0
  492. package/src/server/plugins/errorPages.ts +58 -0
  493. package/src/server/plugins/nunjucks/context.js +88 -0
  494. package/src/server/plugins/nunjucks/context.test.js +142 -0
  495. package/src/server/plugins/nunjucks/enviroment.test.js +201 -0
  496. package/src/server/plugins/nunjucks/environment.js +116 -0
  497. package/src/server/plugins/nunjucks/filters/answer.js +27 -0
  498. package/src/server/plugins/nunjucks/filters/answer.test.js +89 -0
  499. package/src/server/plugins/nunjucks/filters/evaluate.js +21 -0
  500. package/src/server/plugins/nunjucks/filters/field.js +28 -0
  501. package/src/server/plugins/nunjucks/filters/field.test.js +75 -0
  502. package/src/server/plugins/nunjucks/filters/highlight.js +11 -0
  503. package/src/server/plugins/nunjucks/filters/href.js +30 -0
  504. package/src/server/plugins/nunjucks/filters/href.test.js +80 -0
  505. package/src/server/plugins/nunjucks/filters/index.js +8 -0
  506. package/src/server/plugins/nunjucks/filters/inspect.js +15 -0
  507. package/src/server/plugins/nunjucks/filters/page.js +24 -0
  508. package/src/server/plugins/nunjucks/filters/page.test.js +65 -0
  509. package/src/server/plugins/nunjucks/index.js +3 -0
  510. package/src/server/plugins/nunjucks/plugin.js +40 -0
  511. package/src/server/plugins/nunjucks/render.js +42 -0
  512. package/src/server/plugins/nunjucks/types.js +40 -0
  513. package/src/server/plugins/pulse.ts +11 -0
  514. package/src/server/plugins/router.ts +201 -0
  515. package/src/server/plugins/session.ts +28 -0
  516. package/src/server/routes/health.js +13 -0
  517. package/src/server/routes/health.test.js +35 -0
  518. package/src/server/routes/index.test.ts +125 -0
  519. package/src/server/routes/index.ts +2 -0
  520. package/src/server/routes/public.ts +47 -0
  521. package/src/server/routes/types.ts +48 -0
  522. package/src/server/schemas/index.ts +34 -0
  523. package/src/server/secure-context.js +43 -0
  524. package/src/server/services/cacheService.test.ts +276 -0
  525. package/src/server/services/cacheService.ts +131 -0
  526. package/src/server/services/httpService.test.js +491 -0
  527. package/src/server/services/httpService.ts +50 -0
  528. package/src/server/services/index.ts +1 -0
  529. package/src/server/types.ts +54 -0
  530. package/src/server/utils/notify.test.ts +37 -0
  531. package/src/server/utils/notify.ts +50 -0
  532. package/src/server/utils/secure-context/get-trust-store-certs.js +11 -0
  533. package/src/server/utils/secure-context/get-trust-store-certs.test.js +19 -0
  534. package/src/server/utils/utils.js +24 -0
  535. package/src/server/utils/utils.test.js +54 -0
  536. package/src/server/views/404.html +16 -0
  537. package/src/server/views/500.html +19 -0
  538. package/src/server/views/components/debug/macro.njk +3 -0
  539. package/src/server/views/components/debug/template.njk +13 -0
  540. package/src/server/views/components/service-banner/macro.njk +3 -0
  541. package/src/server/views/components/service-banner/template.njk +20 -0
  542. package/src/server/views/components/service-banner/template.test.js +43 -0
  543. package/src/server/views/components/tag-env/macro.njk +3 -0
  544. package/src/server/views/components/tag-env/template.njk +30 -0
  545. package/src/server/views/components/tag-env/template.test.js +66 -0
  546. package/src/server/views/confirmation.html +19 -0
  547. package/src/server/views/help/accessibility-statement.html +58 -0
  548. package/src/server/views/help/cookie-preferences.html +57 -0
  549. package/src/server/views/help/cookies.html +71 -0
  550. package/src/server/views/help/get-support.html +37 -0
  551. package/src/server/views/help/privacy-notice.html +68 -0
  552. package/src/server/views/help/terms-and-conditions.html +83 -0
  553. package/src/server/views/layout.html +199 -0
  554. package/src/server/views/summary.html +50 -0
  555. package/src/typings/hapi/index.d.ts +95 -0
  556. package/src/typings/hapi-tracing/index.d.ts +6 -0
  557. package/src/typings/index.d.ts +3 -0
  558. package/src/typings/joi/index.d.ts +22 -0
  559. package/stylelint.config.js +10 -0
  560. package/test/client/javascripts/file-upload.test.js +1197 -0
  561. package/test/condition/checkboxes.test.js +112 -0
  562. package/test/condition/radios.test.js +112 -0
  563. package/test/condition/text.test.js +103 -0
  564. package/test/fixtures/assets-manifest.json +4 -0
  565. package/test/fixtures/form.js +86 -0
  566. package/test/fixtures/index.js +2 -0
  567. package/test/fixtures/list.js +92 -0
  568. package/test/form/cookies.test.js +338 -0
  569. package/test/form/csrf.test.js +87 -0
  570. package/test/form/definitions/basic.js +101 -0
  571. package/test/form/definitions/blank.js +10 -0
  572. package/test/form/definitions/checkboxes.json +88 -0
  573. package/test/form/definitions/components.json +452 -0
  574. package/test/form/definitions/conditional-reveal.js +140 -0
  575. package/test/form/definitions/conditions-basic.js +187 -0
  576. package/test/form/definitions/conditions-complex.js +338 -0
  577. package/test/form/definitions/conditions-dates.js +78 -0
  578. package/test/form/definitions/conditions-escaping.js +143 -0
  579. package/test/form/definitions/demo-cph-number.js +3099 -0
  580. package/test/form/definitions/feedback.json +45 -0
  581. package/test/form/definitions/fields-optional.js +402 -0
  582. package/test/form/definitions/fields-required.js +402 -0
  583. package/test/form/definitions/file-upload-basic.js +44 -0
  584. package/test/form/definitions/file-upload.js +66 -0
  585. package/test/form/definitions/minimal.js +39 -0
  586. package/test/form/definitions/phase-alpha.json +33 -0
  587. package/test/form/definitions/phase-default.json +26 -0
  588. package/test/form/definitions/radios.json +88 -0
  589. package/test/form/definitions/repeat-mixed.js +54 -0
  590. package/test/form/definitions/repeat.js +70 -0
  591. package/test/form/definitions/status.json +126 -0
  592. package/test/form/definitions/templates.js +183 -0
  593. package/test/form/definitions/test.json +581 -0
  594. package/test/form/definitions/text.json +75 -0
  595. package/test/form/definitions/titles.json +170 -0
  596. package/test/form/definitions.test.js +47 -0
  597. package/test/form/exit-page.test.js +210 -0
  598. package/test/form/feedback.test.js +68 -0
  599. package/test/form/fields-optional.test.js +237 -0
  600. package/test/form/fields-required.test.js +294 -0
  601. package/test/form/file-upload.test.js +313 -0
  602. package/test/form/govuk-notify.test.js +449 -0
  603. package/test/form/journey-basic.test.js +444 -0
  604. package/test/form/persist-files.test.js +227 -0
  605. package/test/form/phase-banner.test.js +71 -0
  606. package/test/form/repeat.test.js +628 -0
  607. package/test/form/summary-submission-email.test.js +95 -0
  608. package/test/form/template.test.js +288 -0
  609. package/test/form/titles.test.js +204 -0
  610. package/test/helpers/component-helpers.js +74 -0
  611. package/test/utils/get-cookie.js +42 -0
  612. package/test/utils/get-form-definitions.js +18 -0
  613. package/tmp.pdf +1 -0
  614. package/tsconfig.json +28 -0
  615. package/webpack.config.js +208 -0
@@ -0,0 +1,169 @@
1
+ import { slugSchema } from '@defra/forms-model';
2
+ import Boom from '@hapi/boom';
3
+ import humanizeDuration from 'humanize-duration';
4
+ import Joi from 'joi';
5
+ import { defaultConsent, parseCookieConsent, serialiseCookieConsent } from "../../common/cookies.js";
6
+ import { config } from "../../config/index.js";
7
+ import { isPathRelative } from "./engine/helpers.js";
8
+ import { getFormMetadata } from "./engine/services/formsService.js";
9
+ import { healthRoute, publicRoutes } from "../routes/index.js";
10
+ import { crumbSchema } from "../schemas/index.js";
11
+ const routes = [...publicRoutes, healthRoute];
12
+ export default {
13
+ plugin: {
14
+ name: 'router',
15
+ register: server => {
16
+ server.route(routes);
17
+
18
+ // Shared help routes params schema & options
19
+ const params = Joi.object().keys({
20
+ slug: slugSchema
21
+ }).required();
22
+ const options = {
23
+ validate: {
24
+ params
25
+ }
26
+ };
27
+ server.route({
28
+ method: 'get',
29
+ path: '/help/get-support/{slug}',
30
+ async handler(request, h) {
31
+ const {
32
+ slug
33
+ } = request.params;
34
+ const form = await getFormMetadata(slug);
35
+ return h.view('help/get-support', {
36
+ form
37
+ });
38
+ },
39
+ options
40
+ });
41
+ server.route({
42
+ method: 'get',
43
+ path: '/help/privacy/{slug}',
44
+ async handler(request, h) {
45
+ const {
46
+ slug
47
+ } = request.params;
48
+ const form = await getFormMetadata(slug);
49
+ return h.view('help/privacy-notice', {
50
+ form
51
+ });
52
+ },
53
+ options
54
+ });
55
+ server.route({
56
+ method: 'get',
57
+ path: '/help/cookies/{slug}',
58
+ handler(_request, h) {
59
+ const sessionTimeout = config.get('sessionTimeout');
60
+ const sessionDurationPretty = humanizeDuration(sessionTimeout);
61
+ return h.view('help/cookies', {
62
+ googleAnalyticsContainerId: config.get('googleAnalyticsTrackingId').replace(/^G-/, ''),
63
+ sessionDurationPretty
64
+ });
65
+ },
66
+ options
67
+ });
68
+ server.route({
69
+ method: 'post',
70
+ path: '/help/cookie-preferences/{slug}',
71
+ handler(request, h) {
72
+ const {
73
+ params,
74
+ payload,
75
+ query
76
+ } = request;
77
+ const {
78
+ slug
79
+ } = params;
80
+ let {
81
+ returnUrl
82
+ } = query;
83
+ if (returnUrl && !isPathRelative(returnUrl)) {
84
+ throw Boom.badRequest('Return URL must be relative');
85
+ }
86
+ const analyticsDecision = (payload['cookies[analytics]'] ?? '').toLowerCase();
87
+ const dismissedDecision = (payload['cookies[dismissed]'] ?? '').toLowerCase();
88
+
89
+ // move the parser into our JS code so we can delegate to the frontend in a future iteration
90
+ let cookieConsent;
91
+ if (typeof request.state.cookieConsent === 'string') {
92
+ cookieConsent = parseCookieConsent(request.state.cookieConsent);
93
+ } else {
94
+ cookieConsent = defaultConsent;
95
+ }
96
+ if (analyticsDecision) {
97
+ cookieConsent.analytics = analyticsDecision === 'yes';
98
+ cookieConsent.dismissed = false;
99
+ }
100
+ if (dismissedDecision) {
101
+ cookieConsent.dismissed = dismissedDecision === 'yes';
102
+ }
103
+ if (!returnUrl) {
104
+ cookieConsent.dismissed = true; // this page already has a confirmation message, don't show another
105
+ returnUrl = `/help/cookie-preferences/${slug}`;
106
+ }
107
+ const serialisedCookieConsent = serialiseCookieConsent(cookieConsent);
108
+ h.state('cookieConsent', serialisedCookieConsent);
109
+ return h.redirect(returnUrl);
110
+ },
111
+ options: {
112
+ validate: {
113
+ params,
114
+ payload: Joi.object({
115
+ crumb: crumbSchema,
116
+ 'cookies[analytics]': Joi.string().valid('yes', 'no').optional(),
117
+ 'cookies[dismissed]': Joi.string().valid('yes', 'no').optional()
118
+ }),
119
+ query: Joi.object({
120
+ returnUrl: Joi.string().optional()
121
+ })
122
+ }
123
+ }
124
+ });
125
+ server.route({
126
+ method: 'get',
127
+ path: '/',
128
+ handler() {
129
+ throw Boom.notFound();
130
+ }
131
+ });
132
+ server.route({
133
+ method: 'get',
134
+ path: '/help/cookie-preferences/{slug}',
135
+ handler(request, h) {
136
+ const {
137
+ params
138
+ } = request;
139
+ const {
140
+ slug
141
+ } = params;
142
+ let cookieConsentDismissed = false;
143
+ if (typeof request.state.cookieConsent === 'string') {
144
+ const cookieConsent = parseCookieConsent(request.state.cookieConsent);
145
+ cookieConsentDismissed = cookieConsent.dismissed;
146
+ }
147
+
148
+ // if the user has come back to this page after updating their preferences
149
+ // override the 'dismissed' behaviour to show a success notification instead of
150
+ // the cookie banner
151
+ const showConsentSuccess = cookieConsentDismissed && request.info.referrer.endsWith(`/help/cookie-preferences/${slug}`);
152
+ return h.view('help/cookie-preferences', {
153
+ cookieConsentUpdated: showConsentSuccess
154
+ });
155
+ },
156
+ options
157
+ });
158
+ server.route({
159
+ method: 'get',
160
+ path: '/help/accessibility-statement/{slug}',
161
+ handler(_request, h) {
162
+ return h.view('help/accessibility-statement');
163
+ },
164
+ options
165
+ });
166
+ }
167
+ }
168
+ };
169
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","names":["slugSchema","Boom","humanizeDuration","Joi","defaultConsent","parseCookieConsent","serialiseCookieConsent","config","isPathRelative","getFormMetadata","healthRoute","publicRoutes","crumbSchema","routes","plugin","name","register","server","route","params","object","keys","slug","required","options","validate","method","path","handler","request","h","form","view","_request","sessionTimeout","get","sessionDurationPretty","googleAnalyticsContainerId","replace","payload","query","returnUrl","badRequest","analyticsDecision","toLowerCase","dismissedDecision","cookieConsent","state","analytics","dismissed","serialisedCookieConsent","redirect","crumb","string","valid","optional","notFound","cookieConsentDismissed","showConsentSuccess","info","referrer","endsWith","cookieConsentUpdated"],"sources":["../../../src/server/plugins/router.ts"],"sourcesContent":["import { slugSchema } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport { type ServerRegisterPluginObject } from '@hapi/hapi'\nimport humanizeDuration from 'humanize-duration'\nimport Joi from 'joi'\n\nimport {\n defaultConsent,\n parseCookieConsent,\n serialiseCookieConsent\n} from '~/src/common/cookies.js'\nimport { type CookieConsent } from '~/src/common/types.js'\nimport { config } from '~/src/config/index.js'\nimport { isPathRelative } from '~/src/server/plugins/engine/helpers.js'\nimport { getFormMetadata } from '~/src/server/plugins/engine/services/formsService.js'\nimport { healthRoute, publicRoutes } from '~/src/server/routes/index.js'\nimport { crumbSchema } from '~/src/server/schemas/index.js'\n\nconst routes = [...publicRoutes, healthRoute]\n\nexport default {\n plugin: {\n name: 'router',\n register: (server) => {\n server.route(routes)\n\n // Shared help routes params schema & options\n const params = Joi.object()\n .keys({\n slug: slugSchema\n })\n .required()\n\n const options = {\n validate: {\n params\n }\n }\n\n server.route<{ Params: { slug: string } }>({\n method: 'get',\n path: '/help/get-support/{slug}',\n async handler(request, h) {\n const { slug } = request.params\n const form = await getFormMetadata(slug)\n\n return h.view('help/get-support', { form })\n },\n options\n })\n\n server.route<{ Params: { slug: string } }>({\n method: 'get',\n path: '/help/privacy/{slug}',\n async handler(request, h) {\n const { slug } = request.params\n const form = await getFormMetadata(slug)\n\n return h.view('help/privacy-notice', { form })\n },\n options\n })\n\n server.route<{ Params: { slug: string } }>({\n method: 'get',\n path: '/help/cookies/{slug}',\n handler(_request, h) {\n const sessionTimeout = config.get('sessionTimeout')\n\n const sessionDurationPretty = humanizeDuration(sessionTimeout)\n\n return h.view('help/cookies', {\n googleAnalyticsContainerId: config\n .get('googleAnalyticsTrackingId')\n .replace(/^G-/, ''),\n sessionDurationPretty\n })\n },\n options\n })\n\n server.route<{\n Params: { slug: string }\n Payload: {\n crumb?: string\n 'cookies[analytics]'?: string\n 'cookies[dismissed]'?: string\n }\n Query: { returnUrl?: string }\n }>({\n method: 'post',\n path: '/help/cookie-preferences/{slug}',\n handler(request, h) {\n const { params, payload, query } = request\n const { slug } = params\n let { returnUrl } = query\n\n if (returnUrl && !isPathRelative(returnUrl)) {\n throw Boom.badRequest('Return URL must be relative')\n }\n\n const analyticsDecision = (\n payload['cookies[analytics]'] ?? ''\n ).toLowerCase()\n\n const dismissedDecision = (\n payload['cookies[dismissed]'] ?? ''\n ).toLowerCase()\n\n // move the parser into our JS code so we can delegate to the frontend in a future iteration\n let cookieConsent: CookieConsent\n\n if (typeof request.state.cookieConsent === 'string') {\n cookieConsent = parseCookieConsent(request.state.cookieConsent)\n } else {\n cookieConsent = defaultConsent\n }\n\n if (analyticsDecision) {\n cookieConsent.analytics = analyticsDecision === 'yes'\n cookieConsent.dismissed = false\n }\n\n if (dismissedDecision) {\n cookieConsent.dismissed = dismissedDecision === 'yes'\n }\n\n if (!returnUrl) {\n cookieConsent.dismissed = true // this page already has a confirmation message, don't show another\n returnUrl = `/help/cookie-preferences/${slug}`\n }\n\n const serialisedCookieConsent = serialiseCookieConsent(cookieConsent)\n h.state('cookieConsent', serialisedCookieConsent)\n\n return h.redirect(returnUrl)\n },\n options: {\n validate: {\n params,\n payload: Joi.object({\n crumb: crumbSchema,\n 'cookies[analytics]': Joi.string().valid('yes', 'no').optional(),\n 'cookies[dismissed]': Joi.string().valid('yes', 'no').optional()\n }),\n query: Joi.object({\n returnUrl: Joi.string().optional()\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/',\n handler() {\n throw Boom.notFound()\n }\n })\n\n server.route<{ Params: { slug: string } }>({\n method: 'get',\n path: '/help/cookie-preferences/{slug}',\n handler(request, h) {\n const { params } = request\n const { slug } = params\n let cookieConsentDismissed = false\n\n if (typeof request.state.cookieConsent === 'string') {\n const cookieConsent = parseCookieConsent(\n request.state.cookieConsent\n )\n\n cookieConsentDismissed = cookieConsent.dismissed\n }\n\n // if the user has come back to this page after updating their preferences\n // override the 'dismissed' behaviour to show a success notification instead of\n // the cookie banner\n const showConsentSuccess =\n cookieConsentDismissed &&\n request.info.referrer.endsWith(`/help/cookie-preferences/${slug}`)\n\n return h.view('help/cookie-preferences', {\n cookieConsentUpdated: showConsentSuccess\n })\n },\n options\n })\n\n server.route<{ Params: { slug: string } }>({\n method: 'get',\n path: '/help/accessibility-statement/{slug}',\n handler(_request, h) {\n return h.view('help/accessibility-statement')\n },\n options\n })\n }\n }\n} satisfies ServerRegisterPluginObject<void>\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,28 @@
1
+ import yar from '@hapi/yar';
2
+ import { config } from "../../config/index.js";
3
+
4
+ /**
5
+ * Yar is used for temporary session data but not form submissions, e.g. UI helpers, session flags.
6
+ */
7
+ export default {
8
+ plugin: yar,
9
+ options: {
10
+ maxCookieSize: 0,
11
+ // Always use server-side storage
12
+ cache: {
13
+ cache: 'session',
14
+ segment: 'session',
15
+ expiresIn: config.get('sessionTimeout')
16
+ },
17
+ /**
18
+ * @todo storeBlank is current commented out as it's a minor efficiency gain but breaks the auth tests if enabled.
19
+ * this only seems to affect the auth code, which we might remove anyway so it's temporarily disabled.
20
+ */
21
+ // storeBlank: false,
22
+ cookieOptions: {
23
+ password: config.get('sessionCookiePassword'),
24
+ isSecure: config.get('isProduction')
25
+ }
26
+ }
27
+ };
28
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","names":["yar","config","plugin","options","maxCookieSize","cache","segment","expiresIn","get","cookieOptions","password","isSecure"],"sources":["../../../src/server/plugins/session.ts"],"sourcesContent":["import { type ServerRegisterPluginObject } from '@hapi/hapi'\nimport yar, { type YarOptions } from '@hapi/yar'\n\nimport { config } from '~/src/config/index.js'\n\n/**\n * Yar is used for temporary session data but not form submissions, e.g. UI helpers, session flags.\n */\nexport default {\n plugin: yar,\n options: {\n maxCookieSize: 0, // Always use server-side storage\n cache: {\n cache: 'session',\n segment: 'session',\n expiresIn: config.get('sessionTimeout')\n },\n /**\n * @todo storeBlank is current commented out as it's a minor efficiency gain but breaks the auth tests if enabled.\n * this only seems to affect the auth code, which we might remove anyway so it's temporarily disabled.\n */\n // storeBlank: false,\n cookieOptions: {\n password: config.get('sessionCookiePassword'),\n isSecure: config.get('isProduction')\n }\n }\n} satisfies ServerRegisterPluginObject<YarOptions>\n"],"mappings":"AACA,OAAOA,GAAG,MAA2B,WAAW;AAEhD,SAASC,MAAM;;AAEf;AACA;AACA;AACA,eAAe;EACbC,MAAM,EAAEF,GAAG;EACXG,OAAO,EAAE;IACPC,aAAa,EAAE,CAAC;IAAE;IAClBC,KAAK,EAAE;MACLA,KAAK,EAAE,SAAS;MAChBC,OAAO,EAAE,SAAS;MAClBC,SAAS,EAAEN,MAAM,CAACO,GAAG,CAAC,gBAAgB;IACxC,CAAC;IACD;AACJ;AACA;AACA;IACI;IACAC,aAAa,EAAE;MACbC,QAAQ,EAAET,MAAM,CAACO,GAAG,CAAC,uBAAuB,CAAC;MAC7CG,QAAQ,EAAEV,MAAM,CAACO,GAAG,CAAC,cAAc;IACrC;EACF;AACF,CAAC","ignoreList":[]}
@@ -0,0 +1,15 @@
1
+ import { StatusCodes } from 'http-status-codes';
2
+ export default (/** @type {ServerRoute} */{
3
+ method: 'GET',
4
+ path: '/health',
5
+ handler(_, h) {
6
+ return h.response({
7
+ message: 'success'
8
+ }).code(StatusCodes.OK);
9
+ }
10
+ });
11
+
12
+ /**
13
+ * @import { ServerRoute } from '@hapi/hapi'
14
+ */
15
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","names":["StatusCodes","method","path","handler","_","h","response","message","code","OK"],"sources":["../../../src/server/routes/health.js"],"sourcesContent":["import { StatusCodes } from 'http-status-codes'\n\nexport default /** @type {ServerRoute} */ ({\n method: 'GET',\n path: '/health',\n handler(_, h) {\n return h.response({ message: 'success' }).code(StatusCodes.OK)\n }\n})\n\n/**\n * @import { ServerRoute } from '@hapi/hapi'\n */\n"],"mappings":"AAAA,SAASA,WAAW,QAAQ,mBAAmB;AAE/C,gBAAe,0BAA4B;EACzCC,MAAM,EAAE,KAAK;EACbC,IAAI,EAAE,SAAS;EACfC,OAAOA,CAACC,CAAC,EAAEC,CAAC,EAAE;IACZ,OAAOA,CAAC,CAACC,QAAQ,CAAC;MAAEC,OAAO,EAAE;IAAU,CAAC,CAAC,CAACC,IAAI,CAACR,WAAW,CAACS,EAAE,CAAC;EAChE;AACF,CAAC;;AAED;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,32 @@
1
+ import { createServer } from "../index.js";
2
+ describe('Health check route', () => {
3
+ const startServer = async () => {
4
+ const server = await createServer();
5
+ await server.initialize();
6
+ return server;
7
+ };
8
+
9
+ /** @type {Server} */
10
+ let server;
11
+ afterEach(async () => {
12
+ await server.stop();
13
+ });
14
+ test('/health route response is correct', async () => {
15
+ server = await startServer();
16
+ const options = {
17
+ method: 'GET',
18
+ url: '/health'
19
+ };
20
+ const {
21
+ result
22
+ } = await server.inject(options);
23
+ expect(result).toMatchObject({
24
+ message: 'success'
25
+ });
26
+ });
27
+ });
28
+
29
+ /**
30
+ * @import { Server } from '@hapi/hapi'
31
+ */
32
+ //# sourceMappingURL=health.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.test.js","names":["createServer","describe","startServer","server","initialize","afterEach","stop","test","options","method","url","result","inject","expect","toMatchObject","message"],"sources":["../../../src/server/routes/health.test.js"],"sourcesContent":["import { createServer } from '~/src/server/index.js'\n\ndescribe('Health check route', () => {\n const startServer = async () => {\n const server = await createServer()\n await server.initialize()\n return server\n }\n\n /** @type {Server} */\n let server\n\n afterEach(async () => {\n await server.stop()\n })\n\n test('/health route response is correct', async () => {\n server = await startServer()\n\n const options = {\n method: 'GET',\n url: '/health'\n }\n\n const { result } = await server.inject(options)\n\n expect(result).toMatchObject({\n message: 'success'\n })\n })\n})\n\n/**\n * @import { Server } from '@hapi/hapi'\n */\n"],"mappings":"AAAA,SAASA,YAAY;AAErBC,QAAQ,CAAC,oBAAoB,EAAE,MAAM;EACnC,MAAMC,WAAW,GAAG,MAAAA,CAAA,KAAY;IAC9B,MAAMC,MAAM,GAAG,MAAMH,YAAY,CAAC,CAAC;IACnC,MAAMG,MAAM,CAACC,UAAU,CAAC,CAAC;IACzB,OAAOD,MAAM;EACf,CAAC;;EAED;EACA,IAAIA,MAAM;EAEVE,SAAS,CAAC,YAAY;IACpB,MAAMF,MAAM,CAACG,IAAI,CAAC,CAAC;EACrB,CAAC,CAAC;EAEFC,IAAI,CAAC,mCAAmC,EAAE,YAAY;IACpDJ,MAAM,GAAG,MAAMD,WAAW,CAAC,CAAC;IAE5B,MAAMM,OAAO,GAAG;MACdC,MAAM,EAAE,KAAK;MACbC,GAAG,EAAE;IACP,CAAC;IAED,MAAM;MAAEC;IAAO,CAAC,GAAG,MAAMR,MAAM,CAACS,MAAM,CAACJ,OAAO,CAAC;IAE/CK,MAAM,CAACF,MAAM,CAAC,CAACG,aAAa,CAAC;MAC3BC,OAAO,EAAE;IACX,CAAC,CAAC;EACJ,CAAC,CAAC;AACJ,CAAC,CAAC;;AAEF;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ export { default as publicRoutes } from "./public.js";
2
+ export { default as healthRoute } from "./health.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["default","publicRoutes","healthRoute"],"sources":["../../../src/server/routes/index.ts"],"sourcesContent":["export { default as publicRoutes } from '~/src/server/routes/public.js'\nexport { default as healthRoute } from '~/src/server/routes/health.js'\n"],"mappings":"AAAA,SAASA,OAAO,IAAIC,YAAY;AAChC,SAASD,OAAO,IAAIE,WAAW","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ import { join } from 'node:path';
2
+ import { config } from "../../config/index.js";
3
+ export default [{
4
+ from: '/javascripts/{path*}',
5
+ to: join(config.get('publicDir'), 'javascripts'),
6
+ immutable: true
7
+ }, {
8
+ from: '/stylesheets/{path*}',
9
+ to: join(config.get('publicDir'), 'stylesheets'),
10
+ immutable: true
11
+ }, {
12
+ from: '/assets/fonts/{path*}',
13
+ to: join(config.get('publicDir'), 'assets/fonts'),
14
+ immutable: true
15
+ }, {
16
+ from: '/assets/{path*}',
17
+ to: join(config.get('publicDir'), 'assets'),
18
+ immutable: false
19
+ }].map(options => {
20
+ return {
21
+ method: 'GET',
22
+ path: options.from,
23
+ options: {
24
+ cache: {
25
+ // Historically, an infinite max-age is the 32-bit maximum 2,147,483,648
26
+ // https://datatracker.ietf.org/doc/html/rfc9111#section-1.2.2
27
+ otherwise: options.immutable ? 'public, max-age=2147483648, immutable' : 'public, max-age=0, must-revalidate'
28
+ },
29
+ handler: {
30
+ directory: {
31
+ path: options.to
32
+ }
33
+ }
34
+ }
35
+ };
36
+ });
37
+ //# sourceMappingURL=public.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public.js","names":["join","config","from","to","get","immutable","map","options","method","path","cache","otherwise","handler","directory"],"sources":["../../../src/server/routes/public.ts"],"sourcesContent":["import { join } from 'node:path'\n\nimport { type HandlerDecorations, type ServerRoute } from '@hapi/hapi'\n\nimport { config } from '~/src/config/index.js'\n\nexport default [\n {\n from: '/javascripts/{path*}',\n to: join(config.get('publicDir'), 'javascripts'),\n immutable: true\n },\n {\n from: '/stylesheets/{path*}',\n to: join(config.get('publicDir'), 'stylesheets'),\n immutable: true\n },\n {\n from: '/assets/fonts/{path*}',\n to: join(config.get('publicDir'), 'assets/fonts'),\n immutable: true\n },\n {\n from: '/assets/{path*}',\n to: join(config.get('publicDir'), 'assets'),\n immutable: false\n }\n].map((options) => {\n return {\n method: 'GET',\n path: options.from,\n options: {\n cache: {\n // Historically, an infinite max-age is the 32-bit maximum 2,147,483,648\n // https://datatracker.ietf.org/doc/html/rfc9111#section-1.2.2\n otherwise: options.immutable\n ? 'public, max-age=2147483648, immutable'\n : 'public, max-age=0, must-revalidate'\n },\n handler: {\n directory: {\n path: options.to\n }\n } satisfies HandlerDecorations\n }\n } satisfies ServerRoute\n})\n"],"mappings":"AAAA,SAASA,IAAI,QAAQ,WAAW;AAIhC,SAASC,MAAM;AAEf,eAAe,CACb;EACEC,IAAI,EAAE,sBAAsB;EAC5BC,EAAE,EAAEH,IAAI,CAACC,MAAM,CAACG,GAAG,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;EAChDC,SAAS,EAAE;AACb,CAAC,EACD;EACEH,IAAI,EAAE,sBAAsB;EAC5BC,EAAE,EAAEH,IAAI,CAACC,MAAM,CAACG,GAAG,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;EAChDC,SAAS,EAAE;AACb,CAAC,EACD;EACEH,IAAI,EAAE,uBAAuB;EAC7BC,EAAE,EAAEH,IAAI,CAACC,MAAM,CAACG,GAAG,CAAC,WAAW,CAAC,EAAE,cAAc,CAAC;EACjDC,SAAS,EAAE;AACb,CAAC,EACD;EACEH,IAAI,EAAE,iBAAiB;EACvBC,EAAE,EAAEH,IAAI,CAACC,MAAM,CAACG,GAAG,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC;EAC3CC,SAAS,EAAE;AACb,CAAC,CACF,CAACC,GAAG,CAAEC,OAAO,IAAK;EACjB,OAAO;IACLC,MAAM,EAAE,KAAK;IACbC,IAAI,EAAEF,OAAO,CAACL,IAAI;IAClBK,OAAO,EAAE;MACPG,KAAK,EAAE;QACL;QACA;QACAC,SAAS,EAAEJ,OAAO,CAACF,SAAS,GACxB,uCAAuC,GACvC;MACN,CAAC;MACDO,OAAO,EAAE;QACPC,SAAS,EAAE;UACTJ,IAAI,EAAEF,OAAO,CAACJ;QAChB;MACF;IACF;EACF,CAAC;AACH,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,14 @@
1
+ export let FormAction = /*#__PURE__*/function (FormAction) {
2
+ FormAction["Continue"] = "continue";
3
+ FormAction["Validate"] = "validate";
4
+ FormAction["Delete"] = "delete";
5
+ FormAction["AddAnother"] = "add-another";
6
+ FormAction["Send"] = "send";
7
+ return FormAction;
8
+ }({});
9
+ export let FormStatus = /*#__PURE__*/function (FormStatus) {
10
+ FormStatus["Draft"] = "draft";
11
+ FormStatus["Live"] = "live";
12
+ return FormStatus;
13
+ }({});
14
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","names":["FormAction","FormStatus"],"sources":["../../../src/server/routes/types.ts"],"sourcesContent":["import { type ReqRefDefaults, type Request } from '@hapi/hapi'\n\nimport { type FormPayload } from '~/src/server/plugins/engine/types.js'\n\nexport interface FormQuery extends Partial<Record<string, string>> {\n /**\n * Allow preview URL direct access without relevant page checks\n */\n force?: string\n\n /**\n * Redirect location after 'continue' form action\n */\n returnUrl?: string\n}\n\nexport interface FormParams extends Partial<Record<string, string>> {\n path: string\n slug: string\n state?: FormStatus\n}\n\nexport interface FormRequestRefs\n extends Omit<ReqRefDefaults, 'Params' | 'Payload' | 'Query'> {\n Params: FormParams\n Payload: object | undefined\n Query: FormQuery\n}\n\nexport interface FormRequestPayloadRefs extends FormRequestRefs {\n Payload: FormPayload\n}\n\nexport type FormRequest = Request<FormRequestRefs>\nexport type FormRequestPayload = Request<FormRequestPayloadRefs>\n\nexport enum FormAction {\n Continue = 'continue',\n Validate = 'validate',\n Delete = 'delete',\n AddAnother = 'add-another',\n Send = 'send'\n}\n\nexport enum FormStatus {\n Draft = 'draft',\n Live = 'live'\n}\n"],"mappings":"AAoCA,WAAYA,UAAU,0BAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAA,OAAVA,UAAU;AAAA;AAQtB,WAAYC,UAAU,0BAAVA,UAAU;EAAVA,UAAU;EAAVA,UAAU;EAAA,OAAVA,UAAU;AAAA","ignoreList":[]}
@@ -0,0 +1,15 @@
1
+ import Joi from 'joi';
2
+ import { FormAction, FormStatus } from "../routes/types.js";
3
+ export const stateSchema = Joi.string().valid(FormStatus.Draft, FormStatus.Live).required();
4
+ export const actionSchema = Joi.string().valid(FormAction.Continue, FormAction.Validate, FormAction.Delete, FormAction.AddAnother, FormAction.Send).default(FormAction.Validate).optional();
5
+ export const pathSchema = Joi.string().required();
6
+ export const itemIdSchema = Joi.string().uuid().required();
7
+ export const crumbSchema = Joi.string().optional().allow('');
8
+ export const confirmSchema = Joi.boolean().empty(false);
9
+ export const paramsSchema = Joi.object().keys({
10
+ action: actionSchema,
11
+ confirm: confirmSchema,
12
+ crumb: crumbSchema,
13
+ itemId: itemIdSchema.optional()
14
+ }).default({}).optional();
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["Joi","FormAction","FormStatus","stateSchema","string","valid","Draft","Live","required","actionSchema","Continue","Validate","Delete","AddAnother","Send","default","optional","pathSchema","itemIdSchema","uuid","crumbSchema","allow","confirmSchema","boolean","empty","paramsSchema","object","keys","action","confirm","crumb","itemId"],"sources":["../../../src/server/schemas/index.ts"],"sourcesContent":["import Joi from 'joi'\n\nimport { type FormParams } from '~/src/server/plugins/engine/types.js'\nimport { FormAction, FormStatus } from '~/src/server/routes/types.js'\n\nexport const stateSchema = Joi.string<FormStatus>()\n .valid(FormStatus.Draft, FormStatus.Live)\n .required()\n\nexport const actionSchema = Joi.string<FormAction>()\n .valid(\n FormAction.Continue,\n FormAction.Validate,\n FormAction.Delete,\n FormAction.AddAnother,\n FormAction.Send\n )\n .default(FormAction.Validate)\n .optional()\n\nexport const pathSchema = Joi.string().required()\nexport const itemIdSchema = Joi.string().uuid().required()\nexport const crumbSchema = Joi.string().optional().allow('')\nexport const confirmSchema = Joi.boolean().empty(false)\n\nexport const paramsSchema = Joi.object<FormParams>()\n .keys({\n action: actionSchema,\n confirm: confirmSchema,\n crumb: crumbSchema,\n itemId: itemIdSchema.optional()\n })\n .default({})\n .optional()\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,KAAK;AAGrB,SAASC,UAAU,EAAEC,UAAU;AAE/B,OAAO,MAAMC,WAAW,GAAGH,GAAG,CAACI,MAAM,CAAa,CAAC,CAChDC,KAAK,CAACH,UAAU,CAACI,KAAK,EAAEJ,UAAU,CAACK,IAAI,CAAC,CACxCC,QAAQ,CAAC,CAAC;AAEb,OAAO,MAAMC,YAAY,GAAGT,GAAG,CAACI,MAAM,CAAa,CAAC,CACjDC,KAAK,CACJJ,UAAU,CAACS,QAAQ,EACnBT,UAAU,CAACU,QAAQ,EACnBV,UAAU,CAACW,MAAM,EACjBX,UAAU,CAACY,UAAU,EACrBZ,UAAU,CAACa,IACb,CAAC,CACAC,OAAO,CAACd,UAAU,CAACU,QAAQ,CAAC,CAC5BK,QAAQ,CAAC,CAAC;AAEb,OAAO,MAAMC,UAAU,GAAGjB,GAAG,CAACI,MAAM,CAAC,CAAC,CAACI,QAAQ,CAAC,CAAC;AACjD,OAAO,MAAMU,YAAY,GAAGlB,GAAG,CAACI,MAAM,CAAC,CAAC,CAACe,IAAI,CAAC,CAAC,CAACX,QAAQ,CAAC,CAAC;AAC1D,OAAO,MAAMY,WAAW,GAAGpB,GAAG,CAACI,MAAM,CAAC,CAAC,CAACY,QAAQ,CAAC,CAAC,CAACK,KAAK,CAAC,EAAE,CAAC;AAC5D,OAAO,MAAMC,aAAa,GAAGtB,GAAG,CAACuB,OAAO,CAAC,CAAC,CAACC,KAAK,CAAC,KAAK,CAAC;AAEvD,OAAO,MAAMC,YAAY,GAAGzB,GAAG,CAAC0B,MAAM,CAAa,CAAC,CACjDC,IAAI,CAAC;EACJC,MAAM,EAAEnB,YAAY;EACpBoB,OAAO,EAAEP,aAAa;EACtBQ,KAAK,EAAEV,WAAW;EAClBW,MAAM,EAAEb,YAAY,CAACF,QAAQ,CAAC;AAChC,CAAC,CAAC,CACDD,OAAO,CAAC,CAAC,CAAC,CAAC,CACXC,QAAQ,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,36 @@
1
+ import tls from 'node:tls';
2
+ import { getTrustStoreCerts } from "./utils/secure-context/get-trust-store-certs.js";
3
+
4
+ /**
5
+ * @type {SecureContext}
6
+ */
7
+ export let secureContext;
8
+
9
+ /**
10
+ * Prepares the TLS secure context
11
+ * @param {Server} server
12
+ * @returns
13
+ */
14
+ export function prepareSecureContext(server) {
15
+ const originalCreateSecureContext = tls.createSecureContext;
16
+ tls.createSecureContext = function (options = {}) {
17
+ const trustStoreCerts = getTrustStoreCerts(process.env);
18
+ if (!trustStoreCerts.length) {
19
+ server.logger.info('Could not find any TRUSTSTORE_ certificates');
20
+ }
21
+ const originalSecureContext = originalCreateSecureContext(options);
22
+ trustStoreCerts.forEach(cert => {
23
+ // eslint-disable-next-line -- Node.js API not documented
24
+ originalSecureContext.context.addCACert(cert);
25
+ });
26
+ return originalSecureContext;
27
+ };
28
+ secureContext = tls.createSecureContext();
29
+ return secureContext;
30
+ }
31
+
32
+ /**
33
+ * @import { Server } from '@hapi/hapi'
34
+ * @import { SecureContext } from 'node:tls'
35
+ */
36
+ //# sourceMappingURL=secure-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secure-context.js","names":["tls","getTrustStoreCerts","secureContext","prepareSecureContext","server","originalCreateSecureContext","createSecureContext","options","trustStoreCerts","process","env","length","logger","info","originalSecureContext","forEach","cert","context","addCACert"],"sources":["../../src/server/secure-context.js"],"sourcesContent":["import tls from 'node:tls'\n\nimport { getTrustStoreCerts } from '~/src/server/utils/secure-context/get-trust-store-certs.js'\n\n/**\n * @type {SecureContext}\n */\nexport let secureContext\n\n/**\n * Prepares the TLS secure context\n * @param {Server} server\n * @returns\n */\nexport function prepareSecureContext(server) {\n const originalCreateSecureContext = tls.createSecureContext\n\n tls.createSecureContext = function (options = {}) {\n const trustStoreCerts = getTrustStoreCerts(process.env)\n\n if (!trustStoreCerts.length) {\n server.logger.info('Could not find any TRUSTSTORE_ certificates')\n }\n\n const originalSecureContext = originalCreateSecureContext(options)\n\n trustStoreCerts.forEach((cert) => {\n // eslint-disable-next-line -- Node.js API not documented\n originalSecureContext.context.addCACert(cert)\n })\n\n return originalSecureContext\n }\n\n secureContext = tls.createSecureContext()\n\n return secureContext\n}\n\n/**\n * @import { Server } from '@hapi/hapi'\n * @import { SecureContext } from 'node:tls'\n */\n"],"mappings":"AAAA,OAAOA,GAAG,MAAM,UAAU;AAE1B,SAASC,kBAAkB;;AAE3B;AACA;AACA;AACA,OAAO,IAAIC,aAAa;;AAExB;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,oBAAoBA,CAACC,MAAM,EAAE;EAC3C,MAAMC,2BAA2B,GAAGL,GAAG,CAACM,mBAAmB;EAE3DN,GAAG,CAACM,mBAAmB,GAAG,UAAUC,OAAO,GAAG,CAAC,CAAC,EAAE;IAChD,MAAMC,eAAe,GAAGP,kBAAkB,CAACQ,OAAO,CAACC,GAAG,CAAC;IAEvD,IAAI,CAACF,eAAe,CAACG,MAAM,EAAE;MAC3BP,MAAM,CAACQ,MAAM,CAACC,IAAI,CAAC,6CAA6C,CAAC;IACnE;IAEA,MAAMC,qBAAqB,GAAGT,2BAA2B,CAACE,OAAO,CAAC;IAElEC,eAAe,CAACO,OAAO,CAAEC,IAAI,IAAK;MAChC;MACAF,qBAAqB,CAACG,OAAO,CAACC,SAAS,CAACF,IAAI,CAAC;IAC/C,CAAC,CAAC;IAEF,OAAOF,qBAAqB;EAC9B,CAAC;EAEDZ,aAAa,GAAGF,GAAG,CAACM,mBAAmB,CAAC,CAAC;EAEzC,OAAOJ,aAAa;AACtB;;AAEA;AACA;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,85 @@
1
+ import * as Hoek from '@hapi/hoek';
2
+ import { config } from "../../config/index.js";
3
+ const partition = 'cache';
4
+ var ADDITIONAL_IDENTIFIER = /*#__PURE__*/function (ADDITIONAL_IDENTIFIER) {
5
+ ADDITIONAL_IDENTIFIER["Confirmation"] = ":confirmation";
6
+ return ADDITIONAL_IDENTIFIER;
7
+ }(ADDITIONAL_IDENTIFIER || {});
8
+ export class CacheService {
9
+ /**
10
+ * This service is responsible for getting, storing or deleting a user's session data in the cache. This service has been registered by {@link createServer}
11
+ */
12
+ cache;
13
+ logger;
14
+ constructor(server) {
15
+ this.cache = server.cache({
16
+ cache: 'session',
17
+ segment: 'formSubmission'
18
+ });
19
+ this.logger = server.logger;
20
+ }
21
+ async getState(request) {
22
+ const cached = await this.cache.get(this.Key(request));
23
+ return cached || {};
24
+ }
25
+ async setState(request, state) {
26
+ const key = this.Key(request);
27
+ const ttl = config.get('sessionTimeout');
28
+ await this.cache.set(key, state, ttl);
29
+ return this.getState(request);
30
+ }
31
+ async getConfirmationState(request) {
32
+ const key = this.Key(request, ADDITIONAL_IDENTIFIER.Confirmation);
33
+ const value = await this.cache.get(key);
34
+ return value || {};
35
+ }
36
+ async setConfirmationState(request, confirmationState) {
37
+ const key = this.Key(request, ADDITIONAL_IDENTIFIER.Confirmation);
38
+ const ttl = config.get('confirmationSessionTimeout');
39
+ return this.cache.set(key, confirmationState, ttl);
40
+ }
41
+ async clearState(request) {
42
+ if (request.yar.id) {
43
+ await this.cache.drop(this.Key(request));
44
+ }
45
+ }
46
+ getFlash(request) {
47
+ const key = this.Key(request);
48
+ const messages = request.yar.flash(key.id);
49
+ if (Array.isArray(messages) && messages.length) {
50
+ return messages.at(0);
51
+ }
52
+ }
53
+ setFlash(request, message) {
54
+ const key = this.Key(request);
55
+ request.yar.flash(key.id, message);
56
+ }
57
+
58
+ /**
59
+ * The key used to store user session data against.
60
+ * If there are multiple forms on the same runner instance, for example `form-a` and `form-a-feedback` this will prevent CacheService from clearing data from `form-a` if a user gave feedback before they finished `form-a`
61
+ * @param request - hapi request object
62
+ * @param additionalIdentifier - appended to the id
63
+ */
64
+ Key(request, additionalIdentifier) {
65
+ if (!request.yar.id) {
66
+ throw Error('No session ID found');
67
+ }
68
+ return {
69
+ segment: partition,
70
+ id: `${request.yar.id}:${request.params.state ?? ''}:${request.params.slug ?? ''}:${additionalIdentifier ?? ''}`
71
+ };
72
+ }
73
+ }
74
+
75
+ /**
76
+ * State merge helper
77
+ * 1. Merges objects (form fields)
78
+ * 2. Overwrites arrays
79
+ */
80
+ export function merge(state, update) {
81
+ return Hoek.merge(state, update, {
82
+ mergeArrays: false
83
+ });
84
+ }
85
+ //# sourceMappingURL=cacheService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cacheService.js","names":["Hoek","config","partition","ADDITIONAL_IDENTIFIER","CacheService","cache","logger","constructor","server","segment","getState","request","cached","get","Key","setState","state","key","ttl","set","getConfirmationState","Confirmation","value","setConfirmationState","confirmationState","clearState","yar","id","drop","getFlash","messages","flash","Array","isArray","length","at","setFlash","message","additionalIdentifier","Error","params","slug","merge","update","mergeArrays"],"sources":["../../../src/server/services/cacheService.ts"],"sourcesContent":["import { type Request, type Server } from '@hapi/hapi'\nimport * as Hoek from '@hapi/hoek'\n\nimport { config } from '~/src/config/index.js'\nimport { type createServer } from '~/src/server/index.js'\nimport {\n type FormPayload,\n type FormState,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload\n} from '~/src/server/routes/types.js'\n\nconst partition = 'cache'\n\nenum ADDITIONAL_IDENTIFIER {\n Confirmation = ':confirmation'\n}\n\nexport class CacheService {\n /**\n * This service is responsible for getting, storing or deleting a user's session data in the cache. This service has been registered by {@link createServer}\n */\n cache\n logger: Server['logger']\n\n constructor(server: Server) {\n this.cache = server.cache({ cache: 'session', segment: 'formSubmission' })\n this.logger = server.logger\n }\n\n async getState(\n request: Request | FormRequest | FormRequestPayload\n ): Promise<FormSubmissionState> {\n const cached = await this.cache.get(this.Key(request))\n\n return cached || {}\n }\n\n async setState(\n request: FormRequest | FormRequestPayload,\n state: FormSubmissionState\n ) {\n const key = this.Key(request)\n const ttl = config.get('sessionTimeout')\n\n await this.cache.set(key, state, ttl)\n return this.getState(request)\n }\n\n async getConfirmationState(\n request: FormRequest | FormRequestPayload\n ): Promise<{ confirmed?: true }> {\n const key = this.Key(request, ADDITIONAL_IDENTIFIER.Confirmation)\n const value = await this.cache.get(key)\n\n return value || {}\n }\n\n async setConfirmationState(\n request: FormRequest | FormRequestPayload,\n confirmationState: { confirmed?: true }\n ) {\n const key = this.Key(request, ADDITIONAL_IDENTIFIER.Confirmation)\n const ttl = config.get('confirmationSessionTimeout')\n\n return this.cache.set(key, confirmationState, ttl)\n }\n\n async clearState(request: FormRequest | FormRequestPayload) {\n if (request.yar.id) {\n await this.cache.drop(this.Key(request))\n }\n }\n\n getFlash(\n request: FormRequest | FormRequestPayload\n ): { errors: FormSubmissionError[] } | undefined {\n const key = this.Key(request)\n const messages = request.yar.flash(key.id)\n\n if (Array.isArray(messages) && messages.length) {\n return messages.at(0) as { errors: FormSubmissionError[] }\n }\n }\n\n setFlash(\n request: FormRequest | FormRequestPayload,\n message: { errors: FormSubmissionError[] }\n ) {\n const key = this.Key(request)\n\n request.yar.flash(key.id, message)\n }\n\n /**\n * The key used to store user session data against.\n * If there are multiple forms on the same runner instance, for example `form-a` and `form-a-feedback` this will prevent CacheService from clearing data from `form-a` if a user gave feedback before they finished `form-a`\n * @param request - hapi request object\n * @param additionalIdentifier - appended to the id\n */\n Key(\n request: Request | FormRequest | FormRequestPayload,\n additionalIdentifier?: ADDITIONAL_IDENTIFIER\n ) {\n if (!request.yar.id) {\n throw Error('No session ID found')\n }\n return {\n segment: partition,\n id: `${request.yar.id}:${request.params.state ?? ''}:${request.params.slug ?? ''}:${additionalIdentifier ?? ''}`\n }\n }\n}\n\n/**\n * State merge helper\n * 1. Merges objects (form fields)\n * 2. Overwrites arrays\n */\nexport function merge<StateType extends FormState | FormPayload>(\n state: StateType,\n update: object\n): StateType {\n return Hoek.merge(state, update, {\n mergeArrays: false\n })\n}\n"],"mappings":"AACA,OAAO,KAAKA,IAAI,MAAM,YAAY;AAElC,SAASC,MAAM;AAaf,MAAMC,SAAS,GAAG,OAAO;AAAA,IAEpBC,qBAAqB,0BAArBA,qBAAqB;EAArBA,qBAAqB;EAAA,OAArBA,qBAAqB;AAAA,EAArBA,qBAAqB;AAI1B,OAAO,MAAMC,YAAY,CAAC;EACxB;AACF;AACA;EACEC,KAAK;EACLC,MAAM;EAENC,WAAWA,CAACC,MAAc,EAAE;IAC1B,IAAI,CAACH,KAAK,GAAGG,MAAM,CAACH,KAAK,CAAC;MAAEA,KAAK,EAAE,SAAS;MAAEI,OAAO,EAAE;IAAiB,CAAC,CAAC;IAC1E,IAAI,CAACH,MAAM,GAAGE,MAAM,CAACF,MAAM;EAC7B;EAEA,MAAMI,QAAQA,CACZC,OAAmD,EACrB;IAC9B,MAAMC,MAAM,GAAG,MAAM,IAAI,CAACP,KAAK,CAACQ,GAAG,CAAC,IAAI,CAACC,GAAG,CAACH,OAAO,CAAC,CAAC;IAEtD,OAAOC,MAAM,IAAI,CAAC,CAAC;EACrB;EAEA,MAAMG,QAAQA,CACZJ,OAAyC,EACzCK,KAA0B,EAC1B;IACA,MAAMC,GAAG,GAAG,IAAI,CAACH,GAAG,CAACH,OAAO,CAAC;IAC7B,MAAMO,GAAG,GAAGjB,MAAM,CAACY,GAAG,CAAC,gBAAgB,CAAC;IAExC,MAAM,IAAI,CAACR,KAAK,CAACc,GAAG,CAACF,GAAG,EAAED,KAAK,EAAEE,GAAG,CAAC;IACrC,OAAO,IAAI,CAACR,QAAQ,CAACC,OAAO,CAAC;EAC/B;EAEA,MAAMS,oBAAoBA,CACxBT,OAAyC,EACV;IAC/B,MAAMM,GAAG,GAAG,IAAI,CAACH,GAAG,CAACH,OAAO,EAAER,qBAAqB,CAACkB,YAAY,CAAC;IACjE,MAAMC,KAAK,GAAG,MAAM,IAAI,CAACjB,KAAK,CAACQ,GAAG,CAACI,GAAG,CAAC;IAEvC,OAAOK,KAAK,IAAI,CAAC,CAAC;EACpB;EAEA,MAAMC,oBAAoBA,CACxBZ,OAAyC,EACzCa,iBAAuC,EACvC;IACA,MAAMP,GAAG,GAAG,IAAI,CAACH,GAAG,CAACH,OAAO,EAAER,qBAAqB,CAACkB,YAAY,CAAC;IACjE,MAAMH,GAAG,GAAGjB,MAAM,CAACY,GAAG,CAAC,4BAA4B,CAAC;IAEpD,OAAO,IAAI,CAACR,KAAK,CAACc,GAAG,CAACF,GAAG,EAAEO,iBAAiB,EAAEN,GAAG,CAAC;EACpD;EAEA,MAAMO,UAAUA,CAACd,OAAyC,EAAE;IAC1D,IAAIA,OAAO,CAACe,GAAG,CAACC,EAAE,EAAE;MAClB,MAAM,IAAI,CAACtB,KAAK,CAACuB,IAAI,CAAC,IAAI,CAACd,GAAG,CAACH,OAAO,CAAC,CAAC;IAC1C;EACF;EAEAkB,QAAQA,CACNlB,OAAyC,EACM;IAC/C,MAAMM,GAAG,GAAG,IAAI,CAACH,GAAG,CAACH,OAAO,CAAC;IAC7B,MAAMmB,QAAQ,GAAGnB,OAAO,CAACe,GAAG,CAACK,KAAK,CAACd,GAAG,CAACU,EAAE,CAAC;IAE1C,IAAIK,KAAK,CAACC,OAAO,CAACH,QAAQ,CAAC,IAAIA,QAAQ,CAACI,MAAM,EAAE;MAC9C,OAAOJ,QAAQ,CAACK,EAAE,CAAC,CAAC,CAAC;IACvB;EACF;EAEAC,QAAQA,CACNzB,OAAyC,EACzC0B,OAA0C,EAC1C;IACA,MAAMpB,GAAG,GAAG,IAAI,CAACH,GAAG,CAACH,OAAO,CAAC;IAE7BA,OAAO,CAACe,GAAG,CAACK,KAAK,CAACd,GAAG,CAACU,EAAE,EAAEU,OAAO,CAAC;EACpC;;EAEA;AACF;AACA;AACA;AACA;AACA;EACEvB,GAAGA,CACDH,OAAmD,EACnD2B,oBAA4C,EAC5C;IACA,IAAI,CAAC3B,OAAO,CAACe,GAAG,CAACC,EAAE,EAAE;MACnB,MAAMY,KAAK,CAAC,qBAAqB,CAAC;IACpC;IACA,OAAO;MACL9B,OAAO,EAAEP,SAAS;MAClByB,EAAE,EAAE,GAAGhB,OAAO,CAACe,GAAG,CAACC,EAAE,IAAIhB,OAAO,CAAC6B,MAAM,CAACxB,KAAK,IAAI,EAAE,IAAIL,OAAO,CAAC6B,MAAM,CAACC,IAAI,IAAI,EAAE,IAAIH,oBAAoB,IAAI,EAAE;IAChH,CAAC;EACH;AACF;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,KAAKA,CACnB1B,KAAgB,EAChB2B,MAAc,EACH;EACX,OAAO3C,IAAI,CAAC0C,KAAK,CAAC1B,KAAK,EAAE2B,MAAM,EAAE;IAC/BC,WAAW,EAAE;EACf,CAAC,CAAC;AACJ","ignoreList":[]}
@@ -0,0 +1,44 @@
1
+ import Wreck from '@hapi/wreck';
2
+ import { applyTraceHeaders } from "../utils/utils.js";
3
+ export const request = async (method, url, options) => {
4
+ const headers = applyTraceHeaders(options?.headers);
5
+ const mergedOptions = {
6
+ ...options,
7
+ headers
8
+ };
9
+ const {
10
+ res,
11
+ payload
12
+ } = await Wreck[method](url, mergedOptions);
13
+ if (!res.statusCode || res.statusCode < 200 || res.statusCode > 299) {
14
+ return {
15
+ res,
16
+ error: payload || new Error('Unknown error')
17
+ };
18
+ }
19
+ return {
20
+ res,
21
+ payload
22
+ };
23
+ };
24
+ export const get = (url, options) => {
25
+ return request('get', url, options);
26
+ };
27
+ export const getJson = url => {
28
+ return get(url, {
29
+ json: true
30
+ });
31
+ };
32
+ export const post = (url, options) => {
33
+ return request('post', url, options);
34
+ };
35
+ export const postJson = (url, options) => {
36
+ return post(url, {
37
+ ...options,
38
+ json: true
39
+ });
40
+ };
41
+ export const put = (url, options) => {
42
+ return request('put', url, options);
43
+ };
44
+ //# sourceMappingURL=httpService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpService.js","names":["Wreck","applyTraceHeaders","request","method","url","options","headers","mergedOptions","res","payload","statusCode","error","Error","get","getJson","json","post","postJson","put"],"sources":["../../../src/server/services/httpService.ts"],"sourcesContent":["import Wreck from '@hapi/wreck'\n\nimport { applyTraceHeaders } from '~/src/server/utils/utils.js'\n\nexport type Method = keyof Pick<typeof Wreck, 'get' | 'post' | 'put' | 'delete'>\nexport type RequestOptions = Parameters<typeof Wreck.defaults>[0]\n\nexport const request = async <BodyType = Buffer>(\n method: Method,\n url: string,\n options?: RequestOptions\n) => {\n const headers = applyTraceHeaders(options?.headers)\n\n const mergedOptions = { ...options, headers }\n\n const { res, payload } = await Wreck[method]<BodyType>(url, mergedOptions)\n\n if (!res.statusCode || res.statusCode < 200 || res.statusCode > 299) {\n return { res, error: payload || new Error('Unknown error') }\n }\n\n return { res, payload }\n}\n\nexport const get = <BodyType>(url: string, options?: RequestOptions) => {\n return request<BodyType>('get', url, options)\n}\n\nexport const getJson = <BodyType extends object>(url: string) => {\n return get<BodyType>(url, { json: true })\n}\n\nexport const post = <BodyType>(url: string, options: RequestOptions) => {\n return request<BodyType>('post', url, options)\n}\n\nexport const postJson = <BodyType extends object>(\n url: string,\n options: RequestOptions\n) => {\n return post<BodyType>(url, {\n ...options,\n json: true\n })\n}\n\nexport const put = <BodyType>(url: string, options: RequestOptions) => {\n return request<BodyType>('put', url, options)\n}\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,aAAa;AAE/B,SAASC,iBAAiB;AAK1B,OAAO,MAAMC,OAAO,GAAG,MAAAA,CACrBC,MAAc,EACdC,GAAW,EACXC,OAAwB,KACrB;EACH,MAAMC,OAAO,GAAGL,iBAAiB,CAACI,OAAO,EAAEC,OAAO,CAAC;EAEnD,MAAMC,aAAa,GAAG;IAAE,GAAGF,OAAO;IAAEC;EAAQ,CAAC;EAE7C,MAAM;IAAEE,GAAG;IAAEC;EAAQ,CAAC,GAAG,MAAMT,KAAK,CAACG,MAAM,CAAC,CAAWC,GAAG,EAAEG,aAAa,CAAC;EAE1E,IAAI,CAACC,GAAG,CAACE,UAAU,IAAIF,GAAG,CAACE,UAAU,GAAG,GAAG,IAAIF,GAAG,CAACE,UAAU,GAAG,GAAG,EAAE;IACnE,OAAO;MAAEF,GAAG;MAAEG,KAAK,EAAEF,OAAO,IAAI,IAAIG,KAAK,CAAC,eAAe;IAAE,CAAC;EAC9D;EAEA,OAAO;IAAEJ,GAAG;IAAEC;EAAQ,CAAC;AACzB,CAAC;AAED,OAAO,MAAMI,GAAG,GAAGA,CAAWT,GAAW,EAAEC,OAAwB,KAAK;EACtE,OAAOH,OAAO,CAAW,KAAK,EAAEE,GAAG,EAAEC,OAAO,CAAC;AAC/C,CAAC;AAED,OAAO,MAAMS,OAAO,GAA6BV,GAAW,IAAK;EAC/D,OAAOS,GAAG,CAAWT,GAAG,EAAE;IAAEW,IAAI,EAAE;EAAK,CAAC,CAAC;AAC3C,CAAC;AAED,OAAO,MAAMC,IAAI,GAAGA,CAAWZ,GAAW,EAAEC,OAAuB,KAAK;EACtE,OAAOH,OAAO,CAAW,MAAM,EAAEE,GAAG,EAAEC,OAAO,CAAC;AAChD,CAAC;AAED,OAAO,MAAMY,QAAQ,GAAGA,CACtBb,GAAW,EACXC,OAAuB,KACpB;EACH,OAAOW,IAAI,CAAWZ,GAAG,EAAE;IACzB,GAAGC,OAAO;IACVU,IAAI,EAAE;EACR,CAAC,CAAC;AACJ,CAAC;AAED,OAAO,MAAMG,GAAG,GAAGA,CAAWd,GAAW,EAAEC,OAAuB,KAAK;EACrE,OAAOH,OAAO,CAAW,KAAK,EAAEE,GAAG,EAAEC,OAAO,CAAC;AAC/C,CAAC","ignoreList":[]}