@defra/forms-engine-plugin 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/.public/assets/images/govuk-crest.svg +1 -1
  2. package/.public/assets/rebrand/images/favicon.ico +0 -0
  3. package/.public/assets/rebrand/images/favicon.svg +1 -0
  4. package/.public/assets/rebrand/images/govuk-crest.svg +1 -0
  5. package/.public/assets/rebrand/images/govuk-icon-180.png +0 -0
  6. package/.public/assets/rebrand/images/govuk-icon-192.png +0 -0
  7. package/.public/assets/rebrand/images/govuk-icon-512.png +0 -0
  8. package/.public/assets/rebrand/images/govuk-icon-mask.svg +1 -0
  9. package/.public/assets/rebrand/images/govuk-opengraph-image.png +0 -0
  10. package/.public/assets/rebrand/manifest.json +39 -0
  11. package/.public/assets-manifest.json +12 -2
  12. package/.public/javascripts/application.min.js +1 -1
  13. package/.public/javascripts/application.min.js.LICENSE.txt +5 -1
  14. package/.public/javascripts/application.min.js.map +1 -1
  15. package/.public/javascripts/shared.min.js +3 -0
  16. package/.public/javascripts/shared.min.js.LICENSE.txt +62 -0
  17. package/.public/javascripts/shared.min.js.map +1 -0
  18. package/.public/stylesheets/application.min.css +3 -3
  19. package/.public/stylesheets/application.min.css.map +1 -1
  20. package/.server/client/javascripts/application.js +2 -67
  21. package/.server/client/javascripts/application.js.map +1 -1
  22. package/.server/client/javascripts/autocomplete.d.ts +1 -0
  23. package/.server/client/javascripts/autocomplete.js +49 -0
  24. package/.server/client/javascripts/autocomplete.js.map +1 -0
  25. package/.server/client/javascripts/file-upload.js +8 -1
  26. package/.server/client/javascripts/file-upload.js.map +1 -1
  27. package/.server/client/javascripts/govuk.d.ts +1 -0
  28. package/.server/client/javascripts/govuk.js +12 -0
  29. package/.server/client/javascripts/govuk.js.map +1 -0
  30. package/.server/client/javascripts/preview-close-link.d.ts +1 -0
  31. package/.server/client/javascripts/preview-close-link.js +12 -0
  32. package/.server/client/javascripts/preview-close-link.js.map +1 -0
  33. package/.server/client/javascripts/shared.d.ts +9 -0
  34. package/.server/client/javascripts/shared.js +15 -0
  35. package/.server/client/javascripts/shared.js.map +1 -0
  36. package/.server/client/stylesheets/_tag-env.scss +9 -0
  37. package/.server/config/index.d.ts +1 -0
  38. package/.server/config/index.js +9 -0
  39. package/.server/config/index.js.map +1 -1
  40. package/.server/index.js +6 -2
  41. package/.server/index.js.map +1 -1
  42. package/.server/server/common/helpers/logging/request-tracing.js +1 -1
  43. package/.server/server/common/helpers/logging/request-tracing.js.map +1 -1
  44. package/.server/server/common/helpers/redis-client.js +5 -3
  45. package/.server/server/common/helpers/redis-client.js.map +1 -1
  46. package/.server/server/constants.d.ts +0 -1
  47. package/.server/server/constants.js +0 -1
  48. package/.server/server/constants.js.map +1 -1
  49. package/.server/server/index.js +3 -1
  50. package/.server/server/index.js.map +1 -1
  51. package/.server/server/plugins/engine/components/DatePartsField.d.ts +1 -6
  52. package/.server/server/plugins/engine/components/DatePartsField.js +2 -1
  53. package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
  54. package/.server/server/plugins/engine/components/MonthYearField.d.ts +1 -5
  55. package/.server/server/plugins/engine/components/MonthYearField.js +3 -2
  56. package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
  57. package/.server/server/plugins/engine/components/YesNoField.js +2 -1
  58. package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
  59. package/.server/server/plugins/engine/components/types.d.ts +9 -0
  60. package/.server/server/plugins/engine/components/types.js.map +1 -1
  61. package/.server/server/plugins/engine/date-helper.d.ts +12 -0
  62. package/.server/server/plugins/engine/date-helper.js +21 -0
  63. package/.server/server/plugins/engine/date-helper.js.map +1 -0
  64. package/.server/server/plugins/engine/helpers.js +4 -3
  65. package/.server/server/plugins/engine/helpers.js.map +1 -1
  66. package/.server/server/plugins/engine/index.d.ts +0 -1
  67. package/.server/server/plugins/engine/index.js +0 -1
  68. package/.server/server/plugins/engine/index.js.map +1 -1
  69. package/.server/server/plugins/engine/models/FormModel.d.ts +13 -6
  70. package/.server/server/plugins/engine/models/FormModel.js +51 -18
  71. package/.server/server/plugins/engine/models/FormModel.js.map +1 -1
  72. package/.server/server/plugins/engine/outputFormatters/machine/v2.js.map +1 -1
  73. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js +3 -2
  74. package/.server/server/plugins/engine/pageControllers/FileUploadPageController.js.map +1 -1
  75. package/.server/server/plugins/engine/plugin.js +6 -5
  76. package/.server/server/plugins/engine/plugin.js.map +1 -1
  77. package/.server/server/plugins/engine/services/notifyService.js +3 -1
  78. package/.server/server/plugins/engine/services/notifyService.js.map +1 -1
  79. package/.server/server/plugins/engine/views/components/tag-env/template.njk +6 -2
  80. package/.server/server/plugins/engine/views/file-upload.html +0 -13
  81. package/.server/server/plugins/errorPages.js +1 -1
  82. package/.server/server/plugins/errorPages.js.map +1 -1
  83. package/.server/server/plugins/nunjucks/context.js +1 -1
  84. package/.server/server/plugins/nunjucks/context.js.map +1 -1
  85. package/.server/server/plugins/nunjucks/environment.js +1 -0
  86. package/.server/server/plugins/nunjucks/environment.js.map +1 -1
  87. package/package.json +21 -25
  88. package/src/client/javascripts/application.js +2 -86
  89. package/src/client/javascripts/autocomplete.js +57 -0
  90. package/src/client/javascripts/file-upload.js +9 -1
  91. package/src/client/javascripts/govuk.js +22 -0
  92. package/src/client/javascripts/preview-close-link.js +12 -0
  93. package/src/client/javascripts/shared.js +16 -0
  94. package/src/client/stylesheets/_tag-env.scss +9 -0
  95. package/src/config/index.ts +10 -0
  96. package/src/index.ts +7 -2
  97. package/src/server/common/helpers/logging/request-tracing.js +1 -1
  98. package/src/server/common/helpers/redis-client.js +5 -3
  99. package/src/server/constants.js +0 -1
  100. package/src/server/index.ts +5 -2
  101. package/src/server/plugins/engine/components/DatePartsField.test.ts +17 -0
  102. package/src/server/plugins/engine/components/DatePartsField.ts +7 -8
  103. package/src/server/plugins/engine/components/MonthYearField.test.ts +15 -0
  104. package/src/server/plugins/engine/components/MonthYearField.ts +12 -8
  105. package/src/server/plugins/engine/components/YesNoField.ts +16 -2
  106. package/src/server/plugins/engine/components/types.ts +11 -0
  107. package/src/server/plugins/engine/date-helper.test.ts +47 -0
  108. package/src/server/plugins/engine/date-helper.ts +32 -0
  109. package/src/server/plugins/engine/helpers.ts +9 -2
  110. package/src/server/plugins/engine/index.ts +0 -1
  111. package/src/server/plugins/engine/models/FormModel.test.ts +163 -1
  112. package/src/server/plugins/engine/models/FormModel.ts +90 -23
  113. package/src/server/plugins/engine/outputFormatters/machine/v2.ts +4 -2
  114. package/src/server/plugins/engine/pageControllers/FileUploadPageController.test.ts +2 -1
  115. package/src/server/plugins/engine/pageControllers/FileUploadPageController.ts +6 -2
  116. package/src/server/plugins/engine/plugin.ts +11 -7
  117. package/src/server/plugins/engine/services/notifyService.ts +6 -2
  118. package/src/server/plugins/engine/views/components/tag-env/template.njk +6 -2
  119. package/src/server/plugins/engine/views/file-upload.html +0 -13
  120. package/src/server/plugins/errorPages.ts +5 -1
  121. package/src/server/plugins/nunjucks/context.js +3 -1
  122. package/src/server/plugins/nunjucks/environment.js +1 -0
  123. package/.public/javascripts/file-upload.min.js +0 -2
  124. package/.public/javascripts/file-upload.min.js.map +0 -1
@@ -1,68 +1,3 @@
1
- import { Button, CharacterCount, Checkboxes, ErrorSummary, Header, NotificationBanner, Radios, SkipLink, createAll } from 'govuk-frontend';
2
- createAll(Button);
3
- createAll(CharacterCount);
4
- createAll(Checkboxes);
5
- createAll(ErrorSummary);
6
- createAll(Header);
7
- createAll(NotificationBanner);
8
- createAll(Radios);
9
- createAll(SkipLink);
10
-
11
- // Show preview close link via `rel="opener"`
12
- if (window.opener) {
13
- const $closeLink = document.querySelector('.js-preview-banner-close');
14
- $closeLink?.removeAttribute('hidden');
15
- $closeLink?.addEventListener('click', event => {
16
- event.preventDefault();
17
- window.close();
18
- });
19
- }
20
-
21
- /**
22
- * Initialise autocomplete
23
- * @param {HTMLSelectElement | null} $select
24
- * @param {(config: object) => void} init
25
- */
26
- function initAutocomplete($select, init) {
27
- if (!$select) {
28
- return;
29
- }
30
- const config = {
31
- id: $select.id,
32
- selectElement: $select
33
- };
34
- init(config);
35
-
36
- /** @type {HTMLInputElement | null} */
37
- const $input = document.querySelector(`#${config.id}`);
38
-
39
- // Allowed values for input
40
- const inputValues = [...$select.options].map(option => option.text);
41
-
42
- // Reset select when input value is not allowed
43
- $input?.addEventListener('blur', () => {
44
- if (!$input.value || !inputValues.includes($input.value)) {
45
- $select.value = '';
46
- }
47
- });
48
- }
49
-
50
- // Find all autocompletes
51
- const $autocompletes = document.querySelectorAll(`[data-module="govuk-accessible-autocomplete"]`);
52
-
53
- // Lazy load autocomplete component
54
- if ($autocompletes.length) {
55
- // @ts-expect-error -- No types available
56
- import('accessible-autocomplete').then(component => {
57
- const {
58
- default: accessibleAutocomplete
59
- } = component;
60
-
61
- // Initialise each autocomplete
62
- $autocompletes.forEach($module => initAutocomplete($module.querySelector('select'), accessibleAutocomplete.enhanceSelectElement));
63
- })
64
-
65
- // eslint-disable-next-line no-console
66
- .catch(console.error);
67
- }
1
+ import { initAll } from "./shared.js";
2
+ initAll();
68
3
  //# sourceMappingURL=application.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"application.js","names":["Button","CharacterCount","Checkboxes","ErrorSummary","Header","NotificationBanner","Radios","SkipLink","createAll","window","opener","$closeLink","document","querySelector","removeAttribute","addEventListener","event","preventDefault","close","initAutocomplete","$select","init","config","id","selectElement","$input","inputValues","options","map","option","text","value","includes","$autocompletes","querySelectorAll","length","then","component","default","accessibleAutocomplete","forEach","$module","enhanceSelectElement","catch","console","error"],"sources":["../../../src/client/javascripts/application.js"],"sourcesContent":["import {\n Button,\n CharacterCount,\n Checkboxes,\n ErrorSummary,\n Header,\n NotificationBanner,\n Radios,\n SkipLink,\n createAll\n} from 'govuk-frontend'\n\ncreateAll(Button)\ncreateAll(CharacterCount)\ncreateAll(Checkboxes)\ncreateAll(ErrorSummary)\ncreateAll(Header)\ncreateAll(NotificationBanner)\ncreateAll(Radios)\ncreateAll(SkipLink)\n\n// Show preview close link via `rel=\"opener\"`\nif (window.opener) {\n const $closeLink = document.querySelector('.js-preview-banner-close')\n\n $closeLink?.removeAttribute('hidden')\n $closeLink?.addEventListener('click', (event) => {\n event.preventDefault()\n window.close()\n })\n}\n\n/**\n * Initialise autocomplete\n * @param {HTMLSelectElement | null} $select\n * @param {(config: object) => void} init\n */\nfunction initAutocomplete($select, init) {\n if (!$select) {\n return\n }\n\n const config = {\n id: $select.id,\n selectElement: $select\n }\n\n init(config)\n\n /** @type {HTMLInputElement | null} */\n const $input = document.querySelector(`#${config.id}`)\n\n // Allowed values for input\n const inputValues = [...$select.options].map((option) => option.text)\n\n // Reset select when input value is not allowed\n $input?.addEventListener('blur', () => {\n if (!$input.value || !inputValues.includes($input.value)) {\n $select.value = ''\n }\n })\n}\n\n// Find all autocompletes\nconst $autocompletes = document.querySelectorAll(\n `[data-module=\"govuk-accessible-autocomplete\"]`\n)\n\n// Lazy load autocomplete component\nif ($autocompletes.length) {\n // @ts-expect-error -- No types available\n import('accessible-autocomplete')\n .then((component) => {\n const { default: accessibleAutocomplete } = component\n\n // Initialise each autocomplete\n $autocompletes.forEach(($module) =>\n initAutocomplete(\n $module.querySelector('select'),\n accessibleAutocomplete.enhanceSelectElement\n )\n )\n })\n\n // eslint-disable-next-line no-console\n .catch(console.error)\n}\n"],"mappings":"AAAA,SACEA,MAAM,EACNC,cAAc,EACdC,UAAU,EACVC,YAAY,EACZC,MAAM,EACNC,kBAAkB,EAClBC,MAAM,EACNC,QAAQ,EACRC,SAAS,QACJ,gBAAgB;AAEvBA,SAAS,CAACR,MAAM,CAAC;AACjBQ,SAAS,CAACP,cAAc,CAAC;AACzBO,SAAS,CAACN,UAAU,CAAC;AACrBM,SAAS,CAACL,YAAY,CAAC;AACvBK,SAAS,CAACJ,MAAM,CAAC;AACjBI,SAAS,CAACH,kBAAkB,CAAC;AAC7BG,SAAS,CAACF,MAAM,CAAC;AACjBE,SAAS,CAACD,QAAQ,CAAC;;AAEnB;AACA,IAAIE,MAAM,CAACC,MAAM,EAAE;EACjB,MAAMC,UAAU,GAAGC,QAAQ,CAACC,aAAa,CAAC,0BAA0B,CAAC;EAErEF,UAAU,EAAEG,eAAe,CAAC,QAAQ,CAAC;EACrCH,UAAU,EAAEI,gBAAgB,CAAC,OAAO,EAAGC,KAAK,IAAK;IAC/CA,KAAK,CAACC,cAAc,CAAC,CAAC;IACtBR,MAAM,CAACS,KAAK,CAAC,CAAC;EAChB,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASC,gBAAgBA,CAACC,OAAO,EAAEC,IAAI,EAAE;EACvC,IAAI,CAACD,OAAO,EAAE;IACZ;EACF;EAEA,MAAME,MAAM,GAAG;IACbC,EAAE,EAAEH,OAAO,CAACG,EAAE;IACdC,aAAa,EAAEJ;EACjB,CAAC;EAEDC,IAAI,CAACC,MAAM,CAAC;;EAEZ;EACA,MAAMG,MAAM,GAAGb,QAAQ,CAACC,aAAa,CAAC,IAAIS,MAAM,CAACC,EAAE,EAAE,CAAC;;EAEtD;EACA,MAAMG,WAAW,GAAG,CAAC,GAAGN,OAAO,CAACO,OAAO,CAAC,CAACC,GAAG,CAAEC,MAAM,IAAKA,MAAM,CAACC,IAAI,CAAC;;EAErE;EACAL,MAAM,EAAEV,gBAAgB,CAAC,MAAM,EAAE,MAAM;IACrC,IAAI,CAACU,MAAM,CAACM,KAAK,IAAI,CAACL,WAAW,CAACM,QAAQ,CAACP,MAAM,CAACM,KAAK,CAAC,EAAE;MACxDX,OAAO,CAACW,KAAK,GAAG,EAAE;IACpB;EACF,CAAC,CAAC;AACJ;;AAEA;AACA,MAAME,cAAc,GAAGrB,QAAQ,CAACsB,gBAAgB,CAC9C,+CACF,CAAC;;AAED;AACA,IAAID,cAAc,CAACE,MAAM,EAAE;EACzB;EACA,MAAM,CAAC,yBAAyB,CAAC,CAC9BC,IAAI,CAAEC,SAAS,IAAK;IACnB,MAAM;MAAEC,OAAO,EAAEC;IAAuB,CAAC,GAAGF,SAAS;;IAErD;IACAJ,cAAc,CAACO,OAAO,CAAEC,OAAO,IAC7BtB,gBAAgB,CACdsB,OAAO,CAAC5B,aAAa,CAAC,QAAQ,CAAC,EAC/B0B,sBAAsB,CAACG,oBACzB,CACF,CAAC;EACH,CAAC;;EAED;EAAA,CACCC,KAAK,CAACC,OAAO,CAACC,KAAK,CAAC;AACzB","ignoreList":[]}
