@morojs/moro 1.7.30 → 1.8.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 (373) hide show
  1. package/README.md +89 -46
  2. package/dist/core/auth/morojs-adapter.js +95 -45
  3. package/dist/core/auth/morojs-adapter.js.map +1 -1
  4. package/dist/core/config/config-manager.js.map +1 -1
  5. package/dist/core/config/config-sources.js +119 -48
  6. package/dist/core/config/config-sources.js.map +1 -1
  7. package/dist/core/config/config-validator.js +189 -8
  8. package/dist/core/config/config-validator.js.map +1 -1
  9. package/dist/core/config/file-loader.js.map +1 -1
  10. package/dist/core/config/index.js.map +1 -1
  11. package/dist/core/config/schema.js +35 -4
  12. package/dist/core/config/schema.js.map +1 -1
  13. package/dist/core/config/utils.js.map +1 -1
  14. package/dist/core/database/adapters/drizzle.js +2 -2
  15. package/dist/core/database/adapters/drizzle.js.map +1 -1
  16. package/dist/core/database/adapters/index.js.map +1 -1
  17. package/dist/core/database/adapters/mongodb.d.ts +1 -0
  18. package/dist/core/database/adapters/mongodb.js +16 -0
  19. package/dist/core/database/adapters/mongodb.js.map +1 -1
  20. package/dist/core/database/adapters/mysql.d.ts +1 -0
  21. package/dist/core/database/adapters/mysql.js +13 -2
  22. package/dist/core/database/adapters/mysql.js.map +1 -1
  23. package/dist/core/database/adapters/postgresql.js +2 -2
  24. package/dist/core/database/adapters/postgresql.js.map +1 -1
  25. package/dist/core/database/adapters/redis.js.map +1 -1
  26. package/dist/core/database/adapters/sql-safety.js +5 -4
  27. package/dist/core/database/adapters/sql-safety.js.map +1 -1
  28. package/dist/core/database/adapters/sqlite.js.map +1 -1
  29. package/dist/core/database/index.js.map +1 -1
  30. package/dist/core/docs/index.js +11 -7
  31. package/dist/core/docs/index.js.map +1 -1
  32. package/dist/core/docs/openapi-generator.js +8 -6
  33. package/dist/core/docs/openapi-generator.js.map +1 -1
  34. package/dist/core/docs/schema-to-openapi.js +3 -3
  35. package/dist/core/docs/schema-to-openapi.js.map +1 -1
  36. package/dist/core/docs/simple-docs.js.map +1 -1
  37. package/dist/core/docs/swagger-ui.js.map +1 -1
  38. package/dist/core/docs/zod-to-openapi.js +2 -2
  39. package/dist/core/docs/zod-to-openapi.js.map +1 -1
  40. package/dist/core/events/event-bus.js +14 -5
  41. package/dist/core/events/event-bus.js.map +1 -1
  42. package/dist/core/events/index.js.map +1 -1
  43. package/dist/core/framework.d.ts +41 -3
  44. package/dist/core/framework.js +342 -95
  45. package/dist/core/framework.js.map +1 -1
  46. package/dist/core/graphql/adapter.js.map +1 -1
  47. package/dist/core/graphql/adapters/graphql-js-adapter.js.map +1 -1
  48. package/dist/core/graphql/core.js.map +1 -1
  49. package/dist/core/graphql/index.js.map +1 -1
  50. package/dist/core/graphql/loader.js.map +1 -1
  51. package/dist/core/graphql/types.js.map +1 -1
  52. package/dist/core/grpc/adapters/grpc-js-adapter.js +4 -0
  53. package/dist/core/grpc/adapters/grpc-js-adapter.js.map +1 -1
  54. package/dist/core/grpc/adapters/index.js.map +1 -1
  55. package/dist/core/grpc/grpc-adapter.js.map +1 -1
  56. package/dist/core/grpc/grpc-manager.js.map +1 -1
  57. package/dist/core/grpc/index.js.map +1 -1
  58. package/dist/core/grpc/middleware/auth.js +1 -1
  59. package/dist/core/grpc/middleware/auth.js.map +1 -1
  60. package/dist/core/grpc/middleware/logging.js.map +1 -1
  61. package/dist/core/grpc/middleware/validation.js +1 -1
  62. package/dist/core/grpc/middleware/validation.js.map +1 -1
  63. package/dist/core/grpc/types.d.ts +7 -7
  64. package/dist/core/grpc/types.js.map +1 -1
  65. package/dist/core/http/http-server.d.ts +17 -23
  66. package/dist/core/http/http-server.js +109 -249
  67. package/dist/core/http/http-server.js.map +1 -1
  68. package/dist/core/http/http2-server.d.ts +6 -16
  69. package/dist/core/http/http2-server.js +40 -83
  70. package/dist/core/http/http2-server.js.map +1 -1
  71. package/dist/core/http/index.d.ts +1 -0
  72. package/dist/core/http/index.js +3 -0
  73. package/dist/core/http/index.js.map +1 -1
  74. package/dist/core/http/moro-engine-server.d.ts +263 -0
  75. package/dist/core/http/moro-engine-server.js +1962 -0
  76. package/dist/core/http/moro-engine-server.js.map +1 -0
  77. package/dist/core/http/utils/compression.d.ts +47 -0
  78. package/dist/core/http/utils/compression.js +132 -0
  79. package/dist/core/http/utils/compression.js.map +1 -0
  80. package/dist/core/http/utils/lazy-event-emitter.d.ts +11 -0
  81. package/dist/core/http/utils/lazy-event-emitter.js +69 -0
  82. package/dist/core/http/utils/lazy-event-emitter.js.map +1 -0
  83. package/dist/core/http/utils/multipart-parser.d.ts +32 -0
  84. package/dist/core/http/utils/multipart-parser.js +215 -0
  85. package/dist/core/http/utils/multipart-parser.js.map +1 -0
  86. package/dist/core/http/utils/query-parser.d.ts +1 -0
  87. package/dist/core/http/utils/query-parser.js +44 -0
  88. package/dist/core/http/utils/query-parser.js.map +1 -0
  89. package/dist/core/http/utils/size.d.ts +33 -0
  90. package/dist/core/http/utils/size.js +37 -0
  91. package/dist/core/http/utils/size.js.map +1 -0
  92. package/dist/core/http/utils/ssl-config.d.ts +69 -0
  93. package/dist/core/http/utils/ssl-config.js +116 -0
  94. package/dist/core/http/utils/ssl-config.js.map +1 -0
  95. package/dist/core/http/utils/uws-worker-clustering.js +45 -32
  96. package/dist/core/http/utils/uws-worker-clustering.js.map +1 -1
  97. package/dist/core/http/uws-http-server.d.ts +25 -3
  98. package/dist/core/http/uws-http-server.js +465 -86
  99. package/dist/core/http/uws-http-server.js.map +1 -1
  100. package/dist/core/jobs/cron-parser.js +7 -5
  101. package/dist/core/jobs/cron-parser.js.map +1 -1
  102. package/dist/core/jobs/index.js.map +1 -1
  103. package/dist/core/jobs/job-executor.d.ts +1 -1
  104. package/dist/core/jobs/job-executor.js.map +1 -1
  105. package/dist/core/jobs/job-scheduler.d.ts +3 -3
  106. package/dist/core/jobs/job-scheduler.js.map +1 -1
  107. package/dist/core/jobs/job-state-manager.d.ts +3 -3
  108. package/dist/core/jobs/job-state-manager.js +25 -4
  109. package/dist/core/jobs/job-state-manager.js.map +1 -1
  110. package/dist/core/jobs/leader-election.d.ts +15 -0
  111. package/dist/core/jobs/leader-election.js +158 -69
  112. package/dist/core/jobs/leader-election.js.map +1 -1
  113. package/dist/core/jobs/types.d.ts +4 -4
  114. package/dist/core/jobs/types.js.map +1 -1
  115. package/dist/core/jobs/utils.d.ts +1 -1
  116. package/dist/core/jobs/utils.js +7 -3
  117. package/dist/core/jobs/utils.js.map +1 -1
  118. package/dist/core/logger/filters.js +3 -2
  119. package/dist/core/logger/filters.js.map +1 -1
  120. package/dist/core/logger/index.js.map +1 -1
  121. package/dist/core/logger/logger.js +56 -25
  122. package/dist/core/logger/logger.js.map +1 -1
  123. package/dist/core/logger/outputs.js.map +1 -1
  124. package/dist/core/mail/adapters/console-adapter.js.map +1 -1
  125. package/dist/core/mail/adapters/index.js.map +1 -1
  126. package/dist/core/mail/adapters/nodemailer-adapter.js.map +1 -1
  127. package/dist/core/mail/adapters/resend-adapter.js.map +1 -1
  128. package/dist/core/mail/adapters/sendgrid-adapter.js.map +1 -1
  129. package/dist/core/mail/adapters/ses-adapter.js.map +1 -1
  130. package/dist/core/mail/index.js.map +1 -1
  131. package/dist/core/mail/mail-adapter.js.map +1 -1
  132. package/dist/core/mail/mail-manager.d.ts +10 -0
  133. package/dist/core/mail/mail-manager.js +21 -5
  134. package/dist/core/mail/mail-manager.js.map +1 -1
  135. package/dist/core/mail/template-engine.js.map +1 -1
  136. package/dist/core/mail/types.js.map +1 -1
  137. package/dist/core/middleware/built-in/auth/core.js +3 -3
  138. package/dist/core/middleware/built-in/auth/core.js.map +1 -1
  139. package/dist/core/middleware/built-in/auth/helpers.js +4 -4
  140. package/dist/core/middleware/built-in/auth/helpers.js.map +1 -1
  141. package/dist/core/middleware/built-in/auth/hook.js.map +1 -1
  142. package/dist/core/middleware/built-in/auth/index.js.map +1 -1
  143. package/dist/core/middleware/built-in/auth/jwt-helpers.d.ts +4 -4
  144. package/dist/core/middleware/built-in/auth/jwt-helpers.js.map +1 -1
  145. package/dist/core/middleware/built-in/auth/middleware.js.map +1 -1
  146. package/dist/core/middleware/built-in/auth/providers.js.map +1 -1
  147. package/dist/core/middleware/built-in/body-parsers/index.js.map +1 -1
  148. package/dist/core/middleware/built-in/body-size/core.js +2 -2
  149. package/dist/core/middleware/built-in/body-size/core.js.map +1 -1
  150. package/dist/core/middleware/built-in/body-size/hook.js.map +1 -1
  151. package/dist/core/middleware/built-in/body-size/index.js.map +1 -1
  152. package/dist/core/middleware/built-in/body-size/middleware.js.map +1 -1
  153. package/dist/core/middleware/built-in/cache/adapters/cache/file.js +3 -1
  154. package/dist/core/middleware/built-in/cache/adapters/cache/file.js.map +1 -1
  155. package/dist/core/middleware/built-in/cache/adapters/cache/index.js.map +1 -1
  156. package/dist/core/middleware/built-in/cache/adapters/cache/memory.js.map +1 -1
  157. package/dist/core/middleware/built-in/cache/adapters/cache/redis.js.map +1 -1
  158. package/dist/core/middleware/built-in/cache/adapters/index.js.map +1 -1
  159. package/dist/core/middleware/built-in/cache/core.js.map +1 -1
  160. package/dist/core/middleware/built-in/cache/hook.js +3 -3
  161. package/dist/core/middleware/built-in/cache/hook.js.map +1 -1
  162. package/dist/core/middleware/built-in/cache/index.js.map +1 -1
  163. package/dist/core/middleware/built-in/cache/middleware.js.map +1 -1
  164. package/dist/core/middleware/built-in/cdn/adapters/cdn/azure.js.map +1 -1
  165. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudflare.js.map +1 -1
  166. package/dist/core/middleware/built-in/cdn/adapters/cdn/cloudfront.js.map +1 -1
  167. package/dist/core/middleware/built-in/cdn/adapters/cdn/index.js.map +1 -1
  168. package/dist/core/middleware/built-in/cdn/adapters/index.js.map +1 -1
  169. package/dist/core/middleware/built-in/cdn/core.js.map +1 -1
  170. package/dist/core/middleware/built-in/cdn/hook.js.map +1 -1
  171. package/dist/core/middleware/built-in/cdn/index.js.map +1 -1
  172. package/dist/core/middleware/built-in/cdn/middleware.js.map +1 -1
  173. package/dist/core/middleware/built-in/compression/core.d.ts +3 -0
  174. package/dist/core/middleware/built-in/compression/core.js +28 -34
  175. package/dist/core/middleware/built-in/compression/core.js.map +1 -1
  176. package/dist/core/middleware/built-in/compression/hook.js.map +1 -1
  177. package/dist/core/middleware/built-in/compression/index.js.map +1 -1
  178. package/dist/core/middleware/built-in/compression/middleware.js.map +1 -1
  179. package/dist/core/middleware/built-in/cookie/core.js.map +1 -1
  180. package/dist/core/middleware/built-in/cookie/hook.js.map +1 -1
  181. package/dist/core/middleware/built-in/cookie/index.js.map +1 -1
  182. package/dist/core/middleware/built-in/cookie/middleware.js.map +1 -1
  183. package/dist/core/middleware/built-in/cors/core.js.map +1 -1
  184. package/dist/core/middleware/built-in/cors/hook.js.map +1 -1
  185. package/dist/core/middleware/built-in/cors/index.js.map +1 -1
  186. package/dist/core/middleware/built-in/cors/middleware.js.map +1 -1
  187. package/dist/core/middleware/built-in/csp/core.js.map +1 -1
  188. package/dist/core/middleware/built-in/csp/hook.js.map +1 -1
  189. package/dist/core/middleware/built-in/csp/index.js.map +1 -1
  190. package/dist/core/middleware/built-in/csp/middleware.js.map +1 -1
  191. package/dist/core/middleware/built-in/csrf/core.js +1 -1
  192. package/dist/core/middleware/built-in/csrf/core.js.map +1 -1
  193. package/dist/core/middleware/built-in/csrf/hook.js.map +1 -1
  194. package/dist/core/middleware/built-in/csrf/index.js.map +1 -1
  195. package/dist/core/middleware/built-in/csrf/middleware.js.map +1 -1
  196. package/dist/core/middleware/built-in/error-tracker/index.js.map +1 -1
  197. package/dist/core/middleware/built-in/error-tracker/middleware.js.map +1 -1
  198. package/dist/core/middleware/built-in/graphql/core.js.map +1 -1
  199. package/dist/core/middleware/built-in/graphql/helpers.js.map +1 -1
  200. package/dist/core/middleware/built-in/graphql/hook.js.map +1 -1
  201. package/dist/core/middleware/built-in/graphql/index.js.map +1 -1
  202. package/dist/core/middleware/built-in/graphql/middleware.js.map +1 -1
  203. package/dist/core/middleware/built-in/graphql/subscriptions.js.map +1 -1
  204. package/dist/core/middleware/built-in/helmet/core.js.map +1 -1
  205. package/dist/core/middleware/built-in/helmet/hook.js.map +1 -1
  206. package/dist/core/middleware/built-in/helmet/index.js.map +1 -1
  207. package/dist/core/middleware/built-in/helmet/middleware.js.map +1 -1
  208. package/dist/core/middleware/built-in/http2/core.js.map +1 -1
  209. package/dist/core/middleware/built-in/http2/hook.js.map +1 -1
  210. package/dist/core/middleware/built-in/http2/index.js.map +1 -1
  211. package/dist/core/middleware/built-in/http2/middleware.js.map +1 -1
  212. package/dist/core/middleware/built-in/index.js.map +1 -1
  213. package/dist/core/middleware/built-in/performance-monitor/index.js.map +1 -1
  214. package/dist/core/middleware/built-in/performance-monitor/middleware.js.map +1 -1
  215. package/dist/core/middleware/built-in/range/core.js +4 -1
  216. package/dist/core/middleware/built-in/range/core.js.map +1 -1
  217. package/dist/core/middleware/built-in/range/hook.js.map +1 -1
  218. package/dist/core/middleware/built-in/range/index.js.map +1 -1
  219. package/dist/core/middleware/built-in/range/middleware.js.map +1 -1
  220. package/dist/core/middleware/built-in/rate-limit/core.js.map +1 -1
  221. package/dist/core/middleware/built-in/rate-limit/hook.js.map +1 -1
  222. package/dist/core/middleware/built-in/rate-limit/index.js.map +1 -1
  223. package/dist/core/middleware/built-in/rate-limit/middleware.js.map +1 -1
  224. package/dist/core/middleware/built-in/request-logger/index.js.map +1 -1
  225. package/dist/core/middleware/built-in/request-logger/middleware.js.map +1 -1
  226. package/dist/core/middleware/built-in/session/core.js +4 -4
  227. package/dist/core/middleware/built-in/session/core.js.map +1 -1
  228. package/dist/core/middleware/built-in/session/hook.js.map +1 -1
  229. package/dist/core/middleware/built-in/session/index.js.map +1 -1
  230. package/dist/core/middleware/built-in/session/middleware.js.map +1 -1
  231. package/dist/core/middleware/built-in/sse/core.js.map +1 -1
  232. package/dist/core/middleware/built-in/sse/hook.js.map +1 -1
  233. package/dist/core/middleware/built-in/sse/index.js.map +1 -1
  234. package/dist/core/middleware/built-in/sse/middleware.js.map +1 -1
  235. package/dist/core/middleware/built-in/static/core.js.map +1 -1
  236. package/dist/core/middleware/built-in/static/hook.js.map +1 -1
  237. package/dist/core/middleware/built-in/static/index.js.map +1 -1
  238. package/dist/core/middleware/built-in/static/middleware.js.map +1 -1
  239. package/dist/core/middleware/built-in/template/core.js +1 -1
  240. package/dist/core/middleware/built-in/template/core.js.map +1 -1
  241. package/dist/core/middleware/built-in/template/hook.js.map +1 -1
  242. package/dist/core/middleware/built-in/template/index.js.map +1 -1
  243. package/dist/core/middleware/built-in/template/middleware.js.map +1 -1
  244. package/dist/core/middleware/built-in/upload/core.js.map +1 -1
  245. package/dist/core/middleware/built-in/upload/hook.js.map +1 -1
  246. package/dist/core/middleware/built-in/upload/index.js.map +1 -1
  247. package/dist/core/middleware/built-in/upload/middleware.js.map +1 -1
  248. package/dist/core/middleware/built-in/validation/core.js.map +1 -1
  249. package/dist/core/middleware/built-in/validation/hook.js.map +1 -1
  250. package/dist/core/middleware/built-in/validation/index.js.map +1 -1
  251. package/dist/core/middleware/built-in/validation/middleware.js.map +1 -1
  252. package/dist/core/middleware/index.js +2 -2
  253. package/dist/core/middleware/index.js.map +1 -1
  254. package/dist/core/modules/auto-discovery.js +11 -7
  255. package/dist/core/modules/auto-discovery.js.map +1 -1
  256. package/dist/core/modules/index.js.map +1 -1
  257. package/dist/core/modules/modules.js +18 -13
  258. package/dist/core/modules/modules.js.map +1 -1
  259. package/dist/core/networking/adapters/engine-adapter.d.ts +23 -0
  260. package/dist/core/networking/adapters/engine-adapter.js +365 -0
  261. package/dist/core/networking/adapters/engine-adapter.js.map +1 -0
  262. package/dist/core/networking/adapters/index.d.ts +1 -0
  263. package/dist/core/networking/adapters/index.js +1 -0
  264. package/dist/core/networking/adapters/index.js.map +1 -1
  265. package/dist/core/networking/adapters/socketio-adapter.d.ts +1 -0
  266. package/dist/core/networking/adapters/socketio-adapter.js +12 -1
  267. package/dist/core/networking/adapters/socketio-adapter.js.map +1 -1
  268. package/dist/core/networking/adapters/uws-adapter.js +27 -16
  269. package/dist/core/networking/adapters/uws-adapter.js.map +1 -1
  270. package/dist/core/networking/adapters/ws-adapter.d.ts +15 -0
  271. package/dist/core/networking/adapters/ws-adapter.js +120 -6
  272. package/dist/core/networking/adapters/ws-adapter.js.map +1 -1
  273. package/dist/core/networking/index.js.map +1 -1
  274. package/dist/core/networking/service-discovery.js +7 -5
  275. package/dist/core/networking/service-discovery.js.map +1 -1
  276. package/dist/core/networking/websocket-adapter.d.ts +22 -3
  277. package/dist/core/networking/websocket-adapter.js.map +1 -1
  278. package/dist/core/networking/websocket-manager.js +70 -67
  279. package/dist/core/networking/websocket-manager.js.map +1 -1
  280. package/dist/core/pooling/object-pool-manager.js +6 -0
  281. package/dist/core/pooling/object-pool-manager.js.map +1 -1
  282. package/dist/core/queue/adapters/bull-adapter.js.map +1 -1
  283. package/dist/core/queue/adapters/index.js.map +1 -1
  284. package/dist/core/queue/adapters/kafka-adapter.js +2 -2
  285. package/dist/core/queue/adapters/kafka-adapter.js.map +1 -1
  286. package/dist/core/queue/adapters/memory-adapter.js +6 -6
  287. package/dist/core/queue/adapters/memory-adapter.js.map +1 -1
  288. package/dist/core/queue/adapters/rabbitmq-adapter.d.ts +50 -0
  289. package/dist/core/queue/adapters/rabbitmq-adapter.js +176 -20
  290. package/dist/core/queue/adapters/rabbitmq-adapter.js.map +1 -1
  291. package/dist/core/queue/adapters/sqs-adapter.d.ts +12 -2
  292. package/dist/core/queue/adapters/sqs-adapter.js +75 -24
  293. package/dist/core/queue/adapters/sqs-adapter.js.map +1 -1
  294. package/dist/core/queue/index.js.map +1 -1
  295. package/dist/core/queue/middleware/index.js.map +1 -1
  296. package/dist/core/queue/middleware/monitoring.d.ts +1 -1
  297. package/dist/core/queue/middleware/monitoring.js.map +1 -1
  298. package/dist/core/queue/middleware/priority.js +2 -1
  299. package/dist/core/queue/middleware/priority.js.map +1 -1
  300. package/dist/core/queue/middleware/rate-limit.js.map +1 -1
  301. package/dist/core/queue/queue-adapter.js.map +1 -1
  302. package/dist/core/queue/queue-manager.js.map +1 -1
  303. package/dist/core/queue/types.d.ts +8 -8
  304. package/dist/core/queue/types.js.map +1 -1
  305. package/dist/core/routing/app-integration.js.map +1 -1
  306. package/dist/core/routing/create-router.js.map +1 -1
  307. package/dist/core/routing/index.js.map +1 -1
  308. package/dist/core/routing/path-matcher.js.map +1 -1
  309. package/dist/core/routing/radix-tree.js.map +1 -1
  310. package/dist/core/routing/router.js.map +1 -1
  311. package/dist/core/routing/unified-router.js +12 -4
  312. package/dist/core/routing/unified-router.js.map +1 -1
  313. package/dist/core/runtime/aws-lambda-adapter.js.map +1 -1
  314. package/dist/core/runtime/base-adapter.js +2 -2
  315. package/dist/core/runtime/base-adapter.js.map +1 -1
  316. package/dist/core/runtime/cloudflare-workers-adapter.js +2 -0
  317. package/dist/core/runtime/cloudflare-workers-adapter.js.map +1 -1
  318. package/dist/core/runtime/index.js.map +1 -1
  319. package/dist/core/runtime/node-adapter.js +19 -17
  320. package/dist/core/runtime/node-adapter.js.map +1 -1
  321. package/dist/core/runtime/vercel-edge-adapter.js +2 -0
  322. package/dist/core/runtime/vercel-edge-adapter.js.map +1 -1
  323. package/dist/core/utilities/circuit-breaker.d.ts +1 -0
  324. package/dist/core/utilities/circuit-breaker.js +25 -2
  325. package/dist/core/utilities/circuit-breaker.js.map +1 -1
  326. package/dist/core/utilities/container.js +9 -9
  327. package/dist/core/utilities/container.js.map +1 -1
  328. package/dist/core/utilities/hooks.js +28 -6
  329. package/dist/core/utilities/hooks.js.map +1 -1
  330. package/dist/core/utilities/index.js.map +1 -1
  331. package/dist/core/utilities/module-path.js.map +1 -1
  332. package/dist/core/utilities/package-utils.d.ts +68 -0
  333. package/dist/core/utilities/package-utils.js +198 -1
  334. package/dist/core/utilities/package-utils.js.map +1 -1
  335. package/dist/core/utilities/response-helpers.js +1 -1
  336. package/dist/core/utilities/response-helpers.js.map +1 -1
  337. package/dist/core/validation/adapters.js.map +1 -1
  338. package/dist/core/validation/error-handler.js.map +1 -1
  339. package/dist/core/validation/index.js.map +1 -1
  340. package/dist/core/validation/schema-interface.js.map +1 -1
  341. package/dist/core/workers/facade.js.map +1 -1
  342. package/dist/core/workers/index.js.map +1 -1
  343. package/dist/core/workers/worker-entry.d.ts +1 -0
  344. package/dist/core/workers/worker-entry.js +12 -0
  345. package/dist/core/workers/worker-entry.js.map +1 -0
  346. package/dist/core/workers/worker-manager.d.ts +23 -2
  347. package/dist/core/workers/worker-manager.js +117 -17
  348. package/dist/core/workers/worker-manager.js.map +1 -1
  349. package/dist/core/workers/worker.js +8 -6
  350. package/dist/core/workers/worker.js.map +1 -1
  351. package/dist/index.d.ts +2 -2
  352. package/dist/index.js +5 -2
  353. package/dist/index.js.map +1 -1
  354. package/dist/moro.d.ts +20 -1
  355. package/dist/moro.js +230 -70
  356. package/dist/moro.js.map +1 -1
  357. package/dist/types/auth.d.ts +4 -4
  358. package/dist/types/auth.js.map +1 -1
  359. package/dist/types/cache.js.map +1 -1
  360. package/dist/types/cdn.js.map +1 -1
  361. package/dist/types/config.d.ts +100 -15
  362. package/dist/types/config.js.map +1 -1
  363. package/dist/types/core.js.map +1 -1
  364. package/dist/types/database.js.map +1 -1
  365. package/dist/types/discovery.js.map +1 -1
  366. package/dist/types/events.js.map +1 -1
  367. package/dist/types/hooks.js.map +1 -1
  368. package/dist/types/http.js.map +1 -1
  369. package/dist/types/logger.js.map +1 -1
  370. package/dist/types/module.js.map +1 -1
  371. package/dist/types/runtime.js.map +1 -1
  372. package/dist/types/session.js.map +1 -1
  373. package/package.json +32 -17
