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.
Files changed (104) hide show
  1. package/README.md +5 -2
  2. package/dist/cli/commands/build.d.ts.map +1 -1
  3. package/dist/cli/commands/build.js +1 -0
  4. package/dist/cli/commands/build.js.map +1 -1
  5. package/dist/cli/commands/dev.d.ts.map +1 -1
  6. package/dist/cli/commands/dev.js +11 -15
  7. package/dist/cli/commands/dev.js.map +1 -1
  8. package/dist/cli/commands/generate.d.ts +3 -1
  9. package/dist/cli/commands/generate.d.ts.map +1 -1
  10. package/dist/cli/commands/generate.js +39 -44
  11. package/dist/cli/commands/generate.js.map +1 -1
  12. package/dist/cli/commands/start.d.ts.map +1 -1
  13. package/dist/cli/commands/start.js +1 -6
  14. package/dist/cli/commands/start.js.map +1 -1
  15. package/dist/cli/commands/test.d.ts +1 -0
  16. package/dist/cli/commands/test.d.ts.map +1 -1
  17. package/dist/cli/commands/test.js +8 -13
  18. package/dist/cli/commands/test.js.map +1 -1
  19. package/dist/cli/index.js +7 -5
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/decorators/index.d.ts +101 -0
  22. package/dist/decorators/index.d.ts.map +1 -1
  23. package/dist/decorators/index.js +153 -21
  24. package/dist/decorators/index.js.map +1 -1
  25. package/dist/di/inject.d.ts +17 -0
  26. package/dist/di/inject.d.ts.map +1 -1
  27. package/dist/di/inject.js +17 -0
  28. package/dist/di/inject.js.map +1 -1
  29. package/dist/index.d.ts +1 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/integrations/mongoose.d.ts.map +1 -1
  33. package/dist/integrations/mongoose.js +3 -2
  34. package/dist/integrations/mongoose.js.map +1 -1
  35. package/dist/lib/start-server.js +30 -2
  36. package/dist/lib/start-server.js.map +1 -1
  37. package/dist/middleware/middleware.d.ts +1 -1
  38. package/dist/middleware/middleware.d.ts.map +1 -1
  39. package/dist/middleware/middleware.js +4 -0
  40. package/dist/middleware/middleware.js.map +1 -1
  41. package/dist/module/module.d.ts +16 -0
  42. package/dist/module/module.d.ts.map +1 -1
  43. package/dist/module/module.js +16 -0
  44. package/dist/module/module.js.map +1 -1
  45. package/dist/router/router.d.ts.map +1 -1
  46. package/dist/router/router.js +44 -22
  47. package/dist/router/router.js.map +1 -1
  48. package/dist/server/app.d.ts.map +1 -1
  49. package/dist/server/app.js +217 -100
  50. package/dist/server/app.js.map +1 -1
  51. package/dist/server/cluster.d.ts.map +1 -1
  52. package/dist/server/cluster.js +4 -9
  53. package/dist/server/cluster.js.map +1 -1
  54. package/dist/server/define.d.ts +14 -0
  55. package/dist/server/define.d.ts.map +1 -1
  56. package/dist/server/define.js +14 -0
  57. package/dist/server/define.js.map +1 -1
  58. package/dist/server/dep-graph.d.ts.map +1 -1
  59. package/dist/server/dep-graph.js +13 -11
  60. package/dist/server/dep-graph.js.map +1 -1
  61. package/dist/server/request.d.ts +137 -1
  62. package/dist/server/request.d.ts.map +1 -1
  63. package/dist/server/request.js +136 -0
  64. package/dist/server/request.js.map +1 -1
  65. package/dist/server/response.d.ts +186 -0
  66. package/dist/server/response.d.ts.map +1 -1
  67. package/dist/server/response.js +188 -1
  68. package/dist/server/response.js.map +1 -1
  69. package/dist/server/route.d.ts +28 -2
  70. package/dist/server/route.d.ts.map +1 -1
  71. package/dist/server/route.js +28 -2
  72. package/dist/server/route.js.map +1 -1
  73. package/dist/server/uws-adapter.d.ts +4 -1
  74. package/dist/server/uws-adapter.d.ts.map +1 -1
  75. package/dist/server/uws-adapter.js +55 -6
  76. package/dist/server/uws-adapter.js.map +1 -1
  77. package/dist/swagger/index.d.ts.map +1 -1
  78. package/dist/swagger/index.js +2 -1
  79. package/dist/swagger/index.js.map +1 -1
  80. package/dist/testing/expect.d.ts +54 -0
  81. package/dist/testing/expect.d.ts.map +1 -0
  82. package/dist/testing/expect.js +419 -0
  83. package/dist/testing/expect.js.map +1 -0
  84. package/dist/testing/index.d.ts +55 -4
  85. package/dist/testing/index.d.ts.map +1 -1
  86. package/dist/testing/index.js +175 -22
  87. package/dist/testing/index.js.map +1 -1
  88. package/dist/testing/reporter.d.mts +38 -0
  89. package/dist/testing/reporter.d.mts.map +1 -0
  90. package/dist/testing/reporter.mjs +225 -0
  91. package/dist/testing/reporter.mjs.map +1 -0
  92. package/dist/types.d.ts +3 -1
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/websocket/server.d.ts.map +1 -1
  95. package/dist/websocket/server.js +5 -3
  96. package/dist/websocket/server.js.map +1 -1
  97. package/dist/websocket/socket.d.ts.map +1 -1
  98. package/dist/websocket/socket.js +8 -6
  99. package/dist/websocket/socket.js.map +1 -1
  100. package/package.json +2 -3
  101. package/dist/testing/reporter.d.ts +0 -13
  102. package/dist/testing/reporter.d.ts.map +0 -1
  103. package/dist/testing/reporter.js +0 -101
  104. package/dist/testing/reporter.js.map +0 -1