1
+ {"version":3,"file":"application.js","names":["initAll"],"sources":["../../../src/client/javascripts/application.js"],"sourcesContent":["import { initAll } from '~/src/client/javascripts/shared.js'\n\ninitAll()\n"],"mappings":"AAAA,SAASA,OAAO;AAEhBA,OAAO,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export function initAllAutocomplete(): void;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Initialise autocomplete
3
+ * @param {HTMLSelectElement | null} $select
4
+ * @param {(config: object) => void} init
5
+ */
6
+ function initAutocomplete($select, init) {
7
+ if (!$select) {
8
+ return;
9
+ }
10
+ const config = {
11
+ id: $select.id,
12
+ selectElement: $select
13
+ };
14
+ init(config);
15
+
16
+ /** @type {HTMLInputElement | null} */
17
+ const $input = document.querySelector(`#${config.id}`);
18
+
19
+ // Allowed values for input
20
+ const inputValues = [...$select.options].map(option => option.text);
21
+
22
+ // Reset select when input value is not allowed
23
+ $input?.addEventListener('blur', () => {
24
+ if (!$input.value || !inputValues.includes($input.value)) {
25
+ $select.value = '';
26
+ }
27
+ });
28
+ }
29
+ export function initAllAutocomplete() {
30
+ // Find all autocompletes
31
+ const $autocompletes = document.querySelectorAll(`[data-module="govuk-accessible-autocomplete"]`);
32
+
33
+ // Lazy load autocomplete component
34
+ if ($autocompletes.length) {
35
+ // @ts-expect-error -- No types available
36
+ import('accessible-autocomplete').then(component => {
37
+ const {
38
+ default: accessibleAutocomplete
39
+ } = component;
40
+
41
+ // Initialise each autocomplete
42
+ $autocompletes.forEach($module => initAutocomplete($module.querySelector('select'), accessibleAutocomplete.enhanceSelectElement));
43
+ })
44
+
45
+ // eslint-disable-next-line no-console
46
+ .catch(console.error);
47
+ }
48
+ }
49
+ //# sourceMappingURL=autocomplete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autocomplete.js","names":["initAutocomplete","$select","init","config","id","selectElement","$input","document","querySelector","inputValues","options","map","option","text","addEventListener","value","includes","initAllAutocomplete","$autocompletes","querySelectorAll","length","then","component","default","accessibleAutocomplete","forEach","$module","enhanceSelectElement","catch","console","error"],"sources":["../../../src/client/javascripts/autocomplete.js"],"sourcesContent":["/**\n * Initialise autocomplete\n * @param {HTMLSelectElement | null} $select\n * @param {(config: object) => void} init\n */\nfunction initAutocomplete($select, init) {\n if (!$select) {\n return\n }\n\n const config = {\n id: $select.id,\n selectElement: $select\n }\n\n init(config)\n\n /** @type {HTMLInputElement | null} */\n const $input = document.querySelector(`#${config.id}`)\n\n // Allowed values for input\n const inputValues = [...$select.options].map((option) => option.text)\n\n // Reset select when input value is not allowed\n $input?.addEventListener('blur', () => {\n if (!$input.value || !inputValues.includes($input.value)) {\n $select.value = ''\n }\n })\n}\n\nexport function initAllAutocomplete() {\n // Find all autocompletes\n const $autocompletes = document.querySelectorAll(\n `[data-module=\"govuk-accessible-autocomplete\"]`\n )\n\n // Lazy load autocomplete component\n if ($autocompletes.length) {\n // @ts-expect-error -- No types available\n import('accessible-autocomplete')\n .then((component) => {\n const { default: accessibleAutocomplete } = component\n\n // Initialise each autocomplete\n $autocompletes.forEach(($module) =>\n initAutocomplete(\n $module.querySelector('select'),\n accessibleAutocomplete.enhanceSelectElement\n )\n )\n })\n\n // eslint-disable-next-line no-console\n .catch(console.error)\n }\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA,SAASA,gBAAgBA,CAACC,OAAO,EAAEC,IAAI,EAAE;EACvC,IAAI,CAACD,OAAO,EAAE;IACZ;EACF;EAEA,MAAME,MAAM,GAAG;IACbC,EAAE,EAAEH,OAAO,CAACG,EAAE;IACdC,aAAa,EAAEJ;EACjB,CAAC;EAEDC,IAAI,CAACC,MAAM,CAAC;;EAEZ;EACA,MAAMG,MAAM,GAAGC,QAAQ,CAACC,aAAa,CAAC,IAAIL,MAAM,CAACC,EAAE,EAAE,CAAC;;EAEtD;EACA,MAAMK,WAAW,GAAG,CAAC,GAAGR,OAAO,CAACS,OAAO,CAAC,CAACC,GAAG,CAAEC,MAAM,IAAKA,MAAM,CAACC,IAAI,CAAC;;EAErE;EACAP,MAAM,EAAEQ,gBAAgB,CAAC,MAAM,EAAE,MAAM;IACrC,IAAI,CAACR,MAAM,CAACS,KAAK,IAAI,CAACN,WAAW,CAACO,QAAQ,CAACV,MAAM,CAACS,KAAK,CAAC,EAAE;MACxDd,OAAO,CAACc,KAAK,GAAG,EAAE;IACpB;EACF,CAAC,CAAC;AACJ;AAEA,OAAO,SAASE,mBAAmBA,CAAA,EAAG;EACpC;EACA,MAAMC,cAAc,GAAGX,QAAQ,CAACY,gBAAgB,CAC9C,+CACF,CAAC;;EAED;EACA,IAAID,cAAc,CAACE,MAAM,EAAE;IACzB;IACA,MAAM,CAAC,yBAAyB,CAAC,CAC9BC,IAAI,CAAEC,SAAS,IAAK;MACnB,MAAM;QAAEC,OAAO,EAAEC;MAAuB,CAAC,GAAGF,SAAS;;MAErD;MACAJ,cAAc,CAACO,OAAO,CAAEC,OAAO,IAC7B1B,gBAAgB,CACd0B,OAAO,CAAClB,aAAa,CAAC,QAAQ,CAAC,EAC/BgB,sBAAsB,CAACG,oBACzB,CACF,CAAC;IACH,CAAC;;IAED;IAAA,CACCC,KAAK,CAACC,OAAO,CAACC,KAAK,CAAC;EACzB;AACF","ignoreList":[]}
@@ -291,7 +291,7 @@ function handleAjaxFormSubmission(event, formElement, fileInput, uploadButton, e
291
291
  });
292
292
  return true;
293
293
  }
294
- export function initFileUpload() {
294
+ function initUpload() {
295
295
  const form = document.querySelector('form:has(input[type="file"])');
296
296
  /** @type {HTMLInputElement | null} */
297
297
  const fileInput = form ? form.querySelector('input[type="file"]') : null;
@@ -330,4 +330,11 @@ export function initFileUpload() {
330
330
  handleAjaxFormSubmission(event, formElement, fileInput, uploadButton, /** @type {HTMLElement | null} */errorSummary, uploadId);
331
331
  });
332
332
  }
