@c9up/ream 0.1.3

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 (451) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/dist/Application.d.ts +71 -0
  4. package/dist/Application.d.ts.map +1 -0
  5. package/dist/Application.js +151 -0
  6. package/dist/Application.js.map +1 -0
  7. package/dist/Codemods.d.ts +16 -0
  8. package/dist/Codemods.d.ts.map +1 -0
  9. package/dist/Codemods.js +277 -0
  10. package/dist/Codemods.js.map +1 -0
  11. package/dist/ConfigLoader.d.ts +29 -0
  12. package/dist/ConfigLoader.d.ts.map +1 -0
  13. package/dist/ConfigLoader.js +43 -0
  14. package/dist/ConfigLoader.js.map +1 -0
  15. package/dist/ErrorBoundary.d.ts +51 -0
  16. package/dist/ErrorBoundary.d.ts.map +1 -0
  17. package/dist/ErrorBoundary.js +122 -0
  18. package/dist/ErrorBoundary.js.map +1 -0
  19. package/dist/GracefulShutdown.d.ts +28 -0
  20. package/dist/GracefulShutdown.d.ts.map +1 -0
  21. package/dist/GracefulShutdown.js +55 -0
  22. package/dist/GracefulShutdown.js.map +1 -0
  23. package/dist/HealthCheck.d.ts +42 -0
  24. package/dist/HealthCheck.d.ts.map +1 -0
  25. package/dist/HealthCheck.js +65 -0
  26. package/dist/HealthCheck.js.map +1 -0
  27. package/dist/HotReload.d.ts +28 -0
  28. package/dist/HotReload.d.ts.map +1 -0
  29. package/dist/HotReload.js +60 -0
  30. package/dist/HotReload.js.map +1 -0
  31. package/dist/HttpKernel.d.ts +62 -0
  32. package/dist/HttpKernel.d.ts.map +1 -0
  33. package/dist/HttpKernel.js +210 -0
  34. package/dist/HttpKernel.js.map +1 -0
  35. package/dist/Ignitor.d.ts +195 -0
  36. package/dist/Ignitor.d.ts.map +1 -0
  37. package/dist/Ignitor.js +505 -0
  38. package/dist/Ignitor.js.map +1 -0
  39. package/dist/Provider.d.ts +54 -0
  40. package/dist/Provider.d.ts.map +1 -0
  41. package/dist/Provider.js +37 -0
  42. package/dist/Provider.js.map +1 -0
  43. package/dist/bodyparser/BodyParserMiddleware.d.ts +38 -0
  44. package/dist/bodyparser/BodyParserMiddleware.d.ts.map +1 -0
  45. package/dist/bodyparser/BodyParserMiddleware.js +143 -0
  46. package/dist/bodyparser/BodyParserMiddleware.js.map +1 -0
  47. package/dist/bodyparser/MultipartFile.d.ts +77 -0
  48. package/dist/bodyparser/MultipartFile.d.ts.map +1 -0
  49. package/dist/bodyparser/MultipartFile.js +138 -0
  50. package/dist/bodyparser/MultipartFile.js.map +1 -0
  51. package/dist/bodyparser/parseSize.d.ts +6 -0
  52. package/dist/bodyparser/parseSize.d.ts.map +1 -0
  53. package/dist/bodyparser/parseSize.js +21 -0
  54. package/dist/bodyparser/parseSize.js.map +1 -0
  55. package/dist/bootstrap/hyper-server.d.ts +27 -0
  56. package/dist/bootstrap/hyper-server.d.ts.map +1 -0
  57. package/dist/bootstrap/hyper-server.js +63 -0
  58. package/dist/bootstrap/hyper-server.js.map +1 -0
  59. package/dist/console/CommandRunner.d.ts +18 -0
  60. package/dist/console/CommandRunner.d.ts.map +1 -0
  61. package/dist/console/CommandRunner.js +65 -0
  62. package/dist/console/CommandRunner.js.map +1 -0
  63. package/dist/container/Container.d.ts +60 -0
  64. package/dist/container/Container.d.ts.map +1 -0
  65. package/dist/container/Container.js +329 -0
  66. package/dist/container/Container.js.map +1 -0
  67. package/dist/container/types.d.ts +25 -0
  68. package/dist/container/types.d.ts.map +1 -0
  69. package/dist/container/types.js +6 -0
  70. package/dist/container/types.js.map +1 -0
  71. package/dist/decorators/Lazy.d.ts +19 -0
  72. package/dist/decorators/Lazy.d.ts.map +1 -0
  73. package/dist/decorators/Lazy.js +53 -0
  74. package/dist/decorators/Lazy.js.map +1 -0
  75. package/dist/decorators/Service.d.ts +48 -0
  76. package/dist/decorators/Service.d.ts.map +1 -0
  77. package/dist/decorators/Service.js +70 -0
  78. package/dist/decorators/Service.js.map +1 -0
  79. package/dist/errors/FuzzyMatcher.d.ts +41 -0
  80. package/dist/errors/FuzzyMatcher.d.ts.map +1 -0
  81. package/dist/errors/FuzzyMatcher.js +81 -0
  82. package/dist/errors/FuzzyMatcher.js.map +1 -0
  83. package/dist/errors/ModuleErrors.d.ts +41 -0
  84. package/dist/errors/ModuleErrors.d.ts.map +1 -0
  85. package/dist/errors/ModuleErrors.js +65 -0
  86. package/dist/errors/ModuleErrors.js.map +1 -0
  87. package/dist/errors/PipelineStageError.d.ts +31 -0
  88. package/dist/errors/PipelineStageError.d.ts.map +1 -0
  89. package/dist/errors/PipelineStageError.js +77 -0
  90. package/dist/errors/PipelineStageError.js.map +1 -0
  91. package/dist/errors/ReamError.d.ts +50 -0
  92. package/dist/errors/ReamError.d.ts.map +1 -0
  93. package/dist/errors/ReamError.js +108 -0
  94. package/dist/errors/ReamError.js.map +1 -0
  95. package/dist/events/Emitter.d.ts +124 -0
  96. package/dist/events/Emitter.d.ts.map +1 -0
  97. package/dist/events/Emitter.js +271 -0
  98. package/dist/events/Emitter.js.map +1 -0
  99. package/dist/events/EventsProvider.d.ts +28 -0
  100. package/dist/events/EventsProvider.d.ts.map +1 -0
  101. package/dist/events/EventsProvider.js +36 -0
  102. package/dist/events/EventsProvider.js.map +1 -0
  103. package/dist/events/config.d.ts +8 -0
  104. package/dist/events/config.d.ts.map +1 -0
  105. package/dist/events/config.js +4 -0
  106. package/dist/events/config.js.map +1 -0
  107. package/dist/events/configure.d.ts +10 -0
  108. package/dist/events/configure.d.ts.map +1 -0
  109. package/dist/events/configure.js +11 -0
  110. package/dist/events/configure.js.map +1 -0
  111. package/dist/events/helix/helpers.d.ts +62 -0
  112. package/dist/events/helix/helpers.d.ts.map +1 -0
  113. package/dist/events/helix/helpers.js +187 -0
  114. package/dist/events/helix/helpers.js.map +1 -0
  115. package/dist/events/index.d.ts +17 -0
  116. package/dist/events/index.d.ts.map +1 -0
  117. package/dist/events/index.js +15 -0
  118. package/dist/events/index.js.map +1 -0
  119. package/dist/events/native.d.ts +21 -0
  120. package/dist/events/native.d.ts.map +1 -0
  121. package/dist/events/native.js +17 -0
  122. package/dist/events/native.js.map +1 -0
  123. package/dist/events/services/main.d.ts +18 -0
  124. package/dist/events/services/main.d.ts.map +1 -0
  125. package/dist/events/services/main.js +31 -0
  126. package/dist/events/services/main.js.map +1 -0
  127. package/dist/events/testing/FakeBus.d.ts +66 -0
  128. package/dist/events/testing/FakeBus.d.ts.map +1 -0
  129. package/dist/events/testing/FakeBus.js +356 -0
  130. package/dist/events/testing/FakeBus.js.map +1 -0
  131. package/dist/graphql/GraphQLEngine.d.ts +69 -0
  132. package/dist/graphql/GraphQLEngine.d.ts.map +1 -0
  133. package/dist/graphql/GraphQLEngine.js +309 -0
  134. package/dist/graphql/GraphQLEngine.js.map +1 -0
  135. package/dist/graphql/GraphQLProvider.d.ts +32 -0
  136. package/dist/graphql/GraphQLProvider.d.ts.map +1 -0
  137. package/dist/graphql/GraphQLProvider.js +49 -0
  138. package/dist/graphql/GraphQLProvider.js.map +1 -0
  139. package/dist/helpers/base64.d.ts +40 -0
  140. package/dist/helpers/base64.d.ts.map +1 -0
  141. package/dist/helpers/base64.js +70 -0
  142. package/dist/helpers/base64.js.map +1 -0
  143. package/dist/helpers/index.d.ts +7 -0
  144. package/dist/helpers/index.d.ts.map +1 -0
  145. package/dist/helpers/index.js +5 -0
  146. package/dist/helpers/index.js.map +1 -0
  147. package/dist/helpers/is.d.ts +101 -0
  148. package/dist/helpers/is.d.ts.map +1 -0
  149. package/dist/helpers/is.js +151 -0
  150. package/dist/helpers/is.js.map +1 -0
  151. package/dist/helpers/napi-loader.d.ts +46 -0
  152. package/dist/helpers/napi-loader.d.ts.map +1 -0
  153. package/dist/helpers/napi-loader.js +69 -0
  154. package/dist/helpers/napi-loader.js.map +1 -0
  155. package/dist/helpers/safeEqual.d.ts +9 -0
  156. package/dist/helpers/safeEqual.d.ts.map +1 -0
  157. package/dist/helpers/safeEqual.js +16 -0
  158. package/dist/helpers/safeEqual.js.map +1 -0
  159. package/dist/helpers/string.d.ts +161 -0
  160. package/dist/helpers/string.d.ts.map +1 -0
  161. package/dist/helpers/string.js +429 -0
  162. package/dist/helpers/string.js.map +1 -0
  163. package/dist/helpers/types.d.ts +83 -0
  164. package/dist/helpers/types.d.ts.map +1 -0
  165. package/dist/helpers/types.js +6 -0
  166. package/dist/helpers/types.js.map +1 -0
  167. package/dist/http/Exception.d.ts +103 -0
  168. package/dist/http/Exception.d.ts.map +1 -0
  169. package/dist/http/Exception.js +228 -0
  170. package/dist/http/Exception.js.map +1 -0
  171. package/dist/http/HttpContext.d.ts +69 -0
  172. package/dist/http/HttpContext.d.ts.map +1 -0
  173. package/dist/http/HttpContext.js +55 -0
  174. package/dist/http/HttpContext.js.map +1 -0
  175. package/dist/http/RedirectBuilder.d.ts +31 -0
  176. package/dist/http/RedirectBuilder.d.ts.map +1 -0
  177. package/dist/http/RedirectBuilder.js +75 -0
  178. package/dist/http/RedirectBuilder.js.map +1 -0
  179. package/dist/http/Request.d.ts +160 -0
  180. package/dist/http/Request.d.ts.map +1 -0
  181. package/dist/http/Request.js +484 -0
  182. package/dist/http/Request.js.map +1 -0
  183. package/dist/http/Response.d.ts +114 -0
  184. package/dist/http/Response.d.ts.map +1 -0
  185. package/dist/http/Response.js +303 -0
  186. package/dist/http/Response.js.map +1 -0
  187. package/dist/http/SseStream.d.ts +89 -0
  188. package/dist/http/SseStream.d.ts.map +1 -0
  189. package/dist/http/SseStream.js +228 -0
  190. package/dist/http/SseStream.js.map +1 -0
  191. package/dist/http/urlDecode.d.ts +8 -0
  192. package/dist/http/urlDecode.d.ts.map +1 -0
  193. package/dist/http/urlDecode.js +18 -0
  194. package/dist/http/urlDecode.js.map +1 -0
  195. package/dist/index.d.ts +92 -0
  196. package/dist/index.d.ts.map +1 -0
  197. package/dist/index.js +67 -0
  198. package/dist/index.js.map +1 -0
  199. package/dist/middleware/Pipeline.d.ts +36 -0
  200. package/dist/middleware/Pipeline.d.ts.map +1 -0
  201. package/dist/middleware/Pipeline.js +104 -0
  202. package/dist/middleware/Pipeline.js.map +1 -0
  203. package/dist/openapi/OpenApiGenerator.d.ts +58 -0
  204. package/dist/openapi/OpenApiGenerator.d.ts.map +1 -0
  205. package/dist/openapi/OpenApiGenerator.js +192 -0
  206. package/dist/openapi/OpenApiGenerator.js.map +1 -0
  207. package/dist/openapi/OpenApiMiddleware.d.ts +24 -0
  208. package/dist/openapi/OpenApiMiddleware.d.ts.map +1 -0
  209. package/dist/openapi/OpenApiMiddleware.js +78 -0
  210. package/dist/openapi/OpenApiMiddleware.js.map +1 -0
  211. package/dist/openapi/OpenApiProvider.d.ts +36 -0
  212. package/dist/openapi/OpenApiProvider.d.ts.map +1 -0
  213. package/dist/openapi/OpenApiProvider.js +42 -0
  214. package/dist/openapi/OpenApiProvider.js.map +1 -0
  215. package/dist/resources/ApiResource.d.ts +45 -0
  216. package/dist/resources/ApiResource.d.ts.map +1 -0
  217. package/dist/resources/ApiResource.js +58 -0
  218. package/dist/resources/ApiResource.js.map +1 -0
  219. package/dist/router/Router.d.ts +205 -0
  220. package/dist/router/Router.d.ts.map +1 -0
  221. package/dist/router/Router.js +552 -0
  222. package/dist/router/Router.js.map +1 -0
  223. package/dist/rpc/RpcProvider.d.ts +34 -0
  224. package/dist/rpc/RpcProvider.d.ts.map +1 -0
  225. package/dist/rpc/RpcProvider.js +37 -0
  226. package/dist/rpc/RpcProvider.js.map +1 -0
  227. package/dist/rpc/RpcRouter.d.ts +61 -0
  228. package/dist/rpc/RpcRouter.d.ts.map +1 -0
  229. package/dist/rpc/RpcRouter.js +187 -0
  230. package/dist/rpc/RpcRouter.js.map +1 -0
  231. package/dist/scheduler/Schedule.d.ts +53 -0
  232. package/dist/scheduler/Schedule.d.ts.map +1 -0
  233. package/dist/scheduler/Schedule.js +76 -0
  234. package/dist/scheduler/Schedule.js.map +1 -0
  235. package/dist/scheduler/ScheduleProvider.d.ts +56 -0
  236. package/dist/scheduler/ScheduleProvider.d.ts.map +1 -0
  237. package/dist/scheduler/ScheduleProvider.js +145 -0
  238. package/dist/scheduler/ScheduleProvider.js.map +1 -0
  239. package/dist/scheduler/Scheduler.d.ts +209 -0
  240. package/dist/scheduler/Scheduler.d.ts.map +1 -0
  241. package/dist/scheduler/Scheduler.js +432 -0
  242. package/dist/scheduler/Scheduler.js.map +1 -0
  243. package/dist/scheduler/index.d.ts +14 -0
  244. package/dist/scheduler/index.d.ts.map +1 -0
  245. package/dist/scheduler/index.js +6 -0
  246. package/dist/scheduler/index.js.map +1 -0
  247. package/dist/scheduler/locks/LockBackend.d.ts +37 -0
  248. package/dist/scheduler/locks/LockBackend.d.ts.map +1 -0
  249. package/dist/scheduler/locks/LockBackend.js +13 -0
  250. package/dist/scheduler/locks/LockBackend.js.map +1 -0
  251. package/dist/scheduler/locks/MemoryLockBackend.d.ts +39 -0
  252. package/dist/scheduler/locks/MemoryLockBackend.d.ts.map +1 -0
  253. package/dist/scheduler/locks/MemoryLockBackend.js +71 -0
  254. package/dist/scheduler/locks/MemoryLockBackend.js.map +1 -0
  255. package/dist/scheduler/observability/ErrorReporter.d.ts +15 -0
  256. package/dist/scheduler/observability/ErrorReporter.d.ts.map +1 -0
  257. package/dist/scheduler/observability/ErrorReporter.js +13 -0
  258. package/dist/scheduler/observability/ErrorReporter.js.map +1 -0
  259. package/dist/scheduler/observability/ScheduleEvent.d.ts +57 -0
  260. package/dist/scheduler/observability/ScheduleEvent.d.ts.map +1 -0
  261. package/dist/scheduler/observability/ScheduleEvent.js +12 -0
  262. package/dist/scheduler/observability/ScheduleEvent.js.map +1 -0
  263. package/dist/scheduler/observability/ScheduleEventSink.d.ts +20 -0
  264. package/dist/scheduler/observability/ScheduleEventSink.d.ts.map +1 -0
  265. package/dist/scheduler/observability/ScheduleEventSink.js +17 -0
  266. package/dist/scheduler/observability/ScheduleEventSink.js.map +1 -0
  267. package/dist/scheduler/observability/StatsTracker.d.ts +50 -0
  268. package/dist/scheduler/observability/StatsTracker.d.ts.map +1 -0
  269. package/dist/scheduler/observability/StatsTracker.js +96 -0
  270. package/dist/scheduler/observability/StatsTracker.js.map +1 -0
  271. package/dist/security/CookieSigner.d.ts +13 -0
  272. package/dist/security/CookieSigner.d.ts.map +1 -0
  273. package/dist/security/CookieSigner.js +51 -0
  274. package/dist/security/CookieSigner.js.map +1 -0
  275. package/dist/security/SignedUrl.d.ts +17 -0
  276. package/dist/security/SignedUrl.d.ts.map +1 -0
  277. package/dist/security/SignedUrl.js +63 -0
  278. package/dist/security/SignedUrl.js.map +1 -0
  279. package/dist/security/crypto.d.ts +25 -0
  280. package/dist/security/crypto.d.ts.map +1 -0
  281. package/dist/security/crypto.js +82 -0
  282. package/dist/security/crypto.js.map +1 -0
  283. package/dist/server/HyperServer.d.ts +64 -0
  284. package/dist/server/HyperServer.d.ts.map +1 -0
  285. package/dist/server/HyperServer.js +54 -0
  286. package/dist/server/HyperServer.js.map +1 -0
  287. package/dist/server/Server.d.ts +68 -0
  288. package/dist/server/Server.d.ts.map +1 -0
  289. package/dist/server/Server.js +113 -0
  290. package/dist/server/Server.js.map +1 -0
  291. package/dist/services/app.d.ts +14 -0
  292. package/dist/services/app.d.ts.map +1 -0
  293. package/dist/services/app.js +27 -0
  294. package/dist/services/app.js.map +1 -0
  295. package/dist/services/router.d.ts +21 -0
  296. package/dist/services/router.d.ts.map +1 -0
  297. package/dist/services/router.js +36 -0
  298. package/dist/services/router.js.map +1 -0
  299. package/dist/services/server.d.ts +16 -0
  300. package/dist/services/server.d.ts.map +1 -0
  301. package/dist/services/server.js +32 -0
  302. package/dist/services/server.js.map +1 -0
  303. package/dist/session/Session.d.ts +88 -0
  304. package/dist/session/Session.d.ts.map +1 -0
  305. package/dist/session/Session.js +186 -0
  306. package/dist/session/Session.js.map +1 -0
  307. package/dist/session/SessionMiddleware.d.ts +16 -0
  308. package/dist/session/SessionMiddleware.d.ts.map +1 -0
  309. package/dist/session/SessionMiddleware.js +132 -0
  310. package/dist/session/SessionMiddleware.js.map +1 -0
  311. package/dist/session/drivers/CookieDriver.d.ts +17 -0
  312. package/dist/session/drivers/CookieDriver.d.ts.map +1 -0
  313. package/dist/session/drivers/CookieDriver.js +42 -0
  314. package/dist/session/drivers/CookieDriver.js.map +1 -0
  315. package/dist/session/drivers/MemoryDriver.d.ts +9 -0
  316. package/dist/session/drivers/MemoryDriver.d.ts.map +1 -0
  317. package/dist/session/drivers/MemoryDriver.js +24 -0
  318. package/dist/session/drivers/MemoryDriver.js.map +1 -0
  319. package/dist/storage/S3Driver.d.ts +27 -0
  320. package/dist/storage/S3Driver.d.ts.map +1 -0
  321. package/dist/storage/S3Driver.js +135 -0
  322. package/dist/storage/S3Driver.js.map +1 -0
  323. package/dist/storage/StaticMiddleware.d.ts +27 -0
  324. package/dist/storage/StaticMiddleware.d.ts.map +1 -0
  325. package/dist/storage/StaticMiddleware.js +153 -0
  326. package/dist/storage/StaticMiddleware.js.map +1 -0
  327. package/dist/storage/StaticProvider.d.ts +26 -0
  328. package/dist/storage/StaticProvider.d.ts.map +1 -0
  329. package/dist/storage/StaticProvider.js +31 -0
  330. package/dist/storage/StaticProvider.js.map +1 -0
  331. package/dist/storage/StorageManager.d.ts +31 -0
  332. package/dist/storage/StorageManager.d.ts.map +1 -0
  333. package/dist/storage/StorageManager.js +120 -0
  334. package/dist/storage/StorageManager.js.map +1 -0
  335. package/dist/testing/RequestBuilder.d.ts +67 -0
  336. package/dist/testing/RequestBuilder.d.ts.map +1 -0
  337. package/dist/testing/RequestBuilder.js +202 -0
  338. package/dist/testing/RequestBuilder.js.map +1 -0
  339. package/dist/testing/TestClient.d.ts +96 -0
  340. package/dist/testing/TestClient.d.ts.map +1 -0
  341. package/dist/testing/TestClient.js +263 -0
  342. package/dist/testing/TestClient.js.map +1 -0
  343. package/dist/types/helpers.d.ts +47 -0
  344. package/dist/types/helpers.d.ts.map +1 -0
  345. package/dist/types/helpers.js +5 -0
  346. package/dist/types/helpers.js.map +1 -0
  347. package/events.darwin-arm64.node +0 -0
  348. package/events.darwin-x64.node +0 -0
  349. package/events.linux-arm64-gnu.node +0 -0
  350. package/events.linux-x64-gnu.node +0 -0
  351. package/events.win32-x64-msvc.node +0 -0
  352. package/index.darwin-arm64.node +0 -0
  353. package/index.darwin-x64.node +0 -0
  354. package/index.linux-arm64-gnu.node +0 -0
  355. package/index.linux-x64-gnu.node +0 -0
  356. package/index.win32-x64-msvc.node +0 -0
  357. package/package.json +106 -0
  358. package/scheduler.darwin-arm64.node +0 -0
  359. package/scheduler.darwin-x64.node +0 -0
  360. package/scheduler.linux-arm64-gnu.node +0 -0
  361. package/scheduler.linux-x64-gnu.node +0 -0
  362. package/scheduler.win32-x64-msvc.node +0 -0
  363. package/scripts/copy-napi.mjs +113 -0
  364. package/src/Application.ts +177 -0
  365. package/src/Codemods.ts +343 -0
  366. package/src/ConfigLoader.ts +49 -0
  367. package/src/ErrorBoundary.ts +157 -0
  368. package/src/GracefulShutdown.ts +80 -0
  369. package/src/HealthCheck.ts +96 -0
  370. package/src/HotReload.ts +78 -0
  371. package/src/HttpKernel.ts +305 -0
  372. package/src/Ignitor.ts +656 -0
  373. package/src/Provider.ts +74 -0
  374. package/src/bodyparser/BodyParserMiddleware.ts +183 -0
  375. package/src/bodyparser/MultipartFile.ts +181 -0
  376. package/src/bodyparser/parseSize.ts +19 -0
  377. package/src/bootstrap/hyper-server.ts +78 -0
  378. package/src/console/CommandRunner.ts +82 -0
  379. package/src/container/Container.ts +383 -0
  380. package/src/container/types.ts +30 -0
  381. package/src/decorators/Lazy.ts +57 -0
  382. package/src/decorators/Service.ts +85 -0
  383. package/src/errors/FuzzyMatcher.ts +93 -0
  384. package/src/errors/ModuleErrors.ts +73 -0
  385. package/src/errors/PipelineStageError.ts +97 -0
  386. package/src/errors/ReamError.ts +138 -0
  387. package/src/events/Emitter.ts +333 -0
  388. package/src/events/EventsProvider.ts +58 -0
  389. package/src/events/config.ts +10 -0
  390. package/src/events/configure.ts +19 -0
  391. package/src/events/helix/helpers.ts +260 -0
  392. package/src/events/index.ts +22 -0
  393. package/src/events/native.ts +37 -0
  394. package/src/events/services/main.ts +39 -0
  395. package/src/events/testing/FakeBus.ts +420 -0
  396. package/src/graphql/GraphQLEngine.ts +421 -0
  397. package/src/graphql/GraphQLProvider.ts +59 -0
  398. package/src/helpers/base64.ts +72 -0
  399. package/src/helpers/index.ts +6 -0
  400. package/src/helpers/is.ts +162 -0
  401. package/src/helpers/napi-loader.ts +106 -0
  402. package/src/helpers/safeEqual.ts +15 -0
  403. package/src/helpers/string.ts +469 -0
  404. package/src/helpers/types.ts +100 -0
  405. package/src/http/Exception.ts +272 -0
  406. package/src/http/HttpContext.ts +108 -0
  407. package/src/http/RedirectBuilder.ts +89 -0
  408. package/src/http/Request.ts +540 -0
  409. package/src/http/Response.ts +351 -0
  410. package/src/http/SseStream.ts +250 -0
  411. package/src/http/urlDecode.ts +18 -0
  412. package/src/index.ts +263 -0
  413. package/src/middleware/Pipeline.ts +136 -0
  414. package/src/openapi/OpenApiGenerator.ts +254 -0
  415. package/src/openapi/OpenApiMiddleware.ts +101 -0
  416. package/src/openapi/OpenApiProvider.ts +67 -0
  417. package/src/resources/ApiResource.ts +79 -0
  418. package/src/router/Router.ts +733 -0
  419. package/src/rpc/RpcProvider.ts +54 -0
  420. package/src/rpc/RpcRouter.ts +243 -0
  421. package/src/scheduler/Schedule.ts +96 -0
  422. package/src/scheduler/ScheduleProvider.ts +177 -0
  423. package/src/scheduler/Scheduler.ts +601 -0
  424. package/src/scheduler/index.ts +24 -0
  425. package/src/scheduler/locks/LockBackend.ts +38 -0
  426. package/src/scheduler/locks/MemoryLockBackend.ts +85 -0
  427. package/src/scheduler/observability/ErrorReporter.ts +13 -0
  428. package/src/scheduler/observability/ScheduleEvent.ts +61 -0
  429. package/src/scheduler/observability/ScheduleEventSink.ts +21 -0
  430. package/src/scheduler/observability/StatsTracker.ts +134 -0
  431. package/src/security/CookieSigner.ts +54 -0
  432. package/src/security/SignedUrl.ts +71 -0
  433. package/src/security/crypto.ts +98 -0
  434. package/src/server/HyperServer.ts +121 -0
  435. package/src/server/Server.ts +147 -0
  436. package/src/services/app.ts +34 -0
  437. package/src/services/router.ts +44 -0
  438. package/src/services/server.ts +40 -0
  439. package/src/session/Session.ts +231 -0
  440. package/src/session/SessionMiddleware.ts +153 -0
  441. package/src/session/drivers/CookieDriver.ts +48 -0
  442. package/src/session/drivers/MemoryDriver.ts +29 -0
  443. package/src/storage/S3Driver.ts +171 -0
  444. package/src/storage/StaticMiddleware.ts +182 -0
  445. package/src/storage/StaticProvider.ts +40 -0
  446. package/src/storage/StorageManager.ts +142 -0
  447. package/src/testing/RequestBuilder.ts +275 -0
  448. package/src/testing/TestClient.ts +344 -0
  449. package/src/types/helpers.ts +52 -0
  450. package/swcrc.app.json +17 -0
  451. package/tsconfig.app.json +21 -0
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Module-specific error subclasses.
3
+ *
4
+ * Each module gets its own error class with appropriate defaults.
5
+ *
6
+ * @implements FR71
7
+ */
8
+
9
+ import { ReamError } from './ReamError.js'
10
+
11
+ /** Container / IoC errors */
12
+ export class ContainerError extends ReamError {
13
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
14
+ super(`CONTAINER_${code}`, message, options)
15
+ this.name = 'ContainerError'
16
+ }
17
+ }
18
+
19
+ /** Router errors */
20
+ export class RouterError extends ReamError {
21
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
22
+ super(`ROUTER_${code}`, message, options)
23
+ this.name = 'RouterError'
24
+ }
25
+ }
26
+
27
+ /** Pipeline / Middleware errors */
28
+ export class PipelineError extends ReamError {
29
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
30
+ super(`PIPELINE_${code}`, message, options)
31
+ this.name = 'PipelineError'
32
+ }
33
+ }
34
+
35
+ /** Atlas ORM errors */
36
+ export class AtlasError extends ReamError {
37
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
38
+ super(`ATLAS_${code}`, message, options)
39
+ this.name = 'AtlasError'
40
+ }
41
+ }
42
+
43
+ /** Rune validation errors */
44
+ export class RuneError extends ReamError {
45
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
46
+ super(`RUNE_${code}`, message, options)
47
+ this.name = 'RuneError'
48
+ }
49
+ }
50
+
51
+ /** Warden auth errors */
52
+ export class WardenError extends ReamError {
53
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
54
+ super(`WARDEN_${code}`, message, options)
55
+ this.name = 'WardenError'
56
+ }
57
+ }
58
+
59
+ /** Event bus errors */
60
+ export class EventsError extends ReamError {
61
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
62
+ super(`EVENTS_${code}`, message, options)
63
+ this.name = 'EventsError'
64
+ }
65
+ }
66
+
67
+ /** Forge CLI errors */
68
+ export class ForgeError extends ReamError {
69
+ constructor(code: string, message: string, options?: ConstructorParameters<typeof ReamError>[2]) {
70
+ super(`FORGE_${code}`, message, options)
71
+ this.name = 'ForgeError'
72
+ }
73
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Pipeline Stage Error — indicates which pipeline stage failed.
3
+ *
4
+ * @implements FR73
5
+ */
6
+
7
+ import { ReamError } from './ReamError.js'
8
+
9
+ /** Pipeline stage names in execution order. */
10
+ export const PIPELINE_STAGES = [
11
+ 'Security (Blackhole)',
12
+ 'Logging',
13
+ 'Global Middleware',
14
+ 'Named Middleware',
15
+ 'Guard',
16
+ 'Validate',
17
+ 'Transaction',
18
+ 'Handler',
19
+ 'After Middleware',
20
+ 'Response Logging',
21
+ ] as const
22
+
23
+ export type PipelineStageName = (typeof PIPELINE_STAGES)[number]
24
+
25
+ /**
26
+ * Create a pipeline stage error with position context.
27
+ *
28
+ * @param stageIndex - Zero-based index in PIPELINE_STAGES (clamped to valid range)
29
+ * @param originalError - The error that occurred
30
+ * @param context - Additional context
31
+ */
32
+ export function createPipelineError(
33
+ stageIndex: number,
34
+ originalError: Error,
35
+ context?: Record<string, string>,
36
+ ): ReamError {
37
+ const total = PIPELINE_STAGES.length
38
+ const clampedIndex = Math.max(0, Math.min(stageIndex, total - 1))
39
+ const stageName = PIPELINE_STAGES[clampedIndex]
40
+ const position = `${clampedIndex + 1}/${total}`
41
+ const nextStage = clampedIndex + 1 < total ? PIPELINE_STAGES[clampedIndex + 1] : '(end)'
42
+
43
+ const errorCode = originalError instanceof ReamError ? originalError.code : 'PIPELINE_ERROR'
44
+
45
+ return new ReamError(errorCode, originalError.message, {
46
+ pipelineStage: `${position} (${stageName})`,
47
+ hint: `Error occurred at pipeline stage ${position} (${stageName}). Next stage would have been: ${nextStage}.`,
48
+ context: {
49
+ ...context,
50
+ stage: stageName,
51
+ position,
52
+ nextStage,
53
+ },
54
+ sourceFile: originalError instanceof ReamError ? originalError.sourceFile : undefined,
55
+ sourceLine: originalError instanceof ReamError ? originalError.sourceLine : undefined,
56
+ docsUrl: originalError instanceof ReamError ? originalError.docsUrl : undefined,
57
+ })
58
+ }
59
+
60
+ /**
61
+ * Validate pipeline configuration at boot time.
62
+ * Detects misconfiguration before accepting traffic.
63
+ *
64
+ * @implements FR74
65
+ */
66
+ export function validatePipelineConfig(config: {
67
+ globalMiddleware?: unknown[]
68
+ namedMiddleware?: Record<string, unknown>
69
+ routes?: Array<{ middleware?: string[] }>
70
+ }): ReamError[] {
71
+ const errors: ReamError[] = []
72
+
73
+ // Check named middleware references exist (deduplicated)
74
+ if (config.routes && config.namedMiddleware) {
75
+ const registered = new Set(Object.keys(config.namedMiddleware))
76
+ const reported = new Set<string>()
77
+
78
+ for (const route of config.routes) {
79
+ for (const mw of route.middleware ?? []) {
80
+ if (!registered.has(mw) && !reported.has(mw)) {
81
+ reported.add(mw)
82
+ errors.push(
83
+ new ReamError('PIPELINE_UNKNOWN_MIDDLEWARE', `Middleware '${mw}' is not registered`, {
84
+ hint: `Register it with middleware.register('${mw}', handler) before using it on routes.`,
85
+ context: {
86
+ middleware: mw,
87
+ registered: [...registered].join(', '),
88
+ },
89
+ }),
90
+ )
91
+ }
92
+ }
93
+ }
94
+ }
95
+
96
+ return errors
97
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Base ReamError class for TypeScript.
3
+ *
4
+ * Parses structured JSON errors from Rust NAPI boundary and provides
5
+ * rich error context (code, hint, source location, docs URL).
6
+ *
7
+ * @implements FR71, FR72, FR73, FR77
8
+ */
9
+
10
+ export class ReamError extends Error {
11
+ /** Error code (e.g., "ATLAS_QUERY_ERROR", "CONTAINER_NOT_FOUND") */
12
+ readonly code: string
13
+
14
+ /** Additional context key-value pairs */
15
+ readonly context: Record<string, string>
16
+
17
+ /** Actionable hint for the developer */
18
+ readonly hint?: string
19
+
20
+ /** Source file where the error originated */
21
+ readonly sourceFile?: string
22
+
23
+ /** Line number in the source file */
24
+ readonly sourceLine?: number
25
+
26
+ /** URL to the error documentation page */
27
+ readonly docsUrl?: string
28
+
29
+ /** Pipeline stage where the error occurred (if applicable) */
30
+ readonly pipelineStage?: string
31
+
32
+ constructor(
33
+ code: string,
34
+ message: string,
35
+ options?: {
36
+ context?: Record<string, string>
37
+ hint?: string
38
+ sourceFile?: string
39
+ sourceLine?: number
40
+ docsUrl?: string
41
+ pipelineStage?: string
42
+ },
43
+ ) {
44
+ super(message)
45
+ this.name = 'ReamError'
46
+ this.code = code
47
+ this.context = options?.context ?? {}
48
+ this.hint = options?.hint
49
+ this.sourceFile = options?.sourceFile
50
+ this.sourceLine = options?.sourceLine
51
+ this.docsUrl = options?.docsUrl ?? `https://docs.ream.dev/errors/${code}`
52
+ this.pipelineStage = options?.pipelineStage
53
+ }
54
+
55
+ /**
56
+ * Parse a NAPI error message (JSON string from Rust ReamError) into a TS ReamError.
57
+ * Falls back to a generic error if parsing fails.
58
+ */
59
+ static fromNapi(error: Error): ReamError {
60
+ try {
61
+ const parsed = JSON.parse(error.message)
62
+ if (typeof parsed !== 'object' || parsed === null || typeof parsed.code !== 'string') {
63
+ return new ReamError('UNKNOWN', error.message)
64
+ }
65
+ return new ReamError(parsed.code, parsed.message ?? error.message, {
66
+ context:
67
+ typeof parsed.context === 'object' && parsed.context !== null ? parsed.context : {},
68
+ hint: typeof parsed.hint === 'string' ? parsed.hint : undefined,
69
+ sourceFile: typeof parsed.sourceFile === 'string' ? parsed.sourceFile : undefined,
70
+ sourceLine: typeof parsed.sourceLine === 'number' ? parsed.sourceLine : undefined,
71
+ docsUrl: typeof parsed.docsUrl === 'string' ? parsed.docsUrl : undefined,
72
+ })
73
+ } catch {
74
+ // Not a JSON error — wrap as generic
75
+ return new ReamError('UNKNOWN', error.message)
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Format for dev console — full box display with all details.
81
+ */
82
+ toDevString(): string {
83
+ const content: string[] = []
84
+ content.push(`[${this.code}] ${this.message}`)
85
+
86
+ if (this.pipelineStage) {
87
+ content.push(`Pipeline: ${this.pipelineStage}`)
88
+ }
89
+
90
+ if (this.sourceFile) {
91
+ content.push(`at ${this.sourceFile}${this.sourceLine ? `:${this.sourceLine}` : ''}`)
92
+ }
93
+
94
+ if (Object.keys(this.context).length > 0) {
95
+ content.push('')
96
+ for (const [key, value] of Object.entries(this.context)) {
97
+ // Escape newlines in values to prevent box corruption
98
+ const safeValue = String(value).replace(/\n/g, '\\n')
99
+ content.push(`${key}: ${safeValue}`)
100
+ }
101
+ }
102
+
103
+ if (this.hint) {
104
+ content.push('')
105
+ content.push(`Hint: ${this.hint}`)
106
+ }
107
+
108
+ if (this.docsUrl) {
109
+ content.push(`Docs: ${this.docsUrl}`)
110
+ }
111
+
112
+ // Compute border width from the longest content line
113
+ const maxLen = Math.min(Math.max(...content.map((l) => l.length)) + 4, 80)
114
+ const border = '─'.repeat(maxLen)
115
+
116
+ const lines = [`┌${border}┐`]
117
+ for (const line of content) {
118
+ lines.push(`│ ${line}`)
119
+ }
120
+ lines.push(`└${border}┘`)
121
+
122
+ return lines.join('\n')
123
+ }
124
+
125
+ /**
126
+ * Format for prod — code + message only.
127
+ */
128
+ toProdString(): string {
129
+ return `[${this.code}] ${this.message}`
130
+ }
131
+
132
+ /**
133
+ * Auto-format based on NODE_ENV.
134
+ */
135
+ toFormattedString(): string {
136
+ return process.env.NODE_ENV === 'production' ? this.toProdString() : this.toDevString()
137
+ }
138
+ }
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Emitter — AdonisJS-compatible typed event system backed by EventBus.
3
+ *
4
+ * Class-based events:
5
+ * emitter.on(TaskDeclared, SendNotification)
6
+ * await new TaskDeclared(task).emit()
7
+ *
8
+ * String-based events:
9
+ * emitter.on('user:registered', (user) => { ... })
10
+ * emitter.emit('user:registered', user)
11
+ *
12
+ * Listeners support @inject() for DI when a container resolver is provided.
13
+ */
14
+
15
+ import type { EventBus } from './native.js'
16
+
17
+ /**
18
+ * Listener class interface — must have a handle() method.
19
+ */
20
+ export interface ListenerClass<T = unknown> {
21
+ handle(event: T): Promise<void> | void
22
+ }
23
+
24
+ type EventConstructor<T = unknown> = new (...args: never[]) => T
25
+
26
+ type ListenerFn<T = unknown> = (event: T) => Promise<void> | void
27
+
28
+ type ListenerConstructor<T = unknown> = new (...args: never[]) => ListenerClass<T>
29
+
30
+ type Listener<T = unknown> = ListenerFn<T> | ListenerConstructor<T>
31
+
32
+ /** Resolver for instantiating listener classes with DI. */
33
+ export interface ContainerResolver {
34
+ make<T>(target: new (...args: never[]) => T): T
35
+ }
36
+
37
+ export class Emitter {
38
+ private bus: EventBus
39
+ private resolver?: ContainerResolver
40
+ private classListeners: Map<EventConstructor, Listener[]> = new Map()
41
+ private stringListeners: Map<string, ListenerFn[]> = new Map()
42
+
43
+ constructor(bus: EventBus, resolver?: ContainerResolver) {
44
+ this.bus = bus
45
+ this.resolver = resolver
46
+ }
47
+
48
+ // ─── Class-based events ───────────────────────────────────
49
+
50
+ /**
51
+ * Listen for a class-based event.
52
+ * emitter.on(TaskDeclared, SendNotification) // listener class
53
+ * emitter.on(TaskDeclared, (event) => { ... }) // inline function
54
+ */
55
+ on<T>(event: EventConstructor<T>, listener: Listener<T>): void
56
+ /**
57
+ * Listen for a string-based event.
58
+ * emitter.on('user:registered', (user) => { ... })
59
+ */
60
+ on(event: string, listener: ListenerFn): void
61
+ on(event: EventConstructor | string, listener: Listener): void {
62
+ if (typeof event === 'string') {
63
+ const list = this.stringListeners.get(event) ?? []
64
+ list.push(listener as ListenerFn)
65
+ this.stringListeners.set(event, list)
66
+ } else {
67
+ const list = this.classListeners.get(event) ?? []
68
+ list.push(listener)
69
+ this.classListeners.set(event, list)
70
+ }
71
+ }
72
+
73
+ // ─── Emit ─────────────────────────────────────────────────
74
+
75
+ /**
76
+ * Emit a string-based event.
77
+ */
78
+ emit(event: string, data: unknown): void {
79
+ // Dispatch to string listeners
80
+ const listeners = this.stringListeners.get(event)
81
+ if (listeners) {
82
+ for (const fn of listeners) {
83
+ Promise.resolve(fn(data)).catch((err) => {
84
+ // Surface listener errors instead of swallowing them
85
+ this.emitError(event, err)
86
+ })
87
+ }
88
+ }
89
+
90
+ // Also push through EventBus for cross-service / Rust subscribers.
91
+ // `#wrapForBus` prepends the correlation envelope when set so the ID
92
+ // reaches the other side; without it `setCorrelationId()` was a no-op.
93
+ void this.bus.emit(event, JSON.stringify(this.#wrapForBus(data))).catch((err: unknown) => {
94
+ this.emitError(event, err)
95
+ })
96
+ }
97
+
98
+ /** Emit an error event for listener failures. */
99
+ private emitError(event: string, error: unknown): void {
100
+ const errorListeners = this.stringListeners.get('emitter:error')
101
+ if (errorListeners && errorListeners.length > 0) {
102
+ for (const fn of errorListeners) {
103
+ try {
104
+ fn({ event, error })
105
+ } catch {
106
+ /* prevent infinite loop */
107
+ }
108
+ }
109
+ } else {
110
+ // No error listener — log to stderr as last resort
111
+ process.stderr.write(`[events] Listener error for '${event}': ${error}\n`)
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Dispatch a class-based event. Called by BaseEvent#emit().
117
+ */
118
+ async dispatchEvent<T extends object>(event: T): Promise<void> {
119
+ const EventClass = event.constructor as EventConstructor<T>
120
+ const listeners = this.classListeners.get(EventClass) ?? []
121
+ const name = (EventClass as { eventName?: string }).eventName ?? classToEventName(EventClass)
122
+
123
+ // Per-listener error isolation — mirrors the string `emit()` contract.
124
+ // A side-effect listener that throws (SMTP down, etc.) MUST NOT abort
125
+ // the sibling listeners NOR suppress the cross-service `bus.emit` below:
126
+ // the domain event already happened, so distributed subscribers must
127
+ // still receive it. Failures surface on the `emitter:error` channel.
128
+ for (const listener of listeners) {
129
+ try {
130
+ if (isListenerClass(listener)) {
131
+ // Listener class — resolve via container for @inject() support
132
+ const instance = this.resolver
133
+ ? this.resolver.make(listener as ListenerConstructor<T>)
134
+ : new (listener as ListenerConstructor<T>)()
135
+ await instance.handle(event)
136
+ } else {
137
+ await (listener as ListenerFn<T>)(event)
138
+ }
139
+ } catch (err) {
140
+ this.emitError(name, err)
141
+ }
142
+ }
143
+
144
+ // Also push through EventBus — same correlation-envelope wrapping as
145
+ // the string-event path so distributed tracing covers class events too.
146
+ // Reached unconditionally: a listener failure above no longer skips it.
147
+ await this.bus.emit(name, JSON.stringify(this.#wrapForBus(event)))
148
+ }
149
+
150
+ // ─── Wildcard subscriptions (via Rust NAPI) ───────────────
151
+
152
+ /**
153
+ * Subscribe to events matching a wildcard pattern.
154
+ * Uses Rust wildcard engine via NAPI for pattern matching.
155
+ *
156
+ * emitter.onAny('order.*', (name, data) => { ... }) // single segment
157
+ * emitter.onAny('order.**', (name, data) => { ... }) // deep match
158
+ */
159
+ async onAny(
160
+ pattern: string,
161
+ listener: (eventName: string, data: unknown) => void,
162
+ ): Promise<number> {
163
+ return this.bus.subscribe(pattern, (eventJson: string) => {
164
+ try {
165
+ const event = JSON.parse(eventJson)
166
+ // The bus delivers a Rust `Event` envelope whose `correlationId`
167
+ // sits at the top of the parsed JSON. Propagate it onto the
168
+ // emitter so nested emits inside the listener body inherit the
169
+ // trace context — that's the whole point of the API. `data` is
170
+ // the raw user payload string (still JSON-encoded if the
171
+ // emitter serialized an object), kept as-is for back-compat.
172
+ if (
173
+ event !== null &&
174
+ typeof event === 'object' &&
175
+ typeof event.correlationId === 'string'
176
+ ) {
177
+ this.setCorrelationId(event.correlationId)
178
+ }
179
+ listener(event.name ?? pattern, event.data ?? event)
180
+ } catch {
181
+ listener(pattern, eventJson)
182
+ }
183
+ })
184
+ }
185
+
186
+ /** Unsubscribe a wildcard subscription by ID. */
187
+ async offAny(subscriptionId: number): Promise<void> {
188
+ await this.bus.unsubscribe(subscriptionId)
189
+ }
190
+
191
+ /** Check if a pattern matches an event name (wildcard matching via Rust). */
192
+ matchesPattern(pattern: string, eventName: string): boolean {
193
+ return this.bus.matchesWildcard(pattern, eventName)
194
+ }
195
+
196
+ // ─── Request / Reply ──────────────────────────────────────
197
+
198
+ /**
199
+ * Send a request event and await a response.
200
+ *
201
+ * const user = await emitter.request('query:user.find', { id: 1 })
202
+ */
203
+ async request<T = unknown>(name: string, data: unknown, timeoutMs = 5000): Promise<T> {
204
+ // Same correlation injection as `emit()` so a `setCorrelationId`
205
+ // preceding a request actually reaches the responder via the
206
+ // top-level `correlationId` field on the parsed payload.
207
+ const result = await this.bus.request(name, JSON.stringify(this.#wrapForBus(data)), timeoutMs)
208
+ try {
209
+ return JSON.parse(result) as T
210
+ } catch {
211
+ return result as T
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Register a request handler.
217
+ *
218
+ * emitter.onRequest('query:user.find', (params, reply) => {
219
+ * const user = db.find(params.id)
220
+ * reply(JSON.stringify(user))
221
+ * })
222
+ */
223
+ onRequest(
224
+ name: string,
225
+ handler: (eventJson: string, reply: (response: string) => void) => void,
226
+ ): void {
227
+ this.bus.onRequest(name, handler)
228
+ }
229
+
230
+ // ─── Correlation context ──────────────────────────────────
231
+
232
+ /** Current correlation ID for event chain tracing. */
233
+ private _correlationId?: string
234
+
235
+ /** Set the correlation ID for subsequent events (typically from HTTP request context). */
236
+ setCorrelationId(id: string): void {
237
+ this._correlationId = id
238
+ }
239
+
240
+ /** Get the current correlation ID. */
241
+ getCorrelationId(): string | undefined {
242
+ return this._correlationId
243
+ }
244
+
245
+ /**
246
+ * Inject the active correlation ID at the top level of the payload so
247
+ * the bus's Event envelope (`{ id, name, data, correlationId, ... }`)
248
+ * surfaces it on the subscriber side — both the Rust `ream-events`
249
+ * envelope serde and `FakeBus.parseEmitData()` already read
250
+ * `correlationId` from the parsed `data` string. Without this injection
251
+ * `setCorrelationId()` was a no-op functional API. Returns `data`
252
+ * unchanged when no correlation ID is set OR when `data` is not a plain
253
+ * object (primitives / arrays / null can't carry a sibling field).
254
+ */
255
+ #wrapForBus(data: unknown): unknown {
256
+ if (this._correlationId === undefined) return data
257
+ if (data === null || typeof data !== 'object' || Array.isArray(data)) {
258
+ return data
259
+ }
260
+ const obj = data as Record<string, unknown>
261
+ // User-supplied correlationId wins — don't clobber an explicit value.
262
+ if (typeof obj.correlationId === 'string') return data
263
+ return { ...obj, correlationId: this._correlationId }
264
+ }
265
+
266
+ // ─── Introspection ────────────────────────────────────────
267
+
268
+ /**
269
+ * Check if any listeners are registered for an event.
270
+ */
271
+ hasListeners(event: EventConstructor | string): boolean {
272
+ if (typeof event === 'string') {
273
+ return (this.stringListeners.get(event)?.length ?? 0) > 0
274
+ }
275
+ return (this.classListeners.get(event)?.length ?? 0) > 0
276
+ }
277
+
278
+ /** Get the number of Rust-side subscriptions. */
279
+ async subscriptionCount(): Promise<number> {
280
+ return this.bus.subscriptionCount()
281
+ }
282
+ }
283
+
284
+ /**
285
+ * BaseEvent — extend to create typed event classes.
286
+ *
287
+ * Usage:
288
+ * class TaskDeclared extends BaseEvent {
289
+ * constructor(public task: Task) { super() }
290
+ * }
291
+ *
292
+ * // In controller:
293
+ * await new TaskDeclared(task).emit()
294
+ *
295
+ * // In events.ts:
296
+ * emitter.on(TaskDeclared, LogTaskEvent)
297
+ */
298
+ export class BaseEvent {
299
+ static eventName?: string
300
+ private static _emitter: Emitter | undefined
301
+
302
+ /** @internal Wire the emitter (called by EventsProvider). */
303
+ static useEmitter(emitter: Emitter): void {
304
+ BaseEvent._emitter = emitter
305
+ }
306
+
307
+ static resetEmitter(): void {
308
+ BaseEvent._emitter = undefined
309
+ }
310
+
311
+ /**
312
+ * Dispatch this event instance via the wired emitter.
313
+ * No-op if no emitter is wired (test/standalone mode).
314
+ */
315
+ async emit(): Promise<void> {
316
+ if (!BaseEvent._emitter) return
317
+ try {
318
+ await BaseEvent._emitter.dispatchEvent(this)
319
+ } catch (err) {
320
+ process.stderr.write(`[events] dispatch error for ${this.constructor.name}: ${err}\n`)
321
+ }
322
+ }
323
+ }
324
+
325
+ /** Convert PascalCase class name to dot.separated event name. */
326
+ function classToEventName(cls: EventConstructor): string {
327
+ return cls.name.replace(/([a-z])([A-Z])/g, '$1.$2').toLowerCase()
328
+ }
329
+
330
+ /** Check if a listener entry is a class (has prototype.handle) vs a function. */
331
+ function isListenerClass(listener: Listener): boolean {
332
+ return typeof listener === 'function' && typeof listener.prototype?.handle === 'function'
333
+ }
@@ -0,0 +1,58 @@
1
+ import { BaseEvent, Emitter } from './Emitter.js'
2
+ import { EventBus } from './native.js'
3
+ import { setEmitter } from './services/main.js'
4
+
5
+ /**
6
+ * Host context for the events provider. The container is referenced
7
+ * structurally (not via a concrete import) so the provider stays a thin
8
+ * seam over ream's IoC container.
9
+ *
10
+ * `make()` is the listener-class resolver Emitter needs. When the host
11
+ * doesn't expose it, listener CLASSES can't be instantiated — only inline
12
+ * function listeners work. The optional `make` field mirrors Emitter's
13
+ * `ContainerResolver` interface so the assignment type-checks without a
14
+ * load-bearing cast.
15
+ */
16
+ interface EventsContainer {
17
+ singleton(token: unknown, factory: () => unknown): void
18
+ resolve<T = unknown>(token: unknown): T
19
+ make?<T>(target: new (...args: never[]) => T): T
20
+ }
21
+ export interface EventsAppContext {
22
+ container: EventsContainer
23
+ }
24
+
25
+ export default class EventsProvider {
26
+ constructor(protected app: EventsAppContext) {}
27
+
28
+ register() {
29
+ this.app.container.singleton(EventBus, () => new EventBus())
30
+ this.app.container.singleton('bus', () => this.app.container.resolve<EventBus>(EventBus))
31
+
32
+ this.app.container.singleton(Emitter, () => {
33
+ const bus = this.app.container.resolve<EventBus>(EventBus)
34
+ // Forward `make` only when the host actually exposes it.
35
+ // Emitter falls back to direct `new Listener()` instantiation
36
+ // otherwise, which keeps zero-arg listener classes working
37
+ // without a full IoC container.
38
+ const resolver =
39
+ typeof this.app.container.make === 'function'
40
+ ? { make: this.app.container.make.bind(this.app.container) }
41
+ : undefined
42
+ return new Emitter(bus, resolver)
43
+ })
44
+ this.app.container.singleton('emitter', () => this.app.container.resolve<Emitter>(Emitter))
45
+ // Primary public token — `ctx.events` and `container.resolve('events')`.
46
+ this.app.container.singleton('events', () => this.app.container.resolve<Emitter>(Emitter))
47
+ }
48
+
49
+ async boot() {
50
+ const emitter = this.app.container.resolve<Emitter>(Emitter)
51
+ BaseEvent.useEmitter(emitter)
52
+ setEmitter(emitter)
53
+ }
54
+
55
+ async shutdown() {
56
+ BaseEvent.resetEmitter()
57
+ }
58
+ }