@defra/forms-engine-plugin 0.1.10 → 0.1.11

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 (116) hide show
  1. package/.public/stylesheets/application.min.css +1 -1
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/application.scss +10 -0
  4. package/.server/config/index.js +3 -14
  5. package/.server/config/index.js.map +1 -1
  6. package/.server/server/devserver/dxt-devtool-baselayout.html +71 -0
  7. package/.server/server/forms/register-as-a-unicorn-breeder.json +393 -0
  8. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +251 -0
  9. package/.server/server/index.js +11 -16
  10. package/.server/server/index.js.map +1 -1
  11. package/.server/server/plugins/engine/configureEnginePlugin.js +16 -2
  12. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  13. package/.server/server/plugins/engine/plugin.js +27 -16
  14. package/.server/server/plugins/engine/plugin.js.map +1 -1
  15. package/.server/server/plugins/engine/services/formsService.js +15 -29
  16. package/.server/server/plugins/engine/services/formsService.js.map +1 -1
  17. package/.server/server/plugins/engine/services/localFormsService.js +52 -0
  18. package/.server/server/plugins/engine/services/localFormsService.js.map +1 -0
  19. package/.server/server/plugins/engine/views/confirmation.html +1 -1
  20. package/.server/server/plugins/engine/views/file-upload.html +1 -1
  21. package/.server/server/plugins/engine/views/index.html +1 -1
  22. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  23. package/.server/server/plugins/engine/views/repeat-list-summary.html +1 -1
  24. package/.server/server/plugins/engine/views/summary.html +1 -1
  25. package/.server/server/plugins/errorPages.js +4 -26
  26. package/.server/server/plugins/errorPages.js.map +1 -1
  27. package/.server/server/plugins/nunjucks/context.js +37 -28
  28. package/.server/server/plugins/nunjucks/context.js.map +1 -1
  29. package/.server/server/plugins/nunjucks/context.test.js +23 -28
  30. package/.server/server/plugins/nunjucks/context.test.js.map +1 -1
  31. package/.server/server/plugins/nunjucks/types.js +3 -4
  32. package/.server/server/plugins/nunjucks/types.js.map +1 -1
  33. package/.server/server/routes/index.js +0 -1
  34. package/.server/server/routes/index.js.map +1 -1
  35. package/.server/typings/hapi/index.d.js.map +1 -1
  36. package/package.json +2 -1
  37. package/src/client/stylesheets/application.scss +10 -0
  38. package/src/config/index.ts +4 -17
  39. package/src/server/devserver/dxt-devtool-baselayout.html +71 -0
  40. package/src/server/forms/register-as-a-unicorn-breeder.json +393 -0
  41. package/src/server/forms/register-as-a-unicorn-breeder.yaml +251 -0
  42. package/src/server/index.test.ts +4 -37
  43. package/src/server/index.ts +13 -16
  44. package/src/server/plugins/engine/configureEnginePlugin.ts +19 -1
  45. package/src/server/plugins/engine/plugin.ts +43 -17
  46. package/src/server/plugins/engine/services/formsService.js +17 -35
  47. package/src/server/plugins/engine/services/localFormsService.js +49 -0
  48. package/src/server/plugins/engine/views/confirmation.html +1 -1
  49. package/src/server/plugins/engine/views/file-upload.html +1 -1
  50. package/src/server/plugins/engine/views/index.html +1 -1
  51. package/src/server/plugins/engine/views/item-delete.html +1 -1
  52. package/src/server/plugins/engine/views/repeat-list-summary.html +1 -1
  53. package/src/server/plugins/engine/views/summary.html +1 -1
  54. package/src/server/plugins/errorPages.ts +4 -26
  55. package/src/server/plugins/nunjucks/context.js +41 -31
  56. package/src/server/plugins/nunjucks/context.test.js +24 -27
  57. package/src/server/plugins/nunjucks/types.js +3 -4
  58. package/src/server/routes/index.ts +0 -1
  59. package/src/typings/hapi/index.d.ts +3 -9
  60. package/.server/common/cookies.js +0 -55
  61. package/.server/common/cookies.js.map +0 -1
  62. package/.server/common/cookies.test.js +0 -15
  63. package/.server/common/cookies.test.js.map +0 -1
  64. package/.server/common/types.js +0 -6
  65. package/.server/common/types.js.map +0 -1
  66. package/.server/server/forms/README.md +0 -10
  67. package/.server/server/forms/report-a-terrorist.json +0 -270
  68. package/.server/server/forms/runner-components-test.json +0 -365
  69. package/.server/server/forms/test.json +0 -581
  70. package/.server/server/forms/test.yaml +0 -363
  71. package/.server/server/plugins/blankie.js +0 -29
  72. package/.server/server/plugins/blankie.js.map +0 -1
  73. package/.server/server/plugins/engine/services/formsService.test.js +0 -71
  74. package/.server/server/plugins/engine/services/formsService.test.js.map +0 -1
  75. package/.server/server/plugins/engine/views/layout.html +0 -199
  76. package/.server/server/plugins/router.js +0 -169
  77. package/.server/server/plugins/router.js.map +0 -1
  78. package/.server/server/routes/health.js +0 -15
  79. package/.server/server/routes/health.js.map +0 -1
  80. package/.server/server/routes/health.test.js +0 -32
  81. package/.server/server/routes/health.test.js.map +0 -1
  82. package/.server/server/utils/file-form-service.test.js +0 -52
  83. package/.server/server/utils/file-form-service.test.js.map +0 -1
  84. package/.server/server/views/404.html +0 -16
  85. package/.server/server/views/500.html +0 -19
  86. package/.server/server/views/help/accessibility-statement.html +0 -58
  87. package/.server/server/views/help/cookie-preferences.html +0 -57
  88. package/.server/server/views/help/cookies.html +0 -71
  89. package/.server/server/views/help/get-support.html +0 -37
  90. package/.server/server/views/help/privacy-notice.html +0 -68
  91. package/.server/server/views/help/terms-and-conditions.html +0 -83
  92. package/src/common/cookies.js +0 -58
  93. package/src/common/cookies.test.js +0 -23
  94. package/src/common/types.js +0 -5
  95. package/src/server/forms/README.md +0 -10
  96. package/src/server/forms/report-a-terrorist.json +0 -270
  97. package/src/server/forms/runner-components-test.json +0 -365
  98. package/src/server/forms/test.json +0 -581
  99. package/src/server/forms/test.yaml +0 -363
  100. package/src/server/plugins/blankie.test.ts +0 -73
  101. package/src/server/plugins/blankie.ts +0 -48
  102. package/src/server/plugins/engine/services/formsService.test.js +0 -90
  103. package/src/server/plugins/engine/views/layout.html +0 -199
  104. package/src/server/plugins/router.ts +0 -201
  105. package/src/server/routes/health.js +0 -13
  106. package/src/server/routes/health.test.js +0 -35
  107. package/src/server/routes/index.test.ts +0 -125
  108. package/src/server/utils/file-form-service.test.js +0 -79
  109. package/src/server/views/404.html +0 -16
  110. package/src/server/views/500.html +0 -19
  111. package/src/server/views/help/accessibility-statement.html +0 -58
  112. package/src/server/views/help/cookie-preferences.html +0 -57
  113. package/src/server/views/help/cookies.html +0 -71
  114. package/src/server/views/help/get-support.html +0 -37
  115. package/src/server/views/help/privacy-notice.html +0 -68
  116. package/src/server/views/help/terms-and-conditions.html +0 -83
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":["hasFormComponents","slugSchema","Boom","vision","isEqual","Joi","nunjucks","PREVIEW_PATH_PREFIX","checkEmailAddressForLiveFormSubmission","checkFormStatus","findPage","getCacheService","getPage","getStartPath","normalisePath","proceed","redirectPath","PLUGIN_PATH","VIEW_PATH","context","prepareNunjucksEnvironment","FormModel","SummaryViewModel","format","FileUploadPageController","RepeatPageController","getFormSubmissionData","generateUniqueReference","defaultServices","getUploadStatus","actionSchema","confirmSchema","crumbSchema","itemIdSchema","pathSchema","stateSchema","httpService","CacheService","plugin","name","dependencies","multiple","register","server","options","model","services","controllers","cacheName","viewPaths","filters","pluginPath","formsService","cacheService","path","Array","isArray","length","push","engines","html","compile","compileOptions","template","environment","render","prepare","next","configure","expose","app","itemCache","Map","models","loadFormPreHandler","request","h","continue","params","slug","isPreview","state","formState","metadata","getFormMetadata","id","notFound","key","item","get","updatedAt","logger","info","definition","getFormDefinition","emailAddress","notificationEmail","outputEmail","basePath","substring","set","dispatchHandler","servicePath","redirectOrMakeHandler","makeHandler","page","getState","$$__referenceNumber","prefix","def","referenceNumberPrefix","badImplementation","referenceNumber","mergeState","flash","getFlash","getFormContext","errors","relevantPath","getRelevantPath","summaryPath","getSummaryPath","startsWith","isForceAccess","redirectTo","query","returnUrl","getHref","getHandler","events","onLoad","type","url","viewModel","items","details","payload","undefined","response","postJson","Object","assign","data","makeGetRouteHandler","postHandler","pageDef","href","makePostRouteHandler","dispatchRouteOptions","pre","method","route","handler","validate","object","keys","getRouteOptions","itemId","optional","postRouteOptions","parse","crumb","action","unknown","required","getListSummaryHandler","makeGetListSummaryRouteHandler","postListSummaryHandler","makePostListSummaryRouteHandler","getItemDeleteHandler","makeGetItemDeleteRouteHandler","postItemDeleteHandler","makePostItemDeleteRouteHandler","confirm","uploadId","status","error","code","plugins","string","guid"],"sources":["../../../../src/server/plugins/engine/plugin.ts"],"sourcesContent":["import { hasFormComponents, slugSchema } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport {\n type Plugin,\n type ResponseObject,\n type ResponseToolkit,\n type RouteOptions,\n type Server\n} from '@hapi/hapi'\nimport vision from '@hapi/vision'\nimport { isEqual } from 'date-fns'\nimport Joi from 'joi'\nimport nunjucks, { type Environment } from 'nunjucks'\n\nimport { PREVIEW_PATH_PREFIX } from '~/src/server/constants.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n findPage,\n getCacheService,\n getPage,\n getStartPath,\n normalisePath,\n proceed,\n redirectPath\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n PLUGIN_PATH,\n VIEW_PATH,\n context,\n prepareNunjucksEnvironment\n} from '~/src/server/plugins/engine/index.js'\nimport {\n FormModel,\n SummaryViewModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport { format } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'\nimport { FileUploadPageController } from '~/src/server/plugins/engine/pageControllers/FileUploadPageController.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { RepeatPageController } from '~/src/server/plugins/engine/pageControllers/RepeatPageController.js'\nimport { getFormSubmissionData } from '~/src/server/plugins/engine/pageControllers/SummaryPageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers.js'\nimport { generateUniqueReference } from '~/src/server/plugins/engine/referenceNumbers.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport { getUploadStatus } from '~/src/server/plugins/engine/services/uploadService.js'\nimport {\n type FilterFunction,\n type FormContext\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n confirmSchema,\n crumbSchema,\n itemIdSchema,\n pathSchema,\n stateSchema\n} from '~/src/server/schemas/index.js'\nimport * as httpService from '~/src/server/services/httpService.js'\nimport { CacheService } from '~/src/server/services/index.js'\nimport { type Services } from '~/src/server/types.js'\n\nexport interface PluginOptions {\n model?: FormModel\n services?: Services\n controllers?: Record<string, typeof PageController>\n cacheName?: string\n viewPaths?: string[]\n filters?: Record<string, FilterFunction>\n pluginPath?: string\n}\n\nexport const plugin = {\n name: '@defra/forms-engine-plugin',\n dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],\n multiple: true,\n async register(server: Server, options: PluginOptions) {\n const {\n model,\n services = defaultServices,\n controllers,\n cacheName,\n viewPaths,\n filters,\n pluginPath = PLUGIN_PATH\n } = options\n const { formsService } = services\n const cacheService = new CacheService(server, cacheName)\n\n // Paths array to tell `vision` and `nunjucks` where template files are stored.\n // We need to include `VIEW_PATH` in addition the runtime path (node_modules)\n // to keep the local tests working\n const path = [`${pluginPath}/${VIEW_PATH}`, VIEW_PATH]\n\n // Include any additional user provided view paths so our internal views engine\n // can find any files they provide from the consumer side if using custom `page.view`s\n if (Array.isArray(viewPaths) && viewPaths.length) {\n path.push(...viewPaths)\n }\n\n await server.register({\n plugin: vision,\n options: {\n engines: {\n html: {\n compile: (\n path: string,\n compileOptions: { environment: Environment }\n ) => {\n const template = nunjucks.compile(\n path,\n compileOptions.environment\n )\n\n return (context: object | undefined) => {\n return template.render(context)\n }\n },\n prepare: (\n options: EngineConfigurationObject,\n next: (err?: Error) => void\n ) => {\n // Nunjucks also needs an additional path configuration\n // to use the templates and macros from `govuk-frontend`\n const environment = nunjucks.configure([\n ...path,\n 'node_modules/govuk-frontend/dist'\n ])\n\n // Applies custom filters and globals for nunjucks\n // that are required by the `forms-engine-plugin`\n prepareNunjucksEnvironment(environment, filters)\n\n options.compileOptions.environment = environment\n\n next()\n }\n }\n },\n path,\n // Provides global context used with all templates\n context\n }\n })\n\n server.expose('cacheService', cacheService)\n\n server.app.model = model\n\n // In-memory cache of FormModel items, exposed\n // (for testing purposes) through `server.app.models`\n const itemCache = new Map<string, { model: FormModel; updatedAt: Date }>()\n server.app.models = itemCache\n\n const loadFormPreHandler = async (\n request: FormRequest | FormRequestPayload,\n h: Pick<ResponseToolkit, 'continue'>\n ) => {\n if (server.app.model) {\n request.app.model = server.app.model\n\n return h.continue\n }\n\n const { params, path } = request\n const { slug } = params\n const { isPreview, state: formState } = checkFormStatus(path)\n\n // Get the form metadata using the `slug` param\n const metadata = await formsService.getFormMetadata(slug)\n\n const { id, [formState]: state } = metadata\n\n // Check the metadata supports the requested state\n if (!state) {\n throw Boom.notFound(`No '${formState}' state for form metadata ${id}`)\n }\n\n // Cache the models based on id, state and whether\n // it's a preview or not. There could be up to 3 models\n // cached for a single form:\n // \"{id}_live_false\" (live/live)\n // \"{id}_live_true\" (live/preview)\n // \"{id}_draft_true\" (draft/preview)\n const key = `${id}_${formState}_${isPreview}`\n let item = itemCache.get(key)\n\n if (!item || !isEqual(item.updatedAt, state.updatedAt)) {\n server.logger.info(\n `Getting form definition ${id} (${slug}) ${formState}`\n )\n\n // Get the form definition using the `id` from the metadata\n const definition = await formsService.getFormDefinition(id, formState)\n\n if (!definition) {\n throw Boom.notFound(\n `No definition found for form metadata ${id} (${slug}) ${formState}`\n )\n }\n\n const emailAddress =\n metadata.notificationEmail ?? definition.outputEmail\n\n checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)\n\n // Build the form model\n server.logger.info(\n `Building model for form definition ${id} (${slug}) ${formState}`\n )\n\n // Set up the basePath for the model\n const basePath = isPreview\n ? `${PREVIEW_PATH_PREFIX.substring(1)}/${formState}/${slug}`\n : slug\n\n // Construct the form model\n const model = new FormModel(\n definition,\n { basePath },\n services,\n controllers\n )\n\n // Create new item and add it to the item cache\n item = { model, updatedAt: state.updatedAt }\n itemCache.set(key, item)\n }\n\n // Assign the model to the request data\n // for use in the downstream handler\n request.app.model = item.model\n\n return h.continue\n }\n\n const dispatchHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { model } = request.app\n\n const servicePath = model ? `/${model.basePath}` : ''\n return proceed(request, h, `${servicePath}${getStartPath(model)}`)\n }\n\n const redirectOrMakeHandler = async (\n request: FormRequest | FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>,\n makeHandler: (\n page: PageControllerClass,\n context: FormContext\n ) => ResponseObject | Promise<ResponseObject>\n ) => {\n const { app, params } = request\n const { model } = app\n\n if (!model) {\n throw Boom.notFound(`No model found for /${params.path}`)\n }\n\n const cacheService = getCacheService(request.server)\n const page = getPage(model, request)\n let state = await page.getState(request)\n\n if (!state.$$__referenceNumber) {\n const prefix = model.def.metadata?.referenceNumberPrefix ?? ''\n\n if (typeof prefix !== 'string') {\n throw Boom.badImplementation(\n 'Reference number prefix must be a string or undefined'\n )\n }\n\n const referenceNumber = generateUniqueReference(prefix)\n state = await page.mergeState(request, state, {\n $$__referenceNumber: referenceNumber\n })\n }\n\n const flash = cacheService.getFlash(request)\n const context = model.getFormContext(request, state, flash?.errors)\n const relevantPath = page.getRelevantPath(request, context)\n const summaryPath = page.getSummaryPath()\n\n // Return handler for relevant pages or preview URL direct access\n if (relevantPath.startsWith(page.path) || context.isForceAccess) {\n return makeHandler(page, context)\n }\n\n // Redirect back to last relevant page\n const redirectTo = findPage(model, relevantPath)\n\n // Set the return URL unless an exit page\n if (redirectTo?.next.length) {\n request.query.returnUrl = page.getHref(summaryPath)\n }\n\n return proceed(request, h, page.getHref(relevantPath))\n }\n\n const getHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n if (normalisePath(params.path) === '') {\n return dispatchHandler(request, h)\n }\n\n return redirectOrMakeHandler(request, h, async (page, context) => {\n // Check for a page onLoad HTTP event and if one exists,\n // call it and assign the response to the context data\n const { events } = page\n const { model } = request.app\n\n if (!model) {\n throw Boom.notFound(`No model found for /${params.path}`)\n }\n\n if (events?.onLoad && events.onLoad.type === 'http') {\n const { options } = events.onLoad\n const { url } = options\n\n // TODO: Update structured data POST payload with when helper\n // is updated to removing the dependency on `SummaryViewModel` etc.\n const viewModel = new SummaryViewModel(request, page, context)\n const items = getFormSubmissionData(\n viewModel.context,\n viewModel.details\n )\n\n // @ts-expect-error - function signature will be refactored in the next iteration of the formatter\n const payload = format(items, model, undefined, undefined)\n\n const { payload: response } = await httpService.postJson(url, {\n payload\n })\n\n Object.assign(context.data, response)\n }\n\n return page.makeGetRouteHandler()(request, context, h)\n })\n }\n\n const postHandler = (\n request: FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { query } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n const { pageDef } = page\n const { isForceAccess } = context\n\n // Redirect to GET for preview URL direct access\n if (isForceAccess && !hasFormComponents(pageDef)) {\n return proceed(request, h, redirectPath(page.href, query))\n }\n\n return page.makePostRouteHandler()(request, context, h)\n })\n }\n\n const dispatchRouteOptions: RouteOptions<FormRequestRefs> = {\n pre: [\n {\n method: loadFormPreHandler\n }\n ]\n }\n\n server.route({\n method: 'get',\n path: '/{slug}',\n handler: dispatchHandler,\n options: {\n ...dispatchRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}',\n handler: dispatchHandler,\n options: {\n ...dispatchRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema\n })\n }\n }\n })\n\n const getRouteOptions: RouteOptions<FormRequestRefs> = {\n pre: [\n {\n method: loadFormPreHandler\n }\n ]\n }\n\n server.route({\n method: 'get',\n path: '/{slug}/{path}/{itemId?}',\n handler: getHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: getHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n })\n\n const postRouteOptions: RouteOptions<FormRequestPayloadRefs> = {\n payload: {\n parse: true\n },\n pre: [{ method: loadFormPreHandler }]\n }\n\n server.route({\n method: 'post',\n path: '/{slug}/{path}/{itemId?}',\n handler: postHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n })\n\n server.route({\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: postHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n })\n\n /**\n * \"AddAnother\" repeat routes\n */\n\n // List summary GET route\n const getListSummaryHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n if (!(page instanceof RepeatPageController)) {\n throw Boom.notFound(`No repeater page found for /${params.path}`)\n }\n\n return page.makeGetListSummaryRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'get',\n path: '/{slug}/{path}/summary',\n handler: getListSummaryHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/summary',\n handler: getListSummaryHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema\n })\n }\n }\n })\n\n // List summary POST route\n const postListSummaryHandler = (\n request: FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n const { isForceAccess } = context\n\n if (isForceAccess || !(page instanceof RepeatPageController)) {\n throw Boom.notFound(`No repeater page found for /${params.path}`)\n }\n\n return page.makePostListSummaryRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'post',\n path: '/{slug}/{path}/summary',\n handler: postListSummaryHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .required()\n }\n }\n })\n\n server.route({\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/summary',\n handler: postListSummaryHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .required()\n }\n }\n })\n\n // Item delete GET route\n const getItemDeleteHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n if (\n !(\n page instanceof RepeatPageController ||\n page instanceof FileUploadPageController\n )\n ) {\n throw Boom.notFound(`No page found for /${params.path}`)\n }\n\n return page.makeGetItemDeleteRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'get',\n path: '/{slug}/{path}/{itemId}/confirm-delete',\n handler: getItemDeleteHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',\n handler: getItemDeleteHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n })\n }\n }\n })\n\n // Item delete POST route\n const postItemDeleteHandler = (\n request: FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n const { isForceAccess } = context\n\n if (\n isForceAccess ||\n !(\n page instanceof RepeatPageController ||\n page instanceof FileUploadPageController\n )\n ) {\n throw Boom.notFound(`No page found for /${params.path}`)\n }\n\n return page.makePostItemDeleteRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'post',\n path: '/{slug}/{path}/{itemId}/confirm-delete',\n handler: postItemDeleteHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema,\n confirm: confirmSchema\n })\n .required()\n }\n }\n })\n\n server.route({\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',\n handler: postItemDeleteHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema,\n confirm: confirmSchema\n })\n .required()\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/upload-status/{uploadId}',\n handler: async (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'response'>\n ) => {\n try {\n const { uploadId } = request.params as unknown as {\n uploadId: string\n }\n const status = await getUploadStatus(uploadId)\n\n if (!status) {\n return h.response({ error: 'Status check failed' }).code(400)\n }\n\n return h.response(status)\n } catch (error) {\n request.logger.error(\n ['upload-status'],\n 'Upload status check failed',\n error\n )\n return h.response({ error: 'Status check error' }).code(500)\n }\n },\n options: {\n plugins: {\n crumb: false\n },\n validate: {\n params: Joi.object().keys({\n uploadId: Joi.string().guid().required()\n })\n }\n }\n })\n }\n} satisfies Plugin<PluginOptions>\n\ninterface CompileOptions {\n environment: Environment\n}\n\nexport interface EngineConfigurationObject {\n compileOptions: CompileOptions\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"plugin.js","names":["existsSync","dirname","join","fileURLToPath","hasFormComponents","slugSchema","Boom","vision","isEqual","Joi","nunjucks","resolvePkg","PREVIEW_PATH_PREFIX","checkEmailAddressForLiveFormSubmission","checkFormStatus","findPage","getCacheService","getPage","getStartPath","normalisePath","proceed","redirectPath","VIEW_PATH","context","prepareNunjucksEnvironment","FormModel","SummaryViewModel","format","FileUploadPageController","RepeatPageController","getFormSubmissionData","generateUniqueReference","defaultServices","getUploadStatus","actionSchema","confirmSchema","crumbSchema","itemIdSchema","pathSchema","stateSchema","httpService","CacheService","findPackageRoot","currentFileName","import","meta","url","currentDirectoryName","dir","Error","plugin","name","dependencies","multiple","register","server","options","model","services","controllers","cacheName","filters","nunjucksOptions","viewContext","formsService","cacheService","packageRoot","govukFrontendPath","sync","viewPathResolved","paths","engines","html","compile","path","compileOptions","template","environment","render","prepare","next","configure","expose","baseLayoutPath","app","itemCache","Map","models","loadFormPreHandler","request","h","continue","params","slug","isPreview","state","formState","metadata","getFormMetadata","id","notFound","key","item","get","updatedAt","logger","info","definition","getFormDefinition","emailAddress","notificationEmail","outputEmail","basePath","substring","set","dispatchHandler","servicePath","redirectOrMakeHandler","makeHandler","page","getState","$$__referenceNumber","prefix","def","referenceNumberPrefix","badImplementation","referenceNumber","mergeState","flash","getFlash","getFormContext","errors","relevantPath","getRelevantPath","summaryPath","getSummaryPath","startsWith","isForceAccess","redirectTo","length","query","returnUrl","getHref","getHandler","events","onLoad","type","viewModel","items","details","payload","undefined","response","postJson","Object","assign","data","makeGetRouteHandler","postHandler","pageDef","href","makePostRouteHandler","dispatchRouteOptions","pre","method","route","handler","validate","object","keys","getRouteOptions","itemId","optional","postRouteOptions","parse","crumb","action","unknown","required","getListSummaryHandler","makeGetListSummaryRouteHandler","postListSummaryHandler","makePostListSummaryRouteHandler","getItemDeleteHandler","makeGetItemDeleteRouteHandler","postItemDeleteHandler","makePostItemDeleteRouteHandler","confirm","uploadId","status","error","code","plugins","string","guid"],"sources":["../../../../src/server/plugins/engine/plugin.ts"],"sourcesContent":["import { existsSync } from 'fs'\nimport { dirname, join } from 'path'\nimport { fileURLToPath } from 'url'\n\nimport { hasFormComponents, slugSchema } from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport {\n type Plugin,\n type ResponseObject,\n type ResponseToolkit,\n type RouteOptions,\n type Server\n} from '@hapi/hapi'\nimport vision from '@hapi/vision'\nimport { isEqual } from 'date-fns'\nimport Joi from 'joi'\nimport nunjucks, { type Environment } from 'nunjucks'\nimport resolvePkg from 'resolve'\n\nimport { PREVIEW_PATH_PREFIX } from '~/src/server/constants.js'\nimport {\n checkEmailAddressForLiveFormSubmission,\n checkFormStatus,\n findPage,\n getCacheService,\n getPage,\n getStartPath,\n normalisePath,\n proceed,\n redirectPath\n} from '~/src/server/plugins/engine/helpers.js'\nimport {\n VIEW_PATH,\n context,\n prepareNunjucksEnvironment\n} from '~/src/server/plugins/engine/index.js'\nimport {\n FormModel,\n SummaryViewModel\n} from '~/src/server/plugins/engine/models/index.js'\nimport { format } from '~/src/server/plugins/engine/outputFormatters/machine/v1.js'\nimport { FileUploadPageController } from '~/src/server/plugins/engine/pageControllers/FileUploadPageController.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { RepeatPageController } from '~/src/server/plugins/engine/pageControllers/RepeatPageController.js'\nimport { getFormSubmissionData } from '~/src/server/plugins/engine/pageControllers/SummaryPageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers.js'\nimport { generateUniqueReference } from '~/src/server/plugins/engine/referenceNumbers.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport { getUploadStatus } from '~/src/server/plugins/engine/services/uploadService.js'\nimport {\n type FilterFunction,\n type FormContext\n} from '~/src/server/plugins/engine/types.js'\nimport {\n type FormRequest,\n type FormRequestPayload,\n type FormRequestPayloadRefs,\n type FormRequestRefs\n} from '~/src/server/routes/types.js'\nimport {\n actionSchema,\n confirmSchema,\n crumbSchema,\n itemIdSchema,\n pathSchema,\n stateSchema\n} from '~/src/server/schemas/index.js'\nimport * as httpService from '~/src/server/services/httpService.js'\nimport { CacheService } from '~/src/server/services/index.js'\nimport { type Services } from '~/src/server/types.js'\n\nexport function findPackageRoot() {\n const currentFileName = fileURLToPath(import.meta.url)\n const currentDirectoryName = dirname(currentFileName)\n\n let dir = currentDirectoryName\n while (dir !== '/') {\n if (existsSync(join(dir, 'package.json'))) {\n return dir\n }\n dir = dirname(dir)\n }\n\n throw new Error('package.json not found in parent directories')\n}\nexport interface PluginOptions {\n model?: FormModel\n services?: Services\n controllers?: Record<string, typeof PageController>\n cacheName?: string\n viewPaths?: string[]\n filters?: Record<string, FilterFunction>\n pluginPath?: string\n nunjucks: {\n baseLayoutPath: string\n paths: string[]\n }\n viewContext: (\n request: FormRequest | FormRequestPayload | null\n ) => Record<string, unknown>\n}\n\nexport const plugin = {\n name: '@defra/forms-engine-plugin',\n dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],\n multiple: true,\n async register(server: Server, options: PluginOptions) {\n const {\n model,\n services = defaultServices,\n controllers,\n cacheName,\n filters,\n nunjucks: nunjucksOptions,\n viewContext\n } = options\n const { formsService } = services\n const cacheService = new CacheService(server, cacheName)\n\n const packageRoot = findPackageRoot()\n const govukFrontendPath = dirname(\n resolvePkg.sync('govuk-frontend/package.json')\n )\n\n const viewPathResolved = join(packageRoot, VIEW_PATH)\n\n const paths = [\n ...nunjucksOptions.paths,\n viewPathResolved,\n join(govukFrontendPath, 'dist')\n ]\n\n await server.register({\n plugin: vision,\n options: {\n engines: {\n html: {\n compile: (\n path: string,\n compileOptions: { environment: Environment }\n ) => {\n const template = nunjucks.compile(\n path,\n compileOptions.environment\n )\n\n return (context: object | undefined) => {\n return template.render(context)\n }\n },\n prepare: (\n options: EngineConfigurationObject,\n next: (err?: Error) => void\n ) => {\n // Nunjucks also needs an additional path configuration\n // to use the templates and macros from `govuk-frontend`\n const environment = nunjucks.configure(paths)\n\n // Applies custom filters and globals for nunjucks\n // that are required by the `forms-engine-plugin`\n prepareNunjucksEnvironment(environment, filters)\n\n options.compileOptions.environment = environment\n\n next()\n }\n }\n },\n path: paths,\n // Provides global context used with all templates\n context\n }\n })\n\n server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath)\n server.expose('viewContext', viewContext)\n server.expose('cacheService', cacheService)\n\n server.app.model = model\n\n // In-memory cache of FormModel items, exposed\n // (for testing purposes) through `server.app.models`\n const itemCache = new Map<string, { model: FormModel; updatedAt: Date }>()\n server.app.models = itemCache\n\n const loadFormPreHandler = async (\n request: FormRequest | FormRequestPayload,\n h: Pick<ResponseToolkit, 'continue'>\n ) => {\n if (server.app.model) {\n request.app.model = server.app.model\n\n return h.continue\n }\n\n const { params, path } = request\n const { slug } = params\n const { isPreview, state: formState } = checkFormStatus(path)\n\n // Get the form metadata using the `slug` param\n const metadata = await formsService.getFormMetadata(slug)\n\n const { id, [formState]: state } = metadata\n\n // Check the metadata supports the requested state\n if (!state) {\n throw Boom.notFound(`No '${formState}' state for form metadata ${id}`)\n }\n\n // Cache the models based on id, state and whether\n // it's a preview or not. There could be up to 3 models\n // cached for a single form:\n // \"{id}_live_false\" (live/live)\n // \"{id}_live_true\" (live/preview)\n // \"{id}_draft_true\" (draft/preview)\n const key = `${id}_${formState}_${isPreview}`\n let item = itemCache.get(key)\n\n if (!item || !isEqual(item.updatedAt, state.updatedAt)) {\n server.logger.info(\n `Getting form definition ${id} (${slug}) ${formState}`\n )\n\n // Get the form definition using the `id` from the metadata\n const definition = await formsService.getFormDefinition(id, formState)\n\n if (!definition) {\n throw Boom.notFound(\n `No definition found for form metadata ${id} (${slug}) ${formState}`\n )\n }\n\n const emailAddress =\n metadata.notificationEmail ?? definition.outputEmail\n\n checkEmailAddressForLiveFormSubmission(emailAddress, isPreview)\n\n // Build the form model\n server.logger.info(\n `Building model for form definition ${id} (${slug}) ${formState}`\n )\n\n // Set up the basePath for the model\n const basePath = isPreview\n ? `${PREVIEW_PATH_PREFIX.substring(1)}/${formState}/${slug}`\n : slug\n\n // Construct the form model\n const model = new FormModel(\n definition,\n { basePath },\n services,\n controllers\n )\n\n // Create new item and add it to the item cache\n item = { model, updatedAt: state.updatedAt }\n itemCache.set(key, item)\n }\n\n // Assign the model to the request data\n // for use in the downstream handler\n request.app.model = item.model\n\n return h.continue\n }\n\n const dispatchHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { model } = request.app\n\n const servicePath = model ? `/${model.basePath}` : ''\n return proceed(request, h, `${servicePath}${getStartPath(model)}`)\n }\n\n const redirectOrMakeHandler = async (\n request: FormRequest | FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>,\n makeHandler: (\n page: PageControllerClass,\n context: FormContext\n ) => ResponseObject | Promise<ResponseObject>\n ) => {\n const { app, params } = request\n const { model } = app\n\n if (!model) {\n throw Boom.notFound(`No model found for /${params.path}`)\n }\n\n const cacheService = getCacheService(request.server)\n const page = getPage(model, request)\n let state = await page.getState(request)\n\n if (!state.$$__referenceNumber) {\n const prefix = model.def.metadata?.referenceNumberPrefix ?? ''\n\n if (typeof prefix !== 'string') {\n throw Boom.badImplementation(\n 'Reference number prefix must be a string or undefined'\n )\n }\n\n const referenceNumber = generateUniqueReference(prefix)\n state = await page.mergeState(request, state, {\n $$__referenceNumber: referenceNumber\n })\n }\n\n const flash = cacheService.getFlash(request)\n const context = model.getFormContext(request, state, flash?.errors)\n const relevantPath = page.getRelevantPath(request, context)\n const summaryPath = page.getSummaryPath()\n\n // Return handler for relevant pages or preview URL direct access\n if (relevantPath.startsWith(page.path) || context.isForceAccess) {\n return makeHandler(page, context)\n }\n\n // Redirect back to last relevant page\n const redirectTo = findPage(model, relevantPath)\n\n // Set the return URL unless an exit page\n if (redirectTo?.next.length) {\n request.query.returnUrl = page.getHref(summaryPath)\n }\n\n return proceed(request, h, page.getHref(relevantPath))\n }\n\n const getHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n if (normalisePath(params.path) === '') {\n return dispatchHandler(request, h)\n }\n\n return redirectOrMakeHandler(request, h, async (page, context) => {\n // Check for a page onLoad HTTP event and if one exists,\n // call it and assign the response to the context data\n const { events } = page\n const { model } = request.app\n\n if (!model) {\n throw Boom.notFound(`No model found for /${params.path}`)\n }\n\n if (events?.onLoad && events.onLoad.type === 'http') {\n const { options } = events.onLoad\n const { url } = options\n\n // TODO: Update structured data POST payload with when helper\n // is updated to removing the dependency on `SummaryViewModel` etc.\n const viewModel = new SummaryViewModel(request, page, context)\n const items = getFormSubmissionData(\n viewModel.context,\n viewModel.details\n )\n\n // @ts-expect-error - function signature will be refactored in the next iteration of the formatter\n const payload = format(items, model, undefined, undefined)\n\n const { payload: response } = await httpService.postJson(url, {\n payload\n })\n\n Object.assign(context.data, response)\n }\n\n return page.makeGetRouteHandler()(request, context, h)\n })\n }\n\n const postHandler = (\n request: FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { query } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n const { pageDef } = page\n const { isForceAccess } = context\n\n // Redirect to GET for preview URL direct access\n if (isForceAccess && !hasFormComponents(pageDef)) {\n return proceed(request, h, redirectPath(page.href, query))\n }\n\n return page.makePostRouteHandler()(request, context, h)\n })\n }\n\n const dispatchRouteOptions: RouteOptions<FormRequestRefs> = {\n pre: [\n {\n method: loadFormPreHandler\n }\n ]\n }\n\n server.route({\n method: 'get',\n path: '/{slug}',\n handler: dispatchHandler,\n options: {\n ...dispatchRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}',\n handler: dispatchHandler,\n options: {\n ...dispatchRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema\n })\n }\n }\n })\n\n const getRouteOptions: RouteOptions<FormRequestRefs> = {\n pre: [\n {\n method: loadFormPreHandler\n }\n ]\n }\n\n server.route({\n method: 'get',\n path: '/{slug}/{path}/{itemId?}',\n handler: getHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: getHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n })\n }\n }\n })\n\n const postRouteOptions: RouteOptions<FormRequestPayloadRefs> = {\n payload: {\n parse: true\n },\n pre: [{ method: loadFormPreHandler }]\n }\n\n server.route({\n method: 'post',\n path: '/{slug}/{path}/{itemId?}',\n handler: postHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n })\n\n server.route({\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/{itemId?}',\n handler: postHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema.optional()\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .unknown(true)\n .required()\n }\n }\n })\n\n /**\n * \"AddAnother\" repeat routes\n */\n\n // List summary GET route\n const getListSummaryHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n if (!(page instanceof RepeatPageController)) {\n throw Boom.notFound(`No repeater page found for /${params.path}`)\n }\n\n return page.makeGetListSummaryRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'get',\n path: '/{slug}/{path}/summary',\n handler: getListSummaryHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/summary',\n handler: getListSummaryHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema\n })\n }\n }\n })\n\n // List summary POST route\n const postListSummaryHandler = (\n request: FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n const { isForceAccess } = context\n\n if (isForceAccess || !(page instanceof RepeatPageController)) {\n throw Boom.notFound(`No repeater page found for /${params.path}`)\n }\n\n return page.makePostListSummaryRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'post',\n path: '/{slug}/{path}/summary',\n handler: postListSummaryHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .required()\n }\n }\n })\n\n server.route({\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/summary',\n handler: postListSummaryHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema\n })\n .required()\n }\n }\n })\n\n // Item delete GET route\n const getItemDeleteHandler = (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n if (\n !(\n page instanceof RepeatPageController ||\n page instanceof FileUploadPageController\n )\n ) {\n throw Boom.notFound(`No page found for /${params.path}`)\n }\n\n return page.makeGetItemDeleteRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'get',\n path: '/{slug}/{path}/{itemId}/confirm-delete',\n handler: getItemDeleteHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n })\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',\n handler: getItemDeleteHandler,\n options: {\n ...getRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n })\n }\n }\n })\n\n // Item delete POST route\n const postItemDeleteHandler = (\n request: FormRequestPayload,\n h: Pick<ResponseToolkit, 'redirect' | 'view'>\n ) => {\n const { params } = request\n\n return redirectOrMakeHandler(request, h, (page, context) => {\n const { isForceAccess } = context\n\n if (\n isForceAccess ||\n !(\n page instanceof RepeatPageController ||\n page instanceof FileUploadPageController\n )\n ) {\n throw Boom.notFound(`No page found for /${params.path}`)\n }\n\n return page.makePostItemDeleteRouteHandler()(request, context, h)\n })\n }\n\n server.route({\n method: 'post',\n path: '/{slug}/{path}/{itemId}/confirm-delete',\n handler: postItemDeleteHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema,\n confirm: confirmSchema\n })\n .required()\n }\n }\n })\n\n server.route({\n method: 'post',\n path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',\n handler: postItemDeleteHandler,\n options: {\n ...postRouteOptions,\n validate: {\n params: Joi.object().keys({\n state: stateSchema,\n slug: slugSchema,\n path: pathSchema,\n itemId: itemIdSchema\n }),\n payload: Joi.object()\n .keys({\n crumb: crumbSchema,\n action: actionSchema,\n confirm: confirmSchema\n })\n .required()\n }\n }\n })\n\n server.route({\n method: 'get',\n path: '/upload-status/{uploadId}',\n handler: async (\n request: FormRequest,\n h: Pick<ResponseToolkit, 'response'>\n ) => {\n try {\n const { uploadId } = request.params as unknown as {\n uploadId: string\n }\n const status = await getUploadStatus(uploadId)\n\n if (!status) {\n return h.response({ error: 'Status check failed' }).code(400)\n }\n\n return h.response(status)\n } catch (error) {\n request.logger.error(\n ['upload-status'],\n 'Upload status check failed',\n error\n )\n return h.response({ error: 'Status check error' }).code(500)\n }\n },\n options: {\n plugins: {\n crumb: false\n },\n validate: {\n params: Joi.object().keys({\n uploadId: Joi.string().guid().required()\n })\n }\n }\n })\n }\n} satisfies Plugin<PluginOptions>\n\ninterface CompileOptions {\n environment: Environment\n}\n\nexport interface EngineConfigurationObject {\n compileOptions: CompileOptions\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,41 +1,27 @@
1
- import { formMetadataSchema } from '@defra/forms-model';
2
- import { config } from "../../../../config/index.js";
3
- import { FormStatus } from "../../../routes/types.js";
4
- import { getJson } from "../../../services/httpService.js";
1
+ const error = Error('Not implemented. Consider setting up a form loader or providing a service implementation.');
5
2
 
3
+ // eslint-disable-next-line jsdoc/require-returns-check
6
4
  /**
7
- * Retrieves a form definition from the form manager for a given slug
8
- * @param {string} slug - the slug of the form
5
+ * Dummy function to get form metadata.
6
+ * @param {string} _slug - the slug of the form
7
+ * @returns {Promise<FormMetadata>}
9
8
  */
10
- export async function getFormMetadata(slug) {
11
- const getJsonByType = /** @type {typeof getJson<FormMetadata>} */getJson;
12
- const {
13
- payload: metadata
14
- } = await getJsonByType(`${config.get('managerUrl')}/forms/slug/${slug}`);
15
-
16
- // Run it through the schema to coerce dates
17
- const result = formMetadataSchema.validate(metadata);
18
- if (result.error) {
19
- throw result.error;
20
- }
21
- return result.value;
9
+ export function getFormMetadata(_slug) {
10
+ throw error;
22
11
  }
23
12
 
13
+ // eslint-disable-next-line jsdoc/require-returns-check
24
14
  /**
25
- * Retrieves a form definition from the form manager for a given id
26
- * @param {string} id - the id of the form
27
- * @param {FormStatus} state - the state of the form
15
+ * Dummy function to get form metadata.
16
+ * @param {string} _id - the id of the form
17
+ * @param {FormStatus} _state - the state of the form
18
+ * @returns {Promise<FormDefinition | undefined>}
28
19
  */
29
- export async function getFormDefinition(id, state) {
30
- const getJsonByType = /** @type {typeof getJson<FormDefinition>} */getJson;
31
- const suffix = state === FormStatus.Draft ? `/${state}` : '';
32
- const {
33
- payload: definition
34
- } = await getJsonByType(`${config.get('managerUrl')}/forms/${id}/definition${suffix}`);
35
- return definition;
20
+ export function getFormDefinition(_id, _state) {
21
+ throw error;
36
22
  }
37
23
 
38
24
  /**
39
- * @import { FormDefinition, FormMetadata } from '@defra/forms-model'
25
+ * @import { FormStatus, FormDefinition, FormMetadata } from '@defra/forms-model'
40
26
  */
41
27
  //# sourceMappingURL=formsService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"formsService.js","names":["formMetadataSchema","config","FormStatus","getJson","getFormMetadata","slug","getJsonByType","payload","metadata","get","result","validate","error","value","getFormDefinition","id","state","suffix","Draft","definition"],"sources":["../../../../../src/server/plugins/engine/services/formsService.js"],"sourcesContent":["import { formMetadataSchema } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { FormStatus } from '~/src/server/routes/types.js'\nimport { getJson } from '~/src/server/services/httpService.js'\n\n/**\n * Retrieves a form definition from the form manager for a given slug\n * @param {string} slug - the slug of the form\n */\nexport async function getFormMetadata(slug) {\n const getJsonByType = /** @type {typeof getJson<FormMetadata>} */ (getJson)\n\n const { payload: metadata } = await getJsonByType(\n `${config.get('managerUrl')}/forms/slug/${slug}`\n )\n\n // Run it through the schema to coerce dates\n const result = formMetadataSchema.validate(metadata)\n\n if (result.error) {\n throw result.error\n }\n\n return result.value\n}\n\n/**\n * Retrieves a form definition from the form manager for a given id\n * @param {string} id - the id of the form\n * @param {FormStatus} state - the state of the form\n */\nexport async function getFormDefinition(id, state) {\n const getJsonByType = /** @type {typeof getJson<FormDefinition>} */ (getJson)\n\n const suffix = state === FormStatus.Draft ? `/${state}` : ''\n const { payload: definition } = await getJsonByType(\n `${config.get('managerUrl')}/forms/${id}/definition${suffix}`\n )\n\n return definition\n}\n\n/**\n * @import { FormDefinition, FormMetadata } from '@defra/forms-model'\n */\n"],"mappings":"AAAA,SAASA,kBAAkB,QAAQ,oBAAoB;AAEvD,SAASC,MAAM;AACf,SAASC,UAAU;AACnB,SAASC,OAAO;;AAEhB;AACA;AACA;AACA;AACA,OAAO,eAAeC,eAAeA,CAACC,IAAI,EAAE;EAC1C,MAAMC,aAAa,GAAG,2CAA6CH,OAAQ;EAE3E,MAAM;IAAEI,OAAO,EAAEC;EAAS,CAAC,GAAG,MAAMF,aAAa,CAC/C,GAAGL,MAAM,CAACQ,GAAG,CAAC,YAAY,CAAC,eAAeJ,IAAI,EAChD,CAAC;;EAED;EACA,MAAMK,MAAM,GAAGV,kBAAkB,CAACW,QAAQ,CAACH,QAAQ,CAAC;EAEpD,IAAIE,MAAM,CAACE,KAAK,EAAE;IAChB,MAAMF,MAAM,CAACE,KAAK;EACpB;EAEA,OAAOF,MAAM,CAACG,KAAK;AACrB;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,iBAAiBA,CAACC,EAAE,EAAEC,KAAK,EAAE;EACjD,MAAMV,aAAa,GAAG,6CAA+CH,OAAQ;EAE7E,MAAMc,MAAM,GAAGD,KAAK,KAAKd,UAAU,CAACgB,KAAK,GAAG,IAAIF,KAAK,EAAE,GAAG,EAAE;EAC5D,MAAM;IAAET,OAAO,EAAEY;EAAW,CAAC,GAAG,MAAMb,aAAa,CACjD,GAAGL,MAAM,CAACQ,GAAG,CAAC,YAAY,CAAC,UAAUM,EAAE,cAAcE,MAAM,EAC7D,CAAC;EAED,OAAOE,UAAU;AACnB;;AAEA;AACA;AACA","ignoreList":[]}
1
+ {"version":3,"file":"formsService.js","names":["error","Error","getFormMetadata","_slug","getFormDefinition","_id","_state"],"sources":["../../../../../src/server/plugins/engine/services/formsService.js"],"sourcesContent":["const error = Error(\n 'Not implemented. Consider setting up a form loader or providing a service implementation.'\n)\n\n// eslint-disable-next-line jsdoc/require-returns-check\n/**\n * Dummy function to get form metadata.\n * @param {string} _slug - the slug of the form\n * @returns {Promise<FormMetadata>}\n */\nexport function getFormMetadata(_slug) {\n throw error\n}\n\n// eslint-disable-next-line jsdoc/require-returns-check\n/**\n * Dummy function to get form metadata.\n * @param {string} _id - the id of the form\n * @param {FormStatus} _state - the state of the form\n * @returns {Promise<FormDefinition | undefined>}\n */\nexport function getFormDefinition(_id, _state) {\n throw error\n}\n\n/**\n * @import { FormStatus, FormDefinition, FormMetadata } from '@defra/forms-model'\n */\n"],"mappings":"AAAA,MAAMA,KAAK,GAAGC,KAAK,CACjB,2FACF,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAACC,KAAK,EAAE;EACrC,MAAMH,KAAK;AACb;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,iBAAiBA,CAACC,GAAG,EAAEC,MAAM,EAAE;EAC7C,MAAMN,KAAK;AACb;;AAEA;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,52 @@
1
+ import { config } from "../../../../config/index.js";
2
+ import { FileFormService } from "../../../utils/file-form-service.js";
3
+
4
+ // Create shared form metadata
5
+ const now = new Date();
6
+ const user = {
7
+ id: 'user',
8
+ displayName: 'Username'
9
+ };
10
+ const author = {
11
+ createdAt: now,
12
+ createdBy: user,
13
+ updatedAt: now,
14
+ updatedBy: user
15
+ };
16
+ const metadata = {
17
+ organisation: 'Defra',
18
+ teamName: 'Team name',
19
+ teamEmail: 'team@defra.gov.uk',
20
+ submissionGuidance: "Thanks for your submission, we'll be in touch",
21
+ notificationEmail: config.get('submissionEmailAddress'),
22
+ ...author,
23
+ live: author
24
+ };
25
+
26
+ /**
27
+ * Return an function rather than the service directly. This is to prevent consumer applications
28
+ * blowing up as they won't have these files on disk. We can defer the execution until when it's
29
+ * needed, i.e. the createServer function of the devtool.
30
+ */
31
+ export const formsService = async () => {
32
+ // Instantiate the file loader form service
33
+ const loader = new FileFormService();
34
+
35
+ // Add a Json form
36
+ await loader.addForm('src/server/forms/register-as-a-unicorn-breeder.json', {
37
+ ...metadata,
38
+ id: '95e92559-968d-44ae-8666-2b1ad3dffd31',
39
+ title: 'Register as a unicorn breeder',
40
+ slug: 'register-as-a-unicorn-breeder'
41
+ });
42
+
43
+ // Add a Yaml form
44
+ await loader.addForm('src/server/forms/register-as-a-unicorn-breeder.yaml', {
45
+ ...metadata,
46
+ id: '641aeafd-13dd-40fa-9186-001703800efb',
47
+ title: 'Register as a unicorn breeder (yaml)',
48
+ slug: 'register-as-a-unicorn-breeder-yaml' // if we needed to validate any JSON logic, make it available for convenience
49
+ });
50
+ return loader.toFormsService();
51
+ };
52
+ //# sourceMappingURL=localFormsService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"localFormsService.js","names":["config","FileFormService","now","Date","user","id","displayName","author","createdAt","createdBy","updatedAt","updatedBy","metadata","organisation","teamName","teamEmail","submissionGuidance","notificationEmail","get","live","formsService","loader","addForm","title","slug","toFormsService"],"sources":["../../../../../src/server/plugins/engine/services/localFormsService.js"],"sourcesContent":["import { config } from '~/src/config/index.js'\nimport { FileFormService } from '~/src/server/utils/file-form-service.js'\n\n// Create shared form metadata\nconst now = new Date()\nconst user = { id: 'user', displayName: 'Username' }\nconst author = {\n createdAt: now,\n createdBy: user,\n updatedAt: now,\n updatedBy: user\n}\nconst metadata = {\n organisation: 'Defra',\n teamName: 'Team name',\n teamEmail: 'team@defra.gov.uk',\n submissionGuidance: \"Thanks for your submission, we'll be in touch\",\n notificationEmail: config.get('submissionEmailAddress'),\n ...author,\n live: author\n}\n\n/**\n * Return an function rather than the service directly. This is to prevent consumer applications\n * blowing up as they won't have these files on disk. We can defer the execution until when it's\n * needed, i.e. the createServer function of the devtool.\n */\nexport const formsService = async () => {\n // Instantiate the file loader form service\n const loader = new FileFormService()\n\n // Add a Json form\n await loader.addForm('src/server/forms/register-as-a-unicorn-breeder.json', {\n ...metadata,\n id: '95e92559-968d-44ae-8666-2b1ad3dffd31',\n title: 'Register as a unicorn breeder',\n slug: 'register-as-a-unicorn-breeder'\n })\n\n // Add a Yaml form\n await loader.addForm('src/server/forms/register-as-a-unicorn-breeder.yaml', {\n ...metadata,\n id: '641aeafd-13dd-40fa-9186-001703800efb',\n title: 'Register as a unicorn breeder (yaml)',\n slug: 'register-as-a-unicorn-breeder-yaml' // if we needed to validate any JSON logic, make it available for convenience\n })\n\n return loader.toFormsService()\n}\n"],"mappings":"AAAA,SAASA,MAAM;AACf,SAASC,eAAe;;AAExB;AACA,MAAMC,GAAG,GAAG,IAAIC,IAAI,CAAC,CAAC;AACtB,MAAMC,IAAI,GAAG;EAAEC,EAAE,EAAE,MAAM;EAAEC,WAAW,EAAE;AAAW,CAAC;AACpD,MAAMC,MAAM,GAAG;EACbC,SAAS,EAAEN,GAAG;EACdO,SAAS,EAAEL,IAAI;EACfM,SAAS,EAAER,GAAG;EACdS,SAAS,EAAEP;AACb,CAAC;AACD,MAAMQ,QAAQ,GAAG;EACfC,YAAY,EAAE,OAAO;EACrBC,QAAQ,EAAE,WAAW;EACrBC,SAAS,EAAE,mBAAmB;EAC9BC,kBAAkB,EAAE,+CAA+C;EACnEC,iBAAiB,EAAEjB,MAAM,CAACkB,GAAG,CAAC,wBAAwB,CAAC;EACvD,GAAGX,MAAM;EACTY,IAAI,EAAEZ;AACR,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMa,YAAY,GAAG,MAAAA,CAAA,KAAY;EACtC;EACA,MAAMC,MAAM,GAAG,IAAIpB,eAAe,CAAC,CAAC;;EAEpC;EACA,MAAMoB,MAAM,CAACC,OAAO,CAAC,qDAAqD,EAAE;IAC1E,GAAGV,QAAQ;IACXP,EAAE,EAAE,sCAAsC;IAC1CkB,KAAK,EAAE,+BAA+B;IACtCC,IAAI,EAAE;EACR,CAAC,CAAC;;EAEF;EACA,MAAMH,MAAM,CAACC,OAAO,CAAC,qDAAqD,EAAE;IAC1E,GAAGV,QAAQ;IACXP,EAAE,EAAE,sCAAsC;IAC1CkB,KAAK,EAAE,sCAAsC;IAC7CC,IAAI,EAAE,oCAAoC,CAAC;EAC7C,CAAC,CAAC;EAEF,OAAOH,MAAM,CAACI,cAAc,CAAC,CAAC;AAChC,CAAC","ignoreList":[]}
@@ -1,4 +1,4 @@
1
- {% extends "layout.html" %}
1
+ {% extends baseLayoutPath %}
2
2
 
3
3
  {% from "govuk/components/panel/macro.njk" import govukPanel %}
4
4
 
@@ -35,7 +35,7 @@
35
35
  {% block bodyEnd %}
36
36
  {{ super() }}
37
37
  <script type="module" nonce="{{ cspNonce }}">
38
- import { initFileUpload } from '{{ getAssetPath("file-upload.js") }}';
38
+ import { initFileUpload } from '{{ getDxtAssetPath("file-upload.js") }}';
39
39
  if (document.readyState === 'loading') {
40
40
  document.addEventListener('DOMContentLoaded', initFileUpload);
41
41
  } else {
@@ -1,4 +1,4 @@
1
- {% extends 'layout.html' %}
1
+ {% extends baseLayoutPath %}
2
2
 
3
3
  {% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
4
4
  {% from "partials/components.html" import componentList with context %}
@@ -1,4 +1,4 @@
1
- {% extends "layout.html" %}
1
+ {% extends baseLayoutPath %}
2
2
 
3
3
  {% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
4
4
  {% from "govuk/components/button/macro.njk" import govukButton %}
@@ -1,4 +1,4 @@
1
- {% extends "layout.html" %}
1
+ {% extends baseLayoutPath %}
2
2
 
3
3
  {% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
4
4
  {% from "govuk/components/button/macro.njk" import govukButton %}
@@ -1,4 +1,4 @@
1
- {% extends "layout.html" %}
1
+ {% extends baseLayoutPath %}
2
2
 
3
3
  {% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
4
4
  {% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
@@ -1,5 +1,3 @@
1
- import { StatusCodes } from 'http-status-codes';
2
-
3
1
  /*
4
2
  * Add an `onPreResponse` listener to return error pages
5
3
  */
@@ -13,33 +11,13 @@ export default {
13
11
  // An error was raised during
14
12
  // processing the request
15
13
  const statusCode = response.output.statusCode;
16
-
17
- // Check for a form model on the request
18
- // and use it to set the correct service name
19
- // and start page path. In the event of a error
20
- // happening inside a "form" level request, the header
21
- // then displays the contextual form text and href
22
- const model = request.app.model;
23
- const viewModel = model ? {
24
- name: model.name,
25
- serviceUrl: `/${model.basePath}`
26
- } : undefined;
27
-
28
- // In the event of 404
29
- // return the `404` view
30
- if (statusCode === StatusCodes.NOT_FOUND.valueOf()) {
31
- return h.view('404', viewModel).code(statusCode);
32
- }
33
- request.log('error', {
14
+ const error = {
34
15
  statusCode,
35
- data: response.data,
36
16
  message: response.message,
37
17
  stack: response.stack
38
- });
39
- request.logger.error(response.stack);
40
-
41
- // The return the `500` view
42
- return h.view('500', viewModel).code(statusCode);
18
+ };
19
+ request.log('error', error);
20
+ return h.response(error).code(statusCode);
43
21
  }
44
22
  return h.continue;
45
23
  });
@@ -1 +1 @@
1
- {"version":3,"file":"errorPages.js","names":["StatusCodes","plugin","name","register","server","ext","request","h","response","isBoom","statusCode","output","model","app","viewModel","serviceUrl","basePath","undefined","NOT_FOUND","valueOf","view","code","log","data","message","stack","logger","error","continue"],"sources":["../../../src/server/plugins/errorPages.ts"],"sourcesContent":["import {\n type Request,\n type ResponseToolkit,\n type ServerRegisterPluginObject\n} from '@hapi/hapi'\nimport { StatusCodes } from 'http-status-codes'\n\n/*\n * Add an `onPreResponse` listener to return error pages\n */\nexport default {\n plugin: {\n name: 'error-pages',\n register(server) {\n server.ext('onPreResponse', (request: Request, h: ResponseToolkit) => {\n const response = request.response\n\n if ('isBoom' in response && response.isBoom) {\n // An error was raised during\n // processing the request\n const statusCode = response.output.statusCode\n\n // Check for a form model on the request\n // and use it to set the correct service name\n // and start page path. In the event of a error\n // happening inside a \"form\" level request, the header\n // then displays the contextual form text and href\n const model = request.app.model\n const viewModel = model\n ? {\n name: model.name,\n serviceUrl: `/${model.basePath}`\n }\n : undefined\n\n // In the event of 404\n // return the `404` view\n if (statusCode === StatusCodes.NOT_FOUND.valueOf()) {\n return h.view('404', viewModel).code(statusCode)\n }\n\n request.log('error', {\n statusCode,\n data: response.data,\n message: response.message,\n stack: response.stack\n })\n\n request.logger.error(response.stack)\n\n // The return the `500` view\n return h.view('500', viewModel).code(statusCode)\n }\n return h.continue\n })\n }\n }\n} satisfies ServerRegisterPluginObject<void>\n"],"mappings":"AAKA,SAASA,WAAW,QAAQ,mBAAmB;;AAE/C;AACA;AACA;AACA,eAAe;EACbC,MAAM,EAAE;IACNC,IAAI,EAAE,aAAa;IACnBC,QAAQA,CAACC,MAAM,EAAE;MACfA,MAAM,CAACC,GAAG,CAAC,eAAe,EAAE,CAACC,OAAgB,EAAEC,CAAkB,KAAK;QACpE,MAAMC,QAAQ,GAAGF,OAAO,CAACE,QAAQ;QAEjC,IAAI,QAAQ,IAAIA,QAAQ,IAAIA,QAAQ,CAACC,MAAM,EAAE;UAC3C;UACA;UACA,MAAMC,UAAU,GAAGF,QAAQ,CAACG,MAAM,CAACD,UAAU;;UAE7C;UACA;UACA;UACA;UACA;UACA,MAAME,KAAK,GAAGN,OAAO,CAACO,GAAG,CAACD,KAAK;UAC/B,MAAME,SAAS,GAAGF,KAAK,GACnB;YACEV,IAAI,EAAEU,KAAK,CAACV,IAAI;YAChBa,UAAU,EAAE,IAAIH,KAAK,CAACI,QAAQ;UAChC,CAAC,GACDC,SAAS;;UAEb;UACA;UACA,IAAIP,UAAU,KAAKV,WAAW,CAACkB,SAAS,CAACC,OAAO,CAAC,CAAC,EAAE;YAClD,OAAOZ,CAAC,CAACa,IAAI,CAAC,KAAK,EAAEN,SAAS,CAAC,CAACO,IAAI,CAACX,UAAU,CAAC;UAClD;UAEAJ,OAAO,CAACgB,GAAG,CAAC,OAAO,EAAE;YACnBZ,UAAU;YACVa,IAAI,EAAEf,QAAQ,CAACe,IAAI;YACnBC,OAAO,EAAEhB,QAAQ,CAACgB,OAAO;YACzBC,KAAK,EAAEjB,QAAQ,CAACiB;UAClB,CAAC,CAAC;UAEFnB,OAAO,CAACoB,MAAM,CAACC,KAAK,CAACnB,QAAQ,CAACiB,KAAK,CAAC;;UAEpC;UACA,OAAOlB,CAAC,CAACa,IAAI,CAAC,KAAK,EAAEN,SAAS,CAAC,CAACO,IAAI,CAACX,UAAU,CAAC;QAClD;QACA,OAAOH,CAAC,CAACqB,QAAQ;MACnB,CAAC,CAAC;IACJ;EACF;AACF,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"errorPages.js","names":["plugin","name","register","server","ext","request","h","response","isBoom","statusCode","output","error","message","stack","log","code","continue"],"sources":["../../../src/server/plugins/errorPages.ts"],"sourcesContent":["import {\n type Request,\n type ResponseToolkit,\n type ServerRegisterPluginObject\n} from '@hapi/hapi'\n\n/*\n * Add an `onPreResponse` listener to return error pages\n */\nexport default {\n plugin: {\n name: 'error-pages',\n register(server) {\n server.ext('onPreResponse', (request: Request, h: ResponseToolkit) => {\n const response = request.response\n\n if ('isBoom' in response && response.isBoom) {\n // An error was raised during\n // processing the request\n const statusCode = response.output.statusCode\n\n const error = {\n statusCode,\n message: response.message,\n stack: response.stack\n }\n\n request.log('error', error)\n\n return h.response(error).code(statusCode)\n }\n return h.continue\n })\n }\n }\n} satisfies ServerRegisterPluginObject<void>\n"],"mappings":"AAMA;AACA;AACA;AACA,eAAe;EACbA,MAAM,EAAE;IACNC,IAAI,EAAE,aAAa;IACnBC,QAAQA,CAACC,MAAM,EAAE;MACfA,MAAM,CAACC,GAAG,CAAC,eAAe,EAAE,CAACC,OAAgB,EAAEC,CAAkB,KAAK;QACpE,MAAMC,QAAQ,GAAGF,OAAO,CAACE,QAAQ;QAEjC,IAAI,QAAQ,IAAIA,QAAQ,IAAIA,QAAQ,CAACC,MAAM,EAAE;UAC3C;UACA;UACA,MAAMC,UAAU,GAAGF,QAAQ,CAACG,MAAM,CAACD,UAAU;UAE7C,MAAME,KAAK,GAAG;YACZF,UAAU;YACVG,OAAO,EAAEL,QAAQ,CAACK,OAAO;YACzBC,KAAK,EAAEN,QAAQ,CAACM;UAClB,CAAC;UAEDR,OAAO,CAACS,GAAG,CAAC,OAAO,EAAEH,KAAK,CAAC;UAE3B,OAAOL,CAAC,CAACC,QAAQ,CAACI,KAAK,CAAC,CAACI,IAAI,CAACN,UAAU,CAAC;QAC3C;QACA,OAAOH,CAAC,CAACU,QAAQ;MACnB,CAAC,CAAC;IACJ;EACF;AACF,CAAC","ignoreList":[]}
@@ -3,7 +3,6 @@ import { basename, join } from 'node:path';
3
3
  import Boom from '@hapi/boom';
4
4
  import { StatusCodes } from 'http-status-codes';
5
5
  import pkg from "../../../../package.json" with { type: 'json' };
6
- import { parseCookieConsent } from "../../../common/cookies.js";
7
6
  import { config } from "../../../config/index.js";
8
7
  import { createLogger } from "../../common/helpers/logging/logger.js";
9
8
  import { PREVIEW_PATH_PREFIX } from "../../constants.js";
@@ -17,62 +16,72 @@ let webpackManifest;
17
16
  * @param {FormRequest | FormRequestPayload | null} request
18
17
  */
19
18
  export function context(request) {
20
- const manifestPath = join(config.get('publicDir'), 'assets-manifest.json');
21
- if (!webpackManifest) {
22
- try {
23
- // eslint-disable-next-line -- Allow JSON type 'any'
24
- webpackManifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
25
- } catch {
26
- logger.error(`Webpack ${basename(manifestPath)} not found`);
27
- }
28
- }
29
19
  const {
30
20
  params,
31
21
  path,
32
- query = {},
33
- response,
34
- state
22
+ response
35
23
  } = request ?? {};
36
- const isForceAccess = 'force' in query;
37
24
  const isPreviewMode = path?.startsWith(PREVIEW_PATH_PREFIX);
38
25
 
39
26
  // Only add the slug in to the context if the response is OK.
40
27
  // Footer meta links are not rendered when the slug is missing.
41
28
  const isResponseOK = !Boom.isBoom(response) && response?.statusCode === StatusCodes.OK;
29
+ const pluginStorage = request?.server.plugins['forms-engine-plugin'];
30
+ let consumerViewContext = {};
31
+ if (!pluginStorage) {
32
+ throw Error('context called before plugin registered');
33
+ }
34
+ if (!pluginStorage.baseLayoutPath) {
35
+ throw Error('Missing baseLayoutPath in plugin.options.nunjucks');
36
+ }
37
+ if ('viewContext' in pluginStorage) {
38
+ consumerViewContext = pluginStorage.viewContext(request);
39
+ }
42
40
 
43
41
  /** @type {ViewContext} */
44
42
  const ctx = {
43
+ // take consumers props first so we can override it
44
+ ...consumerViewContext,
45
+ baseLayoutPath: pluginStorage.baseLayoutPath,
45
46
  appVersion: pkg.version,
46
- assetPath: '/assets',
47
47
  config: {
48
48
  cdpEnvironment: config.get('cdpEnvironment'),
49
49
  designerUrl: config.get('designerUrl'),
50
50
  feedbackLink: encodeUrl(config.get('feedbackLink')),
51
51
  phaseTag: config.get('phaseTag'),
52
- serviceBannerText: config.get('serviceBannerText'),
53
52
  serviceName: config.get('serviceName'),
54
53
  serviceVersion: config.get('serviceVersion')
55
54
  },
56
55
  crumb: safeGenerateCrumb(request),
57
- cspNonce: request?.plugins.blankie?.nonces?.script,
58
- currentPath: request ? `${request.path}${request.url.search}` : undefined,
56
+ currentPath: `${request.path}${request.url.search}`,
59
57
  previewMode: isPreviewMode ? params?.state : undefined,
60
- slug: isResponseOK ? params?.slug : undefined,
61
- getAssetPath: (asset = '') => {
62
- return `/${webpackManifest?.[asset] ?? asset}`;
63
- }
58
+ slug: isResponseOK ? params?.slug : undefined
64
59
  };
65
- if (!isForceAccess) {
66
- ctx.config.googleAnalyticsTrackingId = config.get('googleAnalyticsTrackingId');
67
- if (typeof state?.cookieConsent === 'string') {
68
- ctx.cookieConsent = parseCookieConsent(state.cookieConsent);
60
+ return ctx;
61
+ }
62
+
63
+ /**
64
+ * Returns the context for the devtool. Consumers won't have access to this.
65
+ */
66
+ export function devtoolContext() {
67
+ const manifestPath = join(config.get('publicDir'), 'assets-manifest.json');
68
+ if (!webpackManifest) {
69
+ try {
70
+ // eslint-disable-next-line -- Allow JSON type 'any'
71
+ webpackManifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
72
+ } catch {
73
+ logger.error(`Webpack ${basename(manifestPath)} not found`);
69
74
  }
70
75
  }
71
- return ctx;
76
+ return {
77
+ assetPath: '/assets',
78
+ getDxtAssetPath: (asset = '') => {
79
+ return `/${webpackManifest?.[asset] ?? asset}`;
80
+ }
81
+ };
72
82
  }
73
83
 
74
84
  /**
75
- * @import { CookieConsent } from '~/src/common/types.js'
76
85
  * @import { ViewContext } from '~/src/server/plugins/nunjucks/types.js'
77
86
  * @import { FormRequest, FormRequestPayload } from '~/src/server/routes/types.js'
78
87
  */