@kelpie/server 0.10.0 → 0.12.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 (485) 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 +3 -3
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -1
  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/lib/errors.d.ts +18 -0
  16. package/dist/lib/errors.d.ts.map +1 -1
  17. package/dist/lib/errors.js +17 -0
  18. package/dist/lib/errors.js.map +1 -1
  19. package/dist/modules/activities/repository.d.ts +2 -0
  20. package/dist/modules/activities/repository.d.ts.map +1 -1
  21. package/dist/modules/activities/repository.js +9 -0
  22. package/dist/modules/activities/repository.js.map +1 -1
  23. package/dist/modules/agent-tasks/repository.d.ts +2 -0
  24. package/dist/modules/agent-tasks/repository.d.ts.map +1 -1
  25. package/dist/modules/agent-tasks/repository.js +9 -0
  26. package/dist/modules/agent-tasks/repository.js.map +1 -1
  27. package/dist/modules/api-keys/routes.d.ts.map +1 -1
  28. package/dist/modules/api-keys/routes.js +4 -1
  29. package/dist/modules/api-keys/routes.js.map +1 -1
  30. package/dist/modules/api-keys/schema.d.ts +43 -0
  31. package/dist/modules/api-keys/schema.d.ts.map +1 -1
  32. package/dist/modules/api-keys/schema.js +2 -0
  33. package/dist/modules/api-keys/schema.js.map +1 -1
  34. package/dist/modules/api-keys/scopeMiddleware.d.ts +8 -0
  35. package/dist/modules/api-keys/scopeMiddleware.d.ts.map +1 -0
  36. package/dist/modules/api-keys/scopeMiddleware.js +21 -0
  37. package/dist/modules/api-keys/scopeMiddleware.js.map +1 -0
  38. package/dist/modules/api-keys/service.d.ts +3 -1
  39. package/dist/modules/api-keys/service.d.ts.map +1 -1
  40. package/dist/modules/api-keys/service.js +26 -1
  41. package/dist/modules/api-keys/service.js.map +1 -1
  42. package/dist/modules/auth/credentials.d.ts.map +1 -1
  43. package/dist/modules/auth/credentials.js +2 -0
  44. package/dist/modules/auth/credentials.js.map +1 -1
  45. package/dist/modules/auth/index.d.ts.map +1 -1
  46. package/dist/modules/auth/index.js +21 -4
  47. package/dist/modules/auth/index.js.map +1 -1
  48. package/dist/modules/auth/repository.d.ts +2 -1
  49. package/dist/modules/auth/repository.d.ts.map +1 -1
  50. package/dist/modules/auth/repository.js +1 -0
  51. package/dist/modules/auth/repository.js.map +1 -1
  52. package/dist/modules/auth/routes.d.ts.map +1 -1
  53. package/dist/modules/auth/routes.js +2 -6
  54. package/dist/modules/auth/routes.js.map +1 -1
  55. package/dist/modules/auth/schema.d.ts +18 -1
  56. package/dist/modules/auth/schema.d.ts.map +1 -1
  57. package/dist/modules/auth/schema.js +12 -1
  58. package/dist/modules/auth/schema.js.map +1 -1
  59. package/dist/modules/auth/service.d.ts +18 -0
  60. package/dist/modules/auth/service.d.ts.map +1 -1
  61. package/dist/modules/auth/service.js +95 -6
  62. package/dist/modules/auth/service.js.map +1 -1
  63. package/dist/modules/auth/session.d.ts +12 -0
  64. package/dist/modules/auth/session.d.ts.map +1 -1
  65. package/dist/modules/auth/session.js +12 -0
  66. package/dist/modules/auth/session.js.map +1 -1
  67. package/dist/modules/consent-purposes/index.d.ts +1 -1
  68. package/dist/modules/consent-purposes/index.js +1 -1
  69. package/dist/modules/consent-purposes/schema.d.ts +3 -3
  70. package/dist/modules/consent-purposes/schema.js +3 -3
  71. package/dist/modules/consent-purposes/service.d.ts +1 -1
  72. package/dist/modules/consent-purposes/service.d.ts.map +1 -1
  73. package/dist/modules/consent-purposes/service.js +7 -16
  74. package/dist/modules/consent-purposes/service.js.map +1 -1
  75. package/dist/modules/consent-purposes/starters.d.ts +1 -1
  76. package/dist/modules/consent-purposes/tools.js +1 -1
  77. package/dist/modules/consent-purposes/tools.js.map +1 -1
  78. package/dist/modules/conversions/clearPointers.d.ts +10 -0
  79. package/dist/modules/conversions/clearPointers.d.ts.map +1 -0
  80. package/dist/modules/conversions/clearPointers.js +40 -0
  81. package/dist/modules/conversions/clearPointers.js.map +1 -0
  82. package/dist/modules/conversions/factory.d.ts +5 -0
  83. package/dist/modules/conversions/factory.d.ts.map +1 -0
  84. package/dist/modules/conversions/factory.js +18 -0
  85. package/dist/modules/conversions/factory.js.map +1 -0
  86. package/dist/modules/conversions/fieldMap.d.ts +55 -0
  87. package/dist/modules/conversions/fieldMap.d.ts.map +1 -0
  88. package/dist/modules/conversions/fieldMap.js +398 -0
  89. package/dist/modules/conversions/fieldMap.js.map +1 -0
  90. package/dist/modules/conversions/index.d.ts +7 -0
  91. package/dist/modules/conversions/index.d.ts.map +1 -0
  92. package/dist/modules/conversions/index.js +6 -0
  93. package/dist/modules/conversions/index.js.map +1 -0
  94. package/dist/modules/conversions/mcp.d.ts +7 -0
  95. package/dist/modules/conversions/mcp.d.ts.map +1 -0
  96. package/dist/modules/conversions/mcp.js +47 -0
  97. package/dist/modules/conversions/mcp.js.map +1 -0
  98. package/dist/modules/conversions/repoint.d.ts +19 -0
  99. package/dist/modules/conversions/repoint.d.ts.map +1 -0
  100. package/dist/modules/conversions/repoint.js +51 -0
  101. package/dist/modules/conversions/repoint.js.map +1 -0
  102. package/dist/modules/conversions/routes.d.ts +26 -0
  103. package/dist/modules/conversions/routes.d.ts.map +1 -0
  104. package/dist/modules/conversions/routes.js +23 -0
  105. package/dist/modules/conversions/routes.js.map +1 -0
  106. package/dist/modules/conversions/service.d.ts +28 -0
  107. package/dist/modules/conversions/service.d.ts.map +1 -0
  108. package/dist/modules/conversions/service.js +170 -0
  109. package/dist/modules/conversions/service.js.map +1 -0
  110. package/dist/modules/conversions/wire.d.ts +4 -0
  111. package/dist/modules/conversions/wire.d.ts.map +1 -0
  112. package/dist/modules/conversions/wire.js +28 -0
  113. package/dist/modules/conversions/wire.js.map +1 -0
  114. package/dist/modules/deals/events.d.ts +9 -0
  115. package/dist/modules/deals/events.d.ts.map +1 -1
  116. package/dist/modules/deals/events.js +4 -0
  117. package/dist/modules/deals/events.js.map +1 -1
  118. package/dist/modules/deals/index.d.ts.map +1 -1
  119. package/dist/modules/deals/index.js +4 -2
  120. package/dist/modules/deals/index.js.map +1 -1
  121. package/dist/modules/deals/routes.d.ts +2 -0
  122. package/dist/modules/deals/routes.d.ts.map +1 -1
  123. package/dist/modules/deals/routes.js +8 -1
  124. package/dist/modules/deals/routes.js.map +1 -1
  125. package/dist/modules/deals/schema.d.ts +34 -0
  126. package/dist/modules/deals/schema.d.ts.map +1 -1
  127. package/dist/modules/deals/schema.js +7 -2
  128. package/dist/modules/deals/schema.js.map +1 -1
  129. package/dist/modules/deals/service.d.ts.map +1 -1
  130. package/dist/modules/deals/service.js +2 -0
  131. package/dist/modules/deals/service.js.map +1 -1
  132. package/dist/modules/deals/tools.d.ts +2 -1
  133. package/dist/modules/deals/tools.d.ts.map +1 -1
  134. package/dist/modules/deals/tools.js +3 -1
  135. package/dist/modules/deals/tools.js.map +1 -1
  136. package/dist/modules/decisions/repository.d.ts +2 -1
  137. package/dist/modules/decisions/repository.d.ts.map +1 -1
  138. package/dist/modules/decisions/repository.js +9 -1
  139. package/dist/modules/decisions/repository.js.map +1 -1
  140. package/dist/modules/enquiries/events.d.ts +6 -2
  141. package/dist/modules/enquiries/events.d.ts.map +1 -1
  142. package/dist/modules/enquiries/events.js +5 -1
  143. package/dist/modules/enquiries/events.js.map +1 -1
  144. package/dist/modules/enquiries/index.d.ts.map +1 -1
  145. package/dist/modules/enquiries/index.js +4 -2
  146. package/dist/modules/enquiries/index.js.map +1 -1
  147. package/dist/modules/enquiries/routes.d.ts +2 -0
  148. package/dist/modules/enquiries/routes.d.ts.map +1 -1
  149. package/dist/modules/enquiries/routes.js +9 -9
  150. package/dist/modules/enquiries/routes.js.map +1 -1
  151. package/dist/modules/enquiries/schema.d.ts +36 -1
  152. package/dist/modules/enquiries/schema.d.ts.map +1 -1
  153. package/dist/modules/enquiries/schema.js +9 -3
  154. package/dist/modules/enquiries/schema.js.map +1 -1
  155. package/dist/modules/enquiries/service.d.ts +0 -8
  156. package/dist/modules/enquiries/service.d.ts.map +1 -1
  157. package/dist/modules/enquiries/service.js +3 -95
  158. package/dist/modules/enquiries/service.js.map +1 -1
  159. package/dist/modules/enquiries/tools.d.ts +2 -1
  160. package/dist/modules/enquiries/tools.d.ts.map +1 -1
  161. package/dist/modules/enquiries/tools.js +4 -16
  162. package/dist/modules/enquiries/tools.js.map +1 -1
  163. package/dist/modules/forms/applyMappedFields.d.ts +20 -0
  164. package/dist/modules/forms/applyMappedFields.d.ts.map +1 -0
  165. package/dist/modules/forms/applyMappedFields.js +169 -0
  166. package/dist/modules/forms/applyMappedFields.js.map +1 -0
  167. package/dist/modules/forms/applySubmissionFields.d.ts +18 -0
  168. package/dist/modules/forms/applySubmissionFields.d.ts.map +1 -0
  169. package/dist/modules/forms/applySubmissionFields.js +230 -0
  170. package/dist/modules/forms/applySubmissionFields.js.map +1 -0
  171. package/dist/modules/forms/fields.d.ts +7 -2
  172. package/dist/modules/forms/fields.d.ts.map +1 -1
  173. package/dist/modules/forms/fields.js +17 -6
  174. package/dist/modules/forms/fields.js.map +1 -1
  175. package/dist/modules/forms/mapping.d.ts +8 -2
  176. package/dist/modules/forms/mapping.d.ts.map +1 -1
  177. package/dist/modules/forms/mapping.js +11 -0
  178. package/dist/modules/forms/mapping.js.map +1 -1
  179. package/dist/modules/forms/repository.d.ts +0 -5
  180. package/dist/modules/forms/repository.d.ts.map +1 -1
  181. package/dist/modules/forms/repository.js +0 -2
  182. package/dist/modules/forms/repository.js.map +1 -1
  183. package/dist/modules/forms/routes.d.ts +2 -30
  184. package/dist/modules/forms/routes.d.ts.map +1 -1
  185. package/dist/modules/forms/routes.js +2 -2
  186. package/dist/modules/forms/routes.js.map +1 -1
  187. package/dist/modules/forms/schema.d.ts.map +1 -1
  188. package/dist/modules/forms/schema.js +1 -2
  189. package/dist/modules/forms/schema.js.map +1 -1
  190. package/dist/modules/forms/service.d.ts.map +1 -1
  191. package/dist/modules/forms/service.js +18 -3
  192. package/dist/modules/forms/service.js.map +1 -1
  193. package/dist/modules/forms/starters.d.ts +31 -0
  194. package/dist/modules/forms/starters.d.ts.map +1 -0
  195. package/dist/modules/forms/starters.js +94 -0
  196. package/dist/modules/forms/starters.js.map +1 -0
  197. package/dist/modules/forms/submission.d.ts +1 -0
  198. package/dist/modules/forms/submission.d.ts.map +1 -1
  199. package/dist/modules/forms/submission.js +58 -37
  200. package/dist/modules/forms/submission.js.map +1 -1
  201. package/dist/modules/import-export/customFieldCsv.d.ts +9 -0
  202. package/dist/modules/import-export/customFieldCsv.d.ts.map +1 -0
  203. package/dist/modules/import-export/customFieldCsv.js +39 -0
  204. package/dist/modules/import-export/customFieldCsv.js.map +1 -0
  205. package/dist/modules/import-export/customFieldImport.d.ts +19 -0
  206. package/dist/modules/import-export/customFieldImport.d.ts.map +1 -0
  207. package/dist/modules/import-export/customFieldImport.js +76 -0
  208. package/dist/modules/import-export/customFieldImport.js.map +1 -0
  209. package/dist/modules/import-export/drafts.d.ts +57 -3
  210. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  211. package/dist/modules/import-export/drafts.js +65 -3
  212. package/dist/modules/import-export/drafts.js.map +1 -1
  213. package/dist/modules/import-export/exportRows.d.ts +15 -13
  214. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  215. package/dist/modules/import-export/exportRows.js +99 -26
  216. package/dist/modules/import-export/exportRows.js.map +1 -1
  217. package/dist/modules/import-export/plan.d.ts +42 -11
  218. package/dist/modules/import-export/plan.d.ts.map +1 -1
  219. package/dist/modules/import-export/plan.js +198 -56
  220. package/dist/modules/import-export/plan.js.map +1 -1
  221. package/dist/modules/import-export/repository.d.ts +58 -2
  222. package/dist/modules/import-export/repository.d.ts.map +1 -1
  223. package/dist/modules/import-export/repository.js +201 -12
  224. package/dist/modules/import-export/repository.js.map +1 -1
  225. package/dist/modules/import-export/routes.d.ts.map +1 -1
  226. package/dist/modules/import-export/routes.js +5 -5
  227. package/dist/modules/import-export/routes.js.map +1 -1
  228. package/dist/modules/import-export/service.d.ts +8 -3
  229. package/dist/modules/import-export/service.d.ts.map +1 -1
  230. package/dist/modules/import-export/service.js +133 -40
  231. package/dist/modules/import-export/service.js.map +1 -1
  232. package/dist/modules/import-export/streams.d.ts +2 -2
  233. package/dist/modules/import-export/streams.d.ts.map +1 -1
  234. package/dist/modules/import-export/streams.js +50 -9
  235. package/dist/modules/import-export/streams.js.map +1 -1
  236. package/dist/modules/import-export/tools.d.ts.map +1 -1
  237. package/dist/modules/import-export/tools.js +13 -7
  238. package/dist/modules/import-export/tools.js.map +1 -1
  239. package/dist/modules/import-export/validation.d.ts +5 -1
  240. package/dist/modules/import-export/validation.d.ts.map +1 -1
  241. package/dist/modules/import-export/validation.js +89 -2
  242. package/dist/modules/import-export/validation.js.map +1 -1
  243. package/dist/modules/import-export/writes.d.ts +2 -1
  244. package/dist/modules/import-export/writes.d.ts.map +1 -1
  245. package/dist/modules/import-export/writes.js +358 -25
  246. package/dist/modules/import-export/writes.js.map +1 -1
  247. package/dist/modules/lists/repository.d.ts +0 -1
  248. package/dist/modules/lists/repository.d.ts.map +1 -1
  249. package/dist/modules/lists/repository.js +0 -1
  250. package/dist/modules/lists/repository.js.map +1 -1
  251. package/dist/modules/lists/routes.d.ts +0 -2
  252. package/dist/modules/lists/routes.d.ts.map +1 -1
  253. package/dist/modules/lists/routes.js +0 -8
  254. package/dist/modules/lists/routes.js.map +1 -1
  255. package/dist/modules/lists/schema.d.ts +0 -17
  256. package/dist/modules/lists/schema.d.ts.map +1 -1
  257. package/dist/modules/lists/schema.js +0 -10
  258. package/dist/modules/lists/schema.js.map +1 -1
  259. package/dist/modules/lists/service.d.ts +2 -14
  260. package/dist/modules/lists/service.d.ts.map +1 -1
  261. package/dist/modules/lists/service.js +7 -53
  262. package/dist/modules/lists/service.js.map +1 -1
  263. package/dist/modules/lists/starters.d.ts +12 -0
  264. package/dist/modules/lists/starters.d.ts.map +1 -0
  265. package/dist/modules/lists/starters.js +4 -0
  266. package/dist/modules/lists/starters.js.map +1 -0
  267. package/dist/modules/mcp/protocol.d.ts.map +1 -1
  268. package/dist/modules/mcp/protocol.js +13 -0
  269. package/dist/modules/mcp/protocol.js.map +1 -1
  270. package/dist/modules/notes/repository.d.ts +2 -0
  271. package/dist/modules/notes/repository.d.ts.map +1 -1
  272. package/dist/modules/notes/repository.js +9 -0
  273. package/dist/modules/notes/repository.js.map +1 -1
  274. package/dist/modules/opportunities/events.d.ts +9 -0
  275. package/dist/modules/opportunities/events.d.ts.map +1 -1
  276. package/dist/modules/opportunities/events.js +4 -0
  277. package/dist/modules/opportunities/events.js.map +1 -1
  278. package/dist/modules/opportunities/index.d.ts.map +1 -1
  279. package/dist/modules/opportunities/index.js +4 -2
  280. package/dist/modules/opportunities/index.js.map +1 -1
  281. package/dist/modules/opportunities/routes.d.ts +2 -0
  282. package/dist/modules/opportunities/routes.d.ts.map +1 -1
  283. package/dist/modules/opportunities/routes.js +8 -1
  284. package/dist/modules/opportunities/routes.js.map +1 -1
  285. package/dist/modules/opportunities/schema.d.ts +34 -0
  286. package/dist/modules/opportunities/schema.d.ts.map +1 -1
  287. package/dist/modules/opportunities/schema.js +7 -2
  288. package/dist/modules/opportunities/schema.js.map +1 -1
  289. package/dist/modules/opportunities/service.d.ts.map +1 -1
  290. package/dist/modules/opportunities/service.js +2 -0
  291. package/dist/modules/opportunities/service.js.map +1 -1
  292. package/dist/modules/opportunities/tools.d.ts +2 -1
  293. package/dist/modules/opportunities/tools.d.ts.map +1 -1
  294. package/dist/modules/opportunities/tools.js +3 -1
  295. package/dist/modules/opportunities/tools.js.map +1 -1
  296. package/dist/modules/partnerships/events.d.ts +9 -0
  297. package/dist/modules/partnerships/events.d.ts.map +1 -1
  298. package/dist/modules/partnerships/events.js +4 -0
  299. package/dist/modules/partnerships/events.js.map +1 -1
  300. package/dist/modules/partnerships/index.d.ts.map +1 -1
  301. package/dist/modules/partnerships/index.js +4 -2
  302. package/dist/modules/partnerships/index.js.map +1 -1
  303. package/dist/modules/partnerships/routes.d.ts +2 -0
  304. package/dist/modules/partnerships/routes.d.ts.map +1 -1
  305. package/dist/modules/partnerships/routes.js +8 -1
  306. package/dist/modules/partnerships/routes.js.map +1 -1
  307. package/dist/modules/partnerships/schema.d.ts +34 -0
  308. package/dist/modules/partnerships/schema.d.ts.map +1 -1
  309. package/dist/modules/partnerships/schema.js +7 -2
  310. package/dist/modules/partnerships/schema.js.map +1 -1
  311. package/dist/modules/partnerships/service.d.ts.map +1 -1
  312. package/dist/modules/partnerships/service.js +2 -0
  313. package/dist/modules/partnerships/service.js.map +1 -1
  314. package/dist/modules/partnerships/tools.d.ts +2 -1
  315. package/dist/modules/partnerships/tools.d.ts.map +1 -1
  316. package/dist/modules/partnerships/tools.js +3 -1
  317. package/dist/modules/partnerships/tools.js.map +1 -1
  318. package/dist/modules/people/personConsentWrites.d.ts +1 -1
  319. package/dist/modules/people/schema.js +1 -1
  320. package/dist/modules/people/schema.js.map +1 -1
  321. package/dist/modules/plans/repository.d.ts +2 -0
  322. package/dist/modules/plans/repository.d.ts.map +1 -1
  323. package/dist/modules/plans/repository.js +9 -0
  324. package/dist/modules/plans/repository.js.map +1 -1
  325. package/dist/modules/raises/events.d.ts +9 -0
  326. package/dist/modules/raises/events.d.ts.map +1 -1
  327. package/dist/modules/raises/events.js +4 -0
  328. package/dist/modules/raises/events.js.map +1 -1
  329. package/dist/modules/raises/index.d.ts.map +1 -1
  330. package/dist/modules/raises/index.js +4 -2
  331. package/dist/modules/raises/index.js.map +1 -1
  332. package/dist/modules/raises/routes.d.ts +2 -0
  333. package/dist/modules/raises/routes.d.ts.map +1 -1
  334. package/dist/modules/raises/routes.js +8 -1
  335. package/dist/modules/raises/routes.js.map +1 -1
  336. package/dist/modules/raises/schema.d.ts +34 -0
  337. package/dist/modules/raises/schema.d.ts.map +1 -1
  338. package/dist/modules/raises/schema.js +7 -2
  339. package/dist/modules/raises/schema.js.map +1 -1
  340. package/dist/modules/raises/service.d.ts.map +1 -1
  341. package/dist/modules/raises/service.js +2 -0
  342. package/dist/modules/raises/service.js.map +1 -1
  343. package/dist/modules/raises/tools.d.ts +2 -1
  344. package/dist/modules/raises/tools.d.ts.map +1 -1
  345. package/dist/modules/raises/tools.js +3 -1
  346. package/dist/modules/raises/tools.js.map +1 -1
  347. package/dist/modules/workspace/routes.d.ts +0 -2
  348. package/dist/modules/workspace/routes.d.ts.map +1 -1
  349. package/dist/modules/workspace/routes.js +0 -6
  350. package/dist/modules/workspace/routes.js.map +1 -1
  351. package/dist/modules/workspace/schema.d.ts +0 -34
  352. package/dist/modules/workspace/schema.d.ts.map +1 -1
  353. package/dist/modules/workspace/schema.js +0 -2
  354. package/dist/modules/workspace/schema.js.map +1 -1
  355. package/dist/modules/workspace/seedStarterForms.d.ts +17 -0
  356. package/dist/modules/workspace/seedStarterForms.d.ts.map +1 -0
  357. package/dist/modules/workspace/seedStarterForms.js +71 -0
  358. package/dist/modules/workspace/seedStarterForms.js.map +1 -0
  359. package/dist/modules/workspace/service.d.ts +0 -4
  360. package/dist/modules/workspace/service.d.ts.map +1 -1
  361. package/dist/modules/workspace/service.js +20 -10
  362. package/dist/modules/workspace/service.js.map +1 -1
  363. package/dist/modules/workspace/tools.js +1 -1
  364. package/dist/modules/workspace/tools.js.map +1 -1
  365. package/dist/runtime/module.d.ts +63 -1
  366. package/dist/runtime/module.d.ts.map +1 -1
  367. package/dist/runtime/registry.d.ts.map +1 -1
  368. package/dist/runtime/registry.js +40 -2
  369. package/dist/runtime/registry.js.map +1 -1
  370. package/dist/testing/fixtures.d.ts.map +1 -1
  371. package/dist/testing/fixtures.js +1 -0
  372. package/dist/testing/fixtures.js.map +1 -1
  373. package/migrations/0037_drop_lists_consent_purpose_id.sql +2 -0
  374. package/migrations/0038_smart_white_queen.sql +2 -0
  375. package/migrations/0039_form_map_to_open.sql +1 -0
  376. package/migrations/0040_pipeline_converted_to.sql +20 -0
  377. package/migrations/0041_api_key_scopes.sql +1 -0
  378. package/migrations/0042_drop_workspace_identity.sql +2 -0
  379. package/migrations/0043_external_sign_in.sql +2 -0
  380. package/migrations/meta/0038_snapshot.json +6554 -0
  381. package/migrations/meta/_journal.json +49 -0
  382. package/package.json +2 -2
  383. package/src/app.ts +3 -0
  384. package/src/index.ts +13 -1
  385. package/src/lib/actor.ts +3 -1
  386. package/src/lib/apiKeyScopes.ts +213 -0
  387. package/src/lib/errors.ts +30 -0
  388. package/src/modules/activities/repository.ts +24 -0
  389. package/src/modules/agent-tasks/repository.ts +24 -0
  390. package/src/modules/api-keys/routes.ts +5 -0
  391. package/src/modules/api-keys/schema.ts +2 -0
  392. package/src/modules/api-keys/scopeMiddleware.ts +30 -0
  393. package/src/modules/api-keys/service.ts +36 -2
  394. package/src/modules/auth/credentials.ts +4 -0
  395. package/src/modules/auth/index.ts +25 -4
  396. package/src/modules/auth/repository.ts +2 -1
  397. package/src/modules/auth/routes.ts +2 -8
  398. package/src/modules/auth/schema.ts +12 -1
  399. package/src/modules/auth/service.ts +143 -6
  400. package/src/modules/auth/session.ts +14 -0
  401. package/src/modules/consent-purposes/index.ts +1 -1
  402. package/src/modules/consent-purposes/schema.ts +3 -3
  403. package/src/modules/consent-purposes/service.ts +7 -16
  404. package/src/modules/consent-purposes/starters.ts +1 -1
  405. package/src/modules/consent-purposes/tools.ts +1 -1
  406. package/src/modules/conversions/clearPointers.ts +81 -0
  407. package/src/modules/conversions/factory.ts +20 -0
  408. package/src/modules/conversions/fieldMap.ts +548 -0
  409. package/src/modules/conversions/index.ts +6 -0
  410. package/src/modules/conversions/mcp.ts +71 -0
  411. package/src/modules/conversions/repoint.ts +146 -0
  412. package/src/modules/conversions/routes.ts +68 -0
  413. package/src/modules/conversions/service.ts +310 -0
  414. package/src/modules/conversions/wire.ts +42 -0
  415. package/src/modules/deals/events.ts +9 -0
  416. package/src/modules/deals/index.ts +4 -2
  417. package/src/modules/deals/routes.ts +11 -1
  418. package/src/modules/deals/schema.ts +10 -2
  419. package/src/modules/deals/service.ts +3 -0
  420. package/src/modules/deals/tools.ts +9 -1
  421. package/src/modules/decisions/repository.ts +23 -1
  422. package/src/modules/enquiries/events.ts +8 -2
  423. package/src/modules/enquiries/index.ts +4 -2
  424. package/src/modules/enquiries/routes.ts +11 -13
  425. package/src/modules/enquiries/schema.ts +12 -3
  426. package/src/modules/enquiries/service.ts +3 -150
  427. package/src/modules/enquiries/tools.ts +9 -18
  428. package/src/modules/forms/applyMappedFields.ts +248 -0
  429. package/src/modules/forms/applySubmissionFields.ts +435 -0
  430. package/src/modules/forms/fields.ts +31 -7
  431. package/src/modules/forms/mapping.ts +20 -3
  432. package/src/modules/forms/repository.ts +0 -7
  433. package/src/modules/forms/routes.ts +1 -2
  434. package/src/modules/forms/schema.ts +0 -2
  435. package/src/modules/forms/service.ts +31 -4
  436. package/src/modules/forms/starters.ts +129 -0
  437. package/src/modules/forms/submission.ts +135 -69
  438. package/src/modules/import-export/customFieldCsv.ts +55 -0
  439. package/src/modules/import-export/customFieldImport.ts +111 -0
  440. package/src/modules/import-export/drafts.ts +151 -3
  441. package/src/modules/import-export/exportRows.ts +222 -68
  442. package/src/modules/import-export/plan.ts +321 -67
  443. package/src/modules/import-export/repository.ts +356 -14
  444. package/src/modules/import-export/routes.ts +8 -8
  445. package/src/modules/import-export/service.ts +208 -45
  446. package/src/modules/import-export/streams.ts +95 -13
  447. package/src/modules/import-export/tools.ts +14 -6
  448. package/src/modules/import-export/validation.ts +128 -0
  449. package/src/modules/import-export/writes.ts +559 -27
  450. package/src/modules/lists/repository.ts +0 -2
  451. package/src/modules/lists/routes.ts +0 -8
  452. package/src/modules/lists/schema.ts +0 -10
  453. package/src/modules/lists/service.ts +9 -107
  454. package/src/modules/lists/starters.ts +16 -0
  455. package/src/modules/mcp/protocol.ts +18 -0
  456. package/src/modules/notes/repository.ts +24 -0
  457. package/src/modules/opportunities/events.ts +9 -0
  458. package/src/modules/opportunities/index.ts +4 -2
  459. package/src/modules/opportunities/routes.ts +11 -1
  460. package/src/modules/opportunities/schema.ts +10 -2
  461. package/src/modules/opportunities/service.ts +3 -0
  462. package/src/modules/opportunities/tools.ts +9 -1
  463. package/src/modules/partnerships/events.ts +9 -0
  464. package/src/modules/partnerships/index.ts +4 -2
  465. package/src/modules/partnerships/routes.ts +11 -1
  466. package/src/modules/partnerships/schema.ts +10 -2
  467. package/src/modules/partnerships/service.ts +3 -0
  468. package/src/modules/partnerships/tools.ts +9 -1
  469. package/src/modules/people/personConsentWrites.ts +1 -1
  470. package/src/modules/people/schema.ts +1 -1
  471. package/src/modules/plans/repository.ts +24 -0
  472. package/src/modules/raises/events.ts +9 -0
  473. package/src/modules/raises/index.ts +4 -2
  474. package/src/modules/raises/routes.ts +11 -1
  475. package/src/modules/raises/schema.ts +10 -2
  476. package/src/modules/raises/service.ts +3 -0
  477. package/src/modules/raises/tools.ts +9 -1
  478. package/src/modules/workspace/routes.ts +0 -6
  479. package/src/modules/workspace/schema.ts +0 -2
  480. package/src/modules/workspace/seedStarterForms.ts +98 -0
  481. package/src/modules/workspace/service.ts +23 -15
  482. package/src/modules/workspace/tools.ts +1 -1
  483. package/src/runtime/module.ts +70 -1
  484. package/src/runtime/registry.ts +54 -0
  485. package/src/testing/fixtures.ts +1 -0
