@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
@@ -24,6 +24,8 @@ import '../opportunities/events.ts'
24
24
  import * as partnershipRepository from '../partnerships/repository.ts'
25
25
  import '../partnerships/events.ts'
26
26
  import * as consentPurposesRepository from '../consent-purposes/repository.ts'
27
+ import * as customFieldsRepository from '../custom-fields/repository.ts'
28
+ import { CUSTOM_FIELD_OBJECT_TYPES } from '../custom-fields/schema.ts'
27
29
  import '../people/events.ts'
28
30
  import { upsertPersonConsent } from '../people/personConsentWrites.ts'
29
31
  import * as peopleRepository from '../people/repository.ts'
@@ -33,6 +35,8 @@ import * as pipelineRepository from '../pipelines/repository.ts'
33
35
  import '../positions/events.ts'
34
36
  import * as positionRepository from '../positions/repository.ts'
35
37
  import { targetExists } from '../recordTargets.ts'
38
+ import * as raiseRepository from '../raises/repository.ts'
39
+ import '../raises/events.ts'
36
40
  import * as workspaceRepository from '../workspace/repository.ts'
37
41
  import './events.ts'
38
42
  import {
@@ -42,6 +46,7 @@ import {
42
46
  expandNameTemplate,
43
47
  expectedCloseFrom,
44
48
  fillBlank,
49
+ fillPhonesBlank,
45
50
  findAnswerProblems,
46
51
  mapAnswers,
47
52
  mergeTags,
@@ -51,6 +56,15 @@ import {
51
56
  import type { Answers, ConsentGrant, SubmitIntent } from './mapping.ts'
52
57
  import * as repository from './repository.ts'
53
58
  import type { FormFieldRecord, FormRecord } from './repository.ts'
59
+ import {
60
+ applyCompanyMappedFields,
61
+ applyDealMappedFields,
62
+ applyEnquiryMappedFields,
63
+ applyOpportunityMappedFields,
64
+ applyPartnershipMappedFields,
65
+ applyPersonMappedFields,
66
+ applyRaiseMappedFields,
67
+ } from './applySubmissionFields.ts'
54
68
 
55
69
  /**
56
70
  * The public submit: `forms.md` rules 1 to 7, server-side.
@@ -290,6 +304,7 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
290
304
  const existing = await peopleRepository.findPersonByEmail(tx, workspaceId, intent.email)
291
305
 
292
306
  if (existing === undefined) {
307
+ const phones = fillPhonesBlank([], intent.personPhone)
293
308
  const created = await peopleRepository.insertPerson(tx, {
294
309
  id: dependencies.createId('person'),
295
310
  workspaceId,
@@ -298,10 +313,11 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
298
313
  lastName: intent.personLastName ?? null,
299
314
  email: intent.email,
300
315
  lastContactedAt: now,
316
+ ...(phones === undefined ? {} : { phones: [...phones] }),
301
317
  ...NEW_PERSON_DEFAULTS,
302
318
  })
303
319
 
304
- return { record: created, created: true, filled: [] }
320
+ return { record: created, created: true, filled: phones === undefined ? [] : ['phones'] }
305
321
  }
306
322
 
307
323
  // Each part fills its own blank. A stored first name is what the team has
@@ -310,10 +326,12 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
310
326
  const filledName = fillBlank(existing.name, intent.personName)
311
327
  const filledFirstName = fillBlank(existing.firstName, intent.personFirstName)
312
328
  const filledLastName = fillBlank(existing.lastName, intent.personLastName)
329
+ const filledPhones = fillPhonesBlank(existing.phones, intent.personPhone)
313
330
  const changes = {
314
331
  ...(filledName === undefined ? {} : { name: filledName }),
315
332
  ...(filledFirstName === undefined ? {} : { firstName: filledFirstName }),
316
333
  ...(filledLastName === undefined ? {} : { lastName: filledLastName }),
334
+ ...(filledPhones === undefined ? {} : { phones: [...filledPhones] }),
317
335
  }
318
336
  const updated = await peopleRepository.updatePerson(tx, workspaceId, existing.id, {
319
337
  ...changes,
@@ -847,7 +865,15 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
847
865
  const { workspaceId } = form
848
866
  const fields = await repository.listFields(dependencies.db, form.id)
849
867
  const intent = readAnswers(fields, answers)
868
+ const mapped = mapAnswers(fields, answers)
850
869
  const consentGrants = readConsentGrants(fields, answers)
870
+ const customFieldDefinitions = (
871
+ await Promise.all(
872
+ CUSTOM_FIELD_OBJECT_TYPES.map((objectType) =>
873
+ customFieldsRepository.definitionsForObject(dependencies.db, workspaceId, objectType),
874
+ ),
875
+ )
876
+ ).flat()
851
877
  const [formListRows, attachTargets, consentPurposesForGrants] = await Promise.all([
852
878
  repository.listFormLists(dependencies.db, form.id),
853
879
  repository.listAttachTargets(dependencies.db, form.id),
@@ -855,10 +881,36 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
855
881
  ])
856
882
 
857
883
  return dependencies.transaction(async ({ tx, events }) => {
884
+ const now = dependencies.now()
858
885
  // Core capture: atomic. A failure here fails the submit; every
859
886
  // post-action below runs under its own savepoint and logs.
860
- const person = await upsertPerson(tx, workspaceId, intent)
861
- const company = await upsertCompany(tx, workspaceId, intent)
887
+ const personUpserted = await upsertPerson(tx, workspaceId, intent)
888
+ const personRecord = await applyPersonMappedFields(
889
+ tx,
890
+ workspaceId,
891
+ personUpserted.record,
892
+ mapped,
893
+ customFieldDefinitions,
894
+ now,
895
+ )
896
+ const person = { ...personUpserted, record: personRecord }
897
+
898
+ const companyUpserted = await upsertCompany(tx, workspaceId, intent)
899
+ const companyRecord =
900
+ companyUpserted === undefined
901
+ ? undefined
902
+ : await applyCompanyMappedFields(
903
+ tx,
904
+ workspaceId,
905
+ companyUpserted.record,
906
+ mapped,
907
+ customFieldDefinitions,
908
+ now,
909
+ )
910
+ const company =
911
+ companyUpserted === undefined
912
+ ? undefined
913
+ : { ...companyUpserted, record: companyRecord ?? companyUpserted.record }
862
914
  const position =
863
915
  company === undefined || intent.positionTitle === undefined
864
916
  ? undefined
@@ -976,6 +1028,66 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
976
1028
  )) ?? null)
977
1029
  : null
978
1030
 
1031
+ if (dealId !== null) {
1032
+ const deal = await dealRepository.findDeal(tx, workspaceId, dealId)
1033
+
1034
+ if (deal !== undefined) {
1035
+ await applyDealMappedFields(
1036
+ tx,
1037
+ workspaceId,
1038
+ deal,
1039
+ mapped,
1040
+ customFieldDefinitions,
1041
+ now,
1042
+ )
1043
+ }
1044
+ }
1045
+
1046
+ if (opportunityId !== null) {
1047
+ const opportunity = await opportunityRepository.findOpportunity(tx, workspaceId, opportunityId)
1048
+
1049
+ if (opportunity !== undefined) {
1050
+ await applyOpportunityMappedFields(
1051
+ tx,
1052
+ workspaceId,
1053
+ opportunity,
1054
+ mapped,
1055
+ customFieldDefinitions,
1056
+ now,
1057
+ )
1058
+ }
1059
+ }
1060
+
1061
+ if (partnershipId !== null) {
1062
+ const partnership = await partnershipRepository.findPartnership(tx, workspaceId, partnershipId)
1063
+
1064
+ if (partnership !== undefined) {
1065
+ await applyPartnershipMappedFields(
1066
+ tx,
1067
+ workspaceId,
1068
+ partnership,
1069
+ mapped,
1070
+ customFieldDefinitions,
1071
+ now,
1072
+ )
1073
+ }
1074
+ }
1075
+
1076
+ if (enquiryId !== null) {
1077
+ const enquiry = await enquiryRepository.findEnquiry(tx, workspaceId, enquiryId)
1078
+
1079
+ if (enquiry !== undefined) {
1080
+ await applyEnquiryMappedFields(
1081
+ tx,
1082
+ workspaceId,
1083
+ enquiry,
1084
+ mapped,
1085
+ customFieldDefinitions,
1086
+ now,
1087
+ )
1088
+ }
1089
+ }
1090
+
979
1091
  // --- Tag merges ---
980
1092
 
981
1093
  if (form.personTags.length > 0) {
@@ -1030,30 +1142,8 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
1030
1142
 
1031
1143
  // --- List memberships ---
1032
1144
 
1033
- // Every purpose named by a person list on this form, so consent
1034
- // capture below needs no per-row round trip.
1035
- const listConsentPurposeIds = Array.from(
1036
- new Set(
1037
- formListRows
1038
- .map((row) => row.consentPurposeId)
1039
- .filter((id): id is string => id !== null),
1040
- ),
1041
- )
1042
- const listConsentPurposes =
1043
- listConsentPurposeIds.length === 0
1044
- ? new Map<string, { readonly slug: string; readonly label: string }>()
1045
- : new Map(
1046
- (
1047
- await consentPurposesRepository.listPurposesByIds(
1048
- tx,
1049
- workspaceId,
1050
- listConsentPurposeIds,
1051
- )
1052
- ).map((row) => [row.id, { slug: row.slug, label: row.label }]),
1053
- )
1054
-
1055
1145
  for (const row of formListRows) {
1056
- const inserted = await runAction<boolean>(
1146
+ await runAction<boolean>(
1057
1147
  tx,
1058
1148
  events,
1059
1149
  actionLog,
@@ -1096,49 +1186,6 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
1096
1186
  return { status: 'ok', detail: targetId, value: true }
1097
1187
  },
1098
1188
  )
1099
-
1100
- // Consent capture rides with the add — only on person lists, only
1101
- // when the list carries a purpose, and only when we actually added
1102
- // (or the person was already on it, since a returning submitter
1103
- // did the same thing again). A record already on the list has
1104
- // already been consented for its purpose; the upsert reflects
1105
- // that a fresh submit is fresh evidence.
1106
- if (
1107
- row.targetType === 'person' &&
1108
- row.consentPurposeId !== null &&
1109
- inserted !== null
1110
- ) {
1111
- const purpose = listConsentPurposes.get(row.consentPurposeId)
1112
- if (purpose !== undefined) {
1113
- await runAction<void>(
1114
- tx,
1115
- events,
1116
- actionLog,
1117
- `consent:${row.listId}`,
1118
- async (inner) => {
1119
- await upsertPersonConsent(
1120
- inner,
1121
- workspaceId,
1122
- person.record.id,
1123
- row.consentPurposeId as string,
1124
- purpose.slug,
1125
- purpose.label,
1126
- 'granted',
1127
- `list:${row.listId}`,
1128
- dependencies.now(),
1129
- )
1130
- await dependencies.recordActivity(inner, workspaceId, FORM_ACTOR, {
1131
- targetType: 'person',
1132
- targetId: person.record.id,
1133
- kind: 'updated',
1134
- action: `granted ${purpose.label} consent via ${form.name}`,
1135
- detail: `Added to list membership`,
1136
- })
1137
- return { status: 'ok', detail: purpose.slug }
1138
- },
1139
- )
1140
- }
1141
- }
1142
1189
  }
1143
1190
 
1144
1191
  // --- Attach the submitter to pre-existing pipeline records ---
@@ -1172,6 +1219,25 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
1172
1219
  )
1173
1220
  }
1174
1221
 
1222
+ for (const target of attachTargets) {
1223
+ if (target.targetType !== 'raise') {
1224
+ continue
1225
+ }
1226
+
1227
+ const raise = await raiseRepository.findRaise(tx, workspaceId, target.targetId)
1228
+
1229
+ if (raise !== undefined) {
1230
+ await applyRaiseMappedFields(
1231
+ tx,
1232
+ workspaceId,
1233
+ raise,
1234
+ mapped,
1235
+ customFieldDefinitions,
1236
+ now,
1237
+ )
1238
+ }
1239
+ }
1240
+
1175
1241
  // --- Persist submission + core activity + record events ---
1176
1242
 
1177
1243
  const submission = await repository.insertSubmission(tx, {
@@ -0,0 +1,55 @@
1
+ import type { CustomFieldValue } from '@kelpie/schemas'
2
+
3
+ import type { CustomFieldDefinitionRecord } from '../custom-fields/repository.ts'
4
+ import { centsToMoney } from './mapping.ts'
5
+
6
+ /** Definition keys in workspace sort order — the extra CSV columns on a record export. */
7
+ export function customFieldHeaderKeys(
8
+ definitions: readonly CustomFieldDefinitionRecord[],
9
+ ): readonly string[] {
10
+ return definitions.map((definition) => definition.key)
11
+ }
12
+
13
+ /** One custom field value as a single CSV cell. */
14
+ export function serializeCustomFieldValue(value: CustomFieldValue | undefined): string {
15
+ if (value === undefined) {
16
+ return ''
17
+ }
18
+
19
+ if (typeof value === 'string' || typeof value === 'number') {
20
+ return String(value)
21
+ }
22
+
23
+ if (typeof value === 'boolean') {
24
+ return value ? 'true' : 'false'
25
+ }
26
+
27
+ if (Array.isArray(value)) {
28
+ return value.join('|')
29
+ }
30
+
31
+ if (typeof value === 'object' && 'amountCents' in value && 'currency' in value) {
32
+ return `${centsToMoney(value.amountCents)}|${value.currency}`
33
+ }
34
+
35
+ return ''
36
+ }
37
+
38
+ export function customFieldCells(
39
+ values: Readonly<Record<string, CustomFieldValue>> | undefined,
40
+ keys: readonly string[],
41
+ ): readonly string[] {
42
+ return keys.map((key) => serializeCustomFieldValue(values?.[key]))
43
+ }
44
+
45
+ export function customFieldDefinitionCells(row: CustomFieldDefinitionRecord): readonly string[] {
46
+ return [
47
+ row.objectType,
48
+ row.key,
49
+ row.label,
50
+ row.type,
51
+ row.options.join('|'),
52
+ row.description,
53
+ String(row.sortOrder),
54
+ ]
55
+ }
@@ -0,0 +1,111 @@
1
+ import type { CustomFieldDefinitionRef, CustomFieldObjectType, CustomFieldType, CustomFieldWireValue } from '@kelpie/schemas'
2
+
3
+ import { parseCustomFieldAnswer } from '../forms/applyMappedFields.ts'
4
+ import type { CustomFieldDefinitionRecord } from '../custom-fields/repository.ts'
5
+ import { moneyToCents } from './mapping.ts'
6
+
7
+ /**
8
+ * Custom field columns on a record import: extract, parse, and validate keys.
9
+ *
10
+ * Extra CSV columns named by definition key round-trip with export. A blank cell
11
+ * says nothing about the field, the same additive rule every column follows.
12
+ */
13
+
14
+ /** Kelpie columns declared for an object, not including workspace definition keys. */
15
+ export function baseColumnKeySet(objectColumns: readonly { readonly key: string }[]): ReadonlySet<string> {
16
+ return new Set(objectColumns.map((column) => column.key))
17
+ }
18
+
19
+ /** Non-base, non-blank cells keyed by custom field definition key. */
20
+ export function extractCustomFieldRaw(
21
+ mapped: Readonly<Record<string, string>>,
22
+ baseKeys: ReadonlySet<string>,
23
+ ): Readonly<Record<string, string>> {
24
+ const custom: Record<string, string> = {}
25
+
26
+ for (const [key, value] of Object.entries(mapped)) {
27
+ if (baseKeys.has(key)) {
28
+ continue
29
+ }
30
+
31
+ if (value.trim().length === 0) {
32
+ continue
33
+ }
34
+
35
+ custom[key] = value
36
+ }
37
+
38
+ return custom
39
+ }
40
+
41
+ function parseCurrency(raw: string): CustomFieldWireValue | undefined {
42
+ const trimmed = raw.trim()
43
+
44
+ if (trimmed.length === 0) {
45
+ return undefined
46
+ }
47
+
48
+ const [amountPart, currencyPart] = trimmed.split('|')
49
+ const currency = (currencyPart ?? 'USD').trim().toUpperCase()
50
+
51
+ if (!/^[A-Z]{3}$/u.test(currency)) {
52
+ return undefined
53
+ }
54
+
55
+ const cents = moneyToCents(amountPart)
56
+
57
+ if (cents === undefined || cents === null) {
58
+ return undefined
59
+ }
60
+
61
+ return { amount_cents: cents, currency }
62
+ }
63
+
64
+ /** Parses one inbound custom-field cell into a wire value for the validator. */
65
+ export function parseCustomFieldWireValue(
66
+ definition: CustomFieldDefinitionRecord,
67
+ raw: string,
68
+ ): CustomFieldWireValue | undefined {
69
+ if (definition.type === 'currency') {
70
+ return parseCurrency(raw)
71
+ }
72
+
73
+ const ref: CustomFieldDefinitionRef = {
74
+ objectType: definition.objectType as CustomFieldObjectType,
75
+ key: definition.key,
76
+ label: definition.label,
77
+ type: definition.type as CustomFieldType,
78
+ }
79
+ const parsed = parseCustomFieldAnswer(ref, raw)
80
+
81
+ if (typeof parsed === 'string' && parsed.trim().length === 0) {
82
+ return undefined
83
+ }
84
+
85
+ return parsed as CustomFieldWireValue
86
+ }
87
+
88
+ /** Builds the wire map to pass to `createCustomFieldValues`. Unknown keys are omitted. */
89
+ export function customFieldWireValues(
90
+ raw: Readonly<Record<string, string>>,
91
+ definitions: readonly CustomFieldDefinitionRecord[],
92
+ ): Readonly<Record<string, CustomFieldWireValue>> {
93
+ const byKey = new Map(definitions.map((definition) => [definition.key, definition]))
94
+ const out: Record<string, CustomFieldWireValue> = {}
95
+
96
+ for (const [key, value] of Object.entries(raw)) {
97
+ const definition = byKey.get(key)
98
+
99
+ if (definition === undefined) {
100
+ continue
101
+ }
102
+
103
+ const parsed = parseCustomFieldWireValue(definition, value)
104
+
105
+ if (parsed !== undefined) {
106
+ out[key] = parsed
107
+ }
108
+ }
109
+
110
+ return out
111
+ }
@@ -9,6 +9,8 @@ import {
9
9
  composeName,
10
10
  } from '@kelpie/schemas'
11
11
 
12
+ import type { CustomFieldWireValue } from '@kelpie/schemas'
13
+
12
14
  import { normaliseDomain, normaliseEmail } from '../../lib/normalisation.ts'
13
15
  import { moneyToCents, splitList } from './mapping.ts'
14
16
  import { canonicalEnum } from './validation.ts'
@@ -40,6 +42,7 @@ export interface CompanyDraft {
40
42
  readonly icpFit?: string
41
43
  readonly summary?: string
42
44
  readonly tags?: readonly string[]
45
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
43
46
  }
44
47
 
45
48
  export interface PersonDraft {
@@ -57,6 +60,7 @@ export interface PersonDraft {
57
60
  readonly relationship?: string
58
61
  readonly summary?: string
59
62
  readonly tags?: readonly string[]
63
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
60
64
  }
61
65
 
62
66
  /** The deal columns a row carries directly. Company, stage, owner and people are resolved. */
@@ -70,6 +74,57 @@ export interface DealFieldsDraft {
70
74
  readonly summary?: string
71
75
  readonly tags?: readonly string[]
72
76
  readonly externalId?: string
77
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
78
+ }
79
+
80
+ export interface OpportunityFieldsDraft {
81
+ readonly name?: string
82
+ readonly kind?: string
83
+ readonly expectedClose?: string
84
+ readonly summary?: string
85
+ readonly tags?: readonly string[]
86
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
87
+ }
88
+
89
+ export interface EnquiryFieldsDraft {
90
+ readonly name?: string
91
+ readonly source?: string
92
+ readonly summary?: string
93
+ readonly tags?: readonly string[]
94
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
95
+ }
96
+
97
+ export interface PartnershipFieldsDraft {
98
+ readonly name?: string
99
+ readonly kind?: string
100
+ readonly nextTouchpoint?: string
101
+ readonly goals?: string
102
+ readonly successLooksLike?: string
103
+ readonly summary?: string
104
+ readonly tags?: readonly string[]
105
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
106
+ }
107
+
108
+ export interface RaiseFieldsDraft {
109
+ readonly name?: string
110
+ readonly checkSizeCents?: number | null
111
+ readonly currency?: string
112
+ readonly thesisFit?: string
113
+ readonly passReason?: string
114
+ readonly expectedClose?: string
115
+ readonly summary?: string
116
+ readonly tags?: readonly string[]
117
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue>>
118
+ }
119
+
120
+ export interface CustomFieldDefinitionDraft {
121
+ readonly objectType?: string
122
+ readonly key?: string
123
+ readonly label?: string
124
+ readonly type?: string
125
+ readonly options?: readonly string[]
126
+ readonly description?: string
127
+ readonly sortOrder?: number
73
128
  }
74
129
 
75
130
  /**
@@ -143,7 +198,10 @@ function present<T extends object>(draft: Supplied<T>): T {
143
198
  return Object.fromEntries(Object.entries(draft).filter(([, value]) => value !== undefined)) as T
144
199
  }
145
200
 
146
- export function companyDraft(mapped: Readonly<Record<string, string>>): CompanyDraft {
201
+ export function companyDraft(
202
+ mapped: Readonly<Record<string, string>>,
203
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
204
+ ): CompanyDraft {
147
205
  const domain = text(mapped, 'domain')
148
206
 
149
207
  return present<CompanyDraft>({
@@ -159,6 +217,7 @@ export function companyDraft(mapped: Readonly<Record<string, string>>): CompanyD
159
217
  icpFit: enumeration(mapped, 'icp_fit', ICP_FITS),
160
218
  summary: text(mapped, 'summary'),
161
219
  tags: list(mapped, 'tags'),
220
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
162
221
  })
163
222
  }
164
223
 
@@ -168,7 +227,10 @@ export function companyDraft(mapped: Readonly<Record<string, string>>): CompanyD
168
227
  * blank, and never the other way round: a `name` cell is never split to fill
169
228
  * `first_name`, since a guessed part is stored exactly like one somebody typed.
170
229
  */
171
- export function personDraft(mapped: Readonly<Record<string, string>>): PersonDraft {
230
+ export function personDraft(
231
+ mapped: Readonly<Record<string, string>>,
232
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
233
+ ): PersonDraft {
172
234
  const email = text(mapped, 'email')
173
235
  const firstName = text(mapped, 'first_name')
174
236
  const lastName = text(mapped, 'last_name')
@@ -190,6 +252,7 @@ export function personDraft(mapped: Readonly<Record<string, string>>): PersonDra
190
252
  relationship: enumeration(mapped, 'relationship', RELATIONSHIP_LEVELS),
191
253
  summary: text(mapped, 'summary'),
192
254
  tags: list(mapped, 'tags'),
255
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
193
256
  })
194
257
  }
195
258
 
@@ -217,6 +280,7 @@ export function affiliationCompanyDraft(mapped: Readonly<Record<string, string>>
217
280
  icpFit: undefined,
218
281
  summary: undefined,
219
282
  tags: undefined,
283
+ customFields: undefined,
220
284
  })
221
285
  }
222
286
 
@@ -224,7 +288,10 @@ export function affiliationCompanyDraft(mapped: Readonly<Record<string, string>>
224
288
  * `value` is required, so `moneyToCents` has already been checked by
225
289
  * `validateRow` and cannot be undefined here.
226
290
  */
227
- export function dealFieldsDraft(mapped: Readonly<Record<string, string>>): DealFieldsDraft {
291
+ export function dealFieldsDraft(
292
+ mapped: Readonly<Record<string, string>>,
293
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
294
+ ): DealFieldsDraft {
228
295
  const cents = moneyToCents(mapped.value)
229
296
 
230
297
  return present<DealFieldsDraft>({
@@ -237,5 +304,86 @@ export function dealFieldsDraft(mapped: Readonly<Record<string, string>>): DealF
237
304
  summary: text(mapped, 'summary'),
238
305
  tags: list(mapped, 'tags'),
239
306
  externalId: text(mapped, 'external_id'),
307
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
308
+ })
309
+ }
310
+
311
+ export function opportunityFieldsDraft(
312
+ mapped: Readonly<Record<string, string>>,
313
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
314
+ ): OpportunityFieldsDraft {
315
+ return present<OpportunityFieldsDraft>({
316
+ name: text(mapped, 'name'),
317
+ kind: text(mapped, 'kind'),
318
+ expectedClose: text(mapped, 'expected_close'),
319
+ summary: text(mapped, 'summary'),
320
+ tags: list(mapped, 'tags'),
321
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
322
+ })
323
+ }
324
+
325
+ export function enquiryFieldsDraft(
326
+ mapped: Readonly<Record<string, string>>,
327
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
328
+ ): EnquiryFieldsDraft {
329
+ return present<EnquiryFieldsDraft>({
330
+ name: text(mapped, 'name'),
331
+ source: text(mapped, 'source'),
332
+ summary: text(mapped, 'summary'),
333
+ tags: list(mapped, 'tags'),
334
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
335
+ })
336
+ }
337
+
338
+ export function partnershipFieldsDraft(
339
+ mapped: Readonly<Record<string, string>>,
340
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
341
+ ): PartnershipFieldsDraft {
342
+ return present<PartnershipFieldsDraft>({
343
+ name: text(mapped, 'name'),
344
+ kind: text(mapped, 'kind'),
345
+ nextTouchpoint: text(mapped, 'next_touchpoint'),
346
+ goals: text(mapped, 'goals'),
347
+ successLooksLike: text(mapped, 'success_looks_like'),
348
+ summary: text(mapped, 'summary'),
349
+ tags: list(mapped, 'tags'),
350
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
351
+ })
352
+ }
353
+
354
+ export function raiseFieldsDraft(
355
+ mapped: Readonly<Record<string, string>>,
356
+ customFields: Readonly<Record<string, CustomFieldWireValue>> = {},
357
+ ): RaiseFieldsDraft {
358
+ const cents = moneyToCents(mapped.check_size)
359
+
360
+ return present<RaiseFieldsDraft>({
361
+ name: text(mapped, 'name'),
362
+ checkSizeCents: cents === undefined ? undefined : cents,
363
+ currency: text(mapped, 'currency'),
364
+ thesisFit: text(mapped, 'thesis_fit'),
365
+ passReason: text(mapped, 'pass_reason'),
366
+ expectedClose: text(mapped, 'expected_close'),
367
+ summary: text(mapped, 'summary'),
368
+ tags: list(mapped, 'tags'),
369
+ customFields: Object.keys(customFields).length === 0 ? undefined : customFields,
370
+ })
371
+ }
372
+
373
+ export function customFieldDefinitionDraft(
374
+ mapped: Readonly<Record<string, string>>,
375
+ ): CustomFieldDefinitionDraft {
376
+ const sortOrderRaw = text(mapped, 'sort_order')
377
+ const sortOrder =
378
+ sortOrderRaw === undefined ? undefined : Number.parseInt(sortOrderRaw, 10)
379
+
380
+ return present<CustomFieldDefinitionDraft>({
381
+ objectType: text(mapped, 'object_type'),
382
+ key: text(mapped, 'key'),
383
+ label: text(mapped, 'label'),
384
+ type: text(mapped, 'type'),
385
+ options: list(mapped, 'options'),
386
+ description: text(mapped, 'description'),
387
+ sortOrder: sortOrder !== undefined && Number.isInteger(sortOrder) ? sortOrder : undefined,
240
388
  })
241
389
  }