@expressots/adapter-express 3.0.0 → 4.0.0-preview.1

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 (239) hide show
  1. package/README.md +39 -96
  2. package/lib/CHANGELOG.md +31 -5
  3. package/lib/README.md +39 -96
  4. package/lib/cjs/adapter-express/application-express.base.js +3 -1
  5. package/lib/cjs/adapter-express/application-express.js +1049 -85
  6. package/lib/cjs/adapter-express/express-utils/conditional-middleware.js +102 -0
  7. package/lib/cjs/adapter-express/express-utils/constants.js +17 -0
  8. package/lib/cjs/adapter-express/express-utils/content-negotiation-decorators.js +129 -0
  9. package/lib/cjs/adapter-express/express-utils/decorators.js +186 -49
  10. package/lib/cjs/adapter-express/express-utils/exception-filter-decorators.js +11 -0
  11. package/lib/cjs/adapter-express/express-utils/guard-context-factory.js +84 -0
  12. package/lib/cjs/adapter-express/express-utils/guard-middleware.js +115 -0
  13. package/lib/cjs/adapter-express/express-utils/guard-utils.js +18 -0
  14. package/lib/cjs/adapter-express/express-utils/http-context-store.js +15 -0
  15. package/lib/cjs/adapter-express/express-utils/http-status-middleware.js +37 -2
  16. package/lib/cjs/adapter-express/express-utils/index.js +67 -1
  17. package/lib/cjs/adapter-express/express-utils/interceptor-middleware.js +132 -0
  18. package/lib/cjs/adapter-express/express-utils/inversify-express-server.js +810 -63
  19. package/lib/cjs/adapter-express/express-utils/lazy-module-middleware.js +241 -0
  20. package/lib/cjs/adapter-express/express-utils/middleware-composition.js +95 -0
  21. package/lib/cjs/adapter-express/express-utils/permission-preloader.middleware.js +48 -0
  22. package/lib/cjs/adapter-express/express-utils/route-constraints.js +95 -0
  23. package/lib/cjs/adapter-express/express-utils/scope-extractor.interface.js +2 -0
  24. package/lib/cjs/adapter-express/express-utils/scope-extractor.js +66 -0
  25. package/lib/cjs/adapter-express/express-utils/setup-authorization.js +71 -0
  26. package/lib/cjs/adapter-express/express-utils/setup-event-system.js +113 -0
  27. package/lib/cjs/adapter-express/express-utils/setup-interceptors.js +103 -0
  28. package/lib/cjs/adapter-express/express-utils/setup-lazy-loading.js +228 -0
  29. package/lib/cjs/adapter-express/express-utils/utils.js +30 -12
  30. package/lib/cjs/adapter-express/express-utils/validation-decorators.js +205 -0
  31. package/lib/cjs/adapter-express/express-utils/validation-service.js +252 -0
  32. package/lib/cjs/adapter-express/index.js +7 -5
  33. package/lib/cjs/adapter-express/micro-api/application-express-micro-route.js +31 -1
  34. package/lib/cjs/adapter-express/micro-api/application-express-micro.js +11 -37
  35. package/lib/cjs/adapter-express/micro-api/gateway/circuit-breaker.js +174 -0
  36. package/lib/cjs/adapter-express/micro-api/gateway/index.js +11 -0
  37. package/lib/cjs/adapter-express/micro-api/gateway/service-proxy.js +214 -0
  38. package/lib/cjs/adapter-express/micro-api/index.js +27 -3
  39. package/lib/cjs/adapter-express/micro-api/micro.js +217 -0
  40. package/lib/cjs/adapter-express/micro-api/queue/index.js +8 -0
  41. package/lib/cjs/adapter-express/micro-api/queue/queue.interface.js +2 -0
  42. package/lib/cjs/adapter-express/micro-api/queue/rabbitmq-consumer.js +255 -0
  43. package/lib/cjs/adapter-express/micro-api/serverless/aws-lambda.adapter.js +183 -0
  44. package/lib/cjs/adapter-express/micro-api/serverless/cloudflare.adapter.js +158 -0
  45. package/lib/cjs/adapter-express/micro-api/serverless/index.js +12 -0
  46. package/lib/cjs/adapter-express/micro-api/serverless/vercel.adapter.js +102 -0
  47. package/lib/cjs/adapter-express/micro-api/service-mesh/index.js +10 -0
  48. package/lib/cjs/adapter-express/micro-api/service-mesh/service-client.js +194 -0
  49. package/lib/cjs/adapter-express/micro-api/service-mesh/service-discovery.js +261 -0
  50. package/lib/cjs/adapter-express/middleware/index.js +21 -0
  51. package/lib/cjs/adapter-express/middleware/request-logging.middleware.js +244 -0
  52. package/lib/cjs/adapter-express/render/engine.js +15 -15
  53. package/lib/cjs/adapter-express/render/index.js +5 -0
  54. package/lib/cjs/adapter-express/studio/index.js +9 -0
  55. package/lib/cjs/adapter-express/studio/studio-integration.js +214 -0
  56. package/lib/cjs/index.js +1 -1
  57. package/lib/cjs/types/adapter-express/application-express.base.d.ts +20 -7
  58. package/lib/cjs/types/adapter-express/application-express.d.ts +273 -32
  59. package/lib/cjs/types/adapter-express/express-utils/base-middleware.d.ts +2 -2
  60. package/lib/cjs/types/adapter-express/express-utils/conditional-middleware.d.ts +97 -0
  61. package/lib/cjs/types/adapter-express/express-utils/constants.d.ts +13 -0
  62. package/lib/cjs/types/adapter-express/express-utils/content-negotiation-decorators.d.ts +94 -0
  63. package/lib/cjs/types/adapter-express/express-utils/decorators.d.ts +54 -6
  64. package/lib/cjs/types/adapter-express/express-utils/exception-filter-decorators.d.ts +6 -0
  65. package/lib/cjs/types/adapter-express/express-utils/guard-context-factory.d.ts +17 -0
  66. package/lib/cjs/types/adapter-express/express-utils/guard-middleware.d.ts +22 -0
  67. package/lib/cjs/types/adapter-express/express-utils/guard-utils.d.ts +11 -0
  68. package/lib/cjs/types/adapter-express/express-utils/http-context-store.d.ts +20 -0
  69. package/lib/cjs/types/adapter-express/express-utils/httpResponseMessage.d.ts +1 -1
  70. package/lib/cjs/types/adapter-express/express-utils/index.d.ts +30 -2
  71. package/lib/cjs/types/adapter-express/express-utils/interceptor-middleware.d.ts +40 -0
  72. package/lib/cjs/types/adapter-express/express-utils/interfaces.d.ts +42 -5
  73. package/lib/cjs/types/adapter-express/express-utils/inversify-express-server.d.ts +114 -2
  74. package/lib/cjs/types/adapter-express/express-utils/lazy-module-middleware.d.ts +122 -0
  75. package/lib/cjs/types/adapter-express/express-utils/middleware-composition.d.ts +85 -0
  76. package/lib/cjs/types/adapter-express/express-utils/permission-preloader.middleware.d.ts +10 -0
  77. package/lib/cjs/types/adapter-express/express-utils/route-constraints.d.ts +89 -0
  78. package/lib/cjs/types/adapter-express/express-utils/scope-extractor.d.ts +21 -0
  79. package/lib/cjs/types/adapter-express/express-utils/scope-extractor.interface.d.ts +12 -0
  80. package/lib/cjs/types/adapter-express/express-utils/setup-authorization.d.ts +34 -0
  81. package/lib/cjs/types/adapter-express/express-utils/setup-event-system.d.ts +118 -0
  82. package/lib/cjs/types/adapter-express/express-utils/setup-interceptors.d.ts +115 -0
  83. package/lib/cjs/types/adapter-express/express-utils/setup-lazy-loading.d.ts +123 -0
  84. package/lib/cjs/types/adapter-express/express-utils/utils.d.ts +17 -2
  85. package/lib/cjs/types/adapter-express/express-utils/validation-decorators.d.ts +145 -0
  86. package/lib/cjs/types/adapter-express/express-utils/validation-service.d.ts +88 -0
  87. package/lib/cjs/types/adapter-express/index.d.ts +6 -4
  88. package/lib/cjs/types/adapter-express/micro-api/application-express-micro-route.d.ts +25 -14
  89. package/lib/cjs/types/adapter-express/micro-api/application-express-micro.d.ts +3 -10
  90. package/lib/cjs/types/adapter-express/micro-api/gateway/circuit-breaker.d.ts +111 -0
  91. package/lib/cjs/types/adapter-express/micro-api/gateway/index.d.ts +5 -0
  92. package/lib/cjs/types/adapter-express/micro-api/gateway/service-proxy.d.ts +83 -0
  93. package/lib/cjs/types/adapter-express/micro-api/index.d.ts +7 -1
  94. package/lib/cjs/types/adapter-express/micro-api/micro.d.ts +66 -0
  95. package/lib/cjs/types/adapter-express/micro-api/queue/index.d.ts +5 -0
  96. package/lib/cjs/types/adapter-express/micro-api/queue/queue.interface.d.ts +60 -0
  97. package/lib/cjs/types/adapter-express/micro-api/queue/rabbitmq-consumer.d.ts +86 -0
  98. package/lib/cjs/types/adapter-express/micro-api/serverless/aws-lambda.adapter.d.ts +77 -0
  99. package/lib/cjs/types/adapter-express/micro-api/serverless/cloudflare.adapter.d.ts +64 -0
  100. package/lib/cjs/types/adapter-express/micro-api/serverless/index.d.ts +6 -0
  101. package/lib/cjs/types/adapter-express/micro-api/serverless/vercel.adapter.d.ts +56 -0
  102. package/lib/cjs/types/adapter-express/micro-api/service-mesh/index.d.ts +5 -0
  103. package/lib/cjs/types/adapter-express/micro-api/service-mesh/service-client.d.ts +122 -0
  104. package/lib/cjs/types/adapter-express/micro-api/service-mesh/service-discovery.d.ts +150 -0
  105. package/lib/cjs/types/adapter-express/middleware/index.d.ts +5 -0
  106. package/lib/cjs/types/adapter-express/middleware/request-logging.middleware.d.ts +65 -0
  107. package/lib/cjs/types/adapter-express/render/index.d.ts +1 -0
  108. package/lib/cjs/types/adapter-express/studio/index.d.ts +1 -0
  109. package/lib/cjs/types/adapter-express/studio/studio-integration.d.ts +92 -0
  110. package/lib/cjs/types/index.d.ts +1 -1
  111. package/lib/esm/adapter-express/application-express.base.js +24 -0
  112. package/lib/esm/adapter-express/application-express.js +1300 -0
  113. package/lib/esm/adapter-express/application-express.types.js +1 -0
  114. package/lib/esm/adapter-express/express-utils/base-middleware.js +19 -0
  115. package/lib/esm/adapter-express/express-utils/conditional-middleware.js +96 -0
  116. package/lib/esm/adapter-express/express-utils/constants.js +63 -0
  117. package/lib/esm/adapter-express/express-utils/content/httpContent.js +6 -0
  118. package/lib/esm/adapter-express/express-utils/content-negotiation-decorators.js +120 -0
  119. package/lib/esm/adapter-express/express-utils/decorators.js +575 -0
  120. package/lib/esm/adapter-express/express-utils/exception-filter-decorators.js +6 -0
  121. package/lib/esm/adapter-express/express-utils/guard-context-factory.js +83 -0
  122. package/lib/esm/adapter-express/express-utils/guard-middleware.js +115 -0
  123. package/lib/esm/adapter-express/express-utils/guard-utils.js +14 -0
  124. package/lib/esm/adapter-express/express-utils/http-context-store.js +10 -0
  125. package/lib/esm/adapter-express/express-utils/http-status-middleware.js +116 -0
  126. package/lib/esm/adapter-express/express-utils/httpResponseMessage.js +29 -0
  127. package/lib/esm/adapter-express/express-utils/index.js +24 -0
  128. package/lib/esm/adapter-express/express-utils/interceptor-middleware.js +130 -0
  129. package/lib/esm/adapter-express/express-utils/interfaces.js +1 -0
  130. package/lib/esm/adapter-express/express-utils/inversify-express-server.js +1031 -0
  131. package/lib/esm/adapter-express/express-utils/lazy-module-middleware.js +236 -0
  132. package/lib/esm/adapter-express/express-utils/middleware-composition.js +89 -0
  133. package/lib/esm/adapter-express/express-utils/permission-preloader.middleware.js +45 -0
  134. package/lib/esm/adapter-express/express-utils/resolver-multer.js +30 -0
  135. package/lib/esm/adapter-express/express-utils/route-constraints.js +91 -0
  136. package/lib/esm/adapter-express/express-utils/scope-extractor.interface.js +1 -0
  137. package/lib/esm/adapter-express/express-utils/scope-extractor.js +63 -0
  138. package/lib/esm/adapter-express/express-utils/setup-authorization.js +68 -0
  139. package/lib/esm/adapter-express/express-utils/setup-event-system.js +110 -0
  140. package/lib/esm/adapter-express/express-utils/setup-interceptors.js +100 -0
  141. package/lib/esm/adapter-express/express-utils/setup-lazy-loading.js +225 -0
  142. package/lib/esm/adapter-express/express-utils/utils.js +68 -0
  143. package/lib/esm/adapter-express/express-utils/validation-decorators.js +199 -0
  144. package/lib/esm/adapter-express/express-utils/validation-service.js +251 -0
  145. package/lib/esm/adapter-express/index.js +7 -0
  146. package/lib/esm/adapter-express/micro-api/application-express-micro-container.js +48 -0
  147. package/lib/esm/adapter-express/micro-api/application-express-micro-route.js +128 -0
  148. package/lib/esm/adapter-express/micro-api/application-express-micro.js +161 -0
  149. package/lib/esm/adapter-express/micro-api/gateway/circuit-breaker.js +174 -0
  150. package/lib/esm/adapter-express/micro-api/gateway/index.js +5 -0
  151. package/lib/esm/adapter-express/micro-api/gateway/service-proxy.js +210 -0
  152. package/lib/esm/adapter-express/micro-api/index.js +10 -0
  153. package/lib/esm/adapter-express/micro-api/micro.js +211 -0
  154. package/lib/esm/adapter-express/micro-api/queue/index.js +4 -0
  155. package/lib/esm/adapter-express/micro-api/queue/queue.interface.js +1 -0
  156. package/lib/esm/adapter-express/micro-api/queue/rabbitmq-consumer.js +229 -0
  157. package/lib/esm/adapter-express/micro-api/serverless/aws-lambda.adapter.js +180 -0
  158. package/lib/esm/adapter-express/micro-api/serverless/cloudflare.adapter.js +155 -0
  159. package/lib/esm/adapter-express/micro-api/serverless/index.js +6 -0
  160. package/lib/esm/adapter-express/micro-api/serverless/vercel.adapter.js +99 -0
  161. package/lib/esm/adapter-express/micro-api/service-mesh/index.js +5 -0
  162. package/lib/esm/adapter-express/micro-api/service-mesh/service-client.js +191 -0
  163. package/lib/esm/adapter-express/micro-api/service-mesh/service-discovery.js +259 -0
  164. package/lib/esm/adapter-express/middleware/index.js +5 -0
  165. package/lib/esm/adapter-express/middleware/request-logging.middleware.js +239 -0
  166. package/lib/esm/adapter-express/render/constants.js +37 -0
  167. package/lib/esm/adapter-express/render/engine.js +51 -0
  168. package/lib/esm/adapter-express/render/index.js +1 -0
  169. package/lib/esm/adapter-express/render/resolve-render.js +30 -0
  170. package/lib/esm/adapter-express/studio/index.js +1 -0
  171. package/lib/esm/adapter-express/studio/studio-integration.js +184 -0
  172. package/lib/esm/index.mjs +1 -0
  173. package/lib/esm/package.json +3 -0
  174. package/lib/esm/types/adapter-express/application-express.base.d.ts +77 -0
  175. package/lib/esm/types/adapter-express/application-express.d.ts +411 -0
  176. package/lib/esm/types/adapter-express/application-express.types.d.ts +23 -0
  177. package/lib/esm/types/adapter-express/express-utils/base-middleware.d.ts +8 -0
  178. package/lib/esm/types/adapter-express/express-utils/conditional-middleware.d.ts +97 -0
  179. package/lib/esm/types/adapter-express/express-utils/constants.d.ts +57 -0
  180. package/lib/esm/types/adapter-express/express-utils/content/httpContent.d.ts +6 -0
  181. package/lib/esm/types/adapter-express/express-utils/content-negotiation-decorators.d.ts +94 -0
  182. package/lib/esm/types/adapter-express/express-utils/decorators.d.ts +257 -0
  183. package/lib/esm/types/adapter-express/express-utils/exception-filter-decorators.d.ts +6 -0
  184. package/lib/esm/types/adapter-express/express-utils/guard-context-factory.d.ts +17 -0
  185. package/lib/esm/types/adapter-express/express-utils/guard-middleware.d.ts +22 -0
  186. package/lib/esm/types/adapter-express/express-utils/guard-utils.d.ts +11 -0
  187. package/lib/esm/types/adapter-express/express-utils/http-context-store.d.ts +20 -0
  188. package/lib/esm/types/adapter-express/express-utils/http-status-middleware.d.ts +26 -0
  189. package/lib/esm/types/adapter-express/express-utils/httpResponseMessage.d.ts +14 -0
  190. package/lib/esm/types/adapter-express/express-utils/index.d.ts +30 -0
  191. package/lib/esm/types/adapter-express/express-utils/interceptor-middleware.d.ts +40 -0
  192. package/lib/esm/types/adapter-express/express-utils/interfaces.d.ts +115 -0
  193. package/lib/esm/types/adapter-express/express-utils/inversify-express-server.d.ts +172 -0
  194. package/lib/esm/types/adapter-express/express-utils/lazy-module-middleware.d.ts +122 -0
  195. package/lib/esm/types/adapter-express/express-utils/middleware-composition.d.ts +85 -0
  196. package/lib/esm/types/adapter-express/express-utils/permission-preloader.middleware.d.ts +10 -0
  197. package/lib/esm/types/adapter-express/express-utils/resolver-multer.d.ts +7 -0
  198. package/lib/esm/types/adapter-express/express-utils/route-constraints.d.ts +89 -0
  199. package/lib/esm/types/adapter-express/express-utils/scope-extractor.d.ts +21 -0
  200. package/lib/esm/types/adapter-express/express-utils/scope-extractor.interface.d.ts +12 -0
  201. package/lib/esm/types/adapter-express/express-utils/setup-authorization.d.ts +34 -0
  202. package/lib/esm/types/adapter-express/express-utils/setup-event-system.d.ts +118 -0
  203. package/lib/esm/types/adapter-express/express-utils/setup-interceptors.d.ts +115 -0
  204. package/lib/esm/types/adapter-express/express-utils/setup-lazy-loading.d.ts +123 -0
  205. package/lib/esm/types/adapter-express/express-utils/utils.d.ts +24 -0
  206. package/lib/esm/types/adapter-express/express-utils/validation-decorators.d.ts +145 -0
  207. package/lib/esm/types/adapter-express/express-utils/validation-service.d.ts +88 -0
  208. package/lib/esm/types/adapter-express/index.d.ts +7 -0
  209. package/lib/esm/types/adapter-express/micro-api/application-express-micro-container.d.ts +47 -0
  210. package/lib/esm/types/adapter-express/micro-api/application-express-micro-route.d.ts +104 -0
  211. package/lib/esm/types/adapter-express/micro-api/application-express-micro.d.ts +72 -0
  212. package/lib/esm/types/adapter-express/micro-api/gateway/circuit-breaker.d.ts +111 -0
  213. package/lib/esm/types/adapter-express/micro-api/gateway/index.d.ts +5 -0
  214. package/lib/esm/types/adapter-express/micro-api/gateway/service-proxy.d.ts +83 -0
  215. package/lib/esm/types/adapter-express/micro-api/index.d.ts +7 -0
  216. package/lib/esm/types/adapter-express/micro-api/micro.d.ts +66 -0
  217. package/lib/esm/types/adapter-express/micro-api/queue/index.d.ts +5 -0
  218. package/lib/esm/types/adapter-express/micro-api/queue/queue.interface.d.ts +60 -0
  219. package/lib/esm/types/adapter-express/micro-api/queue/rabbitmq-consumer.d.ts +86 -0
  220. package/lib/esm/types/adapter-express/micro-api/serverless/aws-lambda.adapter.d.ts +77 -0
  221. package/lib/esm/types/adapter-express/micro-api/serverless/cloudflare.adapter.d.ts +64 -0
  222. package/lib/esm/types/adapter-express/micro-api/serverless/index.d.ts +6 -0
  223. package/lib/esm/types/adapter-express/micro-api/serverless/vercel.adapter.d.ts +56 -0
  224. package/lib/esm/types/adapter-express/micro-api/service-mesh/index.d.ts +5 -0
  225. package/lib/esm/types/adapter-express/micro-api/service-mesh/service-client.d.ts +122 -0
  226. package/lib/esm/types/adapter-express/micro-api/service-mesh/service-discovery.d.ts +150 -0
  227. package/lib/esm/types/adapter-express/middleware/index.d.ts +5 -0
  228. package/lib/esm/types/adapter-express/middleware/request-logging.middleware.d.ts +65 -0
  229. package/lib/esm/types/adapter-express/render/constants.d.ts +26 -0
  230. package/lib/esm/types/adapter-express/render/engine.d.ts +20 -0
  231. package/lib/esm/types/adapter-express/render/index.d.ts +5 -0
  232. package/lib/esm/types/adapter-express/render/resolve-render.d.ts +7 -0
  233. package/lib/esm/types/adapter-express/studio/index.d.ts +1 -0
  234. package/lib/esm/types/adapter-express/studio/studio-integration.d.ts +92 -0
  235. package/lib/esm/types/index.d.ts +1 -0
  236. package/lib/package.json +156 -146
  237. package/package.json +156 -146
  238. package/lib/cjs/di/di.interfaces.js +0 -10
  239. package/lib/cjs/types/di/di.interfaces.d.ts +0 -289
