@morojs/moro 1.6.0 → 1.6.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 (388) hide show
  1. package/README.md +256 -74
  2. package/dist/core/auth/morojs-adapter.js +20 -20
  3. package/dist/core/auth/morojs-adapter.js.map +1 -1
  4. package/dist/core/config/file-loader.d.ts +6 -1
  5. package/dist/core/config/file-loader.js +249 -19
  6. package/dist/core/config/file-loader.js.map +1 -1
  7. package/dist/core/config/index.d.ts +12 -41
  8. package/dist/core/config/index.js +54 -65
  9. package/dist/core/config/index.js.map +1 -1
  10. package/dist/core/config/loader.d.ts +7 -0
  11. package/dist/core/config/loader.js +269 -0
  12. package/dist/core/config/loader.js.map +1 -0
  13. package/dist/core/config/schema.d.ts +2 -2
  14. package/dist/core/config/schema.js +44 -52
  15. package/dist/core/config/schema.js.map +1 -1
  16. package/dist/core/config/utils.d.ts +3 -10
  17. package/dist/core/config/utils.js +58 -31
  18. package/dist/core/config/utils.js.map +1 -1
  19. package/dist/core/config/validation.d.ts +17 -0
  20. package/dist/core/config/validation.js +131 -0
  21. package/dist/core/config/validation.js.map +1 -0
  22. package/dist/core/database/adapters/drizzle.d.ts +1 -1
  23. package/dist/core/database/adapters/drizzle.js +11 -18
  24. package/dist/core/database/adapters/drizzle.js.map +1 -1
  25. package/dist/core/database/adapters/index.d.ts +7 -7
  26. package/dist/core/database/adapters/index.js +29 -19
  27. package/dist/core/database/adapters/index.js.map +1 -1
  28. package/dist/core/database/adapters/mongodb.d.ts +1 -13
  29. package/dist/core/database/adapters/mongodb.js +10 -46
  30. package/dist/core/database/adapters/mongodb.js.map +1 -1
  31. package/dist/core/database/adapters/mysql.d.ts +1 -14
  32. package/dist/core/database/adapters/mysql.js +9 -19
  33. package/dist/core/database/adapters/mysql.js.map +1 -1
  34. package/dist/core/database/adapters/postgresql.d.ts +2 -12
  35. package/dist/core/database/adapters/postgresql.js +9 -19
  36. package/dist/core/database/adapters/postgresql.js.map +1 -1
  37. package/dist/core/database/adapters/redis.d.ts +1 -12
  38. package/dist/core/database/adapters/redis.js +13 -48
  39. package/dist/core/database/adapters/redis.js.map +1 -1
  40. package/dist/core/database/adapters/sqlite.d.ts +1 -3
  41. package/dist/core/database/adapters/sqlite.js +8 -19
  42. package/dist/core/database/adapters/sqlite.js.map +1 -1
  43. package/dist/core/database/index.d.ts +2 -2
  44. package/dist/core/database/index.js +18 -2
  45. package/dist/core/database/index.js.map +1 -1
  46. package/dist/core/docs/index.d.ts +9 -9
  47. package/dist/core/docs/index.js +35 -14
  48. package/dist/core/docs/index.js.map +1 -1
  49. package/dist/core/docs/openapi-generator.d.ts +2 -2
  50. package/dist/core/docs/openapi-generator.js +16 -11
  51. package/dist/core/docs/openapi-generator.js.map +1 -1
  52. package/dist/core/docs/schema-to-openapi.d.ts +2 -2
  53. package/dist/core/docs/schema-to-openapi.js +11 -5
  54. package/dist/core/docs/schema-to-openapi.js.map +1 -1
  55. package/dist/core/docs/simple-docs.d.ts +1 -1
  56. package/dist/core/docs/simple-docs.js +9 -4
  57. package/dist/core/docs/simple-docs.js.map +1 -1
  58. package/dist/core/docs/swagger-ui.d.ts +2 -2
  59. package/dist/core/docs/swagger-ui.js +29 -26
  60. package/dist/core/docs/swagger-ui.js.map +1 -1
  61. package/dist/core/docs/zod-to-openapi.js +28 -31
  62. package/dist/core/docs/zod-to-openapi.js.map +1 -1
  63. package/dist/core/events/event-bus.d.ts +1 -1
  64. package/dist/core/events/event-bus.js +10 -6
  65. package/dist/core/events/event-bus.js.map +1 -1
  66. package/dist/core/events/index.d.ts +2 -2
  67. package/dist/core/events/index.js +5 -1
  68. package/dist/core/events/index.js.map +1 -1
  69. package/dist/core/framework.d.ts +12 -19
  70. package/dist/core/framework.js +100 -277
  71. package/dist/core/framework.js.map +1 -1
  72. package/dist/core/http/http-server.d.ts +1 -13
  73. package/dist/core/http/http-server.js +85 -175
  74. package/dist/core/http/http-server.js.map +1 -1
  75. package/dist/core/http/index.d.ts +3 -4
  76. package/dist/core/http/index.js +8 -3
  77. package/dist/core/http/index.js.map +1 -1
  78. package/dist/core/http/router.d.ts +1 -13
  79. package/dist/core/http/router.js +43 -117
  80. package/dist/core/http/router.js.map +1 -1
  81. package/dist/core/logger/filters.d.ts +1 -1
  82. package/dist/core/logger/filters.js +23 -20
  83. package/dist/core/logger/filters.js.map +1 -1
  84. package/dist/core/logger/index.d.ts +3 -3
  85. package/dist/core/logger/index.js +24 -2
  86. package/dist/core/logger/index.js.map +1 -1
  87. package/dist/core/logger/logger.d.ts +14 -30
  88. package/dist/core/logger/logger.js +223 -398
  89. package/dist/core/logger/logger.js.map +1 -1
  90. package/dist/core/logger/outputs.d.ts +1 -1
  91. package/dist/core/logger/outputs.js +17 -8
  92. package/dist/core/logger/outputs.js.map +1 -1
  93. package/dist/core/middleware/built-in/adapters/cache/file.d.ts +1 -1
  94. package/dist/core/middleware/built-in/adapters/cache/file.js +47 -10
  95. package/dist/core/middleware/built-in/adapters/cache/file.js.map +1 -1
  96. package/dist/core/middleware/built-in/adapters/cache/index.d.ts +4 -4
  97. package/dist/core/middleware/built-in/adapters/cache/index.js +17 -10
  98. package/dist/core/middleware/built-in/adapters/cache/index.js.map +1 -1
  99. package/dist/core/middleware/built-in/adapters/cache/memory.d.ts +1 -1
  100. package/dist/core/middleware/built-in/adapters/cache/memory.js +7 -3
  101. package/dist/core/middleware/built-in/adapters/cache/memory.js.map +1 -1
  102. package/dist/core/middleware/built-in/adapters/cache/redis.d.ts +1 -3
  103. package/dist/core/middleware/built-in/adapters/cache/redis.js +9 -11
  104. package/dist/core/middleware/built-in/adapters/cache/redis.js.map +1 -1
  105. package/dist/core/middleware/built-in/adapters/cdn/azure.d.ts +1 -1
  106. package/dist/core/middleware/built-in/adapters/cdn/azure.js +7 -3
  107. package/dist/core/middleware/built-in/adapters/cdn/azure.js.map +1 -1
  108. package/dist/core/middleware/built-in/adapters/cdn/cloudflare.d.ts +1 -1
  109. package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js +7 -3
  110. package/dist/core/middleware/built-in/adapters/cdn/cloudflare.js.map +1 -1
  111. package/dist/core/middleware/built-in/adapters/cdn/cloudfront.d.ts +1 -3
  112. package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js +10 -12
  113. package/dist/core/middleware/built-in/adapters/cdn/cloudfront.js.map +1 -1
  114. package/dist/core/middleware/built-in/adapters/cdn/index.d.ts +4 -4
  115. package/dist/core/middleware/built-in/adapters/cdn/index.js +17 -10
  116. package/dist/core/middleware/built-in/adapters/cdn/index.js.map +1 -1
  117. package/dist/core/middleware/built-in/adapters/index.d.ts +4 -4
  118. package/dist/core/middleware/built-in/adapters/index.js +23 -4
  119. package/dist/core/middleware/built-in/adapters/index.js.map +1 -1
  120. package/dist/core/middleware/built-in/auth-helpers.js +22 -11
  121. package/dist/core/middleware/built-in/auth-helpers.js.map +1 -1
  122. package/dist/core/middleware/built-in/auth-providers.d.ts +1 -1
  123. package/dist/core/middleware/built-in/auth-providers.js +9 -4
  124. package/dist/core/middleware/built-in/auth-providers.js.map +1 -1
  125. package/dist/core/middleware/built-in/auth.d.ts +2 -2
  126. package/dist/core/middleware/built-in/auth.js +26 -93
  127. package/dist/core/middleware/built-in/auth.js.map +1 -1
  128. package/dist/core/middleware/built-in/cache.d.ts +2 -2
  129. package/dist/core/middleware/built-in/cache.js +12 -11
  130. package/dist/core/middleware/built-in/cache.js.map +1 -1
  131. package/dist/core/middleware/built-in/cdn.d.ts +2 -2
  132. package/dist/core/middleware/built-in/cdn.js +9 -5
  133. package/dist/core/middleware/built-in/cdn.js.map +1 -1
  134. package/dist/core/middleware/built-in/cookie.d.ts +1 -1
  135. package/dist/core/middleware/built-in/cookie.js +7 -3
  136. package/dist/core/middleware/built-in/cookie.js.map +1 -1
  137. package/dist/core/middleware/built-in/cors.d.ts +1 -1
  138. package/dist/core/middleware/built-in/cors.js +7 -3
  139. package/dist/core/middleware/built-in/cors.js.map +1 -1
  140. package/dist/core/middleware/built-in/csp.d.ts +1 -1
  141. package/dist/core/middleware/built-in/csp.js +8 -5
  142. package/dist/core/middleware/built-in/csp.js.map +1 -1
  143. package/dist/core/middleware/built-in/csrf.d.ts +1 -1
  144. package/dist/core/middleware/built-in/csrf.js +8 -5
  145. package/dist/core/middleware/built-in/csrf.js.map +1 -1
  146. package/dist/core/middleware/built-in/error-tracker.js +7 -3
  147. package/dist/core/middleware/built-in/error-tracker.js.map +1 -1
  148. package/dist/core/middleware/built-in/index.d.ts +27 -28
  149. package/dist/core/middleware/built-in/index.js +78 -48
  150. package/dist/core/middleware/built-in/index.js.map +1 -1
  151. package/dist/core/middleware/built-in/performance-monitor.js +7 -3
  152. package/dist/core/middleware/built-in/performance-monitor.js.map +1 -1
  153. package/dist/core/middleware/built-in/rate-limit.d.ts +1 -1
  154. package/dist/core/middleware/built-in/rate-limit.js +7 -3
  155. package/dist/core/middleware/built-in/rate-limit.js.map +1 -1
  156. package/dist/core/middleware/built-in/request-logger.js +8 -5
  157. package/dist/core/middleware/built-in/request-logger.js.map +1 -1
  158. package/dist/core/middleware/built-in/session.d.ts +2 -2
  159. package/dist/core/middleware/built-in/session.js +15 -11
  160. package/dist/core/middleware/built-in/session.js.map +1 -1
  161. package/dist/core/middleware/built-in/sse.d.ts +1 -1
  162. package/dist/core/middleware/built-in/sse.js +14 -12
  163. package/dist/core/middleware/built-in/sse.js.map +1 -1
  164. package/dist/core/middleware/built-in/validation.d.ts +1 -1
  165. package/dist/core/middleware/built-in/validation.js +7 -3
  166. package/dist/core/middleware/built-in/validation.js.map +1 -1
  167. package/dist/core/middleware/index.d.ts +4 -4
  168. package/dist/core/middleware/index.js +28 -8
  169. package/dist/core/middleware/index.js.map +1 -1
  170. package/dist/core/modules/auto-discovery.d.ts +2 -19
  171. package/dist/core/modules/auto-discovery.js +74 -391
  172. package/dist/core/modules/auto-discovery.js.map +1 -1
  173. package/dist/core/modules/index.d.ts +2 -2
  174. package/dist/core/modules/index.js +9 -2
  175. package/dist/core/modules/index.js.map +1 -1
  176. package/dist/core/modules/modules.d.ts +3 -3
  177. package/dist/core/modules/modules.js +54 -23
  178. package/dist/core/modules/modules.js.map +1 -1
  179. package/dist/core/networking/adapters/index.d.ts +3 -4
  180. package/dist/core/networking/adapters/index.js +7 -3
  181. package/dist/core/networking/adapters/index.js.map +1 -1
  182. package/dist/core/networking/adapters/socketio-adapter.d.ts +1 -1
  183. package/dist/core/networking/adapters/socketio-adapter.js +40 -5
  184. package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
  185. package/dist/core/networking/adapters/ws-adapter.d.ts +2 -2
  186. package/dist/core/networking/adapters/ws-adapter.js +43 -8
  187. package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
  188. package/dist/core/networking/index.d.ts +2 -3
  189. package/dist/core/networking/index.js +7 -2
  190. package/dist/core/networking/index.js.map +1 -1
  191. package/dist/core/networking/service-discovery.js +12 -8
  192. package/dist/core/networking/service-discovery.js.map +1 -1
  193. package/dist/core/networking/websocket-adapter.js +2 -1
  194. package/dist/core/networking/websocket-adapter.js.map +1 -1
  195. package/dist/core/networking/websocket-manager.d.ts +3 -3
  196. package/dist/core/networking/websocket-manager.js +11 -9
  197. package/dist/core/networking/websocket-manager.js.map +1 -1
  198. package/dist/core/routing/app-integration.d.ts +2 -2
  199. package/dist/core/routing/app-integration.js +12 -7
  200. package/dist/core/routing/app-integration.js.map +1 -1
  201. package/dist/core/routing/index.d.ts +2 -22
  202. package/dist/core/routing/index.js +27 -185
  203. package/dist/core/routing/index.js.map +1 -1
  204. package/dist/core/runtime/aws-lambda-adapter.d.ts +3 -3
  205. package/dist/core/runtime/aws-lambda-adapter.js +6 -2
  206. package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
  207. package/dist/core/runtime/base-adapter.d.ts +2 -2
  208. package/dist/core/runtime/base-adapter.js +7 -3
  209. package/dist/core/runtime/base-adapter.js.map +1 -1
  210. package/dist/core/runtime/cloudflare-workers-adapter.d.ts +3 -3
  211. package/dist/core/runtime/cloudflare-workers-adapter.js +6 -2
  212. package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
  213. package/dist/core/runtime/index.d.ts +12 -12
  214. package/dist/core/runtime/index.js +35 -22
  215. package/dist/core/runtime/index.js.map +1 -1
  216. package/dist/core/runtime/node-adapter.d.ts +4 -4
  217. package/dist/core/runtime/node-adapter.js +49 -18
  218. package/dist/core/runtime/node-adapter.js.map +1 -1
  219. package/dist/core/runtime/vercel-edge-adapter.d.ts +3 -3
  220. package/dist/core/runtime/vercel-edge-adapter.js +6 -2
  221. package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
  222. package/dist/core/utilities/circuit-breaker.js +5 -1
  223. package/dist/core/utilities/circuit-breaker.js.map +1 -1
  224. package/dist/core/utilities/container.js +22 -12
  225. package/dist/core/utilities/container.js.map +1 -1
  226. package/dist/core/utilities/hooks.d.ts +2 -2
  227. package/dist/core/utilities/hooks.js +12 -7
  228. package/dist/core/utilities/hooks.js.map +1 -1
  229. package/dist/core/utilities/index.d.ts +4 -5
  230. package/dist/core/utilities/index.js +19 -5
  231. package/dist/core/utilities/index.js.map +1 -1
  232. package/dist/core/validation/adapters.d.ts +1 -1
  233. package/dist/core/validation/adapters.js +26 -15
  234. package/dist/core/validation/adapters.js.map +1 -1
  235. package/dist/core/validation/index.d.ts +4 -6
  236. package/dist/core/validation/index.js +28 -57
  237. package/dist/core/validation/index.js.map +1 -1
  238. package/dist/core/validation/schema-interface.js +9 -3
  239. package/dist/core/validation/schema-interface.js.map +1 -1
  240. package/dist/index.d.ts +52 -51
  241. package/dist/index.js +132 -23
  242. package/dist/index.js.map +1 -1
  243. package/dist/moro.d.ts +10 -61
  244. package/dist/moro.js +237 -575
  245. package/dist/moro.js.map +1 -1
  246. package/dist/types/auth.js +9 -3
  247. package/dist/types/auth.js.map +1 -1
  248. package/dist/types/cache.js +2 -1
  249. package/dist/types/cdn.js +2 -1
  250. package/dist/types/config.d.ts +2 -70
  251. package/dist/types/config.js +2 -1
  252. package/dist/types/config.js.map +1 -1
  253. package/dist/types/core.d.ts +42 -36
  254. package/dist/types/core.js +2 -1
  255. package/dist/types/database.js +2 -1
  256. package/dist/types/discovery.js +2 -1
  257. package/dist/types/events.js +2 -1
  258. package/dist/types/hooks.d.ts +1 -1
  259. package/dist/types/hooks.js +2 -1
  260. package/dist/types/http.d.ts +1 -16
  261. package/dist/types/http.js +2 -1
  262. package/dist/types/logger.d.ts +0 -7
  263. package/dist/types/logger.js +2 -1
  264. package/dist/types/module.d.ts +0 -11
  265. package/dist/types/module.js +2 -1
  266. package/dist/types/runtime.d.ts +1 -1
  267. package/dist/types/runtime.js +2 -1
  268. package/dist/types/session.js +2 -1
  269. package/package.json +52 -19
  270. package/src/core/auth/morojs-adapter.ts +13 -18
  271. package/src/core/config/file-loader.ts +273 -13
  272. package/src/core/config/index.ts +34 -83
  273. package/src/core/config/loader.ts +633 -0
  274. package/src/core/config/schema.ts +33 -44
  275. package/src/core/config/utils.ts +31 -24
  276. package/src/core/config/validation.ts +140 -0
  277. package/src/core/database/README.md +16 -26
  278. package/src/core/database/adapters/drizzle.ts +6 -18
  279. package/src/core/database/adapters/index.ts +13 -13
  280. package/src/core/database/adapters/mongodb.ts +5 -53
  281. package/src/core/database/adapters/mysql.ts +4 -32
  282. package/src/core/database/adapters/postgresql.ts +5 -30
  283. package/src/core/database/adapters/redis.ts +8 -61
  284. package/src/core/database/adapters/sqlite.ts +3 -19
  285. package/src/core/database/index.ts +2 -2
  286. package/src/core/docs/index.ts +8 -8
  287. package/src/core/docs/openapi-generator.ts +4 -4
  288. package/src/core/docs/schema-to-openapi.ts +6 -3
  289. package/src/core/docs/simple-docs.ts +2 -2
  290. package/src/core/docs/swagger-ui.ts +16 -19
  291. package/src/core/docs/zod-to-openapi.ts +34 -34
  292. package/src/core/events/event-bus.ts +2 -2
  293. package/src/core/events/index.ts +2 -2
  294. package/src/core/framework.ts +67 -311
  295. package/src/core/http/http-server.ts +45 -190
  296. package/src/core/http/index.ts +3 -4
  297. package/src/core/http/router.ts +40 -129
  298. package/src/core/logger/filters.ts +5 -13
  299. package/src/core/logger/index.ts +3 -4
  300. package/src/core/logger/logger.ts +216 -435
  301. package/src/core/logger/outputs.ts +3 -1
  302. package/src/core/middleware/built-in/adapters/cache/file.ts +3 -3
  303. package/src/core/middleware/built-in/adapters/cache/index.ts +7 -7
  304. package/src/core/middleware/built-in/adapters/cache/memory.ts +2 -2
  305. package/src/core/middleware/built-in/adapters/cache/redis.ts +4 -18
  306. package/src/core/middleware/built-in/adapters/cdn/azure.ts +2 -2
  307. package/src/core/middleware/built-in/adapters/cdn/cloudflare.ts +2 -2
  308. package/src/core/middleware/built-in/adapters/cdn/cloudfront.ts +5 -16
  309. package/src/core/middleware/built-in/adapters/cdn/index.ts +7 -7
  310. package/src/core/middleware/built-in/adapters/index.ts +4 -4
  311. package/src/core/middleware/built-in/auth-helpers.ts +1 -1
  312. package/src/core/middleware/built-in/auth-providers.ts +1 -1
  313. package/src/core/middleware/built-in/auth.ts +21 -102
  314. package/src/core/middleware/built-in/cache.ts +6 -8
  315. package/src/core/middleware/built-in/cdn.ts +4 -4
  316. package/src/core/middleware/built-in/cookie.ts +2 -2
  317. package/src/core/middleware/built-in/cors.ts +2 -2
  318. package/src/core/middleware/built-in/csp.ts +3 -3
  319. package/src/core/middleware/built-in/csrf.ts +3 -3
  320. package/src/core/middleware/built-in/error-tracker.ts +1 -1
  321. package/src/core/middleware/built-in/index.ts +30 -38
  322. package/src/core/middleware/built-in/performance-monitor.ts +1 -1
  323. package/src/core/middleware/built-in/rate-limit.ts +2 -2
  324. package/src/core/middleware/built-in/request-logger.ts +1 -3
  325. package/src/core/middleware/built-in/session.ts +8 -7
  326. package/src/core/middleware/built-in/sse.ts +9 -11
  327. package/src/core/middleware/built-in/validation.ts +2 -2
  328. package/src/core/middleware/index.ts +6 -6
  329. package/src/core/modules/auto-discovery.ts +15 -478
  330. package/src/core/modules/index.ts +2 -2
  331. package/src/core/modules/modules.ts +12 -23
  332. package/src/core/networking/adapters/index.ts +3 -4
  333. package/src/core/networking/adapters/socketio-adapter.ts +3 -5
  334. package/src/core/networking/adapters/ws-adapter.ts +9 -8
  335. package/src/core/networking/index.ts +2 -3
  336. package/src/core/networking/service-discovery.ts +7 -6
  337. package/src/core/networking/websocket-manager.ts +7 -7
  338. package/src/core/routing/app-integration.ts +3 -3
  339. package/src/core/routing/index.ts +17 -201
  340. package/src/core/runtime/aws-lambda-adapter.ts +3 -3
  341. package/src/core/runtime/base-adapter.ts +2 -2
  342. package/src/core/runtime/cloudflare-workers-adapter.ts +3 -3
  343. package/src/core/runtime/index.ts +13 -13
  344. package/src/core/runtime/node-adapter.ts +10 -16
  345. package/src/core/runtime/vercel-edge-adapter.ts +3 -3
  346. package/src/core/utilities/hooks.ts +3 -3
  347. package/src/core/utilities/index.ts +4 -5
  348. package/src/core/validation/adapters.ts +1 -1
  349. package/src/core/validation/index.ts +16 -68
  350. package/src/index.ts +66 -73
  351. package/src/moro.ts +204 -685
  352. package/src/types/config.ts +2 -71
  353. package/src/types/core.ts +47 -49
  354. package/src/types/hooks.ts +1 -1
  355. package/src/types/http.ts +1 -23
  356. package/src/types/logger.ts +0 -9
  357. package/src/types/module.ts +0 -12
  358. package/src/types/runtime.ts +1 -1
  359. package/tsconfig.json +2 -4
  360. package/dist/core/config/config-manager.d.ts +0 -44
  361. package/dist/core/config/config-manager.js +0 -104
  362. package/dist/core/config/config-manager.js.map +0 -1
  363. package/dist/core/config/config-sources.d.ts +0 -21
  364. package/dist/core/config/config-sources.js +0 -499
  365. package/dist/core/config/config-sources.js.map +0 -1
  366. package/dist/core/config/config-validator.d.ts +0 -21
  367. package/dist/core/config/config-validator.js +0 -788
  368. package/dist/core/config/config-validator.js.map +0 -1
  369. package/dist/core/http/uws-http-server.d.ts +0 -64
  370. package/dist/core/http/uws-http-server.js +0 -688
  371. package/dist/core/http/uws-http-server.js.map +0 -1
  372. package/dist/core/middleware/built-in/jwt-helpers.d.ts +0 -118
  373. package/dist/core/middleware/built-in/jwt-helpers.js +0 -218
  374. package/dist/core/middleware/built-in/jwt-helpers.js.map +0 -1
  375. package/dist/core/networking/adapters/uws-adapter.d.ts +0 -44
  376. package/dist/core/networking/adapters/uws-adapter.js +0 -513
  377. package/dist/core/networking/adapters/uws-adapter.js.map +0 -1
  378. package/dist/core/utilities/package-utils.d.ts +0 -38
  379. package/dist/core/utilities/package-utils.js +0 -57
  380. package/dist/core/utilities/package-utils.js.map +0 -1
  381. package/jest.config.mjs +0 -41
  382. package/src/core/config/config-manager.ts +0 -133
  383. package/src/core/config/config-sources.ts +0 -596
  384. package/src/core/config/config-validator.ts +0 -1113
  385. package/src/core/http/uws-http-server.ts +0 -794
  386. package/src/core/middleware/built-in/jwt-helpers.ts +0 -243
  387. package/src/core/networking/adapters/uws-adapter.ts +0 -619
  388. package/src/core/utilities/package-utils.ts +0 -59