333
+ export function initFileUpload() {
334
+ if (document.readyState === 'loading') {
335
+ document.addEventListener('DOMContentLoaded', initUpload);
336
+ } else {
337
+ initUpload();
338
+ }
339
+ }
333
340
  //# sourceMappingURL=file-upload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload.js","names":["MAX_POLLING_DURATION","ARIA_DESCRIBEDBY","ERROR_SUMMARY_TITLE_ID","createOrUpdateStatusAnnouncer","form","fileCountP","statusAnnouncer","querySelector","document","createElement","id","className","setAttribute","addStatusAnnouncerToDOM","asHTMLElement","appendChild","body","nextSibling","parentNode","insertBefore","parentElement","findOrCreateSummaryList","summaryList","continueButton","createFileRow","selectedFile","statusText","row","name","innerHTML","renderSummary","container","getElementById","uploadForm","closest","HTMLFormElement","fileInput","existingRow","remove","firstChild","textContent","showError","message","errorSummary","topErrorSummary","titleElement","removeAttribute","formGroup","classList","add","inputId","errorMessage","element","reloadPage","window","history","replaceState","location","href","pathname","buildUploadStatusUrl","uploadId","pathSegments","split","filter","segment","prefix","length","pollUploadStatus","attempts","interval","setInterval","clearInterval","uploadStatusUrl","fetch","headers","Accept","then","response","ok","Error","json","data","uploadStatus","catch","handleStandardFormSubmission","formElement","uploadButton","focus","setTimeout","disabled","handleAjaxFormSubmission","event","action","preventDefault","formData","FormData","isLocalDev","dataset","proxyUrl","uploadUrl","fetchOptions","method","redirect","mode","initFileUpload","Array","from","querySelectorAll","find","button","trim","isSubmitting","addEventListener","files"],"sources":["../../../src/client/javascripts/file-upload.js"],"sourcesContent":["export const MAX_POLLING_DURATION = 300 // 5 minutes\nconst ARIA_DESCRIBEDBY = 'aria-describedby'\nconst ERROR_SUMMARY_TITLE_ID = 'error-summary-title'\n\n/**\n * Creates or updates status announcer for screen readers\n * @param {HTMLElement | null} form - The form element\n * @param {HTMLElement | null} fileCountP - The file count paragraph element\n * @returns {HTMLElement} The status announcer element\n */\nfunction createOrUpdateStatusAnnouncer(form, fileCountP) {\n let statusAnnouncer = form?.querySelector('#statusInformation')\n\n if (!statusAnnouncer) {\n statusAnnouncer = document.createElement('div')\n statusAnnouncer.id = 'statusInformation'\n statusAnnouncer.className = 'govuk-visually-hidden'\n statusAnnouncer.setAttribute('aria-live', 'polite')\n\n // multiple fallbacks to ensure the status announcer is always added to the DOM\n // this helps with cross-browser compatibility and unexpected DOM structures encountered during QA\n try {\n addStatusAnnouncerToDOM(\n asHTMLElement(form),\n asHTMLElement(fileCountP),\n asHTMLElement(statusAnnouncer)\n )\n } catch {\n try {\n form?.appendChild(statusAnnouncer)\n } catch {\n document.body.appendChild(statusAnnouncer)\n }\n }\n }\n\n return /** @type {HTMLElement} */ (statusAnnouncer)\n}\n\n/**\n * Helper function to add the status announcer to the DOM\n * @param {HTMLElement} form - The form element\n * @param {HTMLElement | null} fileCountP - The file count paragraph element\n * @param {HTMLElement} statusAnnouncer - The status announcer element to add\n */\nfunction addStatusAnnouncerToDOM(form, fileCountP, statusAnnouncer) {\n if (fileCountP?.nextSibling && fileCountP.parentNode === form) {\n form.insertBefore(statusAnnouncer, fileCountP.nextSibling)\n return\n }\n\n const parentElement = fileCountP?.parentNode ?? form\n parentElement.appendChild(statusAnnouncer)\n}\n\n/**\n * Finds an existing summary list or creates a new one\n * @param {HTMLFormElement} form - The form element\n * @param {HTMLElement} fileCountP - The file count paragraph element\n * @returns {HTMLElement} The summary list element\n */\nfunction findOrCreateSummaryList(form, fileCountP) {\n let summaryList = form.querySelector('dl.govuk-summary-list')\n\n if (!summaryList) {\n summaryList = document.createElement('dl')\n summaryList.className = 'govuk-summary-list govuk-summary-list--long-key'\n\n const continueButton = form.querySelector('.govuk-button')\n\n if (continueButton) {\n form.insertBefore(summaryList, continueButton)\n } else {\n form.insertBefore(summaryList, fileCountP.nextSibling)\n }\n }\n\n return /** @type {HTMLElement} */ (summaryList)\n}\n\n/**\n * Creates a file row element for the summary list\n * @param {File | null} selectedFile - The selected file\n * @param {string} statusText - The status to display\n * @returns {HTMLElement} The created row element\n */\nfunction createFileRow(selectedFile, statusText) {\n const row = document.createElement('div')\n row.className = 'govuk-summary-list__row'\n row.setAttribute('data-filename', selectedFile?.name ?? '')\n row.innerHTML = `\n <dt class=\"govuk-summary-list__key\">\n ${selectedFile?.name ?? ''}\n </dt>\n <dd class=\"govuk-summary-list__value\">\n <strong class=\"govuk-tag govuk-tag--yellow\">${statusText}</strong>\n </dd>\n <dd class=\"govuk-summary-list__actions\">\n </dd>\n `\n return row\n}\n\n/**\n * Renders or updates the file summary box for the selected file\n * @param {File | null} selectedFile - The selected file\n * @param {string} statusText - The status to display\n * @param {HTMLElement} form - The form element\n */\nfunction renderSummary(selectedFile, statusText, form) {\n const container = document.getElementById('uploadedFilesContainer')\n const uploadForm = container ? container.closest('form') : null\n\n if (!uploadForm || !(uploadForm instanceof HTMLFormElement)) {\n return\n }\n\n const fileCountP = uploadForm.querySelector('p.govuk-body')\n\n if (!fileCountP) {\n return\n }\n\n const statusAnnouncer = createOrUpdateStatusAnnouncer(\n /** @type {HTMLElement} */ (uploadForm),\n /** @type {HTMLElement | null} */ (fileCountP)\n )\n\n const fileInput = form.querySelector('input[type=\"file\"]')\n\n if (fileInput) {\n fileInput.setAttribute(ARIA_DESCRIBEDBY, 'statusInformation')\n }\n\n const summaryList = findOrCreateSummaryList(\n /** @type {HTMLFormElement} */ (uploadForm),\n /** @type {HTMLElement} */ (fileCountP)\n )\n\n const existingRow = document.querySelector(\n `[data-filename=\"${selectedFile?.name}\"]`\n )\n\n if (existingRow) {\n existingRow.remove()\n }\n\n const row = createFileRow(selectedFile, statusText)\n summaryList.insertBefore(row, summaryList.firstChild)\n statusAnnouncer.textContent = `${selectedFile?.name ?? ''} ${statusText}`\n}\n\n/**\n * Shows an error message using the GOV.UK error summary component\n * and adds inline error styling to the file input\n * @param {string} message - The error message to display\n * @param {HTMLElement | null} errorSummary - The error summary container\n * @param {HTMLInputElement} fileInput - The file input element\n * @returns {void}\n */\nfunction showError(message, errorSummary, fileInput) {\n const topErrorSummary = document.querySelector('.govuk-error-summary')\n\n if (topErrorSummary) {\n const titleElement = document.getElementById(ERROR_SUMMARY_TITLE_ID)\n if (titleElement) {\n fileInput.setAttribute(ARIA_DESCRIBEDBY, ERROR_SUMMARY_TITLE_ID)\n } else {\n fileInput.removeAttribute(ARIA_DESCRIBEDBY)\n }\n return\n }\n\n if (errorSummary) {\n errorSummary.innerHTML = `\n <div class=\"govuk-error-summary\" data-module=\"govuk-error-summary\">\n <div role=\"alert\">\n <h2 class=\"govuk-error-summary__title\" id=\"${ERROR_SUMMARY_TITLE_ID}\">\n There is a problem\n </h2>\n <div class=\"govuk-error-summary__body\">\n <ul class=\"govuk-list govuk-error-summary__list\">\n <li>\n <a href=\"#file-upload\">${message}</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n `\n\n fileInput.setAttribute(ARIA_DESCRIBEDBY, ERROR_SUMMARY_TITLE_ID)\n }\n\n const formGroup = fileInput.closest('.govuk-form-group')\n if (formGroup) {\n formGroup.classList.add('govuk-form-group--error')\n fileInput.classList.add('govuk-file-upload--error')\n\n const inputId = fileInput.id\n let errorMessage = document.getElementById(`${inputId}-error`)\n\n if (!errorMessage) {\n errorMessage = document.createElement('p')\n errorMessage.id = `${inputId}-error`\n errorMessage.className = 'govuk-error-message'\n errorMessage.innerHTML = `<span class=\"govuk-visually-hidden\">Error:</span> ${message}`\n formGroup.insertBefore(errorMessage, fileInput)\n }\n\n fileInput.setAttribute(\n ARIA_DESCRIBEDBY,\n `error-summary-title ${inputId}-error`\n )\n }\n}\n\n/**\n * Helper to safely convert an Element to HTMLElement\n * @param {Element | null} element - The element to convert\n */\nfunction asHTMLElement(element) {\n return /** @type {HTMLElement} */ (element)\n}\n\nfunction reloadPage() {\n window.history.replaceState(null, '', window.location.href)\n window.location.href = window.location.pathname\n}\n\n/**\n * Build the upload status URL given the current pathname and the upload ID.\n * @param {string} pathname – e.g. window.location.pathname\n * @param {string} uploadId\n * @returns {string} e.g. \"/form/upload-status/abc123\"\n */\nexport function buildUploadStatusUrl(pathname, uploadId) {\n const pathSegments = pathname.split('/').filter((segment) => segment)\n const prefix = pathSegments.length > 0 ? `/${pathSegments[0]}` : ''\n return `${prefix}/upload-status/${uploadId}`\n}\n\n/**\n * Polls the upload status endpoint until the file is ready or timeout occurs\n * @param {string} uploadId - The upload ID to check\n */\nfunction pollUploadStatus(uploadId) {\n let attempts = 0\n const interval = setInterval(() => {\n attempts++\n\n if (attempts >= MAX_POLLING_DURATION) {\n clearInterval(interval)\n reloadPage()\n return\n }\n\n const uploadStatusUrl = buildUploadStatusUrl(\n window.location.pathname,\n uploadId\n )\n\n fetch(uploadStatusUrl, {\n headers: {\n Accept: 'application/json'\n }\n })\n .then((response) => {\n if (!response.ok) {\n throw new Error('Network response was not ok')\n }\n return response.json()\n })\n .then((data) => {\n if (data.uploadStatus === 'ready') {\n clearInterval(interval)\n reloadPage()\n }\n })\n .catch(() => {\n clearInterval(interval)\n reloadPage()\n })\n }, 1000)\n}\n\n/**\n * Handle standard form submission for file upload\n * @param {HTMLFormElement} formElement - The form element\n * @param {HTMLInputElement} fileInput - The file input element\n * @param {HTMLButtonElement} uploadButton - The upload button\n * @param {HTMLButtonElement} continueButton - The continue button\n * @param {File | null} selectedFile - The selected file\n */\nfunction handleStandardFormSubmission(\n formElement,\n fileInput,\n uploadButton,\n continueButton,\n selectedFile\n) {\n renderSummary(selectedFile, 'Uploading…', formElement)\n\n fileInput.focus()\n\n setTimeout(() => {\n fileInput.disabled = true\n uploadButton.disabled = true\n continueButton.disabled = true\n }, 100)\n}\n\n/**\n * Handle AJAX form submission with upload ID\n * @param {Event} event - The click event\n * @param {HTMLFormElement} formElement - The form element\n * @param {HTMLInputElement} fileInput - The file input element\n * @param {HTMLButtonElement} uploadButton - The upload button\n * @param {HTMLElement | null} errorSummary - The error summary container\n * @param {string | undefined} uploadId - The upload ID\n * @returns {boolean} Whether the event was handled\n */\nfunction handleAjaxFormSubmission(\n event,\n formElement,\n fileInput,\n uploadButton,\n errorSummary,\n uploadId\n) {\n if (!formElement.action || !uploadId) {\n return false\n }\n\n event.preventDefault()\n\n const formData = new FormData(formElement)\n const isLocalDev = !!formElement.dataset.proxyUrl\n const uploadUrl = formElement.dataset.proxyUrl ?? formElement.action\n\n const fetchOptions = /** @type {RequestInit} */ ({\n method: 'POST',\n body: formData,\n redirect: isLocalDev ? 'follow' : 'manual' // follow mode if local development with the proxy\n })\n\n // no-cors mode if needed local development with the proxy\n if (isLocalDev) {\n fetchOptions.mode = 'no-cors'\n }\n\n fetch(uploadUrl, fetchOptions)\n .then(() => {\n pollUploadStatus(uploadId)\n })\n .catch(() => {\n fileInput.disabled = false\n uploadButton.disabled = false\n\n showError(\n 'There was a problem uploading the file',\n errorSummary,\n fileInput\n )\n\n return null\n })\n\n return true\n}\n\nexport function initFileUpload() {\n const form = document.querySelector('form:has(input[type=\"file\"])')\n /** @type {HTMLInputElement | null} */\n const fileInput = form ? form.querySelector('input[type=\"file\"]') : null\n /** @type {HTMLButtonElement | null} */\n const uploadButton = form ? form.querySelector('.upload-file-button') : null\n const continueButton =\n /** @type {HTMLButtonElement} */ (\n Array.from(document.querySelectorAll('button.govuk-button')).find(\n (button) => button.textContent?.trim() === 'Continue'\n )\n ) ?? null\n\n const errorSummary = document.querySelector('.govuk-error-summary-container')\n\n if (!form || !fileInput || !uploadButton) {\n return\n }\n\n const formElement = /** @type {HTMLFormElement} */ (form)\n /** @type {File | null} */\n let selectedFile = null\n let isSubmitting = false\n const uploadId = formElement.dataset.uploadId\n\n fileInput.addEventListener('change', () => {\n if (errorSummary) {\n errorSummary.innerHTML = ''\n }\n\n if (fileInput.files && fileInput.files.length > 0) {\n selectedFile = fileInput.files[0]\n }\n })\n\n uploadButton.addEventListener('click', (event) => {\n if (!selectedFile) {\n event.preventDefault()\n showError(\n 'Select a file',\n /** @type {HTMLElement | null} */ (errorSummary),\n fileInput\n )\n return\n }\n\n if (isSubmitting) {\n event.preventDefault()\n return\n }\n\n isSubmitting = true\n\n handleStandardFormSubmission(\n formElement,\n fileInput,\n uploadButton,\n continueButton,\n selectedFile\n )\n\n handleAjaxFormSubmission(\n event,\n formElement,\n fileInput,\n uploadButton,\n /** @type {HTMLElement | null} */ (errorSummary),\n uploadId\n )\n })\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"file-upload.js","names":["MAX_POLLING_DURATION","ARIA_DESCRIBEDBY","ERROR_SUMMARY_TITLE_ID","createOrUpdateStatusAnnouncer","form","fileCountP","statusAnnouncer","querySelector","document","createElement","id","className","setAttribute","addStatusAnnouncerToDOM","asHTMLElement","appendChild","body","nextSibling","parentNode","insertBefore","parentElement","findOrCreateSummaryList","summaryList","continueButton","createFileRow","selectedFile","statusText","row","name","innerHTML","renderSummary","container","getElementById","uploadForm","closest","HTMLFormElement","fileInput","existingRow","remove","firstChild","textContent","showError","message","errorSummary","topErrorSummary","titleElement","removeAttribute","formGroup","classList","add","inputId","errorMessage","element","reloadPage","window","history","replaceState","location","href","pathname","buildUploadStatusUrl","uploadId","pathSegments","split","filter","segment","prefix","length","pollUploadStatus","attempts","interval","setInterval","clearInterval","uploadStatusUrl","fetch","headers","Accept","then","response","ok","Error","json","data","uploadStatus","catch","handleStandardFormSubmission","formElement","uploadButton","focus","setTimeout","disabled","handleAjaxFormSubmission","event","action","preventDefault","formData","FormData","isLocalDev","dataset","proxyUrl","uploadUrl","fetchOptions","method","redirect","mode","initUpload","Array","from","querySelectorAll","find","button","trim","isSubmitting","addEventListener","files","initFileUpload","readyState"],"sources":["../../../src/client/javascripts/file-upload.js"],"sourcesContent":["export const MAX_POLLING_DURATION = 300 // 5 minutes\nconst ARIA_DESCRIBEDBY = 'aria-describedby'\nconst ERROR_SUMMARY_TITLE_ID = 'error-summary-title'\n\n/**\n * Creates or updates status announcer for screen readers\n * @param {HTMLElement | null} form - The form element\n * @param {HTMLElement | null} fileCountP - The file count paragraph element\n * @returns {HTMLElement} The status announcer element\n */\nfunction createOrUpdateStatusAnnouncer(form, fileCountP) {\n let statusAnnouncer = form?.querySelector('#statusInformation')\n\n if (!statusAnnouncer) {\n statusAnnouncer = document.createElement('div')\n statusAnnouncer.id = 'statusInformation'\n statusAnnouncer.className = 'govuk-visually-hidden'\n statusAnnouncer.setAttribute('aria-live', 'polite')\n\n // multiple fallbacks to ensure the status announcer is always added to the DOM\n // this helps with cross-browser compatibility and unexpected DOM structures encountered during QA\n try {\n addStatusAnnouncerToDOM(\n asHTMLElement(form),\n asHTMLElement(fileCountP),\n asHTMLElement(statusAnnouncer)\n )\n } catch {\n try {\n form?.appendChild(statusAnnouncer)\n } catch {\n document.body.appendChild(statusAnnouncer)\n }\n }\n }\n\n return /** @type {HTMLElement} */ (statusAnnouncer)\n}\n\n/**\n * Helper function to add the status announcer to the DOM\n * @param {HTMLElement} form - The form element\n * @param {HTMLElement | null} fileCountP - The file count paragraph element\n * @param {HTMLElement} statusAnnouncer - The status announcer element to add\n */\nfunction addStatusAnnouncerToDOM(form, fileCountP, statusAnnouncer) {\n if (fileCountP?.nextSibling && fileCountP.parentNode === form) {\n form.insertBefore(statusAnnouncer, fileCountP.nextSibling)\n return\n }\n\n const parentElement = fileCountP?.parentNode ?? form\n parentElement.appendChild(statusAnnouncer)\n}\n\n/**\n * Finds an existing summary list or creates a new one\n * @param {HTMLFormElement} form - The form element\n * @param {HTMLElement} fileCountP - The file count paragraph element\n * @returns {HTMLElement} The summary list element\n */\nfunction findOrCreateSummaryList(form, fileCountP) {\n let summaryList = form.querySelector('dl.govuk-summary-list')\n\n if (!summaryList) {\n summaryList = document.createElement('dl')\n summaryList.className = 'govuk-summary-list govuk-summary-list--long-key'\n\n const continueButton = form.querySelector('.govuk-button')\n\n if (continueButton) {\n form.insertBefore(summaryList, continueButton)\n } else {\n form.insertBefore(summaryList, fileCountP.nextSibling)\n }\n }\n\n return /** @type {HTMLElement} */ (summaryList)\n}\n\n/**\n * Creates a file row element for the summary list\n * @param {File | null} selectedFile - The selected file\n * @param {string} statusText - The status to display\n * @returns {HTMLElement} The created row element\n */\nfunction createFileRow(selectedFile, statusText) {\n const row = document.createElement('div')\n row.className = 'govuk-summary-list__row'\n row.setAttribute('data-filename', selectedFile?.name ?? '')\n row.innerHTML = `\n <dt class=\"govuk-summary-list__key\">\n ${selectedFile?.name ?? ''}\n </dt>\n <dd class=\"govuk-summary-list__value\">\n <strong class=\"govuk-tag govuk-tag--yellow\">${statusText}</strong>\n </dd>\n <dd class=\"govuk-summary-list__actions\">\n </dd>\n `\n return row\n}\n\n/**\n * Renders or updates the file summary box for the selected file\n * @param {File | null} selectedFile - The selected file\n * @param {string} statusText - The status to display\n * @param {HTMLElement} form - The form element\n */\nfunction renderSummary(selectedFile, statusText, form) {\n const container = document.getElementById('uploadedFilesContainer')\n const uploadForm = container ? container.closest('form') : null\n\n if (!uploadForm || !(uploadForm instanceof HTMLFormElement)) {\n return\n }\n\n const fileCountP = uploadForm.querySelector('p.govuk-body')\n\n if (!fileCountP) {\n return\n }\n\n const statusAnnouncer = createOrUpdateStatusAnnouncer(\n /** @type {HTMLElement} */ (uploadForm),\n /** @type {HTMLElement | null} */ (fileCountP)\n )\n\n const fileInput = form.querySelector('input[type=\"file\"]')\n\n if (fileInput) {\n fileInput.setAttribute(ARIA_DESCRIBEDBY, 'statusInformation')\n }\n\n const summaryList = findOrCreateSummaryList(\n /** @type {HTMLFormElement} */ (uploadForm),\n /** @type {HTMLElement} */ (fileCountP)\n )\n\n const existingRow = document.querySelector(\n `[data-filename=\"${selectedFile?.name}\"]`\n )\n\n if (existingRow) {\n existingRow.remove()\n }\n\n const row = createFileRow(selectedFile, statusText)\n summaryList.insertBefore(row, summaryList.firstChild)\n statusAnnouncer.textContent = `${selectedFile?.name ?? ''} ${statusText}`\n}\n\n/**\n * Shows an error message using the GOV.UK error summary component\n * and adds inline error styling to the file input\n * @param {string} message - The error message to display\n * @param {HTMLElement | null} errorSummary - The error summary container\n * @param {HTMLInputElement} fileInput - The file input element\n * @returns {void}\n */\nfunction showError(message, errorSummary, fileInput) {\n const topErrorSummary = document.querySelector('.govuk-error-summary')\n\n if (topErrorSummary) {\n const titleElement = document.getElementById(ERROR_SUMMARY_TITLE_ID)\n if (titleElement) {\n fileInput.setAttribute(ARIA_DESCRIBEDBY, ERROR_SUMMARY_TITLE_ID)\n } else {\n fileInput.removeAttribute(ARIA_DESCRIBEDBY)\n }\n return\n }\n\n if (errorSummary) {\n errorSummary.innerHTML = `\n <div class=\"govuk-error-summary\" data-module=\"govuk-error-summary\">\n <div role=\"alert\">\n <h2 class=\"govuk-error-summary__title\" id=\"${ERROR_SUMMARY_TITLE_ID}\">\n There is a problem\n </h2>\n <div class=\"govuk-error-summary__body\">\n <ul class=\"govuk-list govuk-error-summary__list\">\n <li>\n <a href=\"#file-upload\">${message}</a>\n </li>\n </ul>\n </div>\n </div>\n </div>\n `\n\n fileInput.setAttribute(ARIA_DESCRIBEDBY, ERROR_SUMMARY_TITLE_ID)\n }\n\n const formGroup = fileInput.closest('.govuk-form-group')\n if (formGroup) {\n formGroup.classList.add('govuk-form-group--error')\n fileInput.classList.add('govuk-file-upload--error')\n\n const inputId = fileInput.id\n let errorMessage = document.getElementById(`${inputId}-error`)\n\n if (!errorMessage) {\n errorMessage = document.createElement('p')\n errorMessage.id = `${inputId}-error`\n errorMessage.className = 'govuk-error-message'\n errorMessage.innerHTML = `<span class=\"govuk-visually-hidden\">Error:</span> ${message}`\n formGroup.insertBefore(errorMessage, fileInput)\n }\n\n fileInput.setAttribute(\n ARIA_DESCRIBEDBY,\n `error-summary-title ${inputId}-error`\n )\n }\n}\n\n/**\n * Helper to safely convert an Element to HTMLElement\n * @param {Element | null} element - The element to convert\n */\nfunction asHTMLElement(element) {\n return /** @type {HTMLElement} */ (element)\n}\n\nfunction reloadPage() {\n window.history.replaceState(null, '', window.location.href)\n window.location.href = window.location.pathname\n}\n\n/**\n * Build the upload status URL given the current pathname and the upload ID.\n * @param {string} pathname – e.g. window.location.pathname\n * @param {string} uploadId\n * @returns {string} e.g. \"/form/upload-status/abc123\"\n */\nexport function buildUploadStatusUrl(pathname, uploadId) {\n const pathSegments = pathname.split('/').filter((segment) => segment)\n const prefix = pathSegments.length > 0 ? `/${pathSegments[0]}` : ''\n return `${prefix}/upload-status/${uploadId}`\n}\n\n/**\n * Polls the upload status endpoint until the file is ready or timeout occurs\n * @param {string} uploadId - The upload ID to check\n */\nfunction pollUploadStatus(uploadId) {\n let attempts = 0\n const interval = setInterval(() => {\n attempts++\n\n if (attempts >= MAX_POLLING_DURATION) {\n clearInterval(interval)\n reloadPage()\n return\n }\n\n const uploadStatusUrl = buildUploadStatusUrl(\n window.location.pathname,\n uploadId\n )\n\n fetch(uploadStatusUrl, {\n headers: {\n Accept: 'application/json'\n }\n })\n .then((response) => {\n if (!response.ok) {\n throw new Error('Network response was not ok')\n }\n return response.json()\n })\n .then((data) => {\n if (data.uploadStatus === 'ready') {\n clearInterval(interval)\n reloadPage()\n }\n })\n .catch(() => {\n clearInterval(interval)\n reloadPage()\n })\n }, 1000)\n}\n\n/**\n * Handle standard form submission for file upload\n * @param {HTMLFormElement} formElement - The form element\n * @param {HTMLInputElement} fileInput - The file input element\n * @param {HTMLButtonElement} uploadButton - The upload button\n * @param {HTMLButtonElement} continueButton - The continue button\n * @param {File | null} selectedFile - The selected file\n */\nfunction handleStandardFormSubmission(\n formElement,\n fileInput,\n uploadButton,\n continueButton,\n selectedFile\n) {\n renderSummary(selectedFile, 'Uploading…', formElement)\n\n fileInput.focus()\n\n setTimeout(() => {\n fileInput.disabled = true\n uploadButton.disabled = true\n continueButton.disabled = true\n }, 100)\n}\n\n/**\n * Handle AJAX form submission with upload ID\n * @param {Event} event - The click event\n * @param {HTMLFormElement} formElement - The form element\n * @param {HTMLInputElement} fileInput - The file input element\n * @param {HTMLButtonElement} uploadButton - The upload button\n * @param {HTMLElement | null} errorSummary - The error summary container\n * @param {string | undefined} uploadId - The upload ID\n * @returns {boolean} Whether the event was handled\n */\nfunction handleAjaxFormSubmission(\n event,\n formElement,\n fileInput,\n uploadButton,\n errorSummary,\n uploadId\n) {\n if (!formElement.action || !uploadId) {\n return false\n }\n\n event.preventDefault()\n\n const formData = new FormData(formElement)\n const isLocalDev = !!formElement.dataset.proxyUrl\n const uploadUrl = formElement.dataset.proxyUrl ?? formElement.action\n\n const fetchOptions = /** @type {RequestInit} */ ({\n method: 'POST',\n body: formData,\n redirect: isLocalDev ? 'follow' : 'manual' // follow mode if local development with the proxy\n })\n\n // no-cors mode if needed local development with the proxy\n if (isLocalDev) {\n fetchOptions.mode = 'no-cors'\n }\n\n fetch(uploadUrl, fetchOptions)\n .then(() => {\n pollUploadStatus(uploadId)\n })\n .catch(() => {\n fileInput.disabled = false\n uploadButton.disabled = false\n\n showError(\n 'There was a problem uploading the file',\n errorSummary,\n fileInput\n )\n\n return null\n })\n\n return true\n}\n\nfunction initUpload() {\n const form = document.querySelector('form:has(input[type=\"file\"])')\n /** @type {HTMLInputElement | null} */\n const fileInput = form ? form.querySelector('input[type=\"file\"]') : null\n /** @type {HTMLButtonElement | null} */\n const uploadButton = form ? form.querySelector('.upload-file-button') : null\n const continueButton =\n /** @type {HTMLButtonElement} */ (\n Array.from(document.querySelectorAll('button.govuk-button')).find(\n (button) => button.textContent?.trim() === 'Continue'\n )\n ) ?? null\n\n const errorSummary = document.querySelector('.govuk-error-summary-container')\n\n if (!form || !fileInput || !uploadButton) {\n return\n }\n\n const formElement = /** @type {HTMLFormElement} */ (form)\n /** @type {File | null} */\n let selectedFile = null\n let isSubmitting = false\n const uploadId = formElement.dataset.uploadId\n\n fileInput.addEventListener('change', () => {\n if (errorSummary) {\n errorSummary.innerHTML = ''\n }\n\n if (fileInput.files && fileInput.files.length > 0) {\n selectedFile = fileInput.files[0]\n }\n })\n\n uploadButton.addEventListener('click', (event) => {\n if (!selectedFile) {\n event.preventDefault()\n showError(\n 'Select a file',\n /** @type {HTMLElement | null} */ (errorSummary),\n fileInput\n )\n return\n }\n\n if (isSubmitting) {\n event.preventDefault()\n return\n }\n\n isSubmitting = true\n\n handleStandardFormSubmission(\n formElement,\n fileInput,\n uploadButton,\n continueButton,\n selectedFile\n )\n\n handleAjaxFormSubmission(\n event,\n formElement,\n fileInput,\n uploadButton,\n /** @type {HTMLElement | null} */ (errorSummary),\n uploadId\n )\n })\n}\n\nexport function initFileUpload() {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', initUpload)\n } else {\n initUpload()\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export function initAllGovuk(): void;
