@kelpie/server 0.5.2 → 0.7.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 (406) hide show
  1. package/README.md +5 -2
  2. package/dist/app.d.ts +13 -0
  3. package/dist/app.d.ts.map +1 -1
  4. package/dist/app.js +9 -0
  5. package/dist/app.js.map +1 -1
  6. package/dist/boot.d.ts +42 -0
  7. package/dist/boot.d.ts.map +1 -0
  8. package/dist/boot.js +57 -0
  9. package/dist/boot.js.map +1 -0
  10. package/dist/index.d.ts +20 -8
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +13 -4
  13. package/dist/index.js.map +1 -1
  14. package/dist/lib/actor.d.ts +9 -1
  15. package/dist/lib/actor.d.ts.map +1 -1
  16. package/dist/lib/actor.js +13 -0
  17. package/dist/lib/actor.js.map +1 -1
  18. package/dist/lib/config.d.ts +51 -6
  19. package/dist/lib/config.d.ts.map +1 -1
  20. package/dist/lib/config.js +11 -5
  21. package/dist/lib/config.js.map +1 -1
  22. package/dist/lib/email.d.ts +15 -63
  23. package/dist/lib/email.d.ts.map +1 -1
  24. package/dist/lib/email.js +13 -65
  25. package/dist/lib/email.js.map +1 -1
  26. package/dist/lib/fromEnv.d.ts +60 -0
  27. package/dist/lib/fromEnv.d.ts.map +1 -0
  28. package/dist/lib/fromEnv.js +94 -0
  29. package/dist/lib/fromEnv.js.map +1 -0
  30. package/dist/lib/ids.d.ts +6 -0
  31. package/dist/lib/ids.d.ts.map +1 -1
  32. package/dist/lib/ids.js +6 -0
  33. package/dist/lib/ids.js.map +1 -1
  34. package/dist/lib/kelpieConfigFile.d.ts +129 -0
  35. package/dist/lib/kelpieConfigFile.d.ts.map +1 -0
  36. package/dist/lib/kelpieConfigFile.js +112 -0
  37. package/dist/lib/kelpieConfigFile.js.map +1 -0
  38. package/dist/lib/logger.d.ts +38 -7
  39. package/dist/lib/logger.d.ts.map +1 -1
  40. package/dist/lib/logger.js +58 -20
  41. package/dist/lib/logger.js.map +1 -1
  42. package/dist/modules/agent-tasks/index.d.ts.map +1 -1
  43. package/dist/modules/agent-tasks/index.js +4 -1
  44. package/dist/modules/agent-tasks/index.js.map +1 -1
  45. package/dist/modules/agent-tasks/prompt.d.ts +36 -6
  46. package/dist/modules/agent-tasks/prompt.d.ts.map +1 -1
  47. package/dist/modules/agent-tasks/prompt.js +33 -4
  48. package/dist/modules/agent-tasks/prompt.js.map +1 -1
  49. package/dist/modules/agent-tasks/service.d.ts.map +1 -1
  50. package/dist/modules/agent-tasks/service.js +3 -2
  51. package/dist/modules/agent-tasks/service.js.map +1 -1
  52. package/dist/modules/agent-tasks/wire.d.ts +11 -0
  53. package/dist/modules/agent-tasks/wire.d.ts.map +1 -1
  54. package/dist/modules/agent-tasks/wire.js +1 -0
  55. package/dist/modules/agent-tasks/wire.js.map +1 -1
  56. package/dist/modules/auth/index.d.ts.map +1 -1
  57. package/dist/modules/auth/index.js +8 -7
  58. package/dist/modules/auth/index.js.map +1 -1
  59. package/dist/modules/companies/events.d.ts +22 -0
  60. package/dist/modules/companies/events.d.ts.map +1 -0
  61. package/dist/modules/companies/events.js +8 -0
  62. package/dist/modules/companies/events.js.map +1 -0
  63. package/dist/modules/companies/index.d.ts.map +1 -1
  64. package/dist/modules/companies/index.js +2 -0
  65. package/dist/modules/companies/index.js.map +1 -1
  66. package/dist/modules/companies/service.d.ts +1 -0
  67. package/dist/modules/companies/service.d.ts.map +1 -1
  68. package/dist/modules/companies/service.js +8 -11
  69. package/dist/modules/companies/service.js.map +1 -1
  70. package/dist/modules/core.d.ts.map +1 -1
  71. package/dist/modules/core.js +4 -0
  72. package/dist/modules/core.js.map +1 -1
  73. package/dist/modules/deals/events.d.ts +31 -0
  74. package/dist/modules/deals/events.d.ts.map +1 -0
  75. package/dist/modules/deals/events.js +12 -0
  76. package/dist/modules/deals/events.js.map +1 -0
  77. package/dist/modules/deals/index.d.ts.map +1 -1
  78. package/dist/modules/deals/index.js +2 -0
  79. package/dist/modules/deals/index.js.map +1 -1
  80. package/dist/modules/deals/service.d.ts +1 -0
  81. package/dist/modules/deals/service.d.ts.map +1 -1
  82. package/dist/modules/deals/service.js +9 -18
  83. package/dist/modules/deals/service.js.map +1 -1
  84. package/dist/modules/decisions/events.d.ts +21 -0
  85. package/dist/modules/decisions/events.d.ts.map +1 -0
  86. package/dist/modules/decisions/events.js +11 -0
  87. package/dist/modules/decisions/events.js.map +1 -0
  88. package/dist/modules/decisions/index.d.ts.map +1 -1
  89. package/dist/modules/decisions/index.js +2 -0
  90. package/dist/modules/decisions/index.js.map +1 -1
  91. package/dist/modules/decisions/service.d.ts +1 -0
  92. package/dist/modules/decisions/service.d.ts.map +1 -1
  93. package/dist/modules/decisions/service.js +4 -7
  94. package/dist/modules/decisions/service.js.map +1 -1
  95. package/dist/modules/eventCatalogs.d.ts +35 -0
  96. package/dist/modules/eventCatalogs.d.ts.map +1 -0
  97. package/dist/modules/eventCatalogs.js +35 -0
  98. package/dist/modules/eventCatalogs.js.map +1 -0
  99. package/dist/modules/forms/events.d.ts +37 -0
  100. package/dist/modules/forms/events.d.ts.map +1 -0
  101. package/dist/modules/forms/events.js +15 -0
  102. package/dist/modules/forms/events.js.map +1 -0
  103. package/dist/modules/forms/index.d.ts.map +1 -1
  104. package/dist/modules/forms/index.js +2 -0
  105. package/dist/modules/forms/index.js.map +1 -1
  106. package/dist/modules/forms/service.d.ts +1 -0
  107. package/dist/modules/forms/service.d.ts.map +1 -1
  108. package/dist/modules/forms/service.js +8 -11
  109. package/dist/modules/forms/service.js.map +1 -1
  110. package/dist/modules/forms/submission.d.ts +5 -0
  111. package/dist/modules/forms/submission.d.ts.map +1 -1
  112. package/dist/modules/forms/submission.js +54 -28
  113. package/dist/modules/forms/submission.js.map +1 -1
  114. package/dist/modules/handbook/events.d.ts +28 -0
  115. package/dist/modules/handbook/events.d.ts.map +1 -0
  116. package/dist/modules/handbook/events.js +14 -0
  117. package/dist/modules/handbook/events.js.map +1 -0
  118. package/dist/modules/handbook/index.d.ts.map +1 -1
  119. package/dist/modules/handbook/index.js +2 -0
  120. package/dist/modules/handbook/index.js.map +1 -1
  121. package/dist/modules/handbook/service.d.ts +1 -0
  122. package/dist/modules/handbook/service.d.ts.map +1 -1
  123. package/dist/modules/handbook/service.js +8 -15
  124. package/dist/modules/handbook/service.js.map +1 -1
  125. package/dist/modules/hiring/candidates.d.ts +1 -0
  126. package/dist/modules/hiring/candidates.d.ts.map +1 -1
  127. package/dist/modules/hiring/candidates.js +8 -11
  128. package/dist/modules/hiring/candidates.js.map +1 -1
  129. package/dist/modules/hiring/events.d.ts +35 -0
  130. package/dist/modules/hiring/events.d.ts.map +1 -0
  131. package/dist/modules/hiring/events.js +11 -0
  132. package/dist/modules/hiring/events.js.map +1 -0
  133. package/dist/modules/hiring/index.d.ts.map +1 -1
  134. package/dist/modules/hiring/index.js +2 -0
  135. package/dist/modules/hiring/index.js.map +1 -1
  136. package/dist/modules/hiring/roles.d.ts +1 -0
  137. package/dist/modules/hiring/roles.d.ts.map +1 -1
  138. package/dist/modules/hiring/roles.js +8 -11
  139. package/dist/modules/hiring/roles.js.map +1 -1
  140. package/dist/modules/import-export/drafts.d.ts +9 -0
  141. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  142. package/dist/modules/import-export/drafts.js +25 -0
  143. package/dist/modules/import-export/drafts.js.map +1 -1
  144. package/dist/modules/import-export/events.d.ts +22 -0
  145. package/dist/modules/import-export/events.d.ts.map +1 -0
  146. package/dist/modules/import-export/events.js +12 -0
  147. package/dist/modules/import-export/events.js.map +1 -0
  148. package/dist/modules/import-export/exportRows.d.ts +9 -0
  149. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  150. package/dist/modules/import-export/exportRows.js +10 -1
  151. package/dist/modules/import-export/exportRows.js.map +1 -1
  152. package/dist/modules/import-export/index.d.ts.map +1 -1
  153. package/dist/modules/import-export/index.js +2 -0
  154. package/dist/modules/import-export/index.js.map +1 -1
  155. package/dist/modules/import-export/plan.d.ts +23 -1
  156. package/dist/modules/import-export/plan.d.ts.map +1 -1
  157. package/dist/modules/import-export/plan.js +62 -3
  158. package/dist/modules/import-export/plan.js.map +1 -1
  159. package/dist/modules/import-export/presets.d.ts.map +1 -1
  160. package/dist/modules/import-export/presets.js +25 -0
  161. package/dist/modules/import-export/presets.js.map +1 -1
  162. package/dist/modules/import-export/repository.d.ts +17 -0
  163. package/dist/modules/import-export/repository.d.ts.map +1 -1
  164. package/dist/modules/import-export/repository.js +21 -1
  165. package/dist/modules/import-export/repository.js.map +1 -1
  166. package/dist/modules/import-export/routes.d.ts.map +1 -1
  167. package/dist/modules/import-export/routes.js +5 -1
  168. package/dist/modules/import-export/routes.js.map +1 -1
  169. package/dist/modules/import-export/schema.d.ts +55 -0
  170. package/dist/modules/import-export/schema.d.ts.map +1 -1
  171. package/dist/modules/import-export/schema.js +13 -1
  172. package/dist/modules/import-export/schema.js.map +1 -1
  173. package/dist/modules/import-export/service.d.ts +9 -1
  174. package/dist/modules/import-export/service.d.ts.map +1 -1
  175. package/dist/modules/import-export/service.js +104 -17
  176. package/dist/modules/import-export/service.js.map +1 -1
  177. package/dist/modules/import-export/tools.d.ts.map +1 -1
  178. package/dist/modules/import-export/tools.js +7 -1
  179. package/dist/modules/import-export/tools.js.map +1 -1
  180. package/dist/modules/import-export/writes.d.ts +16 -0
  181. package/dist/modules/import-export/writes.d.ts.map +1 -1
  182. package/dist/modules/import-export/writes.js +77 -2
  183. package/dist/modules/import-export/writes.js.map +1 -1
  184. package/dist/modules/notes/events.d.ts +22 -0
  185. package/dist/modules/notes/events.d.ts.map +1 -0
  186. package/dist/modules/notes/events.js +12 -0
  187. package/dist/modules/notes/events.js.map +1 -0
  188. package/dist/modules/notes/index.d.ts.map +1 -1
  189. package/dist/modules/notes/index.js +2 -0
  190. package/dist/modules/notes/index.js.map +1 -1
  191. package/dist/modules/notes/service.d.ts +1 -0
  192. package/dist/modules/notes/service.d.ts.map +1 -1
  193. package/dist/modules/notes/service.js +4 -7
  194. package/dist/modules/notes/service.js.map +1 -1
  195. package/dist/modules/opportunities/events.d.ts +31 -0
  196. package/dist/modules/opportunities/events.d.ts.map +1 -0
  197. package/dist/modules/opportunities/events.js +12 -0
  198. package/dist/modules/opportunities/events.js.map +1 -0
  199. package/dist/modules/opportunities/index.d.ts.map +1 -1
  200. package/dist/modules/opportunities/index.js +2 -0
  201. package/dist/modules/opportunities/index.js.map +1 -1
  202. package/dist/modules/opportunities/service.d.ts +1 -0
  203. package/dist/modules/opportunities/service.d.ts.map +1 -1
  204. package/dist/modules/opportunities/service.js +9 -18
  205. package/dist/modules/opportunities/service.js.map +1 -1
  206. package/dist/modules/partnerships/events.d.ts +31 -0
  207. package/dist/modules/partnerships/events.d.ts.map +1 -0
  208. package/dist/modules/partnerships/events.js +12 -0
  209. package/dist/modules/partnerships/events.js.map +1 -0
  210. package/dist/modules/partnerships/index.d.ts.map +1 -1
  211. package/dist/modules/partnerships/index.js +2 -0
  212. package/dist/modules/partnerships/index.js.map +1 -1
  213. package/dist/modules/partnerships/service.d.ts +1 -0
  214. package/dist/modules/partnerships/service.d.ts.map +1 -1
  215. package/dist/modules/partnerships/service.js +9 -18
  216. package/dist/modules/partnerships/service.js.map +1 -1
  217. package/dist/modules/people/events.d.ts +28 -0
  218. package/dist/modules/people/events.d.ts.map +1 -0
  219. package/dist/modules/people/events.js +18 -0
  220. package/dist/modules/people/events.js.map +1 -0
  221. package/dist/modules/people/index.d.ts.map +1 -1
  222. package/dist/modules/people/index.js +2 -0
  223. package/dist/modules/people/index.js.map +1 -1
  224. package/dist/modules/people/service.d.ts +1 -0
  225. package/dist/modules/people/service.d.ts.map +1 -1
  226. package/dist/modules/people/service.js +8 -11
  227. package/dist/modules/people/service.js.map +1 -1
  228. package/dist/modules/pipelines/service.d.ts +4 -0
  229. package/dist/modules/pipelines/service.d.ts.map +1 -1
  230. package/dist/modules/pipelines/service.js +31 -8
  231. package/dist/modules/pipelines/service.js.map +1 -1
  232. package/dist/modules/plans/events.d.ts +21 -0
  233. package/dist/modules/plans/events.d.ts.map +1 -0
  234. package/dist/modules/plans/events.js +11 -0
  235. package/dist/modules/plans/events.js.map +1 -0
  236. package/dist/modules/plans/index.d.ts.map +1 -1
  237. package/dist/modules/plans/index.js +2 -0
  238. package/dist/modules/plans/index.js.map +1 -1
  239. package/dist/modules/plans/service.d.ts +1 -0
  240. package/dist/modules/plans/service.d.ts.map +1 -1
  241. package/dist/modules/plans/service.js +6 -14
  242. package/dist/modules/plans/service.js.map +1 -1
  243. package/dist/modules/positions/events.d.ts +22 -0
  244. package/dist/modules/positions/events.d.ts.map +1 -0
  245. package/dist/modules/positions/events.js +8 -0
  246. package/dist/modules/positions/events.js.map +1 -0
  247. package/dist/modules/positions/index.d.ts.map +1 -1
  248. package/dist/modules/positions/index.js +2 -0
  249. package/dist/modules/positions/index.js.map +1 -1
  250. package/dist/modules/positions/service.d.ts +1 -0
  251. package/dist/modules/positions/service.d.ts.map +1 -1
  252. package/dist/modules/positions/service.js +8 -11
  253. package/dist/modules/positions/service.js.map +1 -1
  254. package/dist/modules/raises/events.d.ts +31 -0
  255. package/dist/modules/raises/events.d.ts.map +1 -0
  256. package/dist/modules/raises/events.js +12 -0
  257. package/dist/modules/raises/events.js.map +1 -0
  258. package/dist/modules/raises/index.d.ts.map +1 -1
  259. package/dist/modules/raises/index.js +2 -0
  260. package/dist/modules/raises/index.js.map +1 -1
  261. package/dist/modules/raises/service.d.ts +1 -0
  262. package/dist/modules/raises/service.d.ts.map +1 -1
  263. package/dist/modules/raises/service.js +9 -18
  264. package/dist/modules/raises/service.js.map +1 -1
  265. package/dist/modules/reseal.d.ts +55 -0
  266. package/dist/modules/reseal.d.ts.map +1 -1
  267. package/dist/modules/reseal.js +90 -1
  268. package/dist/modules/reseal.js.map +1 -1
  269. package/dist/modules/smtp-email/index.d.ts +69 -0
  270. package/dist/modules/smtp-email/index.d.ts.map +1 -0
  271. package/dist/modules/smtp-email/index.js +82 -0
  272. package/dist/modules/smtp-email/index.js.map +1 -0
  273. package/dist/modules/webhooks/index.d.ts.map +1 -1
  274. package/dist/modules/webhooks/index.js +5 -1
  275. package/dist/modules/webhooks/index.js.map +1 -1
  276. package/dist/modules/webhooks/payloads.d.ts +22 -7
  277. package/dist/modules/webhooks/payloads.d.ts.map +1 -1
  278. package/dist/modules/webhooks/payloads.js +63 -44
  279. package/dist/modules/webhooks/payloads.js.map +1 -1
  280. package/dist/modules/workspace/events.d.ts +52 -0
  281. package/dist/modules/workspace/events.d.ts.map +1 -0
  282. package/dist/modules/workspace/events.js +16 -0
  283. package/dist/modules/workspace/events.js.map +1 -0
  284. package/dist/modules/workspace/index.d.ts.map +1 -1
  285. package/dist/modules/workspace/index.js +6 -2
  286. package/dist/modules/workspace/index.js.map +1 -1
  287. package/dist/modules/workspace/service.d.ts +1 -0
  288. package/dist/modules/workspace/service.d.ts.map +1 -1
  289. package/dist/modules/workspace/service.js +13 -15
  290. package/dist/modules/workspace/service.js.map +1 -1
  291. package/dist/runtime/events.d.ts +86 -108
  292. package/dist/runtime/events.d.ts.map +1 -1
  293. package/dist/runtime/events.js +123 -52
  294. package/dist/runtime/events.js.map +1 -1
  295. package/dist/runtime/module.d.ts +54 -2
  296. package/dist/runtime/module.d.ts.map +1 -1
  297. package/dist/runtime/registry.d.ts +23 -0
  298. package/dist/runtime/registry.d.ts.map +1 -1
  299. package/dist/runtime/registry.js +102 -2
  300. package/dist/runtime/registry.js.map +1 -1
  301. package/dist/runtime/transaction.d.ts +29 -4
  302. package/dist/runtime/transaction.d.ts.map +1 -1
  303. package/dist/runtime/transaction.js +48 -7
  304. package/dist/runtime/transaction.js.map +1 -1
  305. package/dist/testing/app.d.ts +5 -1
  306. package/dist/testing/app.d.ts.map +1 -1
  307. package/dist/testing/app.js +13 -3
  308. package/dist/testing/app.js.map +1 -1
  309. package/dist/testing/database.d.ts.map +1 -1
  310. package/dist/testing/database.js +6 -3
  311. package/dist/testing/database.js.map +1 -1
  312. package/dist/testing/services.d.ts +21 -1
  313. package/dist/testing/services.d.ts.map +1 -1
  314. package/dist/testing/services.js +20 -5
  315. package/dist/testing/services.js.map +1 -1
  316. package/migrations/0019_sharp_red_skull.sql +4 -0
  317. package/migrations/0020_early_nemesis.sql +2 -0
  318. package/migrations/meta/0019_snapshot.json +5138 -0
  319. package/migrations/meta/0020_snapshot.json +5138 -0
  320. package/migrations/meta/_journal.json +14 -0
  321. package/package.json +5 -2
  322. package/src/app.ts +26 -0
  323. package/src/boot.ts +89 -0
  324. package/src/index.ts +52 -9
  325. package/src/lib/actor.ts +15 -1
  326. package/src/lib/config.ts +65 -7
  327. package/src/lib/email.ts +22 -92
  328. package/src/lib/fromEnv.ts +143 -0
  329. package/src/lib/ids.ts +6 -0
  330. package/src/lib/kelpieConfigFile.ts +291 -0
  331. package/src/lib/logger.ts +92 -34
  332. package/src/modules/agent-tasks/index.ts +4 -1
  333. package/src/modules/agent-tasks/prompt.ts +57 -9
  334. package/src/modules/agent-tasks/service.ts +3 -2
  335. package/src/modules/agent-tasks/wire.ts +12 -0
  336. package/src/modules/auth/index.ts +11 -9
  337. package/src/modules/companies/events.ts +25 -0
  338. package/src/modules/companies/index.ts +2 -0
  339. package/src/modules/companies/service.ts +8 -11
  340. package/src/modules/core.ts +4 -0
  341. package/src/modules/deals/events.ts +34 -0
  342. package/src/modules/deals/index.ts +2 -0
  343. package/src/modules/deals/service.ts +17 -18
  344. package/src/modules/decisions/events.ts +24 -0
  345. package/src/modules/decisions/index.ts +2 -0
  346. package/src/modules/decisions/service.ts +8 -7
  347. package/src/modules/eventCatalogs.ts +35 -0
  348. package/src/modules/forms/events.ts +37 -0
  349. package/src/modules/forms/index.ts +2 -0
  350. package/src/modules/forms/service.ts +12 -11
  351. package/src/modules/forms/submission.ts +80 -29
  352. package/src/modules/handbook/events.ts +31 -0
  353. package/src/modules/handbook/index.ts +2 -0
  354. package/src/modules/handbook/service.ts +8 -15
  355. package/src/modules/hiring/candidates.ts +8 -11
  356. package/src/modules/hiring/events.ts +36 -0
  357. package/src/modules/hiring/index.ts +2 -0
  358. package/src/modules/hiring/roles.ts +8 -11
  359. package/src/modules/import-export/drafts.ts +27 -0
  360. package/src/modules/import-export/events.ts +25 -0
  361. package/src/modules/import-export/exportRows.ts +10 -1
  362. package/src/modules/import-export/index.ts +2 -0
  363. package/src/modules/import-export/plan.ts +107 -5
  364. package/src/modules/import-export/presets.ts +25 -0
  365. package/src/modules/import-export/repository.ts +35 -1
  366. package/src/modules/import-export/routes.ts +5 -0
  367. package/src/modules/import-export/schema.ts +13 -0
  368. package/src/modules/import-export/service.ts +153 -19
  369. package/src/modules/import-export/tools.ts +9 -0
  370. package/src/modules/import-export/writes.ts +116 -3
  371. package/src/modules/notes/events.ts +25 -0
  372. package/src/modules/notes/index.ts +2 -0
  373. package/src/modules/notes/service.ts +8 -7
  374. package/src/modules/opportunities/events.ts +34 -0
  375. package/src/modules/opportunities/index.ts +2 -0
  376. package/src/modules/opportunities/service.ts +17 -18
  377. package/src/modules/partnerships/events.ts +34 -0
  378. package/src/modules/partnerships/index.ts +2 -0
  379. package/src/modules/partnerships/service.ts +17 -18
  380. package/src/modules/people/events.ts +36 -0
  381. package/src/modules/people/index.ts +2 -0
  382. package/src/modules/people/service.ts +97 -87
  383. package/src/modules/pipelines/service.ts +47 -8
  384. package/src/modules/plans/events.ts +24 -0
  385. package/src/modules/plans/index.ts +2 -0
  386. package/src/modules/plans/service.ts +14 -14
  387. package/src/modules/positions/events.ts +25 -0
  388. package/src/modules/positions/index.ts +2 -0
  389. package/src/modules/positions/service.ts +8 -11
  390. package/src/modules/raises/events.ts +34 -0
  391. package/src/modules/raises/index.ts +2 -0
  392. package/src/modules/raises/service.ts +17 -18
  393. package/src/modules/reseal.ts +144 -1
  394. package/src/modules/smtp-email/index.ts +119 -0
  395. package/src/modules/webhooks/index.ts +5 -1
  396. package/src/modules/webhooks/payloads.ts +94 -48
  397. package/src/modules/workspace/events.ts +46 -0
  398. package/src/modules/workspace/index.ts +6 -2
  399. package/src/modules/workspace/service.ts +37 -15
  400. package/src/runtime/events.ts +268 -107
  401. package/src/runtime/module.ts +55 -2
  402. package/src/runtime/registry.ts +169 -1
  403. package/src/runtime/transaction.ts +94 -17
  404. package/src/testing/app.ts +18 -4
  405. package/src/testing/database.ts +6 -3
  406. package/src/testing/services.ts +34 -5