package/dist/moro.js CHANGED
@@ -242,21 +242,29 @@ export class Moro extends EventEmitter {
242
242
  // Default to enabled (true) unless explicitly disabled
243
243
  const jobsEnabled = this.config.jobs?.enabled !== false && options.jobs?.enabled !== false;
244
244
  if (jobsEnabled) {
245
- const leaderElectionOptions = this.config.jobs?.leaderElection?.enabled !== false
245
+ const le = this.config.jobs?.leaderElection;
246
+ const leaderElectionOptions = le?.enabled !== false
246
247
  ? {
247
- strategy: this.config.jobs?.leaderElection?.strategy ?? 'file',
248
- lockPath: this.config.jobs?.leaderElection?.lockPath,
249
- lockTimeout: this.config.jobs?.leaderElection?.lockTimeout,
250
- heartbeatInterval: this.config.jobs?.leaderElection?.heartbeatInterval,
248
+ strategy: le?.strategy ?? 'file',
249
+ ...(le?.lockPath !== undefined ? { lockPath: le.lockPath } : {}),
250
+ ...(le?.lockTimeout !== undefined ? { lockTimeout: le.lockTimeout } : {}),
251
+ ...(le?.heartbeatInterval !== undefined
252
+ ? { heartbeatInterval: le.heartbeatInterval }
253
+ : {}),
251
254
  }
252
255
  : undefined;
256
+ const jobs = this.config.jobs;
253
257
  const jobSchedulerOptions = {
254
- maxConcurrentJobs: this.config.jobs?.maxConcurrentJobs,
255
- enableLeaderElection: this.config.jobs?.leaderElection?.enabled !== false,
256
- leaderElection: leaderElectionOptions,
257
- executor: this.config.jobs?.executor,
258
- stateManager: this.config.jobs?.stateManager,
259
- gracefulShutdownTimeout: this.config.jobs?.gracefulShutdownTimeout,
258
+ enableLeaderElection: jobs?.leaderElection?.enabled !== false,
259
+ ...(jobs?.maxConcurrentJobs !== undefined
260
+ ? { maxConcurrentJobs: jobs.maxConcurrentJobs }
261
+ : {}),
262
+ ...(leaderElectionOptions !== undefined ? { leaderElection: leaderElectionOptions } : {}),
263
+ ...(jobs?.executor !== undefined ? { executor: jobs.executor } : {}),
264
+ ...(jobs?.stateManager !== undefined ? { stateManager: jobs.stateManager } : {}),
265
+ ...(jobs?.gracefulShutdownTimeout !== undefined
266
+ ? { gracefulShutdownTimeout: jobs.gracefulShutdownTimeout }
267
+ : {}),
260
268
  };
261
269
  this.jobScheduler = new JobScheduler(createFrameworkLogger('Jobs'), jobSchedulerOptions);
262
270
  this.jobHealthChecker = new JobHealthChecker(this.jobScheduler, createFrameworkLogger('JobHealth'));
@@ -277,7 +285,7 @@ export class Moro extends EventEmitter {
277
285
  // is registered before module middleware that might bypass it
278
286
  this.autoDiscoveryOptions = options.autoDiscover !== false ? options : null;
279
287
  // Emit initialization event through enterprise event bus
280
- this.eventBus.emit('framework:initialized', {
288
+ void this.eventBus.emit('framework:initialized', {
281
289
  options,
282
290
  config: this.config,
283
291
  runtime: this.runtimeType,
@@ -459,7 +467,7 @@ export class Moro extends EventEmitter {
459
467
  enableDocs(config) {
460
468
  this.documentation.enableDocs(config, this.intelligentRouting);
461
469
  this.logger.info(`API Documentation enabled at ${config.basePath || '/docs'}`, 'Documentation');
462
- this.eventBus.emit('docs:enabled', { config });
470
+ void this.eventBus.emit('docs:enabled', { config });
463
471
  }
464
472
  // Get OpenAPI specification
465
473
  getOpenAPISpec() {
@@ -499,7 +507,7 @@ export class Moro extends EventEmitter {
499
507
  // Standard middleware integration (req, res, next pattern)
500
508
  if (typeof middlewareOrFunction === 'function' && middlewareOrFunction.length >= 3) {
501
509
  this.coreFramework.addMiddleware(middlewareOrFunction);
502
- this.eventBus.emit('middleware:registered', {
510
+ void this.eventBus.emit('middleware:registered', {
503
511
  type: 'standard',
504
512
  middleware: middlewareOrFunction,
505
513
  });
@@ -508,7 +516,7 @@ export class Moro extends EventEmitter {
508
516
  // Function-style middleware execution
509
517
  if (typeof middlewareOrFunction === 'function' && middlewareOrFunction.length <= 1) {
510
518
  await middlewareOrFunction(this);
511
- this.eventBus.emit('middleware:executed', {
519
+ void this.eventBus.emit('middleware:executed', {
512
520
  type: 'function',
513
521
  middleware: middlewareOrFunction,
514
522
  });
@@ -525,7 +533,7 @@ export class Moro extends EventEmitter {
525
533
  return this;
526
534
  }
527
535
  // Fallback: emit event for unknown middleware types
528
- this.eventBus.emit('middleware:advanced', {
536
+ void this.eventBus.emit('middleware:advanced', {
529
537
  middleware: middlewareOrFunction,
530
538
  config,
531
539
  });
@@ -595,14 +603,14 @@ export class Moro extends EventEmitter {
595
603
  }
596
604
  // Module loading with events
597
605
  async loadModule(moduleOrPath) {
598
- this.eventBus.emit('module:loading', {
606
+ void this.eventBus.emit('module:loading', {
599
607
  moduleId: typeof moduleOrPath === 'string' ? moduleOrPath : moduleOrPath.name,
600
608
  });
601
609
  if (typeof moduleOrPath === 'string') {
602
610
  const module = await this.importModule(moduleOrPath);
603
611
  await this.coreFramework.loadModule(module);
604
612
  this.loadedModules.add(moduleOrPath);
605
- this.eventBus.emit('module:loaded', {
613
+ void this.eventBus.emit('module:loaded', {
606
614
  moduleId: module.name,
607
615
  version: module.version || '1.0.0',
608
616
  });
@@ -610,7 +618,7 @@ export class Moro extends EventEmitter {
610
618
  else {
611
619
  await this.coreFramework.loadModule(moduleOrPath);
612
620
  this.loadedModules.add(moduleOrPath.name);
613
- this.eventBus.emit('module:loaded', {
621
+ void this.eventBus.emit('module:loaded', {
614
622
  moduleId: moduleOrPath.name,
615
623
  version: moduleOrPath.version || '1.0.0',
616
624
  });
@@ -624,7 +632,7 @@ export class Moro extends EventEmitter {
624
632
  }
625
633
  // Database helper with events
626
634
  database(adapter) {
627
- this.eventBus.emit('database:connected', {
635
+ void this.eventBus.emit('database:connected', {
628
636
  adapter: adapter.constructor.name,
629
637
  config: 'hidden',
630
638
  });
@@ -747,7 +755,11 @@ export class Moro extends EventEmitter {
747
755
  this.startWithClustering(port, host, callback);
748
756
  return;
749
757
  }
750
- this.eventBus.emit('server:starting', { port, runtime: this.runtimeType });
758
+ // Single-process graceful shutdown: SIGINT/SIGTERM (Ctrl-C) drain in-flight
759
+ // work via close() by default; a second signal force-exits. Opt out with
760
+ // `server.gracefulShutdown: false`. (Cluster mode wires its own handlers.)
761
+ this.registerProcessShutdownHandlers();
762
+ void this.eventBus.emit('server:starting', { port, runtime: this.runtimeType });
751
763
  // Add documentation middleware first (if enabled)
752
764
  try {
753
765
  const docsMiddleware = this.documentation.getDocsMiddleware();
@@ -767,8 +779,11 @@ export class Moro extends EventEmitter {
767
779
  const startServer = () => {
768
780
  const actualCallback = () => {
769
781
  const displayHost = host || 'localhost';
782
+ const serverKind = this.engine;
770
783
  this.logger.info('Moro Server Started', 'Server');
771
784
  this.logger.info(`Runtime: ${this.runtimeType}`, 'Server');
785
+ this.logger.info(`HTTP engine: ${serverKind.server}` +
786
+ (serverKind.enginePackage ? ` (${serverKind.enginePackage})` : ''), 'Server');
772
787
  this.logger.info(`HTTP API: http://${displayHost}:${port}`, 'Server');
773
788
  if (this.config.websocket.enabled) {
774
789
  this.logger.info(`WebSocket: ws://${displayHost}:${port}`, 'Server');
@@ -781,7 +796,11 @@ export class Moro extends EventEmitter {
781
796
  // Log performance stats
782
797
  this.unifiedRouter.logPerformanceStats();
783
798
  }
784
- this.eventBus.emit('server:started', { port, runtime: this.runtimeType });
799
+ void this.eventBus.emit('server:started', {
800
+ port,
801
+ runtime: this.runtimeType,
802
+ engine: serverKind,
803
+ });
785
804
  // Start job scheduler after server starts
786
805
  this.startJobScheduler().catch(err => {
787
806
  this.logger.error(`Failed to start job scheduler: ${String(err)}`);
@@ -813,20 +832,30 @@ export class Moro extends EventEmitter {
813
832
  this.ensureAutoDiscoveryComplete().then(() => this.ensureRoutesLoaded()),
814
833
  this.processQueuedWebSocketRegistrations(),
815
834
  ])
816
- .then(() => {
817
- startServer();
818
- })
819
- .catch(error => {
835
+ .then(() => startServer(), initError => {
836
+ // Initialization (auto-discovery / WebSocket setup) failed — this is
837
+ // NOT the listen() call. Handle it here so a subsequent listen()
838
+ // failure can't be misdiagnosed as an init failure and retried.
820
839
  this.logger.error('Initialization failed during server start', 'Framework', {
821
- error: error instanceof Error ? error.message : String(error),
840
+ error: initError instanceof Error ? initError.message : String(initError),
822
841
  });
823
- // For auto-discovery failures, start server anyway
824
- // For WebSocket failures with queued registrations, error will propagate
825
- if (error instanceof Error &&
826
- error.message.includes('WebSocket features require a WebSocket adapter')) {
827
- throw error;
842
+ // WebSocket-adapter misconfiguration is fatal; propagate it.
843
+ if (initError instanceof Error &&
844
+ initError.message.includes('WebSocket features require a WebSocket adapter')) {
845
+ throw initError;
828
846
  }
847
+ // A non-fatal init issue (e.g. auto-discovery) — start the server anyway.
829
848
  startServer();
849
+ })
850
+ .catch(error => {
851
+ // startServer()/listen() failed — e.g. EADDRINUSE thrown synchronously
852
+ // by the native engine. Retrying would fail identically, so surface it
853
+ // via the 'error' event (Node's server convention) instead of retrying
854
+ // into an unhandled rejection. With no 'error' listener, EventEmitter
855
+ // rethrows — the desired visible crash for a fatal bind failure.
856
+ const message = error instanceof Error ? error.message : String(error);
857
+ this.logger.error(`Failed to start server on port ${port}: ${message}`, 'Framework');
858
+ this.emit('error', error);
830
859
  });
831
860
  }
832
861
  // Public method to manually initialize auto-discovery
@@ -997,7 +1026,7 @@ export class Moro extends EventEmitter {
997
1026
  if (matches) {
998
1027
  req.params = {};
999
1028
  route.paramNames.forEach((name, index) => {
1000
- req.params[name] = matches[index + 1];
1029
+ req.params[name] = matches[index + 1] ?? '';
1001
1030
  });
1002
1031
  }
1003
1032
  // Get handler function
@@ -1113,6 +1142,15 @@ export class Moro extends EventEmitter {
1113
1142
  get core() {
1114
1143
  return this.coreFramework;
1115
1144
  }
1145
+ // Which HTTP server actually booted (engine/node/http2), the package
1146
+ // backing a native engine, and the fallback reason when one was requested
1147
+ // but the Node server booted instead. Stable surface for logs/tests/benchmarks.
1148
+ get engine() {
1149
+ return this.coreFramework.getServerKind();
1150
+ }
1151
+ getServerKind() {
1152
+ return this.coreFramework.getServerKind();
1153
+ }
1116
1154
  // Public API for accessing the DI container
1117
1155
  getContainer() {
1118
1156
  return this.coreFramework.getContainer();
@@ -1203,6 +1241,8 @@ export class Moro extends EventEmitter {
1203
1241
  // This provides the intuitive developer experience users expect
1204
1242
  for (const route of this.routes) {
1205
1243
  const handler = this.routeHandlers[route.handler];
1244
+ if (!handler)
1245
+ continue;
1206
1246
  // Get direct access to the HTTP server through the core framework
1207
1247
  const httpServer = this.coreFramework.httpServer;
1208
1248
  // Create a wrapper handler that handles validation, rate limiting, and return values
@@ -1278,7 +1318,7 @@ export class Moro extends EventEmitter {
1278
1318
  }
1279
1319
  // Rate limiting middleware
1280
1320
  if (route.rateLimit) {
1281
- const clientId = req.ip || req.connection.remoteAddress || 'unknown';
1321
+ const clientId = req.ip || req.connection?.remoteAddress || 'unknown';
1282
1322
  const key = `${route.method}:${route.path}:${clientId}`;
1283
1323
  if (!this.checkRateLimit(key, route.rateLimit)) {
1284
1324
  res.status(429).json({
@@ -1506,20 +1546,20 @@ export class Moro extends EventEmitter {
1506
1546
  this.logger.info('Module changes detected, reloading...', 'ModuleDiscovery');
1507
1547
  // Unload existing modules (if supported)
1508
1548
  // For now, just log the change
1509
- this.eventBus.emit('modules:changed', {
1549
+ void this.eventBus.emit('modules:changed', {
1510
1550
  modules: modules.map(m => ({ name: m.name, version: m.version })),
1511
1551
  timestamp: new Date(),
1512
1552
  });
1513
1553
  }
1514
1554
  // Legacy method for backward compatibility
1515
1555
  autoDiscoverModules(modulesPath) {
1516
- // Redirect to new system
1517
- this.initializeAutoDiscovery({
1556
+ // Redirect to new system (legacy sync shim over the async discovery path).
1557
+ void this.initializeAutoDiscovery({
1518
1558
  autoDiscover: {
1519
1559
  enabled: true,
1520
1560
  paths: [modulesPath],
1521
1561
  },
1522
- });
1562
+ }).catch(err => this.logger.error(`Auto-discovery failed: ${String(err)}`, 'ModuleDiscovery'));
1523
1563
  }
1524
1564
  async importModule(modulePath) {
1525
1565
  // Convert file path to proper file URL for Windows compatibility
@@ -1694,7 +1734,7 @@ export class Moro extends EventEmitter {
1694
1734
  process.on('SIGTERM', workerShutdown);
1695
1735
  process.on('SIGINT', workerShutdown);
1696
1736
  // Continue with normal server startup for this worker
1697
- this.eventBus.emit('server:starting', {
1737
+ void this.eventBus.emit('server:starting', {
1698
1738
  port,
1699
1739
  runtime: this.runtimeType,
1700
1740
  worker: process.pid,
@@ -1716,37 +1756,53 @@ export class Moro extends EventEmitter {
1716
1756
  const workerCallback = () => {
1717
1757
  const displayHost = host || 'localhost';
1718
1758
  this.logger.info(`Worker ${process.pid} ready on ${displayHost}:${port}`, 'Worker');
1719
- this.eventBus.emit('server:started', {
1759
+ void this.eventBus.emit('server:started', {
1720
1760
  port,
1721
1761
  runtime: this.runtimeType,
1722
1762
  worker: process.pid,
1763
+ engine: this.engine,
1723
1764
  });
1724
1765
  };
1725
1766
  // Ensure WebSocket setup is complete before starting worker
1726
- this.processQueuedWebSocketRegistrations()
1727
- .then(() => {
1767
+ const startWorkerListening = () => {
1728
1768
  if (host) {
1729
1769
  this.coreFramework.listen(port, host, workerCallback);
1730
1770
  }
1731
1771
  else {
1732
1772
  this.coreFramework.listen(port, workerCallback);
1733
1773
  }
1734
- })
1774
+ };
1775
+ this.processQueuedWebSocketRegistrations()
1776
+ .then(startWorkerListening)
1735
1777
  .catch(error => {
1778
+ const message = error instanceof Error ? error.message : String(error);
1779
+ const code = error?.code;
1780
+ // listen() itself failed (EADDRINUSE etc.): retrying is guaranteed to
1781
+ // fail again and would surface as an unhandled rejection crash-loop.
1782
+ // Log fatally and exit so the cluster primary sees a clean death.
1783
+ // Prefer the code the native/Node servers set; fall back to message.
1784
+ if (code === 'EADDRINUSE' ||
1785
+ code === 'EACCES' ||
1786
+ /EADDRINUSE|failed to bind/i.test(message)) {
1787
+ this.logger.error(`Worker ${process.pid} could not bind port ${port}: ${message}`, 'Worker');
1788
+ process.exit(1);
1789
+ }
1736
1790
  this.logger.error('WebSocket initialization failed in worker', 'Worker', {
1737
- error: error instanceof Error ? error.message : String(error),
1791
+ error: message,
1738
1792
  });
1739
1793
  // For WebSocket failures with queued registrations, error will propagate
1740
1794
  if (error instanceof Error &&
1741
1795
  error.message.includes('WebSocket features require a WebSocket adapter')) {
1742
1796
  throw error;
1743
1797
  }
1744
- // Start anyway for other errors
1745
- if (host) {
1746
- this.coreFramework.listen(port, host, workerCallback);
1798
+ // WebSocket setup failed but the HTTP server can still serve: start
1799
+ // anyway, and surface (not swallow) a listen failure from this path.
1800
+ try {
1801
+ startWorkerListening();
1747
1802
  }
1748
- else {
1749
- this.coreFramework.listen(port, workerCallback);
1803
+ catch (listenError) {
1804
+ this.logger.error(`Worker ${process.pid} failed to start: ${listenError instanceof Error ? listenError.message : String(listenError)}`, 'Worker');
1805
+ process.exit(1);
1750
1806
  }
1751
1807
  });
1752
1808
  }
@@ -1765,8 +1821,93 @@ export class Moro extends EventEmitter {
1765
1821
  * Gracefully close the application and clean up resources
1766
1822
  * This should be called in tests and during shutdown
1767
1823
  */
1824
+ shutdownHandlersRegistered = false;
1825
+ isShuttingDown = false;
1826
+ // Per-instance opt-in uncaught-error listeners (removed by close()).
1827
+ processListeners = [];
1828
+ // Graceful shutdown is driven by ONE process-level SIGINT/SIGTERM handler
1829
+ // shared across every Moro instance (installed once), so creating many apps
1830
+ // never accumulates process listeners. Instances register here on listen()
1831
+ // and deregister on close().
1832
+ static activeInstances = new Set();
1833
+ static globalSignalsInstalled = false;
1834
+ static globalShuttingDown = false;
1835
+ static installGlobalShutdownSignals() {
1836
+ if (Moro.globalSignalsInstalled)
1837
+ return;
1838
+ Moro.globalSignalsInstalled = true;
1839
+ const handle = (signal, code) => {
1840
+ // A second signal while already draining forces an immediate exit, so a
1841
+ // stuck shutdown can never make the process unkillable via Ctrl-C.
1842
+ if (Moro.globalShuttingDown) {
1843
+ process.exit(code);
1844
+ return;
1845
+ }
1846
+ Moro.globalShuttingDown = true;
1847
+ const instances = Array.from(Moro.activeInstances);
1848
+ instances[0]?.logger.info(`Received ${signal}, shutting down gracefully...`, 'Server');
1849
+ Promise.allSettled(instances.map(inst => inst.close()))
1850
+ .then(() => process.exit(code))
1851
+ .catch(() => process.exit(1));
1852
+ };
1853
+ process.on('SIGINT', () => handle('SIGINT', 0));
1854
+ process.on('SIGTERM', () => handle('SIGTERM', 0));
1855
+ }
1856
+ /**
1857
+ * Enable graceful shutdown for this instance. SIGINT/SIGTERM (Ctrl-C) drain
1858
+ * in-flight work via close() by default; a second signal force-exits. Opt out
1859
+ * with `server.gracefulShutdown: false` (e.g. when the host app owns signals).
1860
+ * Uncaught-error draining is separate and opt-in (`server.handleUncaught`).
1861
+ */
1862
+ registerProcessShutdownHandlers() {
1863
+ if (this.shutdownHandlersRegistered)
1864
+ return;
1865
+ const serverCfg = this.config.server;
1866
+ if (serverCfg?.gracefulShutdown === false)
1867
+ return; // default ON; opt out here
1868
+ this.shutdownHandlersRegistered = true;
1869
+ Moro.activeInstances.add(this);
1870
+ Moro.installGlobalShutdownSignals();
1871
+ // Opt-in uncaught-error draining (per instance, removed on close()).
1872
+ if (serverCfg?.handleUncaught === true) {
1873
+ const add = (event, handler) => {
1874
+ process.on(event, handler);
1875
+ this.processListeners.push([event, handler]);
1876
+ };
1877
+ add('unhandledRejection', reason => {
1878
+ this.logger.error(`Unhandled promise rejection: ${String(reason)}`, 'Server');
1879
+ this.drainAndExit(1);
1880
+ });
1881
+ add('uncaughtException', err => {
1882
+ this.logger.error(`Uncaught exception: ${err instanceof Error ? err.stack || err.message : String(err)}`, 'Server');
1883
+ this.drainAndExit(1);
1884
+ });
1885
+ }
1886
+ }
1887
+ drainAndExit(code) {
1888
+ if (this.isShuttingDown) {
1889
+ process.exit(code);
1890
+ return;
1891
+ }
1892
+ this.isShuttingDown = true;
1893
+ this.close()
1894
+ .then(() => process.exit(code))
1895
+ .catch(() => process.exit(1));
1896
+ }
1897
+ /** Deregister this instance from process shutdown handling (called by close()). */
1898
+ removeProcessShutdownHandlers() {
1899
+ Moro.activeInstances.delete(this);
1900
+ for (const [event, handler] of this.processListeners) {
1901
+ process.removeListener(event, handler);
1902
+ }
1903
+ this.processListeners = [];
1904
+ this.shutdownHandlersRegistered = false;
1905
+ }
1768
1906
  async close() {
1769
1907
  this.logger.debug('Closing Moro application...');
1908
+ // Detach our process signal listeners so repeated create/close cycles
1909
+ // (tests, or a host that spins up many apps) don't leak process listeners.
1910
+ this.removeProcessShutdownHandlers();
1770
1911
  // Run user-registered onClose hooks first, while subsystems are still alive.
1771
1912
  // Failures in one hook don't prevent subsequent hooks or Moro's own teardown.
1772
1913
  if (this.closeHooks.length > 0) {
@@ -1834,6 +1975,13 @@ export class Moro extends EventEmitter {
1834
1975
  // Only wait for close if the server is actually listening
1835
1976
  const isListening = server?.listening || server?.address?.() !== null;
1836
1977
  if (isListening) {
1978
+ // Stop accepting new connections and let in-flight requests finish,
1979
+ // but don't hang on idle keep-alive / WebSocket connections: close
1980
+ // idle sockets right away, then force-close whatever remains at the
1981
+ // deadline so this promise reflects a real close instead of only the
1982
+ // timer firing. (closeIdle/closeAllConnections exist on the Node http
1983
+ // server; the uWS/engine backends ignore the optional calls.)
1984
+ server?.closeIdleConnections?.();
1837
1985
  await Promise.race([
1838
1986
  new Promise(resolve => {
1839
1987
  httpServer.close(() => {
@@ -1841,7 +1989,15 @@ export class Moro extends EventEmitter {
1841
1989
  });
1842
1990
  }),
1843
1991
  new Promise(resolve => {
1844
- const timer = setTimeout(resolve, 2000); // 2 second timeout
1992
+ const timer = setTimeout(() => {
1993
+ try {
1994
+ server?.closeAllConnections?.();
1995
+ }
1996
+ catch {
1997
+ // best-effort force-close
1998
+ }
1999
+ resolve();
2000
+ }, 2000); // 2 second grace period
1845
2001
  timer.unref(); // Don't keep process alive
1846
2002
  }),
1847
2003
  ]);
@@ -1951,19 +2107,21 @@ export class Moro extends EventEmitter {
1951
2107
  }
1952
2108
  const jobOptions = {
1953
2109
  name: options.name || name,
1954
- enabled: options.enabled,
1955
- priority: options.priority,
1956
- timezone: options.timezone,
1957
- maxConcurrent: options.maxConcurrent,
1958
- timeout: options.timeout,
1959
- maxRetries: options.maxRetries,
1960
- retryDelay: options.retryDelay,
1961
- retryBackoff: options.retryBackoff,
1962
- enableCircuitBreaker: options.enableCircuitBreaker,
1963
- metadata: options.metadata,
1964
- onStart: options.onStart,
1965
- onComplete: options.onComplete,
1966
- onError: options.onError,
2110
+ ...(options.enabled !== undefined ? { enabled: options.enabled } : {}),
2111
+ ...(options.priority !== undefined ? { priority: options.priority } : {}),
2112
+ ...(options.timezone !== undefined ? { timezone: options.timezone } : {}),
2113
+ ...(options.maxConcurrent !== undefined ? { maxConcurrent: options.maxConcurrent } : {}),
2114
+ ...(options.timeout !== undefined ? { timeout: options.timeout } : {}),
2115
+ ...(options.maxRetries !== undefined ? { maxRetries: options.maxRetries } : {}),
2116
+ ...(options.retryDelay !== undefined ? { retryDelay: options.retryDelay } : {}),
2117
+ ...(options.retryBackoff !== undefined ? { retryBackoff: options.retryBackoff } : {}),
2118
+ ...(options.enableCircuitBreaker !== undefined
2119
+ ? { enableCircuitBreaker: options.enableCircuitBreaker }
2120
+ : {}),
2121
+ ...(options.metadata !== undefined ? { metadata: options.metadata } : {}),
2122
+ ...(options.onStart !== undefined ? { onStart: options.onStart } : {}),
2123
+ ...(options.onComplete !== undefined ? { onComplete: options.onComplete } : {}),
2124
+ ...(options.onError !== undefined ? { onError: options.onError } : {}),
1967
2125
  };
1968
2126
  const jobId = this.jobScheduler.registerJob(name, jobSchedule, handler, jobOptions);
1969
2127
  this.logger.info(`Job registered: ${name} (${jobId})`);
@@ -2131,7 +2289,7 @@ export class Moro extends EventEmitter {
2131
2289
  // Store config and trigger initialization immediately
2132
2290
  this.graphqlConfig = options;
2133
2291
  this.graphqlInitPromise = this.initializeGraphQL(options);
2134
- this.eventBus.emit('graphql:configured', { options });
2292
+ void this.eventBus.emit('graphql:configured', { options });
2135
2293
  return this;
2136
2294
  }
2137
2295
  /**
@@ -2786,7 +2944,7 @@ export class Moro extends EventEmitter {
2786
2944
  // Store config for lazy initialization
2787
2945
  this.mailConfig = config;
2788
2946
  this.logger.debug('Mail system configured (will initialize on first use)', 'Mail');
2789
- this.eventBus.emit('mail:configured', { config });
2947
+ void this.eventBus.emit('mail:configured', { config });
2790
2948
  return this;
2791
2949
  }
2792
2950
  /**
@@ -2816,7 +2974,9 @@ export class Moro extends EventEmitter {
2816
2974
  await this.ensureQueueInitialized();
2817
2975
  await this.processQueue(queueName, async (job) => {
2818
2976
  if (this.mailManager) {
2819
- return await this.mailManager.send(job.data);
2977
+ // deliver() bypasses the queue check; send() would re-enqueue the
2978
+ // job forever and never actually transmit the email.
2979
+ return await this.mailManager.deliver(job.data);
2820
2980
  }
2821
2981
  throw new Error('Mail manager not initialized');
2822
2982
  });
@@ -2864,19 +3024,19 @@ export class Moro extends EventEmitter {
2864
3024
  async sendMail(options) {
2865
3025
  // Lazy initialize on first use
2866
3026
  await this.ensureMailInitialized();
2867
- this.eventBus.emit('mail:sending', { options });
3027
+ void this.eventBus.emit('mail:sending', { options });
2868
3028
  try {
2869
3029
  const result = await this.mailManager.send(options);
2870
3030
  if (result.success) {
2871
- this.eventBus.emit('mail:sent', { result, options });
3031
+ void this.eventBus.emit('mail:sent', { result, options });
2872
3032
  }
2873
3033
  else {
2874
- this.eventBus.emit('mail:failed', { error: new Error(result.error), options });
3034
+ void this.eventBus.emit('mail:failed', { error: new Error(result.error), options });
2875
3035
  }
2876
3036
  return result;
2877
3037
  }
2878
3038
  catch (error) {
2879
- this.eventBus.emit('mail:failed', { error, options });
3039
+ void this.eventBus.emit('mail:failed', { error, options });
2880
3040
  throw error;
2881
3041
  }
2882
3042
  }