@@ -0,0 +1,12 @@
1
+ import { Button, CharacterCount, Checkboxes, ErrorSummary, Header, NotificationBanner, Radios, SkipLink, createAll } from 'govuk-frontend';
2
+ export function initAllGovuk() {
3
+ createAll(Button);
4
+ createAll(CharacterCount);
5
+ createAll(Checkboxes);
6
+ createAll(ErrorSummary);
7
+ createAll(Header);
8
+ createAll(NotificationBanner);
9
+ createAll(Radios);
10
+ createAll(SkipLink);
11
+ }
12
+ //# sourceMappingURL=govuk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"govuk.js","names":["Button","CharacterCount","Checkboxes","ErrorSummary","Header","NotificationBanner","Radios","SkipLink","createAll","initAllGovuk"],"sources":["../../../src/client/javascripts/govuk.js"],"sourcesContent":["import {\n Button,\n CharacterCount,\n Checkboxes,\n ErrorSummary,\n Header,\n NotificationBanner,\n Radios,\n SkipLink,\n createAll\n} from 'govuk-frontend'\n\nexport function initAllGovuk() {\n createAll(Button)\n createAll(CharacterCount)\n createAll(Checkboxes)\n createAll(ErrorSummary)\n createAll(Header)\n createAll(NotificationBanner)\n createAll(Radios)\n createAll(SkipLink)\n}\n"],"mappings":"AAAA,SACEA,MAAM,EACNC,cAAc,EACdC,UAAU,EACVC,YAAY,EACZC,MAAM,EACNC,kBAAkB,EAClBC,MAAM,EACNC,QAAQ,EACRC,SAAS,QACJ,gBAAgB;AAEvB,OAAO,SAASC,YAAYA,CAAA,EAAG;EAC7BD,SAAS,CAACR,MAAM,CAAC;EACjBQ,SAAS,CAACP,cAAc,CAAC;EACzBO,SAAS,CAACN,UAAU,CAAC;EACrBM,SAAS,CAACL,YAAY,CAAC;EACvBK,SAAS,CAACJ,MAAM,CAAC;EACjBI,SAAS,CAACH,kBAAkB,CAAC;EAC7BG,SAAS,CAACF,MAAM,CAAC;EACjBE,SAAS,CAACD,QAAQ,CAAC;AACrB","ignoreList":[]}
@@ -0,0 +1 @@
1
+ export function initPreviewCloseLink(): void;
@@ -0,0 +1,12 @@
1
+ export function initPreviewCloseLink() {
2
+ // Show preview close link via `rel="opener"`
3
+ if (window.opener) {
4
+ const $closeLink = document.querySelector('.js-preview-banner-close');
5
+ $closeLink?.removeAttribute('hidden');
6
+ $closeLink?.addEventListener('click', event => {
7
+ event.preventDefault();
8
+ window.close();
9
+ });
10
+ }
11
+ }
12
+ //# sourceMappingURL=preview-close-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-close-link.js","names":["initPreviewCloseLink","window","opener","$closeLink","document","querySelector","removeAttribute","addEventListener","event","preventDefault","close"],"sources":["../../../src/client/javascripts/preview-close-link.js"],"sourcesContent":["export function initPreviewCloseLink() {\n // Show preview close link via `rel=\"opener\"`\n if (window.opener) {\n const $closeLink = document.querySelector('.js-preview-banner-close')\n\n $closeLink?.removeAttribute('hidden')\n $closeLink?.addEventListener('click', (event) => {\n event.preventDefault()\n window.close()\n })\n }\n}\n"],"mappings":"AAAA,OAAO,SAASA,oBAAoBA,CAAA,EAAG;EACrC;EACA,IAAIC,MAAM,CAACC,MAAM,EAAE;IACjB,MAAMC,UAAU,GAAGC,QAAQ,CAACC,aAAa,CAAC,0BAA0B,CAAC;IAErEF,UAAU,EAAEG,eAAe,CAAC,QAAQ,CAAC;IACrCH,UAAU,EAAEI,gBAAgB,CAAC,OAAO,EAAGC,KAAK,IAAK;MAC/CA,KAAK,CAACC,cAAc,CAAC,CAAC;MACtBR,MAAM,CAACS,KAAK,CAAC,CAAC;IAChB,CAAC,CAAC;EACJ;AACF","ignoreList":[]}
@@ -0,0 +1,9 @@
1
+ export function initAll(): void;
2
+ export const initAllGovuk: typeof initAllGovukImp;
3
+ export const initAllAutocomplete: typeof initAllAutocompleteImp;
4
+ export const initFileUpload: typeof initFileUploadImp;
5
+ export const initPreviewCloseLink: typeof initPreviewCloseLinkImp;
6
+ import { initAllGovuk as initAllGovukImp } from '~/src/client/javascripts/govuk.js';
7
+ import { initAllAutocomplete as initAllAutocompleteImp } from '~/src/client/javascripts/autocomplete.js';
8
+ import { initFileUpload as initFileUploadImp } from '~/src/client/javascripts/file-upload.js';
9
+ import { initPreviewCloseLink as initPreviewCloseLinkImp } from '~/src/client/javascripts/preview-close-link.js';
@@ -0,0 +1,15 @@
1
+ import { initAllAutocomplete as initAllAutocompleteImp } from "./autocomplete.js";
2
+ import { initFileUpload as initFileUploadImp } from "./file-upload.js";
3
+ import { initAllGovuk as initAllGovukImp } from "./govuk.js";
4
+ import { initPreviewCloseLink as initPreviewCloseLinkImp } from "./preview-close-link.js";
5
+ export const initAllGovuk = initAllGovukImp;
6
+ export const initAllAutocomplete = initAllAutocompleteImp;
7
+ export const initFileUpload = initFileUploadImp;
8
+ export const initPreviewCloseLink = initPreviewCloseLinkImp;
9
+ export function initAll() {
10
+ initAllGovuk();
11
+ initAllAutocomplete();
12
+ initFileUpload();
13
+ initPreviewCloseLink();
14
+ }
15
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","names":["initAllAutocomplete","initAllAutocompleteImp","initFileUpload","initFileUploadImp","initAllGovuk","initAllGovukImp","initPreviewCloseLink","initPreviewCloseLinkImp","initAll"],"sources":["../../../src/client/javascripts/shared.js"],"sourcesContent":["import { initAllAutocomplete as initAllAutocompleteImp } from '~/src/client/javascripts/autocomplete.js'\nimport { initFileUpload as initFileUploadImp } from '~/src/client/javascripts/file-upload.js'\nimport { initAllGovuk as initAllGovukImp } from '~/src/client/javascripts/govuk.js'\nimport { initPreviewCloseLink as initPreviewCloseLinkImp } from '~/src/client/javascripts/preview-close-link.js'\n\nexport const initAllGovuk = initAllGovukImp\nexport const initAllAutocomplete = initAllAutocompleteImp\nexport const initFileUpload = initFileUploadImp\nexport const initPreviewCloseLink = initPreviewCloseLinkImp\n\nexport function initAll() {\n initAllGovuk()\n initAllAutocomplete()\n initFileUpload()\n initPreviewCloseLink()\n}\n"],"mappings":"AAAA,SAASA,mBAAmB,IAAIC,sBAAsB;AACtD,SAASC,cAAc,IAAIC,iBAAiB;AAC5C,SAASC,YAAY,IAAIC,eAAe;AACxC,SAASC,oBAAoB,IAAIC,uBAAuB;AAExD,OAAO,MAAMH,YAAY,GAAGC,eAAe;AAC3C,OAAO,MAAML,mBAAmB,GAAGC,sBAAsB;AACzD,OAAO,MAAMC,cAAc,GAAGC,iBAAiB;AAC/C,OAAO,MAAMG,oBAAoB,GAAGC,uBAAuB;AAE3D,OAAO,SAASC,OAAOA,CAAA,EAAG;EACxBJ,YAAY,CAAC,CAAC;EACdJ,mBAAmB,CAAC,CAAC;EACrBE,cAAc,CAAC,CAAC;EAChBI,oBAAoB,CAAC,CAAC;AACxB","ignoreList":[]}
@@ -21,4 +21,13 @@
21
21
  margin: 0 0 0 govuk-spacing(2);