@@ -3,12 +3,22 @@ import type { AgentTaskDefinition, AgentTaskTargetType } from '@kelpie/schemas'
3
3
  /**
4
4
  * Renders the markdown prompt a ResolvedTask carries. Pure: every fact arrives
5
5
  * as an argument, so the template is unit-testable and Copy and Run cannot
6
- * drift — both read the one string this produces.
6
+ * drift — both read the strings this file produces.
7
7
  *
8
- * The shape is the mockup's (`mockups/src/data/agentTasks.ts`), with two
9
- * server-era changes: workspace-scoped tasks are pointed at `GET /v1/dashboard`
10
- * instead of a single record, and the sweep tasks carry a "Workspace signals"
11
- * section computed at resolve time.
8
+ * Two renderers, one shared body.
9
+ *
10
+ * - {@link renderBasePrompt} returns the general request: the task title,
11
+ * the target, the required reads, the handbook pages, related ids,
12
+ * workspace signals, the task instructions, and the write policy. It
13
+ * says nothing about *how* the receiver should apply the changes.
14
+ * - {@link renderExternalAgentPrompt} wraps the base with framing for an
15
+ * agent that calls the CRM itself — the opening line about MCP / the
16
+ * public API and the closing "Done when… applied allowed updates" tail.
17
+ *
18
+ * The resolved-task and dispatch payloads carry both. The copy-prompt UI
19
+ * flow serves the external-agent version by default; the hosted AI in the
20
+ * cloud reads the base and adds its own structured-output framing. Two
21
+ * consumers, two wrappers, one body.
12
22
  */
