@kelpie/server 0.9.0 → 0.11.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 (449) hide show
  1. package/dist/app.d.ts.map +1 -1
  2. package/dist/app.js +2 -0
  3. package/dist/app.js.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/actor.d.ts +3 -1
  9. package/dist/lib/actor.d.ts.map +1 -1
  10. package/dist/lib/actor.js.map +1 -1
  11. package/dist/lib/apiKeyScopes.d.ts +8 -0
  12. package/dist/lib/apiKeyScopes.d.ts.map +1 -0
  13. package/dist/lib/apiKeyScopes.js +166 -0
  14. package/dist/lib/apiKeyScopes.js.map +1 -0
  15. package/dist/modules/activities/repository.d.ts +2 -0
  16. package/dist/modules/activities/repository.d.ts.map +1 -1
  17. package/dist/modules/activities/repository.js +9 -0
  18. package/dist/modules/activities/repository.js.map +1 -1
  19. package/dist/modules/agent-tasks/repository.d.ts +2 -0
  20. package/dist/modules/agent-tasks/repository.d.ts.map +1 -1
  21. package/dist/modules/agent-tasks/repository.js +9 -0
  22. package/dist/modules/agent-tasks/repository.js.map +1 -1
  23. package/dist/modules/api-keys/routes.d.ts.map +1 -1
  24. package/dist/modules/api-keys/routes.js +4 -1
  25. package/dist/modules/api-keys/routes.js.map +1 -1
  26. package/dist/modules/api-keys/schema.d.ts +43 -0
  27. package/dist/modules/api-keys/schema.d.ts.map +1 -1
  28. package/dist/modules/api-keys/schema.js +2 -0
  29. package/dist/modules/api-keys/schema.js.map +1 -1
  30. package/dist/modules/api-keys/scopeMiddleware.d.ts +8 -0
  31. package/dist/modules/api-keys/scopeMiddleware.d.ts.map +1 -0
  32. package/dist/modules/api-keys/scopeMiddleware.js +21 -0
  33. package/dist/modules/api-keys/scopeMiddleware.js.map +1 -0
  34. package/dist/modules/api-keys/service.d.ts +3 -1
  35. package/dist/modules/api-keys/service.d.ts.map +1 -1
  36. package/dist/modules/api-keys/service.js +26 -1
  37. package/dist/modules/api-keys/service.js.map +1 -1
  38. package/dist/modules/auth/credentials.d.ts.map +1 -1
  39. package/dist/modules/auth/credentials.js +2 -0
  40. package/dist/modules/auth/credentials.js.map +1 -1
  41. package/dist/modules/consent-purposes/index.d.ts +1 -1
  42. package/dist/modules/consent-purposes/index.js +1 -1
  43. package/dist/modules/consent-purposes/schema.d.ts +3 -3
  44. package/dist/modules/consent-purposes/schema.js +3 -3
  45. package/dist/modules/consent-purposes/service.d.ts +1 -1
  46. package/dist/modules/consent-purposes/service.d.ts.map +1 -1
  47. package/dist/modules/consent-purposes/service.js +7 -16
  48. package/dist/modules/consent-purposes/service.js.map +1 -1
  49. package/dist/modules/consent-purposes/starters.d.ts +1 -1
  50. package/dist/modules/consent-purposes/tools.js +1 -1
  51. package/dist/modules/consent-purposes/tools.js.map +1 -1
  52. package/dist/modules/conversions/clearPointers.d.ts +10 -0
  53. package/dist/modules/conversions/clearPointers.d.ts.map +1 -0
  54. package/dist/modules/conversions/clearPointers.js +40 -0
  55. package/dist/modules/conversions/clearPointers.js.map +1 -0
  56. package/dist/modules/conversions/factory.d.ts +5 -0
  57. package/dist/modules/conversions/factory.d.ts.map +1 -0
  58. package/dist/modules/conversions/factory.js +18 -0
  59. package/dist/modules/conversions/factory.js.map +1 -0
  60. package/dist/modules/conversions/fieldMap.d.ts +55 -0
  61. package/dist/modules/conversions/fieldMap.d.ts.map +1 -0
  62. package/dist/modules/conversions/fieldMap.js +398 -0
  63. package/dist/modules/conversions/fieldMap.js.map +1 -0
  64. package/dist/modules/conversions/index.d.ts +7 -0
  65. package/dist/modules/conversions/index.d.ts.map +1 -0
  66. package/dist/modules/conversions/index.js +6 -0
  67. package/dist/modules/conversions/index.js.map +1 -0
  68. package/dist/modules/conversions/mcp.d.ts +7 -0
  69. package/dist/modules/conversions/mcp.d.ts.map +1 -0
  70. package/dist/modules/conversions/mcp.js +47 -0
  71. package/dist/modules/conversions/mcp.js.map +1 -0
  72. package/dist/modules/conversions/repoint.d.ts +19 -0
  73. package/dist/modules/conversions/repoint.d.ts.map +1 -0
  74. package/dist/modules/conversions/repoint.js +51 -0
  75. package/dist/modules/conversions/repoint.js.map +1 -0
  76. package/dist/modules/conversions/routes.d.ts +26 -0
  77. package/dist/modules/conversions/routes.d.ts.map +1 -0
  78. package/dist/modules/conversions/routes.js +23 -0
  79. package/dist/modules/conversions/routes.js.map +1 -0
  80. package/dist/modules/conversions/service.d.ts +28 -0
  81. package/dist/modules/conversions/service.d.ts.map +1 -0
  82. package/dist/modules/conversions/service.js +170 -0
  83. package/dist/modules/conversions/service.js.map +1 -0
  84. package/dist/modules/conversions/wire.d.ts +4 -0
  85. package/dist/modules/conversions/wire.d.ts.map +1 -0
  86. package/dist/modules/conversions/wire.js +28 -0
  87. package/dist/modules/conversions/wire.js.map +1 -0
  88. package/dist/modules/deals/events.d.ts +9 -0
  89. package/dist/modules/deals/events.d.ts.map +1 -1
  90. package/dist/modules/deals/events.js +4 -0
  91. package/dist/modules/deals/events.js.map +1 -1
  92. package/dist/modules/deals/index.d.ts.map +1 -1
  93. package/dist/modules/deals/index.js +4 -2
  94. package/dist/modules/deals/index.js.map +1 -1
  95. package/dist/modules/deals/routes.d.ts +2 -0
  96. package/dist/modules/deals/routes.d.ts.map +1 -1
  97. package/dist/modules/deals/routes.js +8 -1
  98. package/dist/modules/deals/routes.js.map +1 -1
  99. package/dist/modules/deals/schema.d.ts +34 -0
  100. package/dist/modules/deals/schema.d.ts.map +1 -1
  101. package/dist/modules/deals/schema.js +7 -2
  102. package/dist/modules/deals/schema.js.map +1 -1
  103. package/dist/modules/deals/service.d.ts.map +1 -1
  104. package/dist/modules/deals/service.js +2 -0
  105. package/dist/modules/deals/service.js.map +1 -1
  106. package/dist/modules/deals/tools.d.ts +2 -1
  107. package/dist/modules/deals/tools.d.ts.map +1 -1
  108. package/dist/modules/deals/tools.js +3 -1
  109. package/dist/modules/deals/tools.js.map +1 -1
  110. package/dist/modules/decisions/repository.d.ts +2 -1
  111. package/dist/modules/decisions/repository.d.ts.map +1 -1
  112. package/dist/modules/decisions/repository.js +9 -1
  113. package/dist/modules/decisions/repository.js.map +1 -1
  114. package/dist/modules/enquiries/events.d.ts +6 -2
  115. package/dist/modules/enquiries/events.d.ts.map +1 -1
  116. package/dist/modules/enquiries/events.js +5 -1
  117. package/dist/modules/enquiries/events.js.map +1 -1
  118. package/dist/modules/enquiries/index.d.ts.map +1 -1
  119. package/dist/modules/enquiries/index.js +4 -2
  120. package/dist/modules/enquiries/index.js.map +1 -1
  121. package/dist/modules/enquiries/routes.d.ts +2 -0
  122. package/dist/modules/enquiries/routes.d.ts.map +1 -1
  123. package/dist/modules/enquiries/routes.js +9 -9
  124. package/dist/modules/enquiries/routes.js.map +1 -1
  125. package/dist/modules/enquiries/schema.d.ts +36 -1
  126. package/dist/modules/enquiries/schema.d.ts.map +1 -1
  127. package/dist/modules/enquiries/schema.js +9 -3
  128. package/dist/modules/enquiries/schema.js.map +1 -1
  129. package/dist/modules/enquiries/service.d.ts +0 -8
  130. package/dist/modules/enquiries/service.d.ts.map +1 -1
  131. package/dist/modules/enquiries/service.js +3 -95
  132. package/dist/modules/enquiries/service.js.map +1 -1
  133. package/dist/modules/enquiries/tools.d.ts +2 -1
  134. package/dist/modules/enquiries/tools.d.ts.map +1 -1
  135. package/dist/modules/enquiries/tools.js +4 -16
  136. package/dist/modules/enquiries/tools.js.map +1 -1
  137. package/dist/modules/forms/applyMappedFields.d.ts +20 -0
  138. package/dist/modules/forms/applyMappedFields.d.ts.map +1 -0
  139. package/dist/modules/forms/applyMappedFields.js +169 -0
  140. package/dist/modules/forms/applyMappedFields.js.map +1 -0
  141. package/dist/modules/forms/applySubmissionFields.d.ts +18 -0
  142. package/dist/modules/forms/applySubmissionFields.d.ts.map +1 -0
  143. package/dist/modules/forms/applySubmissionFields.js +230 -0
  144. package/dist/modules/forms/applySubmissionFields.js.map +1 -0
  145. package/dist/modules/forms/fields.d.ts +7 -2
  146. package/dist/modules/forms/fields.d.ts.map +1 -1
  147. package/dist/modules/forms/fields.js +17 -6
  148. package/dist/modules/forms/fields.js.map +1 -1
  149. package/dist/modules/forms/mapping.d.ts +8 -2
  150. package/dist/modules/forms/mapping.d.ts.map +1 -1
  151. package/dist/modules/forms/mapping.js +11 -0
  152. package/dist/modules/forms/mapping.js.map +1 -1
  153. package/dist/modules/forms/repository.d.ts +0 -5
  154. package/dist/modules/forms/repository.d.ts.map +1 -1
  155. package/dist/modules/forms/repository.js +0 -2
  156. package/dist/modules/forms/repository.js.map +1 -1
  157. package/dist/modules/forms/routes.d.ts +2 -30
  158. package/dist/modules/forms/routes.d.ts.map +1 -1
  159. package/dist/modules/forms/routes.js +2 -2
  160. package/dist/modules/forms/routes.js.map +1 -1
  161. package/dist/modules/forms/schema.d.ts.map +1 -1
  162. package/dist/modules/forms/schema.js +1 -2
  163. package/dist/modules/forms/schema.js.map +1 -1
  164. package/dist/modules/forms/service.d.ts.map +1 -1
  165. package/dist/modules/forms/service.js +18 -3
  166. package/dist/modules/forms/service.js.map +1 -1
  167. package/dist/modules/forms/starters.d.ts +31 -0
  168. package/dist/modules/forms/starters.d.ts.map +1 -0
  169. package/dist/modules/forms/starters.js +94 -0
  170. package/dist/modules/forms/starters.js.map +1 -0
  171. package/dist/modules/forms/submission.d.ts +1 -0
  172. package/dist/modules/forms/submission.d.ts.map +1 -1
  173. package/dist/modules/forms/submission.js +58 -37
  174. package/dist/modules/forms/submission.js.map +1 -1
  175. package/dist/modules/import-export/customFieldCsv.d.ts +9 -0
  176. package/dist/modules/import-export/customFieldCsv.d.ts.map +1 -0
  177. package/dist/modules/import-export/customFieldCsv.js +39 -0
  178. package/dist/modules/import-export/customFieldCsv.js.map +1 -0
  179. package/dist/modules/import-export/customFieldImport.d.ts +19 -0
  180. package/dist/modules/import-export/customFieldImport.d.ts.map +1 -0
  181. package/dist/modules/import-export/customFieldImport.js +76 -0
  182. package/dist/modules/import-export/customFieldImport.js.map +1 -0
  183. package/dist/modules/import-export/drafts.d.ts +57 -3
  184. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  185. package/dist/modules/import-export/drafts.js +65 -3
  186. package/dist/modules/import-export/drafts.js.map +1 -1
  187. package/dist/modules/import-export/exportRows.d.ts +15 -13
  188. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  189. package/dist/modules/import-export/exportRows.js +99 -26
  190. package/dist/modules/import-export/exportRows.js.map +1 -1
  191. package/dist/modules/import-export/plan.d.ts +42 -11
  192. package/dist/modules/import-export/plan.d.ts.map +1 -1
  193. package/dist/modules/import-export/plan.js +198 -56
  194. package/dist/modules/import-export/plan.js.map +1 -1
  195. package/dist/modules/import-export/repository.d.ts +58 -2
  196. package/dist/modules/import-export/repository.d.ts.map +1 -1
  197. package/dist/modules/import-export/repository.js +201 -12
  198. package/dist/modules/import-export/repository.js.map +1 -1
  199. package/dist/modules/import-export/routes.d.ts.map +1 -1
  200. package/dist/modules/import-export/routes.js +5 -5
  201. package/dist/modules/import-export/routes.js.map +1 -1
  202. package/dist/modules/import-export/service.d.ts +8 -3
  203. package/dist/modules/import-export/service.d.ts.map +1 -1
  204. package/dist/modules/import-export/service.js +133 -40
  205. package/dist/modules/import-export/service.js.map +1 -1
  206. package/dist/modules/import-export/streams.d.ts +2 -2
  207. package/dist/modules/import-export/streams.d.ts.map +1 -1
  208. package/dist/modules/import-export/streams.js +50 -9
  209. package/dist/modules/import-export/streams.js.map +1 -1
  210. package/dist/modules/import-export/tools.d.ts.map +1 -1
  211. package/dist/modules/import-export/tools.js +13 -7
  212. package/dist/modules/import-export/tools.js.map +1 -1
  213. package/dist/modules/import-export/validation.d.ts +5 -1
  214. package/dist/modules/import-export/validation.d.ts.map +1 -1
  215. package/dist/modules/import-export/validation.js +89 -2
  216. package/dist/modules/import-export/validation.js.map +1 -1
  217. package/dist/modules/import-export/writes.d.ts +2 -1
  218. package/dist/modules/import-export/writes.d.ts.map +1 -1
  219. package/dist/modules/import-export/writes.js +358 -25
  220. package/dist/modules/import-export/writes.js.map +1 -1
  221. package/dist/modules/lists/index.d.ts +38 -0
  222. package/dist/modules/lists/index.d.ts.map +1 -1
  223. package/dist/modules/lists/index.js +27 -0
  224. package/dist/modules/lists/index.js.map +1 -1
  225. package/dist/modules/lists/repository.d.ts +15 -1
  226. package/dist/modules/lists/repository.d.ts.map +1 -1
  227. package/dist/modules/lists/repository.js +19 -1
  228. package/dist/modules/lists/repository.js.map +1 -1
  229. package/dist/modules/lists/routes.d.ts +0 -2
  230. package/dist/modules/lists/routes.d.ts.map +1 -1
  231. package/dist/modules/lists/routes.js +0 -8
  232. package/dist/modules/lists/routes.js.map +1 -1
  233. package/dist/modules/lists/schema.d.ts +0 -17
  234. package/dist/modules/lists/schema.d.ts.map +1 -1
  235. package/dist/modules/lists/schema.js +0 -10
  236. package/dist/modules/lists/schema.js.map +1 -1
  237. package/dist/modules/lists/service.d.ts +2 -14
  238. package/dist/modules/lists/service.d.ts.map +1 -1
  239. package/dist/modules/lists/service.js +7 -53
  240. package/dist/modules/lists/service.js.map +1 -1
  241. package/dist/modules/lists/starters.d.ts +12 -0
  242. package/dist/modules/lists/starters.d.ts.map +1 -0
  243. package/dist/modules/lists/starters.js +4 -0
  244. package/dist/modules/lists/starters.js.map +1 -0
  245. package/dist/modules/mcp/protocol.d.ts.map +1 -1
  246. package/dist/modules/mcp/protocol.js +13 -0
  247. package/dist/modules/mcp/protocol.js.map +1 -1
  248. package/dist/modules/notes/repository.d.ts +2 -0
  249. package/dist/modules/notes/repository.d.ts.map +1 -1
  250. package/dist/modules/notes/repository.js +9 -0
  251. package/dist/modules/notes/repository.js.map +1 -1
  252. package/dist/modules/opportunities/events.d.ts +9 -0
  253. package/dist/modules/opportunities/events.d.ts.map +1 -1
  254. package/dist/modules/opportunities/events.js +4 -0
  255. package/dist/modules/opportunities/events.js.map +1 -1
  256. package/dist/modules/opportunities/index.d.ts.map +1 -1
  257. package/dist/modules/opportunities/index.js +4 -2
  258. package/dist/modules/opportunities/index.js.map +1 -1
  259. package/dist/modules/opportunities/routes.d.ts +2 -0
  260. package/dist/modules/opportunities/routes.d.ts.map +1 -1
  261. package/dist/modules/opportunities/routes.js +8 -1
  262. package/dist/modules/opportunities/routes.js.map +1 -1
  263. package/dist/modules/opportunities/schema.d.ts +34 -0
  264. package/dist/modules/opportunities/schema.d.ts.map +1 -1
  265. package/dist/modules/opportunities/schema.js +7 -2
  266. package/dist/modules/opportunities/schema.js.map +1 -1
  267. package/dist/modules/opportunities/service.d.ts.map +1 -1
  268. package/dist/modules/opportunities/service.js +2 -0
  269. package/dist/modules/opportunities/service.js.map +1 -1
  270. package/dist/modules/opportunities/tools.d.ts +2 -1
  271. package/dist/modules/opportunities/tools.d.ts.map +1 -1
  272. package/dist/modules/opportunities/tools.js +3 -1
  273. package/dist/modules/opportunities/tools.js.map +1 -1
  274. package/dist/modules/partnerships/events.d.ts +9 -0
  275. package/dist/modules/partnerships/events.d.ts.map +1 -1
  276. package/dist/modules/partnerships/events.js +4 -0
  277. package/dist/modules/partnerships/events.js.map +1 -1
  278. package/dist/modules/partnerships/index.d.ts.map +1 -1
  279. package/dist/modules/partnerships/index.js +4 -2
  280. package/dist/modules/partnerships/index.js.map +1 -1
  281. package/dist/modules/partnerships/routes.d.ts +2 -0
  282. package/dist/modules/partnerships/routes.d.ts.map +1 -1
  283. package/dist/modules/partnerships/routes.js +8 -1
  284. package/dist/modules/partnerships/routes.js.map +1 -1
  285. package/dist/modules/partnerships/schema.d.ts +34 -0
  286. package/dist/modules/partnerships/schema.d.ts.map +1 -1
  287. package/dist/modules/partnerships/schema.js +7 -2
  288. package/dist/modules/partnerships/schema.js.map +1 -1
  289. package/dist/modules/partnerships/service.d.ts.map +1 -1
  290. package/dist/modules/partnerships/service.js +2 -0
  291. package/dist/modules/partnerships/service.js.map +1 -1
  292. package/dist/modules/partnerships/tools.d.ts +2 -1
  293. package/dist/modules/partnerships/tools.d.ts.map +1 -1
  294. package/dist/modules/partnerships/tools.js +3 -1
  295. package/dist/modules/partnerships/tools.js.map +1 -1
  296. package/dist/modules/people/personConsentWrites.d.ts +1 -1
  297. package/dist/modules/people/schema.js +1 -1
  298. package/dist/modules/people/schema.js.map +1 -1
  299. package/dist/modules/plans/repository.d.ts +2 -0
  300. package/dist/modules/plans/repository.d.ts.map +1 -1
  301. package/dist/modules/plans/repository.js +9 -0
  302. package/dist/modules/plans/repository.js.map +1 -1
  303. package/dist/modules/raises/events.d.ts +9 -0
  304. package/dist/modules/raises/events.d.ts.map +1 -1
  305. package/dist/modules/raises/events.js +4 -0
  306. package/dist/modules/raises/events.js.map +1 -1
  307. package/dist/modules/raises/index.d.ts.map +1 -1
  308. package/dist/modules/raises/index.js +4 -2
  309. package/dist/modules/raises/index.js.map +1 -1
  310. package/dist/modules/raises/routes.d.ts +2 -0
  311. package/dist/modules/raises/routes.d.ts.map +1 -1
  312. package/dist/modules/raises/routes.js +8 -1
  313. package/dist/modules/raises/routes.js.map +1 -1
  314. package/dist/modules/raises/schema.d.ts +34 -0
  315. package/dist/modules/raises/schema.d.ts.map +1 -1
  316. package/dist/modules/raises/schema.js +7 -2
  317. package/dist/modules/raises/schema.js.map +1 -1
  318. package/dist/modules/raises/service.d.ts.map +1 -1
  319. package/dist/modules/raises/service.js +2 -0
  320. package/dist/modules/raises/service.js.map +1 -1
  321. package/dist/modules/raises/tools.d.ts +2 -1
  322. package/dist/modules/raises/tools.d.ts.map +1 -1
  323. package/dist/modules/raises/tools.js +3 -1
  324. package/dist/modules/raises/tools.js.map +1 -1
  325. package/dist/modules/workspace/routes.d.ts +0 -2
  326. package/dist/modules/workspace/routes.d.ts.map +1 -1
  327. package/dist/modules/workspace/routes.js +0 -6
  328. package/dist/modules/workspace/routes.js.map +1 -1
  329. package/dist/modules/workspace/schema.d.ts +0 -34
  330. package/dist/modules/workspace/schema.d.ts.map +1 -1
  331. package/dist/modules/workspace/schema.js +0 -2
  332. package/dist/modules/workspace/schema.js.map +1 -1
  333. package/dist/modules/workspace/seedStarterForms.d.ts +17 -0
  334. package/dist/modules/workspace/seedStarterForms.d.ts.map +1 -0
  335. package/dist/modules/workspace/seedStarterForms.js +71 -0
  336. package/dist/modules/workspace/seedStarterForms.js.map +1 -0
  337. package/dist/modules/workspace/service.d.ts +0 -4
  338. package/dist/modules/workspace/service.d.ts.map +1 -1
  339. package/dist/modules/workspace/service.js +20 -10
  340. package/dist/modules/workspace/service.js.map +1 -1
  341. package/dist/modules/workspace/tools.js +1 -1
  342. package/dist/modules/workspace/tools.js.map +1 -1
  343. package/dist/testing/fixtures.d.ts.map +1 -1
  344. package/dist/testing/fixtures.js +1 -0
  345. package/dist/testing/fixtures.js.map +1 -1
  346. package/migrations/0037_drop_lists_consent_purpose_id.sql +2 -0
  347. package/migrations/0038_smart_white_queen.sql +2 -0
  348. package/migrations/0039_form_map_to_open.sql +1 -0
  349. package/migrations/0040_pipeline_converted_to.sql +20 -0
  350. package/migrations/0041_api_key_scopes.sql +1 -0
  351. package/migrations/0042_drop_workspace_identity.sql +2 -0
  352. package/migrations/meta/0038_snapshot.json +6554 -0
  353. package/migrations/meta/_journal.json +42 -0
  354. package/package.json +2 -2
  355. package/src/app.ts +3 -0
  356. package/src/index.ts +6 -0
  357. package/src/lib/actor.ts +3 -1
  358. package/src/lib/apiKeyScopes.ts +213 -0
  359. package/src/modules/activities/repository.ts +24 -0
  360. package/src/modules/agent-tasks/repository.ts +24 -0
  361. package/src/modules/api-keys/routes.ts +5 -0
  362. package/src/modules/api-keys/schema.ts +2 -0
  363. package/src/modules/api-keys/scopeMiddleware.ts +30 -0
  364. package/src/modules/api-keys/service.ts +36 -2
  365. package/src/modules/auth/credentials.ts +4 -0
  366. package/src/modules/consent-purposes/index.ts +1 -1
  367. package/src/modules/consent-purposes/schema.ts +3 -3
  368. package/src/modules/consent-purposes/service.ts +7 -16
  369. package/src/modules/consent-purposes/starters.ts +1 -1
  370. package/src/modules/consent-purposes/tools.ts +1 -1
  371. package/src/modules/conversions/clearPointers.ts +81 -0
  372. package/src/modules/conversions/factory.ts +20 -0
  373. package/src/modules/conversions/fieldMap.ts +548 -0
  374. package/src/modules/conversions/index.ts +6 -0
  375. package/src/modules/conversions/mcp.ts +71 -0
  376. package/src/modules/conversions/repoint.ts +146 -0
  377. package/src/modules/conversions/routes.ts +68 -0
  378. package/src/modules/conversions/service.ts +310 -0
  379. package/src/modules/conversions/wire.ts +42 -0
  380. package/src/modules/deals/events.ts +9 -0
  381. package/src/modules/deals/index.ts +4 -2
  382. package/src/modules/deals/routes.ts +11 -1
  383. package/src/modules/deals/schema.ts +10 -2
  384. package/src/modules/deals/service.ts +3 -0
  385. package/src/modules/deals/tools.ts +9 -1
  386. package/src/modules/decisions/repository.ts +23 -1
  387. package/src/modules/enquiries/events.ts +8 -2
  388. package/src/modules/enquiries/index.ts +4 -2
  389. package/src/modules/enquiries/routes.ts +11 -13
  390. package/src/modules/enquiries/schema.ts +12 -3
  391. package/src/modules/enquiries/service.ts +3 -150
  392. package/src/modules/enquiries/tools.ts +9 -18
  393. package/src/modules/forms/applyMappedFields.ts +248 -0
  394. package/src/modules/forms/applySubmissionFields.ts +435 -0
  395. package/src/modules/forms/fields.ts +31 -7
  396. package/src/modules/forms/mapping.ts +20 -3
  397. package/src/modules/forms/repository.ts +0 -7
  398. package/src/modules/forms/routes.ts +1 -2
  399. package/src/modules/forms/schema.ts +0 -2
  400. package/src/modules/forms/service.ts +31 -4
  401. package/src/modules/forms/starters.ts +129 -0
  402. package/src/modules/forms/submission.ts +135 -69
  403. package/src/modules/import-export/customFieldCsv.ts +55 -0
  404. package/src/modules/import-export/customFieldImport.ts +111 -0
  405. package/src/modules/import-export/drafts.ts +151 -3
  406. package/src/modules/import-export/exportRows.ts +222 -68
  407. package/src/modules/import-export/plan.ts +321 -67
  408. package/src/modules/import-export/repository.ts +356 -14
  409. package/src/modules/import-export/routes.ts +8 -8
  410. package/src/modules/import-export/service.ts +208 -45
  411. package/src/modules/import-export/streams.ts +95 -13
  412. package/src/modules/import-export/tools.ts +14 -6
  413. package/src/modules/import-export/validation.ts +128 -0
  414. package/src/modules/import-export/writes.ts +559 -27
  415. package/src/modules/lists/index.ts +71 -0
  416. package/src/modules/lists/repository.ts +34 -2
  417. package/src/modules/lists/routes.ts +0 -8
  418. package/src/modules/lists/schema.ts +0 -10
  419. package/src/modules/lists/service.ts +9 -107
  420. package/src/modules/lists/starters.ts +16 -0
  421. package/src/modules/mcp/protocol.ts +18 -0
  422. package/src/modules/notes/repository.ts +24 -0
  423. package/src/modules/opportunities/events.ts +9 -0
  424. package/src/modules/opportunities/index.ts +4 -2
  425. package/src/modules/opportunities/routes.ts +11 -1
  426. package/src/modules/opportunities/schema.ts +10 -2
  427. package/src/modules/opportunities/service.ts +3 -0
  428. package/src/modules/opportunities/tools.ts +9 -1
  429. package/src/modules/partnerships/events.ts +9 -0
  430. package/src/modules/partnerships/index.ts +4 -2
  431. package/src/modules/partnerships/routes.ts +11 -1
  432. package/src/modules/partnerships/schema.ts +10 -2
  433. package/src/modules/partnerships/service.ts +3 -0
  434. package/src/modules/partnerships/tools.ts +9 -1
  435. package/src/modules/people/personConsentWrites.ts +1 -1
  436. package/src/modules/people/schema.ts +1 -1
  437. package/src/modules/plans/repository.ts +24 -0
  438. package/src/modules/raises/events.ts +9 -0
  439. package/src/modules/raises/index.ts +4 -2
  440. package/src/modules/raises/routes.ts +11 -1
  441. package/src/modules/raises/schema.ts +10 -2
  442. package/src/modules/raises/service.ts +3 -0
  443. package/src/modules/raises/tools.ts +9 -1
  444. package/src/modules/workspace/routes.ts +0 -6
  445. package/src/modules/workspace/schema.ts +0 -2
  446. package/src/modules/workspace/seedStarterForms.ts +98 -0
  447. package/src/modules/workspace/service.ts +23 -15
  448. package/src/modules/workspace/tools.ts +1 -1
  449. package/src/testing/fixtures.ts +1 -0
