@kelpie/server 0.5.1 → 0.6.0

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 (347) hide show
  1. package/README.md +5 -2
  2. package/dist/index.d.ts +17 -8
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +8 -4
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/actor.d.ts +9 -1
  7. package/dist/lib/actor.d.ts.map +1 -1
  8. package/dist/lib/actor.js +13 -0
  9. package/dist/lib/actor.js.map +1 -1
  10. package/dist/lib/config.d.ts +44 -6
  11. package/dist/lib/config.d.ts.map +1 -1
  12. package/dist/lib/config.js +9 -5
  13. package/dist/lib/config.js.map +1 -1
  14. package/dist/lib/email.d.ts +15 -63
  15. package/dist/lib/email.d.ts.map +1 -1
  16. package/dist/lib/email.js +13 -65
  17. package/dist/lib/email.js.map +1 -1
  18. package/dist/lib/fromEnv.d.ts +60 -0
  19. package/dist/lib/fromEnv.d.ts.map +1 -0
  20. package/dist/lib/fromEnv.js +94 -0
  21. package/dist/lib/fromEnv.js.map +1 -0
  22. package/dist/lib/ids.d.ts +6 -0
  23. package/dist/lib/ids.d.ts.map +1 -1
  24. package/dist/lib/ids.js +6 -0
  25. package/dist/lib/ids.js.map +1 -1
  26. package/dist/lib/kelpieConfigFile.d.ts +123 -0
  27. package/dist/lib/kelpieConfigFile.d.ts.map +1 -0
  28. package/dist/lib/kelpieConfigFile.js +111 -0
  29. package/dist/lib/kelpieConfigFile.js.map +1 -0
  30. package/dist/lib/logger.d.ts +38 -7
  31. package/dist/lib/logger.d.ts.map +1 -1
  32. package/dist/lib/logger.js +58 -20
  33. package/dist/lib/logger.js.map +1 -1
  34. package/dist/modules/agent-tasks/index.d.ts.map +1 -1
  35. package/dist/modules/agent-tasks/index.js +4 -1
  36. package/dist/modules/agent-tasks/index.js.map +1 -1
  37. package/dist/modules/agent-tasks/prompt.d.ts +36 -6
  38. package/dist/modules/agent-tasks/prompt.d.ts.map +1 -1
  39. package/dist/modules/agent-tasks/prompt.js +33 -4
  40. package/dist/modules/agent-tasks/prompt.js.map +1 -1
  41. package/dist/modules/agent-tasks/service.d.ts.map +1 -1
  42. package/dist/modules/agent-tasks/service.js +3 -2
  43. package/dist/modules/agent-tasks/service.js.map +1 -1
  44. package/dist/modules/agent-tasks/wire.d.ts +11 -0
  45. package/dist/modules/agent-tasks/wire.d.ts.map +1 -1
  46. package/dist/modules/agent-tasks/wire.js +1 -0
  47. package/dist/modules/agent-tasks/wire.js.map +1 -1
  48. package/dist/modules/auth/index.d.ts.map +1 -1
  49. package/dist/modules/auth/index.js +8 -7
  50. package/dist/modules/auth/index.js.map +1 -1
  51. package/dist/modules/companies/events.d.ts +22 -0
  52. package/dist/modules/companies/events.d.ts.map +1 -0
  53. package/dist/modules/companies/events.js +8 -0
  54. package/dist/modules/companies/events.js.map +1 -0
  55. package/dist/modules/companies/index.d.ts.map +1 -1
  56. package/dist/modules/companies/index.js +2 -0
  57. package/dist/modules/companies/index.js.map +1 -1
  58. package/dist/modules/companies/service.d.ts +1 -0
  59. package/dist/modules/companies/service.d.ts.map +1 -1
  60. package/dist/modules/companies/service.js +8 -11
  61. package/dist/modules/companies/service.js.map +1 -1
  62. package/dist/modules/core.d.ts.map +1 -1
  63. package/dist/modules/core.js +4 -0
  64. package/dist/modules/core.js.map +1 -1
  65. package/dist/modules/deals/events.d.ts +31 -0
  66. package/dist/modules/deals/events.d.ts.map +1 -0
  67. package/dist/modules/deals/events.js +12 -0
  68. package/dist/modules/deals/events.js.map +1 -0
  69. package/dist/modules/deals/index.d.ts.map +1 -1
  70. package/dist/modules/deals/index.js +2 -0
  71. package/dist/modules/deals/index.js.map +1 -1
  72. package/dist/modules/deals/service.d.ts +1 -0
  73. package/dist/modules/deals/service.d.ts.map +1 -1
  74. package/dist/modules/deals/service.js +9 -18
  75. package/dist/modules/deals/service.js.map +1 -1
  76. package/dist/modules/decisions/events.d.ts +21 -0
  77. package/dist/modules/decisions/events.d.ts.map +1 -0
  78. package/dist/modules/decisions/events.js +11 -0
  79. package/dist/modules/decisions/events.js.map +1 -0
  80. package/dist/modules/decisions/index.d.ts.map +1 -1
  81. package/dist/modules/decisions/index.js +2 -0
  82. package/dist/modules/decisions/index.js.map +1 -1
  83. package/dist/modules/decisions/service.d.ts +1 -0
  84. package/dist/modules/decisions/service.d.ts.map +1 -1
  85. package/dist/modules/decisions/service.js +4 -7
  86. package/dist/modules/decisions/service.js.map +1 -1
  87. package/dist/modules/forms/events.d.ts +37 -0
  88. package/dist/modules/forms/events.d.ts.map +1 -0
  89. package/dist/modules/forms/events.js +15 -0
  90. package/dist/modules/forms/events.js.map +1 -0
  91. package/dist/modules/forms/index.d.ts.map +1 -1
  92. package/dist/modules/forms/index.js +2 -0
  93. package/dist/modules/forms/index.js.map +1 -1
  94. package/dist/modules/forms/service.d.ts +1 -0
  95. package/dist/modules/forms/service.d.ts.map +1 -1
  96. package/dist/modules/forms/service.js +8 -11
  97. package/dist/modules/forms/service.js.map +1 -1
  98. package/dist/modules/forms/submission.d.ts +5 -0
  99. package/dist/modules/forms/submission.d.ts.map +1 -1
  100. package/dist/modules/forms/submission.js +54 -28
  101. package/dist/modules/forms/submission.js.map +1 -1
  102. package/dist/modules/handbook/events.d.ts +28 -0
  103. package/dist/modules/handbook/events.d.ts.map +1 -0
  104. package/dist/modules/handbook/events.js +14 -0
  105. package/dist/modules/handbook/events.js.map +1 -0
  106. package/dist/modules/handbook/index.d.ts.map +1 -1
  107. package/dist/modules/handbook/index.js +2 -0
  108. package/dist/modules/handbook/index.js.map +1 -1
  109. package/dist/modules/handbook/service.d.ts +1 -0
  110. package/dist/modules/handbook/service.d.ts.map +1 -1
  111. package/dist/modules/handbook/service.js +8 -15
  112. package/dist/modules/handbook/service.js.map +1 -1
  113. package/dist/modules/hiring/candidates.d.ts +1 -0
  114. package/dist/modules/hiring/candidates.d.ts.map +1 -1
  115. package/dist/modules/hiring/candidates.js +8 -11
  116. package/dist/modules/hiring/candidates.js.map +1 -1
  117. package/dist/modules/hiring/events.d.ts +35 -0
  118. package/dist/modules/hiring/events.d.ts.map +1 -0
  119. package/dist/modules/hiring/events.js +11 -0
  120. package/dist/modules/hiring/events.js.map +1 -0
  121. package/dist/modules/hiring/index.d.ts.map +1 -1
  122. package/dist/modules/hiring/index.js +2 -0
  123. package/dist/modules/hiring/index.js.map +1 -1
  124. package/dist/modules/hiring/roles.d.ts +1 -0
  125. package/dist/modules/hiring/roles.d.ts.map +1 -1
  126. package/dist/modules/hiring/roles.js +8 -11
  127. package/dist/modules/hiring/roles.js.map +1 -1
  128. package/dist/modules/import-export/events.d.ts +22 -0
  129. package/dist/modules/import-export/events.d.ts.map +1 -0
  130. package/dist/modules/import-export/events.js +12 -0
  131. package/dist/modules/import-export/events.js.map +1 -0
  132. package/dist/modules/import-export/index.d.ts.map +1 -1
  133. package/dist/modules/import-export/index.js +2 -0
  134. package/dist/modules/import-export/index.js.map +1 -1
  135. package/dist/modules/import-export/service.d.ts +5 -0
  136. package/dist/modules/import-export/service.d.ts.map +1 -1
  137. package/dist/modules/import-export/service.js +53 -14
  138. package/dist/modules/import-export/service.js.map +1 -1
  139. package/dist/modules/notes/events.d.ts +22 -0
  140. package/dist/modules/notes/events.d.ts.map +1 -0
  141. package/dist/modules/notes/events.js +12 -0
  142. package/dist/modules/notes/events.js.map +1 -0
  143. package/dist/modules/notes/index.d.ts.map +1 -1
  144. package/dist/modules/notes/index.js +2 -0
  145. package/dist/modules/notes/index.js.map +1 -1
  146. package/dist/modules/notes/service.d.ts +1 -0
  147. package/dist/modules/notes/service.d.ts.map +1 -1
  148. package/dist/modules/notes/service.js +4 -7
  149. package/dist/modules/notes/service.js.map +1 -1
  150. package/dist/modules/opportunities/events.d.ts +31 -0
  151. package/dist/modules/opportunities/events.d.ts.map +1 -0
  152. package/dist/modules/opportunities/events.js +12 -0
  153. package/dist/modules/opportunities/events.js.map +1 -0
  154. package/dist/modules/opportunities/index.d.ts.map +1 -1
  155. package/dist/modules/opportunities/index.js +2 -0
  156. package/dist/modules/opportunities/index.js.map +1 -1
  157. package/dist/modules/opportunities/service.d.ts +1 -0
  158. package/dist/modules/opportunities/service.d.ts.map +1 -1
  159. package/dist/modules/opportunities/service.js +9 -18
  160. package/dist/modules/opportunities/service.js.map +1 -1
  161. package/dist/modules/partnerships/events.d.ts +31 -0
  162. package/dist/modules/partnerships/events.d.ts.map +1 -0
  163. package/dist/modules/partnerships/events.js +12 -0
  164. package/dist/modules/partnerships/events.js.map +1 -0
  165. package/dist/modules/partnerships/index.d.ts.map +1 -1
  166. package/dist/modules/partnerships/index.js +2 -0
  167. package/dist/modules/partnerships/index.js.map +1 -1
  168. package/dist/modules/partnerships/service.d.ts +1 -0
  169. package/dist/modules/partnerships/service.d.ts.map +1 -1
  170. package/dist/modules/partnerships/service.js +9 -18
  171. package/dist/modules/partnerships/service.js.map +1 -1
  172. package/dist/modules/people/events.d.ts +28 -0
  173. package/dist/modules/people/events.d.ts.map +1 -0
  174. package/dist/modules/people/events.js +18 -0
  175. package/dist/modules/people/events.js.map +1 -0
  176. package/dist/modules/people/index.d.ts.map +1 -1
  177. package/dist/modules/people/index.js +2 -0
  178. package/dist/modules/people/index.js.map +1 -1
  179. package/dist/modules/people/service.d.ts +1 -0
  180. package/dist/modules/people/service.d.ts.map +1 -1
  181. package/dist/modules/people/service.js +8 -11
  182. package/dist/modules/people/service.js.map +1 -1
  183. package/dist/modules/pipelines/service.d.ts +4 -0
  184. package/dist/modules/pipelines/service.d.ts.map +1 -1
  185. package/dist/modules/pipelines/service.js +31 -8
  186. package/dist/modules/pipelines/service.js.map +1 -1
  187. package/dist/modules/plans/events.d.ts +21 -0
  188. package/dist/modules/plans/events.d.ts.map +1 -0
  189. package/dist/modules/plans/events.js +11 -0
  190. package/dist/modules/plans/events.js.map +1 -0
  191. package/dist/modules/plans/index.d.ts.map +1 -1
  192. package/dist/modules/plans/index.js +2 -0
  193. package/dist/modules/plans/index.js.map +1 -1
  194. package/dist/modules/plans/service.d.ts +1 -0
  195. package/dist/modules/plans/service.d.ts.map +1 -1
  196. package/dist/modules/plans/service.js +6 -14
  197. package/dist/modules/plans/service.js.map +1 -1
  198. package/dist/modules/positions/events.d.ts +22 -0
  199. package/dist/modules/positions/events.d.ts.map +1 -0
  200. package/dist/modules/positions/events.js +8 -0
  201. package/dist/modules/positions/events.js.map +1 -0
  202. package/dist/modules/positions/index.d.ts.map +1 -1
  203. package/dist/modules/positions/index.js +2 -0
  204. package/dist/modules/positions/index.js.map +1 -1
  205. package/dist/modules/positions/service.d.ts +1 -0
  206. package/dist/modules/positions/service.d.ts.map +1 -1
  207. package/dist/modules/positions/service.js +8 -11
  208. package/dist/modules/positions/service.js.map +1 -1
  209. package/dist/modules/raises/events.d.ts +31 -0
  210. package/dist/modules/raises/events.d.ts.map +1 -0
  211. package/dist/modules/raises/events.js +12 -0
  212. package/dist/modules/raises/events.js.map +1 -0
  213. package/dist/modules/raises/index.d.ts.map +1 -1
  214. package/dist/modules/raises/index.js +2 -0
  215. package/dist/modules/raises/index.js.map +1 -1
  216. package/dist/modules/raises/service.d.ts +1 -0
  217. package/dist/modules/raises/service.d.ts.map +1 -1
  218. package/dist/modules/raises/service.js +9 -18
  219. package/dist/modules/raises/service.js.map +1 -1
  220. package/dist/modules/reseal.d.ts +55 -0
  221. package/dist/modules/reseal.d.ts.map +1 -1
  222. package/dist/modules/reseal.js +90 -1
  223. package/dist/modules/reseal.js.map +1 -1
  224. package/dist/modules/smtp-email/index.d.ts +69 -0
  225. package/dist/modules/smtp-email/index.d.ts.map +1 -0
  226. package/dist/modules/smtp-email/index.js +82 -0
  227. package/dist/modules/smtp-email/index.js.map +1 -0
  228. package/dist/modules/webhooks/index.d.ts.map +1 -1
  229. package/dist/modules/webhooks/index.js +5 -1
  230. package/dist/modules/webhooks/index.js.map +1 -1
  231. package/dist/modules/webhooks/payloads.d.ts +22 -7
  232. package/dist/modules/webhooks/payloads.d.ts.map +1 -1
  233. package/dist/modules/webhooks/payloads.js +63 -44
  234. package/dist/modules/webhooks/payloads.js.map +1 -1
  235. package/dist/modules/workspace/events.d.ts +52 -0
  236. package/dist/modules/workspace/events.d.ts.map +1 -0
  237. package/dist/modules/workspace/events.js +16 -0
  238. package/dist/modules/workspace/events.js.map +1 -0
  239. package/dist/modules/workspace/index.d.ts.map +1 -1
  240. package/dist/modules/workspace/index.js +6 -2
  241. package/dist/modules/workspace/index.js.map +1 -1
  242. package/dist/modules/workspace/service.d.ts +1 -0
  243. package/dist/modules/workspace/service.d.ts.map +1 -1
  244. package/dist/modules/workspace/service.js +13 -15
  245. package/dist/modules/workspace/service.js.map +1 -1
  246. package/dist/modules/workspace/workspaceAccessMiddleware.d.ts.map +1 -1
  247. package/dist/modules/workspace/workspaceAccessMiddleware.js +11 -3
  248. package/dist/modules/workspace/workspaceAccessMiddleware.js.map +1 -1
  249. package/dist/runtime/events.d.ts +86 -108
  250. package/dist/runtime/events.d.ts.map +1 -1
  251. package/dist/runtime/events.js +123 -52
  252. package/dist/runtime/events.js.map +1 -1
  253. package/dist/runtime/module.d.ts +54 -2
  254. package/dist/runtime/module.d.ts.map +1 -1
  255. package/dist/runtime/registry.d.ts +23 -0
  256. package/dist/runtime/registry.d.ts.map +1 -1
  257. package/dist/runtime/registry.js +102 -2
  258. package/dist/runtime/registry.js.map +1 -1
  259. package/dist/runtime/transaction.d.ts +29 -4
  260. package/dist/runtime/transaction.d.ts.map +1 -1
  261. package/dist/runtime/transaction.js +48 -7
  262. package/dist/runtime/transaction.js.map +1 -1
  263. package/dist/testing/app.d.ts.map +1 -1
  264. package/dist/testing/app.js +11 -3
  265. package/dist/testing/app.js.map +1 -1
  266. package/dist/testing/database.d.ts.map +1 -1
  267. package/dist/testing/database.js +6 -3
  268. package/dist/testing/database.js.map +1 -1
  269. package/dist/testing/services.d.ts +21 -1
  270. package/dist/testing/services.d.ts.map +1 -1
  271. package/dist/testing/services.js +20 -5
  272. package/dist/testing/services.js.map +1 -1
  273. package/package.json +5 -2
  274. package/src/index.ts +44 -9
  275. package/src/lib/actor.ts +15 -1
  276. package/src/lib/config.ts +56 -7
  277. package/src/lib/email.ts +22 -92
  278. package/src/lib/fromEnv.ts +143 -0
  279. package/src/lib/ids.ts +6 -0
  280. package/src/lib/kelpieConfigFile.ts +283 -0
  281. package/src/lib/logger.ts +92 -34
  282. package/src/modules/agent-tasks/index.ts +4 -1
  283. package/src/modules/agent-tasks/prompt.ts +57 -9
  284. package/src/modules/agent-tasks/service.ts +3 -2
  285. package/src/modules/agent-tasks/wire.ts +12 -0
  286. package/src/modules/auth/index.ts +11 -9
  287. package/src/modules/companies/events.ts +25 -0
  288. package/src/modules/companies/index.ts +2 -0
  289. package/src/modules/companies/service.ts +8 -11
  290. package/src/modules/core.ts +4 -0
  291. package/src/modules/deals/events.ts +34 -0
  292. package/src/modules/deals/index.ts +2 -0
  293. package/src/modules/deals/service.ts +17 -18
  294. package/src/modules/decisions/events.ts +24 -0
  295. package/src/modules/decisions/index.ts +2 -0
  296. package/src/modules/decisions/service.ts +8 -7
  297. package/src/modules/forms/events.ts +37 -0
  298. package/src/modules/forms/index.ts +2 -0
  299. package/src/modules/forms/service.ts +12 -11
  300. package/src/modules/forms/submission.ts +80 -29
  301. package/src/modules/handbook/events.ts +31 -0
  302. package/src/modules/handbook/index.ts +2 -0
  303. package/src/modules/handbook/service.ts +8 -15
  304. package/src/modules/hiring/candidates.ts +8 -11
  305. package/src/modules/hiring/events.ts +36 -0
  306. package/src/modules/hiring/index.ts +2 -0
  307. package/src/modules/hiring/roles.ts +8 -11
  308. package/src/modules/import-export/events.ts +25 -0
  309. package/src/modules/import-export/index.ts +2 -0
  310. package/src/modules/import-export/service.ts +83 -15
  311. package/src/modules/notes/events.ts +25 -0
  312. package/src/modules/notes/index.ts +2 -0
  313. package/src/modules/notes/service.ts +8 -7
  314. package/src/modules/opportunities/events.ts +34 -0
  315. package/src/modules/opportunities/index.ts +2 -0
  316. package/src/modules/opportunities/service.ts +17 -18
  317. package/src/modules/partnerships/events.ts +34 -0
  318. package/src/modules/partnerships/index.ts +2 -0
  319. package/src/modules/partnerships/service.ts +17 -18
  320. package/src/modules/people/events.ts +36 -0
  321. package/src/modules/people/index.ts +2 -0
  322. package/src/modules/people/service.ts +97 -87
  323. package/src/modules/pipelines/service.ts +47 -8
  324. package/src/modules/plans/events.ts +24 -0
  325. package/src/modules/plans/index.ts +2 -0
  326. package/src/modules/plans/service.ts +14 -14
  327. package/src/modules/positions/events.ts +25 -0
  328. package/src/modules/positions/index.ts +2 -0
  329. package/src/modules/positions/service.ts +8 -11
  330. package/src/modules/raises/events.ts +34 -0
  331. package/src/modules/raises/index.ts +2 -0
  332. package/src/modules/raises/service.ts +17 -18
  333. package/src/modules/reseal.ts +144 -1
  334. package/src/modules/smtp-email/index.ts +119 -0
  335. package/src/modules/webhooks/index.ts +5 -1
  336. package/src/modules/webhooks/payloads.ts +94 -48
  337. package/src/modules/workspace/events.ts +46 -0
  338. package/src/modules/workspace/index.ts +6 -2
  339. package/src/modules/workspace/service.ts +37 -15
  340. package/src/modules/workspace/workspaceAccessMiddleware.ts +12 -3
  341. package/src/runtime/events.ts +268 -107
  342. package/src/runtime/module.ts +55 -2
  343. package/src/runtime/registry.ts +169 -1
  344. package/src/runtime/transaction.ts +94 -17
  345. package/src/testing/app.ts +11 -3
  346. package/src/testing/database.ts +6 -3
  347. package/src/testing/services.ts +34 -5
