@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,6 +3,7 @@ import {
3
3
  IMPORT_OBJECTS,
4
4
  IMPORT_SOURCES,
5
5
  MAX_IMPORT_FILE_BYTES,
6
+ ON_MISSING_COMPANY,
6
7
  defaultMatchKeyId,
7
8
  } from '@kelpie/schemas'
8
9
  import { z } from 'zod'
@@ -59,6 +60,13 @@ const previewArgs = z.strictObject({
59
60
  .enum(IMPORT_CONFLICT_MODES)
60
61
  .default('skip')
61
62
  .describe('What to do with a row that matches an existing record.'),
63
+ on_missing_company: z
64
+ .enum(ON_MISSING_COMPANY)
65
+ .default('skip')
66
+ .describe(
67
+ 'People import only: what to do when a row names a company that is not here yet. ' +
68
+ "'skip' imports the person and leaves the position unlinked; 'create' invents the company.",
69
+ ),
62
70
  match_key: z.string().min(1).optional().describe('Which field decides that match.'),
63
71
  column_map: columnMapArg.optional(),
64
72
  file_name: z.string().min(1).nullable().default(null).describe('Recorded on the job, for the log.'),
@@ -124,6 +132,7 @@ export function registerImportExportTools(mcp: McpToolRegistry, service: ImportE
124
132
  source: args.source,
125
133
  object: args.object,
126
134
  conflictMode: args.conflict_mode,
135
+ onMissingCompany: args.on_missing_company,
127
136
  matchKeyId: args.match_key ?? defaultMatchKeyId(args.object),
128
137
  columnMap: args.column_map,
129
138
  fileName: args.file_name,
@@ -11,7 +11,7 @@ import * as dealRepository from '../deals/repository.ts'
11
11
  import * as peopleRepository from '../people/repository.ts'
12
12
  import * as positionRepository from '../positions/repository.ts'
13
13
  import { IMPORT_DEAL_CURRENCY, NEW_COMPANY_DEFAULTS, NEW_PERSON_DEFAULTS } from './drafts.ts'
14
- import type { ImportWrite, RowPlan } from './plan.ts'
14
+ import type { ImportWrite, PlannedAffiliation, RowPlan } from './plan.ts'
15
15
 
16
16
  /**
17
17
  * Applying one planned row: the insert or update, and the timeline entry that
@@ -34,6 +34,21 @@ export interface WriteDependencies {
34
34
  readonly sourceName: string
35
35
  }
36
36
 
37
+ /**
38
+ * A record a row wrote besides its primary one.
39
+ *
40
+ * A People row with an affiliation makes a Position, and under
41
+ * `on_missing_company: create` a Company as well. Each needs its own module
42
+ * event, which the service emits from these.
43
+ */
44
+ export interface SideRecord {
45
+ readonly objectType: RecordObjectType
46
+ readonly recordId: string
47
+ readonly created: boolean
48
+ /** The columns an update moved. Empty on a create. */
49
+ readonly changedFields: readonly string[]
50
+ }
51
+
37
52
  export interface WriteOutcome {
38
53
  readonly recordId: string
39
54
  readonly objectType: RecordObjectType
@@ -43,6 +58,8 @@ export interface WriteOutcome {
43
58
  * nothing at all.
44
59
  */
45
60
  readonly changedFields: readonly string[]
61
+ /** Records the row wrote besides its primary one: a People affiliation's company and position. */
62
+ readonly sideRecords?: readonly SideRecord[]
46
63
  }
47
64
 
48
65
  /** A create or update plan. `skip` and `error` never reach here. */
@@ -102,6 +119,92 @@ async function writeCompany(
102
119
  return { recordId: id, objectType: 'company', changedFields }
103
120
  }
104
121
 
122
+ /**
123
+ * Writes the position a People row named, and the company it belongs to when the
124
+ * job was told to create one.
125
+ *
126
+ * The company is created before the position so the link has something to point
127
+ * at. The position is renamed in place when the person already holds one at that
128
+ * company, and created otherwise, which is the two-column-key behaviour the
129
+ * People affiliation chose. Files the `created Company` and `linked to company`
130
+ * activities as it goes, the same sentences the Companies and Positions imports
131
+ * write.
132
+ */
133
+ async function applyAffiliation(
134
+ dependencies: WriteDependencies,
135
+ personId: string,
136
+ affiliation: PlannedAffiliation,
137
+ ): Promise<readonly SideRecord[]> {
138
+ const { tx, workspaceId, actor, sourceName } = dependencies
139
+ const sideRecords: SideRecord[] = []
140
+
141
+ const companyId = await (async (): Promise<string> => {
142
+ if (affiliation.kind === 'link') {
143
+ return affiliation.companyId
144
+ }
145
+
146
+ const created = await companyRepository.insertCompany(tx, {
147
+ ...NEW_COMPANY_DEFAULTS,
148
+ ...affiliation.company,
149
+ tags: affiliation.company.tags === undefined ? undefined : [...affiliation.company.tags],
150
+ id: dependencies.createId('company'),
151
+ workspaceId,
152
+ name: affiliation.company.name ?? '',
153
+ })
154
+
155
+ sideRecords.push({ objectType: 'company', recordId: created.id, created: true, changedFields: [] })
156
+ await dependencies.recordActivity(tx, workspaceId, actor, {
157
+ targetType: 'company',
158
+ targetId: created.id,
159
+ kind: 'created',
160
+ ...describeCreationVia('Company', sourceName),
161
+ })
162
+
163
+ return created.id
164
+ })()
165
+
166
+ const held = await positionRepository.listPositionsAt(tx, workspaceId, personId, companyId)
167
+ const current = held[0]
168
+
169
+ if (current === undefined) {
170
+ const created = await positionRepository.insertPosition(tx, {
171
+ id: dependencies.createId('position'),
172
+ workspaceId,
173
+ personId,
174
+ companyId,
175
+ title: affiliation.title,
176
+ })
177
+
178
+ sideRecords.push({ objectType: 'position', recordId: created.id, created: true, changedFields: [] })
179
+
180
+ for (const end of [
181
+ { targetType: 'person', targetId: personId, related: 'company' },
182
+ { targetType: 'company', targetId: companyId, related: 'person' },
183
+ ] as const) {
184
+ await dependencies.recordActivity(tx, workspaceId, actor, {
185
+ targetType: end.targetType,
186
+ targetId: end.targetId,
187
+ kind: 'linked',
188
+ ...describeLink(end.related, sourceName),
189
+ })
190
+ }
191
+
192
+ return sideRecords
193
+ }
194
+
195
+ const changedFields = changedKeys(current, { title: affiliation.title })
196
+
197
+ if (changedFields.length > 0) {
198
+ await positionRepository.updatePosition(tx, workspaceId, current.id, {
199
+ title: affiliation.title,
200
+ updatedAt: dependencies.now,
201
+ })
202
+ sideRecords.push({ objectType: 'position', recordId: current.id, created: false, changedFields })
203
+ }
204
+
205
+ return sideRecords
206
+ }
207
+
105
208
  async function writePerson(
106
209
  dependencies: WriteDependencies,
107
210
  plan: WritablePlan,
@@ -120,7 +223,12 @@ async function writePerson(
120
223
  name: write.draft.name ?? '',
121
224
  })
122
225
 
123
- return { recordId: created.id, objectType: 'person', changedFields: [] }
226
+ const sideRecords =
227
+ write.affiliation === undefined
228
+ ? []
229
+ : await applyAffiliation(dependencies, created.id, write.affiliation)
230
+
231
+ return { recordId: created.id, objectType: 'person', changedFields: [], sideRecords }
124
232
  }
125
233
 
126
234
  const id = requireTarget(plan)
@@ -144,7 +252,12 @@ async function writePerson(
144
252
  })
145
253
  }
146
254
 
147
- return { recordId: id, objectType: 'person', changedFields }
255
+ const sideRecords =
256
+ write.affiliation === undefined
257
+ ? []
258
+ : await applyAffiliation(dependencies, id, write.affiliation)
259
+
260
+ return { recordId: id, objectType: 'person', changedFields, sideRecords }
148
261
  }