@@ -0,0 +1,241 @@
1
+ "use strict";
2
+ /**
3
+ * Lazy Module Auto-Load Middleware
4
+ *
5
+ * Automatically loads lazy modules when their routes are accessed.
6
+ * This provides seamless lazy loading without 404 errors.
7
+ *
8
+ * @module adapter-express
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.createLazyModuleMiddleware = createLazyModuleMiddleware;
12
+ exports.extractRoutePrefixes = extractRoutePrefixes;
13
+ exports.createRouteMappings = createRouteMappings;
14
+ const express_1 = require("express");
15
+ // ============================================================================
16
+ // Lazy Module Middleware
17
+ // ============================================================================
18
+ /**
19
+ * Create middleware that auto-loads lazy modules when their routes are accessed.
20
+ *
21
+ * @layer public
22
+ * @audience application-developers
23
+ * @concept lazy-loading
24
+ *
25
+ * UNIQUE: Seamless lazy loading - no 404s! Modules load automatically
26
+ * when their routes are accessed for the first time.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const middleware = createLazyModuleMiddleware({
31
+ * routes: [
32
+ * { prefix: "/admin", moduleName: "AdminModule", loaded: false },
33
+ * { prefix: "/reports", moduleName: "ReportsModule", loaded: false }
34
+ * ],
35
+ * loader: lazyModuleLoader,
36
+ * globalPrefix: "/api"
37
+ * });
38
+ *
39
+ * app.use(middleware);
40
+ * ```
41
+ *
42
+ * @param config - Middleware configuration
43
+ * @returns Express middleware function
44
+ *
45
+ * @public API
46
+ */
47
+ function createLazyModuleMiddleware(config) {
48
+ const { routes, loader, globalPrefix = "" } = config;
49
+ // Create a map for O(1) prefix lookup
50
+ const routeMap = new Map();
51
+ for (const route of routes) {
52
+ const fullPrefix = globalPrefix + route.prefix;
53
+ routeMap.set(fullPrefix.toLowerCase(), route);
54
+ }
55
+ // Track modules currently being loaded (to prevent duplicate loads)
56
+ const loadingModules = new Set();
57
+ return async (req, res, next) => {
58
+ const path = req.path.toLowerCase();
59
+ // Find matching route prefix
60
+ let matchedRoute;
61
+ for (const [prefix, route] of routeMap.entries()) {
62
+ if (path.startsWith(prefix)) {
63
+ matchedRoute = route;
64
+ break;
65
+ }
66
+ }
67
+ // No matching lazy module route
68
+ if (!matchedRoute) {
69
+ return next();
70
+ }
71
+ // Already loaded
72
+ if (matchedRoute.loaded || loader.isLoaded(matchedRoute.moduleName)) {
73
+ matchedRoute.loaded = true;
74
+ return next();
75
+ }
76
+ // Currently loading - wait for it
77
+ if (loadingModules.has(matchedRoute.moduleName)) {
78
+ // Poll until loaded (with timeout)
79
+ const maxWait = 30000; // 30 seconds
80
+ const pollInterval = 50;
81
+ let waited = 0;
82
+ while (loadingModules.has(matchedRoute.moduleName) && waited < maxWait) {
83
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
84
+ waited += pollInterval;
85
+ }
86
+ if (loader.isLoaded(matchedRoute.moduleName)) {
87
+ matchedRoute.loaded = true;
88
+ return next();
89
+ }
90
+ else {
91
+ res.status(503).json({
92
+ error: "Service Unavailable",
93
+ message: `Module '${matchedRoute.moduleName}' is still loading. Please try again.`,
94
+ });
95
+ return;
96
+ }
97
+ }
98
+ // Start loading the module
99
+ loadingModules.add(matchedRoute.moduleName);
100
+ const startTime = Date.now();
101
+ config.onLoadStart?.(matchedRoute.moduleName, req.path);
102
+ try {
103
+ await loader.load(matchedRoute.moduleName);
104
+ matchedRoute.loaded = true;
105
+ const loadTime = Date.now() - startTime;
106
+ config.onLoadComplete?.(matchedRoute.moduleName, loadTime);
107
+ console.log(`[Lazy Loading] Module '${matchedRoute.moduleName}' loaded on-demand in ${loadTime}ms ` +
108
+ `(triggered by ${req.method} ${req.path})`);
109
+ loadingModules.delete(matchedRoute.moduleName);
110
+ // Dynamic route registration: If callbacks are provided, register routes
111
+ // and continue the request without redirecting
112
+ if (config.onRegisterRoutes && config.expressApp) {
113
+ try {
114
+ const moduleRouter = (0, express_1.Router)();
115
+ config.onRegisterRoutes(matchedRoute.moduleName, moduleRouter);
116
+ // Mount the new routes (Express will pick them up for future requests)
117
+ // For THIS request, we continue to let it fall through
118
+ console.log(`[Lazy Loading] Dynamically registered routes for '${matchedRoute.moduleName}'`);
119
+ }
120
+ catch (registrationError) {
121
+ console.warn(`[Lazy Loading] Dynamic route registration failed for '${matchedRoute.moduleName}':`, registrationError);
122
+ }
123
+ }
124
+ // Continue to next middleware - the routes should now be available
125
+ // This works because Express route matching happens per-request
126
+ // and the container now has the lazy module's controllers bound.
127
+ //
128
+ // If dynamic registration isn't set up, fall back to 307 redirect
129
+ if (config.onRegisterRoutes) {
130
+ // Re-emit the request through Express routing
131
+ // The route should now match a real handler
132
+ return next("route");
133
+ }
134
+ else {
135
+ // Fallback: 307 redirect for single round-trip (temporary redirect preserves method)
136
+ res.redirect(307, req.originalUrl);
137
+ }
138
+ }
139
+ catch (error) {
140
+ loadingModules.delete(matchedRoute.moduleName);
141
+ const err = error instanceof Error ? error : new Error(String(error));
142
+ config.onLoadError?.(matchedRoute.moduleName, err);
143
+ console.error(`[Lazy Loading] Failed to load module '${matchedRoute.moduleName}':`, err.message);
144
+ res.status(500).json({
145
+ error: "Module Load Failed",
146
+ message: `Failed to load module for route '${req.path}'. ${err.message}`,
147
+ });
148
+ }
149
+ };
150
+ }
151
+ // ============================================================================
152
+ // Helper Functions
153
+ // ============================================================================
154
+ /**
155
+ * Extract route prefixes from a lazy module.
156
+ *
157
+ * Uses auto-detected routes from CreateLazyModule (which analyzes @controller decorators),
158
+ * falls back to prefetchOn config, and finally infers from module name.
159
+ *
160
+ * @param lazyModule - The lazy module to analyze
161
+ * @returns Detected route prefixes
162
+ *
163
+ * @public API
164
+ */
165
+ function extractRoutePrefixes(lazyModule) {
166
+ const prefixes = [];
167
+ // 1. Use auto-detected routePrefixes from CreateLazyModule (best source!)
168
+ if (lazyModule.config.routePrefixes && lazyModule.config.routePrefixes.length > 0) {
169
+ return lazyModule.config.routePrefixes;
170
+ }
171
+ // 2. Try prefetchOn config as fallback
172
+ const prefetchOn = lazyModule.config.prefetchOn || [];
173
+ for (const prefetch of prefetchOn) {
174
+ const parts = prefetch.route.split("/").filter(Boolean);
175
+ if (parts.length > 0) {
176
+ prefixes.push("/" + parts[0]);
177
+ }
178
+ }
179
+ if (prefixes.length > 0) {
180
+ return [...new Set(prefixes)];
181
+ }
182
+ // 3. Last resort: infer from module name
183
+ // "AdminModule" -> "/admin", "UserSettingsModule" -> "/usersettings"
184
+ const inferredPrefix = "/" +
185
+ lazyModule.name
186
+ .replace(/Module$/i, "")
187
+ .replace(/([A-Z])/g, (match, p1, offset) => offset > 0 ? `-${p1.toLowerCase()}` : p1.toLowerCase());
188
+ return [inferredPrefix];
189
+ }
190
+ /**
191
+ * Create route mappings from lazy modules.
192
+ *
193
+ * Route detection priority:
194
+ * 1. Manual routePrefixMap (if provided)
195
+ * 2. Auto-detected from @controller() decorators (via CreateLazyModule)
196
+ * 3. prefetchOn config
197
+ * 4. Inferred from module name
198
+ *
199
+ * @param lazyModules - Array of lazy modules
200
+ * @param routePrefixMap - Optional manual prefix mappings { moduleName: prefix }
201
+ * @returns Array of route mappings
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * // Zero-config: routes auto-detected from controllers!
206
+ * const mappings = createRouteMappings([AdminModule, ReportsModule]);
207
+ * // Automatically maps @controller("/admin") -> /admin
208
+ *
209
+ * // Or with manual overrides
210
+ * const mappings = createRouteMappings(
211
+ * [AdminModule, ReportsModule],
212
+ * { "AdminModule": "/admin-panel" } // Override auto-detection
213
+ * );
214
+ * ```
215
+ *
216
+ * @public API
217
+ */
218
+ function createRouteMappings(lazyModules, routePrefixMap) {
219
+ const mappings = [];
220
+ for (const module of lazyModules) {
221
+ // Use manual mapping if provided (highest priority)
222
+ if (routePrefixMap && routePrefixMap[module.name]) {
223
+ mappings.push({
224
+ prefix: routePrefixMap[module.name],
225
+ moduleName: module.name,
226
+ loaded: module.isLoaded,
227
+ });
228
+ continue;
229
+ }
230
+ // Use auto-detected prefixes (includes @controller detection)
231
+ const prefixes = extractRoutePrefixes(module);
232
+ for (const prefix of prefixes) {
233
+ mappings.push({
234
+ prefix,
235
+ moduleName: module.name,
236
+ loaded: module.isLoaded,
237
+ });
238
+ }
239
+ }
240
+ return mappings;
241
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.COMPOSED_MIDDLEWARE_SYMBOL = void 0;
4
+ exports.isComposedMiddleware = isComposedMiddleware;
5
+ exports.combine = combine;
6
+ exports.sequence = sequence;
7
+ /**
8
+ * Symbol to identify composed middleware configuration objects.
9
+ * Used internally for type checking.
10
+ */
11
+ exports.COMPOSED_MIDDLEWARE_SYMBOL = Symbol("ComposedMiddleware");
12
+ /**
13
+ * Type guard to check if an object is a ComposedMiddlewareConfig.
14
+ */
15
+ function isComposedMiddleware(item) {
16
+ return (typeof item === "object" &&
17
+ item !== null &&
18
+ exports.COMPOSED_MIDDLEWARE_SYMBOL in item &&
19
+ "middleware" in item &&
20
+ "type" in item &&
21
+ Array.isArray(item.middleware) &&
22
+ (item.type === "combine" ||
23
+ item.type === "sequence"));
24
+ }
25
+ /**
26
+ * Combines multiple middleware into a single middleware that executes all of them sequentially.
27
+ * All middleware will execute in order. If any middleware calls `next(error)`, the error
28
+ * is propagated to Express's error handling system.
29
+ *
30
+ * @param middleware - Array of middleware to combine
31
+ * @returns ComposedMiddlewareConfig object
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Combine multiple middleware into a reusable group
36
+ * @Get("/api", combine(AuthMiddleware, LoggingMiddleware, RateLimitMiddleware))
37
+ * async apiHandler() {}
38
+ * ```
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * // Combine with conditional middleware (Phase 3)
43
+ * @Get("/admin",
44
+ * when(req => req.method === "POST", combine(BodyParser, ValidationMiddleware)),
45
+ * combine(AuthMiddleware, LoggingMiddleware)
46
+ * )
47
+ * async adminHandler() {}
48
+ * ```
49
+ */
50
+ function combine(...middleware) {
51
+ if (middleware.length === 0) {
52
+ throw new Error("combine() requires at least one middleware");
53
+ }
54
+ return {
55
+ middleware,
56
+ type: "combine",
57
+ [exports.COMPOSED_MIDDLEWARE_SYMBOL]: true,
58
+ };
59
+ }
60
+ /**
61
+ * Sequences multiple middleware that execute one after another.
62
+ * Similar to `combine()`, but semantically indicates sequential execution
63
+ * where each middleware depends on the previous one completing successfully.
64
+ * If any middleware calls `next(error)`, execution stops and the error is propagated.
65
+ *
66
+ * @param middleware - Array of middleware to sequence
67
+ * @returns ComposedMiddlewareConfig object
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Sequence middleware where each depends on the previous
72
+ * @Get("/api", sequence(ValidateMiddleware, TransformMiddleware, ProcessMiddleware))
73
+ * async apiHandler() {}
74
+ * ```
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * // Sequence with conditional middleware
79
+ * @Get("/data",
80
+ * when(req => req.method === "POST", sequence(BodyParser, ValidateMiddleware)),
81
+ * sequence(AuthMiddleware, ProcessMiddleware)
82
+ * )
83
+ * async dataHandler() {}
84
+ * ```
85
+ */
86
+ function sequence(...middleware) {
87
+ if (middleware.length === 0) {
88
+ throw new Error("sequence() requires at least one middleware");
89
+ }
90
+ return {
91
+ middleware,
92
+ type: "sequence",
93
+ [exports.COMPOSED_MIDDLEWARE_SYMBOL]: true,
94
+ };
95
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.PermissionPreloaderMiddleware = void 0;
13
+ const core_1 = require("@expressots/core");
14
+ const base_middleware_js_1 = require("./base-middleware.js");
15
+ /**
16
+ * Middleware that preloads permissions for authenticated users
17
+ * Caches permissions in request-scoped SecurityContext
18
+ */
19
+ class PermissionPreloaderMiddleware extends base_middleware_js_1.BaseMiddleware {
20
+ async handler(req, res, next) {
21
+ try {
22
+ // Get HttpContext
23
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
24
+ const httpContext = req.__expressotsHttpContext;
25
+ if (!httpContext) {
26
+ return next();
27
+ }
28
+ const principal = httpContext.user;
29
+ // Preload permissions if user is authenticated
30
+ if (principal && (await principal.isAuthenticated())) {
31
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
32
+ const userId = principal.details?.id;
33
+ if (userId && this.securityContext) {
34
+ await this.securityContext.preload(userId);
35
+ }
36
+ }
37
+ next();
38
+ }
39
+ catch (error) {
40
+ next(error);
41
+ }
42
+ }
43
+ }
44
+ exports.PermissionPreloaderMiddleware = PermissionPreloaderMiddleware;
45
+ __decorate([
46
+ (0, core_1.inject)("ISecurityContext"),
47
+ __metadata("design:type", Object)
48
+ ], PermissionPreloaderMiddleware.prototype, "securityContext", void 0);
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Patterns = void 0;
4
+ exports.pattern = pattern;
5
+ /**
6
+ * Route parameter patterns for common use cases.
7
+ * These are Express regex patterns that can be used in route paths.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * import { Patterns, pattern } from "@expressots/adapter-express";
12
+ *
13
+ * @Get(`/users/${pattern("id", Patterns.NUMERIC_ID)}`)
14
+ * getUserById(@param("id") id: number) {
15
+ * // Only matches numeric IDs like /users/123
16
+ * }
17
+ *
18
+ * @Get(`/documents/${pattern("uuid", Patterns.UUID)}`)
19
+ * getDocument(@param("uuid") uuid: string) {
20
+ * // Only matches valid UUIDs
21
+ * }
22
+ * ```
23
+ *
24
+ * @public API
25
+ */
26
+ exports.Patterns = {
27
+ /**
28
+ * Matches one or more digits (numeric ID)
29
+ * Example: /users/123 ✅, /users/abc ❌
30
+ */
31
+ NUMERIC_ID: "(\\d+)",
32
+ /**
33
+ * Matches a valid UUID v4 format
34
+ * Example: /documents/550e8400-e29b-41d4-a716-446655440000 ✅
35
+ */
36
+ UUID: "([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})",
37
+ /**
38
+ * Matches lowercase letters, numbers, and hyphens (URL-friendly slug)
39
+ * Example: /posts/my-awesome-post ✅, /posts/My_Post ❌
40
+ */
41
+ SLUG: "([a-z0-9-]+)",
42
+ /**
43
+ * Matches alphanumeric characters (letters and numbers only)
44
+ * Example: /codes/ABC123 ✅, /codes/ABC-123 ❌
45
+ */
46
+ ALPHANUMERIC: "([a-zA-Z0-9]+)",
47
+ /**
48
+ * Matches lowercase letters only
49
+ * Example: /tags/javascript ✅, /tags/JavaScript ❌
50
+ */
51
+ LOWERCASE: "([a-z]+)",
52
+ /**
53
+ * Matches uppercase letters only
54
+ * Example: /codes/USD ✅, /codes/usd ❌
55
+ */
56
+ UPPERCASE: "([A-Z]+)",
57
+ /**
58
+ * Matches email format (basic validation)
59
+ * Example: /users/user@example.com ✅
60
+ */
61
+ EMAIL: "([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,})",
62
+ /**
63
+ * Matches hexadecimal string (e.g., color codes, hash)
64
+ * Example: /colors/ff5733 ✅, /colors/xyz ❌
65
+ */
66
+ HEXADECIMAL: "([0-9a-fA-F]+)",
67
+ /**
68
+ * Matches MongoDB ObjectId format (24 hex characters)
69
+ * Example: /documents/507f1f77bcf86cd799439011 ✅
70
+ */
71
+ MONGO_ID: "([0-9a-fA-F]{24})",
72
+ };
73
+ /**
74
+ * Helper function to build route parameter patterns.
75
+ * This is optional - you can also use Patterns directly in template strings.
76
+ *
77
+ * @param paramName - The parameter name (e.g., "id", "uuid")
78
+ * @param pattern - The pattern from Patterns
79
+ * @returns The formatted route parameter with pattern
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * import { pattern, Patterns } from "@expressots/adapter-express";
84
+ *
85
+ * @Get(`/users/${pattern("id", Patterns.NUMERIC_ID)}`)
86
+ * getUserById(@param("id") id: number) {
87
+ * // Route: /users/:id(\\d+)
88
+ * }
89
+ * ```
90
+ *
91
+ * @public API
92
+ */
93
+ function pattern(paramName, patternValue) {
94
+ return `:${paramName}(${patternValue})`;
95
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ScopeExtractor = void 0;
10
+ const core_1 = require("@expressots/core");
11
+ /**
12
+ * Extracts scope information from requests
13
+ * Supports tenant extraction from subdomain, header, or param
14
+ * Note: This is bound manually in setupAuthorizationForExpress() to allow user overrides
15
+ */
16
+ let ScopeExtractor = class ScopeExtractor {
17
+ async extract(req) {
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const sessionId = req.session?.id;
20
+ return {
21
+ tenant: this.extractTenant(req),
22
+ request: this.generateRequestId(req),
23
+ session: sessionId,
24
+ transaction: req.headers["x-transaction-id"],
25
+ };
26
+ }
27
+ /**
28
+ * Extract tenant ID from multiple sources
29
+ * @private
30
+ */
31
+ extractTenant(req) {
32
+ // Try subdomain first
33
+ if (req.subdomains && req.subdomains.length > 0) {
34
+ return req.subdomains[0];
35
+ }
36
+ // Try header
37
+ const headerTenant = req.headers["x-tenant-id"];
38
+ if (headerTenant) {
39
+ return headerTenant;
40
+ }
41
+ // Try route parameter
42
+ const paramTenant = req.params.tenantId;
43
+ if (paramTenant) {
44
+ return paramTenant;
45
+ }
46
+ return undefined;
47
+ }
48
+ /**
49
+ * Generate or retrieve request ID
50
+ * @private
51
+ */
52
+ generateRequestId(req) {
53
+ // Try to get existing request ID (if set by middleware)
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ const existingId = req.id;
56
+ if (existingId) {
57
+ return existingId;
58
+ }
59
+ // Generate new ID
60
+ return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;
61
+ }
62
+ };
63
+ exports.ScopeExtractor = ScopeExtractor;
64
+ exports.ScopeExtractor = ScopeExtractor = __decorate([
65
+ (0, core_1.injectable)()
66
+ ], ScopeExtractor);
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setupAuthorizationForExpress = setupAuthorizationForExpress;
4
+ const core_1 = require("@expressots/core");
5
+ const scope_extractor_js_1 = require("./scope-extractor.js");
6
+ const guard_context_factory_js_1 = require("./guard-context-factory.js");
7
+ const guard_middleware_js_1 = require("./guard-middleware.js");
8
+ const permission_preloader_middleware_js_1 = require("./permission-preloader.middleware.js");
9
+ const constants_js_1 = require("./constants.js");
10
+ /**
11
+ * Express-specific authorization setup
12
+ * Automatically registers all adapter-specific services and middleware
13
+ *
14
+ * @param container - DI container
15
+ * @param config - Authorization configuration
16
+ * @param middleware - Optional middleware manager to add PermissionPreloaderMiddleware
17
+ * @param authProvider - Optional AuthProvider class (if not already bound)
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * export class App extends AppExpress {
22
+ * async configureServices(): Promise<void> {
23
+ * setupAuthorizationForExpress(
24
+ * this.config.Container,
25
+ * {
26
+ * enablePreloading: true,
27
+ * enableCaching: true,
28
+ * permissionHierarchy: {
29
+ * admin: ["moderator", "user"],
30
+ * moderator: ["user"],
31
+ * },
32
+ * },
33
+ * this.Middleware,
34
+ * );
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ function setupAuthorizationForExpress(container, config = {}, middleware, authProvider) {
40
+ // Setup core authorization system
41
+ (0, core_1.setupAuthorization)(container, config);
42
+ // Register adapter-specific services
43
+ if (!container.isBound("IScopeExtractor")) {
44
+ container.bind("IScopeExtractor").to(scope_extractor_js_1.ScopeExtractor).inSingletonScope();
45
+ }
46
+ if (!container.isBound(guard_context_factory_js_1.GuardContextFactory)) {
47
+ container.bind(guard_context_factory_js_1.GuardContextFactory).toSelf().inSingletonScope();
48
+ }
49
+ if (!container.isBound(guard_middleware_js_1.GuardMiddleware)) {
50
+ container.bind(guard_middleware_js_1.GuardMiddleware).toSelf().inSingletonScope();
51
+ }
52
+ // Bind AuthProvider if provided and not already bound
53
+ if (authProvider && !container.isBound(constants_js_1.TYPE.AuthProvider)) {
54
+ container.bind(constants_js_1.TYPE.AuthProvider).to(authProvider).inSingletonScope();
55
+ }
56
+ // Add permission preloader middleware if enabled and middleware manager provided
57
+ // PermissionPreloaderMiddleware extends BaseMiddleware which has a handler() method
58
+ // The middleware system accepts BaseMiddleware instances as IExpressoMiddleware
59
+ if (config.enablePreloading !== false && middleware) {
60
+ // Bind PermissionPreloaderMiddleware if not already bound
61
+ if (!container.isBound(permission_preloader_middleware_js_1.PermissionPreloaderMiddleware)) {
62
+ container.bind(permission_preloader_middleware_js_1.PermissionPreloaderMiddleware).toSelf().inSingletonScope();
63
+ }
64
+ // Get instance from container (DI will inject dependencies)
65
+ // Cast to IExpressoMiddleware - BaseMiddleware instances are handled specially
66
+ // by the middleware resolution system (see inversify-express-server.ts)
67
+ const middlewareInstance = container.get(permission_preloader_middleware_js_1.PermissionPreloaderMiddleware);
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ middleware.add(middlewareInstance);
70
+ }
71
+ }