@defra/forms-engine-plugin 1.0.1 → 1.0.3

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 (47) hide show
  1. package/.server/server/plugins/engine/configureEnginePlugin.d.ts +2 -1
  2. package/.server/server/plugins/engine/configureEnginePlugin.js +1 -1
  3. package/.server/server/plugins/engine/configureEnginePlugin.js.map +1 -1
  4. package/.server/server/plugins/engine/options.d.ts +7 -0
  5. package/.server/server/plugins/engine/options.js +36 -0
  6. package/.server/server/plugins/engine/options.js.map +1 -0
  7. package/.server/server/plugins/engine/options.test.js +33 -0
  8. package/.server/server/plugins/engine/options.test.js.map +1 -0
  9. package/.server/server/plugins/engine/plugin.d.ts +2 -30
  10. package/.server/server/plugins/engine/plugin.js +12 -596
  11. package/.server/server/plugins/engine/plugin.js.map +1 -1
  12. package/.server/server/plugins/engine/registrationOptions.d.ts +1 -0
  13. package/.server/server/plugins/engine/registrationOptions.js +2 -0
  14. package/.server/server/plugins/engine/registrationOptions.js.map +1 -0
  15. package/.server/server/plugins/engine/routes/file-upload.d.ts +4 -0
  16. package/.server/server/plugins/engine/routes/file-upload.js +41 -0
  17. package/.server/server/plugins/engine/routes/file-upload.js.map +1 -0
  18. package/.server/server/plugins/engine/routes/index.d.ts +7 -0
  19. package/.server/server/plugins/engine/routes/index.js +141 -0
  20. package/.server/server/plugins/engine/routes/index.js.map +1 -0
  21. package/.server/server/plugins/engine/routes/questions.d.ts +3 -0
  22. package/.server/server/plugins/engine/routes/questions.js +168 -0
  23. package/.server/server/plugins/engine/routes/questions.js.map +1 -0
  24. package/.server/server/plugins/engine/routes/repeaters/item-delete.d.ts +3 -0
  25. package/.server/server/plugins/engine/routes/repeaters/item-delete.js +106 -0
  26. package/.server/server/plugins/engine/routes/repeaters/item-delete.js.map +1 -0
  27. package/.server/server/plugins/engine/routes/repeaters/summary.d.ts +3 -0
  28. package/.server/server/plugins/engine/routes/repeaters/summary.js +98 -0
  29. package/.server/server/plugins/engine/routes/repeaters/summary.js.map +1 -0
  30. package/.server/server/plugins/engine/types.d.ts +19 -1
  31. package/.server/server/plugins/engine/types.js.map +1 -1
  32. package/.server/server/plugins/engine/vision.d.ts +12 -0
  33. package/.server/server/plugins/engine/vision.js +55 -0
  34. package/.server/server/plugins/engine/vision.js.map +1 -0
  35. package/package.json +1 -1
  36. package/src/server/plugins/engine/configureEnginePlugin.ts +3 -5
  37. package/src/server/plugins/engine/options.js +37 -0
  38. package/src/server/plugins/engine/options.test.js +34 -0
  39. package/src/server/plugins/engine/plugin.ts +30 -772
  40. package/src/server/plugins/engine/registrationOptions.ts +0 -0
  41. package/src/server/plugins/engine/routes/file-upload.ts +54 -0
  42. package/src/server/plugins/engine/routes/index.ts +187 -0
  43. package/src/server/plugins/engine/routes/questions.ts +208 -0
  44. package/src/server/plugins/engine/routes/repeaters/item-delete.ts +157 -0
  45. package/src/server/plugins/engine/routes/repeaters/summary.ts +137 -0
  46. package/src/server/plugins/engine/types.ts +26 -1
  47. package/src/server/plugins/engine/vision.ts +95 -0