13
23
 
14
24
  /** A handbook page the task requires, resolved to this workspace's own copy. */
@@ -99,7 +109,13 @@ function firstRead(targetType: AgentTaskTargetType): string {
99
109
  return 'Load the target record and agent fields.'
100
110
  }
101
111
 
102
- export function renderPrompt(
112
+ /**
113
+ * The shared body. Renders everything a receiver needs to *understand* the
114
+ * task, without telling it how to apply results. Callers wrap this with an
115
+ * opening and closing that matches how the receiver will execute (call the
116
+ * CRM, or return structured data for a caller to apply).
117
+ */
118
+ export function renderBasePrompt(
103
119
  definition: AgentTaskDefinition,
104
120
  targetType: AgentTaskTargetType,
105
121
  targetId: string,
@@ -107,9 +123,6 @@ export function renderPrompt(
107
123
  ): string {
108
124
  return `# Agent task: ${definition.label}
109
125
 
110
- You are operating on the Kelpie workspace **${inputs.workspaceName}** via MCP / the public API.
111
- Bring your own model. Kelpie does not bundle AI.
112
-
113
126
  ## Task
114
127
  - **Id:** \`${definition.id}\`
115
128
  - **Intent:** ${definition.description}
@@ -133,8 +146,43 @@ ${definition.instructions}
133
146
 
134
147
  ## Write policy
135
148
  ${definition.writePolicy}
149
+ `
150
+ }
136
151
 
152
+ /**
153
+ * The external-agent-framed prompt. Adds the opening line about MCP / the
154
+ * public API and the closing "Done when" tail to the base. This is what the
155
+ * Copy button hands to the user and what dispatch sends by default; an
156
+ * agent that runs its own tool loop against the CRM reads this and works
157
+ * from it directly.
158
+ */
159
+ export function renderExternalAgentPrompt(
160
+ definition: AgentTaskDefinition,
161
+ targetType: AgentTaskTargetType,
162
+ targetId: string,
163
+ inputs: PromptInputs,
164
+ ): string {
165
+ const opening = `# Agent task: ${definition.label}
166
+
167
+ You are operating on the Kelpie workspace **${inputs.workspaceName}** via MCP / the public API.
168
+ Bring your own model. Kelpie does not bundle AI.
169
+ `
170
+
171
+ // The base opens with its own `# Agent task:` header; strip it so the
172
+ // combined prompt has one heading rather than two.
173
+ const base = renderBasePrompt(definition, targetType, targetId, inputs)
174
+ const bodyWithoutHeading = base.replace(/^# Agent task:[^\n]*\n\n?/u, '')
175
+
176
+ return `${opening}
177
+ ${bodyWithoutHeading}
137
178
  ## Done when
138
179
  You have applied allowed updates via MCP/API (or asked the human when blocked), and summarised what changed.
139
180
  `
140
181
  }
182
+
183
+ /**
184
+ * Backwards-compatible alias for the pre-split renderer. Existing callers
185
+ * that produced the "wrapped" prompt keep working. New callers pick
186
+ * {@link renderBasePrompt} or {@link renderExternalAgentPrompt} directly.
187
+ */
188
+ export const renderPrompt = renderExternalAgentPrompt
@@ -14,7 +14,7 @@ import { requireWorkspaceId } from '../auth/actor.ts'
14
14
  import { roleAllows } from '../workspace/roles.ts'
15
15
  import { AGENT_TASK_DEFINITIONS, findTask, tasksFor } from './catalog.ts'
16
16
  import type { DispatchEngine } from './dispatch.ts'
17
- import { renderPrompt } from './prompt.ts'
17
+ import { renderBasePrompt, renderExternalAgentPrompt } from './prompt.ts'
18
18
  import * as repository from './repository.ts'
19
19
  import { AGENT_SORTS, DEFAULT_AGENT_SORT, DEFAULT_RUN_SORT, RUN_SORTS } from './repository.ts'
20
20
  import type { AgentRecord, RunFilters, RunRecord } from './repository.ts'
@@ -184,7 +184,8 @@ export function createAgentTasksService(dependencies: AgentTasksDependencies): A
184
184
  taskId: definition.id,
185
185
  targetType: target.targetType,
186
186
  targetId: target.targetId,
187
- prompt: renderPrompt(definition, target.targetType, target.targetId, inputs),
187
+ prompt: renderExternalAgentPrompt(definition, target.targetType, target.targetId, inputs),
188
+ basePrompt: renderBasePrompt(definition, target.targetType, target.targetId, inputs),
188
189
  context: {
189
190
  targetLabel: inputs.targetLabel,
190
191
  deepLink: inputs.deepLink,
@@ -21,7 +21,18 @@ export interface ResolvedTaskView {
21
21
  readonly taskId: string
22
22
  readonly targetType: AgentTaskTargetType
23
23
  readonly targetId: string
24
+ /**
25
+ * The external-agent-framed prompt: opens with "operating via MCP / the
26
+ * public API", ends with "Done when… applied allowed updates". This is
27
+ * what Copy hands to a user and what a customer agent reads.
28
+ */
24
29
  readonly prompt: string
30
+ /**
31
+ * The shared body without the framing. What an agent that returns
32
+ * structured data (the hosted AI is the one that ships) reads before
33
+ * adding its own instructions.
34
+ */
35
+ readonly basePrompt: string
25
36
  readonly context: ContextPackView
26
37
  }
27
38
 
@@ -31,6 +42,7 @@ export function resolvedTaskResponse(resolved: ResolvedTaskView): Record<string,
31
42
  target_type: resolved.targetType,
32
43
  target_id: resolved.targetId,
33
44
  prompt: resolved.prompt,
45
+ base_prompt: resolved.basePrompt,
34
46
  context: {
35
47
  target_label: resolved.context.targetLabel,
36
48
  deep_link: resolved.context.deepLink,
@@ -13,12 +13,10 @@ import { createAuthService } from './service.ts'
13
13
  * `users`.
14
14
  */
15
15
 
16
- const authConfigSchema = z
17
- .object({
18
- /** Cookies go out `Secure` everywhere except development. */
19
- NODE_ENV: z.enum(['development', 'test', 'production']),
20
- })
21
- .merge(appUrlConfigSchema)
16
+ const nodeEnvSchema = z.object({
17
+ /** Cookies go out `Secure` everywhere except development. */
18
+ NODE_ENV: z.enum(['development', 'test', 'production']),
19
+ })
22
20
 
23
21
  export function createAuthModule(migrationsDirectory: string): KelpieModule {
24
22
  return {
@@ -26,14 +24,18 @@ export function createAuthModule(migrationsDirectory: string): KelpieModule {
26
24
  structural: true,
27
25
 
28
26
  register(context) {
29
- const config = context.config(authConfigSchema)
27
+ const { NODE_ENV } = context.config(nodeEnvSchema)
28
+ // Prefer the top-level `appBaseUrl` from the assembly's kelpie.config.ts;
29
+ // fall back to the schema read for older assemblies that don't declare it.
30
+ const appBaseUrl = context.appBaseUrl ?? context.config(appUrlConfigSchema).APP_BASE_URL
31
+
30
32
  const service = createAuthService({
31
33
  db: context.db,
32
34
  transaction: context.transaction,
33
35
  email: context.email,
34
36
  createId: context.createId,
35
37
  now: context.now,
36
- appBaseUrl: config.APP_BASE_URL,
38
+ appBaseUrl,
37
39
  })
38
40
 
39
41
  context.schema(schema, migrationsDirectory)
@@ -46,7 +48,7 @@ export function createAuthModule(migrationsDirectory: string): KelpieModule {
46
48
  // `Secure` everywhere except development. A test host reaches the API
47
49
  // over http through a test client, which stores the cookie regardless
48
50
  // of the flag, so test is not excluded.
49
- cookie: { secure: config.NODE_ENV !== 'development' },
51
+ cookie: { secure: NODE_ENV !== 'development' },
50
52
  })
51
53
  })
52
54
 
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /** Domain events published by the companies module. */
6
+
7
+ export const companiesEvents = {
8
+ 'companies.company.created': z.object({}).strict(),
9
+ 'companies.company.updated': z.object({ changed: z.array(z.string()).readonly() }),
10
+ 'companies.company.deleted': z.object({}).strict(),
11
+ } satisfies ModuleEventCatalog
12
+
13
+ export type CompanyCreatedData = Record<string, never>
14
+ export interface CompanyUpdatedData {
15
+ readonly changed: readonly string[]
16
+ }
17
+ export type CompanyDeletedData = Record<string, never>
18
+
19
+ declare module '../../runtime/events.ts' {
20
+ interface KelpieEventMap {
21
+ 'companies.company.created': CompanyCreatedData
22
+ 'companies.company.updated': CompanyUpdatedData
23
+ 'companies.company.deleted': CompanyDeletedData
24
+ }
25
+ }
@@ -1,5 +1,6 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
2
  import { createActivityRecorder } from '../activities/index.ts'
3
+ import { companiesEvents } from './events.ts'
3
4
  import { mountCompaniesRoutes } from './routes.ts'
4
5
  import * as schema from './schema.ts'
5
6
  import { createCompaniesService } from './service.ts'
@@ -16,6 +17,7 @@ export function createCompaniesModule(migrationsDirectory: string): KelpieModule
16
17
  id: 'companies',
17
18
  requires: ['workspace', 'activities'],
18
19
  structural: true,
20
+ events: companiesEvents,
19
21
 
20
22
  register(context) {
21
23
  const service = createCompaniesService({
@@ -10,8 +10,10 @@ import type { TransactionScope } from '../../runtime/transaction.ts'
10
10
  import type { ActivityRecorder } from '../activities/recorder.ts'
11
11
  import { describeCreation, describeUpdate } from '../activities/wording.ts'
12
12
  import type { FieldLabels } from '../activities/wording.ts'
13
+ import { toEventActor } from '../../lib/actor.ts'
13
14
  import type { Actor } from '../auth/actor.ts'
14
15
  import { requireWorkspaceId } from '../auth/actor.ts'
16
+ import './events.ts'
15
17
  import { deleteRecordsAttachedTo } from '../attachedRecords.ts'
16
18
  import { referencedElsewhere } from '../references.ts'
17
19
  import * as repository from './repository.ts'
@@ -185,10 +187,10 @@ export function createCompaniesService(dependencies: CompaniesDependencies): Com
185
187
  ...describeCreation('Company'),
186
188
  })
187
189
 
188
- events.emit('record.created', { workspaceId, objectType: 'company', recordId: created.id })
190
+ events.emit('companies.company.created', { type: 'company', id: created.id }, {})
189
191
 
190
192
  return toView(created)
191
- })
193
+ }, { workspaceId, actor: toEventActor(actor) })
192
194
  },
193
195
 
194
196
  async update(actor, id, changes) {
@@ -228,15 +230,10 @@ export function createCompaniesService(dependencies: CompaniesDependencies): Com
228
230
  ...describeUpdate(changed, COMPANY_FIELD_LABELS, existing, columns),
229
231
  })
230
232
 
231
- events.emit('record.updated', {
232
- workspaceId,
233
- objectType: 'company',
234
- recordId: id,
235
- changedFields: changed,
236
- })
233
+ events.emit('companies.company.updated', { type: 'company', id }, { changed })
237
234
 
238
235
  return toView(updated)
239
- })
236
+ }, { workspaceId, actor: toEventActor(actor) })
240
237
  },
