@defra/forms-engine-plugin 0.1.10 → 0.1.11

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 (116) hide show
  1. package/.public/stylesheets/application.min.css +1 -1
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/application.scss +10 -0
  4. package/.server/config/index.js +3 -14
  5. package/.server/config/index.js.map +1 -1
  6. package/.server/server/devserver/dxt-devtool-baselayout.html +71 -0
  7. package/.server/server/forms/register-as-a-unicorn-breeder.json +393 -0
  8. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +251 -0
  9. package/.server/server/index.js +11 -16
  10. package/.server/server/index.js.map +1 -1
  11. package/.server/server/plugins/engine/configureEnginePlugin.js +16 -2
  12. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  13. package/.server/server/plugins/engine/plugin.js +27 -16
  14. package/.server/server/plugins/engine/plugin.js.map +1 -1
  15. package/.server/server/plugins/engine/services/formsService.js +15 -29
  16. package/.server/server/plugins/engine/services/formsService.js.map +1 -1
  17. package/.server/server/plugins/engine/services/localFormsService.js +52 -0
  18. package/.server/server/plugins/engine/services/localFormsService.js.map +1 -0
  19. package/.server/server/plugins/engine/views/confirmation.html +1 -1
  20. package/.server/server/plugins/engine/views/file-upload.html +1 -1
  21. package/.server/server/plugins/engine/views/index.html +1 -1
  22. package/.server/server/plugins/engine/views/item-delete.html +1 -1
  23. package/.server/server/plugins/engine/views/repeat-list-summary.html +1 -1
  24. package/.server/server/plugins/engine/views/summary.html +1 -1
  25. package/.server/server/plugins/errorPages.js +4 -26
  26. package/.server/server/plugins/errorPages.js.map +1 -1
  27. package/.server/server/plugins/nunjucks/context.js +37 -28
  28. package/.server/server/plugins/nunjucks/context.js.map +1 -1
  29. package/.server/server/plugins/nunjucks/context.test.js +23 -28
  30. package/.server/server/plugins/nunjucks/context.test.js.map +1 -1
  31. package/.server/server/plugins/nunjucks/types.js +3 -4
  32. package/.server/server/plugins/nunjucks/types.js.map +1 -1
  33. package/.server/server/routes/index.js +0 -1
  34. package/.server/server/routes/index.js.map +1 -1
  35. package/.server/typings/hapi/index.d.js.map +1 -1
  36. package/package.json +2 -1
  37. package/src/client/stylesheets/application.scss +10 -0
  38. package/src/config/index.ts +4 -17
  39. package/src/server/devserver/dxt-devtool-baselayout.html +71 -0
  40. package/src/server/forms/register-as-a-unicorn-breeder.json +393 -0
  41. package/src/server/forms/register-as-a-unicorn-breeder.yaml +251 -0
  42. package/src/server/index.test.ts +4 -37
  43. package/src/server/index.ts +13 -16
  44. package/src/server/plugins/engine/configureEnginePlugin.ts +19 -1
  45. package/src/server/plugins/engine/plugin.ts +43 -17
  46. package/src/server/plugins/engine/services/formsService.js +17 -35
  47. package/src/server/plugins/engine/services/localFormsService.js +49 -0
  48. package/src/server/plugins/engine/views/confirmation.html +1 -1
  49. package/src/server/plugins/engine/views/file-upload.html +1 -1
  50. package/src/server/plugins/engine/views/index.html +1 -1
  51. package/src/server/plugins/engine/views/item-delete.html +1 -1
  52. package/src/server/plugins/engine/views/repeat-list-summary.html +1 -1
  53. package/src/server/plugins/engine/views/summary.html +1 -1
  54. package/src/server/plugins/errorPages.ts +4 -26
  55. package/src/server/plugins/nunjucks/context.js +41 -31
  56. package/src/server/plugins/nunjucks/context.test.js +24 -27
  57. package/src/server/plugins/nunjucks/types.js +3 -4
  58. package/src/server/routes/index.ts +0 -1
  59. package/src/typings/hapi/index.d.ts +3 -9
  60. package/.server/common/cookies.js +0 -55
  61. package/.server/common/cookies.js.map +0 -1
  62. package/.server/common/cookies.test.js +0 -15
  63. package/.server/common/cookies.test.js.map +0 -1
  64. package/.server/common/types.js +0 -6
  65. package/.server/common/types.js.map +0 -1
  66. package/.server/server/forms/README.md +0 -10
  67. package/.server/server/forms/report-a-terrorist.json +0 -270
  68. package/.server/server/forms/runner-components-test.json +0 -365
  69. package/.server/server/forms/test.json +0 -581
  70. package/.server/server/forms/test.yaml +0 -363
  71. package/.server/server/plugins/blankie.js +0 -29
  72. package/.server/server/plugins/blankie.js.map +0 -1
  73. package/.server/server/plugins/engine/services/formsService.test.js +0 -71
  74. package/.server/server/plugins/engine/services/formsService.test.js.map +0 -1
  75. package/.server/server/plugins/engine/views/layout.html +0 -199
  76. package/.server/server/plugins/router.js +0 -169
  77. package/.server/server/plugins/router.js.map +0 -1
  78. package/.server/server/routes/health.js +0 -15
  79. package/.server/server/routes/health.js.map +0 -1
  80. package/.server/server/routes/health.test.js +0 -32
  81. package/.server/server/routes/health.test.js.map +0 -1
  82. package/.server/server/utils/file-form-service.test.js +0 -52
  83. package/.server/server/utils/file-form-service.test.js.map +0 -1
  84. package/.server/server/views/404.html +0 -16
  85. package/.server/server/views/500.html +0 -19
  86. package/.server/server/views/help/accessibility-statement.html +0 -58
  87. package/.server/server/views/help/cookie-preferences.html +0 -57
  88. package/.server/server/views/help/cookies.html +0 -71
  89. package/.server/server/views/help/get-support.html +0 -37
  90. package/.server/server/views/help/privacy-notice.html +0 -68
  91. package/.server/server/views/help/terms-and-conditions.html +0 -83
  92. package/src/common/cookies.js +0 -58
  93. package/src/common/cookies.test.js +0 -23
  94. package/src/common/types.js +0 -5
  95. package/src/server/forms/README.md +0 -10
  96. package/src/server/forms/report-a-terrorist.json +0 -270
  97. package/src/server/forms/runner-components-test.json +0 -365
  98. package/src/server/forms/test.json +0 -581
  99. package/src/server/forms/test.yaml +0 -363
  100. package/src/server/plugins/blankie.test.ts +0 -73
  101. package/src/server/plugins/blankie.ts +0 -48
  102. package/src/server/plugins/engine/services/formsService.test.js +0 -90
  103. package/src/server/plugins/engine/views/layout.html +0 -199
  104. package/src/server/plugins/router.ts +0 -201
  105. package/src/server/routes/health.js +0 -13
  106. package/src/server/routes/health.test.js +0 -35
  107. package/src/server/routes/index.test.ts +0 -125
  108. package/src/server/utils/file-form-service.test.js +0 -79
  109. package/src/server/views/404.html +0 -16
  110. package/src/server/views/500.html +0 -19
  111. package/src/server/views/help/accessibility-statement.html +0 -58
  112. package/src/server/views/help/cookie-preferences.html +0 -57
  113. package/src/server/views/help/cookies.html +0 -71
  114. package/src/server/views/help/get-support.html +0 -37
  115. package/src/server/views/help/privacy-notice.html +0 -68
  116. package/src/server/views/help/terms-and-conditions.html +0 -83