@@ -1,3 +1,5 @@
1
+ import type { EventTarget, KelpieEvent } from '@kelpie/schemas';
2
+ import type { ZodType } from 'zod';
1
3
  import type { Logger } from '../lib/logger.ts';
2
4
  /**
3
5
  * In-process typed domain events, per `modules.md`.
@@ -5,135 +7,111 @@ import type { Logger } from '../lib/logger.ts';
5
7
  * Delivery is at-least-once within the process, with no durable queue. A crash
6
8
  * between commit and dispatch loses the event. A durable outbox is a known
7
9
  * follow-up; do not build it before a consumer cannot tolerate the loss.
10
+ *
11
+ * Every event carries the envelope defined in `@kelpie/schemas`
12
+ * (`KelpieEvent<Name, Data>`). Names and payload schemas live in per-module
13
+ * catalogs the bus registers at boot; two modules cannot declare the same name.
8
14
  */
9
15
  /**
10
- * CRM object types that `record.*` events carry. Every object the API writes,
11
- * including the link and content records.
12
- *
13
- * Wider than `EXTENSIBLE_RECORD_TYPES` in `@kelpie/schemas`, which is the
14
- * shorter list of detail pages a UI module can contribute to. A Position, a
15
- * Form, and a Handbook page each publish events but have no page to extend.
16
+ * CRM object types the webhooks bridge treats as deliverable records. Kept
17
+ * here (rather than folded into a module) because import and webhooks both
18
+ * read it, and neither owns the list.
16
19
  */
