import { type Lifecycle, type Plugin, type RouteOptions, type Server, type ServerRoute } from '@hapi/hapi' import { type FormModel } from '~/src/server/plugins/engine/models/index.js' import { validatePluginOptions } from '~/src/server/plugins/engine/options.js' import { getRoutes as getFileUploadStatusRoutes } from '~/src/server/plugins/engine/routes/file-upload.js' import { makeLoadFormPreHandler } from '~/src/server/plugins/engine/routes/index.js' import { getRoutes as getPaymentRoutes } from '~/src/server/plugins/engine/routes/payment.js' import { getRoutes as getQuestionRoutes } from '~/src/server/plugins/engine/routes/questions.js' import { getRoutes as getRepeaterItemDeleteRoutes } from '~/src/server/plugins/engine/routes/repeaters/item-delete.js' import { getRoutes as getRepeaterSummaryRoutes } from '~/src/server/plugins/engine/routes/repeaters/summary.js' import { type PluginOptions } from '~/src/server/plugins/engine/types.js' import { registerVision } from '~/src/server/plugins/engine/vision.js' import { mapPlugin } from '~/src/server/plugins/map/index.js' import { postcodeLookupPlugin } from '~/src/server/plugins/postcode-lookup/index.js' import { type FormRequestPayloadRefs, type FormRequestRefs } from '~/src/server/routes/types.js' import { CacheService } from '~/src/server/services/index.js' export const plugin = { name: '@defra/forms-engine-plugin', dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'], multiple: true, async register(server: Server, options: PluginOptions) { options = validatePluginOptions(options) const { model, cache, saveAndExit, nunjucks: nunjucksOptions, viewContext, preparePageEventRequestOptions, onRequest, ordnanceSurveyApiKey, baseUrl, ordnanceSurveyApiSecret, services } = options const cacheService = typeof cache === 'string' ? new CacheService({ server, cacheName: cache }) : cache await registerVision(server, options) // Register the postcode lookup plugin only if we have an OS api key if (ordnanceSurveyApiKey) { await server.register({ plugin: postcodeLookupPlugin, options: { ordnanceSurveyApiKey } }) } // Register the maps plugin only if we have an OS api key & secret if (ordnanceSurveyApiKey && ordnanceSurveyApiSecret) { await server.register({ plugin: mapPlugin, options: { ordnanceSurveyApiKey, ordnanceSurveyApiSecret } }) } server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath) server.expose('viewContext', viewContext) server.expose('cacheService', cacheService) server.expose('saveAndExit', saveAndExit) server.expose('baseUrl', baseUrl) server.expose('services', services) server.app.model = model // In-memory cache of FormModel items, exposed // (for testing purposes) through `server.app.models` const itemCache = new Map() server.app.models = itemCache const loadFormPreHandler = makeLoadFormPreHandler(server, options) const getRouteOptions: RouteOptions = { pre: [ { method: loadFormPreHandler as unknown as Lifecycle.Method } ] } const postRouteOptions: RouteOptions = { payload: { parse: true }, pre: [ { method: loadFormPreHandler as unknown as Lifecycle.Method } ] } const routes = [ ...getPaymentRoutes(), ...getFileUploadStatusRoutes(), ...getRepeaterSummaryRoutes(getRouteOptions, postRouteOptions, onRequest), ...getRepeaterItemDeleteRoutes( getRouteOptions, postRouteOptions, onRequest ), ...getQuestionRoutes( getRouteOptions, postRouteOptions, preparePageEventRequestOptions, onRequest ) ] server.route(routes as unknown as ServerRoute[]) // TODO } } satisfies Plugin