@@ -681,10 +681,39 @@ class App {
681
681
  ];
682
682
  const routeMeta = routeMetadataMap[route.handlerName] || {};
683
683
  const finalHost = routeMeta.hosts || host;
684
- if (route.schema || finalHost) {
685
- const schema = route.schema || {};
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
- // Dynamic require to avoid circular dependencies and top-level execution
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
- await (0, router_1.runHandlers)(pipeline, req, res, async (err) => {
1037
- if (isAborted)
1038
- return;
1039
- if (err) {
1040
- this.log.error({ err }, 'Error during uWS WebSocket upgrade middleware');
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.writeStatus('500 Internal Server Error');
1043
- uwsRes.end();
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
- const url = `http://${host === '0.0.0.0' ? 'localhost' : host}:${port}`;
1125
- this.log.info({ url, env: this.options.env, backend: 'uws' }, `Server running at ${url} (uWebSockets.js)`);
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
- const dynamicImport = new Function('specifier', 'return import(specifier)');
1481
- const mod = await dynamicImport(url);
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 isController = (obj) => obj &&
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 (isController(routerInstance)) {
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 = (0, node_url_1.pathToFileURL)(filePath).href + '?t=' + Date.now();
1653
- mod = await dynamicImport(url);
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 url = (0, node_url_1.pathToFileURL)(targetGw).href + '?t=' + Date.now();
1692
- // eslint-disable-next-line @typescript-eslint/no-require-imports
1693
- const gwMod = await dynamicImport(url).catch(() => require(targetGw));
1694
- const gwConfig = gwMod.default || gwMod;
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
- if (!mod.config)
1822
- mod.config = {};
1823
- if (mod.config.middleware)
1824
- allMiddlewares.push(...mod.config.middleware);
1825
- if (mod.config.cors !== undefined)
1826
- allCors = mod.config.cors;
1827
- if (mod.config.headers)
1828
- allHeaders = { ...allHeaders, ...mod.config.headers };
1829
- if (mod.config.plugins) {
1830
- for (const plugin of mod.config.plugins) {
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
- // Inject Gateway features into module config for compileFunctionalController and OOP
1835
- mod.config.filters = [
1927
+ // Pass gateway features to controllers via metadata if necessary
1928
+ const combinedFilters = [
1836
1929
  ...allFilters,
1837
- ...(mod.config.filters
1838
- ? Array.isArray(mod.config.filters)
1839
- ? mod.config.filters
1840
- : [mod.config.filters]
1930
+ ...(routeConfig.filters
1931
+ ? Array.isArray(routeConfig.filters)
1932
+ ? routeConfig.filters
1933
+ : [routeConfig.filters]
1841
1934
  : []),
1842
1935
  ];
1843
- mod.config.guards = [
1936
+ const combinedGuards = [
1844
1937
  ...allGuards,
1845
- ...(mod.config.guards
1846
- ? Array.isArray(mod.config.guards)
1847
- ? mod.config.guards
1848
- : [mod.config.guards]
1938
+ ...(routeConfig.guards
1939
+ ? Array.isArray(routeConfig.guards)
1940
+ ? routeConfig.guards
1941
+ : [routeConfig.guards]
1849
1942
  : []),
1850
1943
  ];
1851
- mod.config.interceptors = [
1944
+ const combinedInterceptors = [
1852
1945
  ...allInterceptors,
1853
- ...(mod.config.interceptors
1854
- ? Array.isArray(mod.config.interceptors)
1855
- ? mod.config.interceptors
1856
- : [mod.config.interceptors]
1946
+ ...(routeConfig.interceptors
1947
+ ? Array.isArray(routeConfig.interceptors)
1948
+ ? routeConfig.interceptors
1949
+ : [routeConfig.interceptors]
1857
1950
  : []),
1858
1951
  ];
1859
- mod.config.metadata = { ...allMetadata, ...(mod.config.metadata || {}) };
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
- if (mod.default && mod.default.__isController) {
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(mod.default);
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 (mod.default && isController(mod.default)) {
1887
- this.registerControllers([mod.default], routePath, prefixMiddlewares);
2007
+ else if (unwrappedMod && isController(unwrappedMod)) {
2008
+ this.registerControllers([unwrappedMod], routePath, prefixMiddlewares);
1888
2009
  }
1889
- else if (mod.default && isRouter(mod.default)) {
1890
- this.mountRouteWithSource(routePath, mod.default, filePath, prefixMiddlewares);
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
- // eslint-disable-next-line @typescript-eslint/no-require-imports
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
  }