@@ -1,6 +1,7 @@
1
1
  import { changedKeys } from '../../lib/changes.ts'
2
2
  import { AppError } from '../../lib/errors.ts'
3
3
  import type { IdFactory } from '../../lib/ids.ts'
4
+ import type { CustomFieldValue, CustomFieldWireValue, PipelineKind } from '@kelpie/schemas'
4
5
  import type { RecordObjectType } from '../../runtime/events.ts'
5
6
  import type { Transaction } from '../../runtime/transaction.ts'
6
7
  import type { ActivityRecorder } from '../activities/recorder.ts'
@@ -8,11 +9,18 @@ import { describeCreationVia, describeLink, describeUpdateVia } from '../activit
8
9
  import type { Actor } from '../auth/actor.ts'
9
10
  import * as companyRepository from '../companies/repository.ts'
10
11
  import * as consentPurposesRepository from '../consent-purposes/repository.ts'
12
+ import * as customFieldRepository from '../custom-fields/repository.ts'
13
+ import { createCustomFieldValues } from '../custom-fields/values.ts'
14
+ import type { CustomFieldObjectType } from '../custom-fields/schema.ts'
11
15
  import * as dealRepository from '../deals/repository.ts'
16
+ import * as enquiryRepository from '../enquiries/repository.ts'
17
+ import * as opportunityRepository from '../opportunities/repository.ts'
18
+ import * as partnershipRepository from '../partnerships/repository.ts'
12
19
  import * as peopleRepository from '../people/repository.ts'
