@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
@@ -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,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) {
@@ -7,14 +7,19 @@ import { moduleCapabilityName } from '../../runtime/moduleConfig.ts'
7
7
  import type { BufferedEvents, Transaction, TransactionScope } from '../../runtime/transaction.ts'
8
8
  import type { ActivityRecorder, SystemActor } from '../activities/recorder.ts'
9
9
  import { describeCreationVia, describeFormSubmission } from '../activities/wording.ts'
10
+ import '../companies/events.ts'
10
11
  import * as companyRepository from '../companies/repository.ts'
11
12
  import type { CompanyRecord } from '../companies/repository.ts'
12
13
  import * as dealRepository from '../deals/repository.ts'
14
+ import '../deals/events.ts'
15
+ import '../people/events.ts'
13
16
  import * as peopleRepository from '../people/repository.ts'
14
17
  import type { PersonRecord } from '../people/repository.ts'
15
18
  import * as pipelineRepository from '../pipelines/repository.ts'
19
+ import '../positions/events.ts'
16
20
  import * as positionRepository from '../positions/repository.ts'
17
21
  import * as workspaceRepository from '../workspace/repository.ts'
22
+ import './events.ts'
18
23
  import {
19
24
  DEAL_CLOSE_HORIZON_DAYS,
20
25
  companyNameFrom,
@@ -148,34 +153,80 @@ function emitRecordEvents(
148
153
  workspaceId: string,
149
154
  touched: TouchedRecords,
150
155
  ): void {
151
- const upserts = [
152
- { objectType: 'person', outcome: touched.person } as const,
153
- { objectType: 'company', outcome: touched.company } as const,
154
- { objectType: 'position', outcome: touched.position } as const,
155
- ]
156
-
157
- for (const { objectType, outcome } of upserts) {
158
- if (outcome === undefined) {
159
- continue
160
- }
156
+ if (touched.person !== undefined) {
157
+ emitUpsertEvent(events, 'person', touched.person)
158
+ }
159
+ if (touched.company !== undefined) {
160
+ emitUpsertEvent(events, 'company', touched.company)
161
+ }
162
+ if (touched.position !== undefined) {
163
+ emitUpsertEvent(events, 'position', touched.position)
164
+ }
161
165
 
162
- if (outcome.created) {
163
- events.emit('record.created', { workspaceId, objectType, recordId: outcome.record.id })
164
- continue
165
- }
166
+ if (touched.dealId !== null) {
167
+ events.emit('deals.deal.created', { type: 'deal', id: touched.dealId }, {})
168
+ }
169
+ // workspaceId is used by the transaction scope's envelope stamping; the
170
+ // parameter stays on the signature so future call sites keep the same shape.
171
+ void workspaceId
172
+ }
166
173
 
167
- if (outcome.filled.length > 0) {
168
- events.emit('record.updated', {
169
- workspaceId,
170
- objectType,
171
- recordId: outcome.record.id,
172
- changedFields: outcome.filled,
173
- })
174
+ /**
175
+ * Dispatches the created/updated event owned by the record's module for one
176
+ * upsert. Split from the loop above so TypeScript can correlate the object
177
+ * type with its typed event name at each call site.
178
+ */
179
+ function emitUpsertEvent(
180
+ events: BufferedEvents,
181
+ objectType: 'person' | 'company' | 'position',
182
+ outcome: { readonly created: boolean; readonly record: { readonly id: string }; readonly filled: readonly string[] },
183
+ ): void {
184
+ if (outcome.created) {
185
+ switch (objectType) {
186
+ case 'person':
187
+ events.emit('people.person.created', { type: 'person', id: outcome.record.id }, {})
188
+ return
189
+ case 'company':
190
+ events.emit('companies.company.created', { type: 'company', id: outcome.record.id }, {})
191
+ return
192
+ case 'position':
193
+ events.emit(
194
+ 'positions.position.created',
195
+ { type: 'position', id: outcome.record.id },
196
+ {},
197
+ )
198
+ return
174
199
  }
175
200
  }
176
201
 
177
- if (touched.dealId !== null) {
178
- events.emit('record.created', { workspaceId, objectType: 'deal', recordId: touched.dealId })
202
+ if (outcome.filled.length === 0) {
203
+ return
204
+ }
205
+
206
+ const changed = outcome.filled
207
+
208
+ switch (objectType) {
209
+ case 'person':
210
+ events.emit(
211
+ 'people.person.updated',
212
+ { type: 'person', id: outcome.record.id },
213
+ { changed },
214
+ )
215
+ return
216
+ case 'company':
217
+ events.emit(
218
+ 'companies.company.updated',
219
+ { type: 'company', id: outcome.record.id },
220
+ { changed },
221
+ )
222
+ return
223
+ case 'position':
224
+ events.emit(
225
+ 'positions.position.updated',
226
+ { type: 'position', id: outcome.record.id },
227
+ { changed },
228
+ )
229
+ return
179
230
  }
180
231
  }
181
232
 
@@ -484,11 +535,11 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
484
535
  }
485
536
 
486
537
  emitRecordEvents(events, workspaceId, { person, company, position, dealId })
487
- events.emit('form.submitted', {
488
- workspaceId,
489
- formId: form.id,
490
- submissionId: submission.id,
491
- })
538
+ events.emit(
539
+ 'forms.submission.submitted',
540
+ { type: 'submission', id: submission.id },
541
+ { formId: form.id, submissionId: submission.id },
542
+ )
492
543
 
493
544
  return {
494
545
  submissionId: submission.id,
@@ -500,7 +551,7 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
500
551
  submittedAt: submission.submittedAt,
501
552
  thankYouMessage: form.thankYouMessage,
502
553
  }
503
- })
554
+ }, { workspaceId })
504
555
  },
