@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.
- package/.browserslistrc +16 -0
- package/.editorconfig +9 -0
- package/.eslintrc.cjs +266 -0
- package/.github/dependabot.yml +85 -0
- package/.github/workflows/check-pull-request.yml +209 -0
- package/.github/workflows/pr-notifier.yml +98 -0
- package/.github/workflows/publish.yml +111 -0
- package/.husky/pre-commit +1 -0
- package/.lintstagedrc.js +4 -0
- package/.nvmrc +1 -0
- package/.prettierignore +8 -0
- package/.prettierrc.cjs +26 -0
- package/.server/client/javascripts/application.js +68 -0
- package/.server/client/javascripts/application.js.map +1 -0
- package/.server/client/javascripts/file-upload.js +292 -0
- package/.server/client/javascripts/file-upload.js.map +1 -0
- package/.server/client/stylesheets/_code.scss +33 -0
- package/.server/client/stylesheets/_govuk-frontend.scss +4 -0
- package/.server/client/stylesheets/_prose.scss +56 -0
- package/.server/client/stylesheets/_service-banner.scss +24 -0
- package/.server/client/stylesheets/_summary-list.scss +28 -0
- package/.server/client/stylesheets/_tag-env.scss +24 -0
- package/.server/client/stylesheets/application.scss +14 -0
- package/.server/common/cookies.js +55 -0
- package/.server/common/cookies.js.map +1 -0
- package/.server/common/cookies.test.js +15 -0
- package/.server/common/cookies.test.js.map +1 -0
- package/.server/common/types.js +6 -0
- package/.server/common/types.js.map +1 -0
- package/.server/config/index.js +241 -0
- package/.server/config/index.js.map +1 -0
- package/.server/index.js +25 -0
- package/.server/index.js.map +1 -0
- package/.server/server/common/helpers/logging/logger-options.js +44 -0
- package/.server/server/common/helpers/logging/logger-options.js.map +1 -0
- package/.server/server/common/helpers/logging/logger.js +6 -0
- package/.server/server/common/helpers/logging/logger.js.map +1 -0
- package/.server/server/common/helpers/logging/request-logger.js +7 -0
- package/.server/server/common/helpers/logging/request-logger.js.map +1 -0
- package/.server/server/common/helpers/logging/request-tracing.js +12 -0
- package/.server/server/common/helpers/logging/request-tracing.js.map +1 -0
- package/.server/server/common/helpers/redis-client.js +55 -0
- package/.server/server/common/helpers/redis-client.js.map +1 -0
- package/.server/server/constants.js +2 -0
- package/.server/server/constants.js.map +1 -0
- package/.server/server/forms/README.md +10 -0
- package/.server/server/forms/components.json +1015 -0
- package/.server/server/forms/report-a-terrorist.json +270 -0
- package/.server/server/forms/runner-components-test.json +365 -0
- package/.server/server/forms/test.json +581 -0
- package/.server/server/index.js +116 -0
- package/.server/server/index.js.map +1 -0
- package/.server/server/plugins/blankie.js +29 -0
- package/.server/server/plugins/blankie.js.map +1 -0
- package/.server/server/plugins/crumb.js +15 -0
- package/.server/server/plugins/crumb.js.map +1 -0
- package/.server/server/plugins/engine/README.md +87 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js +37 -0
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -0
- package/.server/server/plugins/engine/components/CheckboxesField.js +79 -0
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -0
- package/.server/server/plugins/engine/components/ComponentBase.js +55 -0
- package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -0
- package/.server/server/plugins/engine/components/ComponentCollection.js +198 -0
- package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -0
- package/.server/server/plugins/engine/components/DatePartsField.js +208 -0
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -0
- package/.server/server/plugins/engine/components/Details.js +26 -0
- package/.server/server/plugins/engine/components/Details.js.map +1 -0
- package/.server/server/plugins/engine/components/EmailAddressField.js +40 -0
- package/.server/server/plugins/engine/components/EmailAddressField.js.map +1 -0
- package/.server/server/plugins/engine/components/FileUploadField.js +195 -0
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -0
- package/.server/server/plugins/engine/components/FormComponent.js +210 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -0
- package/.server/server/plugins/engine/components/Html.js +24 -0
- package/.server/server/plugins/engine/components/Html.js.map +1 -0
- package/.server/server/plugins/engine/components/InsetText.js +22 -0
- package/.server/server/plugins/engine/components/InsetText.js.map +1 -0
- package/.server/server/plugins/engine/components/List.js +65 -0
- package/.server/server/plugins/engine/components/List.js.map +1 -0
- package/.server/server/plugins/engine/components/ListFormComponent.js +87 -0
- package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -0
- package/.server/server/plugins/engine/components/MonthYearField.js +172 -0
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -0
- package/.server/server/plugins/engine/components/MultilineTextField.js +115 -0
- package/.server/server/plugins/engine/components/MultilineTextField.js.map +1 -0
- package/.server/server/plugins/engine/components/NumberField.js +137 -0
- package/.server/server/plugins/engine/components/NumberField.js.map +1 -0
- package/.server/server/plugins/engine/components/RadiosField.js +18 -0
- package/.server/server/plugins/engine/components/RadiosField.js.map +1 -0
- package/.server/server/plugins/engine/components/SelectField.js +33 -0
- package/.server/server/plugins/engine/components/SelectField.js.map +1 -0
- package/.server/server/plugins/engine/components/SelectionControlField.js +43 -0
- package/.server/server/plugins/engine/components/SelectionControlField.js.map +1 -0
- package/.server/server/plugins/engine/components/TelephoneNumberField.js +43 -0
- package/.server/server/plugins/engine/components/TelephoneNumberField.js.map +1 -0
- package/.server/server/plugins/engine/components/TextField.js +63 -0
- package/.server/server/plugins/engine/components/TextField.js.map +1 -0
- package/.server/server/plugins/engine/components/UkAddressField.js +130 -0
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -0
- package/.server/server/plugins/engine/components/YesNoField.js +28 -0
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -0
- package/.server/server/plugins/engine/components/constants.js +2 -0
- package/.server/server/plugins/engine/components/constants.js.map +1 -0
- package/.server/server/plugins/engine/components/helpers.js +219 -0
- package/.server/server/plugins/engine/components/helpers.js.map +1 -0
- package/.server/server/plugins/engine/components/index.js +25 -0
- package/.server/server/plugins/engine/components/index.js.map +1 -0
- package/.server/server/plugins/engine/components/types.js +2 -0
- package/.server/server/plugins/engine/components/types.js.map +1 -0
- package/.server/server/plugins/engine/configureEnginePlugin.js +44 -0
- package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -0
- package/.server/server/plugins/engine/helpers.js +268 -0
- package/.server/server/plugins/engine/helpers.js.map +1 -0
- package/.server/server/plugins/engine/index.js +6 -0
- package/.server/server/plugins/engine/index.js.map +1 -0
- package/.server/server/plugins/engine/models/FormModel.js +363 -0
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -0
- package/.server/server/plugins/engine/models/RepeatingSummaryViewModel.js +2 -0
- package/.server/server/plugins/engine/models/RepeatingSummaryViewModel.js.map +1 -0
- package/.server/server/plugins/engine/models/Section.js +2 -0
- package/.server/server/plugins/engine/models/Section.js.map +1 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js +183 -0
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -0
- package/.server/server/plugins/engine/models/index.js +3 -0
- package/.server/server/plugins/engine/models/index.js.map +1 -0
- package/.server/server/plugins/engine/models/types.js +2 -0
- package/.server/server/plugins/engine/models/types.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +44 -0
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/index.js +24 -0
- package/.server/server/plugins/engine/outputFormatters/index.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v1.js +104 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v1.js.map +1 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +110 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +401 -0
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/PageController.js +133 -0
- package/.server/server/plugins/engine/pageControllers/PageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +482 -0
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/README.md +28 -0
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js +372 -0
- package/.server/server/plugins/engine/pageControllers/RepeatPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/StartPageController.js +16 -0
- package/.server/server/plugins/engine/pageControllers/StartPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js +43 -0
- package/.server/server/plugins/engine/pageControllers/StatusPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +195 -0
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.js +8 -0
- package/.server/server/plugins/engine/pageControllers/TerminalPageController.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/helpers.js +69 -0
- package/.server/server/plugins/engine/pageControllers/helpers.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/index.js +10 -0
- package/.server/server/plugins/engine/pageControllers/index.js.map +1 -0
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +78 -0
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -0
- package/.server/server/plugins/engine/plugin.js +562 -0
- package/.server/server/plugins/engine/plugin.js.map +1 -0
- package/.server/server/plugins/engine/services/formSubmissionService.js +39 -0
- package/.server/server/plugins/engine/services/formSubmissionService.js.map +1 -0
- package/.server/server/plugins/engine/services/formsService.js +41 -0
- package/.server/server/plugins/engine/services/formsService.js.map +1 -0
- package/.server/server/plugins/engine/services/formsService.test.js +71 -0
- package/.server/server/plugins/engine/services/formsService.test.js.map +1 -0
- package/.server/server/plugins/engine/services/index.js +4 -0
- package/.server/server/plugins/engine/services/index.js.map +1 -0
- package/.server/server/plugins/engine/services/notifyService.js +45 -0
- package/.server/server/plugins/engine/services/notifyService.js.map +1 -0
- package/.server/server/plugins/engine/services/uploadService.js +51 -0
- package/.server/server/plugins/engine/services/uploadService.js.map +1 -0
- package/.server/server/plugins/engine/types.js +53 -0
- package/.server/server/plugins/engine/types.js.map +1 -0
- package/.server/server/plugins/engine/views/components/autocompletefield.html +5 -0
- package/.server/server/plugins/engine/views/components/checkboxesfield.html +5 -0
- package/.server/server/plugins/engine/views/components/datepartsfield.html +5 -0
- package/.server/server/plugins/engine/views/components/details.html +6 -0
- package/.server/server/plugins/engine/views/components/emailaddressfield.html +5 -0
- package/.server/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
- package/.server/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
- package/.server/server/plugins/engine/views/components/fileuploadfield.html +24 -0
- package/.server/server/plugins/engine/views/components/html.html +3 -0
- package/.server/server/plugins/engine/views/components/insettext.html +7 -0
- package/.server/server/plugins/engine/views/components/list.html +36 -0
- package/.server/server/plugins/engine/views/components/monthyearfield.html +5 -0
- package/.server/server/plugins/engine/views/components/multilinetextfield.html +10 -0
- package/.server/server/plugins/engine/views/components/numberfield.html +5 -0
- package/.server/server/plugins/engine/views/components/radiosfield.html +5 -0
- package/.server/server/plugins/engine/views/components/selectfield.html +5 -0
- package/.server/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
- package/.server/server/plugins/engine/views/components/textfield.html +5 -0
- package/.server/server/plugins/engine/views/components/ukaddressfield.html +25 -0
- package/.server/server/plugins/engine/views/components/yesnofield.html +5 -0
- package/.server/server/plugins/engine/views/file-upload.html +45 -0
- package/.server/server/plugins/engine/views/index.html +39 -0
- package/.server/server/plugins/engine/views/item-delete.html +56 -0
- package/.server/server/plugins/engine/views/partials/components.html +6 -0
- package/.server/server/plugins/engine/views/partials/conditional-components.html +3 -0
- package/.server/server/plugins/engine/views/partials/debug.html +44 -0
- package/.server/server/plugins/engine/views/partials/form.html +15 -0
- package/.server/server/plugins/engine/views/partials/heading.html +16 -0
- package/.server/server/plugins/engine/views/partials/preview-banner.html +32 -0
- package/.server/server/plugins/engine/views/partials/preview-banner.test.js +108 -0
- package/.server/server/plugins/engine/views/partials/preview-banner.test.js.map +1 -0
- package/.server/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
- package/.server/server/plugins/engine/views/repeat-list-summary.html +53 -0
- package/.server/server/plugins/errorPages.js +49 -0
- package/.server/server/plugins/errorPages.js.map +1 -0
- package/.server/server/plugins/nunjucks/context.js +79 -0
- package/.server/server/plugins/nunjucks/context.js.map +1 -0
- package/.server/server/plugins/nunjucks/context.test.js +134 -0
- package/.server/server/plugins/nunjucks/context.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/enviroment.test.js +166 -0
- package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/environment.js +95 -0
- package/.server/server/plugins/nunjucks/environment.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/answer.js +26 -0
- package/.server/server/plugins/nunjucks/filters/answer.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/answer.test.js +70 -0
- package/.server/server/plugins/nunjucks/filters/answer.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/evaluate.js +22 -0
- package/.server/server/plugins/nunjucks/filters/evaluate.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/field.js +26 -0
- package/.server/server/plugins/nunjucks/filters/field.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/field.test.js +64 -0
- package/.server/server/plugins/nunjucks/filters/field.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/highlight.js +14 -0
- package/.server/server/plugins/nunjucks/filters/highlight.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/href.js +28 -0
- package/.server/server/plugins/nunjucks/filters/href.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/href.test.js +63 -0
- package/.server/server/plugins/nunjucks/filters/href.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/index.js +9 -0
- package/.server/server/plugins/nunjucks/filters/index.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/inspect.js +16 -0
- package/.server/server/plugins/nunjucks/filters/inspect.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/page.js +23 -0
- package/.server/server/plugins/nunjucks/filters/page.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/page.test.js +51 -0
- package/.server/server/plugins/nunjucks/filters/page.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/index.js +4 -0
- package/.server/server/plugins/nunjucks/index.js.map +1 -0
- package/.server/server/plugins/nunjucks/plugin.js +38 -0
- package/.server/server/plugins/nunjucks/plugin.js.map +1 -0
- package/.server/server/plugins/nunjucks/render.js +41 -0
- package/.server/server/plugins/nunjucks/render.js.map +1 -0
- package/.server/server/plugins/nunjucks/types.js +41 -0
- package/.server/server/plugins/nunjucks/types.js.map +1 -0
- package/.server/server/plugins/pulse.js +8 -0
- package/.server/server/plugins/pulse.js.map +1 -0
- package/.server/server/plugins/router.js +169 -0
- package/.server/server/plugins/router.js.map +1 -0
- package/.server/server/plugins/session.js +28 -0
- package/.server/server/plugins/session.js.map +1 -0
- package/.server/server/routes/health.js +15 -0
- package/.server/server/routes/health.js.map +1 -0
- package/.server/server/routes/health.test.js +32 -0
- package/.server/server/routes/health.test.js.map +1 -0
- package/.server/server/routes/index.js +3 -0
- package/.server/server/routes/index.js.map +1 -0
- package/.server/server/routes/public.js +37 -0
- package/.server/server/routes/public.js.map +1 -0
- package/.server/server/routes/types.js +14 -0
- package/.server/server/routes/types.js.map +1 -0
- package/.server/server/schemas/index.js +15 -0
- package/.server/server/schemas/index.js.map +1 -0
- package/.server/server/secure-context.js +36 -0
- package/.server/server/secure-context.js.map +1 -0
- package/.server/server/services/cacheService.js +85 -0
- package/.server/server/services/cacheService.js.map +1 -0
- package/.server/server/services/httpService.js +44 -0
- package/.server/server/services/httpService.js.map +1 -0
- package/.server/server/services/httpService.test.js +504 -0
- package/.server/server/services/httpService.test.js.map +1 -0
- package/.server/server/services/index.js +2 -0
- package/.server/server/services/index.js.map +1 -0
- package/.server/server/types.js +2 -0
- package/.server/server/types.js.map +1 -0
- package/.server/server/utils/notify.js +40 -0
- package/.server/server/utils/notify.js.map +1 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.js +7 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.js.map +1 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.test.js +14 -0
- package/.server/server/utils/secure-context/get-trust-store-certs.test.js.map +1 -0
- package/.server/server/utils/utils.js +20 -0
- package/.server/server/utils/utils.js.map +1 -0
- package/.server/server/utils/utils.test.js +49 -0
- package/.server/server/utils/utils.test.js.map +1 -0
- package/.server/server/views/404.html +16 -0
- package/.server/server/views/500.html +19 -0
- package/.server/server/views/components/debug/macro.njk +3 -0
- package/.server/server/views/components/debug/template.njk +13 -0
- package/.server/server/views/components/service-banner/macro.njk +3 -0
- package/.server/server/views/components/service-banner/template.njk +20 -0
- package/.server/server/views/components/service-banner/template.test.js +36 -0
- package/.server/server/views/components/service-banner/template.test.js.map +1 -0
- package/.server/server/views/components/tag-env/macro.njk +3 -0
- package/.server/server/views/components/tag-env/template.njk +30 -0
- package/.server/server/views/components/tag-env/template.test.js +59 -0
- package/.server/server/views/components/tag-env/template.test.js.map +1 -0
- package/.server/server/views/confirmation.html +19 -0
- package/.server/server/views/help/accessibility-statement.html +58 -0
- package/.server/server/views/help/cookie-preferences.html +57 -0
- package/.server/server/views/help/cookies.html +71 -0
- package/.server/server/views/help/get-support.html +37 -0
- package/.server/server/views/help/privacy-notice.html +68 -0
- package/.server/server/views/help/terms-and-conditions.html +83 -0
- package/.server/server/views/layout.html +199 -0
- package/.server/server/views/summary.html +50 -0
- package/.server/typings/hapi/index.d.js +2 -0
- package/.server/typings/hapi/index.d.js.map +1 -0
- package/.server/typings/hapi-tracing/index.d.js +2 -0
- package/.server/typings/hapi-tracing/index.d.js.map +1 -0
- package/.server/typings/index.d.js +2 -0
- package/.server/typings/index.d.js.map +1 -0
- package/.server/typings/joi/index.d.js +2 -0
- package/.server/typings/joi/index.d.js.map +1 -0
- package/Dockerfile +61 -0
- package/LICENCE +8 -0
- package/Procfile +1 -0
- package/README.md +87 -0
- package/babel.config.cjs +55 -0
- package/compose/aws.env +4 -0
- package/compose/start-localstack.sh +26 -0
- package/docker-compose.yaml +86 -0
- package/globals.d.ts +1 -0
- package/jest.config.cjs +54 -0
- package/jest.environment.js +4 -0
- package/jest.setup.cjs +14 -0
- package/package.json +163 -0
- package/postcss.config.js +26 -0
- package/sonar-project.properties +17 -0
- package/src/client/javascripts/application.js +87 -0
- package/src/client/javascripts/file-upload.js +386 -0
- package/src/client/stylesheets/_code.scss +33 -0
- package/src/client/stylesheets/_govuk-frontend.scss +4 -0
- package/src/client/stylesheets/_prose.scss +56 -0
- package/src/client/stylesheets/_service-banner.scss +24 -0
- package/src/client/stylesheets/_summary-list.scss +28 -0
- package/src/client/stylesheets/_tag-env.scss +24 -0
- package/src/client/stylesheets/application.scss +14 -0
- package/src/common/cookies.js +58 -0
- package/src/common/cookies.test.js +23 -0
- package/src/common/types.js +5 -0
- package/src/config/index.ts +271 -0
- package/src/index.ts +31 -0
- package/src/server/common/helpers/logging/logger-options.test.ts +50 -0
- package/src/server/common/helpers/logging/logger-options.ts +46 -0
- package/src/server/common/helpers/logging/logger.ts +7 -0
- package/src/server/common/helpers/logging/request-logger.ts +9 -0
- package/src/server/common/helpers/logging/request-tracing.js +10 -0
- package/src/server/common/helpers/redis-client.js +70 -0
- package/src/server/constants.js +1 -0
- package/src/server/forms/README.md +10 -0
- package/src/server/forms/components.json +1015 -0
- package/src/server/forms/report-a-terrorist.json +270 -0
- package/src/server/forms/runner-components-test.json +365 -0
- package/src/server/forms/test.json +581 -0
- package/src/server/index.test.ts +582 -0
- package/src/server/index.ts +140 -0
- package/src/server/plugins/blankie.test.ts +73 -0
- package/src/server/plugins/blankie.ts +48 -0
- package/src/server/plugins/crumb.ts +20 -0
- package/src/server/plugins/engine/README.md +87 -0
- package/src/server/plugins/engine/components/AutocompleteField.test.ts +294 -0
- package/src/server/plugins/engine/components/AutocompleteField.ts +49 -0
- package/src/server/plugins/engine/components/CheckboxesField.test.ts +379 -0
- package/src/server/plugins/engine/components/CheckboxesField.ts +106 -0
- package/src/server/plugins/engine/components/ComponentBase.ts +97 -0
- package/src/server/plugins/engine/components/ComponentCollection.ts +278 -0
- package/src/server/plugins/engine/components/DatePartsField.test.ts +822 -0
- package/src/server/plugins/engine/components/DatePartsField.ts +264 -0
- package/src/server/plugins/engine/components/Details.test.ts +49 -0
- package/src/server/plugins/engine/components/Details.ts +30 -0
- package/src/server/plugins/engine/components/EmailAddressField.test.ts +395 -0
- package/src/server/plugins/engine/components/EmailAddressField.ts +55 -0
- package/src/server/plugins/engine/components/FileUploadField.test.ts +778 -0
- package/src/server/plugins/engine/components/FileUploadField.ts +262 -0
- package/src/server/plugins/engine/components/FormComponent.ts +249 -0
- package/src/server/plugins/engine/components/Html.test.ts +48 -0
- package/src/server/plugins/engine/components/Html.ts +29 -0
- package/src/server/plugins/engine/components/InsetText.test.ts +48 -0
- package/src/server/plugins/engine/components/InsetText.ts +27 -0
- package/src/server/plugins/engine/components/List.test.ts +76 -0
- package/src/server/plugins/engine/components/List.ts +72 -0
- package/src/server/plugins/engine/components/ListFormComponent.ts +140 -0
- package/src/server/plugins/engine/components/MonthYearField.test.ts +567 -0
- package/src/server/plugins/engine/components/MonthYearField.ts +222 -0
- package/src/server/plugins/engine/components/MultilineTextField.test.ts +558 -0
- package/src/server/plugins/engine/components/MultilineTextField.ts +138 -0
- package/src/server/plugins/engine/components/NumberField.test.ts +701 -0
- package/src/server/plugins/engine/components/NumberField.ts +163 -0
- package/src/server/plugins/engine/components/RadiosField.test.ts +288 -0
- package/src/server/plugins/engine/components/RadiosField.ts +24 -0
- package/src/server/plugins/engine/components/SelectField.test.ts +288 -0
- package/src/server/plugins/engine/components/SelectField.ts +47 -0
- package/src/server/plugins/engine/components/SelectionControlField.ts +43 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.test.ts +356 -0
- package/src/server/plugins/engine/components/TelephoneNumberField.ts +67 -0
- package/src/server/plugins/engine/components/TextField.test.ts +489 -0
- package/src/server/plugins/engine/components/TextField.ts +96 -0
- package/src/server/plugins/engine/components/UkAddressField.test.ts +623 -0
- package/src/server/plugins/engine/components/UkAddressField.ts +172 -0
- package/src/server/plugins/engine/components/YesNoField.test.ts +248 -0
- package/src/server/plugins/engine/components/YesNoField.ts +31 -0
- package/src/server/plugins/engine/components/constants.ts +1 -0
- package/src/server/plugins/engine/components/helpers.ts +330 -0
- package/src/server/plugins/engine/components/index.ts +24 -0
- package/src/server/plugins/engine/components/types.ts +117 -0
- package/src/server/plugins/engine/configureEnginePlugin.ts +47 -0
- package/src/server/plugins/engine/helpers.test.ts +791 -0
- package/src/server/plugins/engine/helpers.ts +379 -0
- package/src/server/plugins/engine/index.ts +7 -0
- package/src/server/plugins/engine/models/FormModel.test.ts +42 -0
- package/src/server/plugins/engine/models/FormModel.ts +443 -0
- package/src/server/plugins/engine/models/RepeatingSummaryViewModel.ts +0 -0
- package/src/server/plugins/engine/models/Section.ts +0 -0
- package/src/server/plugins/engine/models/SummaryViewModel.test.ts +209 -0
- package/src/server/plugins/engine/models/SummaryViewModel.ts +220 -0
- package/src/server/plugins/engine/models/index.ts +2 -0
- package/src/server/plugins/engine/models/types.ts +114 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.test.ts +143 -0
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +73 -0
- package/src/server/plugins/engine/outputFormatters/index.test.ts +17 -0
- package/src/server/plugins/engine/outputFormatters/index.ts +44 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.test.ts +229 -0
- package/src/server/plugins/engine/outputFormatters/machine/v1.ts +140 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.test.ts +229 -0
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +153 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +1108 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +446 -0
- package/src/server/plugins/engine/pageControllers/PageController.test.ts +205 -0
- package/src/server/plugins/engine/pageControllers/PageController.ts +176 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.test.ts +1264 -0
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +561 -0
- package/src/server/plugins/engine/pageControllers/README.md +28 -0
- package/src/server/plugins/engine/pageControllers/RepeatPageController.test.ts +264 -0
- package/src/server/plugins/engine/pageControllers/RepeatPageController.ts +458 -0
- package/src/server/plugins/engine/pageControllers/StartPageController.ts +18 -0
- package/src/server/plugins/engine/pageControllers/StatusPageController.ts +50 -0
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +261 -0
- package/src/server/plugins/engine/pageControllers/TerminalController.test.ts +28 -0
- package/src/server/plugins/engine/pageControllers/TerminalPageController.ts +19 -0
- package/src/server/plugins/engine/pageControllers/helpers.test.ts +198 -0
- package/src/server/plugins/engine/pageControllers/helpers.ts +101 -0
- package/src/server/plugins/engine/pageControllers/index.ts +10 -0
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +89 -0
- package/src/server/plugins/engine/plugin.ts +673 -0
- package/src/server/plugins/engine/services/formSubmissionService.js +46 -0
- package/src/server/plugins/engine/services/formsService.js +46 -0
- package/src/server/plugins/engine/services/formsService.test.js +90 -0
- package/src/server/plugins/engine/services/index.js +3 -0
- package/src/server/plugins/engine/services/notifyService.test.ts +132 -0
- package/src/server/plugins/engine/services/notifyService.ts +64 -0
- package/src/server/plugins/engine/services/uploadService.js +60 -0
- package/src/server/plugins/engine/types.ts +315 -0
- package/src/server/plugins/engine/views/components/autocompletefield.html +5 -0
- package/src/server/plugins/engine/views/components/checkboxesfield.html +5 -0
- package/src/server/plugins/engine/views/components/datepartsfield.html +5 -0
- package/src/server/plugins/engine/views/components/details.html +6 -0
- package/src/server/plugins/engine/views/components/emailaddressfield.html +5 -0
- package/src/server/plugins/engine/views/components/fileuploadfield-key.html +8 -0
- package/src/server/plugins/engine/views/components/fileuploadfield-value.html +3 -0
- package/src/server/plugins/engine/views/components/fileuploadfield.html +24 -0
- package/src/server/plugins/engine/views/components/html.html +3 -0
- package/src/server/plugins/engine/views/components/insettext.html +7 -0
- package/src/server/plugins/engine/views/components/list.html +36 -0
- package/src/server/plugins/engine/views/components/monthyearfield.html +5 -0
- package/src/server/plugins/engine/views/components/multilinetextfield.html +10 -0
- package/src/server/plugins/engine/views/components/numberfield.html +5 -0
- package/src/server/plugins/engine/views/components/radiosfield.html +5 -0
- package/src/server/plugins/engine/views/components/selectfield.html +5 -0
- package/src/server/plugins/engine/views/components/telephonenumberfield.html +5 -0
- package/src/server/plugins/engine/views/components/textfield.html +5 -0
- package/src/server/plugins/engine/views/components/ukaddressfield.html +25 -0
- package/src/server/plugins/engine/views/components/yesnofield.html +5 -0
- package/src/server/plugins/engine/views/file-upload.html +45 -0
- package/src/server/plugins/engine/views/index.html +39 -0
- package/src/server/plugins/engine/views/item-delete.html +56 -0
- package/src/server/plugins/engine/views/partials/components.html +6 -0
- package/src/server/plugins/engine/views/partials/conditional-components.html +3 -0
- package/src/server/plugins/engine/views/partials/debug.html +44 -0
- package/src/server/plugins/engine/views/partials/form.html +15 -0
- package/src/server/plugins/engine/views/partials/heading.html +16 -0
- package/src/server/plugins/engine/views/partials/preview-banner.html +32 -0
- package/src/server/plugins/engine/views/partials/preview-banner.test.js +122 -0
- package/src/server/plugins/engine/views/partials/warn-missing-notification-email.html +10 -0
- package/src/server/plugins/engine/views/repeat-list-summary.html +53 -0
- package/src/server/plugins/errorPages.ts +58 -0
- package/src/server/plugins/nunjucks/context.js +88 -0
- package/src/server/plugins/nunjucks/context.test.js +142 -0
- package/src/server/plugins/nunjucks/enviroment.test.js +201 -0
- package/src/server/plugins/nunjucks/environment.js +116 -0
- package/src/server/plugins/nunjucks/filters/answer.js +27 -0
- package/src/server/plugins/nunjucks/filters/answer.test.js +89 -0
- package/src/server/plugins/nunjucks/filters/evaluate.js +21 -0
- package/src/server/plugins/nunjucks/filters/field.js +28 -0
- package/src/server/plugins/nunjucks/filters/field.test.js +75 -0
- package/src/server/plugins/nunjucks/filters/highlight.js +11 -0
- package/src/server/plugins/nunjucks/filters/href.js +30 -0
- package/src/server/plugins/nunjucks/filters/href.test.js +80 -0
- package/src/server/plugins/nunjucks/filters/index.js +8 -0
- package/src/server/plugins/nunjucks/filters/inspect.js +15 -0
- package/src/server/plugins/nunjucks/filters/page.js +24 -0
- package/src/server/plugins/nunjucks/filters/page.test.js +65 -0
- package/src/server/plugins/nunjucks/index.js +3 -0
- package/src/server/plugins/nunjucks/plugin.js +40 -0
- package/src/server/plugins/nunjucks/render.js +42 -0
- package/src/server/plugins/nunjucks/types.js +40 -0
- package/src/server/plugins/pulse.ts +11 -0
- package/src/server/plugins/router.ts +201 -0
- package/src/server/plugins/session.ts +28 -0
- package/src/server/routes/health.js +13 -0
- package/src/server/routes/health.test.js +35 -0
- package/src/server/routes/index.test.ts +125 -0
- package/src/server/routes/index.ts +2 -0
- package/src/server/routes/public.ts +47 -0
- package/src/server/routes/types.ts +48 -0
- package/src/server/schemas/index.ts +34 -0
- package/src/server/secure-context.js +43 -0
- package/src/server/services/cacheService.test.ts +276 -0
- package/src/server/services/cacheService.ts +131 -0
- package/src/server/services/httpService.test.js +491 -0
- package/src/server/services/httpService.ts +50 -0
- package/src/server/services/index.ts +1 -0
- package/src/server/types.ts +54 -0
- package/src/server/utils/notify.test.ts +37 -0
- package/src/server/utils/notify.ts +50 -0
- package/src/server/utils/secure-context/get-trust-store-certs.js +11 -0
- package/src/server/utils/secure-context/get-trust-store-certs.test.js +19 -0
- package/src/server/utils/utils.js +24 -0
- package/src/server/utils/utils.test.js +54 -0
- package/src/server/views/404.html +16 -0
- package/src/server/views/500.html +19 -0
- package/src/server/views/components/debug/macro.njk +3 -0
- package/src/server/views/components/debug/template.njk +13 -0
- package/src/server/views/components/service-banner/macro.njk +3 -0
- package/src/server/views/components/service-banner/template.njk +20 -0
- package/src/server/views/components/service-banner/template.test.js +43 -0
- package/src/server/views/components/tag-env/macro.njk +3 -0
- package/src/server/views/components/tag-env/template.njk +30 -0
- package/src/server/views/components/tag-env/template.test.js +66 -0
- package/src/server/views/confirmation.html +19 -0
- package/src/server/views/help/accessibility-statement.html +58 -0
- package/src/server/views/help/cookie-preferences.html +57 -0
- package/src/server/views/help/cookies.html +71 -0
- package/src/server/views/help/get-support.html +37 -0
- package/src/server/views/help/privacy-notice.html +68 -0
- package/src/server/views/help/terms-and-conditions.html +83 -0
- package/src/server/views/layout.html +199 -0
- package/src/server/views/summary.html +50 -0
- package/src/typings/hapi/index.d.ts +95 -0
- package/src/typings/hapi-tracing/index.d.ts +6 -0
- package/src/typings/index.d.ts +3 -0
- package/src/typings/joi/index.d.ts +22 -0
- package/stylelint.config.js +10 -0
- package/test/client/javascripts/file-upload.test.js +1197 -0
- package/test/condition/checkboxes.test.js +112 -0
- package/test/condition/radios.test.js +112 -0
- package/test/condition/text.test.js +103 -0
- package/test/fixtures/assets-manifest.json +4 -0
- package/test/fixtures/form.js +86 -0
- package/test/fixtures/index.js +2 -0
- package/test/fixtures/list.js +92 -0
- package/test/form/cookies.test.js +338 -0
- package/test/form/csrf.test.js +87 -0
- package/test/form/definitions/basic.js +101 -0
- package/test/form/definitions/blank.js +10 -0
- package/test/form/definitions/checkboxes.json +88 -0
- package/test/form/definitions/components.json +452 -0
- package/test/form/definitions/conditional-reveal.js +140 -0
- package/test/form/definitions/conditions-basic.js +187 -0
- package/test/form/definitions/conditions-complex.js +338 -0
- package/test/form/definitions/conditions-dates.js +78 -0
- package/test/form/definitions/conditions-escaping.js +143 -0
- package/test/form/definitions/demo-cph-number.js +3099 -0
- package/test/form/definitions/feedback.json +45 -0
- package/test/form/definitions/fields-optional.js +402 -0
- package/test/form/definitions/fields-required.js +402 -0
- package/test/form/definitions/file-upload-basic.js +44 -0
- package/test/form/definitions/file-upload.js +66 -0
- package/test/form/definitions/minimal.js +39 -0
- package/test/form/definitions/phase-alpha.json +33 -0
- package/test/form/definitions/phase-default.json +26 -0
- package/test/form/definitions/radios.json +88 -0
- package/test/form/definitions/repeat-mixed.js +54 -0
- package/test/form/definitions/repeat.js +70 -0
- package/test/form/definitions/status.json +126 -0
- package/test/form/definitions/templates.js +183 -0
- package/test/form/definitions/test.json +581 -0
- package/test/form/definitions/text.json +75 -0
- package/test/form/definitions/titles.json +170 -0
- package/test/form/definitions.test.js +47 -0
- package/test/form/exit-page.test.js +210 -0
- package/test/form/feedback.test.js +68 -0
- package/test/form/fields-optional.test.js +237 -0
- package/test/form/fields-required.test.js +294 -0
- package/test/form/file-upload.test.js +313 -0
- package/test/form/govuk-notify.test.js +449 -0
- package/test/form/journey-basic.test.js +444 -0
- package/test/form/persist-files.test.js +227 -0
- package/test/form/phase-banner.test.js +71 -0
- package/test/form/repeat.test.js +628 -0
- package/test/form/summary-submission-email.test.js +95 -0
- package/test/form/template.test.js +288 -0
- package/test/form/titles.test.js +204 -0
- package/test/helpers/component-helpers.js +74 -0
- package/test/utils/get-cookie.js +42 -0
- package/test/utils/get-form-definitions.js +18 -0
- package/tmp.pdf +1 -0
- package/tsconfig.json +28 -0
- 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 @@
|
|
|
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":"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","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":[]}
|