@@ -0,0 +1,251 @@
1
+ ---
2
+ name: Register as a unicorn breeder
3
+ pages:
4
+ - path: '/whats-your-name'
5
+ title: What's your name?
6
+ components:
7
+ - type: TextField
8
+ name: textField
9
+ title: Name
10
+ hint:
11
+ This is a single line text box. We use it to ask for information that's
12
+ likely to be 1 sentence
13
+ options:
14
+ required: true
15
+ schema: {}
16
+ next:
17
+ - path: '/whats-your-email-address'
18
+ section: section
19
+ - title: Summary
20
+ path: '/summary'
21
+ controller: './pages/summary.js'
22
+ components: []
23
+ next: []
24
+ - path: '/whats-your-email-address'
25
+ title: What's your email address?
26
+ components:
27
+ - name: MaTzaT
28
+ options:
29
+ required: true
30
+ type: EmailAddressField
31
+ title: Email adress
32
+ schema: {}
33
+ hint: This is an email address. An email address must contain an at sign @
34
+ next:
35
+ - path: '/whats-your-phone-number'
36
+ section: section
37
+ - path: '/whats-your-phone-number'
38
+ title: What's your phone number?
39
+ components:
40
+ - name: BdKgCe
41
+ options:
42
+ required: true
43
+ type: TelephoneNumberField
44
+ title: Phone number
45
+ schema: {}
46
+ hint:
47
+ This is a telephone number. This field can only contain numbers and the
48
+ + symbol
49
+ next:
50
+ - path: '/whats-your-address'
51
+ section: section
52
+ - path: '/whats-your-address'
53
+ title: What's your address?
54
+ components:
55
+ - name: wZLWPy
56
+ options:
57
+ required: true
58
+ type: UkAddressField
59
+ title: Address
60
+ schema: {}
61
+ hint: This is a UK address. Users must enter address line 1, town and a postcode
62
+ next:
63
+ - path: '/do-you-want-your-unicorn-breeder-certificate-sent-to-this-address'
64
+ section: section
65
+ - path: '/do-you-want-your-unicorn-breeder-certificate-sent-to-this-address'
66
+ title: Do you want your unicorn breeder certificate sent to this address?
67
+ components:
68
+ - name: dBfuID
69
+ options: {}
70
+ type: YesNoField
71
+ title: Send certificate to same address
72
+ schema: {}
73
+ hint:
74
+ This is a yes or no question. We can branch to different questions based
75
+ on the answer
76
+ values:
77
+ type: listRef
78
+ next:
79
+ - path: '/what-address-do-you-want-the-certificate-sent-to'
80
+ condition: oyGPwP
81
+ - path: '/when-does-your-unicorn-insurance-policy-start'
82
+ condition: ''
83
+ section: section
84
+ - path: '/what-address-do-you-want-the-certificate-sent-to'
85
+ title: What address do you want the certificate sent to?
86
+ components:
87
+ - name: AegFro
88
+ options: {}
89
+ type: UkAddressField
90
+ title: Address to send certificate
91
+ schema: {}
92
+ hint:
93
+ This is a simple branch to an extra question - it's shown to users who select
94
+ 'no' when asked if this is the address where the certificate should be sent
95
+ next:
96
+ - path: '/when-does-your-unicorn-insurance-policy-start'
97
+ section: section
98
+ - title: When does your unicorn insurance policy start?
99
+ path: '/when-does-your-unicorn-insurance-policy-start'
100
+ section: Regnsa
101
+ next:
102
+ - path: '/upload-your-insurance-certificate'
103
+ components:
104
+ - name: mjAccr
105
+ options: {}
106
+ type: DatePartsField
107
+ title: Unicorn insurance policy start date
108
+ schema: {}
109
+ hint:
110
+ This is a date. We can add custom validation to the field based on your
111
+ requirements. For example, the date entered must be before or after a certain
112
+ date
113
+ - title: How many unicorns do you expect to breed each year?
114
+ path: '/how-many-unicorns-do-you-expect-to-breed-each-year'
115
+ section: susaYr
116
+ next:
117
+ - path: '/what-type-of-unicorns-will-you-breed'
118
+ components:
119
+ - name: aitzzV
120
+ options: {}
121
+ type: RadiosField
122
+ list: IeFOkf
123
+ title: Number of unicorns
124
+ schema: {}
125
+ hint: This is a radio button. Users can only select one option from the list
126
+ values:
127
+ type: listRef
128
+ - title: What type of unicorns will you breed?
129
+ path: '/what-type-of-unicorns-will-you-breed'
130
+ section: susaYr
131
+ next:
132
+ - path: '/where-will-you-keep-the-unicorns'
133
+ components:
134
+ - name: DyfjJC
135
+ options: {}
136
+ type: CheckboxesField
137
+ list: fXiZrL
138
+ title: Type of unicorn
139
+ schema: {}
140
+ hint: This is a check box. Users can select more than one option
141
+ values:
142
+ type: listRef
143
+ - title: Where will you keep the unicorns?
144
+ path: '/where-will-you-keep-the-unicorns'
145
+ section: susaYr
146
+ next:
147
+ - path: '/how-many-members-of-staff-will-look-after-the-unicorns'
148
+ components:
149
+ - name: bClCvo
150
+ options: {}
151
+ schema: {}
152
+ type: MultilineTextField
153
+ title: Where you keep the unicorn
154
+ hint:
155
+ This is a multi-line text box. We use it when you expect the response to
156
+ be more than 1 sentence long
157
+ - title: How many members of staff will look after the unicorns?
158
+ path: '/how-many-members-of-staff-will-look-after-the-unicorns'
159
+ section: susaYr
160
+ next:
161
+ - path: '/summary'
162
+ components:
163
+ - name: zhJMaM
164
+ options:
165
+ classes: govuk-!-width-one-quarter
166
+ type: NumberField
167
+ title: Number of staff
168
+ schema: {}
169
+ hint:
170
+ This is a number field. The answer must be a number. We can use custom validation
171
+ to set decimal places, minimum and maximum values
172
+ - title: Upload your insurance certificate
173
+ path: '/upload-your-insurance-certificate'
174
+ controller: FileUploadPageController
175
+ section: Regnsa
176
+ next:
177
+ - path: '/how-many-unicorns-do-you-expect-to-breed-each-year'
178
+ components:
179
+ - name: dLzALM
180
+ title: Documents
181
+ type: FileUploadField
182
+ hint: We can specify the format and number of uploaded files
183
+ options:
184
+ required: false
185
+ schema:
186
+ min: 1
187
+ max: 3
188
+ conditions:
189
+ - displayName: Address is different
190
+ name: IrVmYz
191
+ value:
192
+ name: Address is different
193
+ conditions:
194
+ - field:
195
+ name: dBfuID
196
+ type: YesNoField
197
+ display: 'Contact details: Send certificate to same address'
198
+ operator: is
199
+ value:
200
+ type: Value
201
+ value: 'false'
202
+ display: 'false'
203
+ - displayName: Address is not the same
204
+ name: oyGPwP
205
+ value:
206
+ name: Address is not the same
207
+ conditions:
208
+ - field:
209
+ name: dBfuID
210
+ type: YesNoField
211
+ display: 'Contact details: Send certificate to same address'
212
+ operator: is
213
+ value:
214
+ type: Value
215
+ value: 'false'
216
+ display: 'No'
217
+ sections:
218
+ - name: section
219
+ title: Contact details
220
+ hideTitle: false
221
+ - title: Unicorn details
222
+ name: susaYr
223
+ hideTitle: false
224
+ - title: Insurance details
225
+ name: Regnsa
226
+ hideTitle: false
227
+ lists:
228
+ - title: number of unicorns
229
+ name: IeFOkf
230
+ type: string
231
+ items:
232
+ - text: 1 to 5
233
+ value: 1 to 5
234
+ - text: 6 to 10
235
+ value: 6 to 10
236
+ - text: 11 or more
237
+ value: 11 or more
238
+ - title: Type of unicorn
239
+ name: fXiZrL
240
+ type: string
241
+ items:
242
+ - text: Flying
243
+ value: Flying
244
+ - text: Fire breathing
245
+ value: Fire breathing
246
+ - text: Aquatic
247
+ value: Aquatic
248
+ - text: Rainbow
249
+ value: Rainbow
250
+ outputEmail: defraforms@defra.gov.uk
251
+ startPage: '/whats-your-name'
@@ -10,14 +10,13 @@ import { config } from "../config/index.js";
10
10
  import { requestLogger } from "./common/helpers/logging/request-logger.js";