package/src/moro.ts CHANGED
@@ -1,90 +1,124 @@
1
1
  // Moro Framework - Modern TypeScript API Framework
2
2
  // Built for developers who demand performance, elegance, and zero compromises
3
3
  // Event-driven • Modular • Enterprise-ready • Developer-first
4
- import { Moro as MoroCore } from './core/framework.js';
5
- import { HttpRequest, HttpResponse, middleware } from './core/http/index.js';
6
- import { ModuleConfig, InternalRouteDefinition } from './types/module.js';
7
- import { MoroOptions } from './types/core.js';
8
- import { ModuleDefaultsConfig } from './types/config.js';
9
- import { MoroEventBus } from './core/events/index.js';
10
- import { createFrameworkLogger, applyLoggingConfiguration } from './core/logger/index.js';
11
- import { Logger } from './types/logger.js';
12
- import { MiddlewareManager } from './core/middleware/index.js';
13
- import { IntelligentRoutingManager } from './core/routing/app-integration.js';
14
- import { RouteBuilder, RouteSchema, CompiledRoute } from './core/routing/index.js';
15
- import { AppDocumentationManager, DocsConfig } from './core/docs/index.js';
4
+ import { Moro as MoroCore } from './core/framework';
5
+ import { HttpRequest, HttpResponse, middleware } from './core/http';
6
+ import { ModuleConfig, InternalRouteDefinition } from './types/module';
7
+ import { MoroOptions } from './types/core';
8
+ import { MoroEventBus } from './core/events';
9
+ import {
10
+ createFrameworkLogger,
11
+ logger as globalLogger,
12
+ applyLoggingConfiguration,
13
+ } from './core/logger';
14
+ import { MiddlewareManager } from './core/middleware';
15
+ import { IntelligentRoutingManager } from './core/routing/app-integration';
16
+ import { RouteBuilder, RouteSchema, CompiledRoute } from './core/routing';
17
+ import { AppDocumentationManager, DocsConfig } from './core/docs';
18
+ import { readdirSync, statSync } from 'fs';
19
+ import { join } from 'path';
16
20
  import { EventEmitter } from 'events';