241
238
 
242
239
  async remove(actor, id) {
@@ -260,8 +257,8 @@ export function createCompaniesService(dependencies: CompaniesDependencies): Com
260
257
  throw error
261
258
  }
262
259
 
263
- events.emit('record.deleted', { workspaceId, objectType: 'company', recordId: id })
264
- })
260
+ events.emit('companies.company.deleted', { type: 'company', id }, {})
261
+ }, { workspaceId, actor: toEventActor(actor) })
265
262
  },
266
263
  }
267
264
  }
@@ -22,6 +22,7 @@ import { createPlansModule } from './plans/index.ts'
22
22
  import { createPositionsModule } from './positions/index.ts'
23
23
  import { createRaisesModule } from './raises/index.ts'
24
24
  import { createSearchModule } from './search/index.ts'
25
+ import { createSmtpEmailModule } from './smtp-email/index.ts'
25
26
  import { createWebhooksModule } from './webhooks/index.ts'
26
27
  import { createWorkspaceModule } from './workspace/index.ts'
27
28
 
@@ -65,4 +66,7 @@ export const coreModules: readonly KelpieModule[] = [
65
66
  createImportExportModule(coreMigrationsDirectory),
66
67
  createAgentTasksModule(coreMigrationsDirectory),
67
68
  createWebhooksModule(coreMigrationsDirectory),
69
+ // Owns no tables. Registers a `'smtp'` provider with core's email runtime;
70
+ // the factory only runs if the assembly's `email.provider` picks it.
71
+ createSmtpEmailModule(),
68
72
  ]
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /** Domain events published by the deals module. */
6
+
7
+ export const dealsEvents = {
8
+ 'deals.deal.created': z.object({}).strict(),
9
+ 'deals.deal.updated': z.object({ changed: z.array(z.string()).readonly() }),
10
+ 'deals.deal.deleted': z.object({}).strict(),
11
+ 'deals.deal.stage_changed': z.object({
12
+ fromStageId: z.string().nullable(),
13
+ toStageId: z.string(),
14
+ }),
15
+ } satisfies ModuleEventCatalog
16
+
17
+ export type DealCreatedData = Record<string, never>
18
+ export interface DealUpdatedData {
19
+ readonly changed: readonly string[]
20
+ }
21
+ export type DealDeletedData = Record<string, never>
22
+ export interface DealStageChangedData {
23
+ readonly fromStageId: string | null
24
+ readonly toStageId: string
25
+ }
26
+
27
+ declare module '../../runtime/events.ts' {
28
+ interface KelpieEventMap {
29
+ 'deals.deal.created': DealCreatedData
30
+ 'deals.deal.updated': DealUpdatedData
31
+ 'deals.deal.deleted': DealDeletedData
32
+ 'deals.deal.stage_changed': DealStageChangedData
33
+ }
34
+ }
@@ -1,5 +1,6 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
2
  import { createActivityRecorder } from '../activities/index.ts'
