exisjs 0.1.3 → 0.1.5
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/README.md +5 -2
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +1 -0
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +11 -15
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/generate.d.ts +3 -1
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +39 -44
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +1 -6
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/test.d.ts +1 -0
- package/dist/cli/commands/test.d.ts.map +1 -1
- package/dist/cli/commands/test.js +8 -13
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/index.js +7 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/decorators/index.d.ts +101 -0
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +153 -21
- package/dist/decorators/index.js.map +1 -1
- package/dist/di/inject.d.ts +17 -0
- package/dist/di/inject.d.ts.map +1 -1
- package/dist/di/inject.js +17 -0
- package/dist/di/inject.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/mongoose.d.ts.map +1 -1
- package/dist/integrations/mongoose.js +3 -2
- package/dist/integrations/mongoose.js.map +1 -1
- package/dist/lib/start-server.js +30 -2
- package/dist/lib/start-server.js.map +1 -1
- package/dist/middleware/middleware.d.ts +1 -1
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/middleware.js +4 -0
- package/dist/middleware/middleware.js.map +1 -1
- package/dist/module/module.d.ts +16 -0
- package/dist/module/module.d.ts.map +1 -1
- package/dist/module/module.js +16 -0
- package/dist/module/module.js.map +1 -1
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +44 -22
- package/dist/router/router.js.map +1 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +217 -100
- package/dist/server/app.js.map +1 -1
- package/dist/server/cluster.d.ts.map +1 -1
- package/dist/server/cluster.js +4 -9
- package/dist/server/cluster.js.map +1 -1
- package/dist/server/define.d.ts +14 -0
- package/dist/server/define.d.ts.map +1 -1
- package/dist/server/define.js +14 -0
- package/dist/server/define.js.map +1 -1
- package/dist/server/dep-graph.d.ts.map +1 -1
- package/dist/server/dep-graph.js +13 -11
- package/dist/server/dep-graph.js.map +1 -1
- package/dist/server/request.d.ts +137 -1
- package/dist/server/request.d.ts.map +1 -1
- package/dist/server/request.js +136 -0
- package/dist/server/request.js.map +1 -1
- package/dist/server/response.d.ts +186 -0
- package/dist/server/response.d.ts.map +1 -1
- package/dist/server/response.js +188 -1
- package/dist/server/response.js.map +1 -1
- package/dist/server/route.d.ts +28 -2
- package/dist/server/route.d.ts.map +1 -1
- package/dist/server/route.js +28 -2
- package/dist/server/route.js.map +1 -1
- package/dist/server/uws-adapter.d.ts +4 -1
- package/dist/server/uws-adapter.d.ts.map +1 -1
- package/dist/server/uws-adapter.js +55 -6
- package/dist/server/uws-adapter.js.map +1 -1
- package/dist/swagger/index.d.ts.map +1 -1
- package/dist/swagger/index.js +2 -1
- package/dist/swagger/index.js.map +1 -1
- package/dist/testing/expect.d.ts +54 -0
- package/dist/testing/expect.d.ts.map +1 -0
- package/dist/testing/expect.js +419 -0
- package/dist/testing/expect.js.map +1 -0
- package/dist/testing/index.d.ts +55 -4
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +175 -22
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/reporter.d.mts +38 -0
- package/dist/testing/reporter.d.mts.map +1 -0
- package/dist/testing/reporter.mjs +225 -0
- package/dist/testing/reporter.mjs.map +1 -0
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/websocket/server.d.ts.map +1 -1
- package/dist/websocket/server.js +5 -3
- package/dist/websocket/server.js.map +1 -1
- package/dist/websocket/socket.d.ts.map +1 -1
- package/dist/websocket/socket.js +8 -6
- package/dist/websocket/socket.js.map +1 -1
- package/package.json +2 -3
- package/dist/testing/reporter.d.ts +0 -13
- package/dist/testing/reporter.d.ts.map +0 -1
- package/dist/testing/reporter.js +0 -101
- package/dist/testing/reporter.js.map +0 -1
package/dist/server/app.js
CHANGED
|
@@ -681,10 +681,39 @@ class App {
|
|
|
681
681
|
];
|
|
682
682
|
const routeMeta = routeMetadataMap[route.handlerName] || {};
|
|
683
683
|
const finalHost = routeMeta.hosts || host;
|
|
684
|
-
|
|
685
|
-
|
|
684
|
+
let schema = route.schema;
|
|
685
|
+
const paramMetadata = paramMetadataMap[route.handlerName] || [];
|
|
686
|
+
let extractedBodySchema = undefined;
|
|
687
|
+
let extractedQuerySchema = undefined;
|
|
688
|
+
for (const param of paramMetadata) {
|
|
689
|
+
if (!param)
|
|
690
|
+
continue;
|
|
691
|
+
if (param.type === 'body') {
|
|
692
|
+
const bodyPipe = param.pipes?.find((p) => p && typeof p.parse === 'function');
|
|
693
|
+
if (bodyPipe)
|
|
694
|
+
extractedBodySchema = bodyPipe;
|
|
695
|
+
}
|
|
696
|
+
if (param.type === 'query') {
|
|
697
|
+
const queryPipe = param.pipes?.find((p) => p && typeof p.parse === 'function');
|
|
698
|
+
if (queryPipe)
|
|
699
|
+
extractedQuerySchema = queryPipe;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
const extractedResponseSchema = routeMeta.responseSchema;
|
|
703
|
+
if (schema ||
|
|
704
|
+
finalHost ||
|
|
705
|
+
extractedBodySchema ||
|
|
706
|
+
extractedQuerySchema ||
|
|
707
|
+
extractedResponseSchema) {
|
|
708
|
+
schema = schema || {};
|
|
686
709
|
if (finalHost)
|
|
687
710
|
schema.host = finalHost;
|
|
711
|
+
if (extractedBodySchema && !schema.body)
|
|
712
|
+
schema.body = extractedBodySchema;
|
|
713
|
+
if (extractedQuerySchema && !schema.query)
|
|
714
|
+
schema.query = extractedQuerySchema;
|
|
715
|
+
if (extractedResponseSchema && !schema.response)
|
|
716
|
+
schema.response = extractedResponseSchema;
|
|
688
717
|
this.router[method](fullPath, ...allMiddlewares, schema, finalHandler);
|
|
689
718
|
}
|
|
690
719
|
else {
|
|
@@ -752,10 +781,8 @@ class App {
|
|
|
752
781
|
return this._compiledPipeline;
|
|
753
782
|
}
|
|
754
783
|
// ─── Web Standard Fetch (Edge Runtime) & Inject ──────────────────────────────
|
|
755
|
-
fetch(request, env, ctx) {
|
|
756
|
-
|
|
757
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
758
|
-
const { handleFetch } = require('../adapters/fetch');
|
|
784
|
+
async fetch(request, env, ctx) {
|
|
785
|
+
const { handleFetch } = await Promise.resolve().then(() => __importStar(require('../adapters/fetch')));
|
|
759
786
|
return handleFetch(this, request, env, ctx);
|
|
760
787
|
}
|
|
761
788
|
async inject(options) {
|
|
@@ -1033,42 +1060,42 @@ class App {
|
|
|
1033
1060
|
});
|
|
1034
1061
|
},
|
|
1035
1062
|
];
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1063
|
+
this._executeWithContext(req, res, () => {
|
|
1064
|
+
(0, router_1.runHandlers)(pipeline, req, res, async (err) => {
|
|
1065
|
+
if (isAborted)
|
|
1066
|
+
return;
|
|
1067
|
+
if (err) {
|
|
1068
|
+
this.log.error({ err }, 'Error during uWS WebSocket upgrade middleware');
|
|
1069
|
+
uwsRes.cork(() => {
|
|
1070
|
+
uwsRes.writeStatus('500 Internal Server Error');
|
|
1071
|
+
uwsRes.end();
|
|
1072
|
+
});
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
1075
|
+
if (res.headersSent) {
|
|
1076
|
+
return; // Middleware sent an HTTP response
|
|
1077
|
+
}
|
|
1078
|
+
// We need to fetch headers directly from the shimReq.headers
|
|
1079
|
+
const secWebSocketKey = shimReq.headers['sec-websocket-key'] || '';
|
|
1080
|
+
const secWebSocketProtocol = shimReq.headers['sec-websocket-protocol'] || '';
|
|
1081
|
+
const secWebSocketExtensions = shimReq.headers['sec-websocket-extensions'] || '';
|
|
1082
|
+
// Prepare user data for the upgraded websocket
|
|
1083
|
+
const userData = {
|
|
1084
|
+
req,
|
|
1085
|
+
res,
|
|
1086
|
+
exisWs: new socket_1.ExisWebSocket(null, req, this.wsServer), // the raw will be set to shim in open()
|
|
1087
|
+
finalHandler: matched.route.handlers[matched.route.handlers.length - 1],
|
|
1088
|
+
};
|
|
1089
|
+
this.wsServer.track(userData.exisWs);
|
|
1090
|
+
req.ws = userData.exisWs;
|
|
1041
1091
|
uwsRes.cork(() => {
|
|
1042
|
-
uwsRes.
|
|
1043
|
-
|
|
1092
|
+
uwsRes.upgrade(userData, secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, context);
|
|
1093
|
+
});
|
|
1094
|
+
Promise.resolve(userData.finalHandler(req, res, () => {
|
|
1095
|
+
/* noop */
|
|
1096
|
+
})).catch((e) => {
|
|
1097
|
+
this.log.error({ err: e }, 'Error in uWS WebSocket handler');
|
|
1044
1098
|
});
|
|
1045
|
-
return;
|
|
1046
|
-
}
|
|
1047
|
-
if (res.headersSent) {
|
|
1048
|
-
return; // Middleware sent an HTTP response
|
|
1049
|
-
}
|
|
1050
|
-
// We need to fetch headers directly from the shimReq.headers
|
|
1051
|
-
const secWebSocketKey = shimReq.headers['sec-websocket-key'] || '';
|
|
1052
|
-
const secWebSocketProtocol = shimReq.headers['sec-websocket-protocol'] || '';
|
|
1053
|
-
const secWebSocketExtensions = shimReq.headers['sec-websocket-extensions'] || '';
|
|
1054
|
-
// Prepare user data for the upgraded websocket
|
|
1055
|
-
const userData = {
|
|
1056
|
-
req,
|
|
1057
|
-
res,
|
|
1058
|
-
exisWs: new socket_1.ExisWebSocket(null, req, this.wsServer), // the raw will be set to shim in open()
|
|
1059
|
-
finalHandler: matched.route.handlers[matched.route.handlers.length - 1],
|
|
1060
|
-
};
|
|
1061
|
-
this.wsServer.track(userData.exisWs);
|
|
1062
|
-
req.ws = userData.exisWs;
|
|
1063
|
-
uwsRes.cork(() => {
|
|
1064
|
-
uwsRes.upgrade(userData, secWebSocketKey, secWebSocketProtocol, secWebSocketExtensions, context);
|
|
1065
|
-
});
|
|
1066
|
-
// The open handler in createUwsApp will call finalHandler?
|
|
1067
|
-
// Actually we should just execute the finalHandler here since upgrade succeeds immediately if we don't block
|
|
1068
|
-
Promise.resolve(userData.finalHandler(req, res, () => {
|
|
1069
|
-
/* noop */
|
|
1070
|
-
})).catch((e) => {
|
|
1071
|
-
this.log.error({ err: e }, 'Error in uWS WebSocket handler');
|
|
1072
1099
|
});
|
|
1073
1100
|
});
|
|
1074
1101
|
}
|
|
@@ -1121,8 +1148,10 @@ class App {
|
|
|
1121
1148
|
onListen(address);
|
|
1122
1149
|
}
|
|
1123
1150
|
else {
|
|
1124
|
-
|
|
1125
|
-
|
|
1151
|
+
if (!process.env.__EXIS_DEV_SERVER && !process.env.__EXIS_CLI) {
|
|
1152
|
+
const url = `http://${host === '0.0.0.0' ? 'localhost' : host}:${port}`;
|
|
1153
|
+
this.log.info({ url, env: this.options.env, backend: 'uws' }, `Server running at ${url} (uWebSockets.js)`);
|
|
1154
|
+
}
|
|
1126
1155
|
}
|
|
1127
1156
|
if (this.options.env === 'production') {
|
|
1128
1157
|
const handleShutdown = async () => {
|
|
@@ -1274,10 +1303,19 @@ class App {
|
|
|
1274
1303
|
: 'use --host 0.0.0.0 to expose';
|
|
1275
1304
|
const readyMs = 125;
|
|
1276
1305
|
const displayEnv = this.options.env || process.env.NODE_ENV || 'development';
|
|
1306
|
+
const workerCount = process.env.__EXIS_CLUSTER_WORKERS;
|
|
1307
|
+
const cluster = await Promise.resolve().then(() => __importStar(require('node:cluster')));
|
|
1308
|
+
// In cluster mode, ONLY let Worker #1 print the banner so we don't spam the console 12 times
|
|
1309
|
+
if (cluster.default.isWorker && cluster.default.worker?.id !== 1) {
|
|
1310
|
+
return;
|
|
1311
|
+
}
|
|
1277
1312
|
console.log(`\n ${c.primary}${c.bold}EXIS v${fwVersion}${c.reset} ready in ${c.bold}${readyMs} ms${c.reset}\n`);
|
|
1278
1313
|
console.log(` ${c.white}➜${c.reset} ${c.bold}Local:${c.reset} ${c.blue}http://${displayHost}:${port}/${c.reset}`);
|
|
1279
1314
|
console.log(` ${c.white}➜${c.reset} ${c.dim}Network:${c.reset} ${c.blue}${networkHost}/${c.reset}`);
|
|
1280
1315
|
console.log(` ${c.white}➜${c.reset} ${c.dim}Environ:${c.reset} ${c.green}${displayEnv}${c.reset}`);
|
|
1316
|
+
if (workerCount && Number(workerCount) > 1) {
|
|
1317
|
+
console.log(` ${c.white}➜${c.reset} ${c.dim}Workers:${c.reset} ${c.magenta}${workerCount}${c.reset}`);
|
|
1318
|
+
}
|
|
1281
1319
|
console.log(` ${c.white}➜${c.reset} press ${c.bold}h + enter${c.reset} ${c.dim}to show help${c.reset}\n`);
|
|
1282
1320
|
}
|
|
1283
1321
|
// ─── Graceful Shutdown ────────────────────────────────────────────────────────
|
|
@@ -1477,8 +1515,14 @@ class App {
|
|
|
1477
1515
|
let url = (0, node_url_1.pathToFileURL)(manifestPath).href;
|
|
1478
1516
|
if (!isProd)
|
|
1479
1517
|
url += '?t=' + Date.now(); // cache bust for dev
|
|
1480
|
-
|
|
1481
|
-
|
|
1518
|
+
let mod;
|
|
1519
|
+
if (process.env.VITEST || process.env.NODE_ENV === 'test') {
|
|
1520
|
+
mod = await Promise.resolve(`${url}`).then(s => __importStar(require(s)));
|
|
1521
|
+
}
|
|
1522
|
+
else {
|
|
1523
|
+
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
1524
|
+
mod = await dynamicImport(url);
|
|
1525
|
+
}
|
|
1482
1526
|
const manifest = mod.manifest;
|
|
1483
1527
|
if (Array.isArray(manifest)) {
|
|
1484
1528
|
for (const entry of manifest) {
|
|
@@ -1486,11 +1530,21 @@ class App {
|
|
|
1486
1530
|
const normalizedPath = path.resolve(root, filePath);
|
|
1487
1531
|
this.routeMap.set(normalizedPath, routePath);
|
|
1488
1532
|
const CONTROLLER_PREFIX = Symbol.for('exisjs:controller_prefix');
|
|
1489
|
-
const
|
|
1533
|
+
const isClassController = (obj) => obj &&
|
|
1490
1534
|
obj.prototype &&
|
|
1491
1535
|
obj.prototype[CONTROLLER_PREFIX] !== undefined;
|
|
1536
|
+
const unwrappedMod = routeMod.default && routeMod.default.default
|
|
1537
|
+
? routeMod.default.default
|
|
1538
|
+
: routeMod.default
|
|
1539
|
+
? routeMod.default
|
|
1540
|
+
: routeMod;
|
|
1541
|
+
const functionalControllerObj = unwrappedMod && unwrappedMod.__isController ? unwrappedMod : null;
|
|
1492
1542
|
const routerInstance = routeMod.router || routeMod.default || routeMod;
|
|
1493
|
-
if (
|
|
1543
|
+
if (functionalControllerObj) {
|
|
1544
|
+
const router = this.compileFunctionalController(functionalControllerObj);
|
|
1545
|
+
this.mountRouteWithSource(routePath, router, normalizedPath);
|
|
1546
|
+
}
|
|
1547
|
+
else if (isClassController(routerInstance)) {
|
|
1494
1548
|
this.registerControllers([routerInstance], routePath);
|
|
1495
1549
|
}
|
|
1496
1550
|
else {
|
|
@@ -1502,7 +1556,10 @@ class App {
|
|
|
1502
1556
|
}
|
|
1503
1557
|
}
|
|
1504
1558
|
}
|
|
1505
|
-
catch {
|
|
1559
|
+
catch (err) {
|
|
1560
|
+
if (err.code !== 'ENOENT') {
|
|
1561
|
+
console.warn('exisjs: Failed to load routes manifest:', err.message);
|
|
1562
|
+
}
|
|
1506
1563
|
// Fall back to scanning the filesystem
|
|
1507
1564
|
}
|
|
1508
1565
|
const searchDirs = isProd
|
|
@@ -1647,10 +1704,17 @@ class App {
|
|
|
1647
1704
|
}
|
|
1648
1705
|
async mountRouteFile(filePath, routePath) {
|
|
1649
1706
|
let mod;
|
|
1650
|
-
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
1651
1707
|
try {
|
|
1652
|
-
const url =
|
|
1653
|
-
|
|
1708
|
+
const url = process.env.VITEST || process.env.NODE_ENV === 'test'
|
|
1709
|
+
? (0, node_url_1.pathToFileURL)(filePath).href
|
|
1710
|
+
: (0, node_url_1.pathToFileURL)(filePath).href + '?t=' + Date.now();
|
|
1711
|
+
if (process.env.VITEST || process.env.NODE_ENV === 'test') {
|
|
1712
|
+
mod = await Promise.resolve(`${url}`).then(s => __importStar(require(s)));
|
|
1713
|
+
}
|
|
1714
|
+
else {
|
|
1715
|
+
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
1716
|
+
mod = await dynamicImport(url);
|
|
1717
|
+
}
|
|
1654
1718
|
}
|
|
1655
1719
|
catch {
|
|
1656
1720
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
@@ -1688,10 +1752,28 @@ class App {
|
|
|
1688
1752
|
else if (await fs.stat(gwPathJs).catch(() => null))
|
|
1689
1753
|
targetGw = gwPathJs;
|
|
1690
1754
|
if (targetGw) {
|
|
1691
|
-
const
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1755
|
+
const gwUrl = process.env.VITEST || process.env.NODE_ENV === 'test'
|
|
1756
|
+
? (0, node_url_1.pathToFileURL)(targetGw).href
|
|
1757
|
+
: (0, node_url_1.pathToFileURL)(targetGw).href + '?t=' + Date.now();
|
|
1758
|
+
let gwMod;
|
|
1759
|
+
try {
|
|
1760
|
+
if (process.env.VITEST || process.env.NODE_ENV === 'test') {
|
|
1761
|
+
gwMod = await Promise.resolve(`${gwUrl}`).then(s => __importStar(require(s)));
|
|
1762
|
+
}
|
|
1763
|
+
else {
|
|
1764
|
+
const dynamicImportGw = new Function('specifier', 'return import(specifier)');
|
|
1765
|
+
gwMod = await dynamicImportGw(gwUrl);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
catch {
|
|
1769
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1770
|
+
gwMod = require(targetGw);
|
|
1771
|
+
}
|
|
1772
|
+
const gwConfig = gwMod && gwMod.default && gwMod.default.default
|
|
1773
|
+
? gwMod.default.default
|
|
1774
|
+
: gwMod && gwMod.default
|
|
1775
|
+
? gwMod.default
|
|
1776
|
+
: gwMod;
|
|
1695
1777
|
if (gwConfig) {
|
|
1696
1778
|
const isExcluded = (reqPath, reqMethod) => {
|
|
1697
1779
|
if (!gwConfig.exclude)
|
|
@@ -1769,9 +1851,7 @@ class App {
|
|
|
1769
1851
|
if (ms) {
|
|
1770
1852
|
req.timeoutTimer = setTimeout(() => {
|
|
1771
1853
|
if (!res.headersSent) {
|
|
1772
|
-
res
|
|
1773
|
-
.status(408)
|
|
1774
|
-
.json({
|
|
1854
|
+
res.status(408).json({
|
|
1775
1855
|
success: false,
|
|
1776
1856
|
error: {
|
|
1777
1857
|
code: 'REQUEST_TIMEOUT',
|
|
@@ -1818,45 +1898,80 @@ class App {
|
|
|
1818
1898
|
/* ignore */
|
|
1819
1899
|
}
|
|
1820
1900
|
}
|
|
1821
|
-
|
|
1822
|
-
mod.
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1901
|
+
const currentMod = mod && mod.default && mod.default.default
|
|
1902
|
+
? mod.default.default
|
|
1903
|
+
: mod && mod.default
|
|
1904
|
+
? mod.default
|
|
1905
|
+
: mod;
|
|
1906
|
+
const isControllerObj = currentMod && currentMod.__isController === true;
|
|
1907
|
+
const routeConfig = {
|
|
1908
|
+
...(isControllerObj ? currentMod : {}),
|
|
1909
|
+
...(mod.config || {}),
|
|
1910
|
+
};
|
|
1911
|
+
// Fallback to global app.options.cors if neither gateway nor route specify it
|
|
1912
|
+
if (routeConfig.cors !== undefined)
|
|
1913
|
+
allCors = routeConfig.cors;
|
|
1914
|
+
else if (allCors === undefined && this.options.cors !== undefined)
|
|
1915
|
+
allCors = this.options.cors;
|
|
1916
|
+
if (routeConfig.middleware)
|
|
1917
|
+
allMiddlewares.push(...(Array.isArray(routeConfig.middleware)
|
|
1918
|
+
? routeConfig.middleware
|
|
1919
|
+
: [routeConfig.middleware]));
|
|
1920
|
+
if (routeConfig.headers)
|
|
1921
|
+
allHeaders = { ...allHeaders, ...routeConfig.headers };
|
|
1922
|
+
if (routeConfig.plugins) {
|
|
1923
|
+
for (const plugin of routeConfig.plugins) {
|
|
1831
1924
|
await this.register(plugin);
|
|
1832
1925
|
}
|
|
1833
1926
|
}
|
|
1834
|
-
//
|
|
1835
|
-
|
|
1927
|
+
// Pass gateway features to controllers via metadata if necessary
|
|
1928
|
+
const combinedFilters = [
|
|
1836
1929
|
...allFilters,
|
|
1837
|
-
...(
|
|
1838
|
-
? Array.isArray(
|
|
1839
|
-
?
|
|
1840
|
-
: [
|
|
1930
|
+
...(routeConfig.filters
|
|
1931
|
+
? Array.isArray(routeConfig.filters)
|
|
1932
|
+
? routeConfig.filters
|
|
1933
|
+
: [routeConfig.filters]
|
|
1841
1934
|
: []),
|
|
1842
1935
|
];
|
|
1843
|
-
|
|
1936
|
+
const combinedGuards = [
|
|
1844
1937
|
...allGuards,
|
|
1845
|
-
...(
|
|
1846
|
-
? Array.isArray(
|
|
1847
|
-
?
|
|
1848
|
-
: [
|
|
1938
|
+
...(routeConfig.guards
|
|
1939
|
+
? Array.isArray(routeConfig.guards)
|
|
1940
|
+
? routeConfig.guards
|
|
1941
|
+
: [routeConfig.guards]
|
|
1849
1942
|
: []),
|
|
1850
1943
|
];
|
|
1851
|
-
|
|
1944
|
+
const combinedInterceptors = [
|
|
1852
1945
|
...allInterceptors,
|
|
1853
|
-
...(
|
|
1854
|
-
? Array.isArray(
|
|
1855
|
-
?
|
|
1856
|
-
: [
|
|
1946
|
+
...(routeConfig.interceptors
|
|
1947
|
+
? Array.isArray(routeConfig.interceptors)
|
|
1948
|
+
? routeConfig.interceptors
|
|
1949
|
+
: [routeConfig.interceptors]
|
|
1857
1950
|
: []),
|
|
1858
1951
|
];
|
|
1859
|
-
|
|
1952
|
+
// Inject into the default export if it's a functional controller
|
|
1953
|
+
if (mod.default && typeof mod.default === 'object') {
|
|
1954
|
+
try {
|
|
1955
|
+
if (!mod.default.filters)
|
|
1956
|
+
mod.default.filters = [];
|
|
1957
|
+
mod.default.filters.push(...combinedFilters);
|
|
1958
|
+
if (!mod.default.guards)
|
|
1959
|
+
mod.default.guards = [];
|
|
1960
|
+
mod.default.guards.push(...combinedGuards);
|
|
1961
|
+
if (!mod.default.interceptors)
|
|
1962
|
+
mod.default.interceptors = [];
|
|
1963
|
+
mod.default.interceptors.push(...combinedInterceptors);
|
|
1964
|
+
if (!mod.default.metadata)
|
|
1965
|
+
mod.default.metadata = {};
|
|
1966
|
+
Object.assign(mod.default.metadata, {
|
|
1967
|
+
...allMetadata,
|
|
1968
|
+
...(routeConfig.metadata || {}),
|
|
1969
|
+
});
|
|
1970
|
+
}
|
|
1971
|
+
catch {
|
|
1972
|
+
// If mod.default is frozen, ignore
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1860
1975
|
const prefixMiddlewares = [];
|
|
1861
1976
|
if (allCors !== undefined) {
|
|
1862
1977
|
if (allCors === true)
|
|
@@ -1875,19 +1990,25 @@ class App {
|
|
|
1875
1990
|
const isRouter = (obj) => obj && 'handle' in obj && 'get' in obj;
|
|
1876
1991
|
const CONTROLLER_PREFIX = Symbol.for('exisjs:controller_prefix');
|
|
1877
1992
|
const isController = (obj) => obj && obj.prototype && obj.prototype[CONTROLLER_PREFIX] !== undefined;
|
|
1878
|
-
|
|
1993
|
+
const unwrappedMod = mod && mod.default && mod.default.default
|
|
1994
|
+
? mod.default.default
|
|
1995
|
+
: mod && mod.default
|
|
1996
|
+
? mod.default
|
|
1997
|
+
: mod;
|
|
1998
|
+
const functionalControllerObj = unwrappedMod && unwrappedMod.__isController ? unwrappedMod : null;
|
|
1999
|
+
if (functionalControllerObj) {
|
|
1879
2000
|
// ─── THE NEW PERFECT FUNCTIONAL CONTROLLER ───
|
|
1880
|
-
const compiledRouter = this.compileFunctionalController(
|
|
2001
|
+
const compiledRouter = this.compileFunctionalController(functionalControllerObj);
|
|
1881
2002
|
this.mountRouteWithSource(routePath, compiledRouter, filePath, prefixMiddlewares);
|
|
1882
2003
|
}
|
|
1883
2004
|
else if (mod.router && isRouter(mod.router)) {
|
|
1884
2005
|
this.mountRouteWithSource(routePath, mod.router, filePath, prefixMiddlewares);
|
|
1885
2006
|
}
|
|
1886
|
-
else if (
|
|
1887
|
-
this.registerControllers([
|
|
2007
|
+
else if (unwrappedMod && isController(unwrappedMod)) {
|
|
2008
|
+
this.registerControllers([unwrappedMod], routePath, prefixMiddlewares);
|
|
1888
2009
|
}
|
|
1889
|
-
else if (
|
|
1890
|
-
this.mountRouteWithSource(routePath,
|
|
2010
|
+
else if (unwrappedMod && isRouter(unwrappedMod)) {
|
|
2011
|
+
this.mountRouteWithSource(routePath, unwrappedMod, filePath, prefixMiddlewares);
|
|
1891
2012
|
}
|
|
1892
2013
|
else if (isRouter(mod)) {
|
|
1893
2014
|
this.mountRouteWithSource(routePath, mod, filePath, prefixMiddlewares);
|
|
@@ -1897,14 +2018,10 @@ class App {
|
|
|
1897
2018
|
}
|
|
1898
2019
|
}
|
|
1899
2020
|
compileFunctionalController(config) {
|
|
1900
|
-
|
|
1901
|
-
const { Router } = require('../router/router');
|
|
1902
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1903
|
-
const { cors } = require('../middleware/middleware');
|
|
1904
|
-
const router = new Router();
|
|
2021
|
+
const router = new router_1.Router();
|
|
1905
2022
|
const fileMiddleware = [];
|
|
1906
2023
|
if (config.cors) {
|
|
1907
|
-
fileMiddleware.push(config.cors === true ? cors({}) : cors(config.cors));
|
|
2024
|
+
fileMiddleware.push(config.cors === true ? (0, middleware_1.cors)({}) : (0, middleware_1.cors)(config.cors));
|
|
1908
2025
|
}
|
|
1909
2026
|
if (config.middleware) {
|
|
1910
2027
|
fileMiddleware.push(...(Array.isArray(config.middleware)
|
|
@@ -1926,7 +2043,7 @@ class App {
|
|
|
1926
2043
|
continue;
|
|
1927
2044
|
const routeMiddlewares = [...fileMiddleware];
|
|
1928
2045
|
if (rc.cors) {
|
|
1929
|
-
routeMiddlewares.push(rc.cors === true ? cors({}) : cors(rc.cors));
|
|
2046
|
+
routeMiddlewares.push(rc.cors === true ? (0, middleware_1.cors)({}) : (0, middleware_1.cors)(rc.cors));
|
|
1930
2047
|
}
|
|
1931
2048
|
if (rc.middleware) {
|
|
1932
2049
|
routeMiddlewares.push(...(Array.isArray(rc.middleware) ? rc.middleware : [rc.middleware]));
|
|
@@ -1947,9 +2064,7 @@ class App {
|
|
|
1947
2064
|
: guard.canActivate(req));
|
|
1948
2065
|
if (!allowed) {
|
|
1949
2066
|
if (res && !res.headersSent) {
|
|
1950
|
-
res
|
|
1951
|
-
.status(403)
|
|
1952
|
-
.json({
|
|
2067
|
+
res.status(403).json({
|
|
1953
2068
|
success: false,
|
|
1954
2069
|
error: { code: 'FORBIDDEN', message: 'Forbidden by Guard' },
|
|
1955
2070
|
});
|
|
@@ -2078,9 +2193,11 @@ class App {
|
|
|
2078
2193
|
}
|
|
2079
2194
|
else {
|
|
2080
2195
|
if (Object.keys(schema).length > 0) {
|
|
2196
|
+
;
|
|
2081
2197
|
router[method](rc.path, ...routeMiddlewares, schema, superHandler);
|
|
2082
2198
|
}
|
|
2083
2199
|
else {
|
|
2200
|
+
;
|
|
2084
2201
|
router[method](rc.path, ...routeMiddlewares, superHandler);
|
|
2085
2202
|
}
|
|
2086
2203
|
}
|