149
262
 
150
263
  /**
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /**
6
+ * Domain events published by the notes module.
7
+ *
8
+ * `target` is the record the note attaches to (a person, company, deal, ...).
9
+ * The note's own id lives in `data` so a consumer that watches records does
10
+ * not need a second lookup to know which record the note landed on.
11
+ */
12
+
13
+ export const notesEvents = {
14
+ 'notes.note.added': z.object({ noteId: z.string() }),
15
+ } satisfies ModuleEventCatalog
16
+
17
+ export interface NoteAddedData {
18
+ readonly noteId: string
19
+ }
20
+
21
+ declare module '../../runtime/events.ts' {
22
+ interface KelpieEventMap {
23
+ 'notes.note.added': NoteAddedData
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 { notesEvents } from './events.ts'
3
4
  import { mountNotesRoutes } from './routes.ts'
4
5
  import * as schema from './schema.ts'
5
6
  import { createNotesService } from './service.ts'
@@ -16,6 +17,7 @@ export function createNotesModule(migrationsDirectory: string): KelpieModule {
16
17
  id: 'notes',
17
18
  requires: ['workspace', 'activities'],
18
19
  structural: true,
20
+ events: notesEvents,
19
21
 
20
22
  register(context) {
21
23
  const service = createNotesService({
@@ -7,8 +7,10 @@ import type { ListQueryParameters, Page } from '../../lib/pagination.ts'
7
7
  import type { TransactionScope } from '../../runtime/transaction.ts'
8
8
  import { describeNote } from '../activities/wording.ts'
9
9
  import type { ActivityRecorder } from '../activities/recorder.ts'
10
+ import { toEventActor } from '../../lib/actor.ts'
10
11
  import type { Actor } from '../auth/actor.ts'
11
12
  import { actorMemberId, requireWorkspaceId } from '../auth/actor.ts'
13
+ import './events.ts'
12
14
  import { missingTargets } from '../recordTargets.ts'
13
15
  import type { RecordTargetType } from '../recordTargets.ts'
14
16
  import * as repository from './repository.ts'
@@ -145,15 +147,14 @@ export function createNotesService(dependencies: NotesDependencies): NotesServic
145
147
  // their own event, carrying the target, because a consumer watching a
146
148
  // record wants the note without a second lookup to find out what it is
147
149
  // attached to.
148
- events.emit('note.added', {
149
- workspaceId,
150
- noteId: created.id,
151
- targetType: created.targetType,
152
- targetId: created.targetId,
153
- })
150
+ events.emit(
151
+ 'notes.note.added',
152
+ { type: created.targetType, id: created.targetId },
153
+ { noteId: created.id },
154
+ )
154
155
 
155
156
  return toView(created)
156
- })
157
+ }, { workspaceId, actor: toEventActor(actor) })
157
158
  },
158
159
 
159
160
  async update(actor, id, changes) {
@@ -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 opportunities module. */
6
+
7
+ export const opportunitiesEvents = {
8
+ 'opportunities.opportunity.created': z.object({}).strict(),
9
+ 'opportunities.opportunity.updated': z.object({ changed: z.array(z.string()).readonly() }),
10
+ 'opportunities.opportunity.deleted': z.object({}).strict(),
11
+ 'opportunities.opportunity.stage_changed': z.object({
12
+ fromStageId: z.string().nullable(),
13
+ toStageId: z.string(),
14
+ }),
15
+ } satisfies ModuleEventCatalog
16
+
17
+ export type OpportunityCreatedData = Record<string, never>
18
+ export interface OpportunityUpdatedData {
19
+ readonly changed: readonly string[]
20
+ }
21
+ export type OpportunityDeletedData = Record<string, never>
22
+ export interface OpportunityStageChangedData {
23
+ readonly fromStageId: string | null
24
+ readonly toStageId: string
25
+ }
26
+
27
+ declare module '../../runtime/events.ts' {
28
+ interface KelpieEventMap {
29
+ 'opportunities.opportunity.created': OpportunityCreatedData
30
+ 'opportunities.opportunity.updated': OpportunityUpdatedData
31
+ 'opportunities.opportunity.deleted': OpportunityDeletedData
32
+ 'opportunities.opportunity.stage_changed': OpportunityStageChangedData
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 { opportunitiesEvents } from './events.ts'
3
4
  import { mountOpportunitiesRoutes } from './routes.ts'
4
5
  import * as schema from './schema.ts'
5
6
  import { createOpportunitiesService } from './service.ts'
@@ -17,6 +18,7 @@ export function createOpportunitiesModule(migrationsDirectory: string): KelpieMo
17
18
  return {
18
19
  id: 'opportunities',
19
20
  requires: ['companies', 'pipelines', 'activities'],
21
+ events: opportunitiesEvents,
20
22
 
21
23
  register(context) {
22
24
  const service = createOpportunitiesService({
@@ -8,8 +8,10 @@ import type { TransactionScope } from '../../runtime/transaction.ts'
8
8
  import type { ActivityRecorder } from '../activities/recorder.ts'
9
9
  import { describeCreation, describeStageChange, describeUpdate } from '../activities/wording.ts'
10
10
  import type { FieldLabels } from '../activities/wording.ts'
11
+ import { toEventActor } from '../../lib/actor.ts'
11
12
  import type { Actor } from '../auth/actor.ts'
12
13
  import { actorMemberId, requireWorkspaceId } from '../auth/actor.ts'
14
+ import './events.ts'
13
15
  import { deleteRecordsAttachedTo } from '../attachedRecords.ts'
14
16
  import * as companyRepository from '../companies/repository.ts'
15
17
  import * as pipelineRepository from '../pipelines/repository.ts'
@@ -236,10 +238,10 @@ export function createOpportunitiesService(
236
238
  ...describeCreation('Opportunity'),
237
239
  })
238
240
 
239
- events.emit('record.created', { workspaceId, objectType: 'opportunity', recordId: id })
241
+ events.emit('opportunities.opportunity.created', { type: 'opportunity', id }, {})
240
242
 
241
243
  return toView(created)
242
- })
244
+ }, { workspaceId, actor: toEventActor(actor) })
243
245
  },
244
246
 
245
247
  async update(actor, id, changes) {
@@ -302,25 +304,22 @@ export function createOpportunitiesService(
302
304
  })
303
305
  }
304
306
 
305
- events.emit('record.updated', {
306
- workspaceId,
307
- objectType: 'opportunity',
308
- recordId: id,
309
- changedFields: changed,
310
- })
307
+ events.emit(
308
+ 'opportunities.opportunity.updated',
309
+ { type: 'opportunity', id },
310
+ { changed },
311
+ )
311
312
 
312
313
  if (stageMove !== undefined) {
313
- events.emit('stage.changed', {
314
- workspaceId,
315
- objectType: 'opportunity',
316
- recordId: id,
317
- fromStageId: stageMove.from.id,
318
- toStageId: stageMove.to.id,
319
- })
314
+ events.emit(
315
+ 'opportunities.opportunity.stage_changed',
316
+ { type: 'opportunity', id },
317
+ { fromStageId: stageMove.from.id, toStageId: stageMove.to.id },
318
+ )
320
319
  }
321
320
 
322
321
  return toView(updated)
323
- })
322
+ }, { workspaceId, actor: toEventActor(actor) })
324
323
  },