3
+ import { dealsEvents } from './events.ts'
3
4
  import { mountDealsRoutes } from './routes.ts'
4
5
  import * as schema from './schema.ts'
5
6
  import { createDealsService } from './service.ts'
@@ -17,6 +18,7 @@ export function createDealsModule(migrationsDirectory: string): KelpieModule {
17
18
  return {
18
19
  id: 'deals',
19
20
  requires: ['companies', 'people', 'pipelines', 'activities'],
21
+ events: dealsEvents,
20
22
 
21
23
  register(context) {
22
24
  const service = createDealsService({
@@ -14,8 +14,10 @@ import {
14
14
  describeUpdate,
15
15
  } from '../activities/wording.ts'
16
16
  import type { FieldLabels } from '../activities/wording.ts'
17
+ import { toEventActor } from '../../lib/actor.ts'
17
18
  import type { Actor } from '../auth/actor.ts'
18
19
  import { actorMemberId, requireWorkspaceId } from '../auth/actor.ts'
20
+ import './events.ts'
19
21
  import { deleteRecordsAttachedTo } from '../attachedRecords.ts'
20
22
  import * as companyRepository from '../companies/repository.ts'
21
23
  import * as pipelineRepository from '../pipelines/repository.ts'
@@ -297,10 +299,10 @@ export function createDealsService(dependencies: DealsDependencies): DealsServic
297
299
  })
298
300
  }
299
301
 
300
- events.emit('record.created', { workspaceId, objectType: 'deal', recordId: id })
302
+ events.emit('deals.deal.created', { type: 'deal', id }, {})
301
303
 
302
304
  return toView(created, personIds)
303
- })
305
+ }, { workspaceId, actor: toEventActor(actor) })
304
306
  },
