@defra/forms-engine-plugin 5.0.0-alpha.23 → 5.0.0-alpha.25

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 (32) hide show
  1. package/.public/javascripts/shared.min.js +1 -1
  2. package/.public/javascripts/shared.min.js.map +1 -1
  3. package/.server/client/javascripts/geospatial-map.d.ts +6 -0
  4. package/.server/client/javascripts/geospatial-map.js +2 -2
  5. package/.server/client/javascripts/geospatial-map.js.map +1 -1
  6. package/.server/client/javascripts/geospatial-map.test.js +152 -0
  7. package/.server/client/javascripts/geospatial-map.test.js.map +1 -0
  8. package/.server/client/javascripts/map.d.ts +2 -2
  9. package/.server/client/javascripts/map.js +0 -1
  10. package/.server/client/javascripts/map.js.map +1 -1
  11. package/.server/server/plugins/engine/components/ComponentCollection.js +1 -1
  12. package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
  13. package/.server/server/plugins/engine/components/helpers/geospatial.js +0 -1
  14. package/.server/server/plugins/engine/components/helpers/geospatial.js.map +1 -1
  15. package/.server/server/plugins/engine/views/summary.html +1 -0
  16. package/.server/server/plugins/nunjucks/enviroment.test.js +11 -4
  17. package/.server/server/plugins/nunjucks/enviroment.test.js.map +1 -1
  18. package/.server/server/plugins/postcode-lookup/models/index.js +16 -3
  19. package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
  20. package/.server/server/plugins/postcode-lookup/routes/index.js +17 -3
  21. package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
  22. package/.server/typings/geodesy/index.d.js +2 -0
  23. package/.server/typings/geodesy/index.d.js.map +1 -0
  24. package/package.json +1 -1
  25. package/src/client/javascripts/geospatial-map.js +2 -2
  26. package/src/client/javascripts/map.js +0 -1
  27. package/src/server/plugins/engine/components/ComponentCollection.ts +1 -4
  28. package/src/server/plugins/engine/components/helpers/geospatial.ts +0 -1
  29. package/src/server/plugins/engine/views/summary.html +1 -0
  30. package/src/server/plugins/postcode-lookup/models/index.js +16 -3
  31. package/src/server/plugins/postcode-lookup/routes/index.js +23 -8
  32. package/src/typings/geodesy/index.d.ts +18 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Joi","t","i18nT","service","crumbSchema","postcodeQueryFieldName","buildingNameQueryFieldName","uprnFieldName","line1FieldName","line2FieldName","townFieldName","countyFieldName","postcodeFieldName","GOVUK_MARGIN_RIGHT_1","COMMON_BACK","steps","details","select","manual","JOURNEY_BASE_URL","buildErrors","err","hasErrors","isError","length","getError","fieldName","find","item","path","postcodeQueryError","buildingNameQueryError","uprnError","line1Error","line2Error","townError","countyError","postcodeError","errors","pushError","push","text","message","href","getAddresses","postcodeQuery","buildingNameQuery","apiKey","addresses","search","addressCount","singleAddress","at","undefined","hasAddresses","hasMultipleAddresses","getDetailsFields","language","id","name","label","hint","value","errorMessage","getSelectFields","payload","selectAddressText","type","uprn","items","concat","map","formatted","getManualFields","addressLine1","addressLine2","classes","town","county","postcode","stepSchema","string","valid","Object","keys","required","sharedPayloadSchemaKeys","crumb","step","createDetailsPayloadSchema","object","pattern","trim","messages","allow","createSelectPayloadSchema","createManualPayloadSchema","getHref","query","detailsViewModel","data","translator","componentId","componentHint","sourceUrl","languages","initial","tComponent","tForm","component","backLink","fields","continueButton","manualLink","selector","showTitle","serviceUrl","pageTitle","buttons","selectViewModel","session","title","formPath","searchAgainText","searchAgainLink","addressesFoundText","count","noAddressFoundText","manualViewModel","detailsLink"],"sources":["../../../../../src/server/plugins/postcode-lookup/models/index.js"],"sourcesContent":["import Joi from 'joi'\n\nimport { t as i18nT } from '~/src/server/plugins/engine/i18n/index.js'\nimport * as service from '~/src/server/plugins/postcode-lookup/service.js'\nimport { crumbSchema } from '~/src/server/schemas/index.js'\n\n// Field names/ids\nconst postcodeQueryFieldName = 'postcodeQuery'\nconst buildingNameQueryFieldName = 'buildingNameQuery'\nconst uprnFieldName = 'uprn'\n\nconst line1FieldName = 'addressLine1'\nconst line2FieldName = 'addressLine2'\nconst townFieldName = 'town'\nconst countyFieldName = 'county'\nconst postcodeFieldName = 'postcode'\n\nconst GOVUK_MARGIN_RIGHT_1 = 'govuk-!-margin-right-1'\nconst COMMON_BACK = 'common.back'\n\nexport const steps = {\n // Step 1: Postcode/building name input\n details: 'details',\n // Step 2: Select address\n select: 'select',\n // Step 3: Manual address\n manual: 'manual'\n}\n\nexport const JOURNEY_BASE_URL = '/postcode-lookup'\n\n/**\n * Build form errors\n * @param {Error} [err]\n */\nfunction buildErrors(err) {\n const hasErrors = Joi.isError(err) && err.details.length > 0\n\n if (!hasErrors) {\n return {}\n }\n\n /**\n * Get error by path\n * @param {string} fieldName\n */\n const getError = (fieldName) => {\n return err.details.find((item) => item.path[0] === fieldName)\n }\n\n const postcodeQueryError = getError(postcodeQueryFieldName)\n const buildingNameQueryError = getError(buildingNameQueryFieldName)\n const uprnError = getError(uprnFieldName)\n const line1Error = getError(line1FieldName)\n const line2Error = getError(line2FieldName)\n const townError = getError(townFieldName)\n const countyError = getError(countyFieldName)\n const postcodeError = getError(postcodeFieldName)\n\n /**\n * @type {{ text: string, href: string }[]}\n */\n const errors = []\n\n /**\n * Push error\n * @param {string} fieldName - the field name\n * @param {ValidationErrorItem} [item] - the joi validation error\n */\n const pushError = (fieldName, item) => {\n if (item) {\n errors.push({\n text: item.message,\n href: `#${fieldName}`\n })\n }\n }\n\n pushError(postcodeQueryFieldName, postcodeQueryError)\n pushError(buildingNameQueryFieldName, buildingNameQueryError)\n pushError(uprnFieldName, uprnError)\n pushError(line1FieldName, line1Error)\n pushError(line2FieldName, line2Error)\n pushError(townFieldName, townError)\n pushError(countyFieldName, countyError)\n pushError(postcodeFieldName, postcodeError)\n\n return {\n errors,\n postcodeQueryError,\n buildingNameQueryError,\n uprnError,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError\n }\n}\n\n/**\n * Search ordnance survey for addresses\n * @param {string} postcodeQuery\n * @param {string} buildingNameQuery\n * @param {string} apiKey\n */\nasync function getAddresses(postcodeQuery, buildingNameQuery, apiKey) {\n const addresses = await service.search(\n postcodeQuery,\n buildingNameQuery,\n apiKey\n )\n const addressCount = addresses.length\n const singleAddress = addressCount === 1 ? addresses.at(0) : undefined\n const hasAddresses = addressCount > 0\n const hasMultipleAddresses = addressCount > 1\n\n return {\n hasAddresses,\n hasMultipleAddresses,\n singleAddress,\n addresses,\n addressCount\n }\n}\n\n/**\n * Get the details view fields\n * @param {PostcodeLookupDetailsData | undefined} details\n * @param {OptionalValidationErrorItem} postcodeQueryError\n * @param {OptionalValidationErrorItem} buildingNameQueryError\n * @param {string} language\n */\nfunction getDetailsFields(\n details,\n postcodeQueryError,\n buildingNameQueryError,\n language\n) {\n return {\n [postcodeQueryFieldName]: {\n id: postcodeQueryFieldName,\n name: postcodeQueryFieldName,\n label: {\n text: i18nT('postcodeLookup.postcodeLabel', language)\n },\n hint: {\n text: i18nT('postcodeLookup.postcodeHint', language)\n },\n value: details?.postcodeQuery,\n errorMessage: postcodeQueryError && { text: postcodeQueryError.message }\n },\n [buildingNameQueryFieldName]: {\n id: buildingNameQueryFieldName,\n name: buildingNameQueryFieldName,\n label: {\n text: i18nT('postcodeLookup.buildingNameLabel', language)\n },\n hint: {\n text: i18nT('postcodeLookup.buildingNameHint', language)\n },\n value: details?.buildingNameQuery,\n errorMessage: buildingNameQueryError && {\n text: buildingNameQueryError.message\n }\n }\n }\n}\n\n/**\n * Get the select view fields\n * @param {PostcodeLookupDetailsData} details\n * @param {boolean} hasMultipleAddresses\n * @param {Address | undefined} singleAddress\n * @param {PostcodeLookupSelectPayload | undefined} payload\n * @param {OptionalValidationErrorItem} uprnError\n * @param {Address[]} addresses\n * @param {string} language\n */\nfunction getSelectFields(\n details,\n hasMultipleAddresses,\n singleAddress,\n payload,\n uprnError,\n addresses,\n language\n) {\n const selectAddressText = i18nT('postcodeLookup.selectAddress', language)\n\n return {\n [postcodeQueryFieldName]: {\n id: postcodeQueryFieldName,\n name: postcodeQueryFieldName,\n type: 'hidden',\n value: details.postcodeQuery\n },\n [buildingNameQueryFieldName]: {\n id: buildingNameQueryFieldName,\n name: buildingNameQueryFieldName,\n type: 'hidden',\n value: details.buildingNameQuery\n },\n [uprnFieldName]: {\n id: uprnFieldName,\n name: uprnFieldName,\n label: hasMultipleAddresses\n ? {\n text: selectAddressText\n }\n : undefined,\n value: singleAddress ? singleAddress.uprn : payload?.uprn,\n errorMessage: uprnError && { text: uprnError.message },\n items: hasMultipleAddresses\n ? [{ text: selectAddressText, value: '' }].concat(\n addresses.map((item) => ({\n text: item.formatted,\n value: item.uprn\n }))\n )\n : undefined,\n type: singleAddress ? 'hidden' : undefined\n }\n }\n}\n\n/**\n * Get the manual view fields\n * @param {PostcodeLookupManualPayload | undefined} payload\n * @param {OptionalValidationErrorItem} line1Error\n * @param {OptionalValidationErrorItem} line2Error\n * @param {OptionalValidationErrorItem} townError\n * @param {OptionalValidationErrorItem} countyError\n * @param {OptionalValidationErrorItem} postcodeError\n * @param {string} language\n */\nfunction getManualFields(\n payload,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError,\n language\n) {\n return {\n [line1FieldName]: {\n id: line1FieldName,\n name: line1FieldName,\n label: {\n text: i18nT('postcodeLookup.addressLine1Label', language)\n },\n value: payload?.addressLine1,\n errorMessage: line1Error && { text: line1Error.message }\n },\n [line2FieldName]: {\n id: line2FieldName,\n name: line2FieldName,\n label: {\n text: i18nT('postcodeLookup.addressLine2Label', language)\n },\n value: payload?.addressLine2,\n errorMessage: line2Error && { text: line2Error.message }\n },\n [townFieldName]: {\n id: townFieldName,\n name: townFieldName,\n label: {\n text: i18nT('postcodeLookup.townLabel', language)\n },\n classes: 'govuk-!-width-two-thirds',\n value: payload?.town,\n errorMessage: townError && { text: townError.message }\n },\n [countyFieldName]: {\n id: countyFieldName,\n name: countyFieldName,\n label: {\n text: i18nT('postcodeLookup.countyLabel', language)\n },\n value: payload?.county,\n errorMessage: countyError && { text: countyError.message }\n },\n [postcodeFieldName]: {\n id: postcodeFieldName,\n name: postcodeFieldName,\n label: {\n text: i18nT('postcodeLookup.postcodeLabel', language)\n },\n classes: 'govuk-input--width-10',\n value: payload?.postcode,\n errorMessage: postcodeError && { text: postcodeError.message }\n }\n }\n}\n\nexport const stepSchema = Joi.string()\n .valid(...Object.keys(steps))\n .required()\n\nconst sharedPayloadSchemaKeys = {\n crumb: crumbSchema,\n step: stepSchema\n}\n\n/**\n * Postcode lookup details form payload schema\n * @param {string} [language]\n * @returns {ObjectSchema<PostcodeLookupDetailsPayload>}\n */\nexport function createDetailsPayloadSchema(language = 'en-GB') {\n return Joi.object()\n .keys({\n ...sharedPayloadSchemaKeys,\n [postcodeQueryFieldName]: Joi.string()\n .pattern(/^[a-zA-Z]{1,2}\\d[a-zA-Z\\d]?\\s?\\d[a-zA-Z]{2}$/)\n .trim()\n .required()\n .messages({\n 'string.pattern.base': i18nT(\n 'postcodeLookup.validation.invalidPostcode',\n language\n ),\n '*': i18nT('postcodeLookup.validation.requiredPostcode', language)\n }),\n [buildingNameQueryFieldName]: Joi.string()\n .trim()\n .required()\n .allow('')\n .trim()\n })\n .required()\n}\n\n/**\n * Postcode lookup select form payload schema\n * @param {string} [language]\n * @returns {ObjectSchema<PostcodeLookupSelectPayload>}\n */\nexport function createSelectPayloadSchema(language = 'en-GB') {\n return Joi.object()\n .keys({\n ...sharedPayloadSchemaKeys,\n [uprnFieldName]: Joi.string()\n .required()\n .messages({\n '*': i18nT('postcodeLookup.validation.selectAddress', language)\n })\n })\n .required()\n}\n\n/**\n * Postcode lookup manual form payload schema\n * @param {string} [language]\n * @returns {ObjectSchema<PostcodeLookupManualPayload>}\n */\nexport function createManualPayloadSchema(language = 'en-GB') {\n return Joi.object()\n .keys({\n ...sharedPayloadSchemaKeys,\n [line1FieldName]: Joi.string()\n .trim()\n .required()\n .messages({\n '*': i18nT('postcodeLookup.validation.requiredAddressLine1', language)\n }),\n [line2FieldName]: Joi.string().trim().allow('').required(),\n [townFieldName]: Joi.string()\n .trim()\n .required()\n .messages({\n '*': i18nT('postcodeLookup.validation.requiredTown', language)\n }),\n [countyFieldName]: Joi.string().trim().allow('').required(),\n [postcodeFieldName]: Joi.string()\n .pattern(/^[a-zA-Z]{1,2}\\d[a-zA-Z\\d]?\\s?\\d[a-zA-Z]{2}$/)\n .trim()\n .required()\n .messages({\n 'string.pattern.base': i18nT(\n 'postcodeLookup.validation.invalidManualPostcode',\n language\n ),\n '*': i18nT(\n 'postcodeLookup.validation.requiredManualPostcode',\n language\n )\n })\n })\n .required()\n}\n\n/**\n * Get the postcode lookup href\n * @param {string} [step] - the postcode lookup step\n */\nfunction getHref(step) {\n const query = step ? `?step=${step}` : ''\n\n return `${JOURNEY_BASE_URL}${query}`\n}\n\n/**\n * The postcode lookup details form view model\n * @param {PostcodeLookupSessionData} data\n * @param {Translator} translator\n * @param {PostcodeLookupDetailsData} [payload]\n * @param {Error} [err]\n */\nexport function detailsViewModel(data, translator, payload, err) {\n const { componentId, componentHint, sourceUrl, languages } = data.initial\n\n const { t, tComponent, tForm } = translator\n\n const component = /** @type {ComponentDef} */ ({ id: componentId })\n\n const backLink = {\n href: sourceUrl,\n text: t(COMMON_BACK)\n }\n\n const { errors, postcodeQueryError, buildingNameQueryError } =\n buildErrors(err)\n\n const fields = getDetailsFields(\n payload ?? data.details,\n postcodeQueryError,\n buildingNameQueryError,\n translator.language\n )\n\n const hint = componentHint && {\n text: tComponent(component, 'hint')\n }\n\n const continueButton = {\n text: t('postcodeLookup.findAddress'),\n classes: GOVUK_MARGIN_RIGHT_1\n }\n const manualLink = {\n text: t('postcodeLookup.enterManually'),\n href: getHref(steps.manual)\n }\n\n const selector = languages?.length ? { languages } : {}\n\n return {\n step: steps.details,\n showTitle: true,\n name: tForm('title'),\n serviceUrl: sourceUrl,\n pageTitle: tComponent(component, 'title'),\n hint,\n backLink,\n errors,\n fields,\n buttons: { continueButton, manualLink },\n t,\n language: translator.language,\n ...selector\n }\n}\n\n/**\n * The postcode lookup select form view model\n * @param {{ session: PostcodeLookupSessionData, apiKey: string }} data\n * @param {Translator} translator\n * @param {PostcodeLookupSelectPayload} [payload]\n * @param {Error} [err]\n */\nexport async function selectViewModel(data, translator, payload, err) {\n const { session, apiKey } = data\n const { details, initial } = session\n const { postcodeQuery, buildingNameQuery } = details\n const { language, t, tComponent, tForm } = translator\n\n const {\n hasAddresses,\n hasMultipleAddresses,\n singleAddress,\n addresses,\n addressCount\n } = await getAddresses(postcodeQuery, buildingNameQuery, apiKey)\n\n const title = hasAddresses\n ? tComponent(\n /** @type {ComponentDef} */ ({ id: initial.componentId }),\n 'title'\n )\n : t('postcodeLookup.noAddressFoundTitle')\n const formPath = initial.sourceUrl\n const href = getHref()\n\n const backLink = {\n href,\n text: t(COMMON_BACK)\n }\n\n const { errors, uprnError } = buildErrors(err)\n\n const fields = getSelectFields(\n details,\n hasMultipleAddresses,\n singleAddress,\n payload,\n uprnError,\n addresses,\n language\n )\n\n const searchAgainText = t('postcodeLookup.searchAgain')\n\n const searchAgainLink = {\n text: searchAgainText,\n href\n }\n\n const continueButton = {\n href: hasAddresses ? undefined : href,\n text: hasAddresses ? t('postcodeLookup.useThisAddress') : searchAgainText,\n classes: GOVUK_MARGIN_RIGHT_1\n }\n const manualLink = {\n text: t('postcodeLookup.enterManually'),\n href: `${href}?step=${steps.manual}`\n }\n\n const addressesFoundText = hasAddresses\n ? t('postcodeLookup.addressFound', { count: addressCount })\n : undefined\n const noAddressFoundText = !hasAddresses\n ? t('postcodeLookup.noAddressFoundBody')\n : undefined\n\n const selector = initial.languages?.length\n ? { languages: initial.languages }\n : {}\n\n return {\n step: steps.select,\n showTitle: true,\n name: tForm('title'),\n serviceUrl: formPath,\n pageTitle: title,\n backLink,\n errors,\n searchAgainLink,\n fields,\n details,\n addressCount,\n singleAddress,\n hasAddresses,\n hasMultipleAddresses,\n addressesFoundText,\n noAddressFoundText,\n buttons: { continueButton, manualLink },\n t,\n language,\n ...selector\n }\n}\n\n/**\n * The postcode lookup manual form view model\n * @param {PostcodeLookupSessionData} data\n * @param {Translator} translator\n * @param {PostcodeLookupManualPayload} [payload]\n * @param {Error} [err]\n */\nexport function manualViewModel(data, translator, payload, err) {\n const { componentId, sourceUrl, componentHint, languages } = data.initial\n const formPath = sourceUrl\n const href = getHref()\n\n const { t, tComponent, tForm } = translator\n\n const component = /** @type {ComponentDef} */ ({ id: componentId })\n\n const backLink = {\n href,\n text: t(COMMON_BACK)\n }\n\n const {\n errors,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError\n } = buildErrors(err)\n\n const hint = componentHint && {\n text: tComponent(component, 'hint')\n }\n\n const fields = getManualFields(\n payload,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError,\n translator.language\n )\n\n const continueButton = {\n text: t('postcodeLookup.useThisAddress'),\n classes: GOVUK_MARGIN_RIGHT_1\n }\n const detailsLink = {\n text: t('postcodeLookup.findAnAddressInstead'),\n href\n }\n\n const selector = languages?.length ? { languages } : {}\n\n return {\n step: steps.manual,\n showTitle: true,\n name: tForm('title'),\n serviceUrl: formPath,\n pageTitle: tComponent(component, 'title'),\n backLink,\n errors,\n hint,\n fields,\n buttons: { continueButton, detailsLink },\n t,\n language: translator.language,\n ...selector\n }\n}\n\n/** @typedef { ValidationErrorItem | undefined } OptionalValidationErrorItem */\n\n/**\n * @import { ObjectSchema, ValidationErrorItem } from 'joi'\n * @import { ComponentDef } from '@defra/forms-model'\n * @import { Address, PostcodeLookupDetailsData, PostcodeLookupDetailsPayload, PostcodeLookupManualPayload, PostcodeLookupSelectPayload, PostcodeLookupSessionData } from '~/src/server/plugins/postcode-lookup/types.js'\n * @import { Translator } from '~/src/server/plugins/engine/i18n/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["Joi","t","i18nT","service","crumbSchema","postcodeQueryFieldName","buildingNameQueryFieldName","uprnFieldName","line1FieldName","line2FieldName","townFieldName","countyFieldName","postcodeFieldName","GOVUK_MARGIN_RIGHT_1","COMMON_BACK","steps","details","select","manual","JOURNEY_BASE_URL","buildErrors","err","hasErrors","isError","length","getError","fieldName","find","item","path","postcodeQueryError","buildingNameQueryError","uprnError","line1Error","line2Error","townError","countyError","postcodeError","errors","pushError","push","text","message","href","getAddresses","postcodeQuery","buildingNameQuery","apiKey","addresses","search","addressCount","singleAddress","at","undefined","hasAddresses","hasMultipleAddresses","getDetailsFields","language","id","name","label","hint","value","errorMessage","getSelectFields","payload","selectAddressText","type","uprn","items","concat","map","formatted","getManualFields","addressLine1","addressLine2","classes","town","county","postcode","stepSchema","string","valid","Object","keys","required","detailsObjectSchema","object","bind","selectObjectSchema","manualObjectSchema","sharedPayloadSchemaKeys","crumb","step","createDetailsPayloadSchema","pattern","trim","messages","allow","createSelectPayloadSchema","createManualPayloadSchema","getHref","query","detailsViewModel","data","translator","componentId","componentHint","sourceUrl","languages","initial","tComponent","tForm","component","backLink","fields","continueButton","manualLink","selector","showTitle","serviceUrl","pageTitle","buttons","selectViewModel","session","title","formPath","searchAgainText","searchAgainLink","addressesFoundText","count","noAddressFoundText","manualViewModel","detailsLink"],"sources":["../../../../../src/server/plugins/postcode-lookup/models/index.js"],"sourcesContent":["import Joi from 'joi'\n\nimport { t as i18nT } from '~/src/server/plugins/engine/i18n/index.js'\nimport * as service from '~/src/server/plugins/postcode-lookup/service.js'\nimport { crumbSchema } from '~/src/server/schemas/index.js'\n\n// Field names/ids\nconst postcodeQueryFieldName = 'postcodeQuery'\nconst buildingNameQueryFieldName = 'buildingNameQuery'\nconst uprnFieldName = 'uprn'\n\nconst line1FieldName = 'addressLine1'\nconst line2FieldName = 'addressLine2'\nconst townFieldName = 'town'\nconst countyFieldName = 'county'\nconst postcodeFieldName = 'postcode'\n\nconst GOVUK_MARGIN_RIGHT_1 = 'govuk-!-margin-right-1'\nconst COMMON_BACK = 'common.back'\n\nexport const steps = {\n // Step 1: Postcode/building name input\n details: 'details',\n // Step 2: Select address\n select: 'select',\n // Step 3: Manual address\n manual: 'manual'\n}\n\nexport const JOURNEY_BASE_URL = '/postcode-lookup'\n\n/**\n * Build form errors\n * @param {Error} [err]\n */\nfunction buildErrors(err) {\n const hasErrors = Joi.isError(err) && err.details.length > 0\n\n if (!hasErrors) {\n return {}\n }\n\n /**\n * Get error by path\n * @param {string} fieldName\n */\n const getError = (fieldName) => {\n return err.details.find((item) => item.path[0] === fieldName)\n }\n\n const postcodeQueryError = getError(postcodeQueryFieldName)\n const buildingNameQueryError = getError(buildingNameQueryFieldName)\n const uprnError = getError(uprnFieldName)\n const line1Error = getError(line1FieldName)\n const line2Error = getError(line2FieldName)\n const townError = getError(townFieldName)\n const countyError = getError(countyFieldName)\n const postcodeError = getError(postcodeFieldName)\n\n /**\n * @type {{ text: string, href: string }[]}\n */\n const errors = []\n\n /**\n * Push error\n * @param {string} fieldName - the field name\n * @param {ValidationErrorItem} [item] - the joi validation error\n */\n const pushError = (fieldName, item) => {\n if (item) {\n errors.push({\n text: item.message,\n href: `#${fieldName}`\n })\n }\n }\n\n pushError(postcodeQueryFieldName, postcodeQueryError)\n pushError(buildingNameQueryFieldName, buildingNameQueryError)\n pushError(uprnFieldName, uprnError)\n pushError(line1FieldName, line1Error)\n pushError(line2FieldName, line2Error)\n pushError(townFieldName, townError)\n pushError(countyFieldName, countyError)\n pushError(postcodeFieldName, postcodeError)\n\n return {\n errors,\n postcodeQueryError,\n buildingNameQueryError,\n uprnError,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError\n }\n}\n\n/**\n * Search ordnance survey for addresses\n * @param {string} postcodeQuery\n * @param {string} buildingNameQuery\n * @param {string} apiKey\n */\nasync function getAddresses(postcodeQuery, buildingNameQuery, apiKey) {\n const addresses = await service.search(\n postcodeQuery,\n buildingNameQuery,\n apiKey\n )\n const addressCount = addresses.length\n const singleAddress = addressCount === 1 ? addresses.at(0) : undefined\n const hasAddresses = addressCount > 0\n const hasMultipleAddresses = addressCount > 1\n\n return {\n hasAddresses,\n hasMultipleAddresses,\n singleAddress,\n addresses,\n addressCount\n }\n}\n\n/**\n * Get the details view fields\n * @param {PostcodeLookupDetailsData | undefined} details\n * @param {OptionalValidationErrorItem} postcodeQueryError\n * @param {OptionalValidationErrorItem} buildingNameQueryError\n * @param {string} language\n */\nfunction getDetailsFields(\n details,\n postcodeQueryError,\n buildingNameQueryError,\n language\n) {\n return {\n [postcodeQueryFieldName]: {\n id: postcodeQueryFieldName,\n name: postcodeQueryFieldName,\n label: {\n text: i18nT('postcodeLookup.postcodeLabel', language)\n },\n hint: {\n text: i18nT('postcodeLookup.postcodeHint', language)\n },\n value: details?.postcodeQuery,\n errorMessage: postcodeQueryError && { text: postcodeQueryError.message }\n },\n [buildingNameQueryFieldName]: {\n id: buildingNameQueryFieldName,\n name: buildingNameQueryFieldName,\n label: {\n text: i18nT('postcodeLookup.buildingNameLabel', language)\n },\n hint: {\n text: i18nT('postcodeLookup.buildingNameHint', language)\n },\n value: details?.buildingNameQuery,\n errorMessage: buildingNameQueryError && {\n text: buildingNameQueryError.message\n }\n }\n }\n}\n\n/**\n * Get the select view fields\n * @param {PostcodeLookupDetailsData} details\n * @param {boolean} hasMultipleAddresses\n * @param {Address | undefined} singleAddress\n * @param {PostcodeLookupSelectPayload | undefined} payload\n * @param {OptionalValidationErrorItem} uprnError\n * @param {Address[]} addresses\n * @param {string} language\n */\nfunction getSelectFields(\n details,\n hasMultipleAddresses,\n singleAddress,\n payload,\n uprnError,\n addresses,\n language\n) {\n const selectAddressText = i18nT('postcodeLookup.selectAddress', language)\n\n return {\n [postcodeQueryFieldName]: {\n id: postcodeQueryFieldName,\n name: postcodeQueryFieldName,\n type: 'hidden',\n value: details.postcodeQuery\n },\n [buildingNameQueryFieldName]: {\n id: buildingNameQueryFieldName,\n name: buildingNameQueryFieldName,\n type: 'hidden',\n value: details.buildingNameQuery\n },\n [uprnFieldName]: {\n id: uprnFieldName,\n name: uprnFieldName,\n label: hasMultipleAddresses\n ? {\n text: selectAddressText\n }\n : undefined,\n value: singleAddress ? singleAddress.uprn : payload?.uprn,\n errorMessage: uprnError && { text: uprnError.message },\n items: hasMultipleAddresses\n ? [{ text: selectAddressText, value: '' }].concat(\n addresses.map((item) => ({\n text: item.formatted,\n value: item.uprn\n }))\n )\n : undefined,\n type: singleAddress ? 'hidden' : undefined\n }\n }\n}\n\n/**\n * Get the manual view fields\n * @param {PostcodeLookupManualPayload | undefined} payload\n * @param {OptionalValidationErrorItem} line1Error\n * @param {OptionalValidationErrorItem} line2Error\n * @param {OptionalValidationErrorItem} townError\n * @param {OptionalValidationErrorItem} countyError\n * @param {OptionalValidationErrorItem} postcodeError\n * @param {string} language\n */\nfunction getManualFields(\n payload,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError,\n language\n) {\n return {\n [line1FieldName]: {\n id: line1FieldName,\n name: line1FieldName,\n label: {\n text: i18nT('postcodeLookup.addressLine1Label', language)\n },\n value: payload?.addressLine1,\n errorMessage: line1Error && { text: line1Error.message }\n },\n [line2FieldName]: {\n id: line2FieldName,\n name: line2FieldName,\n label: {\n text: i18nT('postcodeLookup.addressLine2Label', language)\n },\n value: payload?.addressLine2,\n errorMessage: line2Error && { text: line2Error.message }\n },\n [townFieldName]: {\n id: townFieldName,\n name: townFieldName,\n label: {\n text: i18nT('postcodeLookup.townLabel', language)\n },\n classes: 'govuk-!-width-two-thirds',\n value: payload?.town,\n errorMessage: townError && { text: townError.message }\n },\n [countyFieldName]: {\n id: countyFieldName,\n name: countyFieldName,\n label: {\n text: i18nT('postcodeLookup.countyLabel', language)\n },\n value: payload?.county,\n errorMessage: countyError && { text: countyError.message }\n },\n [postcodeFieldName]: {\n id: postcodeFieldName,\n name: postcodeFieldName,\n label: {\n text: i18nT('postcodeLookup.postcodeLabel', language)\n },\n classes: 'govuk-input--width-10',\n value: payload?.postcode,\n errorMessage: postcodeError && { text: postcodeError.message }\n }\n }\n}\n\nexport const stepSchema = Joi.string()\n .valid(...Object.keys(steps))\n .required()\n\n/**\n * Joi object schema factories typed with their payload, as JavaScript files\n * cannot pass type arguments to `Joi.object<T>()`\n */\n/** @type {() => ObjectSchema<PostcodeLookupDetailsPayload>} */\nconst detailsObjectSchema = Joi.object.bind(Joi)\n\n/** @type {() => ObjectSchema<PostcodeLookupSelectPayload>} */\nconst selectObjectSchema = Joi.object.bind(Joi)\n\n/** @type {() => ObjectSchema<PostcodeLookupManualPayload>} */\nconst manualObjectSchema = Joi.object.bind(Joi)\n\nconst sharedPayloadSchemaKeys = {\n crumb: crumbSchema,\n step: stepSchema\n}\n\n/**\n * Postcode lookup details form payload schema\n * @param {string} [language]\n * @returns {ObjectSchema<PostcodeLookupDetailsPayload>}\n */\nexport function createDetailsPayloadSchema(language = 'en-GB') {\n return detailsObjectSchema()\n .keys({\n ...sharedPayloadSchemaKeys,\n [postcodeQueryFieldName]: Joi.string()\n .pattern(/^[a-zA-Z]{1,2}\\d[a-zA-Z\\d]?\\s?\\d[a-zA-Z]{2}$/)\n .trim()\n .required()\n .messages({\n 'string.pattern.base': i18nT(\n 'postcodeLookup.validation.invalidPostcode',\n language\n ),\n '*': i18nT('postcodeLookup.validation.requiredPostcode', language)\n }),\n [buildingNameQueryFieldName]: Joi.string()\n .trim()\n .required()\n .allow('')\n .trim()\n })\n .required()\n}\n\n/**\n * Postcode lookup select form payload schema\n * @param {string} [language]\n * @returns {ObjectSchema<PostcodeLookupSelectPayload>}\n */\nexport function createSelectPayloadSchema(language = 'en-GB') {\n return selectObjectSchema()\n .keys({\n ...sharedPayloadSchemaKeys,\n [uprnFieldName]: Joi.string()\n .required()\n .messages({\n '*': i18nT('postcodeLookup.validation.selectAddress', language)\n })\n })\n .required()\n}\n\n/**\n * Postcode lookup manual form payload schema\n * @param {string} [language]\n * @returns {ObjectSchema<PostcodeLookupManualPayload>}\n */\nexport function createManualPayloadSchema(language = 'en-GB') {\n return manualObjectSchema()\n .keys({\n ...sharedPayloadSchemaKeys,\n [line1FieldName]: Joi.string()\n .trim()\n .required()\n .messages({\n '*': i18nT('postcodeLookup.validation.requiredAddressLine1', language)\n }),\n [line2FieldName]: Joi.string().trim().allow('').required(),\n [townFieldName]: Joi.string()\n .trim()\n .required()\n .messages({\n '*': i18nT('postcodeLookup.validation.requiredTown', language)\n }),\n [countyFieldName]: Joi.string().trim().allow('').required(),\n [postcodeFieldName]: Joi.string()\n .pattern(/^[a-zA-Z]{1,2}\\d[a-zA-Z\\d]?\\s?\\d[a-zA-Z]{2}$/)\n .trim()\n .required()\n .messages({\n 'string.pattern.base': i18nT(\n 'postcodeLookup.validation.invalidManualPostcode',\n language\n ),\n '*': i18nT(\n 'postcodeLookup.validation.requiredManualPostcode',\n language\n )\n })\n })\n .required()\n}\n\n/**\n * Get the postcode lookup href\n * @param {string} [step] - the postcode lookup step\n */\nfunction getHref(step) {\n const query = step ? `?step=${step}` : ''\n\n return `${JOURNEY_BASE_URL}${query}`\n}\n\n/**\n * The postcode lookup details form view model\n * @param {PostcodeLookupSessionData} data\n * @param {Translator} translator\n * @param {PostcodeLookupDetailsData} [payload]\n * @param {Error} [err]\n */\nexport function detailsViewModel(data, translator, payload, err) {\n const { componentId, componentHint, sourceUrl, languages } = data.initial\n\n const { t, tComponent, tForm } = translator\n\n const component = /** @type {ComponentDef} */ ({ id: componentId })\n\n const backLink = {\n href: sourceUrl,\n text: t(COMMON_BACK)\n }\n\n const { errors, postcodeQueryError, buildingNameQueryError } =\n buildErrors(err)\n\n const fields = getDetailsFields(\n payload ?? data.details,\n postcodeQueryError,\n buildingNameQueryError,\n translator.language\n )\n\n const hint = componentHint && {\n text: tComponent(component, 'hint')\n }\n\n const continueButton = {\n text: t('postcodeLookup.findAddress'),\n classes: GOVUK_MARGIN_RIGHT_1\n }\n const manualLink = {\n text: t('postcodeLookup.enterManually'),\n href: getHref(steps.manual)\n }\n\n const selector = languages?.length ? { languages } : {}\n\n return {\n step: steps.details,\n showTitle: true,\n name: tForm('title'),\n serviceUrl: sourceUrl,\n pageTitle: tComponent(component, 'title'),\n hint,\n backLink,\n errors,\n fields,\n buttons: { continueButton, manualLink },\n t,\n language: translator.language,\n ...selector\n }\n}\n\n/**\n * The postcode lookup select form view model\n * @param {{ session: PostcodeLookupSessionData, apiKey: string }} data\n * @param {Translator} translator\n * @param {PostcodeLookupSelectPayload} [payload]\n * @param {Error} [err]\n */\nexport async function selectViewModel(data, translator, payload, err) {\n const { session, apiKey } = data\n const { details, initial } = session\n const { postcodeQuery, buildingNameQuery } = details\n const { language, t, tComponent, tForm } = translator\n\n const {\n hasAddresses,\n hasMultipleAddresses,\n singleAddress,\n addresses,\n addressCount\n } = await getAddresses(postcodeQuery, buildingNameQuery, apiKey)\n\n const title = hasAddresses\n ? tComponent(\n /** @type {ComponentDef} */ ({ id: initial.componentId }),\n 'title'\n )\n : t('postcodeLookup.noAddressFoundTitle')\n const formPath = initial.sourceUrl\n const href = getHref()\n\n const backLink = {\n href,\n text: t(COMMON_BACK)\n }\n\n const { errors, uprnError } = buildErrors(err)\n\n const fields = getSelectFields(\n details,\n hasMultipleAddresses,\n singleAddress,\n payload,\n uprnError,\n addresses,\n language\n )\n\n const searchAgainText = t('postcodeLookup.searchAgain')\n\n const searchAgainLink = {\n text: searchAgainText,\n href\n }\n\n const continueButton = {\n href: hasAddresses ? undefined : href,\n text: hasAddresses ? t('postcodeLookup.useThisAddress') : searchAgainText,\n classes: GOVUK_MARGIN_RIGHT_1\n }\n const manualLink = {\n text: t('postcodeLookup.enterManually'),\n href: `${href}?step=${steps.manual}`\n }\n\n const addressesFoundText = hasAddresses\n ? t('postcodeLookup.addressFound', { count: addressCount })\n : undefined\n const noAddressFoundText = !hasAddresses\n ? t('postcodeLookup.noAddressFoundBody')\n : undefined\n\n const selector = initial.languages?.length\n ? { languages: initial.languages }\n : {}\n\n return {\n step: steps.select,\n showTitle: true,\n name: tForm('title'),\n serviceUrl: formPath,\n pageTitle: title,\n backLink,\n errors,\n searchAgainLink,\n fields,\n details,\n addressCount,\n singleAddress,\n hasAddresses,\n hasMultipleAddresses,\n addressesFoundText,\n noAddressFoundText,\n buttons: { continueButton, manualLink },\n t,\n language,\n ...selector\n }\n}\n\n/**\n * The postcode lookup manual form view model\n * @param {PostcodeLookupSessionData} data\n * @param {Translator} translator\n * @param {PostcodeLookupManualPayload} [payload]\n * @param {Error} [err]\n */\nexport function manualViewModel(data, translator, payload, err) {\n const { componentId, sourceUrl, componentHint, languages } = data.initial\n const formPath = sourceUrl\n const href = getHref()\n\n const { t, tComponent, tForm } = translator\n\n const component = /** @type {ComponentDef} */ ({ id: componentId })\n\n const backLink = {\n href,\n text: t(COMMON_BACK)\n }\n\n const {\n errors,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError\n } = buildErrors(err)\n\n const hint = componentHint && {\n text: tComponent(component, 'hint')\n }\n\n const fields = getManualFields(\n payload,\n line1Error,\n line2Error,\n townError,\n countyError,\n postcodeError,\n translator.language\n )\n\n const continueButton = {\n text: t('postcodeLookup.useThisAddress'),\n classes: GOVUK_MARGIN_RIGHT_1\n }\n const detailsLink = {\n text: t('postcodeLookup.findAnAddressInstead'),\n href\n }\n\n const selector = languages?.length ? { languages } : {}\n\n return {\n step: steps.manual,\n showTitle: true,\n name: tForm('title'),\n serviceUrl: formPath,\n pageTitle: tComponent(component, 'title'),\n backLink,\n errors,\n hint,\n fields,\n buttons: { continueButton, detailsLink },\n t,\n language: translator.language,\n ...selector\n }\n}\n\n/** @typedef { ValidationErrorItem | undefined } OptionalValidationErrorItem */\n\n/**\n * @import { ObjectSchema, ValidationErrorItem } from 'joi'\n * @import { ComponentDef } from '@defra/forms-model'\n * @import { Address, PostcodeLookupDetailsData, PostcodeLookupDetailsPayload, PostcodeLookupManualPayload, PostcodeLookupSelectPayload, PostcodeLookupSessionData } from '~/src/server/plugins/postcode-lookup/types.js'\n * @import { Translator } from '~/src/server/plugins/engine/i18n/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
