@defra/forms-engine-plugin 0.1.0 → 0.1.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/.public/assets-manifest.json +9 -9
- package/.public/javascripts/application.min.js +3 -0
- package/.public/javascripts/application.min.js.map +1 -0
- package/.public/javascripts/{file-upload.b2f18f5.min.js → file-upload.min.js} +1 -1
- package/.public/javascripts/file-upload.min.js.map +1 -0
- package/.public/javascripts/vendor/{accessible-autocomplete.275d332.min.js → accessible-autocomplete.min.js} +1 -1
- package/.public/javascripts/vendor/accessible-autocomplete.min.js.map +1 -0
- package/.public/stylesheets/{application.e340021.min.css → application.min.css} +1 -1
- package/.public/stylesheets/{application.e340021.min.css.map → application.min.css.map} +1 -1
- package/.server/server/plugins/engine/plugin.js +44 -55
- package/.server/server/plugins/engine/plugin.js.map +1 -1
- package/README.md +5 -1
- package/package.json +9 -1
- package/src/server/plugins/engine/plugin.ts +78 -60
- package/.public/javascripts/application.0fd8c18.min.js +0 -3
- package/.public/javascripts/application.0fd8c18.min.js.map +0 -1
- package/.public/javascripts/file-upload.b2f18f5.min.js.map +0 -1
- package/.public/javascripts/vendor/accessible-autocomplete.275d332.min.js.map +0 -1
- /package/.public/javascripts/{application.0fd8c18.min.js.LICENSE.txt → application.min.js.LICENSE.txt} +0 -0
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { hasFormComponents, slugSchema } from '@defra/forms-model';
|
|
2
2
|
import Boom from '@hapi/boom';
|
|
3
|
-
|
|
3
|
+
import vision from '@hapi/vision';
|
|
4
4
|
import { isEqual } from 'date-fns';
|
|
5
5
|
import Joi from 'joi';
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import nunjucks from 'nunjucks';
|
|
8
7
|
import { PREVIEW_PATH_PREFIX } from "../../constants.js";
|
|
9
8
|
import { checkEmailAddressForLiveFormSubmission, checkFormStatus, findPage, getCacheService, getPage, getStartPath, normalisePath, proceed, redirectPath } from "./helpers.js";
|
|
10
|
-
|
|
11
|
-
// PLUGIN_PATH,
|
|
12
|
-
// VIEW_PATH,
|
|
13
|
-
// context,
|
|
14
|
-
// prepareNunjucksEnvironment
|
|
15
|
-
// } from '~/src/server/plugins/engine/index.js'
|
|
9
|
+
import { PLUGIN_PATH, VIEW_PATH, context, prepareNunjucksEnvironment } from "./index.js";
|
|
16
10
|
import { FormModel, SummaryViewModel } from "./models/index.js";
|
|
17
11
|
import { format } from "./outputFormatters/machine/v1.js";
|
|
18
12
|
import { FileUploadPageController } from "./pageControllers/FileUploadPageController.js";
|
|
@@ -27,14 +21,15 @@ export const plugin = {
|
|
|
27
21
|
name: '@defra/forms-engine-plugin',
|
|
28
22
|
dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],
|
|
29
23
|
multiple: true,
|
|
30
|
-
register(server, options) {
|
|
24
|
+
async register(server, options) {
|
|
31
25
|
const {
|
|
32
26
|
model,
|
|
33
27
|
services = defaultServices,
|
|
34
28
|
controllers,
|
|
35
|
-
cacheName
|
|
36
|
-
|
|
37
|
-
|
|
29
|
+
cacheName,
|
|
30
|
+
viewPaths,
|
|
31
|
+
filters,
|
|
32
|
+
pluginPath = PLUGIN_PATH
|
|
38
33
|
} = options;
|
|
39
34
|
const {
|
|
40
35
|
formsService
|
|
@@ -42,50 +37,44 @@ export const plugin = {
|
|
|
42
37
|
const cacheService = new CacheService(server, cacheName);
|
|
43
38
|
|
|
44
39
|
// Paths array to tell `vision` and `nunjucks` where template files are stored.
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// plugin: vision,
|
|
49
|
-
// options: {
|
|
50
|
-
// engines: {
|
|
51
|
-
// html: {
|
|
52
|
-
// compile: (
|
|
53
|
-
// path: string,
|
|
54
|
-
// compileOptions: { environment: Environment }
|
|
55
|
-
// ) => {
|
|
56
|
-
// const template = nunjucks.compile(
|
|
57
|
-
// path,
|
|
58
|
-
// compileOptions.environment
|
|
59
|
-
// )
|
|
60
|
-
|
|
61
|
-
// return (context: object | undefined) => {
|
|
62
|
-
// return template.render(context)
|
|
63
|
-
// }
|
|
64
|
-
// },
|
|
65
|
-
// prepare: (options: EngineConfigurationObject, next) => {
|
|
66
|
-
// // Nunjucks also needs an additional path configuration
|
|
67
|
-
// // to use the templates and macros from `govuk-frontend`
|
|
68
|
-
// const environment = nunjucks.configure([
|
|
69
|
-
// ...path,
|
|
70
|
-
// 'node_modules/govuk-frontend/dist'
|
|
71
|
-
// ])
|
|
72
|
-
|
|
73
|
-
// // Applies custom filters and globals for nunjucks
|
|
74
|
-
// // that are required by the `forms-engine-plugin`
|
|
75
|
-
// prepareNunjucksEnvironment(environment, filters)
|
|
76
|
-
|
|
77
|
-
// options.compileOptions.environment = environment
|
|
40
|
+
// We need to include `VIEW_PATH` in addition the runtime path (node_modules)
|
|
41
|
+
// to keep the local tests working
|
|
42
|
+
const path = [`${pluginPath}/${VIEW_PATH}`, VIEW_PATH];
|
|
78
43
|
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
44
|
+
// Include any additional user provided view paths so our internal views engine
|
|
45
|
+
// can find any files they provide from the consumer side if using custom `page.view`s
|
|
46
|
+
if (Array.isArray(viewPaths) && viewPaths.length) {
|
|
47
|
+
path.push(...viewPaths);
|
|
48
|
+
}
|
|
49
|
+
await server.register({
|
|
50
|
+
plugin: vision,
|
|
51
|
+
options: {
|
|
52
|
+
engines: {
|
|
53
|
+
html: {
|
|
54
|
+
compile: (path, compileOptions) => {
|
|
55
|
+
const template = nunjucks.compile(path, compileOptions.environment);
|
|
56
|
+
return context => {
|
|
57
|
+
return template.render(context);
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
prepare: (options, next) => {
|
|
61
|
+
// Nunjucks also needs an additional path configuration
|
|
62
|
+
// to use the templates and macros from `govuk-frontend`
|
|
63
|
+
const environment = nunjucks.configure([...path, 'node_modules/govuk-frontend/dist']);
|
|
88
64
|
|
|
65
|
+
// Applies custom filters and globals for nunjucks
|
|
66
|
+
// that are required by the `forms-engine-plugin`
|
|
67
|
+
prepareNunjucksEnvironment(environment, filters);
|
|
68
|
+
options.compileOptions.environment = environment;
|
|
69
|
+
next();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
path,
|
|
74
|
+
// Provides global context used with all templates
|
|
75
|
+
context
|
|
76
|
+
}
|
|
77
|
+
});
|
|
89
78
|
server.expose('cacheService', cacheService);
|
|
90
79
|
server.app.model = model;
|
|
91
80
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":["hasFormComponents","slugSchema","Boom","isEqual","Joi","PREVIEW_PATH_PREFIX","checkEmailAddressForLiveFormSubmission","checkFormStatus","findPage","getCacheService","getPage","getStartPath","normalisePath","proceed","redirectPath","FormModel","SummaryViewModel","format","FileUploadPageController","RepeatPageController","getFormSubmissionData","defaultServices","getUploadStatus","actionSchema","confirmSchema","crumbSchema","itemIdSchema","pathSchema","stateSchema","httpService","CacheService","plugin","name","dependencies","multiple","register","server","options","model","services","controllers","cacheName","formsService","cacheService","expose","app","itemCache","Map","models","loadFormPreHandler","request","h","continue","params","path","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","flash","getFlash","context","getFormContext","errors","relevantPath","getRelevantPath","summaryPath","getSummaryPath","startsWith","isForceAccess","redirectTo","next","length","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} from '@hapi/hapi'\n// import vision from '@hapi/vision'\nimport { isEqual } from 'date-fns'\nimport Joi from 'joi'\nimport { type Environment } from 'nunjucks'\n// import 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'\n// import {\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 * 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 pluginPath?: string\n filters?: Record<string, FilterFunction>\n}\n\nexport const plugin = {\n name: '@defra/forms-engine-plugin',\n dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],\n multiple: true,\n register(server, options) {\n const {\n model,\n services = defaultServices,\n controllers,\n cacheName\n // pluginPath = PLUGIN_PATH,\n // filters\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 // const path = [`${pluginPath}/${VIEW_PATH}`]\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: (options: EngineConfigurationObject, next) => {\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 const state = await page.getState(request)\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 (request, h) => {\n try {\n const { uploadId } = request.params as { uploadId: string }\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":["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","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","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 * 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 const state = await page.getState(request)\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":[]}
|
package/README.md
CHANGED
|
@@ -307,7 +307,9 @@ There are a number of `LiquidJS` filters available to you from within the templa
|
|
|
307
307
|
]
|
|
308
308
|
```
|
|
309
309
|
|
|
310
|
-
## Templates and views
|
|
310
|
+
## Templates and views
|
|
311
|
+
|
|
312
|
+
### Extending the default layout
|
|
311
313
|
|
|
312
314
|
TODO
|
|
313
315
|
|
|
@@ -324,6 +326,8 @@ Which can then be appended to the `node_modules` path `node_modules/@defra/forms
|
|
|
324
326
|
|
|
325
327
|
The main template layout is `govuk-frontend`'s `template.njk` file, this also needs to be added to the `path`s that nunjucks can look in.
|
|
326
328
|
|
|
329
|
+
### Custom page view
|
|
330
|
+
|
|
327
331
|
## Publishing the Package
|
|
328
332
|
|
|
329
333
|
Our GitHub Actions workflow (`publish.yml`) is set up to make publishing a breeze, using semantic versioning and a variety of release strategies. Here's how you can make the most of it:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra/forms-engine-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Defra forms engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": ".server/server/plugins/engine/index.js",
|
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
".public",
|
|
10
10
|
"src"
|
|
11
11
|
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"sass": "./.server/client/stylesheets/application.scss",
|
|
15
|
+
"import": "./.server/client/javascripts/application.js",
|
|
16
|
+
"default": "./.server/client/javascripts/application.js"
|
|
17
|
+
},
|
|
18
|
+
"./file-upload.js": "./.server/client/javascripts/file-upload.js"
|
|
19
|
+
},
|
|
12
20
|
"scripts": {
|
|
13
21
|
"build": "npm run build:server && npm run build:client",
|
|
14
22
|
"build:client": "NODE_ENV=${NODE_ENV:-production} webpack",
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
type Plugin,
|
|
5
5
|
type ResponseObject,
|
|
6
6
|
type ResponseToolkit,
|
|
7
|
-
type RouteOptions
|
|
7
|
+
type RouteOptions,
|
|
8
|
+
type Server
|
|
8
9
|
} from '@hapi/hapi'
|
|
9
|
-
|
|
10
|
+
import vision from '@hapi/vision'
|
|
10
11
|
import { isEqual } from 'date-fns'
|
|
11
12
|
import Joi from 'joi'
|
|
12
|
-
import { type Environment } from 'nunjucks'
|
|
13
|
-
// import nunjucks, { type Environment } from 'nunjucks'
|
|
13
|
+
import nunjucks, { type Environment } from 'nunjucks'
|
|
14
14
|
|
|
15
15
|
import { PREVIEW_PATH_PREFIX } from '~/src/server/constants.js'
|
|
16
16
|
import {
|
|
@@ -24,12 +24,12 @@ import {
|
|
|
24
24
|
proceed,
|
|
25
25
|
redirectPath
|
|
26
26
|
} from '~/src/server/plugins/engine/helpers.js'
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
import {
|
|
28
|
+
PLUGIN_PATH,
|
|
29
|
+
VIEW_PATH,
|
|
30
|
+
context,
|
|
31
|
+
prepareNunjucksEnvironment
|
|
32
|
+
} from '~/src/server/plugins/engine/index.js'
|
|
33
33
|
import {
|
|
34
34
|
FormModel,
|
|
35
35
|
SummaryViewModel
|
|
@@ -69,70 +69,83 @@ export interface PluginOptions {
|
|
|
69
69
|
services?: Services
|
|
70
70
|
controllers?: Record<string, typeof PageController>
|
|
71
71
|
cacheName?: string
|
|
72
|
-
|
|
72
|
+
viewPaths?: string[]
|
|
73
73
|
filters?: Record<string, FilterFunction>
|
|
74
|
+
pluginPath?: string
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
export const plugin = {
|
|
77
78
|
name: '@defra/forms-engine-plugin',
|
|
78
79
|
dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],
|
|
79
80
|
multiple: true,
|
|
80
|
-
register(server, options) {
|
|
81
|
+
async register(server: Server, options: PluginOptions) {
|
|
81
82
|
const {
|
|
82
83
|
model,
|
|
83
84
|
services = defaultServices,
|
|
84
85
|
controllers,
|
|
85
|
-
cacheName
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
cacheName,
|
|
87
|
+
viewPaths,
|
|
88
|
+
filters,
|
|
89
|
+
pluginPath = PLUGIN_PATH
|
|
88
90
|
} = options
|
|
89
91
|
const { formsService } = services
|
|
90
92
|
const cacheService = new CacheService(server, cacheName)
|
|
91
93
|
|
|
92
94
|
// Paths array to tell `vision` and `nunjucks` where template files are stored.
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
95
|
+
// We need to include `VIEW_PATH` in addition the runtime path (node_modules)
|
|
96
|
+
// to keep the local tests working
|
|
97
|
+
const path = [`${pluginPath}/${VIEW_PATH}`, VIEW_PATH]
|
|
98
|
+
|
|
99
|
+
// Include any additional user provided view paths so our internal views engine
|
|
100
|
+
// can find any files they provide from the consumer side if using custom `page.view`s
|
|
101
|
+
if (Array.isArray(viewPaths) && viewPaths.length) {
|
|
102
|
+
path.push(...viewPaths)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
await server.register({
|
|
106
|
+
plugin: vision,
|
|
107
|
+
options: {
|
|
108
|
+
engines: {
|
|
109
|
+
html: {
|
|
110
|
+
compile: (
|
|
111
|
+
path: string,
|
|
112
|
+
compileOptions: { environment: Environment }
|
|
113
|
+
) => {
|
|
114
|
+
const template = nunjucks.compile(
|
|
115
|
+
path,
|
|
116
|
+
compileOptions.environment
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
return (context: object | undefined) => {
|
|
120
|
+
return template.render(context)
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
prepare: (
|
|
124
|
+
options: EngineConfigurationObject,
|
|
125
|
+
next: (err?: Error) => void
|
|
126
|
+
) => {
|
|
127
|
+
// Nunjucks also needs an additional path configuration
|
|
128
|
+
// to use the templates and macros from `govuk-frontend`
|
|
129
|
+
const environment = nunjucks.configure([
|
|
130
|
+
...path,
|
|
131
|
+
'node_modules/govuk-frontend/dist'
|
|
132
|
+
])
|
|
133
|
+
|
|
134
|
+
// Applies custom filters and globals for nunjucks
|
|
135
|
+
// that are required by the `forms-engine-plugin`
|
|
136
|
+
prepareNunjucksEnvironment(environment, filters)
|
|
137
|
+
|
|
138
|
+
options.compileOptions.environment = environment
|
|
139
|
+
|
|
140
|
+
next()
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
path,
|
|
145
|
+
// Provides global context used with all templates
|
|
146
|
+
context
|
|
147
|
+
}
|
|
148
|
+
})
|
|
136
149
|
|
|
137
150
|
server.expose('cacheService', cacheService)
|
|
138
151
|
|
|
@@ -711,9 +724,14 @@ export const plugin = {
|
|
|
711
724
|
server.route({
|
|
712
725
|
method: 'get',
|
|
713
726
|
path: '/upload-status/{uploadId}',
|
|
714
|
-
handler: async (
|
|
727
|
+
handler: async (
|
|
728
|
+
request: FormRequest,
|
|
729
|
+
h: Pick<ResponseToolkit, 'response'>
|
|
730
|
+
) => {
|
|
715
731
|
try {
|
|
716
|
-
const { uploadId } = request.params as
|
|
732
|
+
const { uploadId } = request.params as unknown as {
|
|
733
|
+
uploadId: string
|
|
734
|
+
}
|
|
717
735
|
const status = await getUploadStatus(uploadId)
|
|
718
736
|
|
|
719
737
|
if (!status) {
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
/*! For license information please see application.0fd8c18.min.js.LICENSE.txt */
|
|
2
|
-
var e,t,n,o={},i={};function r(e){var t=i[e];if(void 0!==t)return t.exports;var n=i[e]={exports:{}};return o[e](n,n.exports,r),n.exports}r.m=o,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(n,o){if(1&o&&(n=this(n)),8&o)return n;if("object"==typeof n&&n){if(4&o&&n.__esModule)return n;if(16&o&&"function"==typeof n.then)return n}var i=Object.create(null);r.r(i);var s={};e=e||[null,t({}),t([]),t(t)];for(var a=2&o&&n;"object"==typeof a&&!~e.indexOf(a);a=t(a))Object.getOwnPropertyNames(a).forEach((e=>s[e]=()=>n[e]));return s.default=()=>n,r.d(i,s),i},r.d=(e,t)=>{for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((t,n)=>(r.f[n](e,t),t)),[])),r.u=e=>"javascripts/vendor/accessible-autocomplete.275d332.min.js",r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n={},r.l=(e,t,o,i)=>{if(n[e])n[e].push(t);else{var s,a;if(void 0!==o)for(var l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var u=l[c];if(u.getAttribute("src")==e){s=u;break}}s||(a=!0,(s=document.createElement("script")).type="module",s.charset="utf-8",s.timeout=120,r.nc&&s.setAttribute("nonce",r.nc),s.src=e),n[e]=[t];var h=(t,o)=>{s.onerror=s.onload=null,clearTimeout(d);var i=n[e];if(delete n[e],s.parentNode&&s.parentNode.removeChild(s),i&&i.forEach((e=>e(o))),t)return t(o)},d=setTimeout(h.bind(null,void 0,{type:"timeout",target:s}),12e4);s.onerror=h.bind(null,s.onerror),s.onload=h.bind(null,s.onload),a&&document.head.appendChild(s)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;if("string"==typeof import.meta.url&&(e=import.meta.url),!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),r.p=e+"../"})(),(()=>{var e={543:0};r.f.j=(t,n)=>{var o=r.o(e,t)?e[t]:void 0;if(0!==o)if(o)n.push(o[2]);else{var i=new Promise(((n,i)=>o=e[t]=[n,i]));n.push(o[2]=i);var s=r.p+r.u(t),a=new Error;r.l(s,(n=>{if(r.o(e,t)&&(0!==(o=e[t])&&(e[t]=void 0),o)){var i=n&&("load"===n.type?"missing":n.type),s=n&&n.target&&n.target.src;a.message="Loading chunk "+t+" failed.\n("+i+": "+s+")",a.name="ChunkLoadError",a.type=i,a.request=s,o[1](a)}}),"chunk-"+t,t)}};var t=(t,n)=>{var o,i,s=n[0],a=n[1],l=n[2],c=0;if(s.some((t=>0!==e[t]))){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);l&&l(r)}for(t&&t(n);c<s.length;c++)i=s[c],r.o(e,i)&&e[i]&&e[i][0](),e[i]=0},n=self.webpackChunk=self.webpackChunk||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})(),(()=>{function e(e,t){const n=e?e.trim():"";let o,i=null==t?void 0:t.type;switch(i||(["true","false"].includes(n)&&(i="boolean"),n.length>0&&isFinite(Number(n))&&(i="number")),i){case"boolean":o="true"===n;break;case"number":o=Number(n);break;default:o=e}return o}function t(...e){const n={};for(const o of e)for(const e of Object.keys(o)){const i=n[e],r=o[e];a(i)&&a(r)?n[e]=t(i,r):n[e]=r}return n}function n(t,n,o){const i=t.schema.properties[o];if("object"!==(null==i?void 0:i.type))return;const r={[o]:{}};for(const[s,l]of Object.entries(n)){let t=r;const n=s.split(".");for(const[i,r]of n.entries())"object"==typeof t&&(i<n.length-1?(a(t[r])||(t[r]={}),t=t[r]):s!==o&&(t[r]=e(l)))}return r[o]}function o(e){if(e.includes("#"))return e.split("#").pop()}function i(e,t={}){var n;const o=e.getAttribute("tabindex");function i(){var n;null==(n=t.onBlur)||n.call(e),o||e.removeAttribute("tabindex")}o||e.setAttribute("tabindex","-1"),e.addEventListener("focus",(function(){e.addEventListener("blur",i,{once:!0})}),{once:!0}),null==(n=t.onBeforeFocus)||n.call(e),e.focus()}function s(e=document.body){return!!e&&e.classList.contains("govuk-frontend-supported")}function a(e){return!!e&&"object"==typeof e&&!function(e){return Array.isArray(e)}(e)}function l(e,t){return`${e.moduleName}: ${t}`}class c extends Error{constructor(...e){super(...e),this.name="GOVUKFrontendError"}}class u extends c{constructor(e=document.body){const t="noModule"in HTMLScriptElement.prototype?'GOV.UK Frontend initialised without `<body class="govuk-frontend-supported">` from template `<script>` snippet':"GOV.UK Frontend is not supported in this browser";super(e?t:'GOV.UK Frontend initialised without `<script type="module">`'),this.name="SupportError"}}class h extends c{constructor(...e){super(...e),this.name="ConfigError"}}class d extends c{constructor(e){let t="string"==typeof e?e:"";if("object"==typeof e){const{component:n,identifier:o,element:i,expectedType:r}=e;t=o,t+=i?` is not of type ${null!=r?r:"HTMLElement"}`:" not found",t=l(n,t)}super(t),this.name="ElementError"}}class m extends c{constructor(e){super("string"==typeof e?e:l(e,"Root element (`$root`) already initialised")),this.name="InitError"}}function p(e,t,n){let o,i=document;var r;"object"==typeof n&&(i=null!=(r=n.scope)?r:i,o=n.onError),"function"==typeof n&&(o=n),n instanceof HTMLElement&&(i=n);const a=i.querySelectorAll(`[data-module="${e.moduleName}"]`);return s()?Array.from(a).map((n=>{try{return void 0!==t?new e(n,t):new e(n)}catch(i){return o?o(i,{element:n,component:e,config:t}):console.log(i),null}})).filter(Boolean):(o?o(new u,{component:e,config:t}):console.log(new u),[])}function f(t,o){const i={};for(const[r,s]of Object.entries(t.schema.properties))r in o&&(i[r]=e(o[r],s)),"object"===(null==s?void 0:s.type)&&(i[r]=n(t,o,r));return i}class g{get $root(){return this._$root}constructor(e){this._$root=void 0;const t=this.constructor;if("string"!=typeof t.moduleName)throw new m("`moduleName` not defined in component");if(!(e instanceof t.elementType))throw new d({element:e,component:t,identifier:"Root element (`$root`)",expectedType:t.elementType.name});this._$root=e,t.checkSupport(),this.checkInitialised();const n=t.moduleName;this.$root.setAttribute(`data-${n}-init`,"")}checkInitialised(){const e=this.constructor,t=e.moduleName;if(t&&function(e,t){return e instanceof HTMLElement&&e.hasAttribute(`data-${t}-init`)}(this.$root,t))throw new m(e)}static checkSupport(){if(!s())throw new u}}g.elementType=HTMLElement;class v extends g{constructor(e,n={}){super(e),this.config=void 0,this.debounceFormSubmitTimer=null,this.config=t(v.defaults,n,f(v,this.$root.dataset)),this.$root.addEventListener("keydown",(e=>this.handleKeyDown(e))),this.$root.addEventListener("click",(e=>this.debounce(e)))}handleKeyDown(e){const t=e.target;" "===e.key&&t instanceof HTMLElement&&"button"===t.getAttribute("role")&&(e.preventDefault(),t.click())}debounce(e){if(this.config.preventDoubleClick)return this.debounceFormSubmitTimer?(e.preventDefault(),!1):void(this.debounceFormSubmitTimer=window.setTimeout((()=>{this.debounceFormSubmitTimer=null}),1e3))}}function b(e,t){const n=e.closest(`[${t}]`);return n?n.getAttribute(t):null}v.moduleName="govuk-button",v.defaults=Object.freeze({preventDoubleClick:!1}),v.schema=Object.freeze({properties:{preventDoubleClick:{type:"boolean"}}});class y{constructor(e={},t={}){var n;this.translations=void 0,this.locale=void 0,this.translations=e,this.locale=null!=(n=t.locale)?n:document.documentElement.lang||"en"}t(e,t){if(!e)throw new Error("i18n: lookup key missing");let n=this.translations[e];if("number"==typeof(null==t?void 0:t.count)&&"object"==typeof n){const o=n[this.getPluralSuffix(e,t.count)];o&&(n=o)}if("string"==typeof n){if(n.match(/%{(.\S+)}/)){if(!t)throw new Error("i18n: cannot replace placeholders in string if no option data provided");return this.replacePlaceholders(n,t)}return n}return e}replacePlaceholders(e,t){const n=Intl.NumberFormat.supportedLocalesOf(this.locale).length?new Intl.NumberFormat(this.locale):void 0;return e.replace(/%{(.\S+)}/g,(function(e,o){if(Object.prototype.hasOwnProperty.call(t,o)){const e=t[o];return!1===e||"number"!=typeof e&&"string"!=typeof e?"":"number"==typeof e?n?n.format(e):`${e}`:e}throw new Error(`i18n: no data found to replace ${e} placeholder in string`)}))}hasIntlPluralRulesSupport(){return Boolean("PluralRules"in window.Intl&&Intl.PluralRules.supportedLocalesOf(this.locale).length)}getPluralSuffix(e,t){if(t=Number(t),!isFinite(t))return"other";const n=this.translations[e],o=this.hasIntlPluralRulesSupport()?new Intl.PluralRules(this.locale).select(t):this.selectPluralFormUsingFallbackRules(t);if("object"==typeof n){if(o in n)return o;if("other"in n)return console.warn(`i18n: Missing plural form ".${o}" for "${this.locale}" locale. Falling back to ".other".`),"other"}throw new Error(`i18n: Plural form ".other" is required for "${this.locale}" locale`)}selectPluralFormUsingFallbackRules(e){e=Math.abs(Math.floor(e));const t=this.getPluralRulesForLocale();return t?y.pluralRules[t](e):"other"}getPluralRulesForLocale(){const e=this.locale.split("-")[0];for(const t in y.pluralRulesMap){const n=y.pluralRulesMap[t];if(n.includes(this.locale)||n.includes(e))return t}}}y.pluralRulesMap={arabic:["ar"],chinese:["my","zh","id","ja","jv","ko","ms","th","vi"],french:["hy","bn","fr","gu","hi","fa","pa","zu"],german:["af","sq","az","eu","bg","ca","da","nl","en","et","fi","ka","de","el","hu","lb","no","so","sw","sv","ta","te","tr","ur"],irish:["ga"],russian:["ru","uk"],scottish:["gd"],spanish:["pt-PT","it","es"],welsh:["cy"]},y.pluralRules={arabic:e=>0===e?"zero":1===e?"one":2===e?"two":e%100>=3&&e%100<=10?"few":e%100>=11&&e%100<=99?"many":"other",chinese:()=>"other",french:e=>0===e||1===e?"one":"other",german:e=>1===e?"one":"other",irish:e=>1===e?"one":2===e?"two":e>=3&&e<=6?"few":e>=7&&e<=10?"many":"other",russian(e){const t=e%100,n=t%10;return 1===n&&11!==t?"one":n>=2&&n<=4&&!(t>=12&&t<=14)?"few":0===n||n>=5&&n<=9||t>=11&&t<=14?"many":"other"},scottish:e=>1===e||11===e?"one":2===e||12===e?"two":e>=3&&e<=10||e>=13&&e<=19?"few":"other",spanish:e=>1===e?"one":e%1e6==0&&0!==e?"many":"other",welsh:e=>0===e?"zero":1===e?"one":2===e?"two":3===e?"few":6===e?"many":"other"};class w extends g{constructor(e,n={}){var o,i;super(e),this.$textarea=void 0,this.$visibleCountMessage=void 0,this.$screenReaderCountMessage=void 0,this.lastInputTimestamp=null,this.lastInputValue="",this.valueChecker=null,this.config=void 0,this.i18n=void 0,this.maxLength=void 0;const r=this.$root.querySelector(".govuk-js-character-count");if(!(r instanceof HTMLTextAreaElement||r instanceof HTMLInputElement))throw new d({component:w,element:r,expectedType:"HTMLTextareaElement or HTMLInputElement",identifier:"Form field (`.govuk-js-character-count`)"});const s=f(w,this.$root.dataset);let a={};("maxwords"in s||"maxlength"in s)&&(a={maxlength:void 0,maxwords:void 0}),this.config=t(w.defaults,n,a,s);const c=function(e,t){const n=[];for(const[o,i]of Object.entries(e)){const e=[];if(Array.isArray(i)){for(const{required:n,errorMessage:o}of i)n.every((e=>!!t[e]))||e.push(o);"anyOf"!==o||i.length-e.length>=1||n.push(...e)}}return n}(w.schema,this.config);if(c[0])throw new h(l(w,c[0]));this.i18n=new y(this.config.i18n,{locale:b(this.$root,"lang")}),this.maxLength=null!=(o=null!=(i=this.config.maxwords)?i:this.config.maxlength)?o:1/0,this.$textarea=r;const u=`${this.$textarea.id}-info`,m=document.getElementById(u);if(!m)throw new d({component:w,element:m,identifier:`Count message (\`id="${u}"\`)`});`${m.textContent}`.match(/^\s*$/)&&(m.textContent=this.i18n.t("textareaDescription",{count:this.maxLength})),this.$textarea.insertAdjacentElement("afterend",m);const p=document.createElement("div");p.className="govuk-character-count__sr-status govuk-visually-hidden",p.setAttribute("aria-live","polite"),this.$screenReaderCountMessage=p,m.insertAdjacentElement("afterend",p);const g=document.createElement("div");g.className=m.className,g.classList.add("govuk-character-count__status"),g.setAttribute("aria-hidden","true"),this.$visibleCountMessage=g,m.insertAdjacentElement("afterend",g),m.classList.add("govuk-visually-hidden"),this.$textarea.removeAttribute("maxlength"),this.bindChangeEvents(),window.addEventListener("pageshow",(()=>this.updateCountMessage())),this.updateCountMessage()}bindChangeEvents(){this.$textarea.addEventListener("keyup",(()=>this.handleKeyUp())),this.$textarea.addEventListener("focus",(()=>this.handleFocus())),this.$textarea.addEventListener("blur",(()=>this.handleBlur()))}handleKeyUp(){this.updateVisibleCountMessage(),this.lastInputTimestamp=Date.now()}handleFocus(){this.valueChecker=window.setInterval((()=>{(!this.lastInputTimestamp||Date.now()-500>=this.lastInputTimestamp)&&this.updateIfValueChanged()}),1e3)}handleBlur(){this.valueChecker&&window.clearInterval(this.valueChecker)}updateIfValueChanged(){this.$textarea.value!==this.lastInputValue&&(this.lastInputValue=this.$textarea.value,this.updateCountMessage())}updateCountMessage(){this.updateVisibleCountMessage(),this.updateScreenReaderCountMessage()}updateVisibleCountMessage(){const e=this.maxLength-this.count(this.$textarea.value)<0;this.$visibleCountMessage.classList.toggle("govuk-character-count__message--disabled",!this.isOverThreshold()),this.$textarea.classList.toggle("govuk-textarea--error",e),this.$visibleCountMessage.classList.toggle("govuk-error-message",e),this.$visibleCountMessage.classList.toggle("govuk-hint",!e),this.$visibleCountMessage.textContent=this.getCountMessage()}updateScreenReaderCountMessage(){this.isOverThreshold()?this.$screenReaderCountMessage.removeAttribute("aria-hidden"):this.$screenReaderCountMessage.setAttribute("aria-hidden","true"),this.$screenReaderCountMessage.textContent=this.getCountMessage()}count(e){var t;return this.config.maxwords?(null!=(t=e.match(/\S+/g))?t:[]).length:e.length}getCountMessage(){const e=this.maxLength-this.count(this.$textarea.value),t=this.config.maxwords?"words":"characters";return this.formatCountMessage(e,t)}formatCountMessage(e,t){if(0===e)return this.i18n.t(`${t}AtLimit`);const n=e<0?"OverLimit":"UnderLimit";return this.i18n.t(`${t}${n}`,{count:Math.abs(e)})}isOverThreshold(){if(!this.config.threshold)return!0;const e=this.count(this.$textarea.value);return this.maxLength*this.config.threshold/100<=e}}w.moduleName="govuk-character-count",w.defaults=Object.freeze({threshold:0,i18n:{charactersUnderLimit:{one:"You have %{count} character remaining",other:"You have %{count} characters remaining"},charactersAtLimit:"You have 0 characters remaining",charactersOverLimit:{one:"You have %{count} character too many",other:"You have %{count} characters too many"},wordsUnderLimit:{one:"You have %{count} word remaining",other:"You have %{count} words remaining"},wordsAtLimit:"You have 0 words remaining",wordsOverLimit:{one:"You have %{count} word too many",other:"You have %{count} words too many"},textareaDescription:{other:""}}}),w.schema=Object.freeze({properties:{i18n:{type:"object"},maxwords:{type:"number"},maxlength:{type:"number"},threshold:{type:"number"}},anyOf:[{required:["maxwords"],errorMessage:'Either "maxlength" or "maxwords" must be provided'},{required:["maxlength"],errorMessage:'Either "maxlength" or "maxwords" must be provided'}]});class k extends g{constructor(e){super(e),this.$inputs=void 0;const t=this.$root.querySelectorAll('input[type="checkbox"]');if(!t.length)throw new d({component:k,identifier:'Form inputs (`<input type="checkbox">`)'});this.$inputs=t,this.$inputs.forEach((e=>{const t=e.getAttribute("data-aria-controls");if(t){if(!document.getElementById(t))throw new d({component:k,identifier:`Conditional reveal (\`id="${t}"\`)`});e.setAttribute("aria-controls",t),e.removeAttribute("data-aria-controls")}})),window.addEventListener("pageshow",(()=>this.syncAllConditionalReveals())),this.syncAllConditionalReveals(),this.$root.addEventListener("click",(e=>this.handleClick(e)))}syncAllConditionalReveals(){this.$inputs.forEach((e=>this.syncConditionalRevealWithInputState(e)))}syncConditionalRevealWithInputState(e){const t=e.getAttribute("aria-controls");if(!t)return;const n=document.getElementById(t);if(null!=n&&n.classList.contains("govuk-checkboxes__conditional")){const t=e.checked;e.setAttribute("aria-expanded",t.toString()),n.classList.toggle("govuk-checkboxes__conditional--hidden",!t)}}unCheckAllInputsExcept(e){document.querySelectorAll(`input[type="checkbox"][name="${e.name}"]`).forEach((t=>{e.form===t.form&&t!==e&&(t.checked=!1,this.syncConditionalRevealWithInputState(t))}))}unCheckExclusiveInputs(e){document.querySelectorAll(`input[data-behaviour="exclusive"][type="checkbox"][name="${e.name}"]`).forEach((t=>{e.form===t.form&&(t.checked=!1,this.syncConditionalRevealWithInputState(t))}))}handleClick(e){const t=e.target;t instanceof HTMLInputElement&&"checkbox"===t.type&&(t.getAttribute("aria-controls")&&this.syncConditionalRevealWithInputState(t),t.checked&&("exclusive"===t.getAttribute("data-behaviour")?this.unCheckAllInputsExcept(t):this.unCheckExclusiveInputs(t)))}}k.moduleName="govuk-checkboxes";class $ extends g{constructor(e,n={}){super(e),this.config=void 0,this.config=t($.defaults,n,f($,this.$root.dataset)),this.config.disableAutoFocus||i(this.$root),this.$root.addEventListener("click",(e=>this.handleClick(e)))}handleClick(e){const t=e.target;t&&this.focusTarget(t)&&e.preventDefault()}focusTarget(e){if(!(e instanceof HTMLAnchorElement))return!1;const t=o(e.href);if(!t)return!1;const n=document.getElementById(t);if(!n)return!1;const i=this.getAssociatedLegendOrLabel(n);return!!i&&(i.scrollIntoView(),n.focus({preventScroll:!0}),!0)}getAssociatedLegendOrLabel(e){var t;const n=e.closest("fieldset");if(n){const t=n.getElementsByTagName("legend");if(t.length){const n=t[0];if(e instanceof HTMLInputElement&&("checkbox"===e.type||"radio"===e.type))return n;const o=n.getBoundingClientRect().top,i=e.getBoundingClientRect();if(i.height&&window.innerHeight&&i.top+i.height-o<window.innerHeight/2)return n}}return null!=(t=document.querySelector(`label[for='${e.getAttribute("id")}']`))?t:e.closest("label")}}$.moduleName="govuk-error-summary",$.defaults=Object.freeze({disableAutoFocus:!1}),$.schema=Object.freeze({properties:{disableAutoFocus:{type:"boolean"}}});class x extends g{constructor(e){super(e),this.$menuButton=void 0,this.$menu=void 0,this.menuIsOpen=!1,this.mql=null;const t=this.$root.querySelector(".govuk-js-header-toggle");if(!t)return this;const n=t.getAttribute("aria-controls");if(!n)throw new d({component:x,identifier:'Navigation button (`<button class="govuk-js-header-toggle">`) attribute (`aria-controls`)'});const o=document.getElementById(n);if(!o)throw new d({component:x,element:o,identifier:`Navigation (\`<ul id="${n}">\`)`});this.$menu=o,this.$menuButton=t,this.setupResponsiveChecks(),this.$menuButton.addEventListener("click",(()=>this.handleMenuButtonClick()))}setupResponsiveChecks(){const e=function(e){const t="--govuk-frontend-breakpoint-desktop";return{property:t,value:window.getComputedStyle(document.documentElement).getPropertyValue(t)||void 0}}();if(!e.value)throw new d({component:x,identifier:`CSS custom property (\`${e.property}\`) on pseudo-class \`:root\``});this.mql=window.matchMedia(`(min-width: ${e.value})`),"addEventListener"in this.mql?this.mql.addEventListener("change",(()=>this.checkMode())):this.mql.addListener((()=>this.checkMode())),this.checkMode()}checkMode(){this.mql&&this.$menu&&this.$menuButton&&(this.mql.matches?(this.$menu.removeAttribute("hidden"),this.$menuButton.setAttribute("hidden","")):(this.$menuButton.removeAttribute("hidden"),this.$menuButton.setAttribute("aria-expanded",this.menuIsOpen.toString()),this.menuIsOpen?this.$menu.removeAttribute("hidden"):this.$menu.setAttribute("hidden","")))}handleMenuButtonClick(){this.menuIsOpen=!this.menuIsOpen,this.checkMode()}}x.moduleName="govuk-header";class E extends g{constructor(e,n={}){super(e),this.config=void 0,this.config=t(E.defaults,n,f(E,this.$root.dataset)),"alert"!==this.$root.getAttribute("role")||this.config.disableAutoFocus||i(this.$root)}}E.moduleName="govuk-notification-banner",E.defaults=Object.freeze({disableAutoFocus:!1}),E.schema=Object.freeze({properties:{disableAutoFocus:{type:"boolean"}}});class C extends g{constructor(e){super(e),this.$inputs=void 0;const t=this.$root.querySelectorAll('input[type="radio"]');if(!t.length)throw new d({component:C,identifier:'Form inputs (`<input type="radio">`)'});this.$inputs=t,this.$inputs.forEach((e=>{const t=e.getAttribute("data-aria-controls");if(t){if(!document.getElementById(t))throw new d({component:C,identifier:`Conditional reveal (\`id="${t}"\`)`});e.setAttribute("aria-controls",t),e.removeAttribute("data-aria-controls")}})),window.addEventListener("pageshow",(()=>this.syncAllConditionalReveals())),this.syncAllConditionalReveals(),this.$root.addEventListener("click",(e=>this.handleClick(e)))}syncAllConditionalReveals(){this.$inputs.forEach((e=>this.syncConditionalRevealWithInputState(e)))}syncConditionalRevealWithInputState(e){const t=e.getAttribute("aria-controls");if(!t)return;const n=document.getElementById(t);if(null!=n&&n.classList.contains("govuk-radios__conditional")){const t=e.checked;e.setAttribute("aria-expanded",t.toString()),n.classList.toggle("govuk-radios__conditional--hidden",!t)}}handleClick(e){const t=e.target;if(!(t instanceof HTMLInputElement)||"radio"!==t.type)return;const n=document.querySelectorAll('input[type="radio"][aria-controls]'),o=t.form,i=t.name;n.forEach((e=>{const t=e.form===o;e.name===i&&t&&this.syncConditionalRevealWithInputState(e)}))}}C.moduleName="govuk-radios";class A extends g{constructor(e){var t;super(e);const n=this.$root.hash,r=null!=(t=this.$root.getAttribute("href"))?t:"";let s;try{s=new window.URL(this.$root.href)}catch(c){throw new d(`Skip link: Target link (\`href="${r}"\`) is invalid`)}if(s.origin!==window.location.origin||s.pathname!==window.location.pathname)return;const a=o(n);if(!a)throw new d(`Skip link: Target link (\`href="${r}"\`) has no hash fragment`);const l=document.getElementById(a);if(!l)throw new d({component:A,element:l,identifier:`Target content (\`id="${a}"\`)`});this.$root.addEventListener("click",(()=>i(l,{onBeforeFocus(){l.classList.add("govuk-skip-link-focused-element")},onBlur(){l.classList.remove("govuk-skip-link-focused-element")}})))}}if(A.elementType=HTMLAnchorElement,A.moduleName="govuk-skip-link",p(v),p(w),p(k),p($),p(x),p(E),p(C),p(A),window.opener){const e=document.querySelector(".js-preview-banner-close");null==e||e.removeAttribute("hidden"),null==e||e.addEventListener("click",(e=>{e.preventDefault(),window.close()}))}const L=document.querySelectorAll('[data-module="govuk-accessible-autocomplete"]');L.length&&r.e(7).then(r.t.bind(r,60,19)).then((e=>{const{default:t}=e;L.forEach((e=>function(e,t){if(!e)return;const n={id:e.id,selectElement:e};t(n);const o=document.querySelector(`#${n.id}`),i=[...e.options].map((e=>e.text));null==o||o.addEventListener("blur",(()=>{o.value&&i.includes(o.value)||(e.value="")}))}(e.querySelector("select"),t.enhanceSelectElement)))})).catch(console.error)})();
|
|
3
|
-
//# sourceMappingURL=application.0fd8c18.min.js.map
|