22
22
  }
23
23
  }
24
+
25
+ &-rebrand {
26
+ vertical-align: middle;
27
+
28
+ // Align with product name
29
+ @include govuk-media-query($from: tablet) {
30
+ margin: -3px 0 2px;
31
+ }
32
+ }
24
33
  }
@@ -11,6 +11,7 @@ export declare const config: convict.Config<{
11
11
  isProduction: boolean;
12
12
  isDevelopment: boolean;
13
13
  isTest: boolean;
14
+ showRebrand: boolean;
14
15
  serviceName: string;
15
16
  serviceVersion: SchemaObj<string>;
16
17
  feedbackLink: SchemaObj<string>;
@@ -58,6 +58,15 @@ export const config = convict({
58
58
  format: Boolean,
59
59
  default: isTest
60
60
  },
61
+ /**
62
+ * Feature flags
63
+ */
64
+ showRebrand: {
65
+ doc: 'If this app should show the 2025 rebrand',
66
+ format: Boolean,
67
+ env: 'SHOW_GOVUK_REBRAND',
68
+ default: false
69
+ },
61
70
  /**
62
71
  * Service
63
72
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["resolve","convict","isProduction","process","env","NODE_ENV","isDev","isTest","oneMinute","oneHour","config","appDir","format","String","default","import","meta","dirname","publicDir","port","doc","cdpEnvironment","enforceCsrf","Boolean","isDevelopment","serviceName","serviceVersion","nullable","feedbackLink","phaseTag","sessionTimeout","Number","confirmationSessionTimeout","sessionCookiePassword","sensitive","redis","host","username","password","keyPrefix","tracing","header","notifyTemplateId","notifyAPIKey","designerUrl","submissionUrl","uploaderUrl","uploaderBucketName","log","enabled","level","redact","Array","safelist","stagingPrefix","submissionEmailAddress","validate","allowed"],"sources":["../../src/config/index.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport convict, { type SchemaObj } from 'convict'\nimport { type LevelWithSilent } from 'pino'\n\nimport 'dotenv/config'\n\nconst isProduction = process.env.NODE_ENV === 'production'\nconst isDev = process.env.NODE_ENV !== 'production'\nconst isTest = process.env.NODE_ENV === 'test'\n\nconst oneMinute = 1000 * 60\nconst oneHour = oneMinute * 60\n\nexport const config = convict({\n appDir: {\n format: String,\n default: resolve(import.meta.dirname, '../server')\n },\n publicDir: {\n format: String,\n default: isTest\n ? resolve(import.meta.dirname, '../../test/fixtures')\n : resolve(import.meta.dirname, '../../.public')\n },\n\n /**\n * Server\n */\n port: {\n format: 'port',\n default: 3009,\n env: 'PORT'\n },\n env: {\n doc: 'The application environment.',\n format: ['production', 'development', 'test'],\n default: 'development',\n env: 'NODE_ENV'\n },\n cdpEnvironment: {\n doc: 'The CDP environment the app is currently in, with the addition of \"local\"',\n format: [\n 'local',\n 'infra-dev',\n 'management',\n 'dev',\n 'test',\n 'perf-test',\n 'ext-test',\n 'prod'\n ],\n default: 'local',\n env: 'ENVIRONMENT'\n },\n enforceCsrf: {\n format: Boolean,\n default: isProduction,\n env: 'ENFORCE_CSRF'\n },\n\n /**\n * Helper flags\n */\n isProduction: {\n doc: 'If this application running in the production environment',\n format: Boolean,\n default: isProduction\n },\n isDevelopment: {\n doc: 'If this application running in the development environment',\n format: Boolean,\n default: isDev\n },\n isTest: {\n doc: 'If this application running in the test environment',\n format: Boolean,\n default: isTest\n },\n\n /**\n * Service\n */\n serviceName: {\n doc: 'Applications Service Name',\n format: String,\n default: 'Digital Express Toolkit'\n },\n serviceVersion: {\n doc: 'The service version, this variable is injected into your docker container in CDP environments',\n format: String,\n nullable: true,\n default: '',\n env: 'SERVICE_VERSION'\n } as SchemaObj<string>,\n feedbackLink: {\n doc: 'Used in your phase banner. Can be a URL or more commonly mailto mailto:feedback@department.gov.uk',\n format: String,\n default: '',\n env: 'FEEDBACK_LINK'\n } as SchemaObj<string>,\n phaseTag: {\n format: String,\n default: 'beta', // Accepts \"alpha\" |\"beta\" | \"\"\n env: 'PHASE_TAG'\n },\n\n /**\n * Session storage\n * Redis integration is optional, but recommended for production environments.\n */\n sessionTimeout: {\n format: Number,\n default: oneHour * 24, // 1 day\n env: 'SESSION_TIMEOUT'\n },\n confirmationSessionTimeout: {\n format: Number,\n default: oneMinute * 20,\n env: 'CONFIRMATION_SESSION_TIMEOUT'\n },\n sessionCookiePassword: {\n format: String,\n default: '',\n sensitive: true,\n env: 'SESSION_COOKIE_PASSWORD'\n } as SchemaObj<string>,\n redis: {\n host: {\n doc: 'Redis cache host',\n format: String,\n default: '',\n env: 'REDIS_HOST'\n } as SchemaObj<string>,\n username: {\n doc: 'Redis cache username',\n format: String,\n default: '',\n env: 'REDIS_USERNAME'\n } as SchemaObj<string>,\n password: {\n doc: 'Redis cache password',\n format: '*',\n default: '',\n sensitive: true,\n env: 'REDIS_PASSWORD'\n } as SchemaObj<string>,\n keyPrefix: {\n doc: 'Redis cache key prefix name used to isolate the cached results across multiple clients',\n format: String,\n default: '',\n env: 'REDIS_KEY_PREFIX'\n } as SchemaObj<string>\n },\n tracing: {\n header: {\n doc: 'Tracing header name',\n format: String,\n default: 'x-cdp-request-id',\n env: 'TRACING_HEADER'\n } as SchemaObj<string>\n },\n\n /**\n * Email outputs\n * Email outputs will use notify to send an email to a single inbox.\n */\n notifyTemplateId: {\n format: String,\n default: '',\n env: 'NOTIFY_TEMPLATE_ID'\n } as SchemaObj<string>,\n notifyAPIKey: {\n format: String,\n default: '',\n env: 'NOTIFY_API_KEY'\n } as SchemaObj<string>,\n\n /**\n * API integrations\n */\n designerUrl: {\n format: String,\n default: 'http://localhost:3000',\n env: 'DESIGNER_URL'\n } as SchemaObj<string>,\n\n submissionUrl: {\n format: String,\n default: 'http://localhost:3002',\n env: 'SUBMISSION_URL'\n } as SchemaObj<string>,\n\n uploaderUrl: {\n format: String,\n default: 'http://localhost:7337',\n env: 'UPLOADER_URL'\n } as SchemaObj<string>,\n\n uploaderBucketName: {\n format: String,\n default: 'files',\n env: 'UPLOADER_BUCKET_NAME'\n },\n\n /**\n * Logging\n */\n log: {\n enabled: {\n doc: 'Is logging enabled',\n format: Boolean,\n default: !isTest,\n env: 'LOG_ENABLED'\n },\n level: {\n doc: 'Logging level',\n format: ['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'],\n default: 'info',\n env: 'LOG_LEVEL'\n } as SchemaObj<LevelWithSilent>,\n format: {\n doc: 'Format to output logs in.',\n format: ['ecs', 'pino-pretty'],\n default: isProduction ? 'ecs' : 'pino-pretty',\n env: 'LOG_FORMAT'\n } as SchemaObj<'ecs' | 'pino-pretty'>,\n redact: {\n doc: 'Log paths to redact',\n format: Array,\n default: isProduction\n ? ['req.headers.authorization', 'req.headers.cookie', 'res.headers']\n : ['req', 'res', 'responseTime']\n }\n },\n\n safelist: {\n format: Array,\n default: ['61bca17e-fe74-40e0-9c15-a901ad120eca.mock.pstmn.io'],\n env: 'SAFELIST'\n },\n\n stagingPrefix: {\n doc: 'Prefix for staging files in S3',\n format: String,\n default: 'staging',\n env: 'STAGING_PREFIX'\n },\n\n submissionEmailAddress: {\n doc: 'Email address to send the form to (local devtool only)',\n format: String,\n default: '',\n env: 'SUBMISSION_EMAIL_ADDRESS'\n } as SchemaObj<string>\n})\n\nconfig.validate({ allowed: 'strict' })\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["resolve","convict","isProduction","process","env","NODE_ENV","isDev","isTest","oneMinute","oneHour","config","appDir","format","String","default","import","meta","dirname","publicDir","port","doc","cdpEnvironment","enforceCsrf","Boolean","isDevelopment","showRebrand","serviceName","serviceVersion","nullable","feedbackLink","phaseTag","sessionTimeout","Number","confirmationSessionTimeout","sessionCookiePassword","sensitive","redis","host","username","password","keyPrefix","tracing","header","notifyTemplateId","notifyAPIKey","designerUrl","submissionUrl","uploaderUrl","uploaderBucketName","log","enabled","level","redact","Array","safelist","stagingPrefix","submissionEmailAddress","validate","allowed"],"sources":["../../src/config/index.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport convict, { type SchemaObj } from 'convict'\nimport { type LevelWithSilent } from 'pino'\n\nimport 'dotenv/config'\n\nconst isProduction = process.env.NODE_ENV === 'production'\nconst isDev = process.env.NODE_ENV !== 'production'\nconst isTest = process.env.NODE_ENV === 'test'\n\nconst oneMinute = 1000 * 60\nconst oneHour = oneMinute * 60\n\nexport const config = convict({\n appDir: {\n format: String,\n default: resolve(import.meta.dirname, '../server')\n },\n publicDir: {\n format: String,\n default: isTest\n ? resolve(import.meta.dirname, '../../test/fixtures')\n : resolve(import.meta.dirname, '../../.public')\n },\n\n /**\n * Server\n */\n port: {\n format: 'port',\n default: 3009,\n env: 'PORT'\n },\n env: {\n doc: 'The application environment.',\n format: ['production', 'development', 'test'],\n default: 'development',\n env: 'NODE_ENV'\n },\n cdpEnvironment: {\n doc: 'The CDP environment the app is currently in, with the addition of \"local\"',\n format: [\n 'local',\n 'infra-dev',\n 'management',\n 'dev',\n 'test',\n 'perf-test',\n 'ext-test',\n 'prod'\n ],\n default: 'local',\n env: 'ENVIRONMENT'\n },\n enforceCsrf: {\n format: Boolean,\n default: isProduction,\n env: 'ENFORCE_CSRF'\n },\n\n /**\n * Helper flags\n */\n isProduction: {\n doc: 'If this application running in the production environment',\n format: Boolean,\n default: isProduction\n },\n isDevelopment: {\n doc: 'If this application running in the development environment',\n format: Boolean,\n default: isDev\n },\n isTest: {\n doc: 'If this application running in the test environment',\n format: Boolean,\n default: isTest\n },\n\n /**\n * Feature flags\n */\n showRebrand: {\n doc: 'If this app should show the 2025 rebrand',\n format: Boolean,\n env: 'SHOW_GOVUK_REBRAND',\n default: false\n },\n\n /**\n * Service\n */\n serviceName: {\n doc: 'Applications Service Name',\n format: String,\n default: 'Digital Express Toolkit'\n },\n serviceVersion: {\n doc: 'The service version, this variable is injected into your docker container in CDP environments',\n format: String,\n nullable: true,\n default: '',\n env: 'SERVICE_VERSION'\n } as SchemaObj<string>,\n feedbackLink: {\n doc: 'Used in your phase banner. Can be a URL or more commonly mailto mailto:feedback@department.gov.uk',\n format: String,\n default: '',\n env: 'FEEDBACK_LINK'\n } as SchemaObj<string>,\n phaseTag: {\n format: String,\n default: 'beta', // Accepts \"alpha\" |\"beta\" | \"\"\n env: 'PHASE_TAG'\n },\n\n /**\n * Session storage\n * Redis integration is optional, but recommended for production environments.\n */\n sessionTimeout: {\n format: Number,\n default: oneHour * 24, // 1 day\n env: 'SESSION_TIMEOUT'\n },\n confirmationSessionTimeout: {\n format: Number,\n default: oneMinute * 20,\n env: 'CONFIRMATION_SESSION_TIMEOUT'\n },\n sessionCookiePassword: {\n format: String,\n default: '',\n sensitive: true,\n env: 'SESSION_COOKIE_PASSWORD'\n } as SchemaObj<string>,\n redis: {\n host: {\n doc: 'Redis cache host',\n format: String,\n default: '',\n env: 'REDIS_HOST'\n } as SchemaObj<string>,\n username: {\n doc: 'Redis cache username',\n format: String,\n default: '',\n env: 'REDIS_USERNAME'\n } as SchemaObj<string>,\n password: {\n doc: 'Redis cache password',\n format: '*',\n default: '',\n sensitive: true,\n env: 'REDIS_PASSWORD'\n } as SchemaObj<string>,\n keyPrefix: {\n doc: 'Redis cache key prefix name used to isolate the cached results across multiple clients',\n format: String,\n default: '',\n env: 'REDIS_KEY_PREFIX'\n } as SchemaObj<string>\n },\n tracing: {\n header: {\n doc: 'Tracing header name',\n format: String,\n default: 'x-cdp-request-id',\n env: 'TRACING_HEADER'\n } as SchemaObj<string>\n },\n\n /**\n * Email outputs\n * Email outputs will use notify to send an email to a single inbox.\n */\n notifyTemplateId: {\n format: String,\n default: '',\n env: 'NOTIFY_TEMPLATE_ID'\n } as SchemaObj<string>,\n notifyAPIKey: {\n format: String,\n default: '',\n env: 'NOTIFY_API_KEY'\n } as SchemaObj<string>,\n\n /**\n * API integrations\n */\n designerUrl: {\n format: String,\n default: 'http://localhost:3000',\n env: 'DESIGNER_URL'\n } as SchemaObj<string>,\n\n submissionUrl: {\n format: String,\n default: 'http://localhost:3002',\n env: 'SUBMISSION_URL'\n } as SchemaObj<string>,\n\n uploaderUrl: {\n format: String,\n default: 'http://localhost:7337',\n env: 'UPLOADER_URL'\n } as SchemaObj<string>,\n\n uploaderBucketName: {\n format: String,\n default: 'files',\n env: 'UPLOADER_BUCKET_NAME'\n },\n\n /**\n * Logging\n */\n log: {\n enabled: {\n doc: 'Is logging enabled',\n format: Boolean,\n default: !isTest,\n env: 'LOG_ENABLED'\n },\n level: {\n doc: 'Logging level',\n format: ['fatal', 'error', 'warn', 'info', 'debug', 'trace', 'silent'],\n default: 'info',\n env: 'LOG_LEVEL'\n } as SchemaObj<LevelWithSilent>,\n format: {\n doc: 'Format to output logs in.',\n format: ['ecs', 'pino-pretty'],\n default: isProduction ? 'ecs' : 'pino-pretty',\n env: 'LOG_FORMAT'\n } as SchemaObj<'ecs' | 'pino-pretty'>,\n redact: {\n doc: 'Log paths to redact',\n format: Array,\n default: isProduction\n ? ['req.headers.authorization', 'req.headers.cookie', 'res.headers']\n : ['req', 'res', 'responseTime']\n }\n },\n\n safelist: {\n format: Array,\n default: ['61bca17e-fe74-40e0-9c15-a901ad120eca.mock.pstmn.io'],\n env: 'SAFELIST'\n },\n\n stagingPrefix: {\n doc: 'Prefix for staging files in S3',\n format: String,\n default: 'staging',\n env: 'STAGING_PREFIX'\n },\n\n submissionEmailAddress: {\n doc: 'Email address to send the form to (local devtool only)',\n format: String,\n default: '',\n env: 'SUBMISSION_EMAIL_ADDRESS'\n } as SchemaObj<string>\n})\n\nconfig.validate({ allowed: 'strict' })\n"],"mappings":"AAAA,SAASA,OAAO,QAAQ,WAAW;AAEnC,OAAOC,OAAO,MAA0B,SAAS;AAGjD,OAAO,eAAe;AAEtB,MAAMC,YAAY,GAAGC,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY;AAC1D,MAAMC,KAAK,GAAGH,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,YAAY;AACnD,MAAME,MAAM,GAAGJ,OAAO,CAACC,GAAG,CAACC,QAAQ,KAAK,MAAM;AAE9C,MAAMG,SAAS,GAAG,IAAI,GAAG,EAAE;AAC3B,MAAMC,OAAO,GAAGD,SAAS,GAAG,EAAE;AAE9B,OAAO,MAAME,MAAM,GAAGT,OAAO,CAAC;EAC5BU,MAAM,EAAE;IACNC,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAEd,OAAO,CAACe,MAAM,CAACC,IAAI,CAACC,OAAO,EAAE,WAAW;EACnD,CAAC;EACDC,SAAS,EAAE;IACTN,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAEP,MAAM,GACXP,OAAO,CAACe,MAAM,CAACC,IAAI,CAACC,OAAO,EAAE,qBAAqB,CAAC,GACnDjB,OAAO,CAACe,MAAM,CAACC,IAAI,CAACC,OAAO,EAAE,eAAe;EAClD,CAAC;EAED;AACF;AACA;EACEE,IAAI,EAAE;IACJP,MAAM,EAAE,MAAM;IACdE,OAAO,EAAE,IAAI;IACbV,GAAG,EAAE;EACP,CAAC;EACDA,GAAG,EAAE;IACHgB,GAAG,EAAE,8BAA8B;IACnCR,MAAM,EAAE,CAAC,YAAY,EAAE,aAAa,EAAE,MAAM,CAAC;IAC7CE,OAAO,EAAE,aAAa;IACtBV,GAAG,EAAE;EACP,CAAC;EACDiB,cAAc,EAAE;IACdD,GAAG,EAAE,2EAA2E;IAChFR,MAAM,EAAE,CACN,OAAO,EACP,WAAW,EACX,YAAY,EACZ,KAAK,EACL,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,CACP;IACDE,OAAO,EAAE,OAAO;IAChBV,GAAG,EAAE;EACP,CAAC;EACDkB,WAAW,EAAE;IACXV,MAAM,EAAEW,OAAO;IACfT,OAAO,EAAEZ,YAAY;IACrBE,GAAG,EAAE;EACP,CAAC;EAED;AACF;AACA;EACEF,YAAY,EAAE;IACZkB,GAAG,EAAE,2DAA2D;IAChER,MAAM,EAAEW,OAAO;IACfT,OAAO,EAAEZ;EACX,CAAC;EACDsB,aAAa,EAAE;IACbJ,GAAG,EAAE,4DAA4D;IACjER,MAAM,EAAEW,OAAO;IACfT,OAAO,EAAER;EACX,CAAC;EACDC,MAAM,EAAE;IACNa,GAAG,EAAE,qDAAqD;IAC1DR,MAAM,EAAEW,OAAO;IACfT,OAAO,EAAEP;EACX,CAAC;EAED;AACF;AACA;EACEkB,WAAW,EAAE;IACXL,GAAG,EAAE,0CAA0C;IAC/CR,MAAM,EAAEW,OAAO;IACfnB,GAAG,EAAE,oBAAoB;IACzBU,OAAO,EAAE;EACX,CAAC;EAED;AACF;AACA;EACEY,WAAW,EAAE;IACXN,GAAG,EAAE,2BAA2B;IAChCR,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE;EACX,CAAC;EACDa,cAAc,EAAE;IACdP,GAAG,EAAE,+FAA+F;IACpGR,MAAM,EAAEC,MAAM;IACde,QAAQ,EAAE,IAAI;IACdd,OAAO,EAAE,EAAE;IACXV,GAAG,EAAE;EACP,CAAsB;EACtByB,YAAY,EAAE;IACZT,GAAG,EAAE,mGAAmG;IACxGR,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,EAAE;IACXV,GAAG,EAAE;EACP,CAAsB;EACtB0B,QAAQ,EAAE;IACRlB,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,MAAM;IAAE;IACjBV,GAAG,EAAE;EACP,CAAC;EAED;AACF;AACA;AACA;EACE2B,cAAc,EAAE;IACdnB,MAAM,EAAEoB,MAAM;IACdlB,OAAO,EAAEL,OAAO,GAAG,EAAE;IAAE;IACvBL,GAAG,EAAE;EACP,CAAC;EACD6B,0BAA0B,EAAE;IAC1BrB,MAAM,EAAEoB,MAAM;IACdlB,OAAO,EAAEN,SAAS,GAAG,EAAE;IACvBJ,GAAG,EAAE;EACP,CAAC;EACD8B,qBAAqB,EAAE;IACrBtB,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,EAAE;IACXqB,SAAS,EAAE,IAAI;IACf/B,GAAG,EAAE;EACP,CAAsB;EACtBgC,KAAK,EAAE;IACLC,IAAI,EAAE;MACJjB,GAAG,EAAE,kBAAkB;MACvBR,MAAM,EAAEC,MAAM;MACdC,OAAO,EAAE,EAAE;MACXV,GAAG,EAAE;IACP,CAAsB;IACtBkC,QAAQ,EAAE;MACRlB,GAAG,EAAE,sBAAsB;MAC3BR,MAAM,EAAEC,MAAM;MACdC,OAAO,EAAE,EAAE;MACXV,GAAG,EAAE;IACP,CAAsB;IACtBmC,QAAQ,EAAE;MACRnB,GAAG,EAAE,sBAAsB;MAC3BR,MAAM,EAAE,GAAG;MACXE,OAAO,EAAE,EAAE;MACXqB,SAAS,EAAE,IAAI;MACf/B,GAAG,EAAE;IACP,CAAsB;IACtBoC,SAAS,EAAE;MACTpB,GAAG,EAAE,wFAAwF;MAC7FR,MAAM,EAAEC,MAAM;MACdC,OAAO,EAAE,EAAE;MACXV,GAAG,EAAE;IACP;EACF,CAAC;EACDqC,OAAO,EAAE;IACPC,MAAM,EAAE;MACNtB,GAAG,EAAE,qBAAqB;MAC1BR,MAAM,EAAEC,MAAM;MACdC,OAAO,EAAE,kBAAkB;MAC3BV,GAAG,EAAE;IACP;EACF,CAAC;EAED;AACF;AACA;AACA;EACEuC,gBAAgB,EAAE;IAChB/B,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,EAAE;IACXV,GAAG,EAAE;EACP,CAAsB;EACtBwC,YAAY,EAAE;IACZhC,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,EAAE;IACXV,GAAG,EAAE;EACP,CAAsB;EAEtB;AACF;AACA;EACEyC,WAAW,EAAE;IACXjC,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,uBAAuB;IAChCV,GAAG,EAAE;EACP,CAAsB;EAEtB0C,aAAa,EAAE;IACblC,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,uBAAuB;IAChCV,GAAG,EAAE;EACP,CAAsB;EAEtB2C,WAAW,EAAE;IACXnC,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,uBAAuB;IAChCV,GAAG,EAAE;EACP,CAAsB;EAEtB4C,kBAAkB,EAAE;IAClBpC,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,OAAO;IAChBV,GAAG,EAAE;EACP,CAAC;EAED;AACF;AACA;EACE6C,GAAG,EAAE;IACHC,OAAO,EAAE;MACP9B,GAAG,EAAE,oBAAoB;MACzBR,MAAM,EAAEW,OAAO;MACfT,OAAO,EAAE,CAACP,MAAM;MAChBH,GAAG,EAAE;IACP,CAAC;IACD+C,KAAK,EAAE;MACL/B,GAAG,EAAE,eAAe;MACpBR,MAAM,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC;MACtEE,OAAO,EAAE,MAAM;MACfV,GAAG,EAAE;IACP,CAA+B;IAC/BQ,MAAM,EAAE;MACNQ,GAAG,EAAE,2BAA2B;MAChCR,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;MAC9BE,OAAO,EAAEZ,YAAY,GAAG,KAAK,GAAG,aAAa;MAC7CE,GAAG,EAAE;IACP,CAAqC;IACrCgD,MAAM,EAAE;MACNhC,GAAG,EAAE,qBAAqB;MAC1BR,MAAM,EAAEyC,KAAK;MACbvC,OAAO,EAAEZ,YAAY,GACjB,CAAC,2BAA2B,EAAE,oBAAoB,EAAE,aAAa,CAAC,GAClE,CAAC,KAAK,EAAE,KAAK,EAAE,cAAc;IACnC;EACF,CAAC;EAEDoD,QAAQ,EAAE;IACR1C,MAAM,EAAEyC,KAAK;IACbvC,OAAO,EAAE,CAAC,oDAAoD,CAAC;IAC/DV,GAAG,EAAE;EACP,CAAC;EAEDmD,aAAa,EAAE;IACbnC,GAAG,EAAE,gCAAgC;IACrCR,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,SAAS;IAClBV,GAAG,EAAE;EACP,CAAC;EAEDoD,sBAAsB,EAAE;IACtBpC,GAAG,EAAE,wDAAwD;IAC7DR,MAAM,EAAEC,MAAM;IACdC,OAAO,EAAE,EAAE;IACXV,GAAG,EAAE;EACP;AACF,CAAC,CAAC;AAEFM,MAAM,CAAC+C,QAAQ,CAAC;EAAEC,OAAO,EAAE;AAAS,CAAC,CAAC","ignoreList":[]}
package/.server/index.js CHANGED
@@ -1,10 +1,12 @@
1
+ import { getErrorMessage } from '@defra/forms-model';
1
2
  import { config } from "./config/index.js";
2
3
  import { createLogger } from "./server/common/helpers/logging/logger.js";
3
4
  import { createServer } from "./server/index.js";
4
5
  const logger = createLogger();
5
6
  process.on('unhandledRejection', error => {
7
+ const err = getErrorMessage(error);
6
8
  logger.info('Unhandled rejection');
7
- logger.error(error);
9
+ logger.error(err, `[unhandledRejection] Unhandled promise rejection: ${err}`);
8
10
  throw error;
9
11
  });
10
12
 
@@ -19,7 +21,9 @@ async function startServer() {
19
21
  server.logger.info(`Access your frontend on http://localhost:${config.get('port')}`);
20
22
  }
21
23
  startServer().catch(error => {
24
+ const err = getErrorMessage(error);
22
25
  logger.info('Server failed to start :(');
23
- logger.error(error);
26
+ logger.error(err, `[serverStartup] Server failed to start: ${err}`);
27
+ throw error;
24
28
  });
25
29
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["config","createLogger","createServer","logger","process","on","error","info","startServer","server","start","send","get","catch"],"sources":["../src/index.ts"],"sourcesContent":["import { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\nimport { createServer } from '~/src/server/index.js'\n\nconst logger = createLogger()\n\nprocess.on('unhandledRejection', (error) => {\n logger.info('Unhandled rejection')\n logger.error(error)\n throw error\n})\n\n/**\n * Main entrypoint to the application.\n */\nasync function startServer() {\n const server = await createServer()\n await server.start()\n\n process.send?.('online')\n\n server.logger.info('Server started successfully')\n server.logger.info(\n `Access your frontend on http://localhost:${config.get('port')}`\n )\n}\n\nstartServer().catch((error: unknown) => {\n logger.info('Server failed to start :(')\n logger.error(error)\n})\n"],"mappings":"AAAA,SAASA,MAAM;AACf,SAASC,YAAY;AACrB,SAASC,YAAY;AAErB,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;AAE7BG,OAAO,CAACC,EAAE,CAAC,oBAAoB,EAAGC,KAAK,IAAK;EAC1CH,MAAM,CAACI,IAAI,CAAC,qBAAqB,CAAC;EAClCJ,MAAM,CAACG,KAAK,CAACA,KAAK,CAAC;EACnB,MAAMA,KAAK;AACb,CAAC,CAAC;;AAEF;AACA;AACA;AACA,eAAeE,WAAWA,CAAA,EAAG;EAC3B,MAAMC,MAAM,GAAG,MAAMP,YAAY,CAAC,CAAC;EACnC,MAAMO,MAAM,CAACC,KAAK,CAAC,CAAC;EAEpBN,OAAO,CAACO,IAAI,GAAG,QAAQ,CAAC;EAExBF,MAAM,CAACN,MAAM,CAACI,IAAI,CAAC,6BAA6B,CAAC;EACjDE,MAAM,CAACN,MAAM,CAACI,IAAI,CAChB,4CAA4CP,MAAM,CAACY,GAAG,CAAC,MAAM,CAAC,EAChE,CAAC;AACH;AAEAJ,WAAW,CAAC,CAAC,CAACK,KAAK,CAAEP,KAAc,IAAK;EACtCH,MAAM,CAACI,IAAI,CAAC,2BAA2B,CAAC;EACxCJ,MAAM,CAACG,KAAK,CAACA,KAAK,CAAC;AACrB,CAAC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["getErrorMessage","config","createLogger","createServer","logger","process","on","error","err","info","startServer","server","start","send","get","catch"],"sources":["../src/index.ts"],"sourcesContent":["import { getErrorMessage } from '@defra/forms-model'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\nimport { createServer } from '~/src/server/index.js'\n\nconst logger = createLogger()\n\nprocess.on('unhandledRejection', (error) => {\n const err = getErrorMessage(error)\n logger.info('Unhandled rejection')\n logger.error(err, `[unhandledRejection] Unhandled promise rejection: ${err}`)\n throw error\n})\n\n/**\n * Main entrypoint to the application.\n */\nasync function startServer() {\n const server = await createServer()\n await server.start()\n\n process.send?.('online')\n\n server.logger.info('Server started successfully')\n server.logger.info(\n `Access your frontend on http://localhost:${config.get('port')}`\n )\n}\n\nstartServer().catch((error: unknown) => {\n const err = getErrorMessage(error)\n logger.info('Server failed to start :(')\n logger.error(err, `[serverStartup] Server failed to start: ${err}`)\n throw error\n})\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,oBAAoB;AAEpD,SAASC,MAAM;AACf,SAASC,YAAY;AACrB,SAASC,YAAY;AAErB,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;AAE7BG,OAAO,CAACC,EAAE,CAAC,oBAAoB,EAAGC,KAAK,IAAK;EAC1C,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,qBAAqB,CAAC;EAClCL,MAAM,CAACG,KAAK,CAACC,GAAG,EAAE,qDAAqDA,GAAG,EAAE,CAAC;EAC7E,MAAMD,KAAK;AACb,CAAC,CAAC;;AAEF;AACA;AACA;AACA,eAAeG,WAAWA,CAAA,EAAG;EAC3B,MAAMC,MAAM,GAAG,MAAMR,YAAY,CAAC,CAAC;EACnC,MAAMQ,MAAM,CAACC,KAAK,CAAC,CAAC;EAEpBP,OAAO,CAACQ,IAAI,GAAG,QAAQ,CAAC;EAExBF,MAAM,CAACP,MAAM,CAACK,IAAI,CAAC,6BAA6B,CAAC;EACjDE,MAAM,CAACP,MAAM,CAACK,IAAI,CAChB,4CAA4CR,MAAM,CAACa,GAAG,CAAC,MAAM,CAAC,EAChE,CAAC;AACH;AAEAJ,WAAW,CAAC,CAAC,CAACK,KAAK,CAAER,KAAc,IAAK;EACtC,MAAMC,GAAG,GAAGR,eAAe,CAACO,KAAK,CAAC;EAClCH,MAAM,CAACK,IAAI,CAAC,2BAA2B,CAAC;EACxCL,MAAM,CAACG,KAAK,CAACC,GAAG,EAAE,2CAA2CA,GAAG,EAAE,CAAC;EACnE,MAAMD,KAAK;AACb,CAAC,CAAC","ignoreList":[]}
@@ -6,7 +6,7 @@ import { config } from "../../../../config/index.js";
6
6
  export const requestTracing = {
7
7
  plugin: tracing,
8
8
  options: {
9
- tracingHeader: config.get('tracing').header
9
+ tracingHeader: config.get('tracing.header')
10
10
  }
11
11
  };
12
12
  //# sourceMappingURL=request-tracing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request-tracing.js","names":["tracing","config","requestTracing","plugin","options","tracingHeader","get","header"],"sources":["../../../../../src/server/common/helpers/logging/request-tracing.js"],"sourcesContent":["import { tracing } from '@defra/hapi-tracing'\n\nimport { config } from '~/src/config/index.js'\n\n// Explicitly declare the expected type\n\nexport const requestTracing = {\n plugin: tracing,\n options: { tracingHeader: config.get('tracing').header }\n}\n"],"mappings":"AAAA,SAASA,OAAO,QAAQ,qBAAqB;AAE7C,SAASC,MAAM;;AAEf;;AAEA,OAAO,MAAMC,cAAc,GAAG;EAC5BC,MAAM,EAAEH,OAAO;EACfI,OAAO,EAAE;IAAEC,aAAa,EAAEJ,MAAM,CAACK,GAAG,CAAC,SAAS,CAAC,CAACC;EAAO;AACzD,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"request-tracing.js","names":["tracing","config","requestTracing","plugin","options","tracingHeader","get"],"sources":["../../../../../src/server/common/helpers/logging/request-tracing.js"],"sourcesContent":["import { tracing } from '@defra/hapi-tracing'\n\nimport { config } from '~/src/config/index.js'\n\n// Explicitly declare the expected type\n\nexport const requestTracing = {\n plugin: tracing,\n options: { tracingHeader: config.get('tracing.header') }\n}\n"],"mappings":"AAAA,SAASA,OAAO,QAAQ,qBAAqB;AAE7C,SAASC,MAAM;;AAEf;;AAEA,OAAO,MAAMC,cAAc,GAAG;EAC5BC,MAAM,EAAEH,OAAO;EACfI,OAAO,EAAE;IAAEC,aAAa,EAAEJ,MAAM,CAACK,GAAG,CAAC,gBAAgB;EAAE;AACzD,CAAC","ignoreList":[]}
@@ -1,3 +1,4 @@
1
+ import { getErrorMessage } from '@defra/forms-model';
1
2
  import { Cluster, Redis } from 'ioredis';
2
3
  import { config } from "../../../config/index.js";
3
4
  import { createLogger } from "./logging/logger.js";
@@ -42,13 +43,14 @@ export function buildRedisClient() {
42
43
  });
43
44
  }
44
45
  redisClient.on('connect', () => {
45
- logger.info('Connected to Redis server');
46
+ logger.info('[redisConnected] Connected to Redis server');
46
47
  });
47
48
  redisClient.on('close', () => {
48
- logger.warn('Redis connection closed attempting reconnect with default behavior');
49
+ logger.warn('[redisDisconnected] Redis connection closed attempting reconnect with default behavior');
49
50
  });
50
51
  redisClient.on('error', error => {
51
- logger.error(error, `Redis connection error ${error}.`);
52
+ const err = getErrorMessage(error);
53
+ logger.error(err, `[redisConnectionError] Redis connection error - ${err}`);
52
54
  });
53
55
  return redisClient;
54
56
  }