@@ -175,6 +175,19 @@ function postRoute(options) {
175
175
  };
176
176
  }
177
177
 
178
+ /**
179
+ * Validate a payload against a schema. Joi types the value as `any` when
180
+ * validation fails, so it is typed here as the partially converted payload.
181
+ * @template TSchema
182
+ * @param {ObjectSchema<TSchema>} schema
183
+ * @param {unknown} payload
184
+ * @param {ValidationOptions} [options]
185
+ * @returns {{ value: TSchema, error: undefined } | { value: TSchema | undefined, error: ValidationError }}
186
+ */
187
+ function validatePayload(schema, payload, options) {
188
+ return schema.validate(payload, options);
189
+ }
190
+
178
191
  /**
179
192
  * Post handler for the details step
180
193
  * @param {PostcodeLookupPostRequest} request
@@ -191,7 +204,7 @@ async function detailsPostHandler(request, h, options) {
191
204
  const {
192
205
  value: details,
193
206
  error
194
- } = createDetailsPayloadSchema(language).validate(request.payload);
207
+ } = validatePayload(createDetailsPayloadSchema(language), request.payload);
195
208
  let model;
196
209
  if (error) {
197
210
  model = detailsViewModel(session, translator, details, error);
@@ -231,7 +244,7 @@ async function selectPostHandler(request, h, options) {
231
244
  const {
232
245
  value: select,
233
246
  error
234
- } = createSelectPayloadSchema(language).validate(request.payload);
247
+ } = validatePayload(createSelectPayloadSchema(language), request.payload);
235
248
  if (error) {
236
249
  const model = await selectViewModel({
237
250
  session,
@@ -266,7 +279,7 @@ async function manualPostHandler(request, h) {
266
279
  const {
267
280
  value: manual,
268
281
  error
269
- } = createManualPayloadSchema(language).validate(request.payload, {
282
+ } = validatePayload(createManualPayloadSchema(language), request.payload, {
270
283
  abortEarly: false
271
284
  });
272
285
  if (error) {
@@ -285,6 +298,7 @@ async function manualPostHandler(request, h) {
285
298
 
286
299
  /**
287
300
  * @import { ResponseToolkit, ServerRoute } from '@hapi/hapi'
301
+ * @import { ObjectSchema, ValidationError, ValidationOptions } from 'joi'
288
302
  * @import { FormMetadata } from '@defra/forms-model'
289
303
  * @import { PostcodeLookupManualPayload, Address, PostcodeLookupGetRequestRefs, PostcodeLookupPostRequestRefs, PostcodeLookupRequest, PostcodeLookupPostRequest, PostcodeLookupConfiguration, PostcodeLookupDispatchData, PostcodeLookupSessionData } from '../../../../server/plugins/postcode-lookup/types.js'
290
304
  * @import { FormRequestPayload, FormResponseToolkit } from '../../../../server/routes/types.js'
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Boom","StatusCodes","Joi","EXTERNAL_STATE_APPENDAGE","getCachedPluginTranslator","JOURNEY_BASE_URL","createDetailsPayloadSchema","createManualPayloadSchema","createSelectPayloadSchema","detailsViewModel","manualViewModel","selectViewModel","stepSchema","steps","service","resolveLanguage","viewName","getSessionState","request","state","yar","get","badRequest","flashComponentState","componentName","address","addressState","addressLine1","addressLine2","town","county","postcode","uprn","undefined","appendage","component","data","flash","getDispatchTranslator","initial","language","formId","formStatus","set","typedReq","lang","translator","id","dispatch","h","details","postcodeQuery","buildingNameQuery","query","step","redirect","code","SEE_OTHER","getRoutes","options","getRoute","postRoute","method","path","handler","session","model","manual","view","validate","object","keys","string","allow","optional","payload","detailsPostHandler","select","selectPostHandler","manualPostHandler","unknown","ordnanceSurveyApiKey","apiKey","value","error","addresses","searchByUPRN","property","at","internal","sourceUrl","abortEarly"],"sources":["../../../../../src/server/plugins/postcode-lookup/routes/index.js"],"sourcesContent":["import Boom from '@hapi/boom'\nimport { StatusCodes } from 'http-status-codes'\nimport Joi from 'joi'\n\nimport { EXTERNAL_STATE_APPENDAGE } from '~/src/server/constants.js'\nimport { getCachedPluginTranslator } from '~/src/server/plugins/engine/i18n/form.js'\nimport {\n JOURNEY_BASE_URL,\n createDetailsPayloadSchema,\n createManualPayloadSchema,\n createSelectPayloadSchema,\n detailsViewModel,\n manualViewModel,\n selectViewModel,\n stepSchema,\n steps\n} from '~/src/server/plugins/postcode-lookup/models/index.js'\nimport * as service from '~/src/server/plugins/postcode-lookup/service.js'\nimport { resolveLanguage } from '~/src/server/utils/utils.js'\n\nconst viewName = 'postcode-lookup-details'\n\n/**\n * Get the session state associated with this journey\n * @param {PostcodeLookupRequest} request\n */\nexport function getSessionState(request) {\n /**\n * @type {PostcodeLookupSessionData | null | undefined}\n */\n const state = request.yar.get(JOURNEY_BASE_URL)\n\n if (!state) {\n throw Boom.badRequest(\n `No postcode lookup data found for ${JOURNEY_BASE_URL}`\n )\n }\n\n return state\n}\n\n/**\n * Flash form component state\n * @param {PostcodeLookupRequest} request - the request\n * @param {string} componentName - the component name\n * @param {Address | PostcodeLookupManualPayload} address - the address from ordnance survey or manually entered\n */\nfunction flashComponentState(request, componentName, address) {\n const addressState = {\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n town: address.town,\n county: address.county,\n postcode: address.postcode,\n uprn: 'uprn' in address && address.uprn ? address.uprn : undefined\n }\n\n /**\n * @type {ExternalStateAppendage}\n */\n const appendage = {\n component: componentName,\n data: addressState\n }\n\n request.yar.flash(EXTERNAL_STATE_APPENDAGE, appendage, true)\n}\n/**\n * Get a cached translator, or create a new one if not in the cache\n * @param {PostcodeLookupRequest} request\n * @param {PostcodeLookupDispatchData} initial\n * @param { string | string[] | undefined } language\n */\nexport async function getDispatchTranslator(request, initial, language) {\n const { formId, formStatus } = initial\n\n // Override language if passed as a query param\n if (language) {\n request.yar.set('language', language)\n }\n\n const typedReq = /** @type {AnyFormRequest} */ (/** @type {any} */ (request))\n const lang = resolveLanguage(typedReq)\n\n const translator = await getCachedPluginTranslator(\n typedReq,\n /** @type {FormMetadata} */ ({ id: formId }),\n formStatus,\n lang\n )\n\n return translator\n}\n\n/**\n * Initialises and dispatches the request to the postcode lookup journey\n * @param {FormRequestPayload} request - the source page\n * @param {FormResponseToolkit} h - the source page\n * @param {PostcodeLookupDispatchData} initial - the source data\n */\nexport function dispatch(request, h, initial) {\n /**\n * @type {PostcodeLookupSessionData}\n */\n const data = {\n initial,\n details: { postcodeQuery: '', buildingNameQuery: '' }\n }\n\n request.yar.set(JOURNEY_BASE_URL, data)\n\n const query = initial.step ? `?step=${initial.step}` : ''\n\n return h.redirect(`${JOURNEY_BASE_URL}${query}`).code(StatusCodes.SEE_OTHER)\n}\n\n/**\n * Gets the postcode lookup routes\n * @param {PostcodeLookupConfiguration} options - ordnance survey api key\n */\nexport function getRoutes(options) {\n return [getRoute(), postRoute(options)]\n}\n\n/**\n * @returns {ServerRoute<PostcodeLookupGetRequestRefs>}\n */\nfunction getRoute() {\n return {\n method: 'GET',\n path: JOURNEY_BASE_URL,\n async handler(request, h) {\n const { query } = request\n const { step, language } = query\n const session = getSessionState(request)\n\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n language\n )\n\n const model =\n step === steps.manual\n ? manualViewModel(session, translator)\n : detailsViewModel(session, translator)\n\n return h.view(viewName, model)\n },\n options: {\n validate: {\n query: Joi.object()\n .keys({\n step: Joi.string().allow(steps.details, steps.manual).optional(),\n language: Joi.string().allow('en-GB', 'cy').optional()\n })\n .optional()\n }\n }\n }\n}\n\n/**\n * @param {PostcodeLookupConfiguration} options\n * @returns {ServerRoute<PostcodeLookupPostRequestRefs>}\n */\nfunction postRoute(options) {\n return {\n method: 'POST',\n path: JOURNEY_BASE_URL,\n async handler(request, h) {\n const { payload } = request\n const { step } = payload\n\n switch (step) {\n case steps.details: {\n return detailsPostHandler(request, h, options)\n }\n case steps.select: {\n return selectPostHandler(request, h, options)\n }\n case steps.manual: {\n return manualPostHandler(request, h)\n }\n default:\n throw Boom.badRequest(`Invalid step ${step}`)\n }\n },\n options: {\n validate: {\n payload: Joi.object()\n .keys({\n step: stepSchema\n })\n .unknown(true)\n }\n }\n }\n}\n\n/**\n * Post handler for the details step\n * @param {PostcodeLookupPostRequest} request\n * @param {ResponseToolkit<PostcodeLookupPostRequestRefs>} h\n * @param {PostcodeLookupConfiguration} options\n */\nasync function detailsPostHandler(request, h, options) {\n const session = getSessionState(request)\n const { ordnanceSurveyApiKey: apiKey } = options\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n request.query.language\n )\n const language = translator.language\n\n const { value: details, error } = createDetailsPayloadSchema(\n language\n ).validate(request.payload)\n\n let model\n\n if (error) {\n model = detailsViewModel(session, translator, details, error)\n\n return h.view(viewName, model)\n }\n\n const { postcodeQuery, buildingNameQuery } = details\n session.details = { postcodeQuery, buildingNameQuery }\n\n // Store the updated session\n request.yar.set(JOURNEY_BASE_URL, session)\n\n model = await selectViewModel({ session, apiKey }, translator)\n\n return h.view(viewName, model)\n}\n\n/**\n * Post handler for the select step\n * @param {PostcodeLookupPostRequest} request\n * @param {ResponseToolkit<PostcodeLookupPostRequestRefs>} h\n * @param {PostcodeLookupConfiguration} options\n */\nasync function selectPostHandler(request, h, options) {\n const session = getSessionState(request)\n const { ordnanceSurveyApiKey: apiKey } = options\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n request.query.language\n )\n const language = translator.language\n const { value: select, error } = createSelectPayloadSchema(language).validate(\n request.payload\n )\n\n if (error) {\n const model = await selectViewModel(\n { session, apiKey },\n translator,\n select,\n error\n )\n\n return h.view(viewName, model)\n }\n\n const addresses = await service.searchByUPRN(select.uprn, apiKey)\n const property = addresses.at(0)\n\n if (!property) {\n throw Boom.internal(`UPRN ${property} not found`)\n }\n\n const { componentName, sourceUrl } = session.initial\n flashComponentState(request, componentName, property)\n\n // Redirect back to the source form page\n return h.redirect(sourceUrl).code(StatusCodes.SEE_OTHER)\n}\n\n/**\n * Post handler for the manual step\n * @param {PostcodeLookupPostRequest} request\n * @param {ResponseToolkit<PostcodeLookupPostRequestRefs>} h\n */\nasync function manualPostHandler(request, h) {\n const session = getSessionState(request)\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n request.query.language\n )\n const language = translator.language\n\n const { value: manual, error } = createManualPayloadSchema(language).validate(\n request.payload,\n {\n abortEarly: false\n }\n )\n\n if (error) {\n const model = manualViewModel(session, translator, manual, error)\n\n return h.view(viewName, model)\n }\n\n const { componentName, sourceUrl } = session.initial\n flashComponentState(request, componentName, manual)\n\n // Redirect back to the source form page\n return h.redirect(sourceUrl).code(StatusCodes.SEE_OTHER)\n}\n\n/**\n * @import { ResponseToolkit, ServerRoute } from '@hapi/hapi'\n * @import { FormMetadata } from '@defra/forms-model'\n * @import { PostcodeLookupManualPayload, Address, PostcodeLookupGetRequestRefs, PostcodeLookupPostRequestRefs, PostcodeLookupRequest, PostcodeLookupPostRequest, PostcodeLookupConfiguration, PostcodeLookupDispatchData, PostcodeLookupSessionData } from '~/src/server/plugins/postcode-lookup/types.js'\n * @import { FormRequestPayload, FormResponseToolkit } from '~/src/server/routes/types.js'\n * @import { AnyFormRequest, ExternalStateAppendage } from '~/src/server/plugins/engine/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["Boom","StatusCodes","Joi","EXTERNAL_STATE_APPENDAGE","getCachedPluginTranslator","JOURNEY_BASE_URL","createDetailsPayloadSchema","createManualPayloadSchema","createSelectPayloadSchema","detailsViewModel","manualViewModel","selectViewModel","stepSchema","steps","service","resolveLanguage","viewName","getSessionState","request","state","yar","get","badRequest","flashComponentState","componentName","address","addressState","addressLine1","addressLine2","town","county","postcode","uprn","undefined","appendage","component","data","flash","getDispatchTranslator","initial","language","formId","formStatus","set","typedReq","lang","translator","id","dispatch","h","details","postcodeQuery","buildingNameQuery","query","step","redirect","code","SEE_OTHER","getRoutes","options","getRoute","postRoute","method","path","handler","session","model","manual","view","validate","object","keys","string","allow","optional","payload","detailsPostHandler","select","selectPostHandler","manualPostHandler","unknown","validatePayload","schema","ordnanceSurveyApiKey","apiKey","value","error","addresses","searchByUPRN","property","at","internal","sourceUrl","abortEarly"],"sources":["../../../../../src/server/plugins/postcode-lookup/routes/index.js"],"sourcesContent":["import Boom from '@hapi/boom'\nimport { StatusCodes } from 'http-status-codes'\nimport Joi from 'joi'\n\nimport { EXTERNAL_STATE_APPENDAGE } from '~/src/server/constants.js'\nimport { getCachedPluginTranslator } from '~/src/server/plugins/engine/i18n/form.js'\nimport {\n JOURNEY_BASE_URL,\n createDetailsPayloadSchema,\n createManualPayloadSchema,\n createSelectPayloadSchema,\n detailsViewModel,\n manualViewModel,\n selectViewModel,\n stepSchema,\n steps\n} from '~/src/server/plugins/postcode-lookup/models/index.js'\nimport * as service from '~/src/server/plugins/postcode-lookup/service.js'\nimport { resolveLanguage } from '~/src/server/utils/utils.js'\n\nconst viewName = 'postcode-lookup-details'\n\n/**\n * Get the session state associated with this journey\n * @param {PostcodeLookupRequest} request\n */\nexport function getSessionState(request) {\n /**\n * @type {PostcodeLookupSessionData | null | undefined}\n */\n const state = request.yar.get(JOURNEY_BASE_URL)\n\n if (!state) {\n throw Boom.badRequest(\n `No postcode lookup data found for ${JOURNEY_BASE_URL}`\n )\n }\n\n return state\n}\n\n/**\n * Flash form component state\n * @param {PostcodeLookupRequest} request - the request\n * @param {string} componentName - the component name\n * @param {Address | PostcodeLookupManualPayload} address - the address from ordnance survey or manually entered\n */\nfunction flashComponentState(request, componentName, address) {\n const addressState = {\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n town: address.town,\n county: address.county,\n postcode: address.postcode,\n uprn: 'uprn' in address && address.uprn ? address.uprn : undefined\n }\n\n /**\n * @type {ExternalStateAppendage}\n */\n const appendage = {\n component: componentName,\n data: addressState\n }\n\n request.yar.flash(EXTERNAL_STATE_APPENDAGE, appendage, true)\n}\n/**\n * Get a cached translator, or create a new one if not in the cache\n * @param {PostcodeLookupRequest} request\n * @param {PostcodeLookupDispatchData} initial\n * @param { string | string[] | undefined } language\n */\nexport async function getDispatchTranslator(request, initial, language) {\n const { formId, formStatus } = initial\n\n // Override language if passed as a query param\n if (language) {\n request.yar.set('language', language)\n }\n\n const typedReq = /** @type {AnyFormRequest} */ (/** @type {any} */ (request))\n const lang = resolveLanguage(typedReq)\n\n const translator = await getCachedPluginTranslator(\n typedReq,\n /** @type {FormMetadata} */ ({ id: formId }),\n formStatus,\n lang\n )\n\n return translator\n}\n\n/**\n * Initialises and dispatches the request to the postcode lookup journey\n * @param {FormRequestPayload} request - the source page\n * @param {FormResponseToolkit} h - the source page\n * @param {PostcodeLookupDispatchData} initial - the source data\n */\nexport function dispatch(request, h, initial) {\n /**\n * @type {PostcodeLookupSessionData}\n */\n const data = {\n initial,\n details: { postcodeQuery: '', buildingNameQuery: '' }\n }\n\n request.yar.set(JOURNEY_BASE_URL, data)\n\n const query = initial.step ? `?step=${initial.step}` : ''\n\n return h.redirect(`${JOURNEY_BASE_URL}${query}`).code(StatusCodes.SEE_OTHER)\n}\n\n/**\n * Gets the postcode lookup routes\n * @param {PostcodeLookupConfiguration} options - ordnance survey api key\n */\nexport function getRoutes(options) {\n return [getRoute(), postRoute(options)]\n}\n\n/**\n * @returns {ServerRoute<PostcodeLookupGetRequestRefs>}\n */\nfunction getRoute() {\n return {\n method: 'GET',\n path: JOURNEY_BASE_URL,\n async handler(request, h) {\n const { query } = request\n const { step, language } = query\n const session = getSessionState(request)\n\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n language\n )\n\n const model =\n step === steps.manual\n ? manualViewModel(session, translator)\n : detailsViewModel(session, translator)\n\n return h.view(viewName, model)\n },\n options: {\n validate: {\n query: Joi.object()\n .keys({\n step: Joi.string().allow(steps.details, steps.manual).optional(),\n language: Joi.string().allow('en-GB', 'cy').optional()\n })\n .optional()\n }\n }\n }\n}\n\n/**\n * @param {PostcodeLookupConfiguration} options\n * @returns {ServerRoute<PostcodeLookupPostRequestRefs>}\n */\nfunction postRoute(options) {\n return {\n method: 'POST',\n path: JOURNEY_BASE_URL,\n async handler(request, h) {\n const { payload } = request\n const { step } = payload\n\n switch (step) {\n case steps.details: {\n return detailsPostHandler(request, h, options)\n }\n case steps.select: {\n return selectPostHandler(request, h, options)\n }\n case steps.manual: {\n return manualPostHandler(request, h)\n }\n default:\n throw Boom.badRequest(`Invalid step ${step}`)\n }\n },\n options: {\n validate: {\n payload: Joi.object()\n .keys({\n step: stepSchema\n })\n .unknown(true)\n }\n }\n }\n}\n\n/**\n * Validate a payload against a schema. Joi types the value as `any` when\n * validation fails, so it is typed here as the partially converted payload.\n * @template TSchema\n * @param {ObjectSchema<TSchema>} schema\n * @param {unknown} payload\n * @param {ValidationOptions} [options]\n * @returns {{ value: TSchema, error: undefined } | { value: TSchema | undefined, error: ValidationError }}\n */\nfunction validatePayload(schema, payload, options) {\n return schema.validate(payload, options)\n}\n\n/**\n * Post handler for the details step\n * @param {PostcodeLookupPostRequest} request\n * @param {ResponseToolkit<PostcodeLookupPostRequestRefs>} h\n * @param {PostcodeLookupConfiguration} options\n */\nasync function detailsPostHandler(request, h, options) {\n const session = getSessionState(request)\n const { ordnanceSurveyApiKey: apiKey } = options\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n request.query.language\n )\n const language = translator.language\n\n const { value: details, error } = validatePayload(\n createDetailsPayloadSchema(language),\n request.payload\n )\n\n let model\n\n if (error) {\n model = detailsViewModel(session, translator, details, error)\n\n return h.view(viewName, model)\n }\n\n const { postcodeQuery, buildingNameQuery } = details\n session.details = { postcodeQuery, buildingNameQuery }\n\n // Store the updated session\n request.yar.set(JOURNEY_BASE_URL, session)\n\n model = await selectViewModel({ session, apiKey }, translator)\n\n return h.view(viewName, model)\n}\n\n/**\n * Post handler for the select step\n * @param {PostcodeLookupPostRequest} request\n * @param {ResponseToolkit<PostcodeLookupPostRequestRefs>} h\n * @param {PostcodeLookupConfiguration} options\n */\nasync function selectPostHandler(request, h, options) {\n const session = getSessionState(request)\n const { ordnanceSurveyApiKey: apiKey } = options\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n request.query.language\n )\n const language = translator.language\n const { value: select, error } = validatePayload(\n createSelectPayloadSchema(language),\n request.payload\n )\n\n if (error) {\n const model = await selectViewModel(\n { session, apiKey },\n translator,\n select,\n error\n )\n\n return h.view(viewName, model)\n }\n\n const addresses = await service.searchByUPRN(select.uprn, apiKey)\n const property = addresses.at(0)\n\n if (!property) {\n throw Boom.internal(`UPRN ${property} not found`)\n }\n\n const { componentName, sourceUrl } = session.initial\n flashComponentState(request, componentName, property)\n\n // Redirect back to the source form page\n return h.redirect(sourceUrl).code(StatusCodes.SEE_OTHER)\n}\n\n/**\n * Post handler for the manual step\n * @param {PostcodeLookupPostRequest} request\n * @param {ResponseToolkit<PostcodeLookupPostRequestRefs>} h\n */\nasync function manualPostHandler(request, h) {\n const session = getSessionState(request)\n const translator = await getDispatchTranslator(\n request,\n session.initial,\n request.query.language\n )\n const language = translator.language\n\n const { value: manual, error } = validatePayload(\n createManualPayloadSchema(language),\n request.payload,\n { abortEarly: false }\n )\n\n if (error) {\n const model = manualViewModel(session, translator, manual, error)\n\n return h.view(viewName, model)\n }\n\n const { componentName, sourceUrl } = session.initial\n flashComponentState(request, componentName, manual)\n\n // Redirect back to the source form page\n return h.redirect(sourceUrl).code(StatusCodes.SEE_OTHER)\n}\n\n/**\n * @import { ResponseToolkit, ServerRoute } from '@hapi/hapi'\n * @import { ObjectSchema, ValidationError, ValidationOptions } from 'joi'\n * @import { FormMetadata } from '@defra/forms-model'\n * @import { PostcodeLookupManualPayload, Address, PostcodeLookupGetRequestRefs, PostcodeLookupPostRequestRefs, PostcodeLookupRequest, PostcodeLookupPostRequest, PostcodeLookupConfiguration, PostcodeLookupDispatchData, PostcodeLookupSessionData } from '~/src/server/plugins/postcode-lookup/types.js'\n * @import { FormRequestPayload, FormResponseToolkit } from '~/src/server/routes/types.js'\n * @import { AnyFormRequest, ExternalStateAppendage } from '~/src/server/plugins/engine/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=index.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.js","names":[],"sources":["../../../src/typings/geodesy/index.d.ts"],"sourcesContent":["declare module 'geodesy/osgridref.js' {\n export class LatLon {\n constructor(lat: number, lon: number, height?: number)\n get latitude(): number\n get longitude(): number\n get height(): number\n toOsGrid(): OsGridRef\n }\n\n export default class OsGridRef {\n constructor(easting: number, northing: number)\n easting: number\n northing: number\n toLatLon(): LatLon\n toString(digits?: number): string\n static parse(gridref: string): OsGridRef\n }\n}\n"],"mappings":"","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra/forms-engine-plugin",
3
- "version": "5.0.0-alpha.23",
3
+ "version": "5.0.0-alpha.25",
4
4
  "description": "Defra forms engine",
5
5
  "type": "module",
6
6
  "files": [
@@ -490,7 +490,7 @@ function prepareGeometry(feature) {
490
490
  * @param {GeoJSON} geojson
491
491
  * @returns {FeaturesManager}
492
492
  */
493
- function getFeaturesManager(geojson) {
493
+ export function getFeaturesManager(geojson) {
494
494
  /**
495
495
  * Get a feature from the geojson by id
496
496
  * @type {GetFeatures}
@@ -528,9 +528,9 @@ function getFeaturesManager(geojson) {
528
528
 
529
529
  // Ensure the feature exists in the geojson
530
530
  if (feature) {
531
+ feature.geometry = geometry
531
532
  feature.properties.coordinateGridReference = getCoordinateGridRef(feature)
532
533
  feature.properties.centroidGridReference = getCentroidGridRef(feature)
533
- feature.geometry = geometry
534
534
  prepareGeometry(feature)
535
535
  }
536
536
 
@@ -11,7 +11,6 @@ import createSearchPlugin from '@defra/interactive-map/plugins/search'
11
11
  // @ts-expect-error - no types
12
12
  import maplibreProvider from '@defra/interactive-map/providers/maplibre'
13
13
  import { centroid } from '@turf/centroid'
14
- // @ts-expect-error - no types
15
14
  import OsGridRef, { LatLon } from 'geodesy/osgridref.js'
16
15
 
17
16
  import { processGeospatial } from './geospatial-map.js'
@@ -259,10 +259,7 @@ export class ComponentCollection {
259
259
 
260
260
  // Update error with parent title
261
261
  if (translator && parent) {
262
- error.local.title ??= translator.tComponent(
263
- parent as ComponentDef,
264
- 'title'
265
- )
262
+ error.local.title ??= getTranslatedLabel(parent.def, translator)
266
263
  } else {
267
264
  error.local.title ??= parent?.label
268
265
  }
@@ -5,7 +5,6 @@ import {
5
5
  import Bourne from '@hapi/bourne'
6
6
  import { booleanWithin } from '@turf/boolean-within'
7
7
  import { point } from '@turf/helpers'
8
- // @ts-expect-error - no types
9
8
  import OsGridRef from 'geodesy/osgridref.js'
10
9
  import JoiBase, { type CustomValidator } from 'joi'
11
10
 
@@ -88,6 +88,7 @@
88
88
  When a better fix is implemented, this class can be removed and preventDoubleClick should be set back to true. #}
89
89
  {{ govukButton({
90
90
  text: submitButtonText,
91
+ classes: "prevent-multiple-clicks",
91
92
  name: "action",
92
93
  value: "send",
93
94
  preventDoubleClick: false
@@ -298,6 +298,19 @@ export const stepSchema = Joi.string()
298
298
  .valid(...Object.keys(steps))
299
299
  .required()
300
300
 
301
+ /**
302
+ * Joi object schema factories typed with their payload, as JavaScript files
303
+ * cannot pass type arguments to `Joi.object<T>()`
304
+ */
305
+ /** @type {() => ObjectSchema<PostcodeLookupDetailsPayload>} */
306
+ const detailsObjectSchema = Joi.object.bind(Joi)
307
+
308
+ /** @type {() => ObjectSchema<PostcodeLookupSelectPayload>} */
309
+ const selectObjectSchema = Joi.object.bind(Joi)
310
+
311
+ /** @type {() => ObjectSchema<PostcodeLookupManualPayload>} */
312
+ const manualObjectSchema = Joi.object.bind(Joi)
313
+
301
314
  const sharedPayloadSchemaKeys = {
302
315
  crumb: crumbSchema,
303
316
  step: stepSchema
@@ -309,7 +322,7 @@ const sharedPayloadSchemaKeys = {
309
322
  * @returns {ObjectSchema<PostcodeLookupDetailsPayload>}
310
323
  */
311
324
  export function createDetailsPayloadSchema(language = 'en-GB') {
312
- return Joi.object()
325
+ return detailsObjectSchema()
313
326
  .keys({
314
327
  ...sharedPayloadSchemaKeys,
315
328
  [postcodeQueryFieldName]: Joi.string()
@@ -338,7 +351,7 @@ export function createDetailsPayloadSchema(language = 'en-GB') {
338
351
  * @returns {ObjectSchema<PostcodeLookupSelectPayload>}
339
352
  */
340
353
  export function createSelectPayloadSchema(language = 'en-GB') {
341
- return Joi.object()
354
+ return selectObjectSchema()
342
355
  .keys({
343
356
  ...sharedPayloadSchemaKeys,
344
357
  [uprnFieldName]: Joi.string()
@@ -356,7 +369,7 @@ export function createSelectPayloadSchema(language = 'en-GB') {
356
369
  * @returns {ObjectSchema<PostcodeLookupManualPayload>}
357
370
  */
358
371
  export function createManualPayloadSchema(language = 'en-GB') {
359
- return Joi.object()
372
+ return manualObjectSchema()
360
373
  .keys({
361
374
  ...sharedPayloadSchemaKeys,
362
375
  [line1FieldName]: Joi.string()
@@ -198,6 +198,19 @@ function postRoute(options) {
198
198
  }
199
199
  }
200
200
 
201
+ /**
202
+ * Validate a payload against a schema. Joi types the value as `any` when
203
+ * validation fails, so it is typed here as the partially converted payload.
204
+ * @template TSchema
205
+ * @param {ObjectSchema<TSchema>} schema
206
+ * @param {unknown} payload
207
+ * @param {ValidationOptions} [options]
208
+ * @returns {{ value: TSchema, error: undefined } | { value: TSchema | undefined, error: ValidationError }}
209
+ */
210
+ function validatePayload(schema, payload, options) {
211
+ return schema.validate(payload, options)
212
+ }
213
+
201
214
  /**
202
215
  * Post handler for the details step
203
216
  * @param {PostcodeLookupPostRequest} request
@@ -214,9 +227,10 @@ async function detailsPostHandler(request, h, options) {
214
227
  )
215
228
  const language = translator.language
216
229
 
217
- const { value: details, error } = createDetailsPayloadSchema(
218
- language
219
- ).validate(request.payload)
230
+ const { value: details, error } = validatePayload(
231
+ createDetailsPayloadSchema(language),
232
+ request.payload
233
+ )
220
234
 
221
235
  let model
222
236
 
@@ -252,7 +266,8 @@ async function selectPostHandler(request, h, options) {
252
266
  request.query.language
253
267
  )
254
268
  const language = translator.language
255
- const { value: select, error } = createSelectPayloadSchema(language).validate(
269
+ const { value: select, error } = validatePayload(
270
+ createSelectPayloadSchema(language),
256
271
  request.payload
257
272
  )
258
273
 
@@ -295,11 +310,10 @@ async function manualPostHandler(request, h) {
295
310
  )
296
311
  const language = translator.language
297
312
 
298
- const { value: manual, error } = createManualPayloadSchema(language).validate(
313
+ const { value: manual, error } = validatePayload(
314
+ createManualPayloadSchema(language),
299
315
  request.payload,
300
- {
301
- abortEarly: false
302
- }
316
+ { abortEarly: false }
303
317
  )
304
318
 
305
319
  if (error) {
@@ -317,6 +331,7 @@ async function manualPostHandler(request, h) {
317
331
 
318
332
  /**
319
333
  * @import { ResponseToolkit, ServerRoute } from '@hapi/hapi'
334
+ * @import { ObjectSchema, ValidationError, ValidationOptions } from 'joi'
320
335
  * @import { FormMetadata } from '@defra/forms-model'
321
336
  * @import { PostcodeLookupManualPayload, Address, PostcodeLookupGetRequestRefs, PostcodeLookupPostRequestRefs, PostcodeLookupRequest, PostcodeLookupPostRequest, PostcodeLookupConfiguration, PostcodeLookupDispatchData, PostcodeLookupSessionData } from '../types.js'
322
337
  * @import { FormRequestPayload, FormResponseToolkit } from '../../../routes/types.js'
@@ -0,0 +1,18 @@
1
+ declare module 'geodesy/osgridref.js' {
2
+ export class LatLon {
3
+ constructor(lat: number, lon: number, height?: number)
4
+ get latitude(): number
5
+ get longitude(): number
6
+ get height(): number
7
+ toOsGrid(): OsGridRef
8
+ }
9
+
10
+ export default class OsGridRef {
11
+ constructor(easting: number, northing: number)
12
+ easting: number
13
+ northing: number
14
+ toLatLon(): LatLon
15
+ toString(digits?: number): string
16
+ static parse(gridref: string): OsGridRef
17
+ }
18
+ }