@@ -1,60 +1,25 @@
1
- import { existsSync } from 'fs';
2
- import { dirname, join } from 'path';
3
- import { fileURLToPath } from 'url';
4
- import { getErrorMessage, hasFormComponents, slugSchema } from '@defra/forms-model';
5
- import Boom from '@hapi/boom';
6
- import vision from '@hapi/vision';
7
- import { isEqual } from 'date-fns';
8
- import Joi from 'joi';
9
- import nunjucks from 'nunjucks';
10
- import resolvePkg from 'resolve';
11
- import { PREVIEW_PATH_PREFIX } from "../../constants.js";
12
- import { checkEmailAddressForLiveFormSubmission, checkFormStatus, findPage, getCacheService, getPage, getStartPath, normalisePath, proceed, redirectPath } from "./helpers.js";
13
- import { VIEW_PATH, context, prepareNunjucksEnvironment } from "./index.js";
14
- import { FormModel, SummaryViewModel } from "./models/index.js";
15
- import { format } from "./outputFormatters/machine/v1.js";
16
- import { FileUploadPageController } from "./pageControllers/FileUploadPageController.js";
17
- import { RepeatPageController } from "./pageControllers/RepeatPageController.js";
18
- import { getFormSubmissionData } from "./pageControllers/SummaryPageController.js";
19
- import { generateUniqueReference } from "./referenceNumbers.js";
20
- import * as defaultServices from "./services/index.js";
21
- import { getUploadStatus } from "./services/uploadService.js";
22
- import { actionSchema, confirmSchema, crumbSchema, itemIdSchema, pathSchema, stateSchema } from "../../schemas/index.js";
23
- import * as httpService from "../../services/httpService.js";
1
+ import { validatePluginOptions } from "./options.js";
2
+ import { getRoutes as getFileUploadStatusRoutes } from "./routes/file-upload.js";
3
+ import { makeLoadFormPreHandler } from "./routes/index.js";
4
+ import { getRoutes as getQuestionRoutes } from "./routes/questions.js";
5
+ import { getRoutes as getRepeaterItemDeleteRoutes } from "./routes/repeaters/item-delete.js";
6
+ import { getRoutes as getRepeaterSummaryRoutes } from "./routes/repeaters/summary.js";
7
+ import { registerVision } from "./vision.js";
24
8
  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