@@ -1 +1 @@
1
- {"version":3,"file":"redis-client.js","names":["Cluster","Redis","config","createLogger","buildRedisClient","logger","port","db","redisConfig","get","keyPrefix","host","redisClient","info","slotsRefreshTimeout","dnsLookup","address","callback","redisOptions","username","password","tls","on","warn","error"],"sources":["../../../../src/server/common/helpers/redis-client.js"],"sourcesContent":["import { Cluster, Redis } from 'ioredis'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\n\n/**\n * Setup Redis and provide a redis client\n *\n * Local development - 1 Redis instance\n * Out in the wild - Elasticache / Redis Cluster with username and password\n */\nexport function buildRedisClient() {\n const logger = createLogger()\n\n const port = 6379\n const db = 0\n const redisConfig = config.get('redis')\n const keyPrefix = redisConfig.keyPrefix\n const host = redisConfig.host\n let redisClient\n\n if (!config.get('isProduction')) {\n logger.info('Connecting to Redis using single instance')\n\n redisClient = new Redis({\n port,\n host,\n db,\n keyPrefix\n })\n } else {\n logger.info('Connecting to Redis using cluster')\n\n redisClient = new Cluster(\n [\n {\n host,\n port\n }\n ],\n {\n keyPrefix,\n slotsRefreshTimeout: 2000,\n dnsLookup: (address, callback) => callback(null, address),\n redisOptions: {\n username: redisConfig.username,\n password: redisConfig.password,\n db,\n tls: {}\n }\n }\n )\n }\n\n redisClient.on('connect', () => {\n logger.info('Connected to Redis server')\n })\n\n redisClient.on('close', () => {\n logger.warn(\n 'Redis connection closed attempting reconnect with default behavior'\n )\n })\n\n redisClient.on('error', (error) => {\n logger.error(error, `Redis connection error ${error}.`)\n })\n\n return redisClient\n}\n"],"mappings":"AAAA,SAASA,OAAO,EAAEC,KAAK,QAAQ,SAAS;AAExC,SAASC,MAAM;AACf,SAASC,YAAY;;AAErB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAAA,EAAG;EACjC,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;EAE7B,MAAMG,IAAI,GAAG,IAAI;EACjB,MAAMC,EAAE,GAAG,CAAC;EACZ,MAAMC,WAAW,GAAGN,MAAM,CAACO,GAAG,CAAC,OAAO,CAAC;EACvC,MAAMC,SAAS,GAAGF,WAAW,CAACE,SAAS;EACvC,MAAMC,IAAI,GAAGH,WAAW,CAACG,IAAI;EAC7B,IAAIC,WAAW;EAEf,IAAI,CAACV,MAAM,CAACO,GAAG,CAAC,cAAc,CAAC,EAAE;IAC/BJ,MAAM,CAACQ,IAAI,CAAC,2CAA2C,CAAC;IAExDD,WAAW,GAAG,IAAIX,KAAK,CAAC;MACtBK,IAAI;MACJK,IAAI;MACJJ,EAAE;MACFG;IACF,CAAC,CAAC;EACJ,CAAC,MAAM;IACLL,MAAM,CAACQ,IAAI,CAAC,mCAAmC,CAAC;IAEhDD,WAAW,GAAG,IAAIZ,OAAO,CACvB,CACE;MACEW,IAAI;MACJL;IACF,CAAC,CACF,EACD;MACEI,SAAS;MACTI,mBAAmB,EAAE,IAAI;MACzBC,SAAS,EAAEA,CAACC,OAAO,EAAEC,QAAQ,KAAKA,QAAQ,CAAC,IAAI,EAAED,OAAO,CAAC;MACzDE,YAAY,EAAE;QACZC,QAAQ,EAAEX,WAAW,CAACW,QAAQ;QAC9BC,QAAQ,EAAEZ,WAAW,CAACY,QAAQ;QAC9Bb,EAAE;QACFc,GAAG,EAAE,CAAC;MACR;IACF,CACF,CAAC;EACH;EAEAT,WAAW,CAACU,EAAE,CAAC,SAAS,EAAE,MAAM;IAC9BjB,MAAM,CAACQ,IAAI,CAAC,2BAA2B,CAAC;EAC1C,CAAC,CAAC;EAEFD,WAAW,CAACU,EAAE,CAAC,OAAO,EAAE,MAAM;IAC5BjB,MAAM,CAACkB,IAAI,CACT,oEACF,CAAC;EACH,CAAC,CAAC;EAEFX,WAAW,CAACU,EAAE,CAAC,OAAO,EAAGE,KAAK,IAAK;IACjCnB,MAAM,CAACmB,KAAK,CAACA,KAAK,EAAE,0BAA0BA,KAAK,GAAG,CAAC;EACzD,CAAC,CAAC;EAEF,OAAOZ,WAAW;AACpB","ignoreList":[]}
1
+ {"version":3,"file":"redis-client.js","names":["getErrorMessage","Cluster","Redis","config","createLogger","buildRedisClient","logger","port","db","redisConfig","get","keyPrefix","host","redisClient","info","slotsRefreshTimeout","dnsLookup","address","callback","redisOptions","username","password","tls","on","warn","error","err"],"sources":["../../../../src/server/common/helpers/redis-client.js"],"sourcesContent":["import { getErrorMessage } from '@defra/forms-model'\nimport { Cluster, Redis } from 'ioredis'\n\nimport { config } from '~/src/config/index.js'\nimport { createLogger } from '~/src/server/common/helpers/logging/logger.js'\n\n/**\n * Setup Redis and provide a redis client\n *\n * Local development - 1 Redis instance\n * Out in the wild - Elasticache / Redis Cluster with username and password\n */\nexport function buildRedisClient() {\n const logger = createLogger()\n\n const port = 6379\n const db = 0\n const redisConfig = config.get('redis')\n const keyPrefix = redisConfig.keyPrefix\n const host = redisConfig.host\n let redisClient\n\n if (!config.get('isProduction')) {\n logger.info('Connecting to Redis using single instance')\n\n redisClient = new Redis({\n port,\n host,\n db,\n keyPrefix\n })\n } else {\n logger.info('Connecting to Redis using cluster')\n\n redisClient = new Cluster(\n [\n {\n host,\n port\n }\n ],\n {\n keyPrefix,\n slotsRefreshTimeout: 2000,\n dnsLookup: (address, callback) => callback(null, address),\n redisOptions: {\n username: redisConfig.username,\n password: redisConfig.password,\n db,\n tls: {}\n }\n }\n )\n }\n\n redisClient.on('connect', () => {\n logger.info('[redisConnected] Connected to Redis server')\n })\n\n redisClient.on('close', () => {\n logger.warn(\n '[redisDisconnected] Redis connection closed attempting reconnect with default behavior'\n )\n })\n\n redisClient.on('error', (error) => {\n const err = getErrorMessage(error)\n logger.error(err, `[redisConnectionError] Redis connection error - ${err}`)\n })\n\n return redisClient\n}\n"],"mappings":"AAAA,SAASA,eAAe,QAAQ,oBAAoB;AACpD,SAASC,OAAO,EAAEC,KAAK,QAAQ,SAAS;AAExC,SAASC,MAAM;AACf,SAASC,YAAY;;AAErB;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,gBAAgBA,CAAA,EAAG;EACjC,MAAMC,MAAM,GAAGF,YAAY,CAAC,CAAC;EAE7B,MAAMG,IAAI,GAAG,IAAI;EACjB,MAAMC,EAAE,GAAG,CAAC;EACZ,MAAMC,WAAW,GAAGN,MAAM,CAACO,GAAG,CAAC,OAAO,CAAC;EACvC,MAAMC,SAAS,GAAGF,WAAW,CAACE,SAAS;EACvC,MAAMC,IAAI,GAAGH,WAAW,CAACG,IAAI;EAC7B,IAAIC,WAAW;EAEf,IAAI,CAACV,MAAM,CAACO,GAAG,CAAC,cAAc,CAAC,EAAE;IAC/BJ,MAAM,CAACQ,IAAI,CAAC,2CAA2C,CAAC;IAExDD,WAAW,GAAG,IAAIX,KAAK,CAAC;MACtBK,IAAI;MACJK,IAAI;MACJJ,EAAE;MACFG;IACF,CAAC,CAAC;EACJ,CAAC,MAAM;IACLL,MAAM,CAACQ,IAAI,CAAC,mCAAmC,CAAC;IAEhDD,WAAW,GAAG,IAAIZ,OAAO,CACvB,CACE;MACEW,IAAI;MACJL;IACF,CAAC,CACF,EACD;MACEI,SAAS;MACTI,mBAAmB,EAAE,IAAI;MACzBC,SAAS,EAAEA,CAACC,OAAO,EAAEC,QAAQ,KAAKA,QAAQ,CAAC,IAAI,EAAED,OAAO,CAAC;MACzDE,YAAY,EAAE;QACZC,QAAQ,EAAEX,WAAW,CAACW,QAAQ;QAC9BC,QAAQ,EAAEZ,WAAW,CAACY,QAAQ;QAC9Bb,EAAE;QACFc,GAAG,EAAE,CAAC;MACR;IACF,CACF,CAAC;EACH;EAEAT,WAAW,CAACU,EAAE,CAAC,SAAS,EAAE,MAAM;IAC9BjB,MAAM,CAACQ,IAAI,CAAC,4CAA4C,CAAC;EAC3D,CAAC,CAAC;EAEFD,WAAW,CAACU,EAAE,CAAC,OAAO,EAAE,MAAM;IAC5BjB,MAAM,CAACkB,IAAI,CACT,wFACF,CAAC;EACH,CAAC,CAAC;EAEFX,WAAW,CAACU,EAAE,CAAC,OAAO,EAAGE,KAAK,IAAK;IACjC,MAAMC,GAAG,GAAG1B,eAAe,CAACyB,KAAK,CAAC;IAClCnB,MAAM,CAACmB,KAAK,CAACC,GAAG,EAAE,mDAAmDA,GAAG,EAAE,CAAC;EAC7E,CAAC,CAAC;EAEF,OAAOb,WAAW;AACpB","ignoreList":[]}
@@ -1,3 +1,2 @@
1
1
  export const PREVIEW_PATH_PREFIX: "/preview";