305
307
 
306
308
  async update(actor, id, changes) {
@@ -393,25 +395,22 @@ export function createDealsService(dependencies: DealsDependencies): DealsServic
393
395
  })
394
396
  }
395
397
 
396
- events.emit('record.updated', {
397
- workspaceId,
398
- objectType: 'deal',
399
- recordId: id,
400
- changedFields: linksChanged ? [...changed, 'personIds'] : changed,
401
- })
398
+ events.emit(
399
+ 'deals.deal.updated',
400
+ { type: 'deal', id },
401
+ { changed: linksChanged ? [...changed, 'personIds'] : changed },
402
+ )
402
403
 
403
404
  if (stageMove !== undefined) {
404
- events.emit('stage.changed', {
405
- workspaceId,
406
- objectType: 'deal',
407
- recordId: id,
408
- fromStageId: stageMove.from.id,
409
- toStageId: stageMove.to.id,
410
- })
405
+ events.emit(
406
+ 'deals.deal.stage_changed',
407
+ { type: 'deal', id },
408
+ { fromStageId: stageMove.from.id, toStageId: stageMove.to.id },
409
+ )
411
410
  }
412
411
 
413
412
  return toView(updated, nextPeople ?? currentPeople)
414
- })
413
+ }, { workspaceId, actor: toEventActor(actor) })
415
414
  },