505
556
  }
506
557
  }
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /**
6
+ * Domain events published by the handbook module.
7
+ *
8
+ * Handbook pages are content objects, not CRM records — the target type is
9
+ * `handbook_page`, and the webhooks bridge does not (yet) deliver these to
10
+ * subscribers. They still fire on the bus for in-process consumers.
11
+ */
12
+
13
+ export const handbookEvents = {
14
+ 'handbook.page.created': z.object({}).strict(),
15
+ 'handbook.page.updated': z.object({ changed: z.array(z.string()).readonly() }),
16
+ 'handbook.page.deleted': z.object({}).strict(),
17
+ } satisfies ModuleEventCatalog
18
+
19
+ export type HandbookPageCreatedData = Record<string, never>
20
+ export interface HandbookPageUpdatedData {
21
+ readonly changed: readonly string[]
22
+ }
23
+ export type HandbookPageDeletedData = Record<string, never>
24
+
25
+ declare module '../../runtime/events.ts' {
26
+ interface KelpieEventMap {
27
+ 'handbook.page.created': HandbookPageCreatedData
28
+ 'handbook.page.updated': HandbookPageUpdatedData
29
+ 'handbook.page.deleted': HandbookPageDeletedData
30
+ }
31
+ }
@@ -1,4 +1,5 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
+ import { handbookEvents } from './events.ts'
2
3
  import { mountHandbookRoutes } from './routes.ts'
3
4
  import * as schema from './schema.ts'
4
5
  import { createHandbookService } from './service.ts'
@@ -20,6 +21,7 @@ export function createHandbookModule(migrationsDirectory: string): KelpieModule
20
21
  return {
21
22
  id: 'handbook',
22
23
  requires: ['workspace'],
24
+ events: handbookEvents,
23
25
 
24
26
  register(context) {
25
27
  const service = createHandbookService({
@@ -6,8 +6,10 @@ import type { IdFactory } from '../../lib/ids.ts'
6
6
  import { mapPage, readListWindow, toPage } from '../../lib/pagination.ts'
7
7
  import type { ListQueryParameters, Page } from '../../lib/pagination.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 { actorMemberId, requireWorkspaceId } from '../auth/actor.ts'
12
+ import './events.ts'
11
13
  import * as repository from './repository.ts'
12
14
  import { DEFAULT_HANDBOOK_PAGE_SORT, HANDBOOK_PAGE_SORTS } from './repository.ts'
13
15
  import type { HandbookPageFilters, HandbookPageRecord } from './repository.ts'
@@ -292,11 +294,7 @@ export function createHandbookService(dependencies: HandbookDependencies): Handb
292
294
  updatedBy: actorMemberId(actor),
293
295
  })
294
296
 
295
- events.emit('record.created', {
296
- workspaceId,
297
- objectType: 'handbook_page',
298
- recordId: id,
299
- })
297
+ events.emit('handbook.page.created', { type: 'handbook_page', id }, {})
300
298
 
301
299
  return toView(created)
302
300
  } catch (error: unknown) {
@@ -308,7 +306,7 @@ export function createHandbookService(dependencies: HandbookDependencies): Handb
308
306
 
309
307
  throw error
310
308
  }
311
- })
309
+ }, { workspaceId, actor: toEventActor(actor) })
312
310
  },
313
311
 
314
312
  async update(actor, id, changes) {
@@ -346,16 +344,11 @@ export function createHandbookService(dependencies: HandbookDependencies): Handb
346
344
  const changed = [...written, ...movedFields]
347
345
 
348
346
  if (changed.length > 0) {
349
- events.emit('record.updated', {
350
- workspaceId,
351
- objectType: 'handbook_page',
352
- recordId: id,
353
- changedFields: changed,
354
- })
347
+ events.emit('handbook.page.updated', { type: 'handbook_page', id }, { changed })
355
348
  }
356
349
 
357
350
  return toView(updated)
358
- })
351
+ }, { workspaceId, actor: toEventActor(actor) })
359
352
  },
360
353
 
361
354
  /**
@@ -391,9 +384,9 @@ export function createHandbookService(dependencies: HandbookDependencies): Handb
391
384
  )
392
385
 
393
386
  for (const recordId of removed) {
394
- events.emit('record.deleted', { workspaceId, objectType: 'handbook_page', recordId })
387
+ events.emit('handbook.page.deleted', { type: 'handbook_page', id: recordId }, {})
395
388
  }
396
- })
389
+ }, { workspaceId, actor: toEventActor(actor) })
397
390
  },
398
391
  }
399
392
  }