@defra/forms-engine-plugin 5.0.0-alpha.8 → 5.0.0-alpha.9
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/.server/server/constants.d.ts +1 -0
- package/.server/server/constants.js +2 -1
- package/.server/server/constants.js.map +1 -1
- package/.server/server/plugins/engine/components/ComponentCollection.js +10 -6
- package/.server/server/plugins/engine/components/ComponentCollection.js.map +1 -1
- package/.server/server/plugins/engine/components/DatePartsField.d.ts +4 -2
- package/.server/server/plugins/engine/components/DatePartsField.js +14 -11
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
- package/.server/server/plugins/engine/components/DeclarationField.d.ts +4 -2
- package/.server/server/plugins/engine/components/DeclarationField.js +5 -3
- package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
- package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +24 -2
- package/.server/server/plugins/engine/components/EastingNorthingField.js +93 -52
- package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.d.ts +4 -1
- package/.server/server/plugins/engine/components/FormComponent.js +3 -0
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/LatLongField.d.ts +24 -2
- package/.server/server/plugins/engine/components/LatLongField.js +85 -46
- package/.server/server/plugins/engine/components/LatLongField.js.map +1 -1
- package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +3 -2
- package/.server/server/plugins/engine/components/LocationFieldHelpers.js +10 -11
- package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -1
- package/.server/server/plugins/engine/components/MonthYearField.d.ts +4 -2
- package/.server/server/plugins/engine/components/MonthYearField.js +16 -13
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
- package/.server/server/plugins/engine/components/PaymentField.d.ts +1 -0
- package/.server/server/plugins/engine/components/PaymentField.js +9 -5
- package/.server/server/plugins/engine/components/PaymentField.js.map +1 -1
- package/.server/server/plugins/engine/components/UkAddressField.js +22 -7
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
- package/.server/server/plugins/engine/components/YesNoField.d.ts +3 -2
- package/.server/server/plugins/engine/components/YesNoField.js +5 -3
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/components.js +1 -2
- package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/index.d.ts +7 -0
- package/.server/server/plugins/engine/components/helpers/index.js +13 -1
- package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
- package/.server/server/plugins/engine/helpers.d.ts +21 -2
- package/.server/server/plugins/engine/helpers.js +43 -5
- package/.server/server/plugins/engine/helpers.js.map +1 -1
- package/.server/server/plugins/engine/i18n/createFormTranslator.d.ts +4 -4
- package/.server/server/plugins/engine/i18n/createFormTranslator.js +27 -5
- package/.server/server/plugins/engine/i18n/createFormTranslator.js.map +1 -1
- package/.server/server/plugins/engine/i18n/extractBaseTranslations.d.ts +1 -1
- package/.server/server/plugins/engine/i18n/extractBaseTranslations.js +9 -0
- package/.server/server/plugins/engine/i18n/extractBaseTranslations.js.map +1 -1
- package/.server/server/plugins/engine/i18n/form.d.ts +13 -0
- package/.server/server/plugins/engine/i18n/form.js +35 -0
- package/.server/server/plugins/engine/i18n/form.js.map +1 -0
- package/.server/server/plugins/engine/i18n/languages.d.ts +10 -0
- package/.server/server/plugins/engine/i18n/languages.js +19 -0
- package/.server/server/plugins/engine/i18n/languages.js.map +1 -0
- package/.server/server/plugins/engine/i18n/translations/cy.json +3 -1
- package/.server/server/plugins/engine/i18n/translations/en-GB.json +3 -1
- package/.server/server/plugins/engine/index.d.ts +3 -0
- package/.server/server/plugins/engine/index.js +3 -0
- package/.server/server/plugins/engine/index.js.map +1 -1
- package/.server/server/plugins/engine/models/FormModel.d.ts +0 -4
- package/.server/server/plugins/engine/models/FormModel.js +9 -15
- package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.js +2 -1
- package/.server/server/plugins/engine/models/SummaryViewModel.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js +2 -1
- package/.server/server/plugins/engine/outputFormatters/human/v1.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/machine/v2.d.ts +2 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js +2 -0
- package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +2 -2
- package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js +2 -2
- package/.server/server/plugins/engine/pageControllers/QuestionPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js +6 -3
- package/.server/server/plugins/engine/pageControllers/SummaryPageController.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.d.ts +1 -1
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js +3 -3
- package/.server/server/plugins/engine/pageControllers/helpers/submission.js.map +1 -1
- package/.server/server/plugins/engine/types/schema.js +1 -0
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +1 -0
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/.server/server/plugins/engine/views/components/ukaddressfield.html +1 -1
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.d.ts +9 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js +17 -0
- package/.server/server/plugins/nunjucks/filters/applyUrlParam.test.js.map +1 -0
- package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
- package/.server/server/plugins/nunjucks/filters/index.d.ts +1 -0
- package/.server/server/plugins/nunjucks/filters/index.js +1 -0
- package/.server/server/plugins/nunjucks/filters/index.js.map +1 -1
- package/.server/server/plugins/payment/helper.d.ts +11 -1
- package/.server/server/plugins/payment/helper.js +18 -2
- package/.server/server/plugins/payment/helper.js.map +1 -1
- package/.server/server/plugins/payment/helper.test.js +2 -1
- package/.server/server/plugins/payment/helper.test.js.map +1 -1
- package/.server/server/plugins/payment/service.d.ts +2 -1
- package/.server/server/plugins/payment/service.js +5 -2
- package/.server/server/plugins/payment/service.js.map +1 -1
- package/.server/server/plugins/payment/service.test.js +7 -3
- package/.server/server/plugins/payment/service.test.js.map +1 -1
- package/.server/server/plugins/payment/types.d.ts +4 -0
- package/.server/server/plugins/payment/types.js +1 -0
- package/.server/server/plugins/payment/types.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/models/index.d.ts +247 -3
- package/.server/server/plugins/postcode-lookup/models/index.js +86 -33
- package/.server/server/plugins/postcode-lookup/models/index.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/routes/index.d.ts +15 -1
- package/.server/server/plugins/postcode-lookup/routes/index.js +47 -15
- package/.server/server/plugins/postcode-lookup/routes/index.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/routes/index.test.js +84 -0
- package/.server/server/plugins/postcode-lookup/routes/index.test.js.map +1 -0
- package/.server/server/plugins/postcode-lookup/types.d.ts +12 -0
- package/.server/server/plugins/postcode-lookup/types.js +6 -1
- package/.server/server/plugins/postcode-lookup/types.js.map +1 -1
- package/.server/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
- package/package.json +2 -1
- package/src/server/constants.js +2 -1
- package/src/server/plugins/engine/components/ComponentCollection.ts +15 -9
- package/src/server/plugins/engine/components/DatePartsField.ts +16 -12
- package/src/server/plugins/engine/components/DeclarationField.ts +6 -4
- package/src/server/plugins/engine/components/EastingNorthingField.ts +156 -88
- package/src/server/plugins/engine/components/FormComponent.ts +4 -1
- package/src/server/plugins/engine/components/LatLongField.ts +129 -57
- package/src/server/plugins/engine/components/LocationFieldHelpers.ts +14 -11
- package/src/server/plugins/engine/components/MonthYearField.ts +16 -11
- package/src/server/plugins/engine/components/PaymentField.ts +9 -4
- package/src/server/plugins/engine/components/UkAddressField.ts +29 -6
- package/src/server/plugins/engine/components/YesNoField.ts +6 -5
- package/src/server/plugins/engine/components/helpers/components.ts +1 -2
- package/src/server/plugins/engine/components/helpers/index.ts +19 -0
- package/src/server/plugins/engine/helpers.ts +51 -5
- package/src/server/plugins/engine/i18n/createFormTranslator.ts +43 -12
- package/src/server/plugins/engine/i18n/extractBaseTranslations.ts +7 -1
- package/src/server/plugins/engine/i18n/form.ts +54 -0
- package/src/server/plugins/engine/i18n/languages.ts +19 -0
- package/src/server/plugins/engine/i18n/translations/cy.json +3 -1
- package/src/server/plugins/engine/i18n/translations/en-GB.json +3 -1
- package/src/server/plugins/engine/index.ts +6 -0
- package/src/server/plugins/engine/models/FormModel.ts +9 -15
- package/src/server/plugins/engine/models/SummaryViewModel.ts +2 -1
- package/src/server/plugins/engine/outputFormatters/human/v1.ts +2 -1
- package/src/server/plugins/engine/outputFormatters/machine/v2.ts +3 -0
- package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +2 -2
- package/src/server/plugins/engine/pageControllers/QuestionPageController.ts +2 -2
- package/src/server/plugins/engine/pageControllers/SummaryPageController.ts +9 -3
- package/src/server/plugins/engine/pageControllers/helpers/submission.ts +6 -3
- package/src/server/plugins/engine/types/schema.ts +1 -0
- package/src/server/plugins/engine/types.ts +1 -0
- package/src/server/plugins/engine/views/components/ukaddressfield.html +1 -1
- package/src/server/plugins/nunjucks/filters/applyUrlParam.js +17 -0
- package/src/server/plugins/nunjucks/filters/index.js +1 -0
- package/src/server/plugins/payment/helper.js +22 -2
- package/src/server/plugins/payment/service.js +6 -2
- package/src/server/plugins/payment/types.js +1 -0
- package/src/server/plugins/postcode-lookup/models/index.js +75 -43
- package/src/server/plugins/postcode-lookup/routes/index.js +73 -16
- package/src/server/plugins/postcode-lookup/types.js +6 -1
- package/src/server/plugins/postcode-lookup/views/postcode-lookup-details.html +3 -3
|
@@ -21,7 +21,7 @@ export declare function buildMainRecords(items: DetailItem[], translator: Transl
|
|
|
21
21
|
*
|
|
22
22
|
* Returns an empty array if no payment state exists.
|
|
23
23
|
*/
|
|
24
|
-
export declare function buildPaymentRecords(item: DetailItemField): SubmitRecord[];
|
|
24
|
+
export declare function buildPaymentRecords(item: DetailItemField, translator: Translator): SubmitRecord[];
|
|
25
25
|
/**
|
|
26
26
|
* Builds the repeater submission records from repeater items.
|
|
27
27
|
*/
|
|
@@ -12,7 +12,7 @@ export function buildMainRecords(items, translator) {
|
|
|
12
12
|
const records = [];
|
|
13
13
|
for (const item of fieldItems) {
|
|
14
14
|
if (item.field instanceof PaymentField) {
|
|
15
|
-
records.push(...buildPaymentRecords(item));
|
|
15
|
+
records.push(...buildPaymentRecords(item, translator));
|
|
16
16
|
} else if (item.field instanceof GeospatialField) {
|
|
17
17
|
// Stringify of GeoJSON is done here rather than inside `getContextValueFromState`
|
|
18
18
|
// so we don't incur the overhead of JSON.stringify on every request when building context
|
|
@@ -44,7 +44,7 @@ export function buildMainRecords(items, translator) {
|
|
|
44
44
|
*
|
|
45
45
|
* Returns an empty array if no payment state exists.
|
|
46
46
|
*/
|
|
47
|
-
export function buildPaymentRecords(item) {
|
|
47
|
+
export function buildPaymentRecords(item, translator) {
|
|
48
48
|
const paymentState = item.field.getPaymentStateFromState(item.state);
|
|
49
49
|
if (!paymentState) {
|
|
50
50
|
return [];
|
|
@@ -64,7 +64,7 @@ export function buildPaymentRecords(item) {
|
|
|
64
64
|
}, {
|
|
65
65
|
name: `${item.name}_paymentDate`,
|
|
66
66
|
title: 'Payment date',
|
|
67
|
-
value: paymentState.preAuth?.createdAt ? formatPaymentDate(paymentState.preAuth.createdAt) : ''
|
|
67
|
+
value: paymentState.preAuth?.createdAt ? formatPaymentDate(paymentState.preAuth.createdAt, translator.language) : ''
|
|
68
68
|
}];
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submission.js","names":["GeospatialField","PaymentField","getAnswer","formatCurrency","formatPaymentDate","buildMainRecords","items","translator","fieldItems","filter","item","records","field","push","buildPaymentRecords","value","getFormValueFromState","state","name","title","label","undefined","JSON","stringify","format","paymentState","getPaymentStateFromState","description","amount","reference","preAuth","createdAt","buildRepeaterRecords","map","subItems","detailItems","subItem","formValue"],"sources":["../../../../../../src/server/plugins/engine/pageControllers/helpers/submission.ts"],"sourcesContent":["import { type SubmitPayload } from '@defra/forms-model'\n\nimport { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport { getAnswer } from '~/src/server/plugins/engine/components/helpers/components.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport {\n type DetailItem,\n type DetailItemField\n} from '~/src/server/plugins/engine/models/types.js'\nimport {\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\n\nexport interface SubmitRecord {\n name: string\n title: string\n value: string\n}\n\n/**\n * Builds the main submission records from field items.\n * Regular fields are converted to single records, while PaymentField\n * components are expanded into four separate records.\n */\nexport function buildMainRecords(\n items: DetailItem[],\n translator: Translator\n): SubmitRecord[] {\n const fieldItems = items.filter(\n (item): item is DetailItemField => 'field' in item\n )\n\n const records: SubmitRecord[] = []\n\n for (const item of fieldItems) {\n if (item.field instanceof PaymentField) {\n records.push(...buildPaymentRecords(item))\n } else if (item.field instanceof GeospatialField) {\n // Stringify of GeoJSON is done here rather than inside `getContextValueFromState`\n // so we don't incur the overhead of JSON.stringify on every request when building context\n const value = item.field.getFormValueFromState(item.state)\n records.push({\n name: item.name,\n title: item.label,\n value: value === undefined ? '' : JSON.stringify(value)\n })\n } else {\n records.push({\n name: item.name,\n title: item.label,\n value: getAnswer(item.field, item.state, translator, { format: 'data' })\n })\n }\n }\n\n return records\n}\n\n/**\n * Expands a PaymentField into four submission records:\n * - Payment description\n * - Payment amount (formatted with currency symbol)\n * - Payment reference\n * - Payment date (formatted date/time)\n *\n * Returns an empty array if no payment state exists.\n */\nexport function buildPaymentRecords(item: DetailItemField): SubmitRecord[] {\n const paymentState = (item.field as PaymentField).getPaymentStateFromState(\n item.state\n )\n\n if (!paymentState) {\n return []\n }\n\n return [\n {\n name: `${item.name}_paymentDescription`,\n title: 'Payment description',\n value: paymentState.description\n },\n {\n name: `${item.name}_paymentAmount`,\n title: 'Payment amount',\n value: formatCurrency(paymentState.amount)\n },\n {\n name: `${item.name}_paymentReference`,\n title: 'Payment reference',\n value: paymentState.reference\n },\n {\n name: `${item.name}_paymentDate`,\n title: 'Payment date',\n value: paymentState.preAuth?.createdAt\n ? formatPaymentDate(paymentState.preAuth.createdAt)\n : ''\n }\n ]\n}\n\n/**\n * Builds the repeater submission records from repeater items.\n */\nexport function buildRepeaterRecords(\n items: DetailItem[],\n translator: Translator\n): SubmitPayload['repeaters'] {\n return items\n .filter((item) => 'subItems' in item)\n .map((item) => ({\n name: item.name,\n title: item.label,\n value: item.subItems.map((detailItems) =>\n detailItems.map((subItem) => {\n let value\n\n if (subItem.field instanceof GeospatialField) {\n // Stringify of GeoJSON is done here rather than inside `getContextValueFromState`\n // so we don't incur the overhead of JSON.stringify on every request when building context\n const formValue = subItem.field.getFormValueFromState(subItem.state)\n value = formValue === undefined ? '' : JSON.stringify(formValue)\n } else {\n value = getAnswer(subItem.field, subItem.state, translator, {\n format: 'data'\n })\n }\n\n return {\n name: subItem.name,\n title: subItem.label,\n value\n }\n })\n )\n }))\n}\n"],"mappings":"AAEA,SAASA,eAAe;AACxB,SAASC,YAAY;AACrB,SAASC,SAAS;AAMlB,SACEC,cAAc,EACdC,iBAAiB;AASnB;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAC9BC,KAAmB,EACnBC,UAAsB,EACN;EAChB,MAAMC,UAAU,GAAGF,KAAK,CAACG,MAAM,CAC5BC,IAAI,IAA8B,OAAO,IAAIA,IAChD,CAAC;EAED,MAAMC,OAAuB,GAAG,EAAE;EAElC,KAAK,MAAMD,IAAI,IAAIF,UAAU,EAAE;IAC7B,IAAIE,IAAI,CAACE,KAAK,YAAYX,YAAY,EAAE;MACtCU,OAAO,CAACE,IAAI,CAAC,GAAGC,mBAAmB,CAACJ,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"submission.js","names":["GeospatialField","PaymentField","getAnswer","formatCurrency","formatPaymentDate","buildMainRecords","items","translator","fieldItems","filter","item","records","field","push","buildPaymentRecords","value","getFormValueFromState","state","name","title","label","undefined","JSON","stringify","format","paymentState","getPaymentStateFromState","description","amount","reference","preAuth","createdAt","language","buildRepeaterRecords","map","subItems","detailItems","subItem","formValue"],"sources":["../../../../../../src/server/plugins/engine/pageControllers/helpers/submission.ts"],"sourcesContent":["import { type SubmitPayload } from '@defra/forms-model'\n\nimport { GeospatialField } from '~/src/server/plugins/engine/components/GeospatialField.js'\nimport { PaymentField } from '~/src/server/plugins/engine/components/PaymentField.js'\nimport { getAnswer } from '~/src/server/plugins/engine/components/helpers/components.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport {\n type DetailItem,\n type DetailItemField\n} from '~/src/server/plugins/engine/models/types.js'\nimport {\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\n\nexport interface SubmitRecord {\n name: string\n title: string\n value: string\n}\n\n/**\n * Builds the main submission records from field items.\n * Regular fields are converted to single records, while PaymentField\n * components are expanded into four separate records.\n */\nexport function buildMainRecords(\n items: DetailItem[],\n translator: Translator\n): SubmitRecord[] {\n const fieldItems = items.filter(\n (item): item is DetailItemField => 'field' in item\n )\n\n const records: SubmitRecord[] = []\n\n for (const item of fieldItems) {\n if (item.field instanceof PaymentField) {\n records.push(...buildPaymentRecords(item, translator))\n } else if (item.field instanceof GeospatialField) {\n // Stringify of GeoJSON is done here rather than inside `getContextValueFromState`\n // so we don't incur the overhead of JSON.stringify on every request when building context\n const value = item.field.getFormValueFromState(item.state)\n records.push({\n name: item.name,\n title: item.label,\n value: value === undefined ? '' : JSON.stringify(value)\n })\n } else {\n records.push({\n name: item.name,\n title: item.label,\n value: getAnswer(item.field, item.state, translator, { format: 'data' })\n })\n }\n }\n\n return records\n}\n\n/**\n * Expands a PaymentField into four submission records:\n * - Payment description\n * - Payment amount (formatted with currency symbol)\n * - Payment reference\n * - Payment date (formatted date/time)\n *\n * Returns an empty array if no payment state exists.\n */\nexport function buildPaymentRecords(\n item: DetailItemField,\n translator: Translator\n): SubmitRecord[] {\n const paymentState = (item.field as PaymentField).getPaymentStateFromState(\n item.state\n )\n\n if (!paymentState) {\n return []\n }\n\n return [\n {\n name: `${item.name}_paymentDescription`,\n title: 'Payment description',\n value: paymentState.description\n },\n {\n name: `${item.name}_paymentAmount`,\n title: 'Payment amount',\n value: formatCurrency(paymentState.amount)\n },\n {\n name: `${item.name}_paymentReference`,\n title: 'Payment reference',\n value: paymentState.reference\n },\n {\n name: `${item.name}_paymentDate`,\n title: 'Payment date',\n value: paymentState.preAuth?.createdAt\n ? formatPaymentDate(paymentState.preAuth.createdAt, translator.language)\n : ''\n }\n ]\n}\n\n/**\n * Builds the repeater submission records from repeater items.\n */\nexport function buildRepeaterRecords(\n items: DetailItem[],\n translator: Translator\n): SubmitPayload['repeaters'] {\n return items\n .filter((item) => 'subItems' in item)\n .map((item) => ({\n name: item.name,\n title: item.label,\n value: item.subItems.map((detailItems) =>\n detailItems.map((subItem) => {\n let value\n\n if (subItem.field instanceof GeospatialField) {\n // Stringify of GeoJSON is done here rather than inside `getContextValueFromState`\n // so we don't incur the overhead of JSON.stringify on every request when building context\n const formValue = subItem.field.getFormValueFromState(subItem.state)\n value = formValue === undefined ? '' : JSON.stringify(formValue)\n } else {\n value = getAnswer(subItem.field, subItem.state, translator, {\n format: 'data'\n })\n }\n\n return {\n name: subItem.name,\n title: subItem.label,\n value\n }\n })\n )\n }))\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -23,6 +23,7 @@ export const formAdapterSubmissionMessageDataSchema = Joi.object().keys({
|
|
|
23
23
|
reference: Joi.string().required(),
|
|
24
24
|
amount: Joi.number().required(),
|
|
25
25
|
description: Joi.string().required(),
|
|
26
|
+
descriptionInEng: Joi.string().optional(),
|
|
26
27
|
createdAt: Joi.string().required()
|
|
27
28
|
}).optional(),
|
|
28
29
|
files: Joi.object().pattern(Joi.string(), Joi.array().items(Joi.object().keys({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","names":["FormStatus","formVersionMetadataSchema","idSchema","notificationEmailAddressSchema","slugSchema","titleSchema","Joi","FormAdapterSubmissionSchemaVersion","formAdapterSubmissionMessageMetaSchema","object","keys","schemaVersion","string","valid","Object","values","timestamp","date","required","referenceNumber","formName","formId","formSlug","status","isPreview","boolean","notificationEmail","versionMetadata","optional","language","custom","pattern","any","unknown","description","formAdapterSubmissionMessageDataSchema","main","repeaters","payment","paymentId","reference","amount","number","createdAt","files","array","items","fileName","fileId","userDownloadLink","formAdapterSubmissionMessageResultSchema","formAdapterSubmissionMessagePayloadSchema","meta","data","result"],"sources":["../../../../../src/server/plugins/engine/types/schema.ts"],"sourcesContent":["import {\n FormStatus,\n formVersionMetadataSchema,\n idSchema,\n notificationEmailAddressSchema,\n slugSchema,\n titleSchema\n} from '@defra/forms-model'\nimport Joi from 'joi'\n\nimport { FormAdapterSubmissionSchemaVersion } from '~/src/server/plugins/engine/types/enums.js'\nimport {\n type FormAdapterSubmissionMessageData,\n type FormAdapterSubmissionMessageMeta,\n type FormAdapterSubmissionMessagePayload,\n type FormAdapterSubmissionMessageResult\n} from '~/src/server/plugins/engine/types.js'\n\nexport const formAdapterSubmissionMessageMetaSchema =\n Joi.object<FormAdapterSubmissionMessageMeta>().keys({\n schemaVersion: Joi.string().valid(\n ...Object.values(FormAdapterSubmissionSchemaVersion)\n ),\n timestamp: Joi.date().required(),\n referenceNumber: Joi.string().required(),\n formName: titleSchema,\n formId: idSchema,\n formSlug: slugSchema,\n status: Joi.string()\n .valid(...Object.values(FormStatus))\n .required(),\n isPreview: Joi.boolean().required(),\n notificationEmail: notificationEmailAddressSchema.required(),\n versionMetadata: formVersionMetadataSchema.optional(),\n language: Joi.string().optional(),\n custom: Joi.object()\n .pattern(/^/, Joi.any())\n .unknown()\n .optional()\n .description('Custom properties for the message')\n })\n\nexport const formAdapterSubmissionMessageDataSchema =\n Joi.object<FormAdapterSubmissionMessageData>().keys({\n main: Joi.object(),\n repeaters: Joi.object(),\n payment: Joi.object()\n .keys({\n paymentId: Joi.string().required(),\n reference: Joi.string().required(),\n amount: Joi.number().required(),\n description: Joi.string().required(),\n createdAt: Joi.string().required()\n })\n .optional(),\n files: Joi.object().pattern(\n Joi.string(),\n Joi.array().items(\n Joi.object().keys({\n fileName: Joi.string().required(),\n fileId: Joi.string().required(),\n userDownloadLink: Joi.string().required()\n })\n )\n )\n })\n\nexport const formAdapterSubmissionMessageResultSchema =\n Joi.object<FormAdapterSubmissionMessageResult>().keys({\n files: Joi.object()\n .keys({\n main: Joi.string().required(),\n repeaters: Joi.object()\n })\n .required()\n })\n\nexport const formAdapterSubmissionMessagePayloadSchema =\n Joi.object<FormAdapterSubmissionMessagePayload>().keys({\n meta: formAdapterSubmissionMessageMetaSchema.required(),\n data: formAdapterSubmissionMessageDataSchema.required(),\n result: formAdapterSubmissionMessageResultSchema.required()\n })\n"],"mappings":"AAAA,SACEA,UAAU,EACVC,yBAAyB,EACzBC,QAAQ,EACRC,8BAA8B,EAC9BC,UAAU,EACVC,WAAW,QACN,oBAAoB;AAC3B,OAAOC,GAAG,MAAM,KAAK;AAErB,SAASC,kCAAkC;AAQ3C,OAAO,MAAMC,sCAAsC,GACjDF,GAAG,CAACG,MAAM,CAAmC,CAAC,CAACC,IAAI,CAAC;EAClDC,aAAa,EAAEL,GAAG,CAACM,MAAM,CAAC,CAAC,CAACC,KAAK,CAC/B,GAAGC,MAAM,CAACC,MAAM,CAACR,kCAAkC,CACrD,CAAC;EACDS,SAAS,EAAEV,GAAG,CAACW,IAAI,CAAC,CAAC,CAACC,QAAQ,CAAC,CAAC;EAChCC,eAAe,EAAEb,GAAG,CAACM,MAAM,CAAC,CAAC,CAACM,QAAQ,CAAC,CAAC;EACxCE,QAAQ,EAAEf,WAAW;EACrBgB,MAAM,EAAEnB,QAAQ;EAChBoB,QAAQ,EAAElB,UAAU;EACpBmB,MAAM,EAAEjB,GAAG,CAACM,MAAM,CAAC,CAAC,CACjBC,KAAK,CAAC,GAAGC,MAAM,CAACC,MAAM,CAACf,UAAU,CAAC,CAAC,CACnCkB,QAAQ,CAAC,CAAC;EACbM,SAAS,EAAElB,GAAG,CAACmB,OAAO,CAAC,CAAC,CAACP,QAAQ,CAAC,CAAC;EACnCQ,iBAAiB,EAAEvB,8BAA8B,CAACe,QAAQ,CAAC,CAAC;EAC5DS,eAAe,EAAE1B,yBAAyB,CAAC2B,QAAQ,CAAC,CAAC;EACrDC,QAAQ,EAAEvB,GAAG,CAACM,MAAM,CAAC,CAAC,CAACgB,QAAQ,CAAC,CAAC;EACjCE,MAAM,EAAExB,GAAG,CAACG,MAAM,CAAC,CAAC,CACjBsB,OAAO,CAAC,GAAG,EAAEzB,GAAG,CAAC0B,GAAG,CAAC,CAAC,CAAC,CACvBC,OAAO,CAAC,CAAC,CACTL,QAAQ,CAAC,CAAC,CACVM,WAAW,CAAC,mCAAmC;AACpD,CAAC,CAAC;AAEJ,OAAO,MAAMC,sCAAsC,GACjD7B,GAAG,CAACG,MAAM,CAAmC,CAAC,CAACC,IAAI,CAAC;EAClD0B,IAAI,EAAE9B,GAAG,CAACG,MAAM,CAAC,CAAC;EAClB4B,SAAS,EAAE/B,GAAG,CAACG,MAAM,CAAC,CAAC;EACvB6B,OAAO,EAAEhC,GAAG,CAACG,MAAM,CAAC,CAAC,CAClBC,IAAI,CAAC;IACJ6B,SAAS,EAAEjC,GAAG,CAACM,MAAM,CAAC,CAAC,CAACM,QAAQ,CAAC,CAAC;IAClCsB,SAAS,EAAElC,GAAG,CAACM,MAAM,CAAC,CAAC,CAACM,QAAQ,CAAC,CAAC;IAClCuB,MAAM,EAAEnC,GAAG,CAACoC,MAAM,CAAC,CAAC,CAACxB,QAAQ,CAAC,CAAC;IAC/BgB,WAAW,EAAE5B,GAAG,CAACM,MAAM,CAAC,CAAC,CAACM,QAAQ,CAAC,CAAC;IACpCyB,
|
|
1
|
+
{"version":3,"file":"schema.js","names":["FormStatus","formVersionMetadataSchema","idSchema","notificationEmailAddressSchema","slugSchema","titleSchema","Joi","FormAdapterSubmissionSchemaVersion","formAdapterSubmissionMessageMetaSchema","object","keys","schemaVersion","string","valid","Object","values","timestamp","date","required","referenceNumber","formName","formId","formSlug","status","isPreview","boolean","notificationEmail","versionMetadata","optional","language","custom","pattern","any","unknown","description","formAdapterSubmissionMessageDataSchema","main","repeaters","payment","paymentId","reference","amount","number","descriptionInEng","createdAt","files","array","items","fileName","fileId","userDownloadLink","formAdapterSubmissionMessageResultSchema","formAdapterSubmissionMessagePayloadSchema","meta","data","result"],"sources":["../../../../../src/server/plugins/engine/types/schema.ts"],"sourcesContent":["import {\n FormStatus,\n formVersionMetadataSchema,\n idSchema,\n notificationEmailAddressSchema,\n slugSchema,\n titleSchema\n} from '@defra/forms-model'\nimport Joi from 'joi'\n\nimport { FormAdapterSubmissionSchemaVersion } from '~/src/server/plugins/engine/types/enums.js'\nimport {\n type FormAdapterSubmissionMessageData,\n type FormAdapterSubmissionMessageMeta,\n type FormAdapterSubmissionMessagePayload,\n type FormAdapterSubmissionMessageResult\n} from '~/src/server/plugins/engine/types.js'\n\nexport const formAdapterSubmissionMessageMetaSchema =\n Joi.object<FormAdapterSubmissionMessageMeta>().keys({\n schemaVersion: Joi.string().valid(\n ...Object.values(FormAdapterSubmissionSchemaVersion)\n ),\n timestamp: Joi.date().required(),\n referenceNumber: Joi.string().required(),\n formName: titleSchema,\n formId: idSchema,\n formSlug: slugSchema,\n status: Joi.string()\n .valid(...Object.values(FormStatus))\n .required(),\n isPreview: Joi.boolean().required(),\n notificationEmail: notificationEmailAddressSchema.required(),\n versionMetadata: formVersionMetadataSchema.optional(),\n language: Joi.string().optional(),\n custom: Joi.object()\n .pattern(/^/, Joi.any())\n .unknown()\n .optional()\n .description('Custom properties for the message')\n })\n\nexport const formAdapterSubmissionMessageDataSchema =\n Joi.object<FormAdapterSubmissionMessageData>().keys({\n main: Joi.object(),\n repeaters: Joi.object(),\n payment: Joi.object()\n .keys({\n paymentId: Joi.string().required(),\n reference: Joi.string().required(),\n amount: Joi.number().required(),\n description: Joi.string().required(),\n descriptionInEng: Joi.string().optional(),\n createdAt: Joi.string().required()\n })\n .optional(),\n files: Joi.object().pattern(\n Joi.string(),\n Joi.array().items(\n Joi.object().keys({\n fileName: Joi.string().required(),\n fileId: Joi.string().required(),\n userDownloadLink: Joi.string().required()\n })\n )\n )\n })\n\nexport const formAdapterSubmissionMessageResultSchema =\n Joi.object<FormAdapterSubmissionMessageResult>().keys({\n files: Joi.object()\n .keys({\n main: Joi.string().required(),\n repeaters: Joi.object()\n })\n .required()\n })\n\nexport const formAdapterSubmissionMessagePayloadSchema =\n Joi.object<FormAdapterSubmissionMessagePayload>().keys({\n meta: formAdapterSubmissionMessageMetaSchema.required(),\n data: formAdapterSubmissionMessageDataSchema.required(),\n result: formAdapterSubmissionMessageResultSchema.required()\n })\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":["FileStatus","UploadStatus"],"sources":["../../../../src/server/plugins/engine/types.ts"],"sourcesContent":["import {\n type ComponentDef,\n type Event,\n type FormVersionMetadata,\n type Item,\n type List,\n type Page,\n type PaymentFieldComponent,\n type UkAddressFieldComponent\n} from '@defra/forms-model'\nimport {\n type PluginProperties,\n type Request,\n type RequestQuery,\n type ResponseObject\n} from '@hapi/hapi'\nimport { type Yar } from '@hapi/yar'\nimport { type JoiExpression, type ValidationErrorItem } from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type UkAddressState } from '~/src/server/plugins/engine/components/UkAddressField.js'\nimport { type Component } from '~/src/server/plugins/engine/components/helpers/components.js'\nimport {\n type FileUploadField,\n type PaymentField\n} from '~/src/server/plugins/engine/components/index.js'\nimport {\n type BackLink,\n type ComponentText,\n type ComponentViewModel,\n type DatePartsState,\n type EastingNorthingState,\n type LatLongState,\n type MonthYearState\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItemField } from '~/src/server/plugins/engine/models/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'\nimport { type QuestionPageController } from '~/src/server/plugins/engine/pageControllers/index.js'\nimport {\n type FileStatus,\n type FormAdapterSubmissionSchemaVersion,\n type UploadStatus\n} from '~/src/server/plugins/engine/types/enums.js'\nimport { type ViewContext } from '~/src/server/plugins/nunjucks/types.js'\nimport {\n type FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormResponseToolkit,\n type FormStatus\n} from '~/src/server/routes/types.js'\nimport { type CacheService } from '~/src/server/services/cacheService.js'\nimport { type RequestOptions } from '~/src/server/services/httpService.js'\nimport { type Services } from '~/src/server/types.js'\n\nexport type AnyFormRequest = FormRequest | FormRequestPayload\nexport type AnyRequest = Request | AnyFormRequest\n\nexport interface CacheRequest {\n yar: { id: string | undefined }\n params: { slug?: string; state?: string }\n}\n\n/**\n * Form submission state stores the following in Redis:\n * Props containing user's submitted values as `{ [inputId]: value }` or as `{ [sectionName]: { [inputName]: value } }`\n * a) . e.g:\n * ```ts\n * {\n * _C9PRHmsgt: 'Ben',\n * WfLk9McjzX: 'Music',\n * IK7jkUFCBL: 'Royal Academy of Music'\n * }\n * ```\n *\n * b)\n * ```ts\n * {\n * checkBeforeYouStart: { ukPassport: true },\n * applicantDetails: {\n * numberOfApplicants: 1,\n * phoneNumber: '77777777',\n * emailAddress: 'aaa@aaa.com'\n * },\n * applicantOneDetails: {\n * firstName: 'a',\n * middleName: 'a',\n * lastName: 'a',\n * address: { addressLine1: 'a', addressLine2: 'a', town: 'a', postcode: 'a' }\n * }\n * }\n * ```\n */\n\n/**\n * Form submission state\n */\nexport type FormSubmissionState = {\n upload?: Record<string, TempFileState>\n} & FormState\n\nexport interface FormSubmissionError extends Pick<\n ValidationErrorItem,\n 'context' | 'path'\n> {\n href: string // e.g: '#dateField__day'\n name: string // e.g: 'dateField__day'\n text: string // e.g: 'Date field must be a real date'\n}\n\nexport interface FormConfirmationState {\n confirmed?: true\n formId?: string\n referenceNumber?: string\n}\n\nexport interface FormPayloadParams {\n action?: FormAction\n confirm?: true\n crumb?: string\n itemId?: string\n}\n\n/**\n * Form POST for question pages\n * (after Joi has converted value types)\n */\nexport type FormPayload = FormPayloadParams & Partial<Record<string, FormValue>>\n\nexport type FormValue =\n | Item['value']\n | Item['value'][]\n | UploadState\n | RepeatListState\n | GeospatialState\n | undefined\n\nexport type FormState = Partial<Record<string, FormStateValue>>\nexport type FormStateValue = Exclude<FormValue, undefined> | null\n\nexport interface FormValidationResult<\n ValueType extends FormPayload | FormSubmissionState\n> {\n value: ValueType\n errors: FormSubmissionError[] | undefined\n}\n\nexport interface FormContext {\n /**\n * Evaluation form state only (filtered by visited paths),\n * with values formatted for condition evaluation using\n * {@link FormComponent.getContextValueFromState}\n */\n evaluationState: FormState\n\n /**\n * Relevant form state only (filtered by visited paths)\n */\n relevantState: FormState\n\n /**\n * Relevant pages only (filtered by visited paths)\n */\n relevantPages: PageControllerClass[]\n\n /**\n * Form submission payload (single page)\n */\n payload: FormPayload\n\n /**\n * Form submission state (entire form)\n */\n state: FormSubmissionState\n\n /**\n * Validation errors (entire form)\n */\n errors?: FormSubmissionError[]\n\n /**\n * Visited paths evaluated from form state\n */\n paths: string[]\n\n /**\n * Preview URL direct access is allowed\n */\n isForceAccess: boolean\n\n /**\n * Miscellaneous extra data from event responses\n */\n data: object\n\n pageDefMap: Map<string, Page>\n listDefMap: Map<string, List>\n componentDefMap: Map<string, ComponentDef>\n pageMap: Map<string, PageControllerClass>\n componentMap: Map<string, Component>\n referenceNumber: string\n languages: { name: string; code: string }[]\n translator: Translator | undefined\n}\n\nexport type FormContextRequest = (\n | {\n method: 'get'\n payload?: undefined\n }\n | {\n method: 'post'\n payload: FormPayload\n }\n | {\n method: FormRequest['method']\n payload?: object | undefined\n }\n) &\n Pick<\n FormRequest,\n 'app' | 'method' | 'params' | 'path' | 'query' | 'url' | 'server'\n >\n\nexport interface UploadInitiateResponse {\n uploadId: string\n uploadUrl: string\n statusUrl: string\n}\n\nexport {\n FileStatus,\n UploadStatus\n} from '~/src/server/plugins/engine/types/enums.js'\n\nexport type UploadState = FileState[]\n\nexport type FileUpload = {\n fileId: string\n filename: string\n contentLength: number\n} & (\n | {\n fileStatus: FileStatus.complete | FileStatus.rejected | FileStatus.pending\n errorMessage?: string\n }\n | {\n fileStatus: FileStatus.complete\n errorMessage?: undefined\n }\n)\n\nexport interface FileUploadMetadata {\n retrievalKey: string\n}\n\nexport type UploadStatusResponse =\n | {\n uploadStatus: UploadStatus.initiated\n metadata: FileUploadMetadata\n form: { file?: undefined }\n }\n | {\n uploadStatus: UploadStatus.pending | UploadStatus.ready\n metadata: FileUploadMetadata\n form: { file: FileUpload }\n numberOfRejectedFiles?: number\n }\n | {\n uploadStatus: UploadStatus.ready\n metadata: FileUploadMetadata\n form: { file: FileUpload }\n numberOfRejectedFiles: 0\n }\n\nexport type UploadStatusFileResponse = Exclude<\n UploadStatusResponse,\n { uploadStatus: UploadStatus.initiated }\n>\n\nexport interface FileState {\n uploadId: string\n status: UploadStatusFileResponse\n}\n\nexport interface TempFileState {\n upload?: UploadInitiateResponse\n files: UploadState\n}\n\nexport interface RepeatItemState extends FormPayload {\n itemId: string\n}\n\nexport type RepeatListState = RepeatItemState[]\n\n/**\n * A longitude/latitude coordinate pair in WGS84 format\n * Format: [longitude, latitude]\n */\nexport type Coordinates = [longitude: number, latitude: number]\n\n/**\n * GeoJSON Point geometry\n */\nexport interface PointGeometry {\n type: 'Point'\n coordinates: Coordinates\n}\n\n/**\n * GeoJSON LineString geometry\n */\nexport interface LineStringGeometry {\n type: 'LineString'\n coordinates: Coordinates[]\n}\n\n/**\n * GeoJSON Polygon geometry\n */\nexport interface PolygonGeometry {\n type: 'Polygon'\n coordinates: Coordinates[][]\n}\n\n/**\n * Supported geometry types\n */\nexport type Geometry = PointGeometry | LineStringGeometry | PolygonGeometry\n\n/**\n * Feature metadata\n */\nexport interface FeatureProperties {\n /**\n * Human-readable description of the feature\n */\n description: string\n /**\n * The OS grid reference of the first coordinate of the feature\n */\n coordinateGridReference?: string\n /**\n * The OS grid reference of the centroid of the feature\n */\n centroidGridReference?: string\n}\n\n/**\n * A single GeoJSON Feature\n */\nexport interface Feature {\n id: string\n type: 'Feature'\n properties: FeatureProperties\n geometry: Geometry\n}\n\n/**\n * A GeoJSON FeatureCollection\n */\nexport type FeatureCollection = Feature[]\n\nexport type GeospatialState = FeatureCollection\n\nexport interface CheckAnswers {\n title?: ComponentText\n summaryList: SummaryList\n}\n\nexport interface SummaryList {\n classes?: string\n rows: SummaryListRow[]\n}\n\nexport interface SummaryListRow {\n key: ComponentText\n value: ComponentText\n actions?: { items: SummaryListAction[] }\n}\n\nexport type SummaryListAction = ComponentText & {\n href: string\n visuallyHiddenText: string\n}\n\nexport interface PageViewModelBase extends Partial<ViewContext> {\n page: PageController\n name?: string\n pageTitle: string\n sectionTitle?: string\n showTitle: boolean\n isStartPage: boolean\n backLink?: BackLink\n feedbackLink?: string\n serviceUrl: string\n phaseTag?: string\n t?: (key: string, opts?: Record<string, unknown>) => string\n}\n\nexport interface ItemDeletePageViewModel extends PageViewModelBase {\n context: FormContext\n itemTitle: string\n confirmation?: ComponentText\n buttonConfirm: ComponentText\n buttonCancel: ComponentText\n}\n\nexport interface FormPageViewModel extends PageViewModelBase {\n components: ComponentViewModel[]\n context: FormContext\n errors?: FormSubmissionError[]\n hasMissingNotificationEmail?: boolean\n allowSaveAndExit: boolean\n showSubmitButton?: boolean\n showPaymentExpiredNotification?: boolean\n}\n\nexport interface RepeaterSummaryPageViewModel extends PageViewModelBase {\n context: FormContext\n errors?: FormSubmissionError[]\n checkAnswers: CheckAnswers[]\n repeatTitle: string\n allowSaveAndExit: boolean\n}\n\nexport interface FeaturedFormPageViewModel extends FormPageViewModel {\n formAction?: string\n formComponent: ComponentViewModel\n componentsBefore: ComponentViewModel[]\n uploadId: string | undefined\n proxyUrl: string | null\n}\n\nexport type PageViewModel =\n | PageViewModelBase\n | ItemDeletePageViewModel\n | FormPageViewModel\n | RepeaterSummaryPageViewModel\n | FeaturedFormPageViewModel\n\nexport type GlobalFunction = (value: unknown) => unknown\nexport type FilterFunction = (value: unknown) => unknown\nexport interface ErrorMessageTemplate {\n type: string\n template: JoiExpression\n}\n\nexport interface ErrorMessageTemplateList {\n baseErrors: ErrorMessageTemplate[]\n advancedSettingsErrors: ErrorMessageTemplate[]\n}\n\nexport type PreparePageEventRequestOptions = (\n options: RequestOptions,\n event: Event,\n page: PageControllerClass,\n context: FormContext\n) => void\n\nexport type OnRequestCallback = (\n request: AnyFormRequest,\n h: FormResponseToolkit,\n context: FormContext\n) =>\n | ResponseObject\n | FormResponseToolkit['continue']\n | Promise<ResponseObject | FormResponseToolkit['continue']>\n\nexport type SaveAndExitHandler = (\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n) => ResponseObject\n\nexport type GetLanguageHandler = (query?: RequestQuery, yar?: Yar) => string\n\nexport interface ExternalArgs {\n component: ComponentDef\n controller: QuestionPageController\n sourceUrl: string\n actionArgs?: Record<string, string>\n isLive: boolean\n isPreview: boolean\n}\n\nexport interface PostcodeLookupExternalArgs extends ExternalArgs {\n component: UkAddressFieldComponent\n actionArgs: { step: string }\n}\n\nexport interface PaymentExternalArgs extends ExternalArgs {\n component: PaymentFieldComponent\n}\n\nexport interface ExternalStateAppendage {\n component: string\n data: FormStateValue | FormState\n}\n\nexport interface PluginOptions {\n model?: FormModel\n services?: Services\n controllers?: Record<string, typeof PageController>\n cache?: CacheService | string\n globals?: Record<string, GlobalFunction>\n filters?: Record<string, FilterFunction>\n saveAndExit?: SaveAndExitHandler\n pluginPath?: string\n nunjucks: {\n baseLayoutPath: string\n paths: string[]\n }\n viewContext: PluginProperties['forms-engine-plugin']['viewContext']\n preparePageEventRequestOptions?: PreparePageEventRequestOptions\n onRequest?: OnRequestCallback\n getLanguage?: GetLanguageHandler\n baseUrl: string // base URL of the application, protocol and hostname e.g. \"https://myapp.com\"\n ordnanceSurveyApiKey?: string\n ordnanceSurveyApiSecret?: string\n}\n\nexport interface FormAdapterSubmissionMessageMeta {\n schemaVersion: FormAdapterSubmissionSchemaVersion\n timestamp: Date\n referenceNumber: string\n formName: string\n formId: string\n formSlug: string\n status: FormStatus\n isPreview: boolean\n notificationEmail: string\n versionMetadata?: FormVersionMetadata\n language?: string\n custom?: Record<string, unknown>\n}\n\nexport type FormAdapterSubmissionMessageMetaSerialised = Omit<\n FormAdapterSubmissionMessageMeta,\n 'schemaVersion' | 'timestamp' | 'status'\n> & {\n schemaVersion: number\n status: string\n timestamp: string\n}\nexport interface FormAdapterFile {\n fileName: string\n fileId: string\n userDownloadLink: string\n}\n\nexport interface FormAdapterPayment {\n paymentId: string\n reference: string\n amount: number\n description: string\n createdAt: string\n}\n\nexport interface FormAdapterSubmissionMessageResult {\n files: {\n main: string\n repeaters: Record<string, string>\n }\n}\n\n/**\n * A detail item specifically for files\n */\nexport type FileUploadFieldDetailitem = Omit<DetailItemField, 'field'> & {\n field: FileUploadField\n}\n\n/**\n * A detail item specifically for payments\n */\nexport type PaymentFieldDetailItem = Omit<DetailItemField, 'field'> & {\n field: PaymentField\n}\nexport type RichFormValue =\n | FormValue\n | FormPayload\n | DatePartsState\n | MonthYearState\n | UkAddressState\n | EastingNorthingState\n | LatLongState\n | GeospatialState\n\nexport interface FormAdapterSubmissionMessageData {\n main: Record<string, RichFormValue | null>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<string, FormAdapterFile[]>\n payment?: FormAdapterPayment\n}\n\nexport interface FormAdapterSubmissionMessagePayload {\n meta: FormAdapterSubmissionMessageMeta\n data: FormAdapterSubmissionMessageData\n result: FormAdapterSubmissionMessageResult\n}\n\nexport interface FormAdapterSubmissionMessage extends FormAdapterSubmissionMessagePayload {\n messageId: string\n recordCreatedAt: Date\n}\n\nexport interface FormAdapterSubmissionService {\n handleFormSubmission: (\n submissionMessage: FormAdapterSubmissionMessage\n ) => unknown\n}\n"],"mappings":"AAkEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AA2BA;AACA;AACA;AACA;;AAwGA,SACEA,UAAU,EACVC,YAAY;;AAgEd;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAGA;AACA;AACA;;AAgBA;AACA;AACA;;AAQA;AACA;AACA;;AA8MA;AACA;AACA;;AAKA;AACA;AACA","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"types.js","names":["FileStatus","UploadStatus"],"sources":["../../../../src/server/plugins/engine/types.ts"],"sourcesContent":["import {\n type ComponentDef,\n type Event,\n type FormVersionMetadata,\n type Item,\n type List,\n type Page,\n type PaymentFieldComponent,\n type UkAddressFieldComponent\n} from '@defra/forms-model'\nimport {\n type PluginProperties,\n type Request,\n type RequestQuery,\n type ResponseObject\n} from '@hapi/hapi'\nimport { type Yar } from '@hapi/yar'\nimport { type JoiExpression, type ValidationErrorItem } from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type UkAddressState } from '~/src/server/plugins/engine/components/UkAddressField.js'\nimport { type Component } from '~/src/server/plugins/engine/components/helpers/components.js'\nimport {\n type FileUploadField,\n type PaymentField\n} from '~/src/server/plugins/engine/components/index.js'\nimport {\n type BackLink,\n type ComponentText,\n type ComponentViewModel,\n type DatePartsState,\n type EastingNorthingState,\n type LatLongState,\n type MonthYearState\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport { type DetailItemField } from '~/src/server/plugins/engine/models/types.js'\nimport { type PageController } from '~/src/server/plugins/engine/pageControllers/PageController.js'\nimport { type PageControllerClass } from '~/src/server/plugins/engine/pageControllers/helpers/pages.js'\nimport { type QuestionPageController } from '~/src/server/plugins/engine/pageControllers/index.js'\nimport {\n type FileStatus,\n type FormAdapterSubmissionSchemaVersion,\n type UploadStatus\n} from '~/src/server/plugins/engine/types/enums.js'\nimport { type ViewContext } from '~/src/server/plugins/nunjucks/types.js'\nimport {\n type FormAction,\n type FormRequest,\n type FormRequestPayload,\n type FormResponseToolkit,\n type FormStatus\n} from '~/src/server/routes/types.js'\nimport { type CacheService } from '~/src/server/services/cacheService.js'\nimport { type RequestOptions } from '~/src/server/services/httpService.js'\nimport { type Services } from '~/src/server/types.js'\n\nexport type AnyFormRequest = FormRequest | FormRequestPayload\nexport type AnyRequest = Request | AnyFormRequest\n\nexport interface CacheRequest {\n yar: { id: string | undefined }\n params: { slug?: string; state?: string }\n}\n\n/**\n * Form submission state stores the following in Redis:\n * Props containing user's submitted values as `{ [inputId]: value }` or as `{ [sectionName]: { [inputName]: value } }`\n * a) . e.g:\n * ```ts\n * {\n * _C9PRHmsgt: 'Ben',\n * WfLk9McjzX: 'Music',\n * IK7jkUFCBL: 'Royal Academy of Music'\n * }\n * ```\n *\n * b)\n * ```ts\n * {\n * checkBeforeYouStart: { ukPassport: true },\n * applicantDetails: {\n * numberOfApplicants: 1,\n * phoneNumber: '77777777',\n * emailAddress: 'aaa@aaa.com'\n * },\n * applicantOneDetails: {\n * firstName: 'a',\n * middleName: 'a',\n * lastName: 'a',\n * address: { addressLine1: 'a', addressLine2: 'a', town: 'a', postcode: 'a' }\n * }\n * }\n * ```\n */\n\n/**\n * Form submission state\n */\nexport type FormSubmissionState = {\n upload?: Record<string, TempFileState>\n} & FormState\n\nexport interface FormSubmissionError extends Pick<\n ValidationErrorItem,\n 'context' | 'path'\n> {\n href: string // e.g: '#dateField__day'\n name: string // e.g: 'dateField__day'\n text: string // e.g: 'Date field must be a real date'\n}\n\nexport interface FormConfirmationState {\n confirmed?: true\n formId?: string\n referenceNumber?: string\n}\n\nexport interface FormPayloadParams {\n action?: FormAction\n confirm?: true\n crumb?: string\n itemId?: string\n}\n\n/**\n * Form POST for question pages\n * (after Joi has converted value types)\n */\nexport type FormPayload = FormPayloadParams & Partial<Record<string, FormValue>>\n\nexport type FormValue =\n | Item['value']\n | Item['value'][]\n | UploadState\n | RepeatListState\n | GeospatialState\n | undefined\n\nexport type FormState = Partial<Record<string, FormStateValue>>\nexport type FormStateValue = Exclude<FormValue, undefined> | null\n\nexport interface FormValidationResult<\n ValueType extends FormPayload | FormSubmissionState\n> {\n value: ValueType\n errors: FormSubmissionError[] | undefined\n}\n\nexport interface FormContext {\n /**\n * Evaluation form state only (filtered by visited paths),\n * with values formatted for condition evaluation using\n * {@link FormComponent.getContextValueFromState}\n */\n evaluationState: FormState\n\n /**\n * Relevant form state only (filtered by visited paths)\n */\n relevantState: FormState\n\n /**\n * Relevant pages only (filtered by visited paths)\n */\n relevantPages: PageControllerClass[]\n\n /**\n * Form submission payload (single page)\n */\n payload: FormPayload\n\n /**\n * Form submission state (entire form)\n */\n state: FormSubmissionState\n\n /**\n * Validation errors (entire form)\n */\n errors?: FormSubmissionError[]\n\n /**\n * Visited paths evaluated from form state\n */\n paths: string[]\n\n /**\n * Preview URL direct access is allowed\n */\n isForceAccess: boolean\n\n /**\n * Miscellaneous extra data from event responses\n */\n data: object\n\n pageDefMap: Map<string, Page>\n listDefMap: Map<string, List>\n componentDefMap: Map<string, ComponentDef>\n pageMap: Map<string, PageControllerClass>\n componentMap: Map<string, Component>\n referenceNumber: string\n languages: { name: string; code: string }[]\n translator: Translator | undefined\n}\n\nexport type FormContextRequest = (\n | {\n method: 'get'\n payload?: undefined\n }\n | {\n method: 'post'\n payload: FormPayload\n }\n | {\n method: FormRequest['method']\n payload?: object | undefined\n }\n) &\n Pick<\n FormRequest,\n 'app' | 'method' | 'params' | 'path' | 'query' | 'url' | 'server'\n >\n\nexport interface UploadInitiateResponse {\n uploadId: string\n uploadUrl: string\n statusUrl: string\n}\n\nexport {\n FileStatus,\n UploadStatus\n} from '~/src/server/plugins/engine/types/enums.js'\n\nexport type UploadState = FileState[]\n\nexport type FileUpload = {\n fileId: string\n filename: string\n contentLength: number\n} & (\n | {\n fileStatus: FileStatus.complete | FileStatus.rejected | FileStatus.pending\n errorMessage?: string\n }\n | {\n fileStatus: FileStatus.complete\n errorMessage?: undefined\n }\n)\n\nexport interface FileUploadMetadata {\n retrievalKey: string\n}\n\nexport type UploadStatusResponse =\n | {\n uploadStatus: UploadStatus.initiated\n metadata: FileUploadMetadata\n form: { file?: undefined }\n }\n | {\n uploadStatus: UploadStatus.pending | UploadStatus.ready\n metadata: FileUploadMetadata\n form: { file: FileUpload }\n numberOfRejectedFiles?: number\n }\n | {\n uploadStatus: UploadStatus.ready\n metadata: FileUploadMetadata\n form: { file: FileUpload }\n numberOfRejectedFiles: 0\n }\n\nexport type UploadStatusFileResponse = Exclude<\n UploadStatusResponse,\n { uploadStatus: UploadStatus.initiated }\n>\n\nexport interface FileState {\n uploadId: string\n status: UploadStatusFileResponse\n}\n\nexport interface TempFileState {\n upload?: UploadInitiateResponse\n files: UploadState\n}\n\nexport interface RepeatItemState extends FormPayload {\n itemId: string\n}\n\nexport type RepeatListState = RepeatItemState[]\n\n/**\n * A longitude/latitude coordinate pair in WGS84 format\n * Format: [longitude, latitude]\n */\nexport type Coordinates = [longitude: number, latitude: number]\n\n/**\n * GeoJSON Point geometry\n */\nexport interface PointGeometry {\n type: 'Point'\n coordinates: Coordinates\n}\n\n/**\n * GeoJSON LineString geometry\n */\nexport interface LineStringGeometry {\n type: 'LineString'\n coordinates: Coordinates[]\n}\n\n/**\n * GeoJSON Polygon geometry\n */\nexport interface PolygonGeometry {\n type: 'Polygon'\n coordinates: Coordinates[][]\n}\n\n/**\n * Supported geometry types\n */\nexport type Geometry = PointGeometry | LineStringGeometry | PolygonGeometry\n\n/**\n * Feature metadata\n */\nexport interface FeatureProperties {\n /**\n * Human-readable description of the feature\n */\n description: string\n /**\n * The OS grid reference of the first coordinate of the feature\n */\n coordinateGridReference?: string\n /**\n * The OS grid reference of the centroid of the feature\n */\n centroidGridReference?: string\n}\n\n/**\n * A single GeoJSON Feature\n */\nexport interface Feature {\n id: string\n type: 'Feature'\n properties: FeatureProperties\n geometry: Geometry\n}\n\n/**\n * A GeoJSON FeatureCollection\n */\nexport type FeatureCollection = Feature[]\n\nexport type GeospatialState = FeatureCollection\n\nexport interface CheckAnswers {\n title?: ComponentText\n summaryList: SummaryList\n}\n\nexport interface SummaryList {\n classes?: string\n rows: SummaryListRow[]\n}\n\nexport interface SummaryListRow {\n key: ComponentText\n value: ComponentText\n actions?: { items: SummaryListAction[] }\n}\n\nexport type SummaryListAction = ComponentText & {\n href: string\n visuallyHiddenText: string\n}\n\nexport interface PageViewModelBase extends Partial<ViewContext> {\n page: PageController\n name?: string\n pageTitle: string\n sectionTitle?: string\n showTitle: boolean\n isStartPage: boolean\n backLink?: BackLink\n feedbackLink?: string\n serviceUrl: string\n phaseTag?: string\n t?: (key: string, opts?: Record<string, unknown>) => string\n}\n\nexport interface ItemDeletePageViewModel extends PageViewModelBase {\n context: FormContext\n itemTitle: string\n confirmation?: ComponentText\n buttonConfirm: ComponentText\n buttonCancel: ComponentText\n}\n\nexport interface FormPageViewModel extends PageViewModelBase {\n components: ComponentViewModel[]\n context: FormContext\n errors?: FormSubmissionError[]\n hasMissingNotificationEmail?: boolean\n allowSaveAndExit: boolean\n showSubmitButton?: boolean\n showPaymentExpiredNotification?: boolean\n}\n\nexport interface RepeaterSummaryPageViewModel extends PageViewModelBase {\n context: FormContext\n errors?: FormSubmissionError[]\n checkAnswers: CheckAnswers[]\n repeatTitle: string\n allowSaveAndExit: boolean\n}\n\nexport interface FeaturedFormPageViewModel extends FormPageViewModel {\n formAction?: string\n formComponent: ComponentViewModel\n componentsBefore: ComponentViewModel[]\n uploadId: string | undefined\n proxyUrl: string | null\n}\n\nexport type PageViewModel =\n | PageViewModelBase\n | ItemDeletePageViewModel\n | FormPageViewModel\n | RepeaterSummaryPageViewModel\n | FeaturedFormPageViewModel\n\nexport type GlobalFunction = (value: unknown) => unknown\nexport type FilterFunction = (value: unknown) => unknown\nexport interface ErrorMessageTemplate {\n type: string\n template: JoiExpression\n}\n\nexport interface ErrorMessageTemplateList {\n baseErrors: ErrorMessageTemplate[]\n advancedSettingsErrors: ErrorMessageTemplate[]\n}\n\nexport type PreparePageEventRequestOptions = (\n options: RequestOptions,\n event: Event,\n page: PageControllerClass,\n context: FormContext\n) => void\n\nexport type OnRequestCallback = (\n request: AnyFormRequest,\n h: FormResponseToolkit,\n context: FormContext\n) =>\n | ResponseObject\n | FormResponseToolkit['continue']\n | Promise<ResponseObject | FormResponseToolkit['continue']>\n\nexport type SaveAndExitHandler = (\n request: FormRequestPayload,\n h: FormResponseToolkit,\n context: FormContext\n) => ResponseObject\n\nexport type GetLanguageHandler = (query?: RequestQuery, yar?: Yar) => string\n\nexport interface ExternalArgs {\n component: ComponentDef\n controller: QuestionPageController\n sourceUrl: string\n actionArgs?: Record<string, string>\n isLive: boolean\n isPreview: boolean\n}\n\nexport interface PostcodeLookupExternalArgs extends ExternalArgs {\n component: UkAddressFieldComponent\n actionArgs: { step: string }\n}\n\nexport interface PaymentExternalArgs extends ExternalArgs {\n component: PaymentFieldComponent\n}\n\nexport interface ExternalStateAppendage {\n component: string\n data: FormStateValue | FormState\n}\n\nexport interface PluginOptions {\n model?: FormModel\n services?: Services\n controllers?: Record<string, typeof PageController>\n cache?: CacheService | string\n globals?: Record<string, GlobalFunction>\n filters?: Record<string, FilterFunction>\n saveAndExit?: SaveAndExitHandler\n pluginPath?: string\n nunjucks: {\n baseLayoutPath: string\n paths: string[]\n }\n viewContext: PluginProperties['forms-engine-plugin']['viewContext']\n preparePageEventRequestOptions?: PreparePageEventRequestOptions\n onRequest?: OnRequestCallback\n getLanguage?: GetLanguageHandler\n baseUrl: string // base URL of the application, protocol and hostname e.g. \"https://myapp.com\"\n ordnanceSurveyApiKey?: string\n ordnanceSurveyApiSecret?: string\n}\n\nexport interface FormAdapterSubmissionMessageMeta {\n schemaVersion: FormAdapterSubmissionSchemaVersion\n timestamp: Date\n referenceNumber: string\n formName: string\n formId: string\n formSlug: string\n status: FormStatus\n isPreview: boolean\n notificationEmail: string\n versionMetadata?: FormVersionMetadata\n language?: string\n custom?: Record<string, unknown>\n}\n\nexport type FormAdapterSubmissionMessageMetaSerialised = Omit<\n FormAdapterSubmissionMessageMeta,\n 'schemaVersion' | 'timestamp' | 'status'\n> & {\n schemaVersion: number\n status: string\n timestamp: string\n}\nexport interface FormAdapterFile {\n fileName: string\n fileId: string\n userDownloadLink: string\n}\n\nexport interface FormAdapterPayment {\n paymentId: string\n reference: string\n amount: number\n description: string\n descriptionInEng?: string\n createdAt: string\n}\n\nexport interface FormAdapterSubmissionMessageResult {\n files: {\n main: string\n repeaters: Record<string, string>\n }\n}\n\n/**\n * A detail item specifically for files\n */\nexport type FileUploadFieldDetailitem = Omit<DetailItemField, 'field'> & {\n field: FileUploadField\n}\n\n/**\n * A detail item specifically for payments\n */\nexport type PaymentFieldDetailItem = Omit<DetailItemField, 'field'> & {\n field: PaymentField\n}\nexport type RichFormValue =\n | FormValue\n | FormPayload\n | DatePartsState\n | MonthYearState\n | UkAddressState\n | EastingNorthingState\n | LatLongState\n | GeospatialState\n\nexport interface FormAdapterSubmissionMessageData {\n main: Record<string, RichFormValue | null>\n repeaters: Record<string, Record<string, RichFormValue>[]>\n files: Record<string, FormAdapterFile[]>\n payment?: FormAdapterPayment\n}\n\nexport interface FormAdapterSubmissionMessagePayload {\n meta: FormAdapterSubmissionMessageMeta\n data: FormAdapterSubmissionMessageData\n result: FormAdapterSubmissionMessageResult\n}\n\nexport interface FormAdapterSubmissionMessage extends FormAdapterSubmissionMessagePayload {\n messageId: string\n recordCreatedAt: Date\n}\n\nexport interface FormAdapterSubmissionService {\n handleFormSubmission: (\n submissionMessage: FormAdapterSubmissionMessage\n ) => unknown\n}\n"],"mappings":"AAkEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AA2BA;AACA;AACA;AACA;;AAwGA,SACEA,UAAU,EACVC,YAAY;;AAgEd;AACA;AACA;AACA;;AAGA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAMA;AACA;AACA;;AAGA;AACA;AACA;;AAgBA;AACA;AACA;;AAQA;AACA;AACA;;AA+MA;AACA;AACA;;AAKA;AACA;AACA","ignoreList":[]}
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
classes: "govuk-button--secondary govuk-!-margin-right-1 govuk-!-margin-bottom-0"
|
|
63
63
|
}) }}
|
|
64
|
-
<p class="govuk-body govuk-!-margin-bottom-0">or <button class="govuk-link govuk-button--link govuk-!-margin-right-1 govuk-!-margin-bottom-0" name="action" value="external-{{component.model.name}}--step:manual">{{ t('components.addressField.enterManually') }}</button></p>
|
|
64
|
+
<p class="govuk-body govuk-!-margin-bottom-0">{{ t('common.or')}} <button class="govuk-link govuk-button--link govuk-!-margin-right-1 govuk-!-margin-bottom-0" name="action" value="external-{{component.model.name}}--step:manual">{{ t('components.addressField.enterManually') }}</button></p>
|
|
65
65
|
</div>
|
|
66
66
|
{# Include a line break if this is the last component #}
|
|
67
67
|
{% if components[components.length - 1] == component %}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nunjucks filter to add/replace a parameter on a query string of a url.
|
|
3
|
+
* Currently only used in forms-runner.
|
|
4
|
+
* @param {string} urlPath - existing relative url with query string
|
|
5
|
+
* @param {string} paramName - name of parameter
|
|
6
|
+
* @param {string} paramValue - value of parameter
|
|
7
|
+
* @returns {string}
|
|
8
|
+
*/
|
|
9
|
+
export function applyUrlParam(urlPath: string, paramName: string, paramValue: string): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nunjucks filter to add/replace a parameter on a query string of a url.
|
|
3
|
+
* Currently only used in forms-runner.
|
|
4
|
+
* @param {string} urlPath - existing relative url with query string
|
|
5
|
+
* @param {string} paramName - name of parameter
|
|
6
|
+
* @param {string} paramValue - value of parameter
|
|
7
|
+
* @returns {string}
|
|
8
|
+
*/
|
|
9
|
+
export function applyUrlParam(urlPath, paramName, paramValue) {
|
|
10
|
+
if (typeof urlPath !== 'string') {
|
|
11
|
+
return '';
|
|
12
|
+
}
|
|
13
|
+
const url = new URL(urlPath, 'https://dummy');
|
|
14
|
+
url.searchParams.set(paramName, paramValue);
|
|
15
|
+
return url.pathname + url.search;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=applyUrlParam.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyUrlParam.js","names":["applyUrlParam","urlPath","paramName","paramValue","url","URL","searchParams","set","pathname","search"],"sources":["../../../../../src/server/plugins/nunjucks/filters/applyUrlParam.js"],"sourcesContent":["/**\n * Nunjucks filter to add/replace a parameter on a query string of a url.\n * Currently only used in forms-runner.\n * @param {string} urlPath - existing relative url with query string\n * @param {string} paramName - name of parameter\n * @param {string} paramValue - value of parameter\n * @returns {string}\n */\nexport function applyUrlParam(urlPath, paramName, paramValue) {\n if (typeof urlPath !== 'string') {\n return ''\n }\n const url = new URL(urlPath, 'https://dummy')\n url.searchParams.set(paramName, paramValue)\n\n return url.pathname + url.search\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,aAAaA,CAACC,OAAO,EAAEC,SAAS,EAAEC,UAAU,EAAE;EAC5D,IAAI,OAAOF,OAAO,KAAK,QAAQ,EAAE;IAC/B,OAAO,EAAE;EACX;EACA,MAAMG,GAAG,GAAG,IAAIC,GAAG,CAACJ,OAAO,EAAE,eAAe,CAAC;EAC7CG,GAAG,CAACE,YAAY,CAACC,GAAG,CAACL,SAAS,EAAEC,UAAU,CAAC;EAE3C,OAAOC,GAAG,CAACI,QAAQ,GAAGJ,GAAG,CAACK,MAAM;AAClC","ignoreList":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { applyUrlParam } from "./applyUrlParam.js";
|
|
2
|
+
describe('applyUrlParam', () => {
|
|
3
|
+
test('should return blank string if not a string input', () => {
|
|
4
|
+
// @ts-expect-error - wrong datatype for test
|
|
5
|
+
expect(applyUrlParam({}, 'name', 'val')).toBe('');
|
|
6
|
+
});
|
|
7
|
+
test('should add param', () => {
|
|
8
|
+
expect(applyUrlParam('/my-path/my-form', 'language', 'cy')).toBe('/my-path/my-form?language=cy');
|
|
9
|
+
});
|
|
10
|
+
test('should concat param', () => {
|
|
11
|
+
expect(applyUrlParam('/my-path/my-form?otherParam=123', 'language', 'en-GB')).toBe('/my-path/my-form?otherParam=123&language=en-GB');
|
|
12
|
+
});
|
|
13
|
+
test('should replace param', () => {
|
|
14
|
+
expect(applyUrlParam('/my-path/my-form?language=cy', 'language', 'en-GB')).toBe('/my-path/my-form?language=en-GB');
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=applyUrlParam.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applyUrlParam.test.js","names":["applyUrlParam","describe","test","expect","toBe"],"sources":["../../../../../src/server/plugins/nunjucks/filters/applyUrlParam.test.js"],"sourcesContent":["import { applyUrlParam } from '~/src/server/plugins/nunjucks/filters/applyUrlParam.js'\n\ndescribe('applyUrlParam', () => {\n test('should return blank string if not a string input', () => {\n // @ts-expect-error - wrong datatype for test\n expect(applyUrlParam({}, 'name', 'val')).toBe('')\n })\n\n test('should add param', () => {\n expect(applyUrlParam('/my-path/my-form', 'language', 'cy')).toBe(\n '/my-path/my-form?language=cy'\n )\n })\n\n test('should concat param', () => {\n expect(\n applyUrlParam('/my-path/my-form?otherParam=123', 'language', 'en-GB')\n ).toBe('/my-path/my-form?otherParam=123&language=en-GB')\n })\n\n test('should replace param', () => {\n expect(\n applyUrlParam('/my-path/my-form?language=cy', 'language', 'en-GB')\n ).toBe('/my-path/my-form?language=en-GB')\n })\n})\n"],"mappings":"AAAA,SAASA,aAAa;AAEtBC,QAAQ,CAAC,eAAe,EAAE,MAAM;EAC9BC,IAAI,CAAC,kDAAkD,EAAE,MAAM;IAC7D;IACAC,MAAM,CAACH,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAACI,IAAI,CAAC,EAAE,CAAC;EACnD,CAAC,CAAC;EAEFF,IAAI,CAAC,kBAAkB,EAAE,MAAM;IAC7BC,MAAM,CAACH,aAAa,CAAC,kBAAkB,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAACI,IAAI,CAC9D,8BACF,CAAC;EACH,CAAC,CAAC;EAEFF,IAAI,CAAC,qBAAqB,EAAE,MAAM;IAChCC,MAAM,CACJH,aAAa,CAAC,iCAAiC,EAAE,UAAU,EAAE,OAAO,CACtE,CAAC,CAACI,IAAI,CAAC,gDAAgD,CAAC;EAC1D,CAAC,CAAC;EAEFF,IAAI,CAAC,sBAAsB,EAAE,MAAM;IACjCC,MAAM,CACJH,aAAa,CAAC,8BAA8B,EAAE,UAAU,EAAE,OAAO,CACnE,CAAC,CAACI,IAAI,CAAC,iCAAiC,CAAC;EAC3C,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* @this {NunjucksContext}
|
|
4
4
|
* @param {string} name - The name of the component
|
|
5
5
|
*/
|
|
6
|
-
export function field(this: NunjucksContext, name: string): import("../../engine/components/TextField.js").TextField | import("../../engine/components/
|
|
6
|
+
export function field(this: NunjucksContext, name: string): import("../../engine/components/TextField.js").TextField | import("../../engine/components/SelectField.js").SelectField | import("../../engine/components/RadiosField.js").RadiosField | import("../../engine/components/YesNoField.js").YesNoField | import("../../engine/components/CheckboxesField.js").CheckboxesField | import("../../engine/components/DatePartsField.js").DatePartsField | import("../../engine/components/DeclarationField.js").DeclarationField | import("../../engine/components/EastingNorthingField.js").EastingNorthingField | import("../../engine/components/EmailAddressField.js").EmailAddressField | import("../../engine/components/LatLongField.js").LatLongField | import("../../engine/components/MonthYearField.js").MonthYearField | import("../../engine/components/MultilineTextField.js").MultilineTextField | import("../../engine/components/NationalGridFieldNumberField.js").NationalGridFieldNumberField | import("../../engine/components/NumberField.js").NumberField | import("../../engine/components/OsGridRefField.js").OsGridRefField | import("../../engine/components/TelephoneNumberField.js").TelephoneNumberField | import("../../engine/components/UkAddressField.js").UkAddressField | import("../../engine/components/FileUploadField.js").FileUploadField | import("../../engine/components/HiddenField.js").HiddenField | import("../../engine/components/PaymentField.js").PaymentField | import("../../engine/components/GeospatialField.js").GeospatialField | import("../../engine/components/Details.js").Details | import("../../engine/components/Html.js").Html | import("../../engine/components/InsetText.js").InsetText | import("../../engine/components/List.js").List | import("../../engine/components/Markdown.js").Markdown | import("../../engine/components/NotificationBanner.js").NotificationBanner | undefined;
|
|
7
7
|
import type { NunjucksContext } from '../../../../server/plugins/nunjucks/types.js';
|
|
@@ -6,3 +6,4 @@ export { href } from "../../../../server/plugins/nunjucks/filters/href.js";
|
|
|
6
6
|
export { field } from "../../../../server/plugins/nunjucks/filters/field.js";
|
|
7
7
|
export { page } from "../../../../server/plugins/nunjucks/filters/page.js";
|
|
8
8
|
export { merge } from "../../../../server/plugins/nunjucks/filters/merge.js";
|
|
9
|
+
export { applyUrlParam } from "../../../../server/plugins/nunjucks/filters/applyUrlParam.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["highlight","inspect","evaluate","answer","href","field","page","merge"],"sources":["../../../../../src/server/plugins/nunjucks/filters/index.js"],"sourcesContent":["export { highlight } from '~/src/server/plugins/nunjucks/filters/highlight.js'\nexport { inspect } from '~/src/server/plugins/nunjucks/filters/inspect.js'\nexport { evaluate } from '~/src/server/plugins/nunjucks/filters/evaluate.js'\nexport { answer } from '~/src/server/plugins/nunjucks/filters/answer.js'\nexport { href } from '~/src/server/plugins/nunjucks/filters/href.js'\nexport { field } from '~/src/server/plugins/nunjucks/filters/field.js'\nexport { page } from '~/src/server/plugins/nunjucks/filters/page.js'\nexport { merge } from '~/src/server/plugins/nunjucks/filters/merge.js'\n"],"mappings":"AAAA,SAASA,SAAS;AAClB,SAASC,OAAO;AAChB,SAASC,QAAQ;AACjB,SAASC,MAAM;AACf,SAASC,IAAI;AACb,SAASC,KAAK;AACd,SAASC,IAAI;AACb,SAASC,KAAK","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["highlight","inspect","evaluate","answer","href","field","page","merge","applyUrlParam"],"sources":["../../../../../src/server/plugins/nunjucks/filters/index.js"],"sourcesContent":["export { highlight } from '~/src/server/plugins/nunjucks/filters/highlight.js'\nexport { inspect } from '~/src/server/plugins/nunjucks/filters/inspect.js'\nexport { evaluate } from '~/src/server/plugins/nunjucks/filters/evaluate.js'\nexport { answer } from '~/src/server/plugins/nunjucks/filters/answer.js'\nexport { href } from '~/src/server/plugins/nunjucks/filters/href.js'\nexport { field } from '~/src/server/plugins/nunjucks/filters/field.js'\nexport { page } from '~/src/server/plugins/nunjucks/filters/page.js'\nexport { merge } from '~/src/server/plugins/nunjucks/filters/merge.js'\nexport { applyUrlParam } from '~/src/server/plugins/nunjucks/filters/applyUrlParam.js'\n"],"mappings":"AAAA,SAASA,SAAS;AAClB,SAASC,OAAO;AAChB,SAASC,QAAQ;AACjB,SAASC,MAAM;AACf,SAASC,IAAI;AACb,SAASC,KAAK;AACd,SAASC,IAAI;AACb,SAASC,KAAK;AACd,SAASC,aAAa","ignoreList":[]}
|
|
@@ -9,9 +9,19 @@ export function createPaymentService(isLivePayment: boolean, formId: string, for
|
|
|
9
9
|
/**
|
|
10
10
|
* Formats a payment date for display
|
|
11
11
|
* @param {string} isoString - ISO date string
|
|
12
|
+
* @param {string} language - the target language
|
|
12
13
|
* @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
|
|
13
14
|
*/
|
|
14
|
-
export function formatPaymentDate(isoString: string): string;
|
|
15
|
+
export function formatPaymentDate(isoString: string, language: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Formats a date for display in a specific language.
|
|
18
|
+
* To use additional languages, the appropriate module must be imported from 'date-fns/locale'
|
|
19
|
+
* @param { Date | string } date - the date
|
|
20
|
+
* @param {string} formatMask - the format mask
|
|
21
|
+
* @param {string} language - the target language
|
|
22
|
+
* @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
|
|
23
|
+
*/
|
|
24
|
+
export function formatDateForLanguage(date: Date | string, formatMask: string, language: string): string;
|
|
15
25
|
/**
|
|
16
26
|
* Formats a currency amount with thousand separators and two decimal places
|
|
17
27
|
* @param {number} amount - amount in pounds
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { format } from 'date-fns';
|
|
2
|
+
import { toLanguageLocale } from "../engine/helpers.js";
|
|
2
3
|
import { PaymentService } from "./service.js";
|
|
3
4
|
export const DEFAULT_PAYMENT_HELP_URL = 'https://www.gov.uk/government/organisations/department-for-environment-food-rural-affairs';
|
|
4
5
|
const PAYMENT_TEST_API_KEY = 'payment-test-api-key';
|
|
@@ -20,10 +21,25 @@ export async function createPaymentService(isLivePayment, formId, formsService)
|
|
|
20
21
|
/**
|
|
21
22
|
* Formats a payment date for display
|
|
22
23
|
* @param {string} isoString - ISO date string
|
|
24
|
+
* @param {string} language - the target language
|
|
23
25
|
* @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
|
|
24
26
|
*/
|
|
25
|
-
export function formatPaymentDate(isoString) {
|
|
26
|
-
return
|
|
27
|
+
export function formatPaymentDate(isoString, language) {
|
|
28
|
+
return formatDateForLanguage(new Date(isoString), 'd MMMM yyyy h:mmaaa', language);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Formats a date for display in a specific language.
|
|
33
|
+
* To use additional languages, the appropriate module must be imported from 'date-fns/locale'
|
|
34
|
+
* @param { Date | string } date - the date
|
|
35
|
+
* @param {string} formatMask - the format mask
|
|
36
|
+
* @param {string} language - the target language
|
|
37
|
+
* @returns {string} Formatted date string (e.g., "26 January 2026 5:01pm")
|
|
38
|
+
*/
|
|
39
|
+
export function formatDateForLanguage(date, formatMask, language) {
|
|
40
|
+
return format(date, formatMask, {
|
|
41
|
+
locale: toLanguageLocale(language)
|
|
42
|
+
});
|
|
27
43
|
}
|
|
28
44
|
|
|
29
45
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.js","names":["format","PaymentService","DEFAULT_PAYMENT_HELP_URL","PAYMENT_TEST_API_KEY","PAYMENT_LIVE_API_KEY","createPaymentService","isLivePayment","formId","formsService","secretName","apiKey","getFormSecret","formatPaymentDate","isoString","Date","
|
|
1
|
+
{"version":3,"file":"helper.js","names":["format","toLanguageLocale","PaymentService","DEFAULT_PAYMENT_HELP_URL","PAYMENT_TEST_API_KEY","PAYMENT_LIVE_API_KEY","createPaymentService","isLivePayment","formId","formsService","secretName","apiKey","getFormSecret","formatPaymentDate","isoString","language","formatDateForLanguage","Date","date","formatMask","locale","formatCurrency","amount","currency","formatter","Intl","NumberFormat","style"],"sources":["../../../../src/server/plugins/payment/helper.js"],"sourcesContent":["import { format } from 'date-fns'\n\nimport { toLanguageLocale } from '~/src/server/plugins/engine/helpers.js'\nimport { PaymentService } from '~/src/server/plugins/payment/service.js'\n\nexport const DEFAULT_PAYMENT_HELP_URL =\n 'https://www.gov.uk/government/organisations/department-for-environment-food-rural-affairs'\n\nconst PAYMENT_TEST_API_KEY = 'payment-test-api-key'\nconst PAYMENT_LIVE_API_KEY = 'payment-live-api-key'\n\n/**\n * Creates a PaymentService instance with the appropriate API key\n * @param {boolean} isLivePayment - true if this is a live payment\n * @param {string} formId - id of the form\n * @param {FormsService} formsService - service to handle form data operations\n * @returns {Promise<PaymentService>}\n */\nexport async function createPaymentService(\n isLivePayment,\n formId,\n formsService\n) {\n const secretName = isLivePayment ? PAYMENT_LIVE_API_KEY : PAYMENT_TEST_API_KEY\n const apiKey = await formsService.getFormSecret(formId, secretName)\n return new PaymentService(apiKey)\n}\n\n/**\n * Formats a payment date for display\n * @param {string} isoString - ISO date string\n * @param {string} language - the target language\n * @returns {string} Formatted date string (e.g., \"26 January 2026 5:01pm\")\n */\nexport function formatPaymentDate(isoString, language) {\n return formatDateForLanguage(\n new Date(isoString),\n 'd MMMM yyyy h:mmaaa',\n language\n )\n}\n\n/**\n * Formats a date for display in a specific language.\n * To use additional languages, the appropriate module must be imported from 'date-fns/locale'\n * @param { Date | string } date - the date\n * @param {string} formatMask - the format mask\n * @param {string} language - the target language\n * @returns {string} Formatted date string (e.g., \"26 January 2026 5:01pm\")\n */\nexport function formatDateForLanguage(date, formatMask, language) {\n return format(date, formatMask, {\n locale: toLanguageLocale(language)\n })\n}\n\n/**\n * Formats a currency amount with thousand separators and two decimal places\n * @param {number} amount - amount in pounds\n * @param {'en-GB'} [locale] - locale for formatting\n * @param {'GBP'} [currency] - currency code\n * @returns {string} Formatted amount (e.g., \"£1,234.56\")\n */\nexport function formatCurrency(amount, locale = 'en-GB', currency = 'GBP') {\n const formatter = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency\n })\n\n return formatter.format(amount)\n}\n\n/**\n * @import { FormsService } from '~/src/server/types.js'\n */\n"],"mappings":"AAAA,SAASA,MAAM,QAAQ,UAAU;AAEjC,SAASC,gBAAgB;AACzB,SAASC,cAAc;AAEvB,OAAO,MAAMC,wBAAwB,GACnC,2FAA2F;AAE7F,MAAMC,oBAAoB,GAAG,sBAAsB;AACnD,MAAMC,oBAAoB,GAAG,sBAAsB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,oBAAoBA,CACxCC,aAAa,EACbC,MAAM,EACNC,YAAY,EACZ;EACA,MAAMC,UAAU,GAAGH,aAAa,GAAGF,oBAAoB,GAAGD,oBAAoB;EAC9E,MAAMO,MAAM,GAAG,MAAMF,YAAY,CAACG,aAAa,CAACJ,MAAM,EAAEE,UAAU,CAAC;EACnE,OAAO,IAAIR,cAAc,CAACS,MAAM,CAAC;AACnC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASE,iBAAiBA,CAACC,SAAS,EAAEC,QAAQ,EAAE;EACrD,OAAOC,qBAAqB,CAC1B,IAAIC,IAAI,CAACH,SAAS,CAAC,EACnB,qBAAqB,EACrBC,QACF,CAAC;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CAACE,IAAI,EAAEC,UAAU,EAAEJ,QAAQ,EAAE;EAChE,OAAOf,MAAM,CAACkB,IAAI,EAAEC,UAAU,EAAE;IAC9BC,MAAM,EAAEnB,gBAAgB,CAACc,QAAQ;EACnC,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASM,cAAcA,CAACC,MAAM,EAAEF,MAAM,GAAG,OAAO,EAAEG,QAAQ,GAAG,KAAK,EAAE;EACzE,MAAMC,SAAS,GAAG,IAAIC,IAAI,CAACC,YAAY,CAACN,MAAM,EAAE;IAC9CO,KAAK,EAAE,UAAU;IACjBJ;EACF,CAAC,CAAC;EAEF,OAAOC,SAAS,CAACxB,MAAM,CAACsB,MAAM,CAAC;AACjC;;AAEA;AACA;AACA","ignoreList":[]}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { EN_GB } from "../../constants.js";
|
|
1
2
|
import { formatCurrency, formatPaymentDate } from "./helper.js";
|
|
2
3
|
describe('formatPaymentDate', () => {
|
|
3
4
|
it('should format ISO date string to en-GB format', () => {
|
|
4
|
-
const result = formatPaymentDate('2025-11-10T17:01:29.000Z');
|
|
5
|
+
const result = formatPaymentDate('2025-11-10T17:01:29.000Z', EN_GB);
|
|
5
6
|
expect(result).toBe('10 November 2025 5:01pm');
|
|
6
7
|
});
|
|
7
8
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helper.test.js","names":["formatCurrency","formatPaymentDate","describe","it","result","expect","toBe"],"sources":["../../../../src/server/plugins/payment/helper.test.js"],"sourcesContent":["import {\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\n\ndescribe('formatPaymentDate', () => {\n it('should format ISO date string to en-GB format', () => {\n const result = formatPaymentDate('2025-11-10T17:01:29.000Z')\n expect(result).toBe('10 November 2025 5:01pm')\n })\n})\n\ndescribe('formatCurrency', () => {\n it('should format whole number with currency symbol', () => {\n expect(formatCurrency(10)).toBe('£10.00')\n })\n\n it('should format decimal amount with currency symbol', () => {\n expect(formatCurrency(99.5)).toBe('£99.50')\n })\n\n it('should format large amounts with thousand separators', () => {\n expect(formatCurrency(1234.56)).toBe('£1,234.56')\n })\n\n it('should format very large amounts with thousand separators', () => {\n expect(formatCurrency(20000)).toBe('£20,000.00')\n })\n})\n"],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"helper.test.js","names":["EN_GB","formatCurrency","formatPaymentDate","describe","it","result","expect","toBe"],"sources":["../../../../src/server/plugins/payment/helper.test.js"],"sourcesContent":["import { EN_GB } from '~/src/server/constants.js'\nimport {\n formatCurrency,\n formatPaymentDate\n} from '~/src/server/plugins/payment/helper.js'\n\ndescribe('formatPaymentDate', () => {\n it('should format ISO date string to en-GB format', () => {\n const result = formatPaymentDate('2025-11-10T17:01:29.000Z', EN_GB)\n expect(result).toBe('10 November 2025 5:01pm')\n })\n})\n\ndescribe('formatCurrency', () => {\n it('should format whole number with currency symbol', () => {\n expect(formatCurrency(10)).toBe('£10.00')\n })\n\n it('should format decimal amount with currency symbol', () => {\n expect(formatCurrency(99.5)).toBe('£99.50')\n })\n\n it('should format large amounts with thousand separators', () => {\n expect(formatCurrency(1234.56)).toBe('£1,234.56')\n })\n\n it('should format very large amounts with thousand separators', () => {\n expect(formatCurrency(20000)).toBe('£20,000.00')\n })\n})\n"],"mappings":"AAAA,SAASA,KAAK;AACd,SACEC,cAAc,EACdC,iBAAiB;AAGnBC,QAAQ,CAAC,mBAAmB,EAAE,MAAM;EAClCC,EAAE,CAAC,+CAA+C,EAAE,MAAM;IACxD,MAAMC,MAAM,GAAGH,iBAAiB,CAAC,0BAA0B,EAAEF,KAAK,CAAC;IACnEM,MAAM,CAACD,MAAM,CAAC,CAACE,IAAI,CAAC,yBAAyB,CAAC;EAChD,CAAC,CAAC;AACJ,CAAC,CAAC;AAEFJ,QAAQ,CAAC,gBAAgB,EAAE,MAAM;EAC/BC,EAAE,CAAC,iDAAiD,EAAE,MAAM;IAC1DE,MAAM,CAACL,cAAc,CAAC,EAAE,CAAC,CAAC,CAACM,IAAI,CAAC,QAAQ,CAAC;EAC3C,CAAC,CAAC;EAEFH,EAAE,CAAC,mDAAmD,EAAE,MAAM;IAC5DE,MAAM,CAACL,cAAc,CAAC,IAAI,CAAC,CAAC,CAACM,IAAI,CAAC,QAAQ,CAAC;EAC7C,CAAC,CAAC;EAEFH,EAAE,CAAC,sDAAsD,EAAE,MAAM;IAC/DE,MAAM,CAACL,cAAc,CAAC,OAAO,CAAC,CAAC,CAACM,IAAI,CAAC,WAAW,CAAC;EACnD,CAAC,CAAC;EAEFH,EAAE,CAAC,2DAA2D,EAAE,MAAM;IACpEE,MAAM,CAACL,cAAc,CAAC,KAAK,CAAC,CAAC,CAACM,IAAI,CAAC,YAAY,CAAC;EAClD,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -10,12 +10,13 @@ export class PaymentService {
|
|
|
10
10
|
* @param {string} returnUrl
|
|
11
11
|
* @param {string} reference
|
|
12
12
|
* @param {boolean} isLivePayment
|
|
13
|
-
* @param {{ formId: string, slug: string } | undefined } metadata
|
|
13
|
+
* @param {{ formId: string, slug: string, language: string } | undefined } metadata
|
|
14
14
|
* @param {string} [email] - optional email to prepopulate on GOV.UK Pay
|
|
15
15
|
*/
|
|
16
16
|
createPayment(amount: number, description: string, returnUrl: string, reference: string, isLivePayment: boolean, metadata: {
|
|
17
17
|
formId: string;
|
|
18
18
|
slug: string;
|
|
19
|
+
language: string;
|
|
19
20
|
} | undefined, email?: string): Promise<{
|
|
20
21
|
paymentId: string;
|
|
21
22
|
paymentUrl: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StatusCodes } from 'http-status-codes';
|
|
2
2
|
import { logger } from "../../common/helpers/logging/logger.js";
|
|
3
|
+
import { toPayLanguageCode } from "../engine/helpers.js";
|
|
3
4
|
import { buildPaymentInfo, convertPenceToPounds } from "../engine/routes/payment-helper.js";
|
|
4
5
|
import { get, post, postJson } from "../../services/httpService.js";
|
|
5
6
|
const PAYMENT_BASE_URL = 'https://publicapi.payments.service.gov.uk';
|
|
@@ -32,10 +33,11 @@ export class PaymentService {
|
|
|
32
33
|
* @param {string} returnUrl
|
|
33
34
|
* @param {string} reference
|
|
34
35
|
* @param {boolean} isLivePayment
|
|
35
|
-
* @param {{ formId: string, slug: string } | undefined } metadata
|
|
36
|
+
* @param {{ formId: string, slug: string, language: string } | undefined } metadata
|
|
36
37
|
* @param {string} [email] - optional email to prepopulate on GOV.UK Pay
|
|
37
38
|
*/
|
|
38
39
|
async createPayment(amount, description, returnUrl, reference, isLivePayment, metadata, email) {
|
|
40
|
+
const language = toPayLanguageCode(metadata?.language);
|
|
39
41
|
try {
|
|
40
42
|
/** @type {CreatePaymentRequest} */
|
|
41
43
|
const payload = {
|
|
@@ -44,7 +46,8 @@ export class PaymentService {
|
|
|
44
46
|
reference,
|
|
45
47
|
metadata,
|
|
46
48
|
return_url: returnUrl,
|
|
47
|
-
delayed_capture: true
|
|
49
|
+
delayed_capture: true,
|
|
50
|
+
language
|
|
48
51
|
};
|
|
49
52
|
|
|
50
53
|
// Prepopulate email on GOV.UK Pay if provided
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.js","names":["StatusCodes","logger","buildPaymentInfo","convertPenceToPounds","get","post","postJson","PAYMENT_BASE_URL","PAYMENT_ENDPOINT","getAuthHeaders","apiKey","Authorization","PaymentService","constructor","createPayment","amount","description","returnUrl","reference","isLivePayment","metadata","email","payload","return_url","delayed_capture","response","postToPayProvider","info","payment_id","paymentId","paymentUrl","_links","next_url","href","err","error","output","message","undefined","getPaymentStatus","getByType","headers","json","errorMessage","Error","JSON","stringify","state","status","code","capturePayment","statusCode","res","OK","NO_CONTENT","event","category","action","outcome","reason","postJsonByType","includes"],"sources":["../../../../src/server/plugins/payment/service.js"],"sourcesContent":["import { StatusCodes } from 'http-status-codes'\n\nimport { logger } from '~/src/server/common/helpers/logging/logger.js'\nimport {\n buildPaymentInfo,\n convertPenceToPounds\n} from '~/src/server/plugins/engine/routes/payment-helper.js'\nimport { get, post, postJson } from '~/src/server/services/httpService.js'\n\nconst PAYMENT_BASE_URL = 'https://publicapi.payments.service.gov.uk'\nconst PAYMENT_ENDPOINT = '/v1/payments'\n\n/**\n * @param {string} apiKey\n * @returns {{ Authorization: string }}\n */\nfunction getAuthHeaders(apiKey) {\n return {\n Authorization: `Bearer ${apiKey}`\n }\n}\n\nexport class PaymentService {\n /** @type {string} */\n #apiKey\n\n /**\n * @param {string} apiKey - API key to use (global config for test value, per-form config for live value)\n */\n constructor(apiKey) {\n this.#apiKey = apiKey\n }\n\n /**\n * Creates a payment with delayed capture (pre-authorisation)\n * @param {number} amount - in pence\n * @param {string} description\n * @param {string} returnUrl\n * @param {string} reference\n * @param {boolean} isLivePayment\n * @param {{ formId: string, slug: string } | undefined } metadata\n * @param {string} [email] - optional email to prepopulate on GOV.UK Pay\n */\n async createPayment(\n amount,\n description,\n returnUrl,\n reference,\n isLivePayment,\n metadata,\n email\n ) {\n try {\n /** @type {CreatePaymentRequest} */\n const payload = {\n amount,\n description,\n reference,\n metadata,\n return_url: returnUrl,\n delayed_capture: true\n }\n\n // Prepopulate email on GOV.UK Pay if provided\n if (email) {\n payload.email = email\n }\n\n const response = await this.postToPayProvider(payload)\n\n logger.info(\n buildPaymentInfo(\n 'create-payment',\n 'success',\n `amount=${convertPenceToPounds(amount)}`,\n isLivePayment,\n response.payment_id\n ),\n `[payment] Created payment and user taken to enter pre-auth details for paymentId=${response.payment_id}`\n )\n\n return {\n paymentId: response.payment_id,\n paymentUrl: response._links.next_url.href\n }\n } catch (err) {\n const error =\n /** @type {{ output?: { payload?: any }, message?: any }} */ (err)\n if (isLivePayment) {\n logger.error(\n error.output?.payload ?? error.message,\n `[payment] Failed to create payment session for reference ${reference}`\n )\n }\n }\n return undefined\n }\n\n /**\n * @param {string} paymentId\n * @param {boolean} isLivePayment\n * @returns {Promise<GetPaymentResponse>}\n */\n async getPaymentStatus(paymentId, isLivePayment) {\n const getByType = /** @type {typeof get<GetPaymentApiResponse>} */ (get)\n\n try {\n const response = await getByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}`,\n {\n headers: getAuthHeaders(this.#apiKey),\n json: true\n }\n )\n\n if (response.error) {\n const errorMessage =\n response.error instanceof Error\n ? response.error.message\n : JSON.stringify(response.error)\n throw new Error(`Failed to get payment status: ${errorMessage}`)\n }\n\n const state = response.payload.state\n logger.info(\n buildPaymentInfo(\n 'get-payment-status',\n state.status === 'capturable' || state.status === 'success'\n ? 'success'\n : 'failure',\n `status:${state.status} code:${state.code ?? 'N/A'} message:${state.message ?? 'N/A'}`,\n isLivePayment,\n paymentId\n ),\n `[payment] Got payment status for paymentId=${paymentId}: status=${state.status}`\n )\n\n return {\n state,\n _links: response.payload._links,\n email: response.payload.email,\n paymentId: response.payload.payment_id,\n amount: response.payload.amount\n }\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error getting payment status for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * Captures a payment that is in 'capturable' status\n * @param {string} paymentId\n * @param {number} amount\n * @returns {Promise<boolean>}\n */\n async capturePayment(paymentId, amount) {\n try {\n const response = await post(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}/capture`,\n {\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n const statusCode = response.res.statusCode\n\n if (\n statusCode === StatusCodes.OK ||\n statusCode === StatusCodes.NO_CONTENT\n ) {\n logger.info(\n {\n event: {\n category: 'payment',\n action: 'capture-payment',\n outcome: 'success',\n reason: `amount=${convertPenceToPounds(amount)}`,\n reference: paymentId\n }\n },\n `[payment] Successfully captured payment for paymentId=${paymentId}`\n )\n return true\n }\n\n logger.error(\n `[payment] Capture failed for paymentId=${paymentId}: HTTP ${statusCode}`\n )\n return false\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error capturing payment for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * @param {CreatePaymentRequest} payload\n */\n async postToPayProvider(payload) {\n const postJsonByType =\n /** @type {typeof postJson<CreatePaymentResponse>} */ (postJson)\n\n try {\n const response = await postJsonByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}`,\n {\n payload,\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n if (response.payload?.state.status !== 'created') {\n throw new Error(\n `Failed to create payment for reference=${payload.reference}`\n )\n }\n\n return response.payload\n } catch (err) {\n const error = /** @type {Error} */ (err)\n if (!error.message.includes('401 Unauthorized')) {\n logger.error(\n error,\n `[payment] Error creating payment for reference=${payload.reference}: ${error.message}`\n )\n }\n throw err\n }\n }\n}\n\n/**\n * @import { CreatePaymentRequest, CreatePaymentResponse, GetPaymentApiResponse, GetPaymentResponse } from '~/src/server/plugins/payment/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"service.js","names":["StatusCodes","logger","toPayLanguageCode","buildPaymentInfo","convertPenceToPounds","get","post","postJson","PAYMENT_BASE_URL","PAYMENT_ENDPOINT","getAuthHeaders","apiKey","Authorization","PaymentService","constructor","createPayment","amount","description","returnUrl","reference","isLivePayment","metadata","email","language","payload","return_url","delayed_capture","response","postToPayProvider","info","payment_id","paymentId","paymentUrl","_links","next_url","href","err","error","output","message","undefined","getPaymentStatus","getByType","headers","json","errorMessage","Error","JSON","stringify","state","status","code","capturePayment","statusCode","res","OK","NO_CONTENT","event","category","action","outcome","reason","postJsonByType","includes"],"sources":["../../../../src/server/plugins/payment/service.js"],"sourcesContent":["import { StatusCodes } from 'http-status-codes'\n\nimport { logger } from '~/src/server/common/helpers/logging/logger.js'\nimport { toPayLanguageCode } from '~/src/server/plugins/engine/helpers.js'\nimport {\n buildPaymentInfo,\n convertPenceToPounds\n} from '~/src/server/plugins/engine/routes/payment-helper.js'\nimport { get, post, postJson } from '~/src/server/services/httpService.js'\n\nconst PAYMENT_BASE_URL = 'https://publicapi.payments.service.gov.uk'\nconst PAYMENT_ENDPOINT = '/v1/payments'\n\n/**\n * @param {string} apiKey\n * @returns {{ Authorization: string }}\n */\nfunction getAuthHeaders(apiKey) {\n return {\n Authorization: `Bearer ${apiKey}`\n }\n}\n\nexport class PaymentService {\n /** @type {string} */\n #apiKey\n\n /**\n * @param {string} apiKey - API key to use (global config for test value, per-form config for live value)\n */\n constructor(apiKey) {\n this.#apiKey = apiKey\n }\n\n /**\n * Creates a payment with delayed capture (pre-authorisation)\n * @param {number} amount - in pence\n * @param {string} description\n * @param {string} returnUrl\n * @param {string} reference\n * @param {boolean} isLivePayment\n * @param {{ formId: string, slug: string, language: string } | undefined } metadata\n * @param {string} [email] - optional email to prepopulate on GOV.UK Pay\n */\n async createPayment(\n amount,\n description,\n returnUrl,\n reference,\n isLivePayment,\n metadata,\n email\n ) {\n const language = toPayLanguageCode(metadata?.language)\n\n try {\n /** @type {CreatePaymentRequest} */\n const payload = {\n amount,\n description,\n reference,\n metadata,\n return_url: returnUrl,\n delayed_capture: true,\n language\n }\n\n // Prepopulate email on GOV.UK Pay if provided\n if (email) {\n payload.email = email\n }\n\n const response = await this.postToPayProvider(payload)\n\n logger.info(\n buildPaymentInfo(\n 'create-payment',\n 'success',\n `amount=${convertPenceToPounds(amount)}`,\n isLivePayment,\n response.payment_id\n ),\n `[payment] Created payment and user taken to enter pre-auth details for paymentId=${response.payment_id}`\n )\n\n return {\n paymentId: response.payment_id,\n paymentUrl: response._links.next_url.href\n }\n } catch (err) {\n const error =\n /** @type {{ output?: { payload?: any }, message?: any }} */ (err)\n if (isLivePayment) {\n logger.error(\n error.output?.payload ?? error.message,\n `[payment] Failed to create payment session for reference ${reference}`\n )\n }\n }\n return undefined\n }\n\n /**\n * @param {string} paymentId\n * @param {boolean} isLivePayment\n * @returns {Promise<GetPaymentResponse>}\n */\n async getPaymentStatus(paymentId, isLivePayment) {\n const getByType = /** @type {typeof get<GetPaymentApiResponse>} */ (get)\n\n try {\n const response = await getByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}`,\n {\n headers: getAuthHeaders(this.#apiKey),\n json: true\n }\n )\n\n if (response.error) {\n const errorMessage =\n response.error instanceof Error\n ? response.error.message\n : JSON.stringify(response.error)\n throw new Error(`Failed to get payment status: ${errorMessage}`)\n }\n\n const state = response.payload.state\n logger.info(\n buildPaymentInfo(\n 'get-payment-status',\n state.status === 'capturable' || state.status === 'success'\n ? 'success'\n : 'failure',\n `status:${state.status} code:${state.code ?? 'N/A'} message:${state.message ?? 'N/A'}`,\n isLivePayment,\n paymentId\n ),\n `[payment] Got payment status for paymentId=${paymentId}: status=${state.status}`\n )\n\n return {\n state,\n _links: response.payload._links,\n email: response.payload.email,\n paymentId: response.payload.payment_id,\n amount: response.payload.amount\n }\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error getting payment status for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * Captures a payment that is in 'capturable' status\n * @param {string} paymentId\n * @param {number} amount\n * @returns {Promise<boolean>}\n */\n async capturePayment(paymentId, amount) {\n try {\n const response = await post(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}/${paymentId}/capture`,\n {\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n const statusCode = response.res.statusCode\n\n if (\n statusCode === StatusCodes.OK ||\n statusCode === StatusCodes.NO_CONTENT\n ) {\n logger.info(\n {\n event: {\n category: 'payment',\n action: 'capture-payment',\n outcome: 'success',\n reason: `amount=${convertPenceToPounds(amount)}`,\n reference: paymentId\n }\n },\n `[payment] Successfully captured payment for paymentId=${paymentId}`\n )\n return true\n }\n\n logger.error(\n `[payment] Capture failed for paymentId=${paymentId}: HTTP ${statusCode}`\n )\n return false\n } catch (err) {\n const error = /** @type {Error} */ (err)\n logger.error(\n error,\n `[payment] Error capturing payment for paymentId=${paymentId}: ${error.message}`\n )\n throw err\n }\n }\n\n /**\n * @param {CreatePaymentRequest} payload\n */\n async postToPayProvider(payload) {\n const postJsonByType =\n /** @type {typeof postJson<CreatePaymentResponse>} */ (postJson)\n\n try {\n const response = await postJsonByType(\n `${PAYMENT_BASE_URL}${PAYMENT_ENDPOINT}`,\n {\n payload,\n headers: getAuthHeaders(this.#apiKey)\n }\n )\n\n if (response.payload?.state.status !== 'created') {\n throw new Error(\n `Failed to create payment for reference=${payload.reference}`\n )\n }\n\n return response.payload\n } catch (err) {\n const error = /** @type {Error} */ (err)\n if (!error.message.includes('401 Unauthorized')) {\n logger.error(\n error,\n `[payment] Error creating payment for reference=${payload.reference}: ${error.message}`\n )\n }\n throw err\n }\n }\n}\n\n/**\n * @import { CreatePaymentRequest, CreatePaymentResponse, GetPaymentApiResponse, GetPaymentResponse } from '~/src/server/plugins/payment/types.js'\n */\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EN_GB } from "../../constants.js";
|
|
1
2
|
import { PaymentService } from "./service.js";
|
|
2
3
|
import { get, post, postJson } from "../../services/httpService.js";
|
|
3
4
|
jest.mock("../../services/httpService.ts");
|
|
@@ -33,7 +34,8 @@ describe('payment service', () => {
|
|
|
33
34
|
const returnUrl = 'http://localhost:3009/payment-callback-handler';
|
|
34
35
|
const metadata = {
|
|
35
36
|
formId: 'form-id',
|
|
36
|
-
slug: 'my-form-slug'
|
|
37
|
+
slug: 'my-form-slug',
|
|
38
|
+
language: EN_GB
|
|
37
39
|
};
|
|
38
40
|
const payment = await service.createPayment(100, 'Payment description', returnUrl, referenceNumber, false, metadata);
|
|
39
41
|
expect(payment?.paymentId).toBe('payment-id-12345');
|
|
@@ -45,7 +47,8 @@ describe('payment service', () => {
|
|
|
45
47
|
const returnUrl = 'http://localhost:3009/payment-callback-handler';
|
|
46
48
|
const metadata = {
|
|
47
49
|
formId: 'form-id',
|
|
48
|
-
slug: 'my-form-slug'
|
|
50
|
+
slug: 'my-form-slug',
|
|
51
|
+
language: EN_GB
|
|
49
52
|
};
|
|
50
53
|
const res = await service.createPayment(100, 'Payment description', returnUrl, referenceNumber, false, metadata);
|
|
51
54
|
expect(res).toBeUndefined();
|
|
@@ -68,7 +71,8 @@ describe('payment service', () => {
|
|
|
68
71
|
const returnUrl = 'http://localhost:3009/payment-callback-handler';
|
|
69
72
|
const metadata = {
|
|
70
73
|
formId: 'form-id',
|
|
71
|
-
slug: 'my-form-slug'
|
|
74
|
+
slug: 'my-form-slug',
|
|
75
|
+
language: 'cy'
|
|
72
76
|
};
|
|
73
77
|
const res = await service.createPayment(100, 'Payment description', returnUrl, referenceNumber, false, metadata);
|
|
74
78
|
expect(res).toBeUndefined();
|