@modularizer/plat 0.15.0 → 0.16.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/dist/bridge/cli.d.ts +3 -0
- package/dist/bridge/cli.d.ts.map +1 -0
- package/dist/bridge/cli.js +128 -0
- package/dist/bridge/cli.js.map +1 -0
- package/dist/bridge/http-forwarder.d.ts +51 -0
- package/dist/bridge/http-forwarder.d.ts.map +1 -0
- package/dist/bridge/http-forwarder.js +564 -0
- package/dist/bridge/http-forwarder.js.map +1 -0
- package/dist/bridge/index.d.ts +57 -0
- package/dist/bridge/index.d.ts.map +1 -0
- package/dist/bridge/index.js +69 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/cli/commands/api-proxy.d.ts.map +1 -1
- package/dist/cli/commands/api-proxy.js +5 -7
- package/dist/cli/commands/api-proxy.js.map +1 -1
- package/dist/cli/commands/jwt-cmd.d.ts.map +1 -1
- package/dist/cli/commands/jwt-cmd.js +1 -4
- package/dist/cli/commands/jwt-cmd.js.map +1 -1
- package/dist/cli/proxy.d.ts.map +1 -1
- package/dist/cli/proxy.js +9 -20
- package/dist/cli/proxy.js.map +1 -1
- package/dist/cli/runtime.d.ts.map +1 -1
- package/dist/cli/runtime.js +2 -6
- package/dist/cli/runtime.js.map +1 -1
- package/dist/client/css-transport-plugin.d.ts.map +1 -1
- package/dist/client/css-transport-plugin.js +40 -0
- package/dist/client/css-transport-plugin.js.map +1 -1
- package/dist/client/openapi-client.d.ts +5 -0
- package/dist/client/openapi-client.d.ts.map +1 -1
- package/dist/client/openapi-client.js +21 -2
- package/dist/client/openapi-client.js.map +1 -1
- package/dist/client-entry.d.ts +2 -0
- package/dist/client-entry.d.ts.map +1 -1
- package/dist/client-entry.js +2 -0
- package/dist/client-entry.js.map +1 -1
- package/dist/client-server-entry.d.ts +1 -0
- package/dist/client-server-entry.d.ts.map +1 -1
- package/dist/client-server-entry.js +1 -0
- package/dist/client-server-entry.js.map +1 -1
- package/dist/client-side-server/authority-default.d.ts +13 -0
- package/dist/client-side-server/authority-default.d.ts.map +1 -0
- package/dist/client-side-server/authority-default.js +13 -0
- package/dist/client-side-server/authority-default.js.map +1 -0
- package/dist/client-side-server/channel.d.ts.map +1 -1
- package/dist/client-side-server/channel.js +179 -78
- package/dist/client-side-server/channel.js.map +1 -1
- package/dist/client-side-server/identity.d.ts +1 -0
- package/dist/client-side-server/identity.d.ts.map +1 -1
- package/dist/client-side-server/identity.js +117 -0
- package/dist/client-side-server/identity.js.map +1 -1
- package/dist/client-side-server/mqtt-webrtc.d.ts +13 -2
- package/dist/client-side-server/mqtt-webrtc.d.ts.map +1 -1
- package/dist/client-side-server/mqtt-webrtc.js +17 -2
- package/dist/client-side-server/mqtt-webrtc.js.map +1 -1
- package/dist/client-side-server/plat-bridge.js +3 -1
- package/dist/client-side-server/plat-bridge.js.map +1 -1
- package/dist/client-side-server/plat-fetch.d.ts +3 -0
- package/dist/client-side-server/plat-fetch.d.ts.map +1 -1
- package/dist/client-side-server/plat-fetch.js +199 -29
- package/dist/client-side-server/plat-fetch.js.map +1 -1
- package/dist/client-side-server/plat-service-worker-client.d.ts.map +1 -1
- package/dist/client-side-server/plat-service-worker-client.js +3 -0
- package/dist/client-side-server/plat-service-worker-client.js.map +1 -1
- package/dist/client-side-server/plat-service-worker.js +30 -0
- package/dist/client-side-server/plat-service-worker.js.map +1 -1
- package/dist/client-side-server/protocol.d.ts +22 -0
- package/dist/client-side-server/protocol.d.ts.map +1 -1
- package/dist/client-side-server/protocol.js.map +1 -1
- package/dist/client-side-server/runtime-fetch.d.ts +20 -0
- package/dist/client-side-server/runtime-fetch.d.ts.map +1 -0
- package/dist/client-side-server/runtime-fetch.js +32 -0
- package/dist/client-side-server/runtime-fetch.js.map +1 -0
- package/dist/client-side-server/runtime.d.ts.map +1 -1
- package/dist/client-side-server/runtime.js +36 -7
- package/dist/client-side-server/runtime.js.map +1 -1
- package/dist/client-side-server/server.d.ts.map +1 -1
- package/dist/client-side-server/server.js +29 -5
- package/dist/client-side-server/server.js.map +1 -1
- package/dist/server/config/types.d.ts +12 -1
- package/dist/server/config/types.d.ts.map +1 -1
- package/dist/server/core.d.ts.map +1 -1
- package/dist/server/core.js +25 -14
- package/dist/server/core.js.map +1 -1
- package/dist/server/docs-html.d.ts +11 -0
- package/dist/server/docs-html.d.ts.map +1 -0
- package/dist/server/docs-html.js +30 -0
- package/dist/server/docs-html.js.map +1 -0
- package/dist/server/operation-registry.d.ts +1 -0
- package/dist/server/operation-registry.d.ts.map +1 -1
- package/dist/server/operation-registry.js +16 -2
- package/dist/server/operation-registry.js.map +1 -1
- package/dist/server/routing.d.ts +5 -0
- package/dist/server/routing.d.ts.map +1 -1
- package/dist/server/routing.js +32 -2
- package/dist/server/routing.js.map +1 -1
- package/dist/server/rpc-protocol-plugin.js +2 -2
- package/dist/server/rpc-protocol-plugin.js.map +1 -1
- package/dist/server/server.d.ts +4 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +229 -53
- package/dist/server/server.js.map +1 -1
- package/dist/server/transports.d.ts +1 -0
- package/dist/server/transports.d.ts.map +1 -1
- package/dist/server/webrtc-plugin.d.ts +21 -0
- package/dist/server/webrtc-plugin.d.ts.map +1 -0
- package/dist/server/webrtc-plugin.js +198 -0
- package/dist/server/webrtc-plugin.js.map +1 -0
- package/dist/static/file-response.d.ts +2 -0
- package/dist/static/file-response.d.ts.map +1 -1
- package/dist/static/file-response.js +2 -0
- package/dist/static/file-response.js.map +1 -1
- package/dist/static/plat-static-folders.d.ts +11 -0
- package/dist/static/plat-static-folders.d.ts.map +1 -0
- package/dist/static/plat-static-folders.js +44 -0
- package/dist/static/plat-static-folders.js.map +1 -0
- package/dist/static/static-folder.d.ts +4 -0
- package/dist/static/static-folder.d.ts.map +1 -1
- package/dist/static/static-folder.js +27 -2
- package/dist/static/static-folder.js.map +1 -1
- package/dist/types/endpoints.d.ts +3 -0
- package/dist/types/endpoints.d.ts.map +1 -1
- package/package.json +5 -1
package/dist/server/server.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import express from "express";
|
|
2
2
|
import { createServer as createHttpServer } from 'node:http';
|
|
3
|
+
import nodePath from 'node:path';
|
|
3
4
|
import { applyRateLimitCheck, applyRateLimitRefund, createInMemoryRateLimit } from "./rate-limit/index.js";
|
|
4
5
|
import { applyTokenLimitCheck, applyTokenLimitFailure, applyTokenLimitResponse, createInMemoryTokenLimit } from "./token-limit/index.js";
|
|
5
6
|
import { applyCacheCheck, applyCacheStore, createInMemoryCache } from "./cache/index.js";
|
|
@@ -14,10 +15,12 @@ import { DEFAULT_RPC_PATH } from '../rpc.js';
|
|
|
14
15
|
import { InMemoryCallSessionController } from "./call-sessions.js";
|
|
15
16
|
import { createRpcProtocolPlugin } from './rpc-protocol-plugin.js';
|
|
16
17
|
import { createFileQueueProtocolPlugin } from './file-queue-protocol-plugin.js';
|
|
18
|
+
import { createWebRTCProtocolPlugin } from './webrtc-plugin.js';
|
|
17
19
|
import { PLATOperationRegistry } from './operation-registry.js';
|
|
18
20
|
import { PLATServerCore } from './core.js';
|
|
19
21
|
import { createAuthorityServerController } from './authority-server.js';
|
|
20
22
|
import { isFileResponse } from '../static/file-response.js';
|
|
23
|
+
import { createWildcardRouteMatcher } from './routing.js';
|
|
21
24
|
export class PLATServer {
|
|
22
25
|
app;
|
|
23
26
|
options;
|
|
@@ -31,6 +34,8 @@ export class PLATServer {
|
|
|
31
34
|
staticFolders = [];
|
|
32
35
|
pendingRootFolder;
|
|
33
36
|
core;
|
|
37
|
+
teardownRuntimeCallbacks = [];
|
|
38
|
+
serverCreatedAt = Date.now();
|
|
34
39
|
constructor(options = {}, ...ControllerClasses) {
|
|
35
40
|
this.app = express();
|
|
36
41
|
this.options = {
|
|
@@ -187,6 +192,7 @@ export class PLATServer {
|
|
|
187
192
|
}
|
|
188
193
|
// General help endpoint
|
|
189
194
|
this.app.get('/help', (req, res) => {
|
|
195
|
+
const origin = `${req.protocol}://${req.headers.host ?? ''}`;
|
|
190
196
|
const help = {
|
|
191
197
|
endpoints: {
|
|
192
198
|
'GET /endpoints': 'List all available API endpoints with descriptions',
|
|
@@ -225,12 +231,12 @@ export class PLATServer {
|
|
|
225
231
|
},
|
|
226
232
|
},
|
|
227
233
|
examples: [
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
+
`curl ${origin}/endpoints`,
|
|
235
|
+
`curl "${origin}/endpoints?method=POST"`,
|
|
236
|
+
`curl "${origin}/endpoints?search=user"`,
|
|
237
|
+
`curl "${origin}/endpoints?format=json"`,
|
|
238
|
+
`curl "${origin}/openapi-jq?filter=.paths"`,
|
|
239
|
+
`curl "${origin}/api/users?help=true"`,
|
|
234
240
|
],
|
|
235
241
|
};
|
|
236
242
|
res.json(help);
|
|
@@ -407,12 +413,24 @@ export class PLATServer {
|
|
|
407
413
|
* No path parameters in decorators - all routing is done by method names.
|
|
408
414
|
*/
|
|
409
415
|
register(...ControllerClasses) {
|
|
416
|
+
const exactRegistrations = [];
|
|
417
|
+
const wildcardRegistrations = [];
|
|
410
418
|
for (const registered of this.core.registerControllers(...ControllerClasses)) {
|
|
411
419
|
const { operation: rpcOperation, route } = registered;
|
|
412
|
-
const { methodName
|
|
413
|
-
const httpMethod = route.method.toLowerCase();
|
|
420
|
+
const { methodName } = route;
|
|
414
421
|
const routeMeta = rpcOperation.routeMeta;
|
|
415
|
-
const handler = async (req, res) => {
|
|
422
|
+
const handler = async (req, res, next) => {
|
|
423
|
+
if (rpcOperation.isWildcard) {
|
|
424
|
+
const resolved = this.resolveOperation({
|
|
425
|
+
method: req.method,
|
|
426
|
+
path: req.path,
|
|
427
|
+
});
|
|
428
|
+
if (!resolved || resolved.methodName !== rpcOperation.methodName) {
|
|
429
|
+
next();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
const requestPath = rpcOperation.isWildcard ? req.path : rpcOperation.path;
|
|
416
434
|
let input = {
|
|
417
435
|
...req.params,
|
|
418
436
|
...req.query,
|
|
@@ -436,7 +454,7 @@ export class PLATServer {
|
|
|
436
454
|
const session = this.options.calls.controller.create({
|
|
437
455
|
operationId: methodName,
|
|
438
456
|
method: req.method,
|
|
439
|
-
path:
|
|
457
|
+
path: requestPath,
|
|
440
458
|
});
|
|
441
459
|
const abortController = new AbortController();
|
|
442
460
|
this.options.calls.controller.setCancel(session.id, () => abortController.abort());
|
|
@@ -454,7 +472,7 @@ export class PLATServer {
|
|
|
454
472
|
const deferredEnvelope = {
|
|
455
473
|
protocol: 'http',
|
|
456
474
|
method: req.method,
|
|
457
|
-
path:
|
|
475
|
+
path: requestPath,
|
|
458
476
|
headers: req.headers,
|
|
459
477
|
input,
|
|
460
478
|
ctx,
|
|
@@ -484,7 +502,7 @@ export class PLATServer {
|
|
|
484
502
|
const execution = await this.dispatchTransportCall(rpcOperation, {
|
|
485
503
|
protocol: 'http',
|
|
486
504
|
method: req.method,
|
|
487
|
-
path:
|
|
505
|
+
path: requestPath,
|
|
488
506
|
headers: req.headers,
|
|
489
507
|
input,
|
|
490
508
|
ctx,
|
|
@@ -535,10 +553,31 @@ export class PLATServer {
|
|
|
535
553
|
}
|
|
536
554
|
}
|
|
537
555
|
};
|
|
538
|
-
|
|
539
|
-
|
|
556
|
+
if (rpcOperation.isWildcard) {
|
|
557
|
+
wildcardRegistrations.push({ registered, handler });
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
exactRegistrations.push({ registered, handler });
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
for (const { registered, handler } of exactRegistrations) {
|
|
564
|
+
this.registerExpressRoute(registered.route.method, registered.operation.path, handler);
|
|
540
565
|
for (const variant of registered.variants) {
|
|
541
|
-
this.
|
|
566
|
+
this.registerExpressRoute(variant.method, variant.path, handler);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
for (const { registered, handler } of wildcardRegistrations) {
|
|
570
|
+
const wildcardRoutes = [
|
|
571
|
+
{ method: registered.operation.method, path: registered.operation.path },
|
|
572
|
+
...registered.variants,
|
|
573
|
+
];
|
|
574
|
+
const seen = new Set();
|
|
575
|
+
for (const wildcardRoute of wildcardRoutes) {
|
|
576
|
+
const key = `${wildcardRoute.method} ${wildcardRoute.path}`;
|
|
577
|
+
if (seen.has(key))
|
|
578
|
+
continue;
|
|
579
|
+
seen.add(key);
|
|
580
|
+
this.registerWildcardExpressRoute(wildcardRoute.method, wildcardRoute.path, handler);
|
|
542
581
|
}
|
|
543
582
|
}
|
|
544
583
|
// Register static folder routes (after all API routes for correct priority)
|
|
@@ -556,39 +595,144 @@ export class PLATServer {
|
|
|
556
595
|
* Create CORS middleware
|
|
557
596
|
*/
|
|
558
597
|
createCORSMiddleware(corsConfig) {
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
598
|
+
// If corsConfig is a function, handle per-request
|
|
599
|
+
if (typeof corsConfig === 'function') {
|
|
600
|
+
return async (req, res, next) => {
|
|
601
|
+
try {
|
|
602
|
+
const result = await corsConfig(req);
|
|
603
|
+
if (!result) {
|
|
604
|
+
// CORS not allowed
|
|
605
|
+
if (req.method === 'OPTIONS') {
|
|
606
|
+
res.status(403).end();
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
return next();
|
|
610
|
+
}
|
|
611
|
+
const config = typeof result === 'object' ? result : { origin: '*' };
|
|
612
|
+
const requestOrigin = req.headers.origin;
|
|
613
|
+
let origin = undefined;
|
|
614
|
+
if (typeof config.origin === 'string') {
|
|
615
|
+
if (config.origin === '*' && config.credentials) {
|
|
616
|
+
// Invalid: do not set header
|
|
617
|
+
origin = undefined;
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
origin = config.origin;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
else if (Array.isArray(config.origin)) {
|
|
624
|
+
if (requestOrigin && config.origin.includes(requestOrigin)) {
|
|
625
|
+
origin = requestOrigin;
|
|
626
|
+
}
|
|
627
|
+
else if (!config.credentials) {
|
|
628
|
+
origin = config.origin[0] ?? '*';
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
else if (typeof config.origin === 'function') {
|
|
632
|
+
if (requestOrigin && config.origin(requestOrigin)) {
|
|
633
|
+
origin = requestOrigin;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (origin) {
|
|
637
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
638
|
+
res.setHeader('Vary', 'Origin');
|
|
639
|
+
}
|
|
640
|
+
if (config.credentials) {
|
|
641
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
642
|
+
}
|
|
643
|
+
if (config.methods) {
|
|
644
|
+
res.setHeader('Access-Control-Allow-Methods', config.methods.join(', '));
|
|
645
|
+
}
|
|
646
|
+
else if (req.method === 'OPTIONS') {
|
|
647
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH');
|
|
648
|
+
}
|
|
649
|
+
if (config.headers) {
|
|
650
|
+
res.setHeader('Access-Control-Allow-Headers', config.headers.join(', '));
|
|
651
|
+
}
|
|
652
|
+
else if (req.method === 'OPTIONS' && req.headers['access-control-request-headers']) {
|
|
653
|
+
res.setHeader('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
|
|
654
|
+
}
|
|
655
|
+
if (config.exposedHeaders) {
|
|
656
|
+
res.setHeader('Access-Control-Expose-Headers', config.exposedHeaders.join(', '));
|
|
657
|
+
}
|
|
658
|
+
if (config.maxAge) {
|
|
659
|
+
res.setHeader('Access-Control-Max-Age', String(config.maxAge));
|
|
660
|
+
}
|
|
661
|
+
if (req.method === 'OPTIONS') {
|
|
662
|
+
res.status(204).end();
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
next();
|
|
666
|
+
}
|
|
667
|
+
catch (err) {
|
|
668
|
+
// On error, disallow CORS
|
|
669
|
+
if (req.method === 'OPTIONS') {
|
|
670
|
+
res.status(500).end();
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
next();
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
else {
|
|
678
|
+
// Static config (original logic)
|
|
679
|
+
const config = corsConfig === true
|
|
562
680
|
? { origin: '*', credentials: false }
|
|
563
|
-
: corsConfig
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
681
|
+
: corsConfig === false
|
|
682
|
+
? { origin: '*', credentials: false }
|
|
683
|
+
: corsConfig;
|
|
684
|
+
return (req, res, next) => {
|
|
685
|
+
const requestOrigin = req.headers.origin;
|
|
686
|
+
let origin = undefined;
|
|
687
|
+
if (typeof config.origin === 'string') {
|
|
688
|
+
if (config.origin === '*' && config.credentials) {
|
|
689
|
+
// Invalid: do not set header
|
|
690
|
+
origin = undefined;
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
origin = config.origin;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
else if (Array.isArray(config.origin)) {
|
|
697
|
+
if (requestOrigin && config.origin.includes(requestOrigin)) {
|
|
698
|
+
origin = requestOrigin;
|
|
699
|
+
}
|
|
700
|
+
else if (!config.credentials) {
|
|
701
|
+
origin = config.origin[0] ?? '*';
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
if (origin) {
|
|
705
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
706
|
+
res.setHeader('Vary', 'Origin');
|
|
707
|
+
}
|
|
708
|
+
if (config.credentials) {
|
|
709
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
710
|
+
}
|
|
711
|
+
if (config.methods) {
|
|
712
|
+
res.setHeader('Access-Control-Allow-Methods', config.methods.join(', '));
|
|
713
|
+
}
|
|
714
|
+
else if (req.method === 'OPTIONS') {
|
|
715
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH');
|
|
716
|
+
}
|
|
717
|
+
if (config.headers) {
|
|
718
|
+
res.setHeader('Access-Control-Allow-Headers', config.headers.join(', '));
|
|
719
|
+
}
|
|
720
|
+
else if (req.method === 'OPTIONS' && req.headers['access-control-request-headers']) {
|
|
721
|
+
res.setHeader('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
|
|
722
|
+
}
|
|
723
|
+
if (config.exposedHeaders) {
|
|
724
|
+
res.setHeader('Access-Control-Expose-Headers', config.exposedHeaders.join(', '));
|
|
725
|
+
}
|
|
726
|
+
if (config.maxAge) {
|
|
727
|
+
res.setHeader('Access-Control-Max-Age', String(config.maxAge));
|
|
728
|
+
}
|
|
729
|
+
if (req.method === 'OPTIONS') {
|
|
730
|
+
res.status(204).end();
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
next();
|
|
734
|
+
};
|
|
735
|
+
}
|
|
592
736
|
}
|
|
593
737
|
/**
|
|
594
738
|
* Extract path parameters from a path string
|
|
@@ -942,7 +1086,7 @@ export class PLATServer {
|
|
|
942
1086
|
return this.executeOperation({
|
|
943
1087
|
methodName: operation.methodName,
|
|
944
1088
|
controllerTag: operation.controllerTag,
|
|
945
|
-
fullPath:
|
|
1089
|
+
fullPath: envelope.path,
|
|
946
1090
|
transportMethod: envelope.method,
|
|
947
1091
|
routeMeta: operation.routeMeta,
|
|
948
1092
|
controllerMeta: operation.controllerMeta,
|
|
@@ -1057,7 +1201,7 @@ export class PLATServer {
|
|
|
1057
1201
|
openapi: '3.1.0',
|
|
1058
1202
|
info: {
|
|
1059
1203
|
title: 'plat API',
|
|
1060
|
-
version: '0.
|
|
1204
|
+
version: '0.16.0',
|
|
1061
1205
|
},
|
|
1062
1206
|
paths,
|
|
1063
1207
|
};
|
|
@@ -1118,6 +1262,13 @@ export class PLATServer {
|
|
|
1118
1262
|
config: this.options.fileQueue || undefined,
|
|
1119
1263
|
}),
|
|
1120
1264
|
];
|
|
1265
|
+
if (this.options.webrtc) {
|
|
1266
|
+
builtInPlugins.push(createWebRTCProtocolPlugin(this.options.webrtc, {
|
|
1267
|
+
getOpenAPISpec: () => this.options.openapi,
|
|
1268
|
+
getToolsList: () => Array.from(this.tools.values()),
|
|
1269
|
+
getServerStartedAt: () => this.serverCreatedAt,
|
|
1270
|
+
}));
|
|
1271
|
+
}
|
|
1121
1272
|
const transportRuntime = this.createTransportRuntime();
|
|
1122
1273
|
const allPlugins = [...builtInPlugins, ...(this.options.protocolPlugins ?? [])];
|
|
1123
1274
|
for (const plugin of allPlugins) {
|
|
@@ -1127,10 +1278,13 @@ export class PLATServer {
|
|
|
1127
1278
|
void plugin.attach?.(transportRuntime, hostContext);
|
|
1128
1279
|
void plugin.start?.(transportRuntime);
|
|
1129
1280
|
}
|
|
1281
|
+
this.teardownRuntimeCallbacks = allPlugins
|
|
1282
|
+
.filter((p) => typeof p.teardown === 'function')
|
|
1283
|
+
.map((p) => () => p.teardown(transportRuntime));
|
|
1130
1284
|
// Register root static folder as lowest-priority fallback
|
|
1131
1285
|
if (this.pendingRootFolder) {
|
|
1132
1286
|
const rootFolder = this.pendingRootFolder;
|
|
1133
|
-
this.app.get(
|
|
1287
|
+
this.app.get(/.*/, async (req, res, next) => {
|
|
1134
1288
|
const subPath = req.path.replace(/^\//, '');
|
|
1135
1289
|
try {
|
|
1136
1290
|
const fileResponse = await rootFolder.folder.resolve(subPath);
|
|
@@ -1150,6 +1304,15 @@ export class PLATServer {
|
|
|
1150
1304
|
return this;
|
|
1151
1305
|
}
|
|
1152
1306
|
async close() {
|
|
1307
|
+
for (const cb of this.teardownRuntimeCallbacks) {
|
|
1308
|
+
try {
|
|
1309
|
+
await cb();
|
|
1310
|
+
}
|
|
1311
|
+
catch (err) {
|
|
1312
|
+
this.logger.error('[plugin teardown] error during close', err);
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
this.teardownRuntimeCallbacks = [];
|
|
1153
1316
|
if (!this.httpServer)
|
|
1154
1317
|
return;
|
|
1155
1318
|
await new Promise((resolve, reject) => {
|
|
@@ -1162,6 +1325,17 @@ export class PLATServer {
|
|
|
1162
1325
|
});
|
|
1163
1326
|
this.httpServer = undefined;
|
|
1164
1327
|
}
|
|
1328
|
+
registerExpressRoute(method, path, handler) {
|
|
1329
|
+
this.app[method.toLowerCase()](path, handler);
|
|
1330
|
+
}
|
|
1331
|
+
registerWildcardExpressRoute(method, basePath, handler) {
|
|
1332
|
+
const matcher = createWildcardRouteMatcher(basePath);
|
|
1333
|
+
if (method === '*') {
|
|
1334
|
+
this.app.all(matcher, handler);
|
|
1335
|
+
return;
|
|
1336
|
+
}
|
|
1337
|
+
this.registerExpressRoute(method, matcher, handler);
|
|
1338
|
+
}
|
|
1165
1339
|
registerStaticFolderRoutes() {
|
|
1166
1340
|
for (const sf of this.staticFolders) {
|
|
1167
1341
|
if (sf.name === 'root') {
|
|
@@ -1186,7 +1360,7 @@ export class PLATServer {
|
|
|
1186
1360
|
}
|
|
1187
1361
|
};
|
|
1188
1362
|
this.app.get(prefix, handler);
|
|
1189
|
-
this.app.get(
|
|
1363
|
+
this.app.get(new RegExp(`^${prefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/.*`), handler);
|
|
1190
1364
|
}
|
|
1191
1365
|
}
|
|
1192
1366
|
sendFileResponse(res, fileResponse) {
|
|
@@ -1197,9 +1371,11 @@ export class PLATServer {
|
|
|
1197
1371
|
if (fileResponse.maxAge !== undefined) {
|
|
1198
1372
|
res.setHeader('Cache-Control', `public, max-age=${fileResponse.maxAge}`);
|
|
1199
1373
|
}
|
|
1374
|
+
if (fileResponse.status && fileResponse.status !== 200) {
|
|
1375
|
+
res.status(fileResponse.status);
|
|
1376
|
+
}
|
|
1200
1377
|
if (fileResponse.kind === 'path') {
|
|
1201
|
-
|
|
1202
|
-
res.sendFile(path.resolve(fileResponse.source));
|
|
1378
|
+
res.sendFile(nodePath.resolve(fileResponse.source));
|
|
1203
1379
|
}
|
|
1204
1380
|
else {
|
|
1205
1381
|
const content = fileResponse.source;
|