416
415
 
417
416
  async remove(actor, id) {
@@ -426,8 +425,8 @@ export function createDealsService(dependencies: DealsDependencies): DealsServic
426
425
  await deleteRecordsAttachedTo(tx, workspaceId, 'deal', id)
427
426
  await repository.deleteDeal(tx, workspaceId, id)
428
427
 
429
- events.emit('record.deleted', { workspaceId, objectType: 'deal', recordId: id })
430
- })
428
+ events.emit('deals.deal.deleted', { type: 'deal', id }, {})
429
+ }, { workspaceId, actor: toEventActor(actor) })
431
430
  },
432
431
  }
433
432
  }
@@ -0,0 +1,24 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /**
6
+ * Domain events published by the decisions module.
7
+ *
8
+ * `target` is the record the decision attaches to; the decision's own id lives
9
+ * in `data`.
10
+ */
11
+
12
+ export const decisionsEvents = {
13
+ 'decisions.decision.added': z.object({ decisionId: z.string() }),
14
+ } satisfies ModuleEventCatalog
15
+
16
+ export interface DecisionAddedData {
17
+ readonly decisionId: string
18
+ }
19
+
20
+ declare module '../../runtime/events.ts' {
21
+ interface KelpieEventMap {
22
+ 'decisions.decision.added': DecisionAddedData
23
+ }
24
+ }
@@ -1,4 +1,5 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
+ import { decisionsEvents } from './events.ts'
2
3
  import { mountDecisionsRoutes } from './routes.ts'
3
4
  import * as schema from './schema.ts'
4
5
  import { createDecisionsService } from './service.ts'
@@ -17,6 +18,7 @@ export function createDecisionsModule(migrationsDirectory: string): KelpieModule
17
18
  id: 'decisions',
18
19
  requires: ['workspace'],
19
20
  structural: true,
21
+ events: decisionsEvents,
20
22
 
21
23
  register(context) {
22
24
  const service = createDecisionsService({
@@ -5,8 +5,10 @@ import type { IdFactory } from '../../lib/ids.ts'
5
5
  import { mapPage, readListWindow, toPage } from '../../lib/pagination.ts'
6
6
  import type { ListQueryParameters, Page } from '../../lib/pagination.ts'
7
7
  import type { TransactionScope } from '../../runtime/transaction.ts'
8
+ import { toEventActor } from '../../lib/actor.ts'
8
9
  import type { Actor } from '../auth/actor.ts'
9
10
  import { actorMemberId, requireWorkspaceId } from '../auth/actor.ts'
11
+ import './events.ts'
10
12
  import { targetExists } from '../recordTargets.ts'
11
13
  import type { RecordTargetType } from '../recordTargets.ts'
12
14
  import * as repository from './repository.ts'
@@ -158,15 +160,14 @@ export function createDecisionsService(dependencies: DecisionsDependencies): Dec
158
160
  // decisions their own event, carrying the target, because a consumer
159
161
  // watching a record wants the commitment without a second lookup to
160
162
  // find out what it is attached to.
161
- events.emit('decision.added', {
162
- workspaceId,
163
- decisionId: created.id,
164
- targetType: created.targetType,
165
- targetId: created.targetId,
166
- })
163
+ events.emit(
164
+ 'decisions.decision.added',
165
+ { type: created.targetType, id: created.targetId },
166
+ { decisionId: created.id },
167
+ )
167
168
 
168
169
  return toView(created)
169
- })
170
+ }, { workspaceId, actor: toEventActor(actor) })
170
171
  },