- }
37
9
  export const plugin = {
38
10
  name: '@defra/forms-engine-plugin',
39
11
  dependencies: ['@hapi/crumb', '@hapi/yar', 'hapi-pino'],
40
12
  multiple: true,
41
13
  async register(server, options) {
42
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- hapi types are wrong
43
- const prefix = server.realm.modifiers.route.prefix ?? '';
14
+ options = validatePluginOptions(options);
44
15
  const {
45
16
  model,
46
- services = defaultServices,
47
- controllers,
48
17
  cacheName,
49
18
  keyGenerator,
50
19
  sessionHydrator,
51
- filters,
52
20
  nunjucks: nunjucksOptions,
53
21
  viewContext
54
22
  } = options;
55
- const {
56
- formsService
57
- } = services;
58
23
  const cacheService = new CacheService({
59
24
  server,
60
25
  cacheName,
@@ -63,39 +28,7 @@ export const plugin = {
63
28
  sessionHydrator
64
29
  }
65
30
  });
66
- const packageRoot = findPackageRoot();
67
- const govukFrontendPath = dirname(resolvePkg.sync('govuk-frontend/package.json'));
68
- const viewPathResolved = join(packageRoot, VIEW_PATH);
69
- const paths = [...nunjucksOptions.paths, viewPathResolved, join(govukFrontendPath, 'dist')];
70
- await server.register({
71
- plugin: vision,
72
- options: {
73
- engines: {
74
- html: {
75
- compile: (path, compileOptions) => {
76
- const template = nunjucks.compile(path, compileOptions.environment);
77
- return context => {
78
- return template.render(context);
79
- };
80
- },
81
- prepare: (options, next) => {
82
- // Nunjucks also needs an additional path configuration
83
- // to use the templates and macros from `govuk-frontend`
84
- const environment = nunjucks.configure(paths);
85
-
86
- // Applies custom filters and globals for nunjucks
87
- // that are required by the `forms-engine-plugin`
88
- prepareNunjucksEnvironment(environment, filters);
89
- options.compileOptions.environment = environment;
90
- next();
91
- }
92
- }
93
- },
94
- path: paths,
95
- // Provides global context used with all templates
96
- context
97
- }
98
- });
31
+ await registerVision(server, options);
99
32
  server.expose('baseLayoutPath', nunjucksOptions.baseLayoutPath);
100
33
  server.expose('viewContext', viewContext);
101
34
  server.expose('cacheService', cacheService);
@@ -105,258 +38,12 @@ export const plugin = {
105
38
  // (for testing purposes) through `server.app.models`
106
39
  const itemCache = new Map();
107
40
  server.app.models = itemCache;
108
- const loadFormPreHandler = async (request, h) => {
109
- if (server.app.model) {
110
- request.app.model = server.app.model;
111
- return h.continue;
112
- }
113
- const {
114
- params
115
- } = request;
116
- const {
117
- slug
118
- } = params;
119
- const {
120
- isPreview,
121
- state: formState
122
- } = checkFormStatus(params);
123
-
124
- // Get the form metadata using the `slug` param
125
- const metadata = await formsService.getFormMetadata(slug);
126
- const {
127
- id,
128
- [formState]: state
129
- } = metadata;
130
-
131
- // Check the metadata supports the requested state
132
- if (!state) {
133
- throw Boom.notFound(`No '${formState}' state for form metadata ${id}`);
134
- }
135
-
136
- // Cache the models based on id, state and whether
137
- // it's a preview or not. There could be up to 3 models
138
- // cached for a single form:
139
- // "{id}_live_false" (live/live)
140
- // "{id}_live_true" (live/preview)
141
- // "{id}_draft_true" (draft/preview)
142
- const key = `${id}_${formState}_${isPreview}`;
143
- let item = itemCache.get(key);
144
- if (!item || !isEqual(item.updatedAt, state.updatedAt)) {
145
- server.logger.info(`Getting form definition ${id} (${slug}) ${formState}`);
146
-
147
- // Get the form definition using the `id` from the metadata
148
- const definition = await formsService.getFormDefinition(id, formState);
149
- if (!definition) {
150
- throw Boom.notFound(`No definition found for form metadata ${id} (${slug}) ${formState}`);
151
- }
152
- const emailAddress = metadata.notificationEmail ?? definition.outputEmail;
153
- checkEmailAddressForLiveFormSubmission(emailAddress, isPreview);
154
-
155
- // Build the form model
156
- server.logger.info(`Building model for form definition ${id} (${slug}) ${formState}`);
157
-
158
- // Set up the basePath for the model
159
- const basePath = (isPreview ? `${prefix}${PREVIEW_PATH_PREFIX}/${formState}/${slug}` : `${prefix}/${slug}`).substring(1);
160
-
161
- // Construct the form model
162
- const model = new FormModel(definition, {
163
- basePath
164
- }, services, controllers);
165
-
166
- // Create new item and add it to the item cache
167
- item = {
168
- model,
169
- updatedAt: state.updatedAt
170
- };
171
- itemCache.set(key, item);
172
- }
173
-
174
- // Assign the model to the request data
175
- // for use in the downstream handler
176
- request.app.model = item.model;
177
- return h.continue;
178
- };
179
- const dispatchHandler = (request, h) => {
180
- const {
181
- model
182
- } = request.app;
183
- const servicePath = model ? `/${model.basePath}` : '';
184
- return proceed(request, h, `${servicePath}${getStartPath(model)}`);
185
- };
186
- const redirectOrMakeHandler = async (request, h, makeHandler) => {
187
- const {
188
- app,
189
- params
190
- } = request;
191
- const {
192
- model
193
- } = app;
194
- if (!model) {
195
- throw Boom.notFound(`No model found for /${params.path}`);
196
- }
197
- const cacheService = getCacheService(request.server);
198
- const page = getPage(model, request);
199
- let state = await page.getState(request);
200
- if (!state.$$__referenceNumber) {
201
- const prefix = model.def.metadata?.referenceNumberPrefix ?? '';
202
- if (typeof prefix !== 'string') {
203
- throw Boom.badImplementation('Reference number prefix must be a string or undefined');
204
- }
205
- const referenceNumber = generateUniqueReference(prefix);
206
- state = await page.mergeState(request, state, {
207
- $$__referenceNumber: referenceNumber
208
- });
209
- }
210
- const flash = cacheService.getFlash(request);
211
- const context = model.getFormContext(request, state, flash?.errors);
212
- const relevantPath = page.getRelevantPath(request, context);
213
- const summaryPath = page.getSummaryPath();
214
-
215
- // Return handler for relevant pages or preview URL direct access
216
- if (relevantPath.startsWith(page.path) || context.isForceAccess) {
217
- return makeHandler(page, context);
218
- }
219
-
220
- // Redirect back to last relevant page
221
- const redirectTo = findPage(model, relevantPath);
222
-
223
- // Set the return URL unless an exit page
224
- if (redirectTo?.next.length) {
225
- request.query.returnUrl = page.getHref(summaryPath);
226
- }
227
- return proceed(request, h, page.getHref(relevantPath));
228
- };
229
- const getHandler = (request, h) => {
230
- const {
231
- params
232
- } = request;
233
- if (normalisePath(params.path) === '') {
234
- return dispatchHandler(request, h);
235
- }
236
- return redirectOrMakeHandler(request, h, async (page, context) => {
237
- // Check for a page onLoad HTTP event and if one exists,
238
- // call it and assign the response to the context data
239
- const {
240
- events
241
- } = page;
242
- const {
243
- model
244
- } = request.app;
245
- if (!model) {
246
- throw Boom.notFound(`No model found for /${params.path}`);
247
- }
248
- if (events?.onLoad && events.onLoad.type === 'http') {
249
- const {
250
- options
251
- } = events.onLoad;
252
- const {
253
- url
254
- } = options;
255
-
256
- // TODO: Update structured data POST payload with when helper
257
- // is updated to removing the dependency on `SummaryViewModel` etc.
258
- const viewModel = new SummaryViewModel(request, page, context);
259
- const items = getFormSubmissionData(viewModel.context, viewModel.details);
260
-
261
- // @ts-expect-error - function signature will be refactored in the next iteration of the formatter
262
- const payload = format(items, model, undefined, undefined);
263
- const {
264
- payload: response
265
- } = await httpService.postJson(url, {
266
- payload
267
- });
268
- Object.assign(context.data, response);
269
- }
270
- return page.makeGetRouteHandler()(request, context, h);
271
- });
272
- };
273
- const postHandler = (request, h) => {
274
- const {
275
- query
276
- } = request;
277
- return redirectOrMakeHandler(request, h, (page, context) => {
278
- const {
279
- pageDef
280
- } = page;
281
- const {
282
- isForceAccess
283
- } = context;
284
-
285
- // Redirect to GET for preview URL direct access
286
- if (isForceAccess && !hasFormComponents(pageDef)) {
287
- return proceed(request, h, redirectPath(page.href, query));
288
- }
289
- return page.makePostRouteHandler()(request, context, h);
290
- });
291
- };
292
- const dispatchRouteOptions = {
293
- pre: [{
294
- method: loadFormPreHandler
295
- }]
296
- };
297
- server.route({
298
- method: 'get',
299
- path: '/{slug}',
300
- handler: dispatchHandler,
301
- options: {
302
- ...dispatchRouteOptions,
303
- validate: {
304
- params: Joi.object().keys({
305
- slug: slugSchema
306
- })
307
- }
308
- }
309
- });
310
- server.route({
311
- method: 'get',
312
- path: '/preview/{state}/{slug}',
313
- handler: dispatchHandler,
314
- options: {
315
- ...dispatchRouteOptions,
316
- validate: {
317
- params: Joi.object().keys({
318
- state: stateSchema,
319
- slug: slugSchema
320
- })
321
- }
322
- }
323
- });
41
+ const loadFormPreHandler = makeLoadFormPreHandler(server, options);
324
42
  const getRouteOptions = {
325
43
  pre: [{
326
44
  method: loadFormPreHandler
327
45
  }]
328
46
  };
329
- server.route({
330
- method: 'get',
331
- path: '/{slug}/{path}/{itemId?}',
332
- handler: getHandler,
333
- options: {
334
- ...getRouteOptions,
335
- validate: {
336
- params: Joi.object().keys({
337
- slug: slugSchema,
338
- path: pathSchema,
339
- itemId: itemIdSchema.optional()
340
- })
341
- }
342
- }
343
- });
344
- server.route({
345
- method: 'get',
346
- path: '/preview/{state}/{slug}/{path}/{itemId?}',
347
- handler: getHandler,
348
- options: {
349
- ...getRouteOptions,
350
- validate: {
351
- params: Joi.object().keys({
352
- state: stateSchema,
353
- slug: slugSchema,
354
- path: pathSchema,
355
- itemId: itemIdSchema.optional()
356
- })
357
- }
358
- }
359
- });
360
47
  const postRouteOptions = {
361
48
  payload: {
362
49
  parse: true
@@ -365,279 +52,8 @@ export const plugin = {
365
52
  method: loadFormPreHandler
366
53
  }]
367
54
  };
368
- server.route({
369
- method: 'post',
370
- path: '/{slug}/{path}/{itemId?}',
371
- handler: postHandler,
372
- options: {
373
- ...postRouteOptions,
374
- validate: {
375
- params: Joi.object().keys({
376
- slug: slugSchema,
377
- path: pathSchema,
378
- itemId: itemIdSchema.optional()
379
- }),
380
- payload: Joi.object().keys({
381
- crumb: crumbSchema,
382
- action: actionSchema
383
- }).unknown(true).required()
384
- }
385
- }
386
- });
387
- server.route({
388
- method: 'post',
389
- path: '/preview/{state}/{slug}/{path}/{itemId?}',
390
- handler: postHandler,
391
- options: {
392
- ...postRouteOptions,
393
- validate: {
394
- params: Joi.object().keys({
395
- state: stateSchema,
396
- slug: slugSchema,
397
- path: pathSchema,
398
- itemId: itemIdSchema.optional()
399
- }),
400
- payload: Joi.object().keys({
401
- crumb: crumbSchema,
402
- action: actionSchema
403
- }).unknown(true).required()
404
- }
405
- }
406
- });
407
-
408
- /**
409
- * "AddAnother" repeat routes
410
- */
411
-
412
- // List summary GET route
413
- const getListSummaryHandler = (request, h) => {
414
- const {
415
- params
416
- } = request;
417
- return redirectOrMakeHandler(request, h, (page, context) => {
418
- if (!(page instanceof RepeatPageController)) {
419
- throw Boom.notFound(`No repeater page found for /${params.path}`);
420
- }
421
- return page.makeGetListSummaryRouteHandler()(request, context, h);
422
- });
423
- };
424
- server.route({
425
- method: 'get',
426
- path: '/{slug}/{path}/summary',
427
- handler: getListSummaryHandler,
428
- options: {
429
- ...getRouteOptions,
430
- validate: {
431
- params: Joi.object().keys({
432
- slug: slugSchema,
433
- path: pathSchema
434
- })
435
- }
436
- }
437
- });
438
- server.route({
439
- method: 'get',
440
- path: '/preview/{state}/{slug}/{path}/summary',
441
- handler: getListSummaryHandler,
442
- options: {
443
- ...getRouteOptions,
444
- validate: {
445
- params: Joi.object().keys({
446
- state: stateSchema,
447
- slug: slugSchema,
448
- path: pathSchema
449
- })
450
- }
451
- }
452
- });
453
-
454
- // List summary POST route
455
- const postListSummaryHandler = (request, h) => {
456
- const {
457
- params
458
- } = request;
459
- return redirectOrMakeHandler(request, h, (page, context) => {
460
- const {
461
- isForceAccess
462
- } = context;
463
- if (isForceAccess || !(page instanceof RepeatPageController)) {
464
- throw Boom.notFound(`No repeater page found for /${params.path}`);
465
- }
466
- return page.makePostListSummaryRouteHandler()(request, context, h);
467
- });
468
- };
469
- server.route({
470
- method: 'post',
471
- path: '/{slug}/{path}/summary',
472
- handler: postListSummaryHandler,
473
- options: {
474
- ...postRouteOptions,
475
- validate: {
476
- params: Joi.object().keys({
477
- slug: slugSchema,
478
- path: pathSchema
479
- }),
480
- payload: Joi.object().keys({
481
- crumb: crumbSchema,
482
- action: actionSchema
483
- }).required()
484
- }
485
- }
486
- });
487
- server.route({
488
- method: 'post',
489
- path: '/preview/{state}/{slug}/{path}/summary',
490
- handler: postListSummaryHandler,
491
- options: {
492
- ...postRouteOptions,
493
- validate: {
494
- params: Joi.object().keys({
495
- state: stateSchema,
496
- slug: slugSchema,
497
- path: pathSchema
498
- }),
499
- payload: Joi.object().keys({
500
- crumb: crumbSchema,
501
- action: actionSchema
502
- }).required()
503
- }
504
- }
505
- });
506
-
507
- // Item delete GET route
508
- const getItemDeleteHandler = (request, h) => {
509
- const {
510
- params
511
- } = request;
512
- return redirectOrMakeHandler(request, h, (page, context) => {
513
- if (!(page instanceof RepeatPageController || page instanceof FileUploadPageController)) {
514
- throw Boom.notFound(`No page found for /${params.path}`);
515
- }
516
- return page.makeGetItemDeleteRouteHandler()(request, context, h);
517
- });
518
- };
519
- server.route({
520
- method: 'get',
521
- path: '/{slug}/{path}/{itemId}/confirm-delete',
522
- handler: getItemDeleteHandler,
523
- options: {
524
- ...getRouteOptions,
525
- validate: {
526
- params: Joi.object().keys({
527
- slug: slugSchema,
528
- path: pathSchema,
529
- itemId: itemIdSchema
530
- })
531
- }
532
- }
533
- });
534
- server.route({
535
- method: 'get',
536
- path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',
537
- handler: getItemDeleteHandler,
538
- options: {
539
- ...getRouteOptions,
540
- validate: {
541
- params: Joi.object().keys({
542
- state: stateSchema,
543
- slug: slugSchema,
544
- path: pathSchema,
545
- itemId: itemIdSchema
546
- })
547
- }
548
- }
549
- });
550
-
551
- // Item delete POST route
552
- const postItemDeleteHandler = (request, h) => {
553
- const {
554
- params
555
- } = request;
556
- return redirectOrMakeHandler(request, h, (page, context) => {
557
- const {
558
- isForceAccess
559
- } = context;
560
- if (isForceAccess || !(page instanceof RepeatPageController || page instanceof FileUploadPageController)) {
561
- throw Boom.notFound(`No page found for /${params.path}`);
562
- }
563
- return page.makePostItemDeleteRouteHandler()(request, context, h);
564
- });
565
- };
566
- server.route({
567
- method: 'post',
568
- path: '/{slug}/{path}/{itemId}/confirm-delete',
569
- handler: postItemDeleteHandler,
570
- options: {
571
- ...postRouteOptions,
572
- validate: {
573
- params: Joi.object().keys({
574
- slug: slugSchema,
575
- path: pathSchema,
576
- itemId: itemIdSchema
577
- }),
578
- payload: Joi.object().keys({
579
- crumb: crumbSchema,
580
- action: actionSchema,
581
- confirm: confirmSchema
582
- }).required()
583
- }
584
- }
585
- });
586
- server.route({
587
- method: 'post',
588
- path: '/preview/{state}/{slug}/{path}/{itemId}/confirm-delete',
589
- handler: postItemDeleteHandler,
590
- options: {
591
- ...postRouteOptions,
592
- validate: {
593
- params: Joi.object().keys({
594
- state: stateSchema,
595
- slug: slugSchema,
596
- path: pathSchema,
597
- itemId: itemIdSchema
598
- }),
599
- payload: Joi.object().keys({
600
- crumb: crumbSchema,
601
- action: actionSchema,
602
- confirm: confirmSchema
603
- }).required()
604
- }
605
- }
606
- });
607
- server.route({
608
- method: 'get',
609
- path: '/upload-status/{uploadId}',
610
- handler: async (request, h) => {
611
- const {
612
- uploadId
613
- } = request.params;
614
- try {
615
- const status = await getUploadStatus(uploadId);
616
- if (!status) {
617
- return h.response({
618
- error: 'Status check failed'
619
- }).code(400);
620
- }
621
- return h.response(status);
622
- } catch (error) {
623
- const errMsg = getErrorMessage(error);
624
- request.logger.error(errMsg, `[uploadStatusFailed] Upload status check failed for uploadId: ${uploadId} - ${errMsg}`);
625
- return h.response({
626
- error: 'Status check error'
627
- }).code(500);
628
- }
629
- },
630
- options: {
631
- plugins: {
632
- crumb: false
633
- },
634
- validate: {
635
- params: Joi.object().keys({
636
- uploadId: Joi.string().guid().required()
637
- })
638
- }
639
- }
640
- });
55
+ const routes = [...getQuestionRoutes(getRouteOptions, postRouteOptions), ...getRepeaterSummaryRoutes(getRouteOptions, postRouteOptions), ...getRepeaterItemDeleteRoutes(getRouteOptions, postRouteOptions), ...getFileUploadStatusRoutes()];
56
+ server.route(routes); // TODO
641
57
  }
642
58
  };
643
59
  //# sourceMappingURL=plugin.js.map