2
- export const ERROR_PREVIEW_PATH_PREFIX: "/error-preview";
3
2
  export const FORM_PREFIX: "";
@@ -1,4 +1,3 @@
1
1
  export const PREVIEW_PATH_PREFIX = '/preview';
2
- export const ERROR_PREVIEW_PATH_PREFIX = '/error-preview';
3
2
  export const FORM_PREFIX = '';
4
3
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":["PREVIEW_PATH_PREFIX","ERROR_PREVIEW_PATH_PREFIX","FORM_PREFIX"],"sources":["../../src/server/constants.js"],"sourcesContent":["export const PREVIEW_PATH_PREFIX = '/preview'\nexport const ERROR_PREVIEW_PATH_PREFIX = '/error-preview'\nexport const FORM_PREFIX = ''\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,UAAU;AAC7C,OAAO,MAAMC,yBAAyB,GAAG,gBAAgB;AACzD,OAAO,MAAMC,WAAW,GAAG,EAAE","ignoreList":[]}
1
+ {"version":3,"file":"constants.js","names":["PREVIEW_PATH_PREFIX","FORM_PREFIX"],"sources":["../../src/server/constants.js"],"sourcesContent":["export const PREVIEW_PATH_PREFIX = '/preview'\nexport const FORM_PREFIX = ''\n"],"mappings":"AAAA,OAAO,MAAMA,mBAAmB,GAAG,UAAU;AAC7C,OAAO,MAAMC,WAAW,GAAG,EAAE","ignoreList":[]}
@@ -100,7 +100,9 @@ export async function createServer(routeConfig) {
100
100
  }
101
101
  });
102
102
  await server.register(pluginErrorPages);
103
- await server.register(blipp);
103
+ if (config.get('cdpEnvironment') === 'local') {
104
+ await server.register(blipp);
105
+ }
104
106
  await server.register(requestTracing);
105
107
  return server;
106
108
  }