11
11
  import { requestTracing } from "./common/helpers/logging/request-tracing.js";
12
12
  import { buildRedisClient } from "./common/helpers/redis-client.js";
13
- import { configureBlankiePlugin } from "./plugins/blankie.js";
14
13
  import { configureCrumbPlugin } from "./plugins/crumb.js";
15
- import { configureEnginePlugin } from "./plugins/engine/index.js";
14
+ import { configureEnginePlugin } from "./plugins/engine/configureEnginePlugin.js";
16
15
  import pluginErrorPages from "./plugins/errorPages.js";
17
16
  import { plugin as pluginViews } from "./plugins/nunjucks/index.js";
18
17
  import pluginPulse from "./plugins/pulse.js";
19
- import pluginRouter from "./plugins/router.js";
20
18
  import pluginSession from "./plugins/session.js";
19
+ import { publicRoutes } from "./routes/index.js";
21
20
  import { prepareSecureContext } from "./secure-context.js";
22
21
  const proxyAgent = new ProxyAgent();
23
22
  Wreck.agents = {
@@ -66,14 +65,12 @@ export async function createServer(routeConfig) {
66
65
  if (config.get('isProduction')) {
67
66
  prepareSecureContext(server);
68
67
  }
69
- const pluginEngine = await configureEnginePlugin(routeConfig);
70
68
  const pluginCrumb = configureCrumbPlugin(routeConfig);
71
- const pluginBlankie = configureBlankiePlugin();
69
+ const pluginEngine = await configureEnginePlugin(routeConfig);
72
70
  await server.register(pluginSession);
73
71
  await server.register(pluginPulse);
74
72
  await server.register(inert);
75
73
  await server.register(Scooter);
76
- await server.register(pluginBlankie);
77
74
  await server.register(pluginCrumb);
78
75
  server.ext('onPreResponse', (request, h) => {
79
76
  const {
@@ -94,19 +91,17 @@ export async function createServer(routeConfig) {
94
91
  });
95
92
  await server.register(pluginViews);
96
93
  await server.register(pluginEngine);
97
- await server.register(pluginRouter);
94
+ await server.register({
95
+ plugin: {
96
+ name: 'router',
97
+ register: server => {
98
+ server.route(publicRoutes);
99
+ }
100
+ }
101
+ });
98
102
  await server.register(pluginErrorPages);
99
103
  await server.register(blipp);
100
104
  await server.register(requestTracing);
101
- server.state('cookieConsent', {
102
- ttl: 365 * 24 * 60 * 60 * 1000,
103
- // 1 year in ms
104
- clearInvalid: true,
105
- isHttpOnly: false,
106
- isSecure: config.get('isProduction'),
107
- path: '/',
108
- encoding: 'none' // handle this inside the application so we can share frontend/backend cookie modification
109
- });
110
105
  return server;
111
106
  }
112
107
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Engine","CatboxMemory","CatboxRedis","hapi","inert","Scooter","Wreck","blipp","ProxyAgent","config","requestLogger","requestTracing","buildRedisClient","configureBlankiePlugin","configureCrumbPlugin","configureEnginePlugin","pluginErrorPages","plugin","pluginViews","pluginPulse","pluginRouter","pluginSession","prepareSecureContext","proxyAgent","agents","https","http","httpsAllowUnauthorized","serverOptions","debug","request","get","port","router","stripTrailingSlash","routes","validate","options","abortEarly","security","hsts","maxAge","includeSubDomains","preload","xss","noSniff","xframe","cache","name","engine","client","createServer","routeConfig","server","register","pluginEngine","pluginCrumb","pluginBlankie","ext","h","response","continue","header","path","startsWith","state","ttl","clearInvalid","isHttpOnly","isSecure","encoding"],"sources":["../../src/server/index.ts"],"sourcesContent":["import { Engine as CatboxMemory } from '@hapi/catbox-memory'\nimport { Engine as CatboxRedis } from '@hapi/catbox-redis'\nimport hapi, {\n type Request,\n type ResponseToolkit,\n type ServerOptions\n} from '@hapi/hapi'\nimport inert from '@hapi/inert'\nimport Scooter from '@hapi/scooter'\nimport Wreck from '@hapi/wreck'\nimport blipp from 'blipp'\nimport { ProxyAgent } from 'proxy-agent'\n\nimport { config } from '~/src/config/index.js'\nimport { requestLogger } from '~/src/server/common/helpers/logging/request-logger.js'\nimport { requestTracing } from '~/src/server/common/helpers/logging/request-tracing.js'\nimport { buildRedisClient } from '~/src/server/common/helpers/redis-client.js'\nimport { configureBlankiePlugin } from '~/src/server/plugins/blankie.js'\nimport { configureCrumbPlugin } from '~/src/server/plugins/crumb.js'\nimport { configureEnginePlugin } from '~/src/server/plugins/engine/index.js'\nimport pluginErrorPages from '~/src/server/plugins/errorPages.js'\nimport { plugin as pluginViews } from '~/src/server/plugins/nunjucks/index.js'\nimport pluginPulse from '~/src/server/plugins/pulse.js'\nimport pluginRouter from '~/src/server/plugins/router.js'\nimport pluginSession from '~/src/server/plugins/session.js'\nimport { prepareSecureContext } from '~/src/server/secure-context.js'\nimport { type RouteConfig } from '~/src/server/types.js'\n\nconst proxyAgent = new ProxyAgent()\n\nWreck.agents = {\n https: proxyAgent,\n http: proxyAgent,\n httpsAllowUnauthorized: proxyAgent\n}\n\nconst serverOptions = (): ServerOptions => {\n const serverOptions: ServerOptions = {\n debug: { request: [`${config.get('isDevelopment')}`] },\n port: config.get('port'),\n router: {\n stripTrailingSlash: true\n },\n routes: {\n validate: {\n options: {\n abortEarly: false\n }\n },\n security: {\n hsts: {\n maxAge: 31536000,\n includeSubDomains: true,\n preload: false\n },\n xss: 'enabled',\n noSniff: true,\n xframe: true\n }\n },\n cache: [\n {\n name: 'session',\n engine: config.get('isTest')\n ? new CatboxMemory()\n : new CatboxRedis({\n client: buildRedisClient()\n })\n }\n ]\n }\n\n return serverOptions\n}\n\nexport async function createServer(routeConfig?: RouteConfig) {\n const server = hapi.server(serverOptions())\n\n await server.register(requestLogger)\n\n if (config.get('isProduction')) {\n prepareSecureContext(server)\n }\n\n const pluginEngine = await configureEnginePlugin(routeConfig)\n const pluginCrumb = configureCrumbPlugin(routeConfig)\n const pluginBlankie = configureBlankiePlugin()\n\n await server.register(pluginSession)\n await server.register(pluginPulse)\n await server.register(inert)\n await server.register(Scooter)\n await server.register(pluginBlankie)\n await server.register(pluginCrumb)\n\n server.ext('onPreResponse', (request: Request, h: ResponseToolkit) => {\n const { response } = request\n\n if ('isBoom' in response) {\n return h.continue\n }\n\n // Prevent search engine indexing\n response.header('x-robots-tag', 'noindex, nofollow')\n\n // Disable cache to ensure back/foward navigation updates progress\n if (\n !request.path.startsWith('/javascripts/') &&\n !request.path.startsWith('/stylesheets/') &&\n !request.path.startsWith('/assets/')\n ) {\n response.header('cache-control', 'no-store')\n }\n\n return h.continue\n })\n\n await server.register(pluginViews)\n await server.register(pluginEngine)\n await server.register(pluginRouter)\n await server.register(pluginErrorPages)\n await server.register(blipp)\n await server.register(requestTracing)\n\n server.state('cookieConsent', {\n ttl: 365 * 24 * 60 * 60 * 1000, // 1 year in ms\n clearInvalid: true,\n isHttpOnly: false,\n isSecure: config.get('isProduction'),\n path: '/',\n encoding: 'none' // handle this inside the application so we can share frontend/backend cookie modification\n })\n\n return server\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"index.js","names":["Engine","CatboxMemory","CatboxRedis","hapi","inert","Scooter","Wreck","blipp","ProxyAgent","config","requestLogger","requestTracing","buildRedisClient","configureCrumbPlugin","configureEnginePlugin","pluginErrorPages","plugin","pluginViews","pluginPulse","pluginSession","publicRoutes","prepareSecureContext","proxyAgent","agents","https","http","httpsAllowUnauthorized","serverOptions","debug","request","get","port","router","stripTrailingSlash","routes","validate","options","abortEarly","security","hsts","maxAge","includeSubDomains","preload","xss","noSniff","xframe","cache","name","engine","client","createServer","routeConfig","server","register","pluginCrumb","pluginEngine","ext","h","response","continue","header","path","startsWith","route"],"sources":["../../src/server/index.ts"],"sourcesContent":["import { Engine as CatboxMemory } from '@hapi/catbox-memory'\nimport { Engine as CatboxRedis } from '@hapi/catbox-redis'\nimport hapi, {\n type Request,\n type ResponseToolkit,\n type ServerOptions\n} from '@hapi/hapi'\nimport inert from '@hapi/inert'\nimport Scooter from '@hapi/scooter'\nimport Wreck from '@hapi/wreck'\nimport blipp from 'blipp'\nimport { ProxyAgent } from 'proxy-agent'\n\nimport { config } from '~/src/config/index.js'\nimport { requestLogger } from '~/src/server/common/helpers/logging/request-logger.js'\nimport { requestTracing } from '~/src/server/common/helpers/logging/request-tracing.js'\nimport { buildRedisClient } from '~/src/server/common/helpers/redis-client.js'\nimport { configureCrumbPlugin } from '~/src/server/plugins/crumb.js'\nimport { configureEnginePlugin } from '~/src/server/plugins/engine/configureEnginePlugin.js'\nimport pluginErrorPages from '~/src/server/plugins/errorPages.js'\nimport { plugin as pluginViews } from '~/src/server/plugins/nunjucks/index.js'\nimport pluginPulse from '~/src/server/plugins/pulse.js'\nimport pluginSession from '~/src/server/plugins/session.js'\nimport { publicRoutes } from '~/src/server/routes/index.js'\nimport { prepareSecureContext } from '~/src/server/secure-context.js'\nimport { type RouteConfig } from '~/src/server/types.js'\n\nconst proxyAgent = new ProxyAgent()\n\nWreck.agents = {\n https: proxyAgent,\n http: proxyAgent,\n httpsAllowUnauthorized: proxyAgent\n}\n\nconst serverOptions = (): ServerOptions => {\n const serverOptions: ServerOptions = {\n debug: { request: [`${config.get('isDevelopment')}`] },\n port: config.get('port'),\n router: {\n stripTrailingSlash: true\n },\n routes: {\n validate: {\n options: {\n abortEarly: false\n }\n },\n security: {\n hsts: {\n maxAge: 31536000,\n includeSubDomains: true,\n preload: false\n },\n xss: 'enabled',\n noSniff: true,\n xframe: true\n }\n },\n cache: [\n {\n name: 'session',\n engine: config.get('isTest')\n ? new CatboxMemory()\n : new CatboxRedis({\n client: buildRedisClient()\n })\n }\n ]\n }\n\n return serverOptions\n}\n\nexport async function createServer(routeConfig?: RouteConfig) {\n const server = hapi.server(serverOptions())\n\n await server.register(requestLogger)\n\n if (config.get('isProduction')) {\n prepareSecureContext(server)\n }\n\n const pluginCrumb = configureCrumbPlugin(routeConfig)\n const pluginEngine = await configureEnginePlugin(routeConfig)\n\n await server.register(pluginSession)\n await server.register(pluginPulse)\n await server.register(inert)\n await server.register(Scooter)\n await server.register(pluginCrumb)\n\n server.ext('onPreResponse', (request: Request, h: ResponseToolkit) => {\n const { response } = request\n\n if ('isBoom' in response) {\n return h.continue\n }\n\n // Prevent search engine indexing\n response.header('x-robots-tag', 'noindex, nofollow')\n\n // Disable cache to ensure back/foward navigation updates progress\n if (\n !request.path.startsWith('/javascripts/') &&\n !request.path.startsWith('/stylesheets/') &&\n !request.path.startsWith('/assets/')\n ) {\n response.header('cache-control', 'no-store')\n }\n\n return h.continue\n })\n\n await server.register(pluginViews)\n await server.register(pluginEngine)\n\n await server.register({\n plugin: {\n name: 'router',\n register: (server) => {\n server.route(publicRoutes)\n }\n }\n })\n\n await server.register(pluginErrorPages)\n await server.register(blipp)\n await server.register(requestTracing)\n\n return server\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,6 +1,10 @@
1
1
  import { join, parse } from 'node:path';
2
2
  import { FormModel } from "./models/FormModel.js";
3
3
  import { plugin } from "./plugin.js";
4
+ import { findPackageRoot } from "./plugin.js";
5
+ import * as defaultServices from "./services/index.js";
6
+ import { formsService } from "./services/localFormsService.js";
7
+ import { devtoolContext } from "../nunjucks/context.js";
4
8
  export const configureEnginePlugin = async ({
5
9
  formFileName,
6
10
  formFilePath,
@@ -21,8 +25,18 @@ export const configureEnginePlugin = async ({
21
25
  plugin,
22
26
  options: {
23
27
  model,
24
- services,
25
- controllers
28
+ services: services ?? {
29
+ // services for testing, else use the disk loader option for running this service locally
30
+ ...defaultServices,
31
+ formsService: await formsService()
32
+ },
33
+ controllers,
34
+ cacheName: 'session',
35
+ nunjucks: {
36
+ baseLayoutPath: 'dxt-devtool-baselayout.html',
37
+ paths: [join(findPackageRoot(), 'src/server/devserver')] // custom layout to make it really clear this is not the same as the runner
38
+ },
39
+ viewContext: devtoolContext
26
40
  }
27
41
  };
28
42
  };
@@ -1 +1 @@
1
- {"version":3,"file":"configureEnginePlugin.js","names":["join","parse","FormModel","plugin","configureEnginePlugin","formFileName","formFilePath","services","controllers","model","definition","getForm","name","basePath","options","importPath","ext","attributes","type","formImport","with","default"],"sources":["../../../../src/server/plugins/engine/configureEnginePlugin.ts"],"sourcesContent":["import { join, parse } from 'node:path'\n\nimport { type FormDefinition } from '@defra/forms-model'\nimport { type ServerRegisterPluginObject } from '@hapi/hapi'\n\nimport { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'\nimport {\n plugin,\n type PluginOptions\n} from '~/src/server/plugins/engine/plugin.js'\nimport { type RouteConfig } from '~/src/server/types.js'\n\nexport const configureEnginePlugin = async ({\n formFileName,\n formFilePath,\n services,\n controllers\n}: RouteConfig = {}): Promise<ServerRegisterPluginObject<PluginOptions>> => {\n let model: FormModel | undefined\n\n if (formFileName && formFilePath) {\n const definition = await getForm(join(formFilePath, formFileName))\n const { name } = parse(formFileName)\n\n model = new FormModel(definition, { basePath: name }, services, controllers)\n }\n\n return {\n plugin,\n options: { model, services, controllers }\n }\n}\n\nexport async function getForm(importPath: string) {\n const { ext } = parse(importPath)\n\n const attributes: ImportAttributes = {\n type: ext === '.json' ? 'json' : 'module'\n }\n\n const formImport = import(importPath, { with: attributes }) as Promise<{\n default: FormDefinition\n }>\n\n const { default: definition } = await formImport\n return definition\n}\n"],"mappings":"AAAA,SAASA,IAAI,EAAEC,KAAK,QAAQ,WAAW;AAKvC,SAASC,SAAS;AAClB,SACEC,MAAM;AAKR,OAAO,MAAMC,qBAAqB,GAAG,MAAAA,CAAO;EAC1CC,YAAY;EACZC,YAAY;EACZC,QAAQ;EACRC;AACW,CAAC,GAAG,CAAC,CAAC,KAAyD;EAC1E,IAAIC,KAA4B;EAEhC,IAAIJ,YAAY,IAAIC,YAAY,EAAE;IAChC,MAAMI,UAAU,GAAG,MAAMC,OAAO,CAACX,IAAI,CAACM,YAAY,EAAED,YAAY,CAAC,CAAC;IAClE,MAAM;MAAEO;IAAK,CAAC,GAAGX,KAAK,CAACI,YAAY,CAAC;IAEpCI,KAAK,GAAG,IAAIP,SAAS,CAACQ,UAAU,EAAE;MAAEG,QAAQ,EAAED;IAAK,CAAC,EAAEL,QAAQ,EAAEC,WAAW,CAAC;EAC9E;EAEA,OAAO;IACLL,MAAM;IACNW,OAAO,EAAE;MAAEL,KAAK;MAAEF,QAAQ;MAAEC;IAAY;EAC1C,CAAC;AACH,CAAC;AAED,OAAO,eAAeG,OAAOA,CAACI,UAAkB,EAAE;EAChD,MAAM;IAAEC;EAAI,CAAC,GAAGf,KAAK,CAACc,UAAU,CAAC;EAEjC,MAAME,UAA4B,GAAG;IACnCC,IAAI,EAAEF,GAAG,KAAK,OAAO,GAAG,MAAM,GAAG;EACnC,CAAC;EAED,MAAMG,UAAU,GAAG,MAAM,CAACJ,UAAU,EAAE;IAAEK,IAAI,EAAEH;EAAW,CAAC,CAExD;EAEF,MAAM;IAAEI,OAAO,EAAEX;EAAW,CAAC,GAAG,MAAMS,UAAU;EAChD,OAAOT,UAAU;AACnB","ignoreList":[]}
1
+ {"version":3,"file":"configureEnginePlugin.js","names":["join","parse","FormModel","plugin","findPackageRoot","defaultServices","formsService","devtoolContext","configureEnginePlugin","formFileName","formFilePath","services","controllers","model","definition","getForm","name","basePath","options","cacheName","nunjucks","baseLayoutPath","paths","viewContext","importPath","ext","attributes","type","formImport","with","default"],"sources":["../../../../src/server/plugins/engine/configureEnginePlugin.ts"],"sourcesContent":["import { join, parse } from 'node:path'\n\nimport { type FormDefinition } from '@defra/forms-model'\nimport { type ServerRegisterPluginObject } from '@hapi/hapi'\n\nimport { FormModel } from '~/src/server/plugins/engine/models/FormModel.js'\nimport {\n plugin,\n type PluginOptions\n} from '~/src/server/plugins/engine/plugin.js'\nimport { findPackageRoot } from '~/src/server/plugins/engine/plugin.js'\nimport * as defaultServices from '~/src/server/plugins/engine/services/index.js'\nimport { formsService } from '~/src/server/plugins/engine/services/localFormsService.js'\nimport { devtoolContext } from '~/src/server/plugins/nunjucks/context.js'\nimport { type RouteConfig } from '~/src/server/types.js'\n\nexport const configureEnginePlugin = async ({\n formFileName,\n formFilePath,\n services,\n controllers\n}: RouteConfig = {}): Promise<ServerRegisterPluginObject<PluginOptions>> => {\n let model: FormModel | undefined\n\n if (formFileName && formFilePath) {\n const definition = await getForm(join(formFilePath, formFileName))\n const { name } = parse(formFileName)\n\n model = new FormModel(definition, { basePath: name }, services, controllers)\n }\n\n return {\n plugin,\n options: {\n model,\n services: services ?? {\n // services for testing, else use the disk loader option for running this service locally\n ...defaultServices,\n formsService: await formsService()\n },\n controllers,\n cacheName: 'session',\n nunjucks: {\n baseLayoutPath: 'dxt-devtool-baselayout.html',\n paths: [join(findPackageRoot(), 'src/server/devserver')] // custom layout to make it really clear this is not the same as the runner\n },\n viewContext: devtoolContext\n }\n }\n}\n\nexport async function getForm(importPath: string) {\n const { ext } = parse(importPath)\n\n const attributes: ImportAttributes = {\n type: ext === '.json' ? 'json' : 'module'\n }\n\n const formImport = import(importPath, { with: attributes }) as Promise<{\n default: FormDefinition\n }>\n\n const { default: definition } = await formImport\n return definition\n}\n"],"mappings":"AAAA,SAASA,IAAI,EAAEC,KAAK,QAAQ,WAAW;AAKvC,SAASC,SAAS;AAClB,SACEC,MAAM;AAGR,SAASC,eAAe;AACxB,OAAO,KAAKC,eAAe;AAC3B,SAASC,YAAY;AACrB,SAASC,cAAc;AAGvB,OAAO,MAAMC,qBAAqB,GAAG,MAAAA,CAAO;EAC1CC,YAAY;EACZC,YAAY;EACZC,QAAQ;EACRC;AACW,CAAC,GAAG,CAAC,CAAC,KAAyD;EAC1E,IAAIC,KAA4B;EAEhC,IAAIJ,YAAY,IAAIC,YAAY,EAAE;IAChC,MAAMI,UAAU,GAAG,MAAMC,OAAO,CAACf,IAAI,CAACU,YAAY,EAAED,YAAY,CAAC,CAAC;IAClE,MAAM;MAAEO;IAAK,CAAC,GAAGf,KAAK,CAACQ,YAAY,CAAC;IAEpCI,KAAK,GAAG,IAAIX,SAAS,CAACY,UAAU,EAAE;MAAEG,QAAQ,EAAED;IAAK,CAAC,EAAEL,QAAQ,EAAEC,WAAW,CAAC;EAC9E;EAEA,OAAO;IACLT,MAAM;IACNe,OAAO,EAAE;MACPL,KAAK;MACLF,QAAQ,EAAEA,QAAQ,IAAI;QACpB;QACA,GAAGN,eAAe;QAClBC,YAAY,EAAE,MAAMA,YAAY,CAAC;MACnC,CAAC;MACDM,WAAW;MACXO,SAAS,EAAE,SAAS;MACpBC,QAAQ,EAAE;QACRC,cAAc,EAAE,6BAA6B;QAC7CC,KAAK,EAAE,CAACtB,IAAI,CAACI,eAAe,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC;MAC3D,CAAC;MACDmB,WAAW,EAAEhB;IACf;EACF,CAAC;AACH,CAAC;AAED,OAAO,eAAeQ,OAAOA,CAACS,UAAkB,EAAE;EAChD,MAAM;IAAEC;EAAI,CAAC,GAAGxB,KAAK,CAACuB,UAAU,CAAC;EAEjC,MAAME,UAA4B,GAAG;IACnCC,IAAI,EAAEF,GAAG,KAAK,OAAO,GAAG,MAAM,GAAG;EACnC,CAAC;EAED,MAAMG,UAAU,GAAG,MAAM,CAACJ,UAAU,EAAE;IAAEK,IAAI,EAAEH;EAAW,CAAC,CAExD;EAEF,MAAM;IAAEI,OAAO,EAAEhB;EAAW,CAAC,GAAG,MAAMc,UAAU;EAChD,OAAOd,UAAU;AACnB","ignoreList":[]}
@@ -1,12 +1,16 @@
1
+ import { existsSync } from 'fs';
2
+ import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
1
4
  import { hasFormComponents, slugSchema } from '@defra/forms-model';
2
5
  import Boom from '@hapi/boom';
3
6
  import vision from '@hapi/vision';
4
7
  import { isEqual } from 'date-fns';
5
8
  import Joi from 'joi';
6
9
  import nunjucks from 'nunjucks';
10
+ import resolvePkg from 'resolve';
7
11
  import { PREVIEW_PATH_PREFIX } from "../../constants.js";
8
12
  import { checkEmailAddressForLiveFormSubmission, checkFormStatus, findPage, getCacheService, getPage, getStartPath, normalisePath, proceed, redirectPath } from "./helpers.js";
9
- import { PLUGIN_PATH, VIEW_PATH, context, prepareNunjucksEnvironment } from "./index.js";
13
+ import { VIEW_PATH, context, prepareNunjucksEnvironment } from "./index.js";
10
14
  import { FormModel, SummaryViewModel } from "./models/index.js";
11
15
  import { format } from "./outputFormatters/machine/v1.js";
12
16
  import { FileUploadPageController } from "./pageControllers/FileUploadPageController.js";
@@ -18,6 +22,18 @@ import { getUploadStatus } from "./services/uploadService.js";
18
22
  import { actionSchema, confirmSchema, crumbSchema, itemIdSchema, pathSchema, stateSchema } from "../../schemas/index.js";
19
23
  import * as httpService from "../../services/httpService.js";
20
24
  import { CacheService } from "../../services/index.js";
25
+ export function findPackageRoot() {
26
+ const currentFileName = fileURLToPath(import.meta.url);
27
+ const currentDirectoryName = dirname(currentFileName);
28
+ let dir = currentDirectoryName;
29
+ while (dir !== '/') {
30
+ if (existsSync(join(dir, 'package.json'))) {
31
+ return dir;
32
+ }
33
+ dir = dirname(dir);
34
+ }
35
+ throw new Error('package.json not found in parent directories');
36
+ }
21
37
  export const plugin = {
22
38
  name: '@defra/forms-engine-plugin',
23
39
  dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],
@@ -28,25 +44,18 @@ export const plugin = {
28
44
  services = defaultServices,
29
45
  controllers,
30
46
  cacheName,
31
- viewPaths,
32
47
  filters,
33
- pluginPath = PLUGIN_PATH
48
+ nunjucks: nunjucksOptions,
49
+ viewContext
34
50
  } = options;
35
51
  const {
36
52
  formsService
37
53
  } = services;
38
54
  const cacheService = new CacheService(server, cacheName);
39
-
40
- // Paths array to tell `vision` and `nunjucks` where template files are stored.
41
- // We need to include `VIEW_PATH` in addition the runtime path (node_modules)
42
- // to keep the local tests working
43
- const path = [`${pluginPath}/${VIEW_PATH}`, VIEW_PATH];
44
-
45
- // Include any additional user provided view paths so our internal views engine
46
- // can find any files they provide from the consumer side if using custom `page.view`s
47
- if (Array.isArray(viewPaths) && viewPaths.length) {
48
- path.push(...viewPaths);
49
- }
55
+ const packageRoot = findPackageRoot();
56
+ const govukFrontendPath = dirname(resolvePkg.sync('govuk-frontend/package.json'));
57
+ const viewPathResolved = join(packageRoot, VIEW_PATH);
58
+ const paths = [...nunjucksOptions.paths, viewPathResolved, join(govukFrontendPath, 'dist')];
50
59
  await server.register({
51
60
  plugin: vision,
52
61
  options: {
@@ -61,7 +70,7 @@ export const plugin = {
61
70
  prepare: (options, next) => {
62
71
  // Nunjucks also needs an additional path configuration
63
72
  // to use the templates and macros from `govuk-frontend`
64
- const environment = nunjucks.configure([...path, 'node_modules/govuk-frontend/dist']);
73
+ const environment = nunjucks.configure(paths);
65
74
 
66
75
  // Applies custom filters and globals for nunjucks
67
76
  // that are required by the `forms-engine-plugin`
@@ -71,11 +80,13 @@ export const plugin = {
71
80
  }
72
81
  }
73
82
  },
74
- path,
83
+ path: paths,
75
84
  // Provides global context used with all templates
76
85
  context
77
86
  }
78
87
  });
88
+ server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath);
89
+ server.expose('viewContext', viewContext);
79
90
  server.expose('cacheService', cacheService);
80
91
  server.app.model = model;
81
92