17
20
  export declare const RECORD_OBJECT_TYPES: readonly ['person', 'company', 'position', 'deal', 'opportunity', 'partnership', 'raise', 'role', 'candidate', 'handbook_page', 'form'];
18
21
  export type RecordObjectType = (typeof RECORD_OBJECT_TYPES)[number];
19
- /** Objects whose stage or status moves through a pipeline. */
20
- export type StagedObjectType = 'deal' | 'opportunity' | 'raise' | 'partnership';
21
22
  /**
22
- * The event catalog. Every payload carries `workspaceId`: a consumer must never
23
- * have to look up which tenant an event belongs to.
23
+ * The compile-time event catalog.
24
24
  *
25
- * Adding an event means adding a key here. The name is the key, so a typo is a
26
- * compile error rather than a subscription that never fires.
25
+ * Modules extend this interface via TypeScript declaration merging, one
26
+ * declaration per module. The runtime catalog (see `registerCatalog`) is the
27
+ * authority; this interface is what gives autocomplete and payload typing at
28
+ * every `publish` and `subscribe` call site.
27
29
  */
28
- export interface DomainEvents {
29
- 'workspace.created': {
30
- workspaceId: string;
31
- slug: string;
32
- };
33
- /** Fires after the cascade, so nothing the workspace owned still exists. */
34
- 'workspace.deleted': {
35
- workspaceId: string;
36
- slug: string;
37
- };
38
- 'member.invited': {
39
- workspaceId: string;
40
- inviteId: string;
41
- email: string;
42
- };
43
- 'member.joined': {
44
- workspaceId: string;
45
- memberId: string;
46
- userId: string;
47
- };
48
- /** Pairs with `member.joined`, which is what a seat count subscribes to. */
49
- 'member.removed': {
50
- workspaceId: string;
51
- memberId: string;
52
- userId: string;
53
- };
54
- 'record.created': {
55
- workspaceId: string;
56
- objectType: RecordObjectType;
57
- recordId: string;
58
- };
59
- 'record.updated': {
60
- workspaceId: string;
61
- objectType: RecordObjectType;
62
- recordId: string;
63
- changedFields: readonly string[];
64
- };
65
- 'record.deleted': {
66
- workspaceId: string;
67
- objectType: RecordObjectType;
68
- recordId: string;
69
- };
70
- 'stage.changed': {
71
- workspaceId: string;
72
- objectType: StagedObjectType;
73
- recordId: string;
74
- fromStageId: string | null;
75
- toStageId: string;
76
- };
77
- 'note.added': {
78
- workspaceId: string;
79
- noteId: string;
80
- targetType: string;
81
- targetId: string;
82
- };
83
- 'decision.added': {
84
- workspaceId: string;
85
- decisionId: string;
86
- targetType: string;
87
- targetId: string;
88
- };
89
- 'plan.completed': {
90
- workspaceId: string;
91
- planItemId: string;
92
- targetType: string;
93
- targetId: string;
94
- };
95
- 'form.submitted': {
96
- workspaceId: string;
97
- formId: string;
98
- submissionId: string;
99
- };
100
- 'import.completed': {
101
- workspaceId: string;
102
- importJobId: string;
103
- object: string;
104
- };
105
- 'agent_run.finished': {
106
- workspaceId: string;
107
- agentRunId: string;
108
- status: 'succeeded' | 'failed';
109
- };
30
+ export interface KelpieEventMap {
110
31
  }
111
- export type DomainEventName = keyof DomainEvents;
112
32
  /**
113
- * The catalog as data. Webhooks needs the deliverable event names at runtime, and
114
- * `satisfies` keeps this list from drifting from the interface above.
115
- *
116
- * An event added to `DomainEvents` but forgotten here is caught by
117
- * `createHandlerRegistry`, which must produce an entry for every name.
33
+ * When `KelpieEventMap` is empty (no module has declared an event yet) `keyof`
34
+ * is `never`, which would make every `EventHandler` signature unusable. The
35
+ * fallback keeps types working during boot and in tests that build the bus
36
+ * without any modules registered.
118
37
  */
119
- export declare const DOMAIN_EVENT_NAMES: readonly ["workspace.created", "workspace.deleted", "member.invited", "member.joined", "member.removed", "record.created", "record.updated", "record.deleted", "stage.changed", "note.added", "decision.added", "plan.completed", "form.submitted", "import.completed", "agent_run.finished"];
38
+ type EventMapWithFallback = keyof KelpieEventMap extends never ? Readonly<Record<string, unknown>> : KelpieEventMap;
39
+ export type EventName = string & keyof EventMapWithFallback;
120
40
  /** Handlers are async and must be idempotent: the same event may arrive twice. */
121
- export type EventHandler<Name extends DomainEventName> = (payload: DomainEvents[Name]) => Promise<void>;
41
+ export type EventHandler<Name extends EventName> = (event: KelpieEvent<Name, EventMapWithFallback[Name]>) => Promise<void> | void;
42
+ /** Prefix subscribers see events they cannot name statically. */
43
+ export type AnyEventHandler = (event: KelpieEvent<string, unknown>) => Promise<void> | void;
44
+ /**
45
+ * What a module hands the runtime at registration: the module's id and the Zod
46
+ * schema for every event name the module publishes.
47
+ */
48
+ export interface EventCatalog {
49
+ readonly moduleId: string;
50
+ readonly events: Readonly<Record<string, ZodType>>;
51
+ }
52
+ /** One frame in the causation chain that produced an event. */
53
+ export interface EventChainEntry {
54
+ readonly id: string;
55
+ readonly name: string;
56
+ readonly targetType: string;
57
+ readonly targetId: string;
58
+ }
59
+ export declare function currentEventChain(): readonly EventChainEntry[];
60
+ /**
61
+ * Runs the cycle guard against the current chain. Called from the transaction
62
+ * scope's `emit` before it buffers the event.
63
+ */
64
+ export declare function checkEventCycle(chain: readonly EventChainEntry[], name: string, target: EventTarget, maxDepth: number): CycleGuardOutcome;
65
+ export type CycleGuardOutcome = {
66
+ readonly kind: 'ok';
67
+ } | {
68
+ readonly kind: 'depth';
69
+ } | {
70
+ readonly kind: 'repeat';
71
+ };
72
+ export interface SubscribeOptions {
73
+ /** Shown in logs when the handler fails or times out. Defaults to the event name. */
74
+ readonly label?: string;
75
+ /** Overrides the bus-wide default. */
76
+ readonly timeoutMs?: number;
77
+ }
122
78
  export interface EventBus {
123
- /** Registers a handler. Handlers for one event run concurrently, not in order. */
124
- subscribe<Name extends DomainEventName>(name: Name, handler: EventHandler<Name>): void;
79
+ /**
80
+ * Registers a module's event catalog. Called by `registerModules` at boot,
81
+ * once per module that declares events. Two modules cannot declare the same
82
+ * event name; the second call throws.
83
+ */
84
+ registerCatalog(catalog: EventCatalog): void;
85
+ /** True if any module has declared this event name. */
86
+ hasEvent(name: string): boolean;
87
+ /** The payload schema registered for this event, or `undefined` if unknown. */
88
+ getSchema(name: string): ZodType | undefined;
89
+ /**
90
+ * Subscribe to an event by exact name. Handlers for one event run
91
+ * concurrently, each in its own error and timeout boundary.
92
+ */
93
+ subscribe<Name extends EventName>(name: Name, handler: EventHandler<Name>, options?: SubscribeOptions): void;
94
+ /**
95
+ * Subscribe to every event whose name starts with `prefix`. Runs concurrently
96
+ * with exact-name subscribers. Match is a plain `startsWith`; there is no
97
+ * pattern language.
98
+ */
99
+ subscribePrefix(prefix: string, handler: AnyEventHandler, options?: SubscribeOptions): void;
125
100
  /**
126
101
  * Dispatches immediately. Services should not call this directly: they emit
127
102
  * through the transaction scope so nothing fires before the commit.
128
- *
129
- * @returns A promise that settles when every handler for this event has settled.
130
103
  */
131
- publish<Name extends DomainEventName>(name: Name, payload: DomainEvents[Name]): Promise<void>;
104
+ publish<Name extends EventName>(event: KelpieEvent<Name, EventMapWithFallback[Name]>): Promise<void>;
132
105
  /**
133
106
  * Settles once every in-flight publication has finished, including any a
134
107
  * handler started. Used by tests, and by shutdown to flush before exit.
135
108
  */
136
109
  drain(): Promise<void>;
137
110
  }
138
- export declare function createEventBus(logger: Logger): EventBus;
111
+ export interface EventBusOptions {
112
+ /** Default per-handler timeout in ms. Defaults to 5000. */
113
+ readonly defaultHandlerTimeoutMs?: number;
114
+ }
115
+ export declare function createEventBus(logger: Logger, options?: EventBusOptions): EventBus;
116
+ export {};
139
117
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/runtime/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/runtime/events.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import Emittery from 'emittery';
1
3
  import { describeThrown } from '../lib/errors.js';
2
4
  /**
3
5
  * In-process typed domain events, per `modules.md`.
@@ -5,14 +7,15 @@ import { describeThrown } from '../lib/errors.js';
5
7
  * Delivery is at-least-once within the process, with no durable queue. A crash
6
8
  * between commit and dispatch loses the event. A durable outbox is a known
7
9
  * follow-up; do not build it before a consumer cannot tolerate the loss.
10
+ *
11
+ * Every event carries the envelope defined in `@kelpie/schemas`
12
+ * (`KelpieEvent<Name, Data>`). Names and payload schemas live in per-module
13
+ * catalogs the bus registers at boot; two modules cannot declare the same name.
8
14
  */
9
15
  /**
10
- * CRM object types that `record.*` events carry. Every object the API writes,
11
- * including the link and content records.
12
- *
13
- * Wider than `EXTENSIBLE_RECORD_TYPES` in `@kelpie/schemas`, which is the
14
- * shorter list of detail pages a UI module can contribute to. A Position, a
15
- * Form, and a Handbook page each publish events but have no page to extend.
16
+ * CRM object types the webhooks bridge treats as deliverable records. Kept
17
+ * here (rather than folded into a module) because import and webhooks both
18
+ * read it, and neither owns the list.
16
19
  */
17
20
  export const RECORD_OBJECT_TYPES = [
18
21
  'person',
@@ -28,63 +31,131 @@ export const RECORD_OBJECT_TYPES = [
28
31
  'form',
29
32
  ];
30
33
  /**
31
- * The catalog as data. Webhooks needs the deliverable event names at runtime, and
32
- * `satisfies` keeps this list from drifting from the interface above.
34
+ * The chain of ancestor events currently being handled, keyed against the async
35
+ * context that started them. `undefined` outside any handler.
33
36
  *
34
- * An event added to `DomainEvents` but forgotten here is caught by
35
- * `createHandlerRegistry`, which must produce an entry for every name.
37
+ * The bus wraps every `publish` in `run(child, ...)`, so a handler that opens a
38
+ * transaction and calls `emit(...)` inherits the chain. The transaction scope
39
+ * reads this to stamp `causedBy` and to run the cycle guard.
36
40
  */
37
- export const DOMAIN_EVENT_NAMES = [
38
- 'workspace.created',
39
- 'workspace.deleted',
40
- 'member.invited',
41
- 'member.joined',
42
- 'member.removed',
43
- 'record.created',
44
- 'record.updated',
45
- 'record.deleted',
46
- 'stage.changed',
47
- 'note.added',
48
- 'decision.added',
49
- 'plan.completed',
50
- 'form.submitted',
51
- 'import.completed',
52
- 'agent_run.finished',
53
- ];
41
+ const chainStorage = new AsyncLocalStorage();
42
+ export function currentEventChain() {
43
+ return chainStorage.getStore() ?? [];
44
+ }
54
45
  /**
55
- * Every name gets a list up front. TypeScript cannot check a write through a
56
- * generic key, so pre-seeding turns `subscribe` into a read plus a push, which it
57
- * can check. The one assertion is building a complete record from its own key list.
46
+ * Runs the cycle guard against the current chain. Called from the transaction
47
+ * scope's `emit` before it buffers the event.
58
48
  */
59
- function createHandlerRegistry() {
60
- const registry = {};
61
- for (const name of DOMAIN_EVENT_NAMES) {
62
- registry[name] = [];
49
+ export function checkEventCycle(chain, name, target, maxDepth) {
50
+ if (chain.length >= maxDepth) {
51
+ return { kind: 'depth' };
52
+ }
53
+ for (const entry of chain) {
54
+ if (entry.name === name && entry.targetType === target.type && entry.targetId === target.id) {
55
+ return { kind: 'repeat' };
56
+ }
63
57
  }
64
- return registry;
58
+ return { kind: 'ok' };
65
59
  }
66
- export function createEventBus(logger) {
67
- const handlers = createHandlerRegistry();
60
+ const DEFAULT_HANDLER_TIMEOUT_MS = 5000;
61
+ export function createEventBus(logger, options = {}) {
62
+ const emittery = new Emittery();
63
+ const schemas = new Map();
64
+ const owners = new Map();
65
+ const prefixHandlers = [];
68
66
  const inFlight = new Set();
67
+ const defaultTimeoutMs = options.defaultHandlerTimeoutMs ?? DEFAULT_HANDLER_TIMEOUT_MS;
68
+ function wrap(label, timeoutMs, handler, context) {
69
+ return async (event) => {
70
+ let timerHandle;
71
+ const timedOut = Symbol('timeout');
72
+ const timer = new Promise((resolve) => {
73
+ timerHandle = setTimeout(() => resolve(timedOut), timeoutMs);
74
+ timerHandle.unref?.();
75
+ });
76
+ try {
77
+ const outcome = await Promise.race([
78
+ Promise.resolve().then(() => handler(event)),
79
+ timer,
80
+ ]);
81
+ if (outcome === timedOut) {
82
+ logger.error('event handler timed out', { label, timeoutMs, ...context(event) });
83
+ }
84
+ }
85
+ catch (error) {
86
+ logger.error('event handler failed', {
87
+ label,
88
+ error: describeThrown(error),
89
+ ...context(event),
90
+ });
91
+ }
92
+ finally {
93
+ if (timerHandle !== undefined) {
94
+ clearTimeout(timerHandle);
95
+ }
96
+ }
97
+ };
98
+ }
69
99
  return {
70
- subscribe(name, handler) {
71
- handlers[name].push(handler);
72
- },
73
- publish(name, payload) {
74
- const registered = handlers[name];
75
- const settled = Promise.allSettled(registered.map((handler) => handler(payload))).then((outcomes) => {
76
- for (const outcome of outcomes) {
77
- if (outcome.status === 'rejected') {
78
- logger.error('event handler failed', {
79
- event: name,
80
- error: describeThrown(outcome.reason),
81
- });
82
- }
100
+ registerCatalog(catalog) {
101
+ for (const [name, schema] of Object.entries(catalog.events)) {
102
+ const existing = owners.get(name);
103
+ if (existing !== undefined) {
104
+ throw new Error(`event "${name}" is declared by both module "${existing}" and module "${catalog.moduleId}"`);
83
105
  }
106
+ owners.set(name, catalog.moduleId);
107
+ schemas.set(name, schema);
108
+ }
109
+ },
110
+ hasEvent(name) {
111
+ return schemas.has(name);
112
+ },
113
+ getSchema(name) {
114
+ return schemas.get(name);
115
+ },
116
+ subscribe(name, handler, subscribeOptions) {
117
+ const label = subscribeOptions?.label ?? name;
118
+ const timeoutMs = subscribeOptions?.timeoutMs ?? defaultTimeoutMs;
119
+ const wrapped = wrap(label, timeoutMs, (event) => {
120
+ const envelope = event.data;
121
+ return handler(envelope);
122
+ }, (event) => {
123
+ const envelope = event.data;
124
+ return { event: envelope.name, eventId: envelope.id };
125
+ });
126
+ emittery.on(name, wrapped);
127
+ },
128
+ subscribePrefix(prefix, handler, subscribeOptions) {
129
+ const label = subscribeOptions?.label ?? `${prefix}*`;
130
+ const timeoutMs = subscribeOptions?.timeoutMs ?? defaultTimeoutMs;
131
+ prefixHandlers.push({
132
+ prefix,
133
+ label,
134
+ run: wrap(label, timeoutMs, handler, (event) => ({ event: event.name, eventId: event.id })),
84
135
  });
136
+ },
137
+ publish(event) {
138
+ const parent = chainStorage.getStore() ?? [];
139
+ const child = [
140
+ ...parent,
141
+ {
142
+ id: event.id,
143
+ name: event.name,
144
+ targetType: event.target.type,
145
+ targetId: event.target.id,
146
+ },
147
+ ];
148
+ const matching = prefixHandlers.filter((entry) => event.name.startsWith(entry.prefix));
149
+ const typedEvent = event;
150
+ const settled = chainStorage.run(child, () => Promise.allSettled([
151
+ emittery.emit(event.name, typedEvent),
152
+ ...matching.map((entry) => entry.run(typedEvent)),
153
+ ]));
85
154
  inFlight.add(settled);
86
- void settled.finally(() => inFlight.delete(settled));
87
- return settled;
155
+ void settled.finally(() => {
156
+ inFlight.delete(settled);
157
+ });
158
+ return settled.then(() => undefined);
88
159
  },
89
160
  async drain() {
90
161
  // A handler may publish further events, so keep draining until the set is
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/runtime/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAGjD;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,QAAQ;IACR,SAAS;IACT,UAAU;IACV,MAAM;IACN,aAAa;IACb,aAAa;IACb,OAAO;IACP,MAAM;IACN,WAAW;IACX,eAAe;IACf,MAAM;CACE,CAAA;AA+CV;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,mBAAmB;IACnB,mBAAmB;IACnB,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,YAAY;IACZ,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,kBAAkB;IAClB,oBAAoB;CACyB,CAAA;AA6B/C;;;;GAIG;AACH,SAAS,qBAAqB;IAC5B,MAAM,QAAQ,GAA6B,EAAE,CAAA;IAE7C,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,CAAC;QACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,CAAA;IACrB,CAAC;IAED,OAAO,QAA2B,CAAA;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAA;IACxC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiB,CAAA;IAEzC,OAAO;QACL,SAAS,CAAC,IAAI,EAAE,OAAO;YACrB,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC9B,CAAC;QAED,OAAO,CAAC,IAAI,EAAE,OAAO;YACnB,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;YAEjC,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CACpF,CAAC,QAAQ,EAAE,EAAE;gBACX,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;wBAClC,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE;4BACnC,KAAK,EAAE,IAAI;4BACX,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;yBACtC,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC,CACF,CAAA;YAED,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACrB,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;YAEpD,OAAO,OAAO,CAAA;QAChB,CAAC;QAED,KAAK,CAAC,KAAK;YACT,0EAA0E;YAC1E,iDAAiD;YACjD,OAAO,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACzB,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAA;YACzC,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/runtime/events.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ import type { Database } from '../lib/database.ts';
5
5
  import type { EmailSender } from '../lib/email.ts';
6
6
  import type { IdFactory } from '../lib/ids.ts';
7
7
  import type { Logger } from '../lib/logger.ts';
8
+ import type { SecretEncryptionConfig } from '../lib/secrets.ts';
8
9
  import type { EntitlementRegistry } from './entitlements.ts';
9
10
  import type { EventBus } from './events.ts';
10
11
  import type { TransactionScope } from './transaction.ts';
@@ -62,16 +63,54 @@ export interface ModuleServices {
62
63
  readonly db: Database;
63
64
  /** Runs work in one transaction and publishes its events after commit. */
64
65
  readonly transaction: TransactionScope;
65
- /** Transactional mail only: invites and password resets. */
66
- readonly email: EmailSender;
67
66
  /** Generates `<prefix>_<ulid>` ids. Injected so tests can pin them. */
68
67
  readonly createId: IdFactory;
69
68
  /** The current time, injected so expiry logic is testable. */
70
69
  readonly now: () => Date;
70
+ /**
71
+ * The deployment's base URL, when the assembly declares `appBaseUrl` in
72
+ * `kelpie.config.ts`. Modules that need it prefer this over
73
+ * `context.config(appUrlConfigSchema)`, which they fall back to when this is
74
+ * undefined (older assemblies).
75
+ */
76
+ readonly appBaseUrl?: string | undefined;
77
+ /**
78
+ * The keys that seal stored secrets, when the assembly declares
79
+ * `secretEncryption`. Same fallback pattern as `appBaseUrl`.
80
+ */
81
+ readonly secretEncryption?: SecretEncryptionConfig | undefined;
71
82
  }
72
83
  export interface ModuleContext extends ModuleServices {
73
84
  /** Registers routes. They mount under `/v1` and are public API like any other. */
74
85
  routes(mount: (router: Hono) => void): void;
86
+ /**
87
+ * Registers a named transactional-mail provider. `name` is what the assembly
88
+ * puts in `kelpie.config.ts`'s `email.provider`; the runtime resolves that
89
+ * field against the registry after every module has registered.
90
+ *
91
+ * `build` is a factory the runtime calls exactly once, and only for the
92
+ * provider `email.provider` picked. A provider that is registered but never
93
+ * picked never has its factory called, so a module can register itself
94
+ * without demanding its own env up front: a self-hoster who leaves the
95
+ * built-in `smtp-email` core module in `coreModules` while running on
96
+ * `EMAIL_PROVIDER=log` will not be asked for SMTP credentials at boot.
97
+ * The factory may throw; the runtime wraps the error with the module id.
98
+ *
99
+ * Any number of modules may register different names side by side. Two
100
+ * modules registering the same name fails boot. `'log'` is registered by
101
+ * the runtime itself, so a module that tries to shadow it fails boot too.
102
+ *
103
+ * `context.email` is a proxy: every module receives the same object, and
104
+ * its `send` delegates to whichever provider `email.provider` picked.
105
+ * Consumer modules capture the proxy at register time; registration order
106
+ * does not matter.
107
+ */
108
+ provideEmailSender(name: string, build: () => EmailSender): void;
109
+ /**
110
+ * Transactional mail. Every module receives the same proxy; `.send()`
111
+ * delegates to the provider `email.provider` picked.
112
+ */
113
+ readonly email: EmailSender;
75
114
  /**
76
115
  * Registers routes that mount under `/v1/public`, take no credentials, and
77
116
  * answer cross-origin requests from any site.
@@ -143,6 +182,14 @@ export interface ModuleCatalogEntry {
143
182
  readonly id: string;
144
183
  readonly structural: boolean;
145
184
  }
185
+ /**
186
+ * A module's event catalog: the Zod schema for every event name the module
187
+ * publishes. Registered with the bus at boot; two modules cannot claim the same
188
+ * name.
189
+ */
190
+ export interface ModuleEventCatalog {
191
+ readonly [eventName: string]: ZodType;
192
+ }
146
193
  export interface KelpieModule {
147
194
  readonly id: string;
148
195
  /** Ids of modules that must register first. Missing ones fail boot. */
@@ -157,6 +204,11 @@ export interface KelpieModule {
157
204
  * without its author having to opt in.
158
205
  */
159
206
  readonly structural?: boolean;
207
+ /**
208
+ * The events this module publishes, as a runtime catalog. Optional: a module
209
+ * that only consumes events, or contributes none, may omit it.
210
+ */
211
+ readonly events?: ModuleEventCatalog;
160
212
  register(context: ModuleContext): Promise<void>;
161
213
  }
162
214
  //# sourceMappingURL=module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/runtime/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AAElC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AAExD;;;;;;GAMG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IAClD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;CAC/B;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB,CAAC,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,CAAA;IACpC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAClE;AAED;;;GAGG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CACvE;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;CACxD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAA;IACrB,0EAA0E;IAC1E,QAAQ,CAAC,WAAW,EAAE,gBAAgB,CAAA;IACtC,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAA;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAA;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,kFAAkF;IAClF,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,KAAK,IAAI,GAAG,IAAI,CAAA;IAC3C;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,KAAK,IAAI,GAAG,IAAI,CAAA;IACjD;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3F;;;;;;;;;OASG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAChE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9E,QAAQ,CAAC,GAAG,EAAE,eAAe,CAAA;IAC7B;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;IACzB;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAA;IAC1C,iFAAiF;IACjF,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACrD;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAA;CACrE;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAChD"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../src/runtime/module.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { Hono } from 'hono';
2
2
  import type { Context, Handler, MiddlewareHandler } from 'hono';
3
3
  import type { Actor } from '../lib/actor.ts';
4
4
  import type { Environment } from '../lib/config.ts';
5
+ import type { EmailSender } from '../lib/email.ts';
5
6
  import type { Logger } from '../lib/logger.ts';
6
7
  import type { EntitlementRegistry } from './entitlements.ts';
7
8
  import type { EventBus } from './events.ts';
@@ -62,6 +63,28 @@ export interface ModuleRuntimeOptions {
62
63
  readonly entitlements?: EntitlementRegistry | undefined;
63
64
  /** The database, transaction scope, and collaborators every module builds on. */
64
65
  readonly services: ModuleServices;
66
+ /**
67
+ * Picks the transactional-mail provider. `provider` is a name a module
68
+ * registered via `context.provideEmailSender(name, sender)`. `'log'` is a
69
+ * built-in the runtime always registers using its own logger and `from`, so
70
+ * a bare install boots without a provider module.
71
+ *
72
+ * `from` is the address on every outgoing message. The log provider uses it
73
+ * verbatim; other providers may read the same value through their own
74
+ * `context.config` if they need to.
75
+ */
76
+ readonly email: {
77
+ readonly provider: string;
78
+ readonly from: string;
79
+ };
80
+ /**
81
+ * Extra named providers seeded into the registry before any module runs.
82
+ * Modules still register through `context.provideEmailSender`; these are for
83
+ * tests that want to inspect what was sent without building a whole module.
84
+ * A name collision with a module (or with `'log'`) fails boot exactly as if
85
+ * two modules had registered it.
86
+ */
87
+ readonly additionalEmailProviders?: ReadonlyMap<string, EmailSender> | undefined;
65
88
  /**
66
89
  * The deploy-time module override (`lib/moduleConfig.ts`), parsed. A locked
67
90
  * module id wins over whatever a workspace's own settings say.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAA;AAE/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,KAAK,EACV,YAAY,EACZ,OAAO,EAGP,cAAc,EACd,kBAAkB,EACnB,MAAM,aAAa,CAAA;AAIpB;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IACzC,0FAA0F;IAC1F,QAAQ,CAAC,aAAa,EAAE,SAAS,YAAY,EAAE,CAAA;IAC/C,qFAAqF;IACrF,QAAQ,CAAC,aAAa,EAAE,SAAS,yBAAyB,EAAE,CAAA;IAC5D,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACnD,QAAQ,CAAC,OAAO,EAAE,SAAS,kBAAkB,EAAE,CAAA;IAC/C,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;IACrC,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;IACzB,yEAAyE;IACzE,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAA;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAA;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAA;CACpC;AAwBD;;;;;;;;;GASG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IACzC,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;IACtC,yEAAyE;IACzE,QAAQ,CAAC,YAAY,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAA;IACvD,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAA;IACrE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAA;CAC3E;AA8HD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA2EjG"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/runtime/registry.ts"],"names":[],"mappings":"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"}