17
- import cluster from 'cluster';
18
- import os from 'os';
19
- import { normalizeValidationError } from './core/validation/schema-interface.js';
20
21
  // Configuration System Integration
21
- import { initializeConfig, type AppConfig } from './core/config/index.js';
22
+ import { initializeConfig, getGlobalConfig, type AppConfig } from './core/config';
22
23
  // Runtime System Integration
23
- import { RuntimeAdapter, RuntimeType, createRuntimeAdapter } from './core/runtime/index.js';
24
+ import {
25
+ RuntimeAdapter,
26
+ RuntimeType,
27
+ createRuntimeAdapter,
28
+ NodeRuntimeAdapter,
29
+ } from './core/runtime';
24
30
 
25
31
  export class Moro extends EventEmitter {
26
- private coreFramework!: MoroCore;
32
+ private coreFramework: MoroCore;
27
33
  private routes: InternalRouteDefinition[] = [];
28
34
  private moduleCounter = 0;
29
35
  private loadedModules = new Set<string>();
30
- private lazyModules = new Map<string, ModuleConfig>();
31
36
  private routeHandlers: Record<string, Function> = {};
32
- private moduleDiscovery?: any; // Store for cleanup
33
- private autoDiscoveryOptions: MoroOptions | null = null;
34
- private autoDiscoveryInitialized = false;
35
- private autoDiscoveryPromise: Promise<void> | null = null;
36
37
  // Enterprise event system integration
37
- private eventBus!: MoroEventBus;
38
+ private eventBus: MoroEventBus;
38
39
  // Application logger
39
- private logger!: Logger;
40
+ private logger = createFrameworkLogger('App');
40
41
  // Intelligent routing system
41
42
  private intelligentRouting = new IntelligentRoutingManager();
42
43
  // Documentation system
43
44
  private documentation = new AppDocumentationManager();
44
45
  // Configuration system
45
- private config!: AppConfig;
46
+ private config: AppConfig;
46
47
  // Runtime system
47
- private runtimeAdapter!: RuntimeAdapter;
48
- private runtimeType!: RuntimeType;
48
+ private runtimeAdapter: RuntimeAdapter;
49
+ private runtimeType: RuntimeType;
49
50
  // Middleware system
50
- private middlewareManager!: MiddlewareManager;
51
- // Queued WebSocket registrations (for async adapter detection)
52
- private queuedWebSocketRegistrations: Array<{
53
- namespace: string;
54
- handlers: Record<string, Function>;
55
- processed: boolean;
56
- }> = [];
51
+ private middlewareManager: MiddlewareManager;
57
52
 
58
53
  constructor(options: MoroOptions = {}) {
59
54
  super(); // Call EventEmitter constructor
60
55
 
61
- // Apply logging configuration BEFORE config loading to avoid DEBUG spam
62
- // 1. Environment variables (base level)
56
+ // Configure logger from environment variables BEFORE config system initialization
57
+ // This ensures the config loading process respects the log level
63
58
  const envLogLevel = process.env.LOG_LEVEL || process.env.MORO_LOG_LEVEL;
64
59
  if (envLogLevel) {
65
60
  applyLoggingConfiguration({ level: envLogLevel }, undefined);
66
61
  }
67
62
 
68
- // 2. createApp logger options (highest precedence)
63
+ // Initialize configuration system - create a deep copy for this instance
64
+ this.config = JSON.parse(JSON.stringify(initializeConfig()));
65
+
66
+ // Apply logging configuration from the loaded config (this happens after config file processing)
67
+ if (this.config.logging) {
68
+ applyLoggingConfiguration(this.config.logging, undefined);
69
+ }
70
+
71
+ // Apply additional logging configuration from createApp options (takes precedence)
69
72
  if (options.logger !== undefined) {
70
73
  applyLoggingConfiguration(undefined, options.logger);
71
74
  }
72
75
 
73
- // Create logger AFTER initial configuration
74
- this.logger = createFrameworkLogger('App');
75
-
76
- // Use simplified global configuration system
77
- this.config = initializeConfig(options);
76
+ // Apply performance configuration from createApp options (takes precedence)
77
+ if (options.performance) {
78
+ if (options.performance.clustering) {
79
+ this.config.performance.clustering = {
80
+ ...this.config.performance.clustering,
81
+ ...options.performance.clustering,
82
+ };
83
+ }
84
+ if (options.performance.compression) {
85
+ this.config.performance.compression = {
86
+ ...this.config.performance.compression,
87
+ ...options.performance.compression,
88
+ };
89
+ }
90
+ if (options.performance.circuitBreaker) {
91
+ this.config.performance.circuitBreaker = {
92
+ ...this.config.performance.circuitBreaker,
93
+ ...options.performance.circuitBreaker,
94
+ };
95
+ }
96
+ }
78
97
 
79
- // Apply config file logging if it exists (may override createApp options if needed)
80
- if (this.config.logging && !options.logger) {
81
- applyLoggingConfiguration(this.config.logging, undefined);
82
- // Recreate logger with updated config
83
- this.logger = createFrameworkLogger('App');
98
+ // Apply modules configuration from createApp options (takes precedence)
99
+ if (options.modules) {
100
+ if (options.modules.cache) {
101
+ this.config.modules.cache = {
102
+ ...this.config.modules.cache,
103
+ ...options.modules.cache,
104
+ };
105
+ }
106
+ if (options.modules.rateLimit) {
107
+ this.config.modules.rateLimit = {
108
+ ...this.config.modules.rateLimit,
109
+ ...options.modules.rateLimit,
110
+ };
111
+ }
112
+ if (options.modules.validation) {
113
+ this.config.modules.validation = {
114
+ ...this.config.modules.validation,
115
+ ...options.modules.validation,
116
+ };
117
+ }
84
118
  }
85
119
 
86
120
  this.logger.info(
87
- `Configuration system initialized: ${process.env.NODE_ENV || 'development'}:${this.config.server.port}`
121
+ `Configuration system initialized: ${this.config.server.environment}:${this.config.server.port}`
88
122
  );
89
123
 
90
124
  // Initialize runtime system
@@ -93,16 +127,10 @@ export class Moro extends EventEmitter {
93
127
 
94
128
  this.logger.info(`Runtime system initialized: ${this.runtimeType}`, 'Runtime');
95
129
 
96
- // Pass configuration from config to framework
130
+ // Pass logging configuration from config to framework
97
131
  const frameworkOptions: any = {
98
132
  ...options,
99
133
  logger: this.config.logging,
100
- // Enable websockets if either config has it enabled OR user passed websocket options
101
- websocket:
102
- this.config.websocket.enabled || options.websocket
103
- ? options.websocket || this.config.websocket || {}
104
- : false,
105
- config: this.config,
106
134
  };
107
135
 
108
136
  this.coreFramework = new MoroCore(frameworkOptions);
@@ -134,10 +162,10 @@ export class Moro extends EventEmitter {
134
162
  ...options,
135
163
  });
136
164
 
137
- // Store auto-discovery options for later initialization
138
- // IMPORTANT: Auto-discovery is deferred to ensure user middleware (like auth)
139
- // is registered before module middleware that might bypass it
140
- this.autoDiscoveryOptions = options.autoDiscover !== false ? options : null;
165
+ // Auto-discover modules if enabled
166
+ if (options.autoDiscover !== false) {
167
+ this.autoDiscoverModules(options.modulesPath || './modules');
168
+ }
141
169
 
142
170
  // Emit initialization event through enterprise event bus
143
171
  this.eventBus.emit('framework:initialized', {
@@ -366,13 +394,6 @@ export class Moro extends EventEmitter {
366
394
  version: moduleOrPath.version || '1.0.0',
367
395
  });
368
396
  }
369
-
370
- // IMPORTANT: If modules are loaded manually after auto-discovery,
371
- // ensure the final module handler is set up to maintain middleware order
372
- if (this.autoDiscoveryInitialized) {
373
- this.coreFramework.setupFinalModuleHandler();
374
- }
375
-
376
397
  return this;
377
398
  }
378
399
 
@@ -388,45 +409,34 @@ export class Moro extends EventEmitter {
388
409
 
389
410
  // WebSocket helper with events
390
411
  websocket(namespace: string, handlers: Record<string, Function>) {
391
- // Queue the registration to be processed after adapter initialization
392
- const registration = { namespace, handlers, processed: false };
393
- this.queuedWebSocketRegistrations.push(registration);
394
-
395
- // Try to process immediately if adapter is already ready
396
412
  const adapter = this.coreFramework.getWebSocketAdapter();
397
- if (adapter && !registration.processed) {
398
- // Adapter is ready, process immediately
399
- this.processWebSocketRegistration(namespace, handlers, adapter);
400
- registration.processed = true;
413
+ if (!adapter) {
414
+ throw new Error(
415
+ 'WebSocket features require a WebSocket adapter. Install socket.io or configure an adapter:\n' +
416
+ 'npm install socket.io\n' +
417
+ 'or\n' +
418
+ 'new Moro({ websocket: { adapter: new SocketIOAdapter() } })'
419
+ );
401
420
  }
402
- // Otherwise, it will be processed when the server starts
403
-
404
- return this;
405
- }
406
421
 
407
- private processWebSocketRegistration(
408
- namespace: string,
409
- handlers: Record<string, Function>,
410
- adapter: any
411
- ) {
412
422
  this.emit('websocket:registering', { namespace, handlers });
413
423
 
414
424
  const ns = adapter.createNamespace(namespace);
415
425
 
416
426
  Object.entries(handlers).forEach(([event, handler]) => {
417
- ns.on('connection', (socket: any) => {
427
+ ns.on('connection', socket => {
418
428
  this.emit('websocket:connection', { namespace, event, socket });
419
429
 
420
- socket.on(event, (data: any, callback: any) => {
430
+ socket.on(event, (data, callback) => {
421
431
  this.emit('websocket:event', { namespace, event, data });
422
432
 
423
433
  Promise.resolve(handler(socket, data))
424
- .then((result: any) => {
434
+ .then(result => {
425
435
  this.emit('websocket:response', { namespace, event, result });
426
436
  if (callback) callback(result);
427
437
  else if (result) socket.emit(`${event}:response`, result);
428
438
  })
429
- .catch((error: any) => {
439
+ .catch(error => {
430
440
  this.emit('websocket:error', { namespace, event, error });
431
441
  const errorResponse = { success: false, error: error.message };
432
442
  if (callback) callback(errorResponse);
@@ -437,40 +447,7 @@ export class Moro extends EventEmitter {
437
447
  });
438
448
 
439
449
  this.emit('websocket:registered', { namespace, handlers });
440
- }
441
-
442
- private async processQueuedWebSocketRegistrations() {
443
- // Wait for WebSocket adapter to be ready
444
- await this.coreFramework.ensureWebSocketReady();
445
-
446
- const adapter = this.coreFramework.getWebSocketAdapter();
447
-
448
- // Check if any unprocessed registrations exist
449
- const unprocessedRegistrations = this.queuedWebSocketRegistrations.filter(r => !r.processed);
450
-
451
- if (!adapter && unprocessedRegistrations.length > 0) {
452
- throw new Error(
453
- 'WebSocket features require a WebSocket adapter.\n\n' +
454
- 'Option 1: Install socket.io (auto-detected):\n' +
455
- ' npm install socket.io\n' +
456
- ' const app = new Moro({ websocket: {} });\n\n' +
457
- 'Option 2: Configure a specific adapter:\n' +
458
- " import { SocketIOAdapter } from '@morojs/moro';\n" +
459
- ' const app = new Moro({ websocket: { adapter: new SocketIOAdapter() } });\n\n' +
460
- 'Option 3: Enable in config file (moro.config.js):\n' +
461
- ' export default { websocket: { enabled: true } };'
462
- );
463
- }
464
-
465
- if (adapter) {
466
- // Process all unprocessed registrations
467
- for (const registration of this.queuedWebSocketRegistrations) {
468
- if (!registration.processed) {
469
- this.processWebSocketRegistration(registration.namespace, registration.handlers, adapter);
470
- registration.processed = true;
471
- }
472
- }
473
- }
450
+ return this;
474
451
  }
475
452
 
476
453
  // Start server with events (Node.js only)
@@ -526,21 +503,9 @@ export class Moro extends EventEmitter {
526
503
  }
527
504
 
528
505
  // Check if clustering is enabled for massive performance gains
529
- // NOTE: uWebSockets.js does NOT support Node.js clustering - it's single-threaded only
530
- const usingUWebSockets = this.config.server?.useUWebSockets || false;
531
-
532
506
  if (this.config.performance?.clustering?.enabled) {
533
- if (usingUWebSockets) {
534
- this.logger.warn(
535
- 'Clustering is not supported with uWebSockets.js - running in single-threaded mode. ' +
536
- 'uWebSockets is so fast that single-threaded performance often exceeds multi-threaded Node.js!',
537
- 'Cluster'
538
- );
539
- // Continue without clustering
540
- } else {
541
- this.startWithClustering(port, host as string, callback);
542
- return;
543
- }
507
+ this.startWithClustering(port, host as string, callback);
508
+ return;
544
509
  }
545
510
  this.eventBus.emit('server:starting', { port, runtime: this.runtimeType });
546
511
 
@@ -570,169 +535,34 @@ export class Moro extends EventEmitter {
570
535
  this.registerDirectRoutes();
571
536
  }
572
537
 
573
- const startServer = () => {
574
- const actualCallback = () => {
575
- const displayHost = host || 'localhost';
576
- this.logger.info('Moro Server Started', 'Server');
577
- this.logger.info(`Runtime: ${this.runtimeType}`, 'Server');
578
- this.logger.info(`HTTP API: http://${displayHost}:${port}`, 'Server');
579
- if (this.config.websocket.enabled) {
580
- this.logger.info(`WebSocket: ws://${displayHost}:${port}`, 'Server');
581
- }
582
- this.logger.info('Learn more at https://morojs.com', 'Server');
583
-
584
- // Log intelligent routes info
585
- const intelligentRoutes = this.intelligentRouting.getIntelligentRoutes();
586
- if (intelligentRoutes.length > 0) {
587
- this.logger.info(`Intelligent Routes: ${intelligentRoutes.length} registered`, 'Server');
588
- }
589
-
590
- this.eventBus.emit('server:started', { port, runtime: this.runtimeType });
591
- if (callback) callback();
592
- };
593
-
594
- if (host && typeof host === 'string') {
595
- this.coreFramework.listen(port, host, actualCallback);
596
- } else {
597
- this.coreFramework.listen(port, actualCallback);
538
+ const actualCallback = () => {
539
+ const displayHost = host || 'localhost';
540
+ this.logger.info('Moro Server Started', 'Server');
541
+ this.logger.info(`Runtime: ${this.runtimeType}`, 'Server');
542
+ this.logger.info(`HTTP API: http://${displayHost}:${port}`, 'Server');
543
+ this.logger.info(`WebSocket: ws://${displayHost}:${port}`, 'Server');
544
+ this.logger.info('Native Node.js HTTP • Zero Dependencies • Maximum Performance', 'Server');
545
+ this.logger.info('Learn more at https://morojs.com', 'Server');
546
+
547
+ // Log intelligent routes info
548
+ const intelligentRoutes = this.intelligentRouting.getIntelligentRoutes();
549
+ if (intelligentRoutes.length > 0) {
550
+ this.logger.info(`Intelligent Routes: ${intelligentRoutes.length} registered`, 'Server');
598
551
  }
599
- };
600
552
 
601
- // Ensure auto-discovery and WebSocket setup is complete before starting server
602
- Promise.all([this.ensureAutoDiscoveryComplete(), this.processQueuedWebSocketRegistrations()])
603
- .then(() => {
604
- startServer();
605
- })
606
- .catch(error => {
607
- this.logger.error('Initialization failed during server start', 'Framework', {
608
- error: error instanceof Error ? error.message : String(error),
609
- });
610
- // For auto-discovery failures, start server anyway
611
- // For WebSocket failures with queued registrations, error will propagate
612
- if (
613
- error instanceof Error &&
614
- error.message.includes('WebSocket features require a WebSocket adapter')
615
- ) {
616
- throw error;
617
- }
618
- startServer();
619
- });
620
- }
621
-
622
- // Public method to manually initialize auto-discovery
623
- // Useful for ensuring auth middleware is registered before auto-discovery
624
- async initializeAutoDiscoveryNow(): Promise<void> {
625
- return this.ensureAutoDiscoveryComplete();
626
- }
627
-
628
- // Public API: Initialize modules explicitly after middleware setup
629
- // This provides users with explicit control over module loading timing
630
- // IMPORTANT: This forces module loading even if autoDiscovery.enabled is false
631
- // Usage: app.initModules() or app.initModules({ paths: ['./my-modules'] })
632
- initModules(options?: {
633
- paths?: string[];
634
- patterns?: string[];
635
- recursive?: boolean;
636
- loadingStrategy?: 'eager' | 'lazy' | 'conditional';
637
- watchForChanges?: boolean;
638
- ignorePatterns?: string[];
639
- loadOrder?: 'alphabetical' | 'dependency' | 'custom';
640
- failOnError?: boolean;
641
- maxDepth?: number;
642
- }): void {
643
- this.logger.info('User-requested module initialization', 'ModuleSystem');
644
-
645
- // If already initialized, do nothing
646
- if (this.autoDiscoveryInitialized) {
647
- this.logger.debug('Auto-discovery already completed, skipping', 'ModuleSystem');
648
- return;
649
- }
650
-
651
- // Store the options and mark that we want to force initialization
652
- this.autoDiscoveryOptions = {
653
- autoDiscover: {
654
- enabled: true, // Force enabled regardless of original config
655
- paths: options?.paths || ['./modules', './src/modules'],
656
- patterns: options?.patterns || [
657
- '**/*.module.{ts,js}',
658
- '**/index.{ts,js}',
659
- '**/*.config.{ts,js}',
660
- ],
661
- recursive: options?.recursive ?? true,
662
- loadingStrategy: options?.loadingStrategy || ('eager' as const),
663
- watchForChanges: options?.watchForChanges ?? false,
664
- ignorePatterns: options?.ignorePatterns || [
665
- '**/*.test.{ts,js}',
666
- '**/*.spec.{ts,js}',
667
- '**/node_modules/**',
668
- ],
669
- loadOrder: options?.loadOrder || ('dependency' as const),
670
- failOnError: options?.failOnError ?? false,
671
- maxDepth: options?.maxDepth ?? 5,
672
- },
553
+ this.eventBus.emit('server:started', { port, runtime: this.runtimeType });
554
+ if (callback) callback();
673
555
  };
674
556
 
675
- this.logger.debug(
676
- 'Module initialization options stored, will execute on next listen/getHandler call',
677
- 'ModuleSystem'
678
- );
679
- }
680
-
681
- // Robust method to ensure auto-discovery is complete, handling race conditions
682
- private async ensureAutoDiscoveryComplete(): Promise<void> {
683
- // If already initialized, nothing to do
684
- if (this.autoDiscoveryInitialized) {
685
- return;
686
- }
687
-
688
- // If auto-discovery is disabled, mark as initialized
689
- if (!this.autoDiscoveryOptions) {
690
- this.autoDiscoveryInitialized = true;
691
- return;
692
- }
693
-
694
- // If already in progress, wait for it to complete
695
- if (this.autoDiscoveryPromise) {
696
- return this.autoDiscoveryPromise;
697
- }
698
-
699
- // Start auto-discovery
700
- this.autoDiscoveryPromise = this.performAutoDiscovery();
701
-
702
- try {
703
- await this.autoDiscoveryPromise;
704
- this.autoDiscoveryInitialized = true;
705
- } catch (error) {
706
- // Reset promise on error so it can be retried
707
- this.autoDiscoveryPromise = null;
708
- throw error;
709
- } finally {
710
- this.autoDiscoveryOptions = null; // Clear after attempt
557
+ if (host && typeof host === 'string') {
558
+ this.coreFramework.listen(port, host, actualCallback);
559
+ } else {
560
+ this.coreFramework.listen(port, actualCallback);
711
561
  }
712
562
  }
713
563
 
714
- // Perform the actual auto-discovery work
715
- private async performAutoDiscovery(optionsOverride?: MoroOptions): Promise<void> {
716
- const optionsToUse = optionsOverride || this.autoDiscoveryOptions;
717
- if (!optionsToUse) return;
718
-
719
- this.logger.debug('Starting auto-discovery initialization', 'AutoDiscovery');
720
-
721
- await this.initializeAutoDiscovery(optionsToUse);
722
-
723
- this.logger.debug('Auto-discovery initialization completed', 'AutoDiscovery');
724
- }
725
-
726
564
  // Get handler for non-Node.js runtimes
727
565
  getHandler() {
728
- // Ensure auto-discovery is complete for non-Node.js runtimes
729
- // This handles the case where users call getHandler() immediately after createApp()
730
- this.ensureAutoDiscoveryComplete().catch(error => {
731
- this.logger.error('Auto-discovery initialization failed for runtime handler', 'Framework', {
732
- error: error instanceof Error ? error.message : String(error),
733
- });
734
- });
735
-
736
566
  // Create a unified request handler that works with the runtime adapter
737
567
  const handler = async (req: HttpRequest, res: HttpResponse) => {
738
568
  // Add documentation middleware first (if enabled)
@@ -977,6 +807,7 @@ export class Moro extends EventEmitter {
977
807
  req.body = validated;
978
808
  } catch (error: any) {
979
809
  // Handle universal validation errors
810
+ const { normalizeValidationError } = require('./core/validation/schema-interface');
980
811
  const normalizedError = normalizeValidationError(error);
981
812
  res.status(400).json({
982
813
  success: false,
@@ -1055,33 +886,20 @@ export class Moro extends EventEmitter {
1055
886
  }
1056
887
 
1057
888
  private setupDefaultMiddleware(options: MoroOptions) {
1058
- // CORS - check config enabled property OR options.security.cors.enabled === true
1059
- if (this.config.security.cors.enabled || options.security?.cors?.enabled === true) {
1060
- const corsOptions =
1061
- typeof options.cors === 'object'
1062
- ? options.cors
1063
- : this.config.security.cors
1064
- ? this.config.security.cors
1065
- : {};
889
+ // CORS
890
+ if (options.cors !== false) {
891
+ const corsOptions = typeof options.cors === 'object' ? options.cors : {};
1066
892
  this.use(middleware.cors(corsOptions));
1067
893
  }
1068
894
 
1069
- // Helmet - check config enabled property OR options.security.helmet.enabled === true
1070
- if (this.config.security.helmet.enabled || options.security?.helmet?.enabled === true) {
895
+ // Helmet
896
+ if (options.helmet !== false) {
1071
897
  this.use(middleware.helmet());
1072
898
  }
1073
899
 
1074
- // Compression - check config enabled property OR options.performance.compression.enabled === true
1075
- if (
1076
- this.config.performance.compression.enabled ||
1077
- options.performance?.compression?.enabled === true
1078
- ) {
1079
- const compressionOptions =
1080
- typeof options.compression === 'object'
1081
- ? options.compression
1082
- : this.config.performance.compression
1083
- ? this.config.performance.compression
1084
- : {};
900
+ // Compression
901
+ if (options.compression !== false) {
902
+ const compressionOptions = typeof options.compression === 'object' ? options.compression : {};
1085
903
  this.use(middleware.compression(compressionOptions));
1086
904
  }
1087
905
 
@@ -1089,298 +907,83 @@ export class Moro extends EventEmitter {
1089
907
  this.use(middleware.bodySize({ limit: '10mb' }));
1090
908
  }
1091
909
 
1092
- // Enhanced auto-discovery initialization
1093
- private async initializeAutoDiscovery(options: MoroOptions): Promise<void> {
1094
- const { ModuleDiscovery } = await import('./core/modules/auto-discovery.js');
1095
-
1096
- // Merge auto-discovery configuration
1097
- const autoDiscoveryConfig = this.mergeAutoDiscoveryConfig(options);
1098
-
1099
- if (!autoDiscoveryConfig.enabled) {
1100
- return;
1101
- }
1102
-
1103
- this.moduleDiscovery = new ModuleDiscovery(process.cwd());
1104
-
910
+ private autoDiscoverModules(modulesPath: string) {
1105
911
  try {
1106
- // Discover modules based on configuration
1107
- const modules = await this.moduleDiscovery.discoverModulesAdvanced(autoDiscoveryConfig);
1108
-
1109
- // Load modules based on strategy
1110
- await this.loadDiscoveredModules(modules, autoDiscoveryConfig);
1111
-
1112
- // Setup final module handler to run after user middleware (like auth)
1113
- this.coreFramework.setupFinalModuleHandler();
1114
-
1115
- // Setup file watching if enabled
1116
- if (autoDiscoveryConfig.watchForChanges) {
1117
- this.moduleDiscovery.watchModulesAdvanced(
1118
- autoDiscoveryConfig,
1119
- async (updatedModules: ModuleConfig[]) => {
1120
- await this.handleModuleChanges(updatedModules);
912
+ if (!statSync(modulesPath).isDirectory()) return;
913
+
914
+ const items = readdirSync(modulesPath);
915
+ items.forEach(item => {
916
+ const fullPath = join(modulesPath, item);
917
+ if (statSync(fullPath).isDirectory()) {
918
+ const indexPath = join(fullPath, 'index.ts');
919
+ try {
920
+ statSync(indexPath);
921
+ // Module directory found, will be loaded later
922
+ this.logger.debug(`Discovered module: ${item}`, 'ModuleDiscovery');
923
+ } catch {
924
+ // No index.ts, skip
1121
925
  }
1122
- );
1123
- }
1124
-
1125
- this.logger.info(
1126
- `Auto-discovery completed: ${modules.length} modules loaded`,
1127
- 'ModuleDiscovery'
1128
- );
1129
- } catch (error) {
1130
- const errorMsg = error instanceof Error ? error.message : String(error);
1131
-
1132
- if (autoDiscoveryConfig.failOnError) {
1133
- throw new Error(`Module auto-discovery failed: ${errorMsg}`);
1134
- } else {
1135
- this.logger.warn(`Module auto-discovery failed: ${errorMsg}`, 'ModuleDiscovery');
1136
- }
1137
- }
1138
- }
1139
-
1140
- // Merge auto-discovery configuration from multiple sources
1141
- private mergeAutoDiscoveryConfig(options: MoroOptions) {
1142
- const defaultConfig = this.config.modules.autoDiscovery;
1143
-
1144
- // Handle legacy modulesPath option
1145
- if (options.modulesPath && !options.autoDiscover) {
1146
- return {
1147
- ...defaultConfig,
1148
- paths: [options.modulesPath],
1149
- };
1150
- }
1151
-
1152
- // Handle boolean autoDiscover option
1153
- if (typeof options.autoDiscover === 'boolean') {
1154
- return {
1155
- ...defaultConfig,
1156
- enabled: options.autoDiscover,
1157
- };
1158
- }
1159
-
1160
- // Handle object autoDiscover option
1161
- if (typeof options.autoDiscover === 'object') {
1162
- return {
1163
- ...defaultConfig,
1164
- ...options.autoDiscover,
1165
- };
1166
- }
1167
-
1168
- return defaultConfig;
1169
- }
1170
-
1171
- // Load discovered modules based on strategy
1172
- private async loadDiscoveredModules(
1173
- modules: ModuleConfig[],
1174
- config: ModuleDefaultsConfig['autoDiscovery']
1175
- ): Promise<void> {
1176
- switch (config.loadingStrategy) {
1177
- case 'eager':
1178
- // Load all modules immediately
1179
- for (const module of modules) {
1180
- await this.loadModule(module);
1181
- }
1182
- break;
1183
-
1184
- case 'lazy':
1185
- // Register modules for lazy loading
1186
- this.registerLazyModules(modules);
1187
- break;
1188
-
1189
- case 'conditional':
1190
- // Load modules based on conditions
1191
- await this.loadConditionalModules(modules);
1192
- break;
1193
-
1194
- default:
1195
- // Default to eager loading
1196
- for (const module of modules) {
1197
- await this.loadModule(module);
1198
926
  }
927
+ });
928
+ } catch {
929
+ // Modules directory doesn't exist, that's fine
1199
930
  }
1200
931
  }
1201
932
 
1202
- // Register modules for lazy loading
1203
- private registerLazyModules(modules: ModuleConfig[]): void {
1204
- modules.forEach(module => {
1205
- // Store module for lazy loading when first route is accessed
1206
- this.lazyModules.set(module.name, module);
1207
-
1208
- // Register placeholder routes that trigger lazy loading
1209
- if (module.routes) {
1210
- module.routes.forEach(route => {
1211
- const basePath = `/api/v${module.version}/${module.name}`;
1212
- const fullPath = `${basePath}${route.path}`;
1213
-
1214
- // Note: Lazy loading will be implemented when route is accessed
1215
- // For now, we'll store the module for later loading
1216
- this.logger.debug(
1217
- `Registered lazy route: ${route.method} ${fullPath}`,
1218
- 'ModuleDiscovery'
1219
- );
1220
- });
1221
- }
1222
- });
1223
-
1224
- this.logger.info(`Registered ${modules.length} modules for lazy loading`, 'ModuleDiscovery');
1225
- }
1226
-
1227
- // Load modules conditionally based on environment or configuration
1228
- private async loadConditionalModules(modules: ModuleConfig[]): Promise<void> {
1229
- for (const module of modules) {
1230
- const shouldLoad = this.shouldLoadModule(module);
1231
-
1232
- if (shouldLoad) {
1233
- await this.loadModule(module);
1234
- } else {
1235
- this.logger.debug(`Skipping module ${module.name} due to conditions`, 'ModuleDiscovery');
1236
- }
1237
- }
1238
- }
1239
-
1240
- // Determine if a module should be loaded based on conditions
1241
- private shouldLoadModule(module: ModuleConfig): boolean {
1242
- const moduleConfig = module.config as any;
1243
-
1244
- // Check environment conditions
1245
- if (moduleConfig?.conditions?.environment) {
1246
- const requiredEnv = moduleConfig.conditions.environment;
1247
- const currentEnv = process.env.NODE_ENV || 'development';
1248
-
1249
- if (Array.isArray(requiredEnv)) {
1250
- if (!requiredEnv.includes(currentEnv)) {
1251
- return false;
1252
- }
1253
- } else if (requiredEnv !== currentEnv) {
1254
- return false;
1255
- }
1256
- }
1257
-
1258
- // Check feature flags
1259
- if (moduleConfig?.conditions?.features) {
1260
- const requiredFeatures = moduleConfig.conditions.features;
1261
-
1262
- for (const feature of requiredFeatures) {
1263
- if (!process.env[`FEATURE_${feature.toUpperCase()}`]) {
1264
- return false;
1265
- }
1266
- }
1267
- }
1268
-
1269
- // Check custom conditions
1270
- if (moduleConfig?.conditions?.custom) {
1271
- const customCondition = moduleConfig.conditions.custom;
1272
-
1273
- if (typeof customCondition === 'function') {
1274
- return customCondition();
1275
- }
1276
- }
1277
-
1278
- return true;
1279
- }
1280
-
1281
- // Handle module changes during development
1282
- private async handleModuleChanges(modules: ModuleConfig[]): Promise<void> {
1283
- this.logger.info('Module changes detected, reloading...', 'ModuleDiscovery');
1284
-
1285
- // Unload existing modules (if supported)
1286
- // For now, just log the change
1287
- this.eventBus.emit('modules:changed', {
1288
- modules: modules.map(m => ({ name: m.name, version: m.version })),
1289
- timestamp: new Date(),
1290
- });
1291
- }
1292
-
1293
- // Legacy method for backward compatibility
1294
- private autoDiscoverModules(modulesPath: string) {
1295
- // Redirect to new system
1296
- this.initializeAutoDiscovery({
1297
- autoDiscover: {
1298
- enabled: true,
1299
- paths: [modulesPath],
1300
- },
1301
- });
1302
- }
1303
-
1304
933
  private async importModule(modulePath: string): Promise<ModuleConfig> {
1305
934
  const module = await import(modulePath);
1306
935
  return module.default || module;
1307
936
  }
1308
937
 
1309
- /**
1310
- * Node.js Clustering Implementation
1311
- * This clustering algorithm is based on published research and Node.js best practices.
1312
- *
1313
- * IPC (Inter-Process Communication) Considerations:
1314
- * - Excessive workers create IPC bottlenecks (Source: BetterStack Node.js Guide)
1315
- * - Round-robin scheduling provides better load distribution (Node.js Documentation)
1316
- * - Message passing overhead increases significantly with worker count
1317
- *
1318
- * Memory Management:
1319
- * - ~2GB per worker prevents memory pressure and GC overhead
1320
- * - Conservative heap limits reduce memory fragmentation
1321
- *
1322
- * References:
1323
- * - Node.js Cluster Documentation: https://nodejs.org/api/cluster.html
1324
- * - BetterStack Node.js Clustering: https://betterstack.com/community/guides/scaling-nodejs/node-clustering/
1325
- */
938
+ // Clustering support for massive performance gains with proper cleanup
1326
939
  private clusterWorkers = new Map<number, any>();
1327
-
1328
940
  private startWithClustering(port: number, host?: string, callback?: () => void): void {
1329
- // Worker count calculation - respect user choice
941
+ const cluster = require('cluster');
942
+ const os = require('os');
943
+
944
+ // Smart worker count calculation based on actual bottlenecks
1330
945
  let workerCount = this.config.performance?.clustering?.workers || os.cpus().length;
1331
946
 
1332
- // Only auto-optimize if user hasn't specified a number or set it to 'auto'
1333
- if (workerCount === 'auto') {
947
+ // Auto-optimize worker count based on system characteristics
948
+ if (workerCount === 'auto' || workerCount > 8) {
949
+ // For high-core machines, limit workers to prevent IPC/memory bottlenecks
1334
950
  const cpuCount = os.cpus().length;
1335
951
  const totalMemoryGB = os.totalmem() / (1024 * 1024 * 1024);
1336
952
 
1337
- // Get memory per worker from config - if not set by user, calculate dynamically
1338
- let memoryPerWorkerGB = this.config.performance?.clustering?.memoryPerWorkerGB;
1339
-
1340
- if (!memoryPerWorkerGB) {
1341
- // Dynamic calculation: (Total RAM - 4GB headroom) / CPU cores
1342
- const headroomGB = 4;
1343
- memoryPerWorkerGB = Math.max(0.5, Math.floor((totalMemoryGB - headroomGB) / cpuCount));
953
+ // Optimal worker count formula based on research
954
+ if (cpuCount >= 16) {
955
+ // High-core machines: focus on memory/IPC efficiency
956
+ workerCount = Math.min(Math.ceil(totalMemoryGB / 2), 4); // 2GB per worker max, cap at 4
957
+ } else if (cpuCount >= 8) {
958
+ // Mid-range machines: balanced approach
959
+ workerCount = Math.min(cpuCount / 2, 4);
960
+ } else {
961
+ // Low-core machines: use all cores
962
+ workerCount = cpuCount;
1344
963
  }
1345
964
 
1346
- // Conservative formula based on general guidelines:
1347
- // - Don't exceed CPU cores
1348
- // - Respect user's memory allocation preference
1349
- // - Let the system resources determine the limit
1350
- workerCount = Math.min(
1351
- cpuCount, // Don't exceed CPU cores
1352
- Math.floor(totalMemoryGB / memoryPerWorkerGB) // User-configurable memory per worker
1353
- );
1354
-
1355
965
  this.logger.info(
1356
- `Auto-calculated worker count: ${workerCount} (CPU: ${cpuCount}, RAM: ${totalMemoryGB.toFixed(1)}GB, ${memoryPerWorkerGB}GB per worker)`,
966
+ `Auto-optimized workers: ${workerCount} (CPU: ${cpuCount}, RAM: ${totalMemoryGB.toFixed(1)}GB)`,
1357
967
  'Cluster'
1358
968
  );
1359
- } else if (typeof workerCount === 'number') {
1360
- // User specified a number - respect their choice
1361
- this.logger.info(`Using user-specified worker count: ${workerCount}`, 'Cluster');
1362
969
  }
1363
970
 
1364
971
  if (cluster.isPrimary) {
1365
- this.logger.info(`Starting ${workerCount} workers`, 'Cluster');
972
+ this.logger.info(`🚀 Starting ${workerCount} workers for maximum performance`, 'Cluster');
1366
973
 
1367
974
  // Optimize cluster scheduling for high concurrency
1368
- // Round-robin is the default on all platforms except Windows (Node.js docs)
1369
- // Provides better load distribution than shared socket approach
1370
- cluster.schedulingPolicy = cluster.SCHED_RR;
975
+ cluster.schedulingPolicy = cluster.SCHED_RR; // Round-robin scheduling
1371
976
 
1372
977
  // Set cluster settings for better performance
1373
978
  cluster.setupMaster({
1374
- exec: process.argv[1] || process.execPath,
979
+ exec: process.argv[1],
1375
980
  args: process.argv.slice(2),
1376
981
  silent: false,
1377
982
  });
1378
983
 
1379
- // IPC Optimization: Reduce communication overhead between master and workers
1380
- // Research shows excessive IPC can create bottlenecks in clustered applications
1381
- // (Source: BetterStack - Node.js Clustering Guide)
984
+ // Optimize IPC to reduce communication overhead
1382
985
  process.env.NODE_CLUSTER_SCHED_POLICY = 'rr'; // Ensure round-robin
1383
- process.env.NODE_DISABLE_COLORS = '1'; // Reduce IPC message size by disabling color codes
986
+ process.env.NODE_DISABLE_COLORS = '1'; // Reduce IPC message size
1384
987
 
1385
988
  // Graceful shutdown handler
1386
989
  const gracefulShutdown = () => {
@@ -1401,32 +1004,37 @@ export class Moro extends EventEmitter {
1401
1004
  process.on('SIGINT', gracefulShutdown);
1402
1005
  process.on('SIGTERM', gracefulShutdown);
1403
1006
 
1404
- // Fork workers with basic tracking
1007
+ // Fork workers with proper tracking and CPU affinity
1405
1008
  for (let i = 0; i < workerCount; i++) {
1406
- const worker = cluster.fork();
1009
+ const worker = cluster.fork({
1010
+ WORKER_ID: i,
1011
+ WORKER_CPU_AFFINITY: i % os.cpus().length, // Distribute workers across CPUs
1012
+ });
1407
1013
  this.clusterWorkers.set(worker.process.pid!, worker);
1408
- this.logger.info(`Worker ${worker.process.pid} started`, 'Cluster');
1014
+ this.logger.info(
1015
+ `Worker ${worker.process.pid} started (CPU ${i % os.cpus().length})`,
1016
+ 'Cluster'
1017
+ );
1409
1018
 
1410
- // Handle individual worker messages
1019
+ // Handle individual worker messages (reuse handler)
1411
1020
  worker.on('message', this.handleWorkerMessage.bind(this));
1412
1021
  }
1413
1022
 
1414
- // Simple worker exit handling
1023
+ // Handle worker exits with cleanup
1415
1024
  cluster.on('exit', (worker: any, code: number, signal: string) => {
1416
- const pid = worker.process.pid;
1417
- this.clusterWorkers.delete(pid);
1418
-
1419
- if (code !== 0 && !worker.exitedAfterDisconnect) {
1420
- this.logger.warn(
1421
- `Worker ${pid} died unexpectedly (${signal || code}). Restarting...`,
1422
- 'Cluster'
1423
- );
1424
-
1425
- // Simple restart
1426
- const newWorker = cluster.fork();
1427
- this.clusterWorkers.set(newWorker.process.pid!, newWorker);
1428
- this.logger.info(`Worker ${newWorker.process.pid} restarted`, 'Cluster');
1429
- }
1025
+ // Clean up worker tracking
1026
+ this.clusterWorkers.delete(worker.process.pid);
1027
+
1028
+ this.logger.warn(
1029
+ `Worker ${worker.process.pid} died (${signal || code}). Restarting...`,
1030
+ 'Cluster'
1031
+ );
1032
+
1033
+ // Restart worker with proper tracking
1034
+ const newWorker = cluster.fork();
1035
+ this.clusterWorkers.set(newWorker.process.pid!, newWorker);
1036
+ newWorker.on('message', this.handleWorkerMessage.bind(this));
1037
+ this.logger.info(`Worker ${newWorker.process.pid} started`, 'Cluster');
1430
1038
  });
1431
1039
 
1432
1040
  // Master process callback
@@ -1439,28 +1047,13 @@ export class Moro extends EventEmitter {
1439
1047
  process.env.UV_THREADPOOL_SIZE = '64';
1440
1048
 
1441
1049
  // Reduce logging contention in workers (major bottleneck)
1442
- // Multiple workers writing to same log files creates I/O contention
1443
1050
  if (this.config.logging) {
1444
1051
  // Workers log less frequently to reduce I/O contention
1445
- applyLoggingConfiguration(undefined, { level: 'warn' }); // Only warnings and errors
1052
+ this.config.logging.level = 'warn'; // Only warnings and errors
1446
1053
  }
1447
1054
 
1448
- // Research-based memory optimization for workers
1449
- const totalMemoryGB = os.totalmem() / (1024 * 1024 * 1024);
1450
- const workerCount = Object.keys(cluster.workers || {}).length || 1;
1451
-
1452
- // Conservative memory allocation
1453
- const heapSizePerWorkerMB = Math.min(
1454
- Math.floor(((totalMemoryGB * 1024) / workerCount) * 0.8), // 80% of available memory
1455
- 1536 // Cap at 1.5GB (GC efficiency threshold from research)
1456
- );
1457
-
1458
- process.env.NODE_OPTIONS = `--max-old-space-size=${heapSizePerWorkerMB}`;
1459
-
1460
- this.logger.debug(
1461
- `Worker memory allocated: ${heapSizePerWorkerMB}MB heap (${workerCount} workers, ${totalMemoryGB.toFixed(1)}GB total)`,
1462
- 'Worker'
1463
- );
1055
+ // Memory optimization for workers
1056
+ process.env.NODE_OPTIONS = '--max-old-space-size=1024'; // Limit memory per worker
1464
1057
 
1465
1058
  // Optimize V8 flags for better performance (Rust-level optimizations)
1466
1059
  if (process.env.NODE_ENV === 'production') {
@@ -1548,37 +1141,15 @@ export class Moro extends EventEmitter {
1548
1141
  });
1549
1142
  };
1550
1143
 
1551
- // Ensure WebSocket setup is complete before starting worker
1552
- this.processQueuedWebSocketRegistrations()
1553
- .then(() => {
1554
- if (host) {
1555
- this.coreFramework.listen(port, host, workerCallback);
1556
- } else {
1557
- this.coreFramework.listen(port, workerCallback);
1558
- }
1559
- })
1560
- .catch(error => {
1561
- this.logger.error('WebSocket initialization failed in worker', 'Worker', {
1562
- error: error instanceof Error ? error.message : String(error),
1563
- });
1564
- // For WebSocket failures with queued registrations, error will propagate
1565
- if (
1566
- error instanceof Error &&
1567
- error.message.includes('WebSocket features require a WebSocket adapter')
1568
- ) {
1569
- throw error;
1570
- }
1571
- // Start anyway for other errors
1572
- if (host) {
1573
- this.coreFramework.listen(port, host, workerCallback);
1574
- } else {
1575
- this.coreFramework.listen(port, workerCallback);
1576
- }
1577
- });
1144
+ if (host) {
1145
+ this.coreFramework.listen(port, host, workerCallback);
1146
+ } else {
1147
+ this.coreFramework.listen(port, workerCallback);
1148
+ }
1578
1149
  }
1579
1150
  }
1580
1151
 
1581
- // Simple worker message handler
1152
+ // Reusable worker message handler (avoids creating new functions)
1582
1153
  private handleWorkerMessage(message: any): void {
1583
1154
  // Handle inter-worker communication if needed
1584
1155
  if (message.type === 'health-check') {
@@ -1589,58 +1160,6 @@ export class Moro extends EventEmitter {
1589
1160
  // Log other worker messages
1590
1161
  this.logger.debug(`Worker message: ${JSON.stringify(message)}`, 'Cluster');
1591
1162
  }
1592
-
1593
- /**
1594
- * Gracefully close the application and clean up resources
1595
- * This should be called in tests and during shutdown
1596
- */
1597
- async close(): Promise<void> {
1598
- this.logger.debug('Closing Moro application...');
1599
-
1600
- // Flush logger buffer before shutdown
1601
- try {
1602
- // Use flushBuffer for immediate synchronous flush
1603
- this.logger.flushBuffer();
1604
- } catch (error) {
1605
- // Ignore flush errors during shutdown
1606
- }
1607
-
1608
- // Close the core framework with timeout
1609
- if (this.coreFramework && (this.coreFramework as any).httpServer) {
1610
- try {
1611
- await Promise.race([
1612
- new Promise<void>(resolve => {
1613
- (this.coreFramework as any).httpServer.close(() => {
1614
- resolve();
1615
- });
1616
- }),
1617
- new Promise<void>(resolve => setTimeout(resolve, 2000)), // 2 second timeout
1618
- ]);
1619
- } catch (error) {
1620
- // Force close if graceful close fails
1621
- this.logger.warn('Force closing HTTP server due to timeout');
1622
- }
1623
- }
1624
-
1625
- // Clean up module discovery watchers
1626
- if (this.moduleDiscovery && typeof this.moduleDiscovery.cleanup === 'function') {
1627
- try {
1628
- this.moduleDiscovery.cleanup();
1629
- } catch (error) {
1630
- // Ignore cleanup errors
1631
- }
1632
- }
1633
-
1634
- // Clean up event listeners
1635
- try {
1636
- this.eventBus.removeAllListeners();
1637
- this.removeAllListeners();
1638
- } catch (error) {
1639
- // Ignore cleanup errors
1640
- }
1641
-
1642
- this.logger.debug('Moro application closed successfully');
1643
- }
1644
1163
  }
1645
1164
 
1646
1165
  // Export convenience function