325
324
 
326
325
  async remove(actor, id) {
@@ -335,8 +334,8 @@ export function createOpportunitiesService(
335
334
  await deleteRecordsAttachedTo(tx, workspaceId, 'opportunity', id)
336
335
  await repository.deleteOpportunity(tx, workspaceId, id)
337
336
 
338
- events.emit('record.deleted', { workspaceId, objectType: 'opportunity', recordId: id })
339
- })
337
+ events.emit('opportunities.opportunity.deleted', { type: 'opportunity', id }, {})
338
+ }, { workspaceId, actor: toEventActor(actor) })
340
339
  },
341
340
  }
342
341
  }
@@ -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 partnerships module. */
6
+
7
+ export const partnershipsEvents = {
8
+ 'partnerships.partnership.created': z.object({}).strict(),
9
+ 'partnerships.partnership.updated': z.object({ changed: z.array(z.string()).readonly() }),
10
+ 'partnerships.partnership.deleted': z.object({}).strict(),
11
+ 'partnerships.partnership.stage_changed': z.object({
12
+ fromStageId: z.string().nullable(),
13
+ toStageId: z.string(),
14
+ }),
15
+ } satisfies ModuleEventCatalog
16
+
17
+ export type PartnershipCreatedData = Record<string, never>
18
+ export interface PartnershipUpdatedData {
19
+ readonly changed: readonly string[]
20
+ }
21
+ export type PartnershipDeletedData = Record<string, never>
22
+ export interface PartnershipStageChangedData {
23
+ readonly fromStageId: string | null
24
+ readonly toStageId: string
25
+ }
26
+
27
+ declare module '../../runtime/events.ts' {
28
+ interface KelpieEventMap {
29
+ 'partnerships.partnership.created': PartnershipCreatedData
30
+ 'partnerships.partnership.updated': PartnershipUpdatedData
31
+ 'partnerships.partnership.deleted': PartnershipDeletedData
32
+ 'partnerships.partnership.stage_changed': PartnershipStageChangedData
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 { partnershipsEvents } from './events.ts'
3
4
  import { mountPartnershipsRoutes } from './routes.ts'
4
5
  import * as schema from './schema.ts'
5
6
  import { createPartnershipsService } from './service.ts'
@@ -17,6 +18,7 @@ export function createPartnershipsModule(migrationsDirectory: string): KelpieMod
17
18
  return {
18
19
  id: 'partnerships',
19
20
  requires: ['companies', 'people', 'pipelines', 'activities'],
21
+ events: partnershipsEvents,
20
22
 
21
23
  register(context) {
22
24
  const service = createPartnershipsService({
@@ -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'
@@ -301,10 +303,10 @@ export function createPartnershipsService(
301
303
  })
302
304
  }
303
305
 
304
- events.emit('record.created', { workspaceId, objectType: 'partnership', recordId: id })
306
+ events.emit('partnerships.partnership.created', { type: 'partnership', id }, {})
305
307
 
306
308
  return toView(created, personIds)
307
- })
309
+ }, { workspaceId, actor: toEventActor(actor) })
308
310
  },