@@ -4,7 +4,10 @@ import {
4
4
  MAX_IMPORT_ROWS,
5
5
  OBJECT_COLUMNS,
6
6
  SYNC_IMPORT_ROWS,
7
+ customFieldObjectTypeForExport,
7
8
  findMatchKey,
9
+ knownImportColumnKeys,
10
+ pipelineKindForImport,
8
11
  requiredColumns,
9
12
  } from '@kelpie/schemas'
10
13
  import type {
@@ -13,6 +16,7 @@ import type {
13
16
  ImportCounts,
14
17
  ImportJobStatus,
15
18
  ImportObject,
19
+ ExportObject,
16
20
  ImportPreviewRow,
17
21
  ImportRowError,
18
22
  ImportSource,
@@ -27,14 +31,20 @@ import type { Logger } from '../../lib/logger.ts'
27
31
  import { normaliseDomain, normaliseEmail } from '../../lib/normalisation.ts'
28
32
  import type { BufferedEvents, Queryable, TransactionScope } from '../../runtime/transaction.ts'
29
33
  import type { ActivityRecorder } from '../activities/recorder.ts'
34
+ import { definitionsForObject } from '../custom-fields/repository.ts'
35
+ import { baseColumnKeySet } from './customFieldImport.ts'
30
36
  import { toEventActor } from '../../lib/actor.ts'
31
- import type { RecordObjectType } from '../../runtime/events.ts'
32
37
  import type { Actor } from '../auth/actor.ts'
33
38
  import { requireWorkspaceId } from '../auth/actor.ts'
34
39
  import '../companies/events.ts'
35
40
  import '../deals/events.ts'
41
+ import '../enquiries/events.ts'
42
+ import '../opportunities/events.ts'
43
+ import '../partnerships/events.ts'
36
44
  import '../people/events.ts'
37
45
  import '../positions/events.ts'
46
+ import '../raises/events.ts'
47
+ import '../custom-fields/events.ts'
38
48
  import './events.ts'
39
49
 
40
50
  /**
@@ -44,8 +54,10 @@ import './events.ts'
44
54
  */
45
55
  function emitImportedRecordCreated(
46
56
  events: BufferedEvents,
47
- objectType: RecordObjectType,
57
+ objectType: import('./writes.ts').ImportWrittenObjectType,
48
58
  recordId: string,
59
+ writeObject?: ImportObject,
60
+ draft?: { readonly objectType?: string; readonly key?: string },
49
61
  ): void {
50
62
  switch (objectType) {
51
63
  case 'person':
@@ -60,7 +72,27 @@ function emitImportedRecordCreated(
60
72
  case 'deal':
61
73
  events.emit('deals.deal.created', { type: 'deal', id: recordId }, {})
62
74
  return
63
- // The remaining `RecordObjectType` values are not produced by an import.
75
+ case 'opportunity':
76
+ events.emit('opportunities.opportunity.created', { type: 'opportunity', id: recordId }, {})
77
+ return
78
+ case 'enquiry':
79
+ events.emit('enquiries.enquiry.created', { type: 'enquiry', id: recordId }, {})
80
+ return
81
+ case 'partnership':
82
+ events.emit('partnerships.partnership.created', { type: 'partnership', id: recordId }, {})
83
+ return
84
+ case 'raise':
85
+ events.emit('raises.raise.created', { type: 'raise', id: recordId }, {})
86
+ return
87
+ case 'custom_field':
88
+ if (writeObject === 'custom_fields' && draft?.objectType !== undefined && draft.key !== undefined) {
89
+ events.emit(
90
+ 'custom_fields.field.created',
91
+ { type: 'custom_field', id: recordId },
92
+ { objectType: draft.objectType, key: draft.key },
93
+ )
94
+ }
95
+ return
64
96
  default:
65
97
  throw new Error(`import produced an unexpected object type: ${objectType}`)
66
98
  }
@@ -68,9 +100,10 @@ function emitImportedRecordCreated(
68
100
 
69
101
  function emitImportedRecordUpdated(
70
102
  events: BufferedEvents,
71
- objectType: RecordObjectType,
103
+ objectType: import('./writes.ts').ImportWrittenObjectType,
72
104
  recordId: string,
73
105
  changed: readonly string[],
106
+ draft?: { readonly objectType?: string; readonly key?: string },
74
107
  ): void {
75
108
  switch (objectType) {
76
109
  case 'person':
@@ -93,6 +126,27 @@ function emitImportedRecordUpdated(
93
126
  case 'deal':
94
127
  events.emit('deals.deal.updated', { type: 'deal', id: recordId }, { changed })
95
128
  return
129
+ case 'opportunity':
130
+ events.emit('opportunities.opportunity.updated', { type: 'opportunity', id: recordId }, { changed })
131
+ return
132
+ case 'enquiry':
133
+ events.emit('enquiries.enquiry.updated', { type: 'enquiry', id: recordId }, { changed })
134
+ return
135
+ case 'partnership':
136
+ events.emit('partnerships.partnership.updated', { type: 'partnership', id: recordId }, { changed })
137
+ return
138
+ case 'raise':
139
+ events.emit('raises.raise.updated', { type: 'raise', id: recordId }, { changed })
140
+ return
141
+ case 'custom_field':
142
+ if (draft?.objectType !== undefined && draft.key !== undefined) {
143
+ events.emit(
144
+ 'custom_fields.field.updated',
145
+ { type: 'custom_field', id: recordId },
146
+ { objectType: draft.objectType, key: draft.key, changed },
147
+ )
148
+ }
149
+ return
96
150
  default:
97
151
  throw new Error(`import produced an unexpected object type: ${objectType}`)
98
152
  }
@@ -184,8 +238,8 @@ export interface ImportExportService {
184
238
  commit(actor: Actor, id: string, csv: string): Promise<ImportJobView>
185
239
  deleteJob(actor: Actor, id: string): Promise<void>
186
240
  /** CSV lines for a whole object, a page of records at a time. */
187
- exportCsv(actor: Actor, object: ImportObject): AsyncGenerator<string>
188
- templateCsv(object: ImportObject): string
241
+ exportCsv(actor: Actor, object: ExportObject): AsyncGenerator<string>
242
+ templateCsv(actor: Actor, object: ExportObject): Promise<string>
189
243
  }
190
244
 
191
245
  const EMPTY_COUNTS: ImportCounts = { total: 0, create: 0, update: 0, skip: 0, error: 0 }
@@ -271,8 +325,9 @@ export function createImportExportService(
271
325
  matchKey: MatchKeyOption,
272
326
  columnMap: ImportColumnMap,
273
327
  headers: readonly string[],
328
+ customFieldKeys: readonly string[] = [],
274
329
  ): void {
275
- const known = new Set(OBJECT_COLUMNS[object].map((column) => column.key))
330
+ const known = new Set(knownImportColumnKeys(object, customFieldKeys))
276
331
  const present = new Set(headers)
277
332
  const problems = [
278
333
  ...Object.keys(columnMap)
@@ -340,6 +395,33 @@ export function createImportExportService(
340
395
  return matchKey.id === 'external_id'
341
396
  ? repository.findDealKeysByExternalId(db, workspaceId, column('external_id'))
342
397
  : repository.findDealKeysByCompany(db, workspaceId, domains)
398
+ case 'opportunities':
399
+ return matchKey.id === 'name'
400
+ ? repository.findOpportunityKeysByName(
401
+ db,
402
+ workspaceId,
403
+ column('name').map((name) => name.toLowerCase()),
404
+ )
405
+ : repository.findOpportunityKeysByCompany(db, workspaceId, domains)
406
+ case 'enquiries':
407
+ return matchKey.id === 'name'
408
+ ? repository.findEnquiryKeysByName(
409
+ db,
410
+ workspaceId,
411
+ column('name').map((name) => name.toLowerCase()),
412
+ )
413
+ : repository.findEnquiryKeysByCompany(db, workspaceId, domains)
414
+ case 'partnerships':
415
+ return repository.findPartnershipKeysByCompany(db, workspaceId, domains)
416
+ case 'raises':
417
+ return repository.findRaiseKeysByCompany(db, workspaceId, domains)
418
+ case 'custom_fields':
419
+ return repository.findCustomFieldDefinitionKeys(
420
+ db,
421
+ workspaceId,
422
+ column('object_type'),
423
+ column('key'),
424
+ )
343
425
  }
344
426
  })()
345
427
 
@@ -369,14 +451,14 @@ export function createImportExportService(
369
451
  ): Promise<ImportLookups> {
370
452
  const existing = await findExistingKeys(db, workspaceId, object, matchKey, rows)
371
453
 
372
- if (object === 'companies') {
454
+ if (object === 'companies' || object === 'custom_fields') {
373
455
  return {
374
456
  existing,
375
457
  personIdByEmail: new Map(),
376
458
  companyIdByDomain: new Map(),
377
459
  companyIdByName: new Map(),
378
460
  memberIdByEmail: new Map(),
379
- dealStageIdByName: new Map(),
461
+ stageIdByName: new Map(),
380
462
  }
381
463
  }
382
464
 
@@ -401,10 +483,11 @@ export function createImportExportService(
401
483
  ),
402
484
  companyIdByName: new Map(byName.map((row) => [row.name.toLowerCase(), row.id] as const)),
403
485
  memberIdByEmail: new Map(),
404
- dealStageIdByName: new Map(),
486
+ stageIdByName: new Map(),
405
487
  }
406
488
  }
407
489
 
490
+ const pipelineKind = pipelineKindForImport(object)
408
491
  const emails = distinct([
409
492
  ...rows.map((row) => normaliseEmail(row.mapped.person_email ?? '')),
410
493
  ...rows.flatMap((row) =>
@@ -428,46 +511,96 @@ export function createImportExportService(
428
511
  ),
429
512
  companyIdByName: new Map(),
430
513
  memberIdByEmail: new Map(),
431
- dealStageIdByName: new Map(),
514
+ stageIdByName: new Map(),
432
515
  }
433
516
  }
434
517
 
435
- const [members, stages] = await Promise.all([
436
- repository.listMemberEmails(db, workspaceId),
437
- repository.listDealStages(db, workspaceId),
438
- ])
518
+ if (pipelineKind !== null) {
519
+ const [members, stages] = await Promise.all([
520
+ repository.listMemberEmails(db, workspaceId),
521
+ repository.listPipelineStages(db, workspaceId, pipelineKind),
522
+ ])
523
+ const stagesByName = new Map<string, string>()
439
524
 
440
- // A stage answers to its slug and to its label. The slug is the stable one
441
- // an export writes; the label is what a person typed into the spreadsheet.
442
- const stagesByName = new Map<string, string>()
525
+ for (const stage of stages) {
526
+ stagesByName.set(stage.slug.toLowerCase(), stage.id)
527
+ stagesByName.set(stage.label.toLowerCase(), stage.id)
528
+ }
443
529
 
444
- for (const stage of stages) {
445
- stagesByName.set(stage.slug.toLowerCase(), stage.id)
446
- stagesByName.set(stage.label.toLowerCase(), stage.id)
530
+ return {
531
+ existing,
532
+ personIdByEmail: new Map(
533
+ peopleRows.flatMap((row) => (row.email === null ? [] : [[row.email, row.id] as const])),
534
+ ),
535
+ companyIdByDomain: new Map(
536
+ companyRows.flatMap((row) => (row.domain === null ? [] : [[row.domain, row.id] as const])),
537
+ ),
538
+ companyIdByName: new Map(),
539
+ memberIdByEmail: new Map(members.map((member) => [member.email.toLowerCase(), member.id])),
540
+ stageIdByName: stagesByName,
541
+ }
447
542
  }
448
543
 
449
- return {
450
- existing,
451
- personIdByEmail: new Map(
452
- peopleRows.flatMap((row) => (row.email === null ? [] : [[row.email, row.id] as const])),
453
- ),
454
- companyIdByDomain: new Map(
455
- companyRows.flatMap((row) => (row.domain === null ? [] : [[row.domain, row.id] as const])),
456
- ),
457
- companyIdByName: new Map(),
458
- memberIdByEmail: new Map(members.map((member) => [member.email.toLowerCase(), member.id])),
459
- dealStageIdByName: stagesByName,
544
+ throw new Error(`No lookup builder for import object ${object}`)
545
+ }
546
+
547
+ async function customFieldContext(
548
+ workspaceId: string,
549
+ object: ImportObject,
550
+ ): Promise<{
551
+ readonly definitions: Awaited<ReturnType<typeof definitionsForObject>>
552
+ readonly keys: readonly string[]
553
+ }> {
554
+ const objectType = customFieldObjectTypeForExport(object)
555
+
556
+ if (objectType === null) {
557
+ return { definitions: [], keys: [] }
460
558
  }
559
+
560
+ const definitions = await definitionsForObject(dependencies.db, workspaceId, objectType)
561
+
562
+ return { definitions, keys: definitions.map((definition) => definition.key) }
563
+ }
564
+
565
+ function augmentColumnMap(
566
+ _object: ImportObject,
567
+ headers: readonly string[],
568
+ columnMap: ImportColumnMap,
569
+ customFieldKeys: readonly string[],
570
+ ): ImportColumnMap {
571
+ const map = { ...columnMap }
572
+
573
+ for (const key of customFieldKeys) {
574
+ if (map[key] !== undefined) {
575
+ continue
576
+ }
577
+
578
+ const match = headers.find((header) => header.toLowerCase() === key.toLowerCase())
579
+
580
+ if (match !== undefined) {
581
+ map[key] = match
582
+ }
583
+ }
584
+
585
+ return map
461
586
  }
462
587
 
463
- function contextFor(job: ImportJobRecord, lookups: ImportLookups): PlanContext {
588
+ function contextFor(
589
+ job: ImportJobRecord,
590
+ lookups: ImportLookups,
591
+ customFieldDefinitions: Awaited<ReturnType<typeof definitionsForObject>>,
592
+ ): PlanContext {
593
+ const object = job.object as ImportObject
594
+
464
595
  return {
465
- object: job.object as ImportObject,
466
- matchKey: requireMatchKey(job.object as ImportObject, job.matchKey),
596
+ object,
597
+ matchKey: requireMatchKey(object, job.matchKey),
467
598
  conflictMode: job.conflictMode as ImportConflictMode,
468
599
  onMissingCompany: job.onMissingCompany as OnMissingCompany,
469
600
  consentPurposeId: job.consentPurposeId,
470
601
  lookups,
602
+ customFieldDefinitions,
603
+ baseColumnKeys: baseColumnKeySet(OBJECT_COLUMNS[object]),
471
604
  }
472
605
  }
473
606
 
@@ -581,14 +714,16 @@ export function createImportExportService(
581
714
  async function runDryRun(workspaceId: string, jobId: string, parsed: ParsedCsv): Promise<void> {
582
715
  const job = await requireJob(workspaceId, jobId)
583
716
  const { rows } = readFile(job, parsed)
717
+ const object = job.object as ImportObject
718
+ const { definitions } = await customFieldContext(workspaceId, object)
584
719
  const lookups = await buildLookups(
585
720
  dependencies.db,
586
721
  workspaceId,
587
- job.object as ImportObject,
588
- requireMatchKey(job.object as ImportObject, job.matchKey),
722
+ object,
723
+ requireMatchKey(object, job.matchKey),
589
724
  rows,
590
725
  )
591
- const planned = planRows(contextFor(job, lookups), rows)
726
+ const planned = planRows(contextFor(job, lookups, definitions), rows)
592
727
 
593
728
  await repository.updateJob(dependencies.db, workspaceId, jobId, {
594
729
  status: 'ready',
@@ -652,8 +787,9 @@ export function createImportExportService(
652
787
  // Resolved inside the transaction, against the rows this commit has
653
788
  // already written. That is what makes a file listing one company twice
654
789
  // create it once, and what lets an interrupted commit be re-run.
790
+ const { definitions } = await customFieldContext(workspaceId, object)
655
791
  const lookups = await buildLookups(tx, workspaceId, object, matchKey, [row])
656
- const plan = planRow(contextFor(job, lookups), mapped)
792
+ const plan = planRow(contextFor(job, lookups, definitions), mapped)
657
793
 
658
794
  const outcome: repository.RowOutcome = {
659
795
  rowNumber: line.number,
@@ -678,7 +814,13 @@ export function createImportExportService(
678
814
  )
679
815
 
680
816
  if (plan.action === 'create') {
681
- emitImportedRecordCreated(events, written.objectType, written.recordId)
817
+ emitImportedRecordCreated(
818
+ events,
819
+ written.objectType,
820
+ written.recordId,
821
+ object,
822
+ plan.write.object === 'custom_fields' ? plan.write.draft : undefined,
823
+ )
682
824
  } else if (written.changedFields.length > 0) {
683
825
  // An update that moved nothing publishes nothing. Re-running the same
684
826
  // file must not wake every consumer watching for a change.
@@ -687,6 +829,7 @@ export function createImportExportService(
687
829
  written.objectType,
688
830
  written.recordId,
689
831
  written.changedFields,
832
+ plan.write.object === 'custom_fields' ? plan.write.draft : undefined,
690
833
  )
691
834
  }
692
835
 
@@ -839,10 +982,21 @@ export function createImportExportService(
839
982
  }
840
983
 
841
984
  const matchKey = requireMatchKey(input.object, input.matchKeyId)
842
- const columnMap =
843
- input.columnMap ?? defaultColumnMap(input.source, input.object, parsed.headers)
985
+ const { keys: customFieldKeys } = await customFieldContext(workspaceId, input.object)
986
+ let columnMap =
987
+ input.columnMap ??
988
+ augmentColumnMap(
989
+ input.object,
990
+ parsed.headers,
991
+ defaultColumnMap(input.source, input.object, parsed.headers),
992
+ customFieldKeys,
993
+ )
994
+
995
+ if (input.columnMap !== undefined) {
996
+ columnMap = augmentColumnMap(input.object, parsed.headers, columnMap, customFieldKeys)
997
+ }
844
998
 
845
- requireUsableColumnMap(input.object, matchKey, columnMap, parsed.headers)
999
+ requireUsableColumnMap(input.object, matchKey, columnMap, parsed.headers, customFieldKeys)
846
1000
 
847
1001
  // Consent is a People-only feature. A purpose on any other object is
848
1002
  // refused up front; mapping the consent columns without one is refused
@@ -995,8 +1149,17 @@ export function createImportExportService(
995
1149
  return streamExport(dependencies.db, requireWorkspaceId(actor), object)
996
1150
  },
997
1151
 
998
- templateCsv(object) {
999
- return csvLine(templateHeadersFor(object))
1152
+ templateCsv(actor, object) {
1153
+ const workspaceId = requireWorkspaceId(actor)
1154
+ const objectType = customFieldObjectTypeForExport(object)
1155
+
1156
+ if (objectType === null) {
1157
+ return Promise.resolve(csvLine(templateHeadersFor(object)))
1158
+ }
1159
+
1160
+ return definitionsForObject(dependencies.db, workspaceId, objectType).then((definitions) =>
1161
+ csvLine(templateHeadersFor(object, definitions)),
1162
+ )
1000
1163
  },
1001
1164
  }
1002
1165
  }
@@ -1,14 +1,28 @@
1
- import type { ImportObject } from '@kelpie/schemas'
1
+ import { customFieldObjectTypeForExport } from '@kelpie/schemas'
2
+ import type { ExportObject } from '@kelpie/schemas'
2
3
 
3
4
  import type { Database } from '../../lib/database.ts'
5
+ import { definitionsForObject } from '../custom-fields/repository.ts'
6
+ import type { CustomFieldDefinitionRecord } from '../custom-fields/repository.ts'
4
7
  import { csvLine } from './csv.ts'
5
- import { companyCells, dealCells, headersFor, personCells, positionCells } from './exportRows.ts'
8
+ import {
9
+ companyCells,
10
+ customFieldDefinitionRowCells,
11
+ dealCells,
12
+ enquiryCells,
13
+ headersFor,
14
+ opportunityCells,
15
+ partnershipCells,
16
+ personCells,
17
+ positionCells,
18
+ raiseCells,
19
+ } from './exportRows.ts'
6
20
  import * as repository from './repository.ts'
7
21
 
8
22
  /**
9
23
  * A whole object as CSV, a page of records at a time.
10
24
  *
11
- * A generator rather than a string, because a workspace's deals do not have to
25
+ * A generator rather than a string, because a workspace's records do not have to
12
26
  * fit in memory to be downloaded and `import-export.md` says the endpoint
13
27
  * streams. The route pipes this straight into the response.
14
28
  *
@@ -49,39 +63,68 @@ async function* pageThrough<TRow extends { readonly id: string }>(
49
63
  }
50
64
  }
51
65
 
52
- /** The rows of one page, all their people in one query rather than one per deal. */
53
- async function dealPage(
66
+ async function linkedPersonEmailCells<T extends { readonly id: string }>(
54
67
  db: Database,
55
68
  workspaceId: string,
56
- rows: readonly repository.ExportDealRow[],
69
+ targetType: string,
70
+ rows: readonly T[],
71
+ toCells: (row: T, personEmails: readonly string[]) => readonly string[],
57
72
  ): Promise<readonly (readonly string[])[]> {
58
- const emails = await repository.readDealPersonEmails(
73
+ const emails = await repository.readLinkedPersonEmails(
59
74
  db,
60
75
  workspaceId,
76
+ targetType,
61
77
  rows.map((row) => row.id),
62
78
  )
63
79
 
64
- return rows.map((row) => dealCells(row, emails.get(row.id) ?? []))
80
+ return rows.map((row) => toCells(row, emails.get(row.id) ?? []))
81
+ }
82
+
83
+ async function customFieldDefinitionsFor(
84
+ db: Database,
85
+ workspaceId: string,
86
+ object: ExportObject,
87
+ ): Promise<readonly CustomFieldDefinitionRecord[]> {
88
+ const objectType = customFieldObjectTypeForExport(object)
89
+
90
+ if (objectType === null) {
91
+ return []
92
+ }
93
+
94
+ return definitionsForObject(db, workspaceId, objectType)
65
95
  }
66
96
 
67
97
  export async function* streamExport(
68
98
  db: Database,
69
99
  workspaceId: string,
70
- object: ImportObject,
100
+ object: ExportObject,
71
101
  ): AsyncGenerator<string> {
72
- yield csvLine(headersFor(object))
102
+ if (object === 'custom_fields') {
103
+ yield csvLine(headersFor(object))
104
+
105
+ yield* pageThrough({
106
+ read: (after) => repository.readCustomFieldDefinitions(db, workspaceId, after),
107
+ cells: (rows) => Promise.resolve(rows.map(customFieldDefinitionRowCells)),
108
+ })
109
+
110
+ return
111
+ }
112
+
113
+ const definitions = await customFieldDefinitionsFor(db, workspaceId, object)
114
+
115
+ yield csvLine(headersFor(object, definitions))
73
116
 
74
117
  switch (object) {
75
118
  case 'companies':
76
119
  yield* pageThrough({
77
120
  read: (after) => repository.readCompanies(db, workspaceId, after),
78
- cells: (rows) => Promise.resolve(rows.map(companyCells)),
121
+ cells: (rows) => Promise.resolve(rows.map((row) => companyCells(row, definitions))),
79
122
  })
80
123
  return
81
124
  case 'people':
82
125
  yield* pageThrough({
83
126
  read: (after) => repository.readPeople(db, workspaceId, after),
84
- cells: (rows) => Promise.resolve(rows.map(personCells)),
127
+ cells: (rows) => Promise.resolve(rows.map((row) => personCells(row, definitions))),
85
128
  })
86
129
  return
87
130
  case 'positions':
@@ -93,7 +136,46 @@ export async function* streamExport(
93
136
  case 'deals':
94
137
  yield* pageThrough({
95
138
  read: (after) => repository.readDeals(db, workspaceId, after),
96
- cells: (rows) => dealPage(db, workspaceId, rows),
139
+ cells: (rows) =>
140
+ linkedPersonEmailCells(db, workspaceId, 'deal', rows, (row, personEmails) =>
141
+ dealCells(row, personEmails, definitions),
142
+ ),
143
+ })
144
+ return
145
+ case 'opportunities':
146
+ yield* pageThrough({
147
+ read: (after) => repository.readOpportunities(db, workspaceId, after),
148
+ cells: (rows) =>
149
+ linkedPersonEmailCells(db, workspaceId, 'opportunity', rows, (row, personEmails) =>
150
+ opportunityCells(row, personEmails, definitions),
151
+ ),
152
+ })
153
+ return
154
+ case 'enquiries':
155
+ yield* pageThrough({
156
+ read: (after) => repository.readEnquiries(db, workspaceId, after),
157
+ cells: (rows) =>
158
+ linkedPersonEmailCells(db, workspaceId, 'enquiry', rows, (row, personEmails) =>
159
+ enquiryCells(row, personEmails, definitions),
160
+ ),
161
+ })
162
+ return
163
+ case 'partnerships':
164
+ yield* pageThrough({
165
+ read: (after) => repository.readPartnerships(db, workspaceId, after),
166
+ cells: (rows) =>
167
+ linkedPersonEmailCells(db, workspaceId, 'partnership', rows, (row, personEmails) =>
168
+ partnershipCells(row, personEmails, definitions),
169
+ ),
170
+ })
171
+ return
172
+ case 'raises':
173
+ yield* pageThrough({
174
+ read: (after) => repository.readRaises(db, workspaceId, after),
175
+ cells: (rows) =>
176
+ linkedPersonEmailCells(db, workspaceId, 'raise', rows, (row, personEmails) =>
177
+ raiseCells(row, personEmails, definitions),
178
+ ),
97
179
  })
98
180
  return
99
181
  }
@@ -1,4 +1,5 @@
1
1
  import {
2
+ EXPORT_OBJECTS,
2
3
  IMPORT_CONFLICT_MODES,
3
4
  IMPORT_OBJECTS,
4
5
  IMPORT_SOURCES,
@@ -34,9 +35,13 @@ import type { ImportExportService } from './service.ts'
34
35
  */
35
36
  export const MAX_INLINE_EXPORT_BYTES = 256 * 1024
36
37
 
37
- const objectArg = z
38
+ const exportObjectArg = z
39
+ .enum(EXPORT_OBJECTS)
40
+ .describe(`Which object to export. One of: ${EXPORT_OBJECTS.join(', ')}.`)
41
+
42
+ const importObjectArg = z
38
43
  .enum(IMPORT_OBJECTS)
39
- .describe(`Which object to move. One of: ${IMPORT_OBJECTS.join(', ')}.`)
44
+ .describe(`Which object to import. One of: ${IMPORT_OBJECTS.join(', ')}.`)
40
45
 
41
46
  /** `column_map` is a real object here. The multipart route takes it as a JSON string. */
42
47
  const columnMapArg = z
@@ -54,7 +59,7 @@ const csvArg = z
54
59
 
55
60
  const previewArgs = z.strictObject({
56
61
  source: z.enum(IMPORT_SOURCES).describe('Which export the file came out of.'),
57
- object: objectArg,
62
+ object: importObjectArg,
58
63
  csv: csvArg,
59
64
  conflict_mode: z
60
65
  .enum(IMPORT_CONFLICT_MODES)
@@ -112,7 +117,7 @@ export function registerImportExportTools(mcp: McpToolRegistry, service: ImportE
112
117
  description:
113
118
  'Export every record of one object as CSV text. Refuses an export too large to sit in ' +
114
119
  'a tool result, and names the download to use instead. Mirrors GET /v1/export/{object}.csv.',
115
- inputSchema: z.strictObject({ object: objectArg }),
120
+ inputSchema: z.strictObject({ object: exportObjectArg }),
116
121
  invoke: async ({ object }, actor) => ({
117
122
  object,
118
123
  csv: await collectCsv(service.exportCsv(actor, object)),
@@ -124,8 +129,11 @@ export function registerImportExportTools(mcp: McpToolRegistry, service: ImportE
124
129
  description:
125
130
  'The header row Kelpie expects for one object, with no records in it. Start a hand-built ' +
126
131
  'import from this. Mirrors GET /v1/export/templates/{object}.csv.',
127
- inputSchema: z.strictObject({ object: objectArg }),
128
- invoke: ({ object }) => Promise.resolve({ object, csv: service.templateCsv(object) }),
132
+ inputSchema: z.strictObject({ object: exportObjectArg }),
133
+ invoke: async ({ object }, actor) => ({
134
+ object,
135
+ csv: await service.templateCsv(actor, object),
136
+ }),
129
137
  })
130
138
 
131
139
  mcp.tool({