13
20
  import { upsertPersonConsent } from '../people/personConsentWrites.ts'
14
21
  import * as personLinks from '../personLinks.ts'
15
22
  import * as positionRepository from '../positions/repository.ts'
23
+ import * as raiseRepository from '../raises/repository.ts'
16
24
  import { IMPORT_DEAL_CURRENCY, NEW_COMPANY_DEFAULTS, NEW_PERSON_DEFAULTS } from './drafts.ts'
17
25
  import type { ImportConsentGrant, ImportWrite, PlannedAffiliation, RowPlan } from './plan.ts'
18
26
 
@@ -52,9 +60,11 @@ export interface SideRecord {
52
60
  readonly changedFields: readonly string[]
53
61
  }
54
62
 
63
+ export type ImportWrittenObjectType = RecordObjectType | 'custom_field'
64
+
55
65
  export interface WriteOutcome {
56
66
  readonly recordId: string
57
- readonly objectType: RecordObjectType
67
+ readonly objectType: ImportWrittenObjectType
58
68
  /**
59
69
  * The columns an update moved, for `record.updated`. Empty on a create, and
60
70
  * empty on an update that resent the values already stored — which emits
@@ -79,6 +89,51 @@ function requireTarget(plan: Extract<RowPlan, { action: 'update' }>): string {
79
89
  return plan.targetId
80
90
  }
81
91
 
92
+ async function validatedCustomFieldsForCreate(
93
+ tx: Transaction,
94
+ workspaceId: string,
95
+ objectType: CustomFieldObjectType,
96
+ sent: Readonly<Record<string, CustomFieldWireValue>> | undefined,
97
+ ): Promise<Readonly<Record<string, CustomFieldValue>> | undefined> {
98
+ if (sent === undefined || Object.keys(sent).length === 0) {
99
+ return undefined
100
+ }
101
+
102
+ return createCustomFieldValues({ db: tx }).forCreate(tx, workspaceId, objectType, sent)
103
+ }
104
+
105
+ async function validatedCustomFieldsForUpdate(
106
+ tx: Transaction,
107
+ workspaceId: string,
108
+ objectType: CustomFieldObjectType,
109
+ stored: Readonly<Record<string, CustomFieldValue>>,
110
+ sent: Readonly<Record<string, CustomFieldWireValue>> | undefined,
111
+ ): Promise<
112
+ | {
113
+ readonly merged: Readonly<Record<string, CustomFieldValue>>
114
+ readonly changedPaths: readonly string[]
115
+ }
116
+ | undefined
117
+ > {
118
+ if (sent === undefined || Object.keys(sent).length === 0) {
119
+ return undefined
120
+ }
121
+
122
+ const merge = await createCustomFieldValues({ db: tx }).forUpdate(
123
+ tx,
124
+ workspaceId,
125
+ objectType,
126
+ stored,
127
+ sent,
128
+ )
129
+
130
+ if (merge === undefined) {
131
+ return undefined
132
+ }
133
+
134
+ return { merged: merge.merged, changedPaths: merge.changedPaths }
135
+ }
136
+
82
137
  async function writeCompany(
83
138
  dependencies: WriteDependencies,
84
139
  plan: WritablePlan,
@@ -87,10 +142,18 @@ async function writeCompany(
87
142
  const { tx, workspaceId } = dependencies
88
143
 
89
144
  if (plan.action === 'create') {
145
+ const customFields = await validatedCustomFieldsForCreate(
146
+ tx,
147
+ workspaceId,
148
+ 'company',
149
+ write.draft.customFields,
150
+ )
151
+ const { customFields: _draftCustomFields, tags, ...rest } = write.draft
90
152
  const created = await companyRepository.insertCompany(tx, {
91
153
  ...NEW_COMPANY_DEFAULTS,
92
- ...write.draft,
93
- tags: write.draft.tags === undefined ? undefined : [...write.draft.tags],
154
+ ...rest,
155
+ tags: tags === undefined ? undefined : [...tags],
156
+ ...(customFields === undefined ? {} : { customFields }),
94
157
  id: dependencies.createId('company'),
95
158
  workspaceId,
96
159
  name: write.draft.name ?? '',
@@ -106,11 +169,23 @@ async function writeCompany(
106
169
  throw AppError.notFound('Company not found')
107
170
  }
108
171
 
172
+ const { customFields: draftCustomFields, tags, ...rest } = write.draft
173
+ const customMerge = await validatedCustomFieldsForUpdate(
174
+ tx,
175
+ workspaceId,
176
+ 'company',
177
+ existing.customFields,
178
+ draftCustomFields,
179
+ )
109
180
  const columns = {
110
- ...write.draft,
111
- tags: write.draft.tags === undefined ? undefined : [...write.draft.tags],
181
+ ...rest,
182
+ tags: tags === undefined ? undefined : [...tags],
183
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
112
184
  }
113
- const changedFields = changedKeys(existing, columns)
185
+ const changedFields = [
186
+ ...changedKeys(existing, columns),
187
+ ...(customMerge?.changedPaths ?? []),
188
+ ]
114
189
 
115
190
  if (changedFields.length > 0) {
116
191
  await companyRepository.updateCompany(tx, workspaceId, id, {
@@ -146,10 +221,11 @@ async function applyAffiliation(
146
221
  return affiliation.companyId
147
222
  }
148
223
 
224
+ const { customFields: _customFields, tags, ...companyRest } = affiliation.company
149
225
  const created = await companyRepository.insertCompany(tx, {
150
226
  ...NEW_COMPANY_DEFAULTS,
151
- ...affiliation.company,
152
- tags: affiliation.company.tags === undefined ? undefined : [...affiliation.company.tags],
227
+ ...companyRest,
228
+ tags: tags === undefined ? undefined : [...tags],
153
229
  id: dependencies.createId('company'),
154
230
  workspaceId,
155
231
  name: affiliation.company.name ?? '',
@@ -216,11 +292,19 @@ async function writePerson(
216
292
  const { tx, workspaceId } = dependencies
217
293
 
218
294
  if (plan.action === 'create') {
295
+ const customFields = await validatedCustomFieldsForCreate(
296
+ tx,
297
+ workspaceId,
298
+ 'person',
299
+ write.draft.customFields,
300
+ )
301
+ const { customFields: _draftCustomFields, phones, tags, ...rest } = write.draft
219
302
  const created = await peopleRepository.insertPerson(tx, {
220
303
  ...NEW_PERSON_DEFAULTS,
221
- ...write.draft,
222
- phones: write.draft.phones === undefined ? undefined : [...write.draft.phones],
223
- tags: write.draft.tags === undefined ? undefined : [...write.draft.tags],
304
+ ...rest,
305
+ phones: phones === undefined ? undefined : [...phones],
306
+ tags: tags === undefined ? undefined : [...tags],
307
+ ...(customFields === undefined ? {} : { customFields }),
224
308
  id: dependencies.createId('person'),
225
309
  workspaceId,
226
310
  // `name` is not a required column any more; the People row check is what
@@ -248,12 +332,24 @@ async function writePerson(
248
332
  throw AppError.notFound('Person not found')
249
333
  }
250
334
 
335
+ const { customFields: draftCustomFields, phones, tags, ...rest } = write.draft
336
+ const customMerge = await validatedCustomFieldsForUpdate(
337
+ tx,
338
+ workspaceId,
339
+ 'person',
340
+ existing.customFields,
341
+ draftCustomFields,
342
+ )
251
343
  const columns = {
252
- ...write.draft,
253
- phones: write.draft.phones === undefined ? undefined : [...write.draft.phones],
254
- tags: write.draft.tags === undefined ? undefined : [...write.draft.tags],
344
+ ...rest,
345
+ phones: phones === undefined ? undefined : [...phones],
346
+ tags: tags === undefined ? undefined : [...tags],
347
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
255
348
  }
256
- const changedFields = changedKeys(existing, columns)
349
+ const changedFields = [
350
+ ...changedKeys(existing, columns),
351
+ ...(customMerge?.changedPaths ?? []),
352
+ ]
257
353
 
258
354
  if (changedFields.length > 0) {
259
355
  await peopleRepository.updatePerson(tx, workspaceId, id, {
@@ -365,12 +461,13 @@ async function writePosition(
365
461
  * rule every other column follows. A mapped, filled-in cell is the file stating
366
462
  * the list, so it replaces.
367
463
  */
368
- async function reconcileDealPeople(
464
+ async function reconcileLinkedPeople(
369
465
  dependencies: WriteDependencies,
370
- dealId: string,
466
+ targetType: PipelineKind,
467
+ targetId: string,
371
468
  personIds: readonly string[],
372
469
  ): Promise<boolean> {
373
- const target = { targetType: 'deal' as const, targetId: dealId }
470
+ const target = { targetType, targetId }
374
471
  const current = await personLinks.listPersonIds(dependencies.tx, dependencies.workspaceId, target)
375
472
  const added = personIds.filter((personId) => !current.includes(personId))
376
473
  const removed = current.filter((personId) => !personIds.includes(personId))
@@ -396,11 +493,25 @@ async function writeDeal(
396
493
 
397
494
  if (plan.action === 'create') {
398
495
  const id = dependencies.createId('deal')
496
+ const customFields = await validatedCustomFieldsForCreate(
497
+ tx,
498
+ workspaceId,
499
+ 'deal',
500
+ write.draft.customFields,
501
+ )
502
+
503
+ const {
504
+ customFields: _draftCustomFields,
505
+ competitors,
506
+ tags,
507
+ ...rest
508
+ } = write.draft
399
509
 
400
510
  await dealRepository.insertDeal(tx, {
401
- ...write.draft,
402
- competitors: write.draft.competitors === undefined ? undefined : [...write.draft.competitors],
403
- tags: write.draft.tags === undefined ? undefined : [...write.draft.tags],
511
+ ...rest,
512
+ competitors: competitors === undefined ? undefined : [...competitors],
513
+ tags: tags === undefined ? undefined : [...tags],
514
+ ...(customFields === undefined ? {} : { customFields }),
404
515
  id,
405
516
  workspaceId,
406
517
  name: write.draft.name ?? '',
@@ -429,15 +540,29 @@ async function writeDeal(
429
540
  throw AppError.notFound('Deal not found')
430
541
  }
431
542
 
543
+ const {
544
+ customFields: draftCustomFields,
545
+ competitors,
546
+ tags,
547
+ ...rest
548
+ } = write.draft
549
+ const customMerge = await validatedCustomFieldsForUpdate(
550
+ tx,
551
+ workspaceId,
552
+ 'deal',
553
+ existing.customFields,
554
+ draftCustomFields,
555
+ )
432
556
  const columns = {
433
- ...write.draft,
434
- competitors: write.draft.competitors === undefined ? undefined : [...write.draft.competitors],
435
- tags: write.draft.tags === undefined ? undefined : [...write.draft.tags],
557
+ ...rest,
558
+ competitors: competitors === undefined ? undefined : [...competitors],
559
+ tags: tags === undefined ? undefined : [...tags],
436
560
  companyId: write.companyId,
437
561
  stageId: write.stageId,
438
562
  ...(write.ownerId === null ? {} : { ownerId: write.ownerId }),
563
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
439
564
  }
440
- const changed = changedKeys(existing, columns)
565
+ const changed = [...changedKeys(existing, columns), ...(customMerge?.changedPaths ?? [])]
441
566
 
442
567
  if (changed.length > 0) {
443
568
  await dealRepository.updateDeal(tx, workspaceId, id, {
@@ -447,7 +572,7 @@ async function writeDeal(
447
572
  }
448
573
 
449
574
  const peopleMoved = write.setsPeople
450
- ? await reconcileDealPeople(dependencies, id, write.personIds)
575
+ ? await reconcileLinkedPeople(dependencies, 'deal', id, write.personIds)
451
576
  : false
452
577
 
453
578
  return {
@@ -457,12 +582,405 @@ async function writeDeal(
457
582
  }
458
583
  }
459
584
 
585
+ async function writeOpportunity(
586
+ dependencies: WriteDependencies,
587
+ plan: WritablePlan,
588
+ write: Extract<ImportWrite, { object: 'opportunities' }>,
589
+ ): Promise<WriteOutcome> {
590
+ const { tx, workspaceId } = dependencies
591
+
592
+ if (plan.action === 'create') {
593
+ const id = dependencies.createId('opportunity')
594
+ const customFields = await validatedCustomFieldsForCreate(
595
+ tx,
596
+ workspaceId,
597
+ 'opportunity',
598
+ write.draft.customFields,
599
+ )
600
+
601
+ const { customFields: _draftCustomFields, tags, ...rest } = write.draft
602
+
603
+ await opportunityRepository.insertOpportunity(tx, {
604
+ ...rest,
605
+ tags: tags === undefined ? undefined : [...tags],
606
+ ...(customFields === undefined ? {} : { customFields }),
607
+ id,
608
+ workspaceId,
609
+ name: write.draft.name ?? '',
610
+ kind: write.draft.kind ?? '',
611
+ stageId: write.stageId,
612
+ companyId: write.companyId,
613
+ ownerId: write.ownerId,
614
+ })
615
+ await personLinks.linkPeople(tx, dependencies.createId, workspaceId, { targetType: 'opportunity', targetId: id }, write.personIds)
616
+
617
+ return { recordId: id, objectType: 'opportunity', changedFields: [] }
618
+ }
619
+
620
+ const id = requireTarget(plan)
621
+ const existing = await opportunityRepository.findOpportunity(tx, workspaceId, id)
622
+
623
+ if (existing === undefined) {
624
+ throw AppError.notFound('Opportunity not found')
625
+ }
626
+
627
+ const { customFields: draftCustomFields, tags, ...rest } = write.draft
628
+ const customMerge = await validatedCustomFieldsForUpdate(
629
+ tx,
630
+ workspaceId,
631
+ 'opportunity',
632
+ existing.customFields,
633
+ draftCustomFields,
634
+ )
635
+ const columns = {
636
+ ...rest,
637
+ tags: tags === undefined ? undefined : [...tags],
638
+ stageId: write.stageId,
639
+ companyId: write.companyId,
640
+ ...(write.ownerId === null ? {} : { ownerId: write.ownerId }),
641
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
642
+ }
643
+ const changed = [...changedKeys(existing, columns), ...(customMerge?.changedPaths ?? [])]
644
+
645
+ if (changed.length > 0) {
646
+ await opportunityRepository.updateOpportunity(tx, workspaceId, id, {
647
+ ...columns,
648
+ updatedAt: dependencies.now,
649
+ })
650
+ }
651
+
652
+ const peopleMoved = write.setsPeople
653
+ ? await reconcileLinkedPeople(dependencies, 'opportunity', id, write.personIds)
654
+ : false
655
+
656
+ return {
657
+ recordId: id,
658
+ objectType: 'opportunity',
659
+ changedFields: peopleMoved ? [...changed, 'personIds'] : changed,
660
+ }
661
+ }
662
+
663
+ async function writeEnquiry(
664
+ dependencies: WriteDependencies,
665
+ plan: WritablePlan,
666
+ write: Extract<ImportWrite, { object: 'enquiries' }>,
667
+ ): Promise<WriteOutcome> {
668
+ const { tx, workspaceId } = dependencies
669
+
670
+ if (plan.action === 'create') {
671
+ const id = dependencies.createId('enquiry')
672
+ const customFields = await validatedCustomFieldsForCreate(
673
+ tx,
674
+ workspaceId,
675
+ 'enquiry',
676
+ write.draft.customFields,
677
+ )
678
+
679
+ const { customFields: _draftCustomFields, tags, ...rest } = write.draft
680
+
681
+ await enquiryRepository.insertEnquiry(tx, {
682
+ ...rest,
683
+ tags: tags === undefined ? undefined : [...tags],
684
+ ...(customFields === undefined ? {} : { customFields }),
685
+ id,
686
+ workspaceId,
687
+ name: write.draft.name ?? '',
688
+ source: write.draft.source ?? '',
689
+ stageId: write.stageId,
690
+ companyId: write.companyId,
691
+ ownerId: write.ownerId,
692
+ })
693
+ await personLinks.linkPeople(tx, dependencies.createId, workspaceId, { targetType: 'enquiry', targetId: id }, write.personIds)
694
+
695
+ return { recordId: id, objectType: 'enquiry', changedFields: [] }
696
+ }
697
+
698
+ const id = requireTarget(plan)
699
+ const existing = await enquiryRepository.findEnquiry(tx, workspaceId, id)
700
+
701
+ if (existing === undefined) {
702
+ throw AppError.notFound('Enquiry not found')
703
+ }
704
+
705
+ const { customFields: draftCustomFields, tags, ...rest } = write.draft
706
+ const customMerge = await validatedCustomFieldsForUpdate(
707
+ tx,
708
+ workspaceId,
709
+ 'enquiry',
710
+ existing.customFields,
711
+ draftCustomFields,
712
+ )
713
+ const columns = {
714
+ ...rest,
715
+ tags: tags === undefined ? undefined : [...tags],
716
+ stageId: write.stageId,
717
+ companyId: write.companyId,
718
+ ...(write.ownerId === null ? {} : { ownerId: write.ownerId }),
719
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
720
+ }
721
+ const changed = [...changedKeys(existing, columns), ...(customMerge?.changedPaths ?? [])]
722
+
723
+ if (changed.length > 0) {
724
+ await enquiryRepository.updateEnquiry(tx, workspaceId, id, {
725
+ ...columns,
726
+ updatedAt: dependencies.now,
727
+ })
728
+ }
729
+
730
+ const peopleMoved = write.setsPeople
731
+ ? await reconcileLinkedPeople(dependencies, 'enquiry', id, write.personIds)
732
+ : false
733
+
734
+ return {
735
+ recordId: id,
736
+ objectType: 'enquiry',
737
+ changedFields: peopleMoved ? [...changed, 'personIds'] : changed,
738
+ }
739
+ }
740
+
741
+ async function writePartnership(
742
+ dependencies: WriteDependencies,
743
+ plan: WritablePlan,
744
+ write: Extract<ImportWrite, { object: 'partnerships' }>,
745
+ ): Promise<WriteOutcome> {
746
+ const { tx, workspaceId } = dependencies
747
+
748
+ if (plan.action === 'create') {
749
+ const id = dependencies.createId('partnership')
750
+ const customFields = await validatedCustomFieldsForCreate(
751
+ tx,
752
+ workspaceId,
753
+ 'partnership',
754
+ write.draft.customFields,
755
+ )
756
+
757
+ const { customFields: _draftCustomFields, tags, ...rest } = write.draft
758
+
759
+ await partnershipRepository.insertPartnership(tx, {
760
+ ...rest,
761
+ tags: tags === undefined ? undefined : [...tags],
762
+ ...(customFields === undefined ? {} : { customFields }),
763
+ id,
764
+ workspaceId,
765
+ name: write.draft.name ?? '',
766
+ kind: write.draft.kind ?? '',
767
+ stageId: write.stageId,
768
+ companyId: write.companyId,
769
+ ownerId: write.ownerId,
770
+ })
771
+ await personLinks.linkPeople(tx, dependencies.createId, workspaceId, { targetType: 'partnership', targetId: id }, write.personIds)
772
+
773
+ return { recordId: id, objectType: 'partnership', changedFields: [] }
774
+ }
775
+
776
+ const id = requireTarget(plan)
777
+ const existing = await partnershipRepository.findPartnership(tx, workspaceId, id)
778
+
779
+ if (existing === undefined) {
780
+ throw AppError.notFound('Partnership not found')
781
+ }
782
+
783
+ const { customFields: draftCustomFields, tags, ...rest } = write.draft
784
+ const customMerge = await validatedCustomFieldsForUpdate(
785
+ tx,
786
+ workspaceId,
787
+ 'partnership',
788
+ existing.customFields,
789
+ draftCustomFields,
790
+ )
791
+ const columns = {
792
+ ...rest,
793
+ tags: tags === undefined ? undefined : [...tags],
794
+ stageId: write.stageId,
795
+ companyId: write.companyId,
796
+ ...(write.ownerId === null ? {} : { ownerId: write.ownerId }),
797
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
798
+ }
799
+ const changed = [...changedKeys(existing, columns), ...(customMerge?.changedPaths ?? [])]
800
+
801
+ if (changed.length > 0) {
802
+ await partnershipRepository.updatePartnership(tx, workspaceId, id, {
803
+ ...columns,
804
+ updatedAt: dependencies.now,
805
+ })
806
+ }
807
+
808
+ const peopleMoved = write.setsPeople
809
+ ? await reconcileLinkedPeople(dependencies, 'partnership', id, write.personIds)
810
+ : false
811
+
812
+ return {
813
+ recordId: id,
814
+ objectType: 'partnership',
815
+ changedFields: peopleMoved ? [...changed, 'personIds'] : changed,
816
+ }
817
+ }
818
+
819
+ async function writeRaise(
820
+ dependencies: WriteDependencies,
821
+ plan: WritablePlan,
822
+ write: Extract<ImportWrite, { object: 'raises' }>,
823
+ ): Promise<WriteOutcome> {
824
+ const { tx, workspaceId } = dependencies
825
+
826
+ if (plan.action === 'create') {
827
+ const id = dependencies.createId('raise')
828
+ const customFields = await validatedCustomFieldsForCreate(
829
+ tx,
830
+ workspaceId,
831
+ 'raise',
832
+ write.draft.customFields,
833
+ )
834
+
835
+ const { customFields: _draftCustomFields, tags, ...rest } = write.draft
836
+
837
+ await raiseRepository.insertRaise(tx, {
838
+ ...rest,
839
+ tags: tags === undefined ? undefined : [...tags],
840
+ ...(customFields === undefined ? {} : { customFields }),
841
+ id,
842
+ workspaceId,
843
+ name: write.draft.name ?? '',
844
+ stageId: write.stageId,
845
+ companyId: write.companyId,
846
+ ownerId: write.ownerId,
847
+ currency:
848
+ write.draft.currency ??
849
+ (write.draft.checkSizeCents === undefined || write.draft.checkSizeCents === null
850
+ ? undefined
851
+ : IMPORT_DEAL_CURRENCY),
852
+ })
853
+ await personLinks.linkPeople(tx, dependencies.createId, workspaceId, { targetType: 'raise', targetId: id }, write.personIds)
854
+
855
+ return { recordId: id, objectType: 'raise', changedFields: [] }
856
+ }
857
+
858
+ const id = requireTarget(plan)
859
+ const existing = await raiseRepository.findRaise(tx, workspaceId, id)
860
+
861
+ if (existing === undefined) {
862
+ throw AppError.notFound('Raise not found')
863
+ }
864
+
865
+ const { customFields: draftCustomFields, tags, ...rest } = write.draft
866
+ const customMerge = await validatedCustomFieldsForUpdate(
867
+ tx,
868
+ workspaceId,
869
+ 'raise',
870
+ existing.customFields,
871
+ draftCustomFields,
872
+ )
873
+ const columns = {
874
+ ...rest,
875
+ tags: tags === undefined ? undefined : [...tags],
876
+ stageId: write.stageId,
877
+ companyId: write.companyId,
878
+ ...(write.ownerId === null ? {} : { ownerId: write.ownerId }),
879
+ ...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
880
+ }
881
+ const changed = [...changedKeys(existing, columns), ...(customMerge?.changedPaths ?? [])]
882
+
883
+ if (changed.length > 0) {
884
+ await raiseRepository.updateRaise(tx, workspaceId, id, {
885
+ ...columns,
886
+ updatedAt: dependencies.now,
887
+ })
888
+ }
889
+
890
+ const peopleMoved = write.setsPeople
891
+ ? await reconcileLinkedPeople(dependencies, 'raise', id, write.personIds)
892
+ : false
893
+
894
+ return {
895
+ recordId: id,
896
+ objectType: 'raise',
897
+ changedFields: peopleMoved ? [...changed, 'personIds'] : changed,
898
+ }
899
+ }
900
+
901
+ async function writeCustomFieldDefinition(
902
+ dependencies: WriteDependencies,
903
+ plan: WritablePlan,
904
+ write: Extract<ImportWrite, { object: 'custom_fields' }>,
905
+ ): Promise<WriteOutcome> {
906
+ const { tx, workspaceId } = dependencies
907
+
908
+ if (plan.action === 'create') {
909
+ const id = dependencies.createId('customFieldDefinition')
910
+ const created = await customFieldRepository.insertDefinition(tx, {
911
+ id,
912
+ workspaceId,
913
+ objectType: write.draft.objectType as CustomFieldObjectType,
914
+ key: write.draft.key ?? '',
915
+ label: write.draft.label ?? '',
916
+ type: write.draft.type as import('../custom-fields/schema.ts').CustomFieldType,
917
+ options: write.draft.options === undefined ? [] : [...write.draft.options],
918
+ description: write.draft.description ?? '',
919
+ sortOrder: write.draft.sortOrder ?? 0,
920
+ })
921
+
922
+ return { recordId: created.id, objectType: 'custom_field', changedFields: [] }
923
+ }
924
+
925
+ const id = requireTarget(plan)
926
+ const existing = await customFieldRepository.findDefinition(tx, workspaceId, id)
927
+
928
+ if (existing === undefined) {
929
+ throw AppError.notFound('Custom field not found')
930
+ }
931
+
932
+ const columns = {
933
+ ...(write.draft.label === undefined ? {} : { label: write.draft.label }),
934
+ ...(write.draft.description === undefined ? {} : { description: write.draft.description }),
935
+ ...(write.draft.options === undefined ? {} : { options: [...write.draft.options] }),
936
+ ...(write.draft.sortOrder === undefined ? {} : { sortOrder: write.draft.sortOrder }),
937
+ }
938
+ const changedFields = changedKeys(existing, columns)
939
+
940
+ if (changedFields.length > 0) {
941
+ await customFieldRepository.updateDefinition(tx, workspaceId, id, {
942
+ ...columns,
943
+ updatedAt: dependencies.now,
944
+ })
945
+ }
946
+
947
+ return { recordId: id, objectType: 'custom_field', changedFields }
948
+ }
949
+
460
950
  /** What a timeline calls each object. */
461
951
  const OBJECT_LABEL: Readonly<Record<ImportWrite['object'], string>> = {
462
952
  companies: 'Company',
463
953
  people: 'Person',
464
954
  positions: 'Position',
465
955
  deals: 'Deal',
956
+ opportunities: 'Opportunity',
957
+ enquiries: 'Enquiry',
958
+ partnerships: 'Partnership',
959
+ raises: 'Raise',
960
+ custom_fields: 'Custom field',
961
+ }
962
+
963
+ function historyTargetType(
964
+ write: ImportWrite,
965
+ ): 'company' | 'person' | 'deal' | 'opportunity' | 'enquiry' | 'partnership' | 'raise' {
966
+ switch (write.object) {
967
+ case 'companies':
968
+ return 'company'
969
+ case 'people':
970
+ return 'person'
971
+ case 'deals':
972
+ return 'deal'
973
+ case 'opportunities':
974
+ return 'opportunity'
975
+ case 'enquiries':
976
+ return 'enquiry'
977
+ case 'partnerships':
978
+ return 'partnership'
979
+ case 'raises':
980
+ return 'raise'
981
+ default:
982
+ throw new Error(`No history target for ${write.object}`)
983
+ }
466
984
  }
467
985
 
468
986
  /**
@@ -480,6 +998,10 @@ async function recordHistory(
480
998
  ): Promise<void> {
481
999
  const { tx, workspaceId, actor, sourceName } = dependencies
482
1000
 
1001
+ if (write.object === 'custom_fields') {
1002
+ return
1003
+ }
1004
+
483
1005
  if (write.object === 'positions') {
484
1006
  if (plan.action !== 'create') {
485
1007
  return
@@ -509,7 +1031,7 @@ async function recordHistory(
509
1031
  const label = OBJECT_LABEL[write.object]
510
1032
 
511
1033
  await dependencies.recordActivity(tx, workspaceId, actor, {
512
- targetType: write.object === 'companies' ? 'company' : write.object === 'people' ? 'person' : 'deal',
1034
+ targetType: historyTargetType(write),
513
1035
  targetId: outcome.recordId,
514
1036
  kind: plan.action === 'create' ? 'created' : 'updated',
515
1037
  ...(plan.action === 'create'
@@ -534,6 +1056,16 @@ export async function applyWrite(
534
1056
  return writePosition(dependencies, plan, write)
535
1057
  case 'deals':
536
1058
  return writeDeal(dependencies, plan, write)
1059
+ case 'opportunities':
1060
+ return writeOpportunity(dependencies, plan, write)
1061
+ case 'enquiries':
1062
+ return writeEnquiry(dependencies, plan, write)
1063
+ case 'partnerships':
1064
+ return writePartnership(dependencies, plan, write)
1065
+ case 'raises':
1066
+ return writeRaise(dependencies, plan, write)
1067
+ case 'custom_fields':
1068
+ return writeCustomFieldDefinition(dependencies, plan, write)
537
1069
  }
538
1070
  })()
539
1071