309
311
 
310
312
  async update(actor, id, changes) {
@@ -402,25 +404,22 @@ export function createPartnershipsService(
402
404
  })
403
405
  }
404
406
 
405
- events.emit('record.updated', {
406
- workspaceId,
407
- objectType: 'partnership',
408
- recordId: id,
409
- changedFields: linksChanged ? [...changed, 'personIds'] : changed,
410
- })
407
+ events.emit(
408
+ 'partnerships.partnership.updated',
409
+ { type: 'partnership', id },
410
+ { changed: linksChanged ? [...changed, 'personIds'] : changed },
411
+ )
411
412
 
412
413
  if (stageMove !== undefined) {
413
- events.emit('stage.changed', {
414
- workspaceId,
415
- objectType: 'partnership',
416
- recordId: id,
417
- fromStageId: stageMove.from.id,
418
- toStageId: stageMove.to.id,
419
- })
414
+ events.emit(
415
+ 'partnerships.partnership.stage_changed',
416
+ { type: 'partnership', id },
417
+ { fromStageId: stageMove.from.id, toStageId: stageMove.to.id },
418
+ )
420
419
  }
421
420
 
422
421
  return toView(updated, nextPeople ?? currentPeople)
423
- })
422
+ }, { workspaceId, actor: toEventActor(actor) })
424
423
  },
425
424
 
426
425
  async remove(actor, id) {
@@ -435,8 +434,8 @@ export function createPartnershipsService(
435
434
  await deleteRecordsAttachedTo(tx, workspaceId, 'partnership', id)
436
435
  await repository.deletePartnership(tx, workspaceId, id)
437
436
 
438
- events.emit('record.deleted', { workspaceId, objectType: 'partnership', recordId: id })
439
- })
437
+ events.emit('partnerships.partnership.deleted', { type: 'partnership', id }, {})
438
+ }, { workspaceId, actor: toEventActor(actor) })
440
439
  },
441
440
  }
442
441
  }
@@ -0,0 +1,36 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /**
6
+ * Domain events published by the people module.
7
+ *
8
+ * The runtime catalog (below) is the authority; the `KelpieEventMap`
9
+ * augmentation gives autocomplete at every emit and subscribe site.
10
+ */
11
+
12
+ export const PEOPLE_EVENT_NAMES = [
13
+ 'people.person.created',
14
+ 'people.person.updated',
15
+ 'people.person.deleted',
16
+ ] as const
17
+
18
+ export const peopleEvents = {
19
+ 'people.person.created': z.object({}).strict(),
20
+ 'people.person.updated': z.object({ changed: z.array(z.string()).readonly() }),
21
+ 'people.person.deleted': z.object({}).strict(),
22
+ } satisfies ModuleEventCatalog
23
+
24
+ export type PersonCreatedData = Record<string, never>
25
+ export interface PersonUpdatedData {
26
+ readonly changed: readonly string[]
27
+ }
28
+ export type PersonDeletedData = Record<string, never>
29
+
30
+ declare module '../../runtime/events.ts' {
31
+ interface KelpieEventMap {
32
+ 'people.person.created': PersonCreatedData
33
+ 'people.person.updated': PersonUpdatedData
34
+ 'people.person.deleted': PersonDeletedData
35
+ }
36
+ }
@@ -1,5 +1,6 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
2
  import { createActivityRecorder } from '../activities/index.ts'
3
+ import { peopleEvents } from './events.ts'
3
4
  import { mountPeopleRoutes } from './routes.ts'
4
5
  import * as schema from './schema.ts'
5
6
  import { createPeopleService } from './service.ts'
@@ -16,6 +17,7 @@ export function createPeopleModule(migrationsDirectory: string): KelpieModule {
16
17
  id: 'people',
17
18
  requires: ['workspace', 'activities'],
18
19
  structural: true,
20
+ events: peopleEvents,
19
21
 
20
22
  register(context) {
21
23
  const service = createPeopleService({