@squiz/render-runtime-lib 1.63.4 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/component-runner/ComponentRunnerServiceWithWorkers.d.ts +2 -0
- package/lib/index.d.ts +3 -1
- package/lib/index.js +590 -254
- package/lib/index.js.map +4 -4
- package/lib/ioc.d.ts +4 -1
- package/lib/public/docs.json +20 -1
- package/lib/test/helpers/stack.d.ts +3 -3
- package/lib/webserver/app.d.ts +2 -2
- package/lib/webserver/controllers/DevelopmentController.d.ts +20 -0
- package/lib/webserver/controllers/DevelopmentController.spec.d.ts +1 -0
- package/lib/webserver/controllers/test/development-route-tests.d.ts +2 -0
- package/lib/worker/component-bootstrapper.js +7 -5
- package/lib/worker/component-bootstrapper.js.map +2 -2
- package/package.json +10 -10
package/lib/index.js
CHANGED
|
@@ -81,10 +81,10 @@ var import_cors = __toESM(require("cors"));
|
|
|
81
81
|
var import_compression = __toESM(require("compression"));
|
|
82
82
|
var import_crypto = require("crypto");
|
|
83
83
|
var import_helmet = __toESM(require("helmet"));
|
|
84
|
-
var
|
|
84
|
+
var import_dx_common_lib6 = require("@squiz/dx-common-lib");
|
|
85
85
|
|
|
86
86
|
// src/webserver/routes/routes.ts
|
|
87
|
-
var
|
|
87
|
+
var import_runtime6 = require("@tsoa/runtime");
|
|
88
88
|
|
|
89
89
|
// src/webserver/controllers/CoreController.ts
|
|
90
90
|
var import_tsoa = require("tsoa");
|
|
@@ -340,17 +340,157 @@ DefinitionController = __decorateClass([
|
|
|
340
340
|
__decorateParam(3, (0, import_inversify2.inject)("ComponentRootUrlResolver"))
|
|
341
341
|
], DefinitionController);
|
|
342
342
|
|
|
343
|
-
// src/webserver/controllers/
|
|
343
|
+
// src/webserver/controllers/DevelopmentController.ts
|
|
344
344
|
var import_tsoa3 = require("tsoa");
|
|
345
345
|
var import_inversify_binding_decorators3 = require("inversify-binding-decorators");
|
|
346
346
|
var import_inversify3 = require("inversify");
|
|
347
|
+
var import_dx_common_lib3 = require("@squiz/dx-common-lib");
|
|
348
|
+
var DevelopmentController = class extends import_tsoa3.Controller {
|
|
349
|
+
constructor(config, manifestService, componentRunnerService) {
|
|
350
|
+
super();
|
|
351
|
+
this.config = config;
|
|
352
|
+
this.manifestService = manifestService;
|
|
353
|
+
this.componentRunnerService = componentRunnerService;
|
|
354
|
+
}
|
|
355
|
+
async getComponents() {
|
|
356
|
+
if (!this.config.enableDevMode) {
|
|
357
|
+
throw new import_dx_common_lib3.ResourceNotFoundError("Route does not exist.");
|
|
358
|
+
}
|
|
359
|
+
const components = await this.manifestService.listAllComponentManifests();
|
|
360
|
+
return components.map((component) => component.getModel());
|
|
361
|
+
}
|
|
362
|
+
async Manifest(namespace, componentName, version) {
|
|
363
|
+
if (!this.config.enableDevMode) {
|
|
364
|
+
throw new import_dx_common_lib3.ResourceNotFoundError("Route does not exist.");
|
|
365
|
+
}
|
|
366
|
+
const manifest = await this.manifestService.loadManifest(namespace, componentName, version);
|
|
367
|
+
return manifest.getModel();
|
|
368
|
+
}
|
|
369
|
+
async getContentSchema(namespace, componentName, version) {
|
|
370
|
+
if (!this.config.enableDevMode) {
|
|
371
|
+
throw new import_dx_common_lib3.ResourceNotFoundError("Route does not exist.");
|
|
372
|
+
}
|
|
373
|
+
const componentManifest = await this.manifestService.loadManifest(namespace, componentName, version);
|
|
374
|
+
const inputSchemas = componentManifest.getInputSchemas();
|
|
375
|
+
const schemaResult = [];
|
|
376
|
+
inputSchemas.forEach((inputSchema) => {
|
|
377
|
+
if (inputSchema.schema && Object.keys(inputSchema.schema).length) {
|
|
378
|
+
schemaResult.push(inputSchema);
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
return schemaResult;
|
|
382
|
+
}
|
|
383
|
+
/* Commenting this out for POC, would like to do something like the following: */
|
|
384
|
+
/* TODO: FEAAS-627 Temporary Preview:
|
|
385
|
+
- Bit crude and should be improved but the method is:
|
|
386
|
+
- A preview is created by post of the temp data (env, header, content etc) to the server and stored in the map bellow
|
|
387
|
+
- Post request returns the id for the map
|
|
388
|
+
- Front end opens the get route in the browser using the id thats returned
|
|
389
|
+
|
|
390
|
+
type TemporaryPreviewInput = {
|
|
391
|
+
componentSet: RuntimeComponentSet;
|
|
392
|
+
headers: Headers;
|
|
393
|
+
// content: ContentItemWebModelForCreate
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
temporaryPreviewResultMap: Map<string, { componentResult: FunctionReturnTypes; headers: Headers }> = new Map();
|
|
397
|
+
|
|
398
|
+
@Post('/temp-preview/:namespace/:componentName/:version/:functionName')
|
|
399
|
+
public async TemporaryPreview(
|
|
400
|
+
@Request() req: ExpressRequest,
|
|
401
|
+
@Path() namespace: string,
|
|
402
|
+
@Path() componentName: string,
|
|
403
|
+
@Path() version: string,
|
|
404
|
+
@Path() functionName: string,
|
|
405
|
+
@Body() requestBody?: TemporaryPreviewInput,
|
|
406
|
+
) {
|
|
407
|
+
const res = (<any>req).res as ExpressResponse;
|
|
408
|
+
// const contentItem: ContentItem = new ContentItem(requestBody); //FIXME: do something like this
|
|
409
|
+
const rootUrl = parseEnvVarForVar('COMPONENT_RENDER_SERVICE_URL').replace(/\/+$/, '');
|
|
410
|
+
const componentManifest = await this.manifestService.loadManifest(namespace, componentName, version);
|
|
411
|
+
// const renderedOutput = await this.doFunctionRender(renderInput);
|
|
412
|
+
|
|
413
|
+
// Form the input from the request body content
|
|
414
|
+
// const input = await this.getContentFromContentService(request);
|
|
415
|
+
// this.assertInputIsValid(input, componentFunction);
|
|
416
|
+
// const resolvedInput = await resolveFormattedTextNodes(
|
|
417
|
+
// input,
|
|
418
|
+
// componentFunction.input,
|
|
419
|
+
// formattedTextToHtmlStringResolvers,
|
|
420
|
+
// { withJoin: '' },
|
|
421
|
+
// );
|
|
422
|
+
// this.assertRenderInputIsValid(resolvedInput, componentFunction);
|
|
423
|
+
|
|
424
|
+
const result = await this.componentRunnerService.executeComponentFunction({
|
|
425
|
+
dxpApiKey: undefined,
|
|
426
|
+
requestId: 'MOCK_ME',
|
|
427
|
+
args: [],
|
|
428
|
+
functionEntryFilePath: await componentManifest.getComponentFunctionEntryFilePath(
|
|
429
|
+
componentManifest.getComponentFunctionByName(functionName),
|
|
430
|
+
),
|
|
431
|
+
environment: requestBody.componentSet.environment,
|
|
432
|
+
componentFullName: componentName,
|
|
433
|
+
componentFunction: componentManifest.getComponentFunctionByName(functionName),
|
|
434
|
+
componentRootUrl: rootUrl,
|
|
435
|
+
manifest: componentManifest.getModel(),
|
|
436
|
+
runtimeSet: requestBody.componentSet,
|
|
437
|
+
manifestPath: await componentManifest.getManifestPath(),
|
|
438
|
+
previewKey: undefined,
|
|
439
|
+
queryParameters: undefined,
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
//Set the render and headers into temporary memory
|
|
443
|
+
this.temporaryPreviewResultMap.set(req.id, { componentResult: result, headers: requestBody.headers });
|
|
444
|
+
res.send(req.id);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
@Get('/temp-preview/:id')
|
|
448
|
+
public async getTemporaryPreviewRender(@Request() req: ExpressRequest, @Path() id: string) {
|
|
449
|
+
const res = (<any>req).res as ExpressResponse;
|
|
450
|
+
const temporaryPreview = this.temporaryPreviewResultMap.get(id);
|
|
451
|
+
if (temporaryPreview === undefined) {
|
|
452
|
+
throw new BadRequestError(`Temporary Preview with id ${id}, does not exist`);
|
|
453
|
+
}
|
|
454
|
+
setHeadersOnExpressResponse(temporaryPreview.headers, res);
|
|
455
|
+
res.send(temporaryPreview.componentResult);
|
|
456
|
+
}
|
|
457
|
+
*/
|
|
458
|
+
};
|
|
459
|
+
__decorateClass([
|
|
460
|
+
(0, import_tsoa3.Get)("/all")
|
|
461
|
+
], DevelopmentController.prototype, "getComponents", 1);
|
|
462
|
+
__decorateClass([
|
|
463
|
+
(0, import_tsoa3.Get)("/manifest/:namespace/:componentName/:version"),
|
|
464
|
+
__decorateParam(0, (0, import_tsoa3.Path)()),
|
|
465
|
+
__decorateParam(1, (0, import_tsoa3.Path)()),
|
|
466
|
+
__decorateParam(2, (0, import_tsoa3.Path)())
|
|
467
|
+
], DevelopmentController.prototype, "Manifest", 1);
|
|
468
|
+
__decorateClass([
|
|
469
|
+
(0, import_tsoa3.Get)("/schemas/:namespace/:componentName/:version"),
|
|
470
|
+
__decorateParam(0, (0, import_tsoa3.Path)()),
|
|
471
|
+
__decorateParam(1, (0, import_tsoa3.Path)()),
|
|
472
|
+
__decorateParam(2, (0, import_tsoa3.Path)())
|
|
473
|
+
], DevelopmentController.prototype, "getContentSchema", 1);
|
|
474
|
+
DevelopmentController = __decorateClass([
|
|
475
|
+
(0, import_inversify_binding_decorators3.provide)(DevelopmentController),
|
|
476
|
+
(0, import_tsoa3.Route)("/dev"),
|
|
477
|
+
(0, import_tsoa3.Hidden)(),
|
|
478
|
+
__decorateParam(0, (0, import_inversify3.inject)("Config")),
|
|
479
|
+
__decorateParam(1, (0, import_inversify3.inject)("ManifestService")),
|
|
480
|
+
__decorateParam(2, (0, import_inversify3.inject)("ComponentRunnerService"))
|
|
481
|
+
], DevelopmentController);
|
|
482
|
+
|
|
483
|
+
// src/webserver/controllers/RenderController.ts
|
|
484
|
+
var import_tsoa4 = require("tsoa");
|
|
485
|
+
var import_inversify_binding_decorators4 = require("inversify-binding-decorators");
|
|
486
|
+
var import_inversify4 = require("inversify");
|
|
347
487
|
var import_query_string = require("query-string");
|
|
348
488
|
var import_component_lib = require("@squiz/component-lib");
|
|
349
|
-
var
|
|
489
|
+
var import_dx_common_lib4 = require("@squiz/dx-common-lib");
|
|
350
490
|
var import_api = require("@opentelemetry/api");
|
|
351
491
|
var UPPERCASE_REGEX = /[A-Z]/;
|
|
352
492
|
var meter = import_api.metrics.getMeter("render-runtime");
|
|
353
|
-
var RenderController = class extends
|
|
493
|
+
var RenderController = class extends import_tsoa4.Controller {
|
|
354
494
|
constructor(componentSetService, manifestService, componentFunctionService, componentRunnerService, renderInputService, contentItemService, componentPreviewService) {
|
|
355
495
|
super();
|
|
356
496
|
this.componentSetService = componentSetService;
|
|
@@ -375,7 +515,7 @@ var RenderController = class extends import_tsoa3.Controller {
|
|
|
375
515
|
}
|
|
376
516
|
async getGivenFunctionRendering(expressRequest, namespace, componentName, version, functionName, componentSet, previewKey, contentItemId) {
|
|
377
517
|
const response = expressRequest.res;
|
|
378
|
-
(0,
|
|
518
|
+
(0, import_dx_common_lib4.assertIsDefined)(response);
|
|
379
519
|
const { path: path7, query } = expressRequest;
|
|
380
520
|
if (UPPERCASE_REGEX.test(path7) || componentSet && UPPERCASE_REGEX.test(componentSet)) {
|
|
381
521
|
const url = (0, import_query_string.stringifyUrl)({
|
|
@@ -479,50 +619,50 @@ var RenderController = class extends import_tsoa3.Controller {
|
|
|
479
619
|
if (typeof cacheControl !== "string") {
|
|
480
620
|
cacheControl = void 0;
|
|
481
621
|
}
|
|
482
|
-
response.setHeader("cache-control", (0,
|
|
622
|
+
response.setHeader("cache-control", (0, import_dx_common_lib4.parseAndSanitiseCacheControlHeader)(cacheControl));
|
|
483
623
|
}
|
|
484
624
|
};
|
|
485
625
|
__decorateClass([
|
|
486
|
-
(0,
|
|
487
|
-
__decorateParam(0, (0,
|
|
488
|
-
__decorateParam(1, (0,
|
|
489
|
-
__decorateParam(2, (0,
|
|
490
|
-
__decorateParam(3, (0,
|
|
491
|
-
__decorateParam(4, (0,
|
|
492
|
-
__decorateParam(5, (0,
|
|
493
|
-
__decorateParam(6, (0,
|
|
626
|
+
(0, import_tsoa4.Get)("/:namespace/:componentName/:version"),
|
|
627
|
+
__decorateParam(0, (0, import_tsoa4.Request)()),
|
|
628
|
+
__decorateParam(1, (0, import_tsoa4.Path)()),
|
|
629
|
+
__decorateParam(2, (0, import_tsoa4.Path)()),
|
|
630
|
+
__decorateParam(3, (0, import_tsoa4.Path)()),
|
|
631
|
+
__decorateParam(4, (0, import_tsoa4.Query)("_componentSet")),
|
|
632
|
+
__decorateParam(5, (0, import_tsoa4.Query)("_previewKey")),
|
|
633
|
+
__decorateParam(6, (0, import_tsoa4.Query)("_contentItemId"))
|
|
494
634
|
], RenderController.prototype, "getDefaultFunctionRendering", 1);
|
|
495
635
|
__decorateClass([
|
|
496
|
-
(0,
|
|
497
|
-
__decorateParam(0, (0,
|
|
498
|
-
__decorateParam(1, (0,
|
|
499
|
-
__decorateParam(2, (0,
|
|
500
|
-
__decorateParam(3, (0,
|
|
501
|
-
__decorateParam(4, (0,
|
|
502
|
-
__decorateParam(5, (0,
|
|
503
|
-
__decorateParam(6, (0,
|
|
504
|
-
__decorateParam(7, (0,
|
|
636
|
+
(0, import_tsoa4.Get)("/:namespace/:componentName/:version/:functionName"),
|
|
637
|
+
__decorateParam(0, (0, import_tsoa4.Request)()),
|
|
638
|
+
__decorateParam(1, (0, import_tsoa4.Path)()),
|
|
639
|
+
__decorateParam(2, (0, import_tsoa4.Path)()),
|
|
640
|
+
__decorateParam(3, (0, import_tsoa4.Path)()),
|
|
641
|
+
__decorateParam(4, (0, import_tsoa4.Path)()),
|
|
642
|
+
__decorateParam(5, (0, import_tsoa4.Query)("_componentSet")),
|
|
643
|
+
__decorateParam(6, (0, import_tsoa4.Query)("_previewKey")),
|
|
644
|
+
__decorateParam(7, (0, import_tsoa4.Query)("_contentItemId"))
|
|
505
645
|
], RenderController.prototype, "getGivenFunctionRendering", 1);
|
|
506
646
|
RenderController = __decorateClass([
|
|
507
|
-
(0,
|
|
508
|
-
(0,
|
|
509
|
-
__decorateParam(0, (0,
|
|
510
|
-
__decorateParam(1, (0,
|
|
511
|
-
__decorateParam(2, (0,
|
|
512
|
-
__decorateParam(3, (0,
|
|
513
|
-
__decorateParam(4, (0,
|
|
514
|
-
__decorateParam(5, (0,
|
|
515
|
-
__decorateParam(6, (0,
|
|
647
|
+
(0, import_inversify_binding_decorators4.provide)(RenderController),
|
|
648
|
+
(0, import_tsoa4.Route)("/r"),
|
|
649
|
+
__decorateParam(0, (0, import_inversify4.inject)("ComponentSetService")),
|
|
650
|
+
__decorateParam(1, (0, import_inversify4.inject)("ManifestService")),
|
|
651
|
+
__decorateParam(2, (0, import_inversify4.inject)("ComponentFunctionService")),
|
|
652
|
+
__decorateParam(3, (0, import_inversify4.inject)("ComponentRunnerService")),
|
|
653
|
+
__decorateParam(4, (0, import_inversify4.inject)("RenderInputService")),
|
|
654
|
+
__decorateParam(5, (0, import_inversify4.inject)("ContentItemService")),
|
|
655
|
+
__decorateParam(6, (0, import_inversify4.inject)("ComponentPreviewService"))
|
|
516
656
|
], RenderController);
|
|
517
657
|
|
|
518
658
|
// src/webserver/controllers/StaticController.ts
|
|
519
|
-
var
|
|
520
|
-
var
|
|
521
|
-
var
|
|
659
|
+
var import_tsoa5 = require("tsoa");
|
|
660
|
+
var import_inversify_binding_decorators5 = require("inversify-binding-decorators");
|
|
661
|
+
var import_dx_common_lib5 = require("@squiz/dx-common-lib");
|
|
522
662
|
var import_path = __toESM(require("path"));
|
|
523
|
-
var
|
|
663
|
+
var import_inversify5 = require("inversify");
|
|
524
664
|
var import_assert = __toESM(require("assert"));
|
|
525
|
-
var StaticController = class extends
|
|
665
|
+
var StaticController = class extends import_tsoa5.Controller {
|
|
526
666
|
constructor(manifestService, componentSetService, componentFunctionService) {
|
|
527
667
|
super();
|
|
528
668
|
this.manifestService = manifestService;
|
|
@@ -531,7 +671,7 @@ var StaticController = class extends import_tsoa4.Controller {
|
|
|
531
671
|
}
|
|
532
672
|
async getPreview(namespace, componentName, version, staticFile, req, _componentSet, _previewKey) {
|
|
533
673
|
if (_componentSet !== void 0 && _previewKey !== void 0) {
|
|
534
|
-
throw new
|
|
674
|
+
throw new import_dx_common_lib5.BadRequestError("You can not have both _componentSet and _previewKey");
|
|
535
675
|
}
|
|
536
676
|
const manifest = await this.manifestService.loadManifest(namespace, componentName, version);
|
|
537
677
|
const manifestModel = manifest.getModel();
|
|
@@ -560,7 +700,7 @@ var StaticController = class extends import_tsoa4.Controller {
|
|
|
560
700
|
if (req.next) {
|
|
561
701
|
if (e?.code == "ENOENT") {
|
|
562
702
|
req.next(
|
|
563
|
-
new
|
|
703
|
+
new import_dx_common_lib5.ResourceNotFoundError(
|
|
564
704
|
`could not find ${e?.path.substr(
|
|
565
705
|
e?.path.indexOf(componentStaticFileRoot) + componentStaticFileRoot.length
|
|
566
706
|
)}`
|
|
@@ -579,20 +719,20 @@ var StaticController = class extends import_tsoa4.Controller {
|
|
|
579
719
|
});
|
|
580
720
|
});
|
|
581
721
|
} else {
|
|
582
|
-
throw new
|
|
722
|
+
throw new import_dx_common_lib5.ResourceNotFoundError(`${componentName} ${version} doesn't expose any static resources`);
|
|
583
723
|
}
|
|
584
724
|
}
|
|
585
725
|
setResponseHeaders(headers, response) {
|
|
586
726
|
setHeadersOnExpressResponse(headers, response);
|
|
587
727
|
let cacheControl = response.getHeader("cache-control");
|
|
588
728
|
if (typeof cacheControl != "string") {
|
|
589
|
-
cacheControl =
|
|
729
|
+
cacheControl = import_dx_common_lib5.DEFAULT_CACHE_CONTROL_HEADER;
|
|
590
730
|
}
|
|
591
|
-
let cacheControlObj = (0,
|
|
592
|
-
cacheControlObj = (0,
|
|
731
|
+
let cacheControlObj = (0, import_dx_common_lib5.parseCacheControl)(cacheControl);
|
|
732
|
+
cacheControlObj = (0, import_dx_common_lib5.applyDefaultRulesToCacheControlObject)(cacheControlObj);
|
|
593
733
|
cacheControlObj.immutable = true;
|
|
594
734
|
cacheControlObj["max-age"] = 604800;
|
|
595
|
-
response.setHeader("cache-control", (0,
|
|
735
|
+
response.setHeader("cache-control", (0, import_dx_common_lib5.cacheControlToString)(cacheControlObj));
|
|
596
736
|
}
|
|
597
737
|
async getHeadersForInputType(_componentSet, _previewKey, manifest) {
|
|
598
738
|
if (_componentSet) {
|
|
@@ -605,13 +745,13 @@ var StaticController = class extends import_tsoa4.Controller {
|
|
|
605
745
|
const headers = functionPreview?.headers ? functionPreview.headers : {};
|
|
606
746
|
return headers;
|
|
607
747
|
}
|
|
608
|
-
throw new
|
|
748
|
+
throw new import_dx_common_lib5.BadRequestError(`neither componentSet or previewKey set`);
|
|
609
749
|
}
|
|
610
750
|
async getValidatedSet(_componentSet, manifest) {
|
|
611
751
|
const set = await this.componentSetService.getComponentSet(_componentSet);
|
|
612
752
|
const isCompVersionInSet = this.componentSetService.componentVersionInSet(manifest, set.webPath);
|
|
613
753
|
if (!isCompVersionInSet) {
|
|
614
|
-
throw new
|
|
754
|
+
throw new import_dx_common_lib5.ResourceNotFoundError(`${manifest.getName()} ${manifest.getVersion()} not in set ${set.webPath}`);
|
|
615
755
|
}
|
|
616
756
|
return set;
|
|
617
757
|
}
|
|
@@ -630,33 +770,34 @@ var StaticController = class extends import_tsoa4.Controller {
|
|
|
630
770
|
}
|
|
631
771
|
};
|
|
632
772
|
__decorateClass([
|
|
633
|
-
(0,
|
|
634
|
-
__decorateParam(0, (0,
|
|
635
|
-
__decorateParam(1, (0,
|
|
636
|
-
__decorateParam(2, (0,
|
|
637
|
-
__decorateParam(3, (0,
|
|
638
|
-
__decorateParam(4, (0,
|
|
639
|
-
__decorateParam(5, (0,
|
|
640
|
-
__decorateParam(6, (0,
|
|
773
|
+
(0, import_tsoa5.Get)("/:namespace/:componentName/:version/:staticFile*"),
|
|
774
|
+
__decorateParam(0, (0, import_tsoa5.Path)()),
|
|
775
|
+
__decorateParam(1, (0, import_tsoa5.Path)()),
|
|
776
|
+
__decorateParam(2, (0, import_tsoa5.Path)()),
|
|
777
|
+
__decorateParam(3, (0, import_tsoa5.Path)()),
|
|
778
|
+
__decorateParam(4, (0, import_tsoa5.Request)()),
|
|
779
|
+
__decorateParam(5, (0, import_tsoa5.Query)()),
|
|
780
|
+
__decorateParam(6, (0, import_tsoa5.Query)())
|
|
641
781
|
], StaticController.prototype, "getPreview", 1);
|
|
642
782
|
StaticController = __decorateClass([
|
|
643
|
-
(0,
|
|
644
|
-
(0,
|
|
645
|
-
__decorateParam(0, (0,
|
|
646
|
-
__decorateParam(1, (0,
|
|
647
|
-
__decorateParam(2, (0,
|
|
783
|
+
(0, import_inversify_binding_decorators5.provide)(StaticController),
|
|
784
|
+
(0, import_tsoa5.Route)("/s"),
|
|
785
|
+
__decorateParam(0, (0, import_inversify5.inject)("ManifestService")),
|
|
786
|
+
__decorateParam(1, (0, import_inversify5.inject)("ComponentSetService")),
|
|
787
|
+
__decorateParam(2, (0, import_inversify5.inject)("ComponentFunctionService"))
|
|
648
788
|
], StaticController);
|
|
649
789
|
|
|
650
790
|
// src/ioc.ts
|
|
651
|
-
var
|
|
652
|
-
var
|
|
653
|
-
var
|
|
654
|
-
(0,
|
|
791
|
+
var import_inversify6 = require("inversify");
|
|
792
|
+
var import_inversify_binding_decorators6 = require("inversify-binding-decorators");
|
|
793
|
+
var import_tsoa6 = require("tsoa");
|
|
794
|
+
(0, import_inversify6.decorate)((0, import_inversify6.injectable)(), import_tsoa6.Controller);
|
|
655
795
|
var iocContainer;
|
|
656
|
-
var initIocContainer = (services) => {
|
|
657
|
-
const container = new
|
|
658
|
-
container.load((0,
|
|
659
|
-
container.bind("
|
|
796
|
+
var initIocContainer = (services, config) => {
|
|
797
|
+
const container = new import_inversify6.Container();
|
|
798
|
+
container.load((0, import_inversify_binding_decorators6.buildProviderModule)());
|
|
799
|
+
container.bind("Config").toConstantValue(config);
|
|
800
|
+
container.bind("Sandbox").toConstantValue(services.sandbox);
|
|
660
801
|
container.bind("Logger").toConstantValue(services.logger);
|
|
661
802
|
container.bind("ComponentFunctionService").toConstantValue(services.componentFunctionService);
|
|
662
803
|
container.bind("ComponentRunnerService").toConstantValue(services.componentRunnerService);
|
|
@@ -1106,15 +1247,25 @@ var models = {
|
|
|
1106
1247
|
"queryParameters": { "dataType": "nestedObjectLiteral", "nestedProperties": {}, "additionalProperties": { "ref": "QueryParameterValueType" } }
|
|
1107
1248
|
},
|
|
1108
1249
|
"additionalProperties": { "dataType": "any" }
|
|
1250
|
+
},
|
|
1251
|
+
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
|
1252
|
+
"ComponentManifest": {
|
|
1253
|
+
"dataType": "refAlias",
|
|
1254
|
+
"type": { "ref": "MANIFEST_MODELS.v1.ComponentManifest", "validators": {} }
|
|
1255
|
+
},
|
|
1256
|
+
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
|
1257
|
+
"ComponentSchema": {
|
|
1258
|
+
"dataType": "refAlias",
|
|
1259
|
+
"type": { "dataType": "nestedObjectLiteral", "nestedProperties": { "schema": { "dataType": "object", "required": true }, "name": { "dataType": "string", "required": true } }, "validators": {} }
|
|
1109
1260
|
}
|
|
1110
1261
|
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
|
|
1111
1262
|
};
|
|
1112
|
-
var validationService = new
|
|
1263
|
+
var validationService = new import_runtime6.ValidationService(models);
|
|
1113
1264
|
function RegisterRoutes(app) {
|
|
1114
1265
|
app.get(
|
|
1115
1266
|
"/schemas/:version.json",
|
|
1116
|
-
...(0,
|
|
1117
|
-
...(0,
|
|
1267
|
+
...(0, import_runtime6.fetchMiddlewares)(CoreController),
|
|
1268
|
+
...(0, import_runtime6.fetchMiddlewares)(CoreController.prototype.getSchemaVersion),
|
|
1118
1269
|
async function CoreController_getSchemaVersion(request, response, next) {
|
|
1119
1270
|
const args = {
|
|
1120
1271
|
version: { "in": "path", "name": "version", "required": true, "dataType": "string" }
|
|
@@ -1136,8 +1287,8 @@ function RegisterRoutes(app) {
|
|
|
1136
1287
|
);
|
|
1137
1288
|
app.get(
|
|
1138
1289
|
"/health",
|
|
1139
|
-
...(0,
|
|
1140
|
-
...(0,
|
|
1290
|
+
...(0, import_runtime6.fetchMiddlewares)(CoreController),
|
|
1291
|
+
...(0, import_runtime6.fetchMiddlewares)(CoreController.prototype.getHealthInfo),
|
|
1141
1292
|
async function CoreController_getHealthInfo(request, response, next) {
|
|
1142
1293
|
const args = {};
|
|
1143
1294
|
let validatedArgs = [];
|
|
@@ -1157,8 +1308,8 @@ function RegisterRoutes(app) {
|
|
|
1157
1308
|
);
|
|
1158
1309
|
app.get(
|
|
1159
1310
|
"/",
|
|
1160
|
-
...(0,
|
|
1161
|
-
...(0,
|
|
1311
|
+
...(0, import_runtime6.fetchMiddlewares)(CoreController),
|
|
1312
|
+
...(0, import_runtime6.fetchMiddlewares)(CoreController.prototype.getComponents),
|
|
1162
1313
|
async function CoreController_getComponents(request, response, next) {
|
|
1163
1314
|
const args = {
|
|
1164
1315
|
req: { "in": "request", "name": "req", "required": true, "dataType": "object" }
|
|
@@ -1180,8 +1331,8 @@ function RegisterRoutes(app) {
|
|
|
1180
1331
|
);
|
|
1181
1332
|
app.get(
|
|
1182
1333
|
"/d/:namespace/:componentName/:version/manifest.json",
|
|
1183
|
-
...(0,
|
|
1184
|
-
...(0,
|
|
1334
|
+
...(0, import_runtime6.fetchMiddlewares)(DefinitionController),
|
|
1335
|
+
...(0, import_runtime6.fetchMiddlewares)(DefinitionController.prototype.getComponentVersionManifest),
|
|
1185
1336
|
async function DefinitionController_getComponentVersionManifest(request, response, next) {
|
|
1186
1337
|
const args = {
|
|
1187
1338
|
namespace: { "in": "path", "name": "namespace", "required": true, "dataType": "string" },
|
|
@@ -1208,8 +1359,8 @@ function RegisterRoutes(app) {
|
|
|
1208
1359
|
);
|
|
1209
1360
|
app.get(
|
|
1210
1361
|
"/d/:namespace/:componentName/:version",
|
|
1211
|
-
...(0,
|
|
1212
|
-
...(0,
|
|
1362
|
+
...(0, import_runtime6.fetchMiddlewares)(DefinitionController),
|
|
1363
|
+
...(0, import_runtime6.fetchMiddlewares)(DefinitionController.prototype.getDefaultFunctionDefinition),
|
|
1213
1364
|
async function DefinitionController_getDefaultFunctionDefinition(request, response, next) {
|
|
1214
1365
|
const args = {
|
|
1215
1366
|
namespace: { "in": "path", "name": "namespace", "required": true, "dataType": "string" },
|
|
@@ -1236,8 +1387,8 @@ function RegisterRoutes(app) {
|
|
|
1236
1387
|
);
|
|
1237
1388
|
app.get(
|
|
1238
1389
|
"/d/:namespace/:componentName/:version/:functionName",
|
|
1239
|
-
...(0,
|
|
1240
|
-
...(0,
|
|
1390
|
+
...(0, import_runtime6.fetchMiddlewares)(DefinitionController),
|
|
1391
|
+
...(0, import_runtime6.fetchMiddlewares)(DefinitionController.prototype.getGivenFunctionDefinition),
|
|
1241
1392
|
async function DefinitionController_getGivenFunctionDefinition(request, response, next) {
|
|
1242
1393
|
const args = {
|
|
1243
1394
|
namespace: { "in": "path", "name": "namespace", "required": true, "dataType": "string" },
|
|
@@ -1263,10 +1414,81 @@ function RegisterRoutes(app) {
|
|
|
1263
1414
|
}
|
|
1264
1415
|
}
|
|
1265
1416
|
);
|
|
1417
|
+
app.get(
|
|
1418
|
+
"/dev/all",
|
|
1419
|
+
...(0, import_runtime6.fetchMiddlewares)(DevelopmentController),
|
|
1420
|
+
...(0, import_runtime6.fetchMiddlewares)(DevelopmentController.prototype.getComponents),
|
|
1421
|
+
async function DevelopmentController_getComponents(request, response, next) {
|
|
1422
|
+
const args = {};
|
|
1423
|
+
let validatedArgs = [];
|
|
1424
|
+
try {
|
|
1425
|
+
validatedArgs = getValidatedArgs(args, request, response);
|
|
1426
|
+
const container = typeof iocContainer === "function" ? iocContainer(request) : iocContainer;
|
|
1427
|
+
const controller = await container.get(DevelopmentController);
|
|
1428
|
+
if (typeof controller["setStatus"] === "function") {
|
|
1429
|
+
controller.setStatus(void 0);
|
|
1430
|
+
}
|
|
1431
|
+
const promise = controller.getComponents.apply(controller, validatedArgs);
|
|
1432
|
+
promiseHandler(controller, promise, response, void 0, next);
|
|
1433
|
+
} catch (err) {
|
|
1434
|
+
return next(err);
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
);
|
|
1438
|
+
app.get(
|
|
1439
|
+
"/dev/manifest/:namespace/:componentName/:version",
|
|
1440
|
+
...(0, import_runtime6.fetchMiddlewares)(DevelopmentController),
|
|
1441
|
+
...(0, import_runtime6.fetchMiddlewares)(DevelopmentController.prototype.Manifest),
|
|
1442
|
+
async function DevelopmentController_Manifest(request, response, next) {
|
|
1443
|
+
const args = {
|
|
1444
|
+
namespace: { "in": "path", "name": "namespace", "required": true, "dataType": "string" },
|
|
1445
|
+
componentName: { "in": "path", "name": "componentName", "required": true, "dataType": "string" },
|
|
1446
|
+
version: { "in": "path", "name": "version", "required": true, "dataType": "string" }
|
|
1447
|
+
};
|
|
1448
|
+
let validatedArgs = [];
|
|
1449
|
+
try {
|
|
1450
|
+
validatedArgs = getValidatedArgs(args, request, response);
|
|
1451
|
+
const container = typeof iocContainer === "function" ? iocContainer(request) : iocContainer;
|
|
1452
|
+
const controller = await container.get(DevelopmentController);
|
|
1453
|
+
if (typeof controller["setStatus"] === "function") {
|
|
1454
|
+
controller.setStatus(void 0);
|
|
1455
|
+
}
|
|
1456
|
+
const promise = controller.Manifest.apply(controller, validatedArgs);
|
|
1457
|
+
promiseHandler(controller, promise, response, void 0, next);
|
|
1458
|
+
} catch (err) {
|
|
1459
|
+
return next(err);
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
);
|
|
1463
|
+
app.get(
|
|
1464
|
+
"/dev/schemas/:namespace/:componentName/:version",
|
|
1465
|
+
...(0, import_runtime6.fetchMiddlewares)(DevelopmentController),
|
|
1466
|
+
...(0, import_runtime6.fetchMiddlewares)(DevelopmentController.prototype.getContentSchema),
|
|
1467
|
+
async function DevelopmentController_getContentSchema(request, response, next) {
|
|
1468
|
+
const args = {
|
|
1469
|
+
namespace: { "in": "path", "name": "namespace", "required": true, "dataType": "string" },
|
|
1470
|
+
componentName: { "in": "path", "name": "componentName", "required": true, "dataType": "string" },
|
|
1471
|
+
version: { "in": "path", "name": "version", "required": true, "dataType": "string" }
|
|
1472
|
+
};
|
|
1473
|
+
let validatedArgs = [];
|
|
1474
|
+
try {
|
|
1475
|
+
validatedArgs = getValidatedArgs(args, request, response);
|
|
1476
|
+
const container = typeof iocContainer === "function" ? iocContainer(request) : iocContainer;
|
|
1477
|
+
const controller = await container.get(DevelopmentController);
|
|
1478
|
+
if (typeof controller["setStatus"] === "function") {
|
|
1479
|
+
controller.setStatus(void 0);
|
|
1480
|
+
}
|
|
1481
|
+
const promise = controller.getContentSchema.apply(controller, validatedArgs);
|
|
1482
|
+
promiseHandler(controller, promise, response, void 0, next);
|
|
1483
|
+
} catch (err) {
|
|
1484
|
+
return next(err);
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
);
|
|
1266
1488
|
app.get(
|
|
1267
1489
|
"/r/:namespace/:componentName/:version",
|
|
1268
|
-
...(0,
|
|
1269
|
-
...(0,
|
|
1490
|
+
...(0, import_runtime6.fetchMiddlewares)(RenderController),
|
|
1491
|
+
...(0, import_runtime6.fetchMiddlewares)(RenderController.prototype.getDefaultFunctionRendering),
|
|
1270
1492
|
async function RenderController_getDefaultFunctionRendering(request, response, next) {
|
|
1271
1493
|
const args = {
|
|
1272
1494
|
expressRequest: { "in": "request", "name": "expressRequest", "required": true, "dataType": "object" },
|
|
@@ -1294,8 +1516,8 @@ function RegisterRoutes(app) {
|
|
|
1294
1516
|
);
|
|
1295
1517
|
app.get(
|
|
1296
1518
|
"/r/:namespace/:componentName/:version/:functionName",
|
|
1297
|
-
...(0,
|
|
1298
|
-
...(0,
|
|
1519
|
+
...(0, import_runtime6.fetchMiddlewares)(RenderController),
|
|
1520
|
+
...(0, import_runtime6.fetchMiddlewares)(RenderController.prototype.getGivenFunctionRendering),
|
|
1299
1521
|
async function RenderController_getGivenFunctionRendering(request, response, next) {
|
|
1300
1522
|
const args = {
|
|
1301
1523
|
expressRequest: { "in": "request", "name": "expressRequest", "required": true, "dataType": "object" },
|
|
@@ -1324,8 +1546,8 @@ function RegisterRoutes(app) {
|
|
|
1324
1546
|
);
|
|
1325
1547
|
app.get(
|
|
1326
1548
|
"/s/:namespace/:componentName/:version/:staticFile*",
|
|
1327
|
-
...(0,
|
|
1328
|
-
...(0,
|
|
1549
|
+
...(0, import_runtime6.fetchMiddlewares)(StaticController),
|
|
1550
|
+
...(0, import_runtime6.fetchMiddlewares)(StaticController.prototype.getPreview),
|
|
1329
1551
|
async function StaticController_getPreview(request, response, next) {
|
|
1330
1552
|
const args = {
|
|
1331
1553
|
namespace: { "in": "path", "name": "namespace", "required": true, "dataType": "string" },
|
|
@@ -1419,7 +1641,7 @@ function RegisterRoutes(app) {
|
|
|
1419
1641
|
}
|
|
1420
1642
|
});
|
|
1421
1643
|
if (Object.keys(fieldErrors).length > 0) {
|
|
1422
|
-
throw new
|
|
1644
|
+
throw new import_runtime6.ValidateError(fieldErrors, "");
|
|
1423
1645
|
}
|
|
1424
1646
|
return values;
|
|
1425
1647
|
}
|
|
@@ -1428,8 +1650,8 @@ function RegisterRoutes(app) {
|
|
|
1428
1650
|
// src/webserver/app.ts
|
|
1429
1651
|
var import_path2 = __toESM(require("path"));
|
|
1430
1652
|
var import_swagger_ui_express = __toESM(require("swagger-ui-express"));
|
|
1431
|
-
function setupApp(services) {
|
|
1432
|
-
initIocContainer(services);
|
|
1653
|
+
function setupApp(services, config = {}) {
|
|
1654
|
+
initIocContainer(services, config);
|
|
1433
1655
|
const app = (0, import_express.default)();
|
|
1434
1656
|
app.request.services = services;
|
|
1435
1657
|
app.options("*", (0, import_cors.default)({ credentials: true }));
|
|
@@ -1466,6 +1688,11 @@ function setupApp(services) {
|
|
|
1466
1688
|
next();
|
|
1467
1689
|
});
|
|
1468
1690
|
app.use((req, res, next) => {
|
|
1691
|
+
req.accepts("json");
|
|
1692
|
+
if (["POST", "PUT", "PATCH"].includes(req.method) && req.header("content-type") !== "application/json") {
|
|
1693
|
+
next(new import_dx_common_lib6.BadRequestError("content-type must be application/json"));
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1469
1696
|
const id = (0, import_crypto.randomUUID)();
|
|
1470
1697
|
req.log = services.logger.child({ req_id: id, area: "application", path: req.path });
|
|
1471
1698
|
req.id = id;
|
|
@@ -1484,7 +1711,7 @@ function setupApp(services) {
|
|
|
1484
1711
|
})
|
|
1485
1712
|
);
|
|
1486
1713
|
RegisterRoutes(app);
|
|
1487
|
-
app.use(
|
|
1714
|
+
app.use(import_dx_common_lib6.errorMiddleware);
|
|
1488
1715
|
return app;
|
|
1489
1716
|
}
|
|
1490
1717
|
|
|
@@ -1495,7 +1722,7 @@ var import_component_lib3 = require("@squiz/component-lib");
|
|
|
1495
1722
|
var import_path3 = __toESM(require("path"));
|
|
1496
1723
|
var import_api2 = require("@opentelemetry/api");
|
|
1497
1724
|
var import_component_lib2 = require("@squiz/component-lib");
|
|
1498
|
-
var
|
|
1725
|
+
var import_dx_common_lib7 = require("@squiz/dx-common-lib");
|
|
1499
1726
|
|
|
1500
1727
|
// src/component-runner/ExecuteComponentTask.ts
|
|
1501
1728
|
var isJobTask = (task) => {
|
|
@@ -1565,29 +1792,7 @@ var ComponentRunnerServiceWithWorkers = class {
|
|
|
1565
1792
|
});
|
|
1566
1793
|
return result;
|
|
1567
1794
|
} catch (e) {
|
|
1568
|
-
|
|
1569
|
-
const message = `function ${task.componentFunction.name} of component ${task.componentFullName} ${task.manifest.version} ` + WORKER_TIMEOUT_ERROR_MESSAGE;
|
|
1570
|
-
await this.componentLogger.error(message, task.requestId).catch((err) => this.logger.error(err));
|
|
1571
|
-
throw new import_component_lib2.ComponentError(
|
|
1572
|
-
task.requestId,
|
|
1573
|
-
new Error(message),
|
|
1574
|
-
task.componentFunction.name,
|
|
1575
|
-
task.componentFullName,
|
|
1576
|
-
task.manifest.version,
|
|
1577
|
-
task.runtimeSet.webPath
|
|
1578
|
-
);
|
|
1579
|
-
} else {
|
|
1580
|
-
const componentError = new import_component_lib2.ComponentError(
|
|
1581
|
-
task.requestId,
|
|
1582
|
-
e,
|
|
1583
|
-
task.componentFunction.name,
|
|
1584
|
-
task.componentFullName,
|
|
1585
|
-
task.manifest.version,
|
|
1586
|
-
task.runtimeSet.webPath
|
|
1587
|
-
);
|
|
1588
|
-
await this.componentLogger.error(componentError.message, task.requestId).catch((err) => this.logger.error(err));
|
|
1589
|
-
throw componentError;
|
|
1590
|
-
}
|
|
1795
|
+
return await this.handleComponentExecutionError(e, task);
|
|
1591
1796
|
} finally {
|
|
1592
1797
|
await this.componentLogger.flush().catch((err) => this.logger.error(err));
|
|
1593
1798
|
span.end();
|
|
@@ -1600,7 +1805,7 @@ var ComponentRunnerServiceWithWorkers = class {
|
|
|
1600
1805
|
const result = await this.sandbox.execute(task);
|
|
1601
1806
|
return result;
|
|
1602
1807
|
} catch (e) {
|
|
1603
|
-
if (e instanceof
|
|
1808
|
+
if (e instanceof import_dx_common_lib7.TimeoutError) {
|
|
1604
1809
|
const message = `function ${task.jobFunction.name} of job ${task.jobFullName} ${task.manifest.version} ` + WORKER_TIMEOUT_ERROR_MESSAGE;
|
|
1605
1810
|
await this.componentLogger.error(message, task.requestId).catch((err) => this.logger.error(err));
|
|
1606
1811
|
throw new import_component_lib2.JobError(task.requestId, e, task.jobFunction.name, task.jobFullName, task.manifest.version);
|
|
@@ -1625,6 +1830,24 @@ var ComponentRunnerServiceWithWorkers = class {
|
|
|
1625
1830
|
async healthCheck() {
|
|
1626
1831
|
return this.sandbox.health();
|
|
1627
1832
|
}
|
|
1833
|
+
async handleComponentExecutionError(e, task) {
|
|
1834
|
+
const componentError = new import_component_lib2.ComponentError(
|
|
1835
|
+
task.requestId,
|
|
1836
|
+
e,
|
|
1837
|
+
task.componentFunction.name,
|
|
1838
|
+
task.componentFullName,
|
|
1839
|
+
task.manifest.version,
|
|
1840
|
+
task.runtimeSet.webPath
|
|
1841
|
+
);
|
|
1842
|
+
if (e instanceof import_dx_common_lib7.TimeoutError) {
|
|
1843
|
+
componentError.message = this.constructTimeoutErrorMessage(e, task);
|
|
1844
|
+
}
|
|
1845
|
+
await this.componentLogger.error(componentError.message, task.requestId).catch((err) => this.logger.error(err));
|
|
1846
|
+
throw componentError;
|
|
1847
|
+
}
|
|
1848
|
+
constructTimeoutErrorMessage(e, task) {
|
|
1849
|
+
return `function ${task.componentFunction.name} of component ${task.componentFullName} ${task.manifest.version} ` + WORKER_TIMEOUT_ERROR_MESSAGE;
|
|
1850
|
+
}
|
|
1628
1851
|
};
|
|
1629
1852
|
|
|
1630
1853
|
// src/PreviewComponentService.ts
|
|
@@ -1693,7 +1916,7 @@ function cssIncludeTagHtml(file) {
|
|
|
1693
1916
|
}
|
|
1694
1917
|
|
|
1695
1918
|
// src/PreviewComponentService.ts
|
|
1696
|
-
var
|
|
1919
|
+
var import_dx_common_lib8 = require("@squiz/dx-common-lib");
|
|
1697
1920
|
var PREVIEW_COMPONENT_SET = "unknown";
|
|
1698
1921
|
var ComponentPreviewService = class {
|
|
1699
1922
|
async dressRenderedOutputForPreview(componentManifest, functionDefinition, previewKey, componentOutput) {
|
|
@@ -1713,7 +1936,7 @@ var ComponentPreviewService = class {
|
|
|
1713
1936
|
async embedComponentIntoWrapper(componentDirectory, wrapper, functionDefinition, componentOutput) {
|
|
1714
1937
|
const wrapperFilePath = import_path4.default.resolve(componentDirectory, wrapper.path);
|
|
1715
1938
|
if (await (0, import_fs_extra.pathExists)(wrapperFilePath) === false) {
|
|
1716
|
-
throw new
|
|
1939
|
+
throw new import_dx_common_lib8.BadRequestError(`Preview wrapper file "${wrapper.path}" does not exist`);
|
|
1717
1940
|
}
|
|
1718
1941
|
const wrapperContent = await import_promises.default.readFile(wrapperFilePath, {
|
|
1719
1942
|
encoding: "utf-8"
|
|
@@ -1729,17 +1952,17 @@ var ComponentPreviewService = class {
|
|
|
1729
1952
|
case "json":
|
|
1730
1953
|
return componentOutput;
|
|
1731
1954
|
default:
|
|
1732
|
-
return (0,
|
|
1955
|
+
return (0, import_dx_common_lib8.never)(type);
|
|
1733
1956
|
}
|
|
1734
1957
|
}
|
|
1735
1958
|
};
|
|
1736
1959
|
|
|
1737
1960
|
// src/test/helpers/stack.ts
|
|
1738
|
-
var
|
|
1961
|
+
var import_dx_common_lib10 = require("@squiz/dx-common-lib");
|
|
1739
1962
|
|
|
1740
1963
|
// src/RenderInputService.ts
|
|
1741
1964
|
var import_strict = __toESM(require("assert/strict"));
|
|
1742
|
-
var
|
|
1965
|
+
var import_dx_common_lib9 = require("@squiz/dx-common-lib");
|
|
1743
1966
|
var import_formatted_text_lib = require("@squiz/formatted-text-lib");
|
|
1744
1967
|
var import_dx_json_schema_lib2 = require("@squiz/dx-json-schema-lib");
|
|
1745
1968
|
var import_api3 = require("@opentelemetry/api");
|
|
@@ -1786,7 +2009,7 @@ var RenderInputService = class {
|
|
|
1786
2009
|
case "preview":
|
|
1787
2010
|
return this.getPreviewRenderInput(request, manifest);
|
|
1788
2011
|
default:
|
|
1789
|
-
return (0,
|
|
2012
|
+
return (0, import_dx_common_lib9.never)(renderType);
|
|
1790
2013
|
}
|
|
1791
2014
|
} finally {
|
|
1792
2015
|
span.end();
|
|
@@ -1797,10 +2020,10 @@ var RenderInputService = class {
|
|
|
1797
2020
|
getRenderType(request) {
|
|
1798
2021
|
if (request.previewKey) {
|
|
1799
2022
|
if (request.contentItemId) {
|
|
1800
|
-
throw new
|
|
2023
|
+
throw new import_dx_common_lib9.BadRequestError("You cannot provide a previewKey and a ContentId as input");
|
|
1801
2024
|
}
|
|
1802
2025
|
if (request.componentSet) {
|
|
1803
|
-
throw new
|
|
2026
|
+
throw new import_dx_common_lib9.BadRequestError("You cannot provide a previewKey and a componentSet as input");
|
|
1804
2027
|
}
|
|
1805
2028
|
return "preview";
|
|
1806
2029
|
}
|
|
@@ -1810,7 +2033,7 @@ var RenderInputService = class {
|
|
|
1810
2033
|
}
|
|
1811
2034
|
return "set-without-content-item";
|
|
1812
2035
|
}
|
|
1813
|
-
throw new
|
|
2036
|
+
throw new import_dx_common_lib9.BadRequestError("invalid input, you must provide either a previewKey or a component set");
|
|
1814
2037
|
}
|
|
1815
2038
|
async getContentItemAndSetInput(request, manifest) {
|
|
1816
2039
|
await this.assertComponentVersionInSet(request, manifest);
|
|
@@ -1932,13 +2155,13 @@ var RenderInputService = class {
|
|
|
1932
2155
|
const queryParameters = {};
|
|
1933
2156
|
for (const parameter of Object.keys(componentFunction.queryParameters)) {
|
|
1934
2157
|
if (componentFunction.queryParameters[parameter].required && request.expressRequest.query[parameter] === void 0) {
|
|
1935
|
-
throw new
|
|
2158
|
+
throw new import_dx_common_lib9.BadRequestError(`Required query parameter '${parameter}' is missing`);
|
|
1936
2159
|
}
|
|
1937
2160
|
if (request.expressRequest.query[parameter] === void 0) {
|
|
1938
2161
|
continue;
|
|
1939
2162
|
}
|
|
1940
2163
|
if (typeof request.expressRequest.query[parameter] !== "string") {
|
|
1941
|
-
throw new
|
|
2164
|
+
throw new import_dx_common_lib9.BadRequestError(`Value for query parameter '${parameter}' must be a string`);
|
|
1942
2165
|
}
|
|
1943
2166
|
queryParameters[parameter] = request.expressRequest.query[parameter];
|
|
1944
2167
|
}
|
|
@@ -1957,7 +2180,7 @@ var RenderInputService = class {
|
|
|
1957
2180
|
this.componentFunctionService.assertInputValidForComponentFunction(input, componentFunction);
|
|
1958
2181
|
} catch (e) {
|
|
1959
2182
|
if (e instanceof Error) {
|
|
1960
|
-
const error = new
|
|
2183
|
+
const error = new import_dx_common_lib9.BadRequestError(e.message);
|
|
1961
2184
|
error.stack = e.stack;
|
|
1962
2185
|
throw error;
|
|
1963
2186
|
}
|
|
@@ -1969,7 +2192,7 @@ var RenderInputService = class {
|
|
|
1969
2192
|
this.componentFunctionService.assertRenderInputValidForComponentFunction(input, componentFunction);
|
|
1970
2193
|
} catch (e) {
|
|
1971
2194
|
if (e instanceof Error) {
|
|
1972
|
-
const error = new
|
|
2195
|
+
const error = new import_dx_common_lib9.BadRequestError(e.message);
|
|
1973
2196
|
error.stack = e.stack;
|
|
1974
2197
|
throw error;
|
|
1975
2198
|
}
|
|
@@ -1981,7 +2204,7 @@ var RenderInputService = class {
|
|
|
1981
2204
|
const set = await this.componentSetService.getComponentSet(request.componentSet);
|
|
1982
2205
|
const isCompVersionInSet = await this.componentSetService.componentVersionInSet(manifest, set.webPath);
|
|
1983
2206
|
if (!isCompVersionInSet) {
|
|
1984
|
-
throw new
|
|
2207
|
+
throw new import_dx_common_lib9.ResourceNotFoundError(`${request.componentName} ${request.version} not in set ${set.webPath}`);
|
|
1985
2208
|
}
|
|
1986
2209
|
}
|
|
1987
2210
|
async getInputForPreview(request, manifest) {
|
|
@@ -2010,14 +2233,14 @@ var RenderInputService = class {
|
|
|
2010
2233
|
}
|
|
2011
2234
|
async getContentFromContentService(request) {
|
|
2012
2235
|
if (!this.contentItemService) {
|
|
2013
|
-
throw new
|
|
2236
|
+
throw new import_dx_common_lib9.InternalServerError("Content Item service is not configured");
|
|
2014
2237
|
}
|
|
2015
2238
|
if (!request.contentItemId) {
|
|
2016
|
-
throw new
|
|
2239
|
+
throw new import_dx_common_lib9.InternalServerError("Content Item id must be defined");
|
|
2017
2240
|
}
|
|
2018
2241
|
const contentInput = await this.contentItemService.getContentItem(request.contentItemId, this.getDxpApiKey());
|
|
2019
2242
|
if (!contentInput) {
|
|
2020
|
-
throw new
|
|
2243
|
+
throw new import_dx_common_lib9.ResourceNotFoundError(`Cannot find content item with ID '${request.contentItemId}'`);
|
|
2021
2244
|
}
|
|
2022
2245
|
return contentInput;
|
|
2023
2246
|
}
|
|
@@ -2057,10 +2280,10 @@ function getTestComponentFolder() {
|
|
|
2057
2280
|
const rootDir = (0, import_child_process.execSync)("git rev-parse --show-toplevel", { encoding: "utf-8" }).replace(/\n$/, "");
|
|
2058
2281
|
return import_path5.default.resolve(rootDir, "test-components");
|
|
2059
2282
|
}
|
|
2060
|
-
function setupTestApp(services = {}) {
|
|
2283
|
+
function setupTestApp(services = {}, config = {}) {
|
|
2061
2284
|
const dataMount = getTestComponentFolder();
|
|
2062
2285
|
const componentRootUrlResolver = () => "http://localhost:3000";
|
|
2063
|
-
const apiKeyService = new
|
|
2286
|
+
const apiKeyService = new import_dx_common_lib10.DevelopmentApiKeyService();
|
|
2064
2287
|
const sandbox = services.sandbox || createTestSandbox();
|
|
2065
2288
|
const componentRunnerService = new ComponentRunnerServiceWithWorkers(sandbox, testLogger, testComponentLogger);
|
|
2066
2289
|
const componentFunctionService = new import_component_lib3.ComponentFunctionService();
|
|
@@ -2075,20 +2298,23 @@ function setupTestApp(services = {}) {
|
|
|
2075
2298
|
contentItemService,
|
|
2076
2299
|
componentRootUrlResolver
|
|
2077
2300
|
);
|
|
2078
|
-
const app = setupApp(
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2301
|
+
const app = setupApp(
|
|
2302
|
+
{
|
|
2303
|
+
componentFunctionService,
|
|
2304
|
+
componentSetService,
|
|
2305
|
+
manifestService,
|
|
2306
|
+
componentRunnerService,
|
|
2307
|
+
contentItemService,
|
|
2308
|
+
renderInputService,
|
|
2309
|
+
logger: testLogger,
|
|
2310
|
+
apiKeyService,
|
|
2311
|
+
componentPreviewService: new ComponentPreviewService(),
|
|
2312
|
+
sandbox,
|
|
2313
|
+
componentRootUrlResolver,
|
|
2314
|
+
...services
|
|
2315
|
+
},
|
|
2316
|
+
config
|
|
2317
|
+
);
|
|
2092
2318
|
return { server: import_http.default.createServer(app), app };
|
|
2093
2319
|
}
|
|
2094
2320
|
function getTestWebServer(services = {}) {
|
|
@@ -2104,8 +2330,8 @@ function getTestWebServer(services = {}) {
|
|
|
2104
2330
|
return agent;
|
|
2105
2331
|
}
|
|
2106
2332
|
var TestServer = class {
|
|
2107
|
-
constructor(services = {}) {
|
|
2108
|
-
const { server, app } = setupTestApp(services);
|
|
2333
|
+
constructor(services = {}, config = {}) {
|
|
2334
|
+
const { server, app } = setupTestApp(services, config);
|
|
2109
2335
|
this.server = server;
|
|
2110
2336
|
this.server.on("close", async () => {
|
|
2111
2337
|
for (const service of Object.values(app.request.services)) {
|
|
@@ -3313,6 +3539,116 @@ function definitionRouteTests(request, _rootUrl = "http://localhost:3000") {
|
|
|
3313
3539
|
});
|
|
3314
3540
|
}
|
|
3315
3541
|
|
|
3542
|
+
// src/webserver/controllers/test/development-route-tests.ts
|
|
3543
|
+
function developmentRouteTests(request, devModeEnabled) {
|
|
3544
|
+
describe(`development routes`, () => {
|
|
3545
|
+
if (devModeEnabled) {
|
|
3546
|
+
describe("all route (dev mode enabled)", () => {
|
|
3547
|
+
it("should return an array of all component manifests", async () => {
|
|
3548
|
+
const response = await request().get("/dev/all");
|
|
3549
|
+
expect(response.statusCode).toEqual(200);
|
|
3550
|
+
expect(response.type).toEqual("application/json");
|
|
3551
|
+
expect(response.body).toEqual(
|
|
3552
|
+
expect.arrayContaining([
|
|
3553
|
+
expect.objectContaining({
|
|
3554
|
+
$schema: "http://localhost:3000/schemas/v1.json#",
|
|
3555
|
+
name: "test-preview-component",
|
|
3556
|
+
version: "1.0.1",
|
|
3557
|
+
mainFunction: "main",
|
|
3558
|
+
displayName: "some-display-name",
|
|
3559
|
+
namespace: "unit-test-components",
|
|
3560
|
+
description: "some-description",
|
|
3561
|
+
functions: expect.any(Array),
|
|
3562
|
+
staticFiles: expect.any(Object),
|
|
3563
|
+
previews: expect.any(Object)
|
|
3564
|
+
})
|
|
3565
|
+
])
|
|
3566
|
+
);
|
|
3567
|
+
});
|
|
3568
|
+
});
|
|
3569
|
+
describe("manifest route (dev mode enabled)", () => {
|
|
3570
|
+
it("should return the manifest of the requested component", async () => {
|
|
3571
|
+
const response = await request().get("/dev/manifest/unit-test-components/test-preview-component/1.0.1");
|
|
3572
|
+
expect(response.statusCode).toEqual(200);
|
|
3573
|
+
expect(response.type).toEqual("application/json");
|
|
3574
|
+
expect(response.body).toEqual(
|
|
3575
|
+
expect.objectContaining({
|
|
3576
|
+
$schema: "http://localhost:3000/schemas/v1.json#",
|
|
3577
|
+
name: "test-preview-component",
|
|
3578
|
+
version: "1.0.1",
|
|
3579
|
+
mainFunction: "main",
|
|
3580
|
+
displayName: "some-display-name",
|
|
3581
|
+
namespace: "unit-test-components",
|
|
3582
|
+
description: "some-description",
|
|
3583
|
+
functions: expect.any(Array),
|
|
3584
|
+
staticFiles: expect.any(Object),
|
|
3585
|
+
previews: expect.any(Object)
|
|
3586
|
+
})
|
|
3587
|
+
);
|
|
3588
|
+
});
|
|
3589
|
+
});
|
|
3590
|
+
describe("schemas route (dev mode enabled)", () => {
|
|
3591
|
+
it("should return the schemas of the requested component", async () => {
|
|
3592
|
+
const response = await request().get("/dev/schemas/unit-test-components/test-preview-component/1.0.1");
|
|
3593
|
+
expect(response.statusCode).toEqual(200);
|
|
3594
|
+
expect(response.type).toEqual("application/json");
|
|
3595
|
+
expect(response.body).toEqual([
|
|
3596
|
+
{
|
|
3597
|
+
name: "main",
|
|
3598
|
+
schema: {
|
|
3599
|
+
type: "object",
|
|
3600
|
+
properties: {
|
|
3601
|
+
something: {
|
|
3602
|
+
type: "string"
|
|
3603
|
+
}
|
|
3604
|
+
},
|
|
3605
|
+
required: []
|
|
3606
|
+
}
|
|
3607
|
+
},
|
|
3608
|
+
{
|
|
3609
|
+
name: "promise-func",
|
|
3610
|
+
schema: {
|
|
3611
|
+
type: "object",
|
|
3612
|
+
properties: {
|
|
3613
|
+
something: {
|
|
3614
|
+
type: "string"
|
|
3615
|
+
}
|
|
3616
|
+
},
|
|
3617
|
+
required: ["something"]
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
]);
|
|
3621
|
+
});
|
|
3622
|
+
});
|
|
3623
|
+
} else {
|
|
3624
|
+
describe("all route (dev mode disabled)", () => {
|
|
3625
|
+
it("all return a 404 error", async () => {
|
|
3626
|
+
const response = await request().get("/dev/all");
|
|
3627
|
+
expect(response.statusCode).toEqual(404);
|
|
3628
|
+
expect(response.type).toEqual("application/json");
|
|
3629
|
+
expect(response.body).toEqual({ message: "Route does not exist." });
|
|
3630
|
+
});
|
|
3631
|
+
});
|
|
3632
|
+
describe("manifest route (dev mode disabled)", () => {
|
|
3633
|
+
it("should return a 404 error", async () => {
|
|
3634
|
+
const response = await request().get("/dev/manifest/unit-test-components/test-preview-component/1.0.1");
|
|
3635
|
+
expect(response.statusCode).toEqual(404);
|
|
3636
|
+
expect(response.type).toEqual("application/json");
|
|
3637
|
+
expect(response.body).toEqual({ message: "Route does not exist." });
|
|
3638
|
+
});
|
|
3639
|
+
});
|
|
3640
|
+
describe("schemas route (dev mode disabled)", () => {
|
|
3641
|
+
it("should return a 404 error", async () => {
|
|
3642
|
+
const response = await request().get("/dev/schemas/unit-test-components/test-preview-component/1.0.1");
|
|
3643
|
+
expect(response.statusCode).toEqual(404);
|
|
3644
|
+
expect(response.type).toEqual("application/json");
|
|
3645
|
+
expect(response.body).toEqual({ message: "Route does not exist." });
|
|
3646
|
+
});
|
|
3647
|
+
});
|
|
3648
|
+
}
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3316
3652
|
// src/webserver/controllers/test/static-route-tests.ts
|
|
3317
3653
|
function staticRouteTests(request) {
|
|
3318
3654
|
describe("GET /s/set/unit-test-components/test-static-files/1.0.0/", () => {
|
|
@@ -3431,6 +3767,9 @@ function staticRouteTests(request) {
|
|
|
3431
3767
|
|
|
3432
3768
|
// src/webserver/controllers/test/render-route-tests.ts
|
|
3433
3769
|
var import_os2 = __toESM(require("os"));
|
|
3770
|
+
function wrapMessageInHtmlComment(message) {
|
|
3771
|
+
return `<!-- ${message} -->`;
|
|
3772
|
+
}
|
|
3434
3773
|
function renderRouteTests(request, rootUrl) {
|
|
3435
3774
|
describe("GET /r/unit-test-components/test-component/1.0.10/?_componentSet=set", () => {
|
|
3436
3775
|
it("should render the test component with html endpoint", async () => {
|
|
@@ -3500,12 +3839,12 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3500
3839
|
"/r/unit-test-components/test-component/1.0.4/render-json-invalid?_componentSet=set"
|
|
3501
3840
|
);
|
|
3502
3841
|
expect(response.statusCode).toEqual(500);
|
|
3503
|
-
expect(response.headers["content-type"]).toContain("
|
|
3504
|
-
expect(response.
|
|
3505
|
-
|
|
3506
|
-
"
|
|
3507
|
-
|
|
3508
|
-
|
|
3842
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3843
|
+
expect(response.text).toEqual(
|
|
3844
|
+
wrapMessageInHtmlComment(
|
|
3845
|
+
"failed validation: Expected `3` (string) in `#/my-array/0/a-number` to be of type `number`"
|
|
3846
|
+
)
|
|
3847
|
+
);
|
|
3509
3848
|
}, 2e4);
|
|
3510
3849
|
it("should validate a complex json against a schema", async () => {
|
|
3511
3850
|
const response = await request().get(
|
|
@@ -3528,13 +3867,13 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3528
3867
|
"/r/unit-test-components/test-component/1.0.4/render-json-nested-object-invalid?_componentSet=set"
|
|
3529
3868
|
);
|
|
3530
3869
|
expect(response.statusCode).toEqual(500);
|
|
3531
|
-
expect(response.headers["content-type"]).toContain("
|
|
3532
|
-
expect(response.
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3870
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3871
|
+
expect(response.text).toEqual(
|
|
3872
|
+
wrapMessageInHtmlComment(
|
|
3873
|
+
`failed validation: Expected \`false\` (string) in \`#/my-object/a-boolean\` to be of type \`boolean\`,
|
|
3874
|
+
Expected given value \`N\` in #/my-object/a-nested-object/an-enum\` to be one of \`[Y, E, S]\``
|
|
3875
|
+
)
|
|
3876
|
+
);
|
|
3538
3877
|
}, 2e4);
|
|
3539
3878
|
});
|
|
3540
3879
|
describe("GET /r/unit-test-components/test-component/1.0.7?_componentSet=set", () => {
|
|
@@ -3636,26 +3975,24 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3636
3975
|
it("should throw an error if trying to use modules in the js", async () => {
|
|
3637
3976
|
const response = await request().get("/r/unit-test-components/test-component/1.0.8/module-js?_componentSet=set");
|
|
3638
3977
|
expect(response.statusCode).toEqual(500);
|
|
3639
|
-
expect(response.headers["content-type"]).toContain("
|
|
3640
|
-
expect(response.
|
|
3978
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3979
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment("ESM style modules are not supported."));
|
|
3641
3980
|
});
|
|
3642
3981
|
it("should throw an error if the component uploaded does not export a function", async () => {
|
|
3643
3982
|
const response = await request().get(
|
|
3644
3983
|
"/r/unit-test-components/test-component/1.0.8/no-module-export?_componentSet=set"
|
|
3645
3984
|
);
|
|
3646
3985
|
expect(response.statusCode).toEqual(500);
|
|
3647
|
-
expect(response.headers["content-type"]).toContain("
|
|
3648
|
-
expect(response.
|
|
3986
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3987
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment("script is not a function"));
|
|
3649
3988
|
});
|
|
3650
3989
|
it("should throw an error if the component is not async and throws and error object", async () => {
|
|
3651
3990
|
const response = await request().get(
|
|
3652
3991
|
"/r/unit-test-components/test-component/1.0.8/no-promise-throws-error?_componentSet=set"
|
|
3653
3992
|
);
|
|
3654
3993
|
expect(response.statusCode).toEqual(500);
|
|
3655
|
-
expect(response.headers["content-type"]).toContain("
|
|
3656
|
-
expect(response.
|
|
3657
|
-
message: "throw error"
|
|
3658
|
-
});
|
|
3994
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3995
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment("throw error"));
|
|
3659
3996
|
});
|
|
3660
3997
|
it("throw an error if the component is not async and throws an arbitrary value", async () => {
|
|
3661
3998
|
const response = await request().get(
|
|
@@ -3663,10 +4000,10 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3663
4000
|
);
|
|
3664
4001
|
expect(response.statusCode).toEqual(500);
|
|
3665
4002
|
expect(response.headers["cache-control"]).toEqual("no-cache, no-store, max-age=0");
|
|
3666
|
-
expect(response.headers["content-type"]).toContain("
|
|
3667
|
-
expect(response.
|
|
3668
|
-
|
|
3669
|
-
|
|
4003
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4004
|
+
expect(response.text).toEqual(
|
|
4005
|
+
wrapMessageInHtmlComment("An error occurred with no additional information available")
|
|
4006
|
+
);
|
|
3670
4007
|
});
|
|
3671
4008
|
it("throw an error if the component is not async and throws undefined", async () => {
|
|
3672
4009
|
const response = await request().get(
|
|
@@ -3674,10 +4011,10 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3674
4011
|
);
|
|
3675
4012
|
expect(response.statusCode).toEqual(500);
|
|
3676
4013
|
expect(response.headers["cache-control"]).toEqual("no-cache, no-store, max-age=0");
|
|
3677
|
-
expect(response.headers["content-type"]).toContain("
|
|
3678
|
-
expect(response.
|
|
3679
|
-
|
|
3680
|
-
|
|
4014
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4015
|
+
expect(response.text).toEqual(
|
|
4016
|
+
wrapMessageInHtmlComment("An error occurred with no additional information available")
|
|
4017
|
+
);
|
|
3681
4018
|
});
|
|
3682
4019
|
it("should throw an error if the component is async/returns a promise but rejects", async () => {
|
|
3683
4020
|
const response = await request().get(
|
|
@@ -3685,10 +4022,10 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3685
4022
|
);
|
|
3686
4023
|
expect(response.statusCode).toEqual(500);
|
|
3687
4024
|
expect(response.headers["cache-control"]).toEqual("no-cache, no-store, max-age=0");
|
|
3688
|
-
expect(response.headers["content-type"]).toContain("
|
|
3689
|
-
expect(response.
|
|
3690
|
-
|
|
3691
|
-
|
|
4025
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4026
|
+
expect(response.text).toEqual(
|
|
4027
|
+
wrapMessageInHtmlComment("An error occurred with no additional information available")
|
|
4028
|
+
);
|
|
3692
4029
|
});
|
|
3693
4030
|
it("should throw an error if the component is async/returns a promise and throws and error object", async () => {
|
|
3694
4031
|
const response = await request().get(
|
|
@@ -3696,10 +4033,8 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3696
4033
|
);
|
|
3697
4034
|
expect(response.statusCode).toEqual(500);
|
|
3698
4035
|
expect(response.headers["cache-control"]).toEqual("no-cache, no-store, max-age=0");
|
|
3699
|
-
expect(response.headers["content-type"]).toContain("
|
|
3700
|
-
expect(response.
|
|
3701
|
-
message: "throws error"
|
|
3702
|
-
});
|
|
4036
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4037
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment("throws error"));
|
|
3703
4038
|
});
|
|
3704
4039
|
it("throw an error if the component is async/returns a promise and throws an arbitrary value", async () => {
|
|
3705
4040
|
const response = await request().get(
|
|
@@ -3707,10 +4042,10 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3707
4042
|
);
|
|
3708
4043
|
expect(response.statusCode).toEqual(500);
|
|
3709
4044
|
expect(response.headers["cache-control"]).toEqual("no-cache, no-store, max-age=0");
|
|
3710
|
-
expect(response.headers["content-type"]).toContain("
|
|
3711
|
-
expect(response.
|
|
3712
|
-
|
|
3713
|
-
|
|
4045
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4046
|
+
expect(response.text).toEqual(
|
|
4047
|
+
wrapMessageInHtmlComment("An error occurred with no additional information available")
|
|
4048
|
+
);
|
|
3714
4049
|
});
|
|
3715
4050
|
it("throw an error if the component is async/returns a promise and throws undefined", async () => {
|
|
3716
4051
|
const response = await request().get(
|
|
@@ -3718,20 +4053,18 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3718
4053
|
);
|
|
3719
4054
|
expect(response.statusCode).toEqual(500);
|
|
3720
4055
|
expect(response.headers["cache-control"]).toEqual("no-cache, no-store, max-age=0");
|
|
3721
|
-
expect(response.headers["content-type"]).toContain("
|
|
3722
|
-
expect(response.
|
|
3723
|
-
|
|
3724
|
-
|
|
4056
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4057
|
+
expect(response.text).toEqual(
|
|
4058
|
+
wrapMessageInHtmlComment("An error occurred with no additional information available")
|
|
4059
|
+
);
|
|
3725
4060
|
});
|
|
3726
4061
|
it("throw an error if the component has a syntax error", async () => {
|
|
3727
4062
|
const response = await request().get(
|
|
3728
4063
|
"/r/unit-test-components/test-component/1.0.8/syntax-error?_componentSet=set"
|
|
3729
4064
|
);
|
|
3730
4065
|
expect(response.statusCode).toEqual(500);
|
|
3731
|
-
expect(response.headers["content-type"]).toContain("
|
|
3732
|
-
expect(response.
|
|
3733
|
-
message: "Unexpected token '}'"
|
|
3734
|
-
});
|
|
4066
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4067
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment("Unexpected token '}'"));
|
|
3735
4068
|
});
|
|
3736
4069
|
});
|
|
3737
4070
|
describe("GET /r/unit-test-components/test-static-files/1.0.0?_componentSet=set", () => {
|
|
@@ -3869,6 +4202,9 @@ function renderRouteTests(request, rootUrl) {
|
|
|
3869
4202
|
}
|
|
3870
4203
|
|
|
3871
4204
|
// src/webserver/controllers/test/render-route-sandbox-tests.ts
|
|
4205
|
+
function wrapMessageInHtmlComment2(message) {
|
|
4206
|
+
return `<!-- ${message} -->`;
|
|
4207
|
+
}
|
|
3872
4208
|
function renderRouteSandboxTests(request) {
|
|
3873
4209
|
describe("GET /r/unit-test-components/test-malicious-code/...", () => {
|
|
3874
4210
|
it("should timeout infinite running code", async () => {
|
|
@@ -3876,40 +4212,47 @@ function renderRouteSandboxTests(request) {
|
|
|
3876
4212
|
"/r/unit-test-components/test-malicious-code/1.0.0/?_componentSet=set&something=hello"
|
|
3877
4213
|
);
|
|
3878
4214
|
expect(response.statusCode).toEqual(500);
|
|
3879
|
-
expect(response.headers["content-type"]).toContain("
|
|
3880
|
-
expect(response.
|
|
3881
|
-
|
|
3882
|
-
|
|
4215
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4216
|
+
expect(response.text).toEqual(
|
|
4217
|
+
wrapMessageInHtmlComment2(
|
|
4218
|
+
"function while-true of component unit-test-components/test-malicious-code 1.0.0 could not complete with in the allotted time"
|
|
4219
|
+
)
|
|
4220
|
+
);
|
|
3883
4221
|
}, 3e4);
|
|
3884
4222
|
it("should timeout non terminating code", async () => {
|
|
3885
4223
|
const response = await request().get(
|
|
3886
4224
|
"/r/unit-test-components/test-malicious-code/1.3.0/executing-after-return?_componentSet=set"
|
|
3887
4225
|
);
|
|
3888
4226
|
expect(response.statusCode).toEqual(500);
|
|
3889
|
-
expect(response.headers["content-type"]).toContain("
|
|
3890
|
-
expect(response.
|
|
3891
|
-
|
|
3892
|
-
|
|
4227
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4228
|
+
expect(response.text).toEqual(
|
|
4229
|
+
wrapMessageInHtmlComment2(
|
|
4230
|
+
"function executing-after-return of component unit-test-components/test-malicious-code 1.3.0 could not complete with in the allotted time"
|
|
4231
|
+
)
|
|
4232
|
+
);
|
|
3893
4233
|
}, 3e4);
|
|
3894
4234
|
it.skip("should not allow starting your own services", async () => {
|
|
3895
4235
|
const response = await request().get(
|
|
3896
4236
|
"/r/unit-test-components/test-malicious-code/1.3.0/reverse-shell?_componentSet=set"
|
|
3897
4237
|
);
|
|
4238
|
+
expect(response.text).toEqual(
|
|
4239
|
+
wrapMessageInHtmlComment2(
|
|
4240
|
+
"function executing-after-return of component unit-test-components/test-malicious-code 1.3.0 could not complete with in the allotted time"
|
|
4241
|
+
)
|
|
4242
|
+
);
|
|
3898
4243
|
expect(response.statusCode).toEqual(500);
|
|
3899
|
-
expect(response.headers["content-type"]).toContain("
|
|
3900
|
-
expect(response.body).toEqual({
|
|
3901
|
-
message: "function executing-after-return of component unit-test-components/test-malicious-code 1.3.0 could not complete with in the allotted time"
|
|
3902
|
-
});
|
|
4244
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3903
4245
|
}, 1e4);
|
|
3904
4246
|
it.skip("should deny access to fs", async () => {
|
|
3905
4247
|
const response = await request().get(
|
|
3906
4248
|
"/r/unit-test-components/test-malicious-code/1.1.0/?_componentSet=set&something=hello"
|
|
3907
4249
|
);
|
|
3908
4250
|
expect(response.statusCode).toEqual(500);
|
|
3909
|
-
expect(response.headers["content-type"]).toContain("
|
|
4251
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
3910
4252
|
expect(response.body).toEqual({
|
|
3911
4253
|
message: "Cannot find module 'fs'"
|
|
3912
4254
|
});
|
|
4255
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment2(`"Cannot find module 'fs'`));
|
|
3913
4256
|
});
|
|
3914
4257
|
it("should allow access to a subset of node provided modules", async () => {
|
|
3915
4258
|
const response = await request().get(
|
|
@@ -3993,100 +4336,92 @@ function renderRouteSandboxTests(request) {
|
|
|
3993
4336
|
"/r/unit-test-components/test-malicious-code/1.2.0/process-exit?_componentSet=set"
|
|
3994
4337
|
);
|
|
3995
4338
|
expect(response.statusCode).toEqual(500);
|
|
3996
|
-
expect(response.headers["content-type"]).toContain("
|
|
3997
|
-
expect(response.
|
|
3998
|
-
message: "process.exit is not a function"
|
|
3999
|
-
});
|
|
4339
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4340
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment2("process.exit is not a function"));
|
|
4000
4341
|
});
|
|
4001
4342
|
it("should not allow process.binding calls", async () => {
|
|
4002
4343
|
const response = await request().get(
|
|
4003
4344
|
"/r/unit-test-components/test-malicious-code/1.2.0/process-binding?_componentSet=set"
|
|
4004
4345
|
);
|
|
4005
4346
|
expect(response.statusCode).toEqual(500);
|
|
4006
|
-
expect(response.headers["content-type"]).toContain("
|
|
4007
|
-
expect(response.
|
|
4008
|
-
|
|
4009
|
-
|
|
4347
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4348
|
+
expect(response.text).toEqual(
|
|
4349
|
+
wrapMessageInHtmlComment2("Cannot read properties of undefined (reading 'process')")
|
|
4350
|
+
);
|
|
4010
4351
|
});
|
|
4011
4352
|
it("should not allow process.kill calls", async () => {
|
|
4012
4353
|
const response = await request().get(
|
|
4013
4354
|
"/r/unit-test-components/test-malicious-code/1.2.0/process-kill?_componentSet=set"
|
|
4014
4355
|
);
|
|
4015
4356
|
expect(response.statusCode).toEqual(500);
|
|
4016
|
-
expect(response.headers["content-type"]).toContain("
|
|
4017
|
-
expect(response.
|
|
4018
|
-
message: "process.kill is not a function"
|
|
4019
|
-
});
|
|
4357
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4358
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment2("process.kill is not a function"));
|
|
4020
4359
|
});
|
|
4021
4360
|
it("should not allow process.abort calls", async () => {
|
|
4022
4361
|
const response = await request().get(
|
|
4023
4362
|
"/r/unit-test-components/test-malicious-code/1.2.0/process-abort?_componentSet=set"
|
|
4024
4363
|
);
|
|
4025
4364
|
expect(response.statusCode).toEqual(500);
|
|
4026
|
-
expect(response.headers["content-type"]).toContain("
|
|
4027
|
-
expect(response.
|
|
4028
|
-
message: "process.abort is not a function"
|
|
4029
|
-
});
|
|
4365
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4366
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment2("process.abort is not a function"));
|
|
4030
4367
|
});
|
|
4031
4368
|
it.skip("should not allow access to parentPort", async () => {
|
|
4032
4369
|
const response = await request().get(
|
|
4033
4370
|
"/r/unit-test-components/test-malicious-code/1.3.0/accessing-parent-port?_componentSet=set"
|
|
4034
4371
|
);
|
|
4035
4372
|
expect(response.statusCode).toEqual(500);
|
|
4036
|
-
expect(response.headers["content-type"]).toContain("
|
|
4037
|
-
expect(response.
|
|
4038
|
-
message: "Cannot find module 'worker_threads'"
|
|
4039
|
-
});
|
|
4373
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4374
|
+
expect(response.text).toEqual(wrapMessageInHtmlComment2("Cannot find module 'worker_threads'"));
|
|
4040
4375
|
});
|
|
4041
4376
|
it("should not allow escaping the sandbox through the constructor", async () => {
|
|
4042
4377
|
const response = await request().get(
|
|
4043
4378
|
"/r/unit-test-components/test-malicious-code/1.2.0/constructor-escape?_componentSet=set"
|
|
4044
4379
|
);
|
|
4045
4380
|
expect(response.statusCode).toEqual(500);
|
|
4046
|
-
expect(response.headers["content-type"]).toContain("
|
|
4047
|
-
expect(response.
|
|
4048
|
-
|
|
4049
|
-
|
|
4381
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4382
|
+
expect(response.text).toEqual(
|
|
4383
|
+
wrapMessageInHtmlComment2("Cannot read properties of undefined (reading 'constructor')")
|
|
4384
|
+
);
|
|
4050
4385
|
});
|
|
4051
4386
|
it("should not allow escaping the sandbox through the constructor and calling exit", async () => {
|
|
4052
4387
|
const response = await request().get(
|
|
4053
4388
|
"/r/unit-test-components/test-malicious-code/1.2.0/constructor-escape?_componentSet=set"
|
|
4054
4389
|
);
|
|
4055
4390
|
expect(response.statusCode).toEqual(500);
|
|
4056
|
-
expect(response.headers["content-type"]).toContain("
|
|
4057
|
-
expect(response.
|
|
4058
|
-
|
|
4059
|
-
|
|
4391
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4392
|
+
expect(response.text).toEqual(
|
|
4393
|
+
wrapMessageInHtmlComment2("Cannot read properties of undefined (reading 'constructor')")
|
|
4394
|
+
);
|
|
4060
4395
|
});
|
|
4061
4396
|
it("should not allow escaping the sandbox through the constructor and loading restricted modules", async () => {
|
|
4062
4397
|
const response = await request().get(
|
|
4063
4398
|
"/r/unit-test-components/test-malicious-code/1.2.0/constructor-fs?_componentSet=set"
|
|
4064
4399
|
);
|
|
4400
|
+
expect(response.text).toEqual(
|
|
4401
|
+
wrapMessageInHtmlComment2("Cannot read properties of undefined (reading 'constructor')")
|
|
4402
|
+
);
|
|
4065
4403
|
expect(response.statusCode).toEqual(500);
|
|
4066
|
-
expect(response.headers["content-type"]).toContain("
|
|
4067
|
-
expect(response.body).toEqual({
|
|
4068
|
-
message: "Cannot read properties of undefined (reading 'constructor')"
|
|
4069
|
-
});
|
|
4404
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4070
4405
|
});
|
|
4071
4406
|
it("should not allow circumvention of module restrictions", async () => {
|
|
4072
4407
|
const response = await request().get(
|
|
4073
4408
|
"/r/unit-test-components/test-malicious-code/1.2.0/circumventing-module-restriction?_componentSet=set"
|
|
4074
4409
|
);
|
|
4075
4410
|
expect(response.statusCode).toEqual(500);
|
|
4076
|
-
expect(response.headers["content-type"]).toContain("
|
|
4077
|
-
expect(response.
|
|
4078
|
-
|
|
4079
|
-
|
|
4411
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4412
|
+
expect(response.text).toEqual(
|
|
4413
|
+
wrapMessageInHtmlComment2("Cannot read properties of undefined (reading 'constructor')")
|
|
4414
|
+
);
|
|
4080
4415
|
});
|
|
4081
4416
|
it("should not allow circumvention of module restrictions with mainmodule", async () => {
|
|
4082
4417
|
const response = await request().get(
|
|
4083
4418
|
"/r/unit-test-components/test-malicious-code/1.2.0/circumventing-module-restriction-mainmodule?_componentSet=set"
|
|
4084
4419
|
);
|
|
4085
4420
|
expect(response.statusCode).toEqual(500);
|
|
4086
|
-
expect(response.headers["content-type"]).toContain("
|
|
4087
|
-
expect(response.
|
|
4088
|
-
|
|
4089
|
-
|
|
4421
|
+
expect(response.headers["content-type"]).toContain("text/html; charset=utf-8");
|
|
4422
|
+
expect(response.text).toEqual(
|
|
4423
|
+
wrapMessageInHtmlComment2("Cannot read properties of undefined (reading 'require')")
|
|
4424
|
+
);
|
|
4090
4425
|
});
|
|
4091
4426
|
});
|
|
4092
4427
|
}
|
|
@@ -4195,7 +4530,8 @@ var routeTests = {
|
|
|
4195
4530
|
static: staticRouteTests,
|
|
4196
4531
|
render: renderRouteTests,
|
|
4197
4532
|
renderSandbox: renderRouteSandboxTests,
|
|
4198
|
-
preview: previewRouteTests
|
|
4533
|
+
preview: previewRouteTests,
|
|
4534
|
+
development: developmentRouteTests
|
|
4199
4535
|
};
|
|
4200
4536
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4201
4537
|
0 && (module.exports = {
|