171
172
 
172
173
  async update(actor, id, changes) {
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Loads every core module's `KelpieEventMap` augmentation at the package entry.
3
+ *
4
+ * Each module declares its event payload types in `<module>/events.ts` through
5
+ * `declare module '../../runtime/events.ts'`. Inside the monorepo those merge
6
+ * because the source graph reaches every file. A consumer that installs
7
+ * `@kelpie/server` from npm typechecks against `dist`, and declaration emit
8
+ * keeps only the imports a file actually references. Nothing in `dist/index.d.ts`
9
+ * referenced the per-module `events.d.ts` files, so `KelpieEventMap` stayed empty
10
+ * for consumers and every `subscribe` handler saw `event.data: unknown`.
11
+ *
12
+ * These side-effect imports give `index.ts` one reference into each catalog. The
13
+ * emitted `index.d.ts` carries them, so a consumer loads the augmentations and
14
+ * gets a typed `event.data` without a cast at the read site.
15
+ *
16
+ * List only modules whose `events.ts` augments `KelpieEventMap`. A module that
17
+ * publishes no events has no `events.ts` and does not belong here. Order mirrors
18
+ * `coreModules` in `core.ts` for readability; it has no runtime effect.
19
+ */
20
+
21
+ import './workspace/events.ts'
22
+ import './people/events.ts'
23
+ import './companies/events.ts'
24
+ import './positions/events.ts'
25
+ import './notes/events.ts'
26
+ import './deals/events.ts'
27
+ import './opportunities/events.ts'
28
+ import './partnerships/events.ts'
29
+ import './raises/events.ts'
30
+ import './hiring/events.ts'
31
+ import './plans/events.ts'
32
+ import './decisions/events.ts'
33
+ import './handbook/events.ts'
34
+ import './forms/events.ts'
35
+ import './import-export/events.ts'
@@ -0,0 +1,37 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /**
6
+ * Domain events published by the forms module.
7
+ *
8
+ * `forms.form.*` cover the form definition CRUD. `forms.submission.submitted`
9
+ * fires once per submission; the webhooks bridge translates it to the wire
10
+ * `form.submitted` event (the ids live in `data`).
11
+ */
12
+
13
+ export const formsEvents = {
14
+ 'forms.form.created': z.object({}).strict(),
15
+ 'forms.form.updated': z.object({ changed: z.array(z.string()).readonly() }),
16
+ 'forms.form.deleted': z.object({}).strict(),
17
+ 'forms.submission.submitted': z.object({ formId: z.string(), submissionId: z.string() }),
18
+ } satisfies ModuleEventCatalog
19
+
20
+ export type FormCreatedData = Record<string, never>
21
+ export interface FormUpdatedData {
22
+ readonly changed: readonly string[]
23
+ }
24
+ export type FormDeletedData = Record<string, never>
25
+ export interface FormSubmissionData {
26
+ readonly formId: string
27
+ readonly submissionId: string
28
+ }
29
+
30
+ declare module '../../runtime/events.ts' {
31
+ interface KelpieEventMap {
32
+ 'forms.form.created': FormCreatedData
33
+ 'forms.form.updated': FormUpdatedData
34
+ 'forms.form.deleted': FormDeletedData
35
+ 'forms.submission.submitted': FormSubmissionData
36
+ }
37
+ }
@@ -1,5 +1,6 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
2
  import { createActivityRecorder } from '../activities/index.ts'
3
+ import { formsEvents } from './events.ts'
3
4
  import { mountPublicFormRoutes } from './publicRoutes.ts'
4
5
  import { mountFormsRoutes } from './routes.ts'
5
6
  import * as schema from './schema.ts'
@@ -23,6 +24,7 @@ export function createFormsModule(migrationsDirectory: string): KelpieModule {
23
24
  return {
24
25
  id: 'forms',
25
26
  requires: ['people', 'companies', 'positions', 'pipelines', 'deals', 'activities'],
27
+ events: formsEvents,
26
28
 
27
29
  register(context) {
28
30
  const service = createFormsService({
@@ -6,8 +6,10 @@ import { mapPage, readListWindow, toPage } from '../../lib/pagination.ts'
6
6
  import type { ListQueryParameters, Page } from '../../lib/pagination.ts'
7
7
  import { generateToken } from '../../lib/tokens.ts'
8
8
  import type { Transaction, TransactionScope } from '../../runtime/transaction.ts'
9
+ import { toEventActor } from '../../lib/actor.ts'
9
10
  import type { Actor } from '../auth/actor.ts'
10
11
  import { requireWorkspaceId } from '../auth/actor.ts'
12
+ import './events.ts'
11
13
  import * as pipelineRepository from '../pipelines/repository.ts'
12
14
  import { fieldsDiffer, findFieldProblems, storedOptions } from './fields.ts'
13
15
  import type { FieldDraft, FieldShape } from './fields.ts'
@@ -253,10 +255,10 @@ export function createFormsService(dependencies: FormsDependencies): FormsServic
253
255
  })
254
256
  const fields = await writeFields(tx, workspaceId, id, input.fields)
255
257
 
256
- events.emit('record.created', { workspaceId, objectType: 'form', recordId: id })
258
+ events.emit('forms.form.created', { type: 'form', id }, {})
257
259
 
258
260
  return toView(created, fields)
259
- })
261
+ }, { workspaceId, actor: toEventActor(actor) })
260
262
  },
261
263
 
262
264
  async update(actor, id, changes) {
@@ -310,15 +312,14 @@ export function createFormsService(dependencies: FormsDependencies): FormsServic
310
312
  return writeFields(tx, workspaceId, id, changes.fields)
311
313
  })()
312
314
 
313
- events.emit('record.updated', {
314
- workspaceId,
315
- objectType: 'form',
316
- recordId: id,
317
- changedFields: rewritesFields ? [...written, 'fields'] : written,
318
- })
315
+ events.emit(
316
+ 'forms.form.updated',
317
+ { type: 'form', id },
318
+ { changed: rewritesFields ? [...written, 'fields'] : written },
319
+ )
319
320
 
320
321
  return toView(updated, fields)
321
- })
322
+ }, { workspaceId, actor: toEventActor(actor) })
322
323
  },
323
324
 
324
325
  /**
@@ -339,8 +340,8 @@ export function createFormsService(dependencies: FormsDependencies): FormsServic
339
340
  throw AppError.notFound('Form not found')
340
341
  }
341
342
 
342
- events.emit('record.deleted', { workspaceId, objectType: 'form', recordId: id })
343
- })
343
+ events.emit('forms.form.deleted', { type: 'form', id }, {})
344
+ }, { workspaceId, actor: toEventActor(actor) })
344
345
  },
345
346
 
346
347
  async listSubmissions(actor, formId, query) {