@kelpie/server 0.8.0 → 0.9.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 (584) hide show
  1. package/dist/lib/ids.d.ts +11 -0
  2. package/dist/lib/ids.d.ts.map +1 -1
  3. package/dist/lib/ids.js +11 -0
  4. package/dist/lib/ids.js.map +1 -1
  5. package/dist/modules/activities/repository.d.ts.map +1 -1
  6. package/dist/modules/activities/repository.js +19 -20
  7. package/dist/modules/activities/repository.js.map +1 -1
  8. package/dist/modules/activities/wording.d.ts +12 -0
  9. package/dist/modules/activities/wording.d.ts.map +1 -1
  10. package/dist/modules/activities/wording.js +16 -0
  11. package/dist/modules/activities/wording.js.map +1 -1
  12. package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
  13. package/dist/modules/agent-tasks/catalog.js +62 -0
  14. package/dist/modules/agent-tasks/catalog.js.map +1 -1
  15. package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
  16. package/dist/modules/agent-tasks/resolve.js +42 -9
  17. package/dist/modules/agent-tasks/resolve.js.map +1 -1
  18. package/dist/modules/agent-tasks/routes.d.ts +2 -0
  19. package/dist/modules/agent-tasks/routes.d.ts.map +1 -1
  20. package/dist/modules/attachedRecords.d.ts +6 -1
  21. package/dist/modules/attachedRecords.d.ts.map +1 -1
  22. package/dist/modules/attachedRecords.js +15 -1
  23. package/dist/modules/attachedRecords.js.map +1 -1
  24. package/dist/modules/companies/index.d.ts.map +1 -1
  25. package/dist/modules/companies/index.js +3 -1
  26. package/dist/modules/companies/index.js.map +1 -1
  27. package/dist/modules/companies/routes.d.ts +14 -0
  28. package/dist/modules/companies/routes.d.ts.map +1 -1
  29. package/dist/modules/companies/routes.js +7 -0
  30. package/dist/modules/companies/routes.js.map +1 -1
  31. package/dist/modules/companies/schema.d.ts +20 -0
  32. package/dist/modules/companies/schema.d.ts.map +1 -1
  33. package/dist/modules/companies/schema.js +6 -1
  34. package/dist/modules/companies/schema.js.map +1 -1
  35. package/dist/modules/companies/service.d.ts +5 -0
  36. package/dist/modules/companies/service.d.ts.map +1 -1
  37. package/dist/modules/companies/service.js +24 -12
  38. package/dist/modules/companies/service.js.map +1 -1
  39. package/dist/modules/consent-purposes/capabilities.d.ts +7 -0
  40. package/dist/modules/consent-purposes/capabilities.d.ts.map +1 -0
  41. package/dist/modules/consent-purposes/capabilities.js +10 -0
  42. package/dist/modules/consent-purposes/capabilities.js.map +1 -0
  43. package/dist/modules/consent-purposes/events.d.ts +38 -0
  44. package/dist/modules/consent-purposes/events.d.ts.map +1 -0
  45. package/dist/modules/consent-purposes/events.js +17 -0
  46. package/dist/modules/consent-purposes/events.js.map +1 -0
  47. package/dist/modules/consent-purposes/index.d.ts +13 -0
  48. package/dist/modules/consent-purposes/index.d.ts.map +1 -0
  49. package/dist/modules/consent-purposes/index.js +41 -0
  50. package/dist/modules/consent-purposes/index.js.map +1 -0
  51. package/dist/modules/consent-purposes/repository.d.ts +21 -0
  52. package/dist/modules/consent-purposes/repository.d.ts.map +1 -0
  53. package/dist/modules/consent-purposes/repository.js +98 -0
  54. package/dist/modules/consent-purposes/repository.js.map +1 -0
  55. package/dist/modules/consent-purposes/routes.d.ts +39 -0
  56. package/dist/modules/consent-purposes/routes.d.ts.map +1 -0
  57. package/dist/modules/consent-purposes/routes.js +79 -0
  58. package/dist/modules/consent-purposes/routes.js.map +1 -0
  59. package/dist/modules/consent-purposes/schema.d.ts +175 -0
  60. package/dist/modules/consent-purposes/schema.d.ts.map +1 -0
  61. package/dist/modules/consent-purposes/schema.js +35 -0
  62. package/dist/modules/consent-purposes/schema.js.map +1 -0
  63. package/dist/modules/consent-purposes/service.d.ts +50 -0
  64. package/dist/modules/consent-purposes/service.d.ts.map +1 -0
  65. package/dist/modules/consent-purposes/service.js +263 -0
  66. package/dist/modules/consent-purposes/service.js.map +1 -0
  67. package/dist/modules/consent-purposes/starters.d.ts +17 -0
  68. package/dist/modules/consent-purposes/starters.d.ts.map +1 -0
  69. package/dist/modules/consent-purposes/starters.js +15 -0
  70. package/dist/modules/consent-purposes/starters.js.map +1 -0
  71. package/dist/modules/consent-purposes/tools.d.ts +4 -0
  72. package/dist/modules/consent-purposes/tools.d.ts.map +1 -0
  73. package/dist/modules/consent-purposes/tools.js +29 -0
  74. package/dist/modules/consent-purposes/tools.js.map +1 -0
  75. package/dist/modules/core.d.ts.map +1 -1
  76. package/dist/modules/core.js +10 -0
  77. package/dist/modules/core.js.map +1 -1
  78. package/dist/modules/custom-fields/capabilities.d.ts +12 -0
  79. package/dist/modules/custom-fields/capabilities.d.ts.map +1 -0
  80. package/dist/modules/custom-fields/capabilities.js +15 -0
  81. package/dist/modules/custom-fields/capabilities.js.map +1 -0
  82. package/dist/modules/custom-fields/events.d.ts +49 -0
  83. package/dist/modules/custom-fields/events.d.ts.map +1 -0
  84. package/dist/modules/custom-fields/events.js +25 -0
  85. package/dist/modules/custom-fields/events.js.map +1 -0
  86. package/dist/modules/custom-fields/index.d.ts +19 -0
  87. package/dist/modules/custom-fields/index.d.ts.map +1 -0
  88. package/dist/modules/custom-fields/index.js +46 -0
  89. package/dist/modules/custom-fields/index.js.map +1 -0
  90. package/dist/modules/custom-fields/repository.d.ts +37 -0
  91. package/dist/modules/custom-fields/repository.d.ts.map +1 -0
  92. package/dist/modules/custom-fields/repository.js +144 -0
  93. package/dist/modules/custom-fields/repository.js.map +1 -0
  94. package/dist/modules/custom-fields/routes.d.ts +44 -0
  95. package/dist/modules/custom-fields/routes.d.ts.map +1 -0
  96. package/dist/modules/custom-fields/routes.js +103 -0
  97. package/dist/modules/custom-fields/routes.js.map +1 -0
  98. package/dist/modules/custom-fields/schema.d.ts +215 -0
  99. package/dist/modules/custom-fields/schema.d.ts.map +1 -0
  100. package/dist/modules/custom-fields/schema.js +43 -0
  101. package/dist/modules/custom-fields/schema.js.map +1 -0
  102. package/dist/modules/custom-fields/service.d.ts +57 -0
  103. package/dist/modules/custom-fields/service.d.ts.map +1 -0
  104. package/dist/modules/custom-fields/service.js +273 -0
  105. package/dist/modules/custom-fields/service.js.map +1 -0
  106. package/dist/modules/custom-fields/tools.d.ts +4 -0
  107. package/dist/modules/custom-fields/tools.d.ts.map +1 -0
  108. package/dist/modules/custom-fields/tools.js +38 -0
  109. package/dist/modules/custom-fields/tools.js.map +1 -0
  110. package/dist/modules/custom-fields/values.d.ts +49 -0
  111. package/dist/modules/custom-fields/values.d.ts.map +1 -0
  112. package/dist/modules/custom-fields/values.js +249 -0
  113. package/dist/modules/custom-fields/values.js.map +1 -0
  114. package/dist/modules/custom-fields/wire.d.ts +12 -0
  115. package/dist/modules/custom-fields/wire.d.ts.map +1 -0
  116. package/dist/modules/custom-fields/wire.js +30 -0
  117. package/dist/modules/custom-fields/wire.js.map +1 -0
  118. package/dist/modules/dashboard/repository.d.ts.map +1 -1
  119. package/dist/modules/dashboard/repository.js +4 -3
  120. package/dist/modules/dashboard/repository.js.map +1 -1
  121. package/dist/modules/deals/index.d.ts +2 -1
  122. package/dist/modules/deals/index.d.ts.map +1 -1
  123. package/dist/modules/deals/index.js +5 -2
  124. package/dist/modules/deals/index.js.map +1 -1
  125. package/dist/modules/deals/repository.d.ts +0 -16
  126. package/dist/modules/deals/repository.d.ts.map +1 -1
  127. package/dist/modules/deals/repository.js +6 -76
  128. package/dist/modules/deals/repository.js.map +1 -1
  129. package/dist/modules/deals/routes.d.ts +14 -0
  130. package/dist/modules/deals/routes.d.ts.map +1 -1
  131. package/dist/modules/deals/routes.js +7 -0
  132. package/dist/modules/deals/routes.js.map +1 -1
  133. package/dist/modules/deals/schema.d.ts +20 -42
  134. package/dist/modules/deals/schema.d.ts.map +1 -1
  135. package/dist/modules/deals/schema.js +6 -11
  136. package/dist/modules/deals/schema.js.map +1 -1
  137. package/dist/modules/deals/service.d.ts +13 -2
  138. package/dist/modules/deals/service.d.ts.map +1 -1
  139. package/dist/modules/deals/service.js +43 -20
  140. package/dist/modules/deals/service.js.map +1 -1
  141. package/dist/modules/decisions/repository.d.ts.map +1 -1
  142. package/dist/modules/decisions/repository.js +2 -0
  143. package/dist/modules/decisions/repository.js.map +1 -1
  144. package/dist/modules/decisions/routes.d.ts +1 -0
  145. package/dist/modules/decisions/routes.d.ts.map +1 -1
  146. package/dist/modules/enquiries/events.d.ts +44 -0
  147. package/dist/modules/enquiries/events.d.ts.map +1 -0
  148. package/dist/modules/enquiries/events.js +19 -0
  149. package/dist/modules/enquiries/events.js.map +1 -0
  150. package/dist/modules/enquiries/index.d.ts +13 -0
  151. package/dist/modules/enquiries/index.d.ts.map +1 -0
  152. package/dist/modules/enquiries/index.js +44 -0
  153. package/dist/modules/enquiries/index.js.map +1 -0
  154. package/dist/modules/enquiries/repository.d.ts +30 -0
  155. package/dist/modules/enquiries/repository.d.ts.map +1 -0
  156. package/dist/modules/enquiries/repository.js +94 -0
  157. package/dist/modules/enquiries/repository.js.map +1 -0
  158. package/dist/modules/enquiries/routes.d.ts +52 -0
  159. package/dist/modules/enquiries/routes.d.ts.map +1 -0
  160. package/dist/modules/enquiries/routes.js +127 -0
  161. package/dist/modules/enquiries/routes.js.map +1 -0
  162. package/dist/modules/enquiries/schema.d.ts +290 -0
  163. package/dist/modules/enquiries/schema.d.ts.map +1 -0
  164. package/dist/modules/enquiries/schema.js +52 -0
  165. package/dist/modules/enquiries/schema.js.map +1 -0
  166. package/dist/modules/enquiries/service.d.ts +85 -0
  167. package/dist/modules/enquiries/service.d.ts.map +1 -0
  168. package/dist/modules/enquiries/service.js +370 -0
  169. package/dist/modules/enquiries/service.js.map +1 -0
  170. package/dist/modules/enquiries/tools.d.ts +4 -0
  171. package/dist/modules/enquiries/tools.d.ts.map +1 -0
  172. package/dist/modules/enquiries/tools.js +50 -0
  173. package/dist/modules/enquiries/tools.js.map +1 -0
  174. package/dist/modules/eventCatalogs.d.ts +3 -0
  175. package/dist/modules/eventCatalogs.d.ts.map +1 -1
  176. package/dist/modules/eventCatalogs.js +3 -0
  177. package/dist/modules/eventCatalogs.js.map +1 -1
  178. package/dist/modules/forms/embed.d.ts +20 -6
  179. package/dist/modules/forms/embed.d.ts.map +1 -1
  180. package/dist/modules/forms/embed.js +359 -43
  181. package/dist/modules/forms/embed.js.map +1 -1
  182. package/dist/modules/forms/events.d.ts +20 -7
  183. package/dist/modules/forms/events.d.ts.map +1 -1
  184. package/dist/modules/forms/events.js +20 -2
  185. package/dist/modules/forms/events.js.map +1 -1
  186. package/dist/modules/forms/fields.d.ts +14 -1
  187. package/dist/modules/forms/fields.d.ts.map +1 -1
  188. package/dist/modules/forms/fields.js +87 -3
  189. package/dist/modules/forms/fields.js.map +1 -1
  190. package/dist/modules/forms/index.d.ts.map +1 -1
  191. package/dist/modules/forms/index.js +12 -1
  192. package/dist/modules/forms/index.js.map +1 -1
  193. package/dist/modules/forms/mapping.d.ts +62 -5
  194. package/dist/modules/forms/mapping.d.ts.map +1 -1
  195. package/dist/modules/forms/mapping.js +139 -5
  196. package/dist/modules/forms/mapping.js.map +1 -1
  197. package/dist/modules/forms/publicRoutes.d.ts.map +1 -1
  198. package/dist/modules/forms/publicRoutes.js +29 -1
  199. package/dist/modules/forms/publicRoutes.js.map +1 -1
  200. package/dist/modules/forms/repository.d.ts +31 -0
  201. package/dist/modules/forms/repository.d.ts.map +1 -1
  202. package/dist/modules/forms/repository.js +90 -1
  203. package/dist/modules/forms/repository.js.map +1 -1
  204. package/dist/modules/forms/routes.d.ts +83 -1
  205. package/dist/modules/forms/routes.d.ts.map +1 -1
  206. package/dist/modules/forms/routes.js +185 -2
  207. package/dist/modules/forms/routes.js.map +1 -1
  208. package/dist/modules/forms/schema.d.ts +672 -1
  209. package/dist/modules/forms/schema.d.ts.map +1 -1
  210. package/dist/modules/forms/schema.js +146 -3
  211. package/dist/modules/forms/schema.js.map +1 -1
  212. package/dist/modules/forms/service.d.ts +54 -1
  213. package/dist/modules/forms/service.d.ts.map +1 -1
  214. package/dist/modules/forms/service.js +338 -28
  215. package/dist/modules/forms/service.js.map +1 -1
  216. package/dist/modules/forms/submission.d.ts +15 -0
  217. package/dist/modules/forms/submission.d.ts.map +1 -1
  218. package/dist/modules/forms/submission.js +418 -40
  219. package/dist/modules/forms/submission.js.map +1 -1
  220. package/dist/modules/import-export/drafts.d.ts +10 -0
  221. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  222. package/dist/modules/import-export/drafts.js +16 -2
  223. package/dist/modules/import-export/drafts.js.map +1 -1
  224. package/dist/modules/import-export/exportRows.d.ts +7 -4
  225. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  226. package/dist/modules/import-export/exportRows.js +20 -5
  227. package/dist/modules/import-export/exportRows.js.map +1 -1
  228. package/dist/modules/import-export/plan.d.ts +12 -1
  229. package/dist/modules/import-export/plan.d.ts.map +1 -1
  230. package/dist/modules/import-export/plan.js +29 -2
  231. package/dist/modules/import-export/plan.js.map +1 -1
  232. package/dist/modules/import-export/presets.d.ts.map +1 -1
  233. package/dist/modules/import-export/presets.js +10 -0
  234. package/dist/modules/import-export/presets.js.map +1 -1
  235. package/dist/modules/import-export/repository.d.ts +11 -1
  236. package/dist/modules/import-export/repository.d.ts.map +1 -1
  237. package/dist/modules/import-export/repository.js +42 -9
  238. package/dist/modules/import-export/repository.js.map +1 -1
  239. package/dist/modules/import-export/routes.d.ts.map +1 -1
  240. package/dist/modules/import-export/routes.js +4 -0
  241. package/dist/modules/import-export/routes.js.map +1 -1
  242. package/dist/modules/import-export/schema.d.ts +17 -0
  243. package/dist/modules/import-export/schema.d.ts.map +1 -1
  244. package/dist/modules/import-export/schema.js +11 -0
  245. package/dist/modules/import-export/schema.js.map +1 -1
  246. package/dist/modules/import-export/service.d.ts +6 -0
  247. package/dist/modules/import-export/service.d.ts.map +1 -1
  248. package/dist/modules/import-export/service.js +14 -2
  249. package/dist/modules/import-export/service.js.map +1 -1
  250. package/dist/modules/import-export/streams.d.ts.map +1 -1
  251. package/dist/modules/import-export/streams.js +3 -3
  252. package/dist/modules/import-export/streams.js.map +1 -1
  253. package/dist/modules/import-export/tools.d.ts.map +1 -1
  254. package/dist/modules/import-export/tools.js +8 -0
  255. package/dist/modules/import-export/tools.js.map +1 -1
  256. package/dist/modules/import-export/validation.d.ts.map +1 -1
  257. package/dist/modules/import-export/validation.js +22 -1
  258. package/dist/modules/import-export/validation.js.map +1 -1
  259. package/dist/modules/import-export/writes.d.ts.map +1 -1
  260. package/dist/modules/import-export/writes.js +37 -4
  261. package/dist/modules/import-export/writes.js.map +1 -1
  262. package/dist/modules/lists/repository.d.ts +11 -0
  263. package/dist/modules/lists/repository.d.ts.map +1 -1
  264. package/dist/modules/lists/repository.js +13 -0
  265. package/dist/modules/lists/repository.js.map +1 -1
  266. package/dist/modules/lists/routes.d.ts +4 -0
  267. package/dist/modules/lists/routes.d.ts.map +1 -1
  268. package/dist/modules/lists/routes.js +8 -0
  269. package/dist/modules/lists/routes.js.map +1 -1
  270. package/dist/modules/lists/schema.d.ts +17 -0
  271. package/dist/modules/lists/schema.d.ts.map +1 -1
  272. package/dist/modules/lists/schema.js +10 -0
  273. package/dist/modules/lists/schema.js.map +1 -1
  274. package/dist/modules/lists/service.d.ts +14 -2
  275. package/dist/modules/lists/service.d.ts.map +1 -1
  276. package/dist/modules/lists/service.js +55 -7
  277. package/dist/modules/lists/service.js.map +1 -1
  278. package/dist/modules/mcp/index.d.ts.map +1 -1
  279. package/dist/modules/mcp/index.js +5 -0
  280. package/dist/modules/mcp/index.js.map +1 -1
  281. package/dist/modules/notes/routes.d.ts +1 -0
  282. package/dist/modules/notes/routes.d.ts.map +1 -1
  283. package/dist/modules/opportunities/index.d.ts.map +1 -1
  284. package/dist/modules/opportunities/index.js +3 -1
  285. package/dist/modules/opportunities/index.js.map +1 -1
  286. package/dist/modules/opportunities/repository.d.ts +2 -0
  287. package/dist/modules/opportunities/repository.d.ts.map +1 -1
  288. package/dist/modules/opportunities/repository.js +4 -0
  289. package/dist/modules/opportunities/repository.js.map +1 -1
  290. package/dist/modules/opportunities/routes.d.ts +16 -0
  291. package/dist/modules/opportunities/routes.d.ts.map +1 -1
  292. package/dist/modules/opportunities/routes.js +13 -0
  293. package/dist/modules/opportunities/routes.js.map +1 -1
  294. package/dist/modules/opportunities/schema.d.ts +20 -0
  295. package/dist/modules/opportunities/schema.d.ts.map +1 -1
  296. package/dist/modules/opportunities/schema.js +6 -1
  297. package/dist/modules/opportunities/schema.js.map +1 -1
  298. package/dist/modules/opportunities/service.d.ts +20 -3
  299. package/dist/modules/opportunities/service.d.ts.map +1 -1
  300. package/dist/modules/opportunities/service.js +99 -18
  301. package/dist/modules/opportunities/service.js.map +1 -1
  302. package/dist/modules/opportunities/tools.d.ts.map +1 -1
  303. package/dist/modules/opportunities/tools.js +2 -0
  304. package/dist/modules/opportunities/tools.js.map +1 -1
  305. package/dist/modules/partnerships/index.d.ts.map +1 -1
  306. package/dist/modules/partnerships/index.js +3 -1
  307. package/dist/modules/partnerships/index.js.map +1 -1
  308. package/dist/modules/partnerships/repository.d.ts +0 -17
  309. package/dist/modules/partnerships/repository.d.ts.map +1 -1
  310. package/dist/modules/partnerships/repository.js +6 -82
  311. package/dist/modules/partnerships/repository.js.map +1 -1
  312. package/dist/modules/partnerships/routes.d.ts +14 -0
  313. package/dist/modules/partnerships/routes.d.ts.map +1 -1
  314. package/dist/modules/partnerships/routes.js +7 -0
  315. package/dist/modules/partnerships/routes.js.map +1 -1
  316. package/dist/modules/partnerships/schema.d.ts +20 -41
  317. package/dist/modules/partnerships/schema.d.ts.map +1 -1
  318. package/dist/modules/partnerships/schema.js +6 -10
  319. package/dist/modules/partnerships/schema.js.map +1 -1
  320. package/dist/modules/partnerships/service.d.ts +11 -1
  321. package/dist/modules/partnerships/service.d.ts.map +1 -1
  322. package/dist/modules/partnerships/service.js +43 -20
  323. package/dist/modules/partnerships/service.js.map +1 -1
  324. package/dist/modules/people/consentHydration.d.ts +26 -0
  325. package/dist/modules/people/consentHydration.d.ts.map +1 -0
  326. package/dist/modules/people/consentHydration.js +100 -0
  327. package/dist/modules/people/consentHydration.js.map +1 -0
  328. package/dist/modules/people/index.d.ts.map +1 -1
  329. package/dist/modules/people/index.js +3 -1
  330. package/dist/modules/people/index.js.map +1 -1
  331. package/dist/modules/people/personConsentWrites.d.ts +40 -0
  332. package/dist/modules/people/personConsentWrites.d.ts.map +1 -0
  333. package/dist/modules/people/personConsentWrites.js +98 -0
  334. package/dist/modules/people/personConsentWrites.js.map +1 -0
  335. package/dist/modules/people/repository.d.ts.map +1 -1
  336. package/dist/modules/people/repository.js +5 -1
  337. package/dist/modules/people/repository.js.map +1 -1
  338. package/dist/modules/people/routes.d.ts +57 -4
  339. package/dist/modules/people/routes.d.ts.map +1 -1
  340. package/dist/modules/people/routes.js +104 -5
  341. package/dist/modules/people/routes.js.map +1 -1
  342. package/dist/modules/people/schema.d.ts +366 -1
  343. package/dist/modules/people/schema.d.ts.map +1 -1
  344. package/dist/modules/people/schema.js +92 -2
  345. package/dist/modules/people/schema.js.map +1 -1
  346. package/dist/modules/people/service.d.ts +30 -1
  347. package/dist/modules/people/service.d.ts.map +1 -1
  348. package/dist/modules/people/service.js +115 -38
  349. package/dist/modules/people/service.js.map +1 -1
  350. package/dist/modules/people/tools.d.ts.map +1 -1
  351. package/dist/modules/people/tools.js +4 -1
  352. package/dist/modules/people/tools.js.map +1 -1
  353. package/dist/modules/personLinks.d.ts +79 -0
  354. package/dist/modules/personLinks.d.ts.map +1 -0
  355. package/dist/modules/personLinks.js +155 -0
  356. package/dist/modules/personLinks.js.map +1 -0
  357. package/dist/modules/pipelines/routes.d.ts +1 -0
  358. package/dist/modules/pipelines/routes.d.ts.map +1 -1
  359. package/dist/modules/plans/routes.d.ts +1 -0
  360. package/dist/modules/plans/routes.d.ts.map +1 -1
  361. package/dist/modules/raises/index.d.ts.map +1 -1
  362. package/dist/modules/raises/index.js +3 -1
  363. package/dist/modules/raises/index.js.map +1 -1
  364. package/dist/modules/raises/repository.d.ts +0 -17
  365. package/dist/modules/raises/repository.d.ts.map +1 -1
  366. package/dist/modules/raises/repository.js +6 -77
  367. package/dist/modules/raises/repository.js.map +1 -1
  368. package/dist/modules/raises/routes.d.ts +14 -0
  369. package/dist/modules/raises/routes.d.ts.map +1 -1
  370. package/dist/modules/raises/routes.js +7 -0
  371. package/dist/modules/raises/routes.js.map +1 -1
  372. package/dist/modules/raises/schema.d.ts +20 -41
  373. package/dist/modules/raises/schema.d.ts.map +1 -1
  374. package/dist/modules/raises/schema.js +6 -10
  375. package/dist/modules/raises/schema.js.map +1 -1
  376. package/dist/modules/raises/service.d.ts +11 -1
  377. package/dist/modules/raises/service.d.ts.map +1 -1
  378. package/dist/modules/raises/service.js +41 -18
  379. package/dist/modules/raises/service.js.map +1 -1
  380. package/dist/modules/recordTargets.d.ts.map +1 -1
  381. package/dist/modules/recordTargets.js +2 -0
  382. package/dist/modules/recordTargets.js.map +1 -1
  383. package/dist/modules/references.d.ts +10 -0
  384. package/dist/modules/references.d.ts.map +1 -1
  385. package/dist/modules/references.js +27 -4
  386. package/dist/modules/references.js.map +1 -1
  387. package/dist/modules/sample-data/fixture.d.ts +21 -0
  388. package/dist/modules/sample-data/fixture.d.ts.map +1 -1
  389. package/dist/modules/sample-data/fixture.js +40 -0
  390. package/dist/modules/sample-data/fixture.js.map +1 -1
  391. package/dist/modules/sample-data/index.d.ts.map +1 -1
  392. package/dist/modules/sample-data/index.js +1 -0
  393. package/dist/modules/sample-data/index.js.map +1 -1
  394. package/dist/modules/sample-data/routes.d.ts.map +1 -1
  395. package/dist/modules/sample-data/routes.js +1 -0
  396. package/dist/modules/sample-data/routes.js.map +1 -1
  397. package/dist/modules/sample-data/service.d.ts +1 -0
  398. package/dist/modules/sample-data/service.d.ts.map +1 -1
  399. package/dist/modules/sample-data/service.js +77 -8
  400. package/dist/modules/sample-data/service.js.map +1 -1
  401. package/dist/modules/search/index.d.ts +1 -1
  402. package/dist/modules/search/index.d.ts.map +1 -1
  403. package/dist/modules/search/index.js +2 -1
  404. package/dist/modules/search/index.js.map +1 -1
  405. package/dist/modules/search/repository.d.ts +1 -0
  406. package/dist/modules/search/repository.d.ts.map +1 -1
  407. package/dist/modules/search/repository.js +23 -0
  408. package/dist/modules/search/repository.js.map +1 -1
  409. package/dist/modules/search/service.d.ts +3 -3
  410. package/dist/modules/search/service.d.ts.map +1 -1
  411. package/dist/modules/search/service.js +5 -4
  412. package/dist/modules/search/service.js.map +1 -1
  413. package/dist/modules/stagedRecords.d.ts +3 -3
  414. package/dist/modules/stagedRecords.d.ts.map +1 -1
  415. package/dist/modules/stagedRecords.js +9 -0
  416. package/dist/modules/stagedRecords.js.map +1 -1
  417. package/dist/modules/webhooks/payloads.d.ts.map +1 -1
  418. package/dist/modules/webhooks/payloads.js +15 -2
  419. package/dist/modules/webhooks/payloads.js.map +1 -1
  420. package/dist/modules/workspace/repository.d.ts +2 -0
  421. package/dist/modules/workspace/repository.d.ts.map +1 -1
  422. package/dist/modules/workspace/repository.js +7 -0
  423. package/dist/modules/workspace/repository.js.map +1 -1
  424. package/dist/modules/workspace/service.d.ts.map +1 -1
  425. package/dist/modules/workspace/service.js +10 -0
  426. package/dist/modules/workspace/service.js.map +1 -1
  427. package/dist/modules/workspace/starters.d.ts.map +1 -1
  428. package/dist/modules/workspace/starters.js +5 -0
  429. package/dist/modules/workspace/starters.js.map +1 -1
  430. package/dist/runtime/events.d.ts +1 -1
  431. package/dist/runtime/events.d.ts.map +1 -1
  432. package/dist/runtime/events.js +1 -0
  433. package/dist/runtime/events.js.map +1 -1
  434. package/dist/schema/index.d.ts +3 -0
  435. package/dist/schema/index.d.ts.map +1 -1
  436. package/dist/schema/index.js +3 -0
  437. package/dist/schema/index.js.map +1 -1
  438. package/dist/testing/database.d.ts +5 -1
  439. package/dist/testing/database.d.ts.map +1 -1
  440. package/dist/testing/database.js +81 -10
  441. package/dist/testing/database.js.map +1 -1
  442. package/migrations/0024_third_king_cobra.sql +46 -0
  443. package/migrations/0025_worthless_chimera.sql +3 -0
  444. package/migrations/0026_late_aqueduct.sql +46 -0
  445. package/migrations/0027_brainy_silver_sable.sql +3 -0
  446. package/migrations/0028_freezing_scrambler.sql +19 -0
  447. package/migrations/0029_custom_fields.sql +26 -0
  448. package/migrations/0030_enquiries.sql +79 -0
  449. package/migrations/0031_consent.sql +45 -0
  450. package/migrations/0032_form_field_statement.sql +1 -0
  451. package/migrations/0033_form_field_consent_purpose_ids.sql +5 -0
  452. package/migrations/0034_drop_form_field_consent_purpose_id.sql +1 -0
  453. package/migrations/0035_form_field_consent_purpose_labels.sql +1 -0
  454. package/migrations/0036_form_field_notice_type.sql +2 -0
  455. package/migrations/meta/0024_snapshot.json +5516 -0
  456. package/migrations/meta/0025_snapshot.json +5336 -0
  457. package/migrations/meta/0026_snapshot.json +5710 -0
  458. package/migrations/meta/0027_snapshot.json +5716 -0
  459. package/migrations/meta/0028_snapshot.json +5740 -0
  460. package/migrations/meta/0029_snapshot.json +5935 -0
  461. package/migrations/meta/0030_snapshot.json +6245 -0
  462. package/migrations/meta/0031_snapshot.json +6572 -0
  463. package/migrations/meta/0032_snapshot.json +6578 -0
  464. package/migrations/meta/0033_snapshot.json +6572 -0
  465. package/migrations/meta/0034_snapshot.json +6566 -0
  466. package/migrations/meta/0035_snapshot.json +6573 -0
  467. package/migrations/meta/0036_snapshot.json +6573 -0
  468. package/migrations/meta/_journal.json +91 -0
  469. package/package.json +2 -2
  470. package/src/lib/ids.ts +11 -0
  471. package/src/modules/activities/repository.ts +22 -23
  472. package/src/modules/activities/wording.ts +18 -0
  473. package/src/modules/agent-tasks/catalog.ts +63 -0
  474. package/src/modules/agent-tasks/resolve.ts +64 -24
  475. package/src/modules/attachedRecords.ts +29 -2
  476. package/src/modules/companies/index.ts +3 -1
  477. package/src/modules/companies/routes.ts +7 -0
  478. package/src/modules/companies/schema.ts +7 -1
  479. package/src/modules/companies/service.ts +48 -13
  480. package/src/modules/consent-purposes/capabilities.ts +12 -0
  481. package/src/modules/consent-purposes/events.ts +38 -0
  482. package/src/modules/consent-purposes/index.ts +48 -0
  483. package/src/modules/consent-purposes/repository.ts +163 -0
  484. package/src/modules/consent-purposes/routes.ts +122 -0
  485. package/src/modules/consent-purposes/schema.ts +46 -0
  486. package/src/modules/consent-purposes/service.ts +423 -0
  487. package/src/modules/consent-purposes/starters.ts +32 -0
  488. package/src/modules/consent-purposes/tools.ts +44 -0
  489. package/src/modules/core.ts +10 -0
  490. package/src/modules/custom-fields/capabilities.ts +17 -0
  491. package/src/modules/custom-fields/events.ts +51 -0
  492. package/src/modules/custom-fields/index.ts +61 -0
  493. package/src/modules/custom-fields/repository.ts +225 -0
  494. package/src/modules/custom-fields/routes.ts +155 -0
  495. package/src/modules/custom-fields/schema.ts +61 -0
  496. package/src/modules/custom-fields/service.ts +439 -0
  497. package/src/modules/custom-fields/tools.ts +53 -0
  498. package/src/modules/custom-fields/values.ts +352 -0
  499. package/src/modules/custom-fields/wire.ts +32 -0
  500. package/src/modules/dashboard/repository.ts +4 -3
  501. package/src/modules/deals/index.ts +5 -2
  502. package/src/modules/deals/repository.ts +6 -106
  503. package/src/modules/deals/routes.ts +7 -0
  504. package/src/modules/deals/schema.ts +7 -15
  505. package/src/modules/deals/service.ts +92 -23
  506. package/src/modules/decisions/repository.ts +2 -0
  507. package/src/modules/enquiries/events.ts +45 -0
  508. package/src/modules/enquiries/index.ts +50 -0
  509. package/src/modules/enquiries/repository.ts +164 -0
  510. package/src/modules/enquiries/routes.ts +172 -0
  511. package/src/modules/enquiries/schema.ts +59 -0
  512. package/src/modules/enquiries/service.ts +644 -0
  513. package/src/modules/enquiries/tools.ts +66 -0
  514. package/src/modules/eventCatalogs.ts +3 -0
  515. package/src/modules/forms/embed.ts +391 -44
  516. package/src/modules/forms/events.ts +30 -2
  517. package/src/modules/forms/fields.ts +102 -2
  518. package/src/modules/forms/index.ts +12 -1
  519. package/src/modules/forms/mapping.ts +183 -6
  520. package/src/modules/forms/publicRoutes.ts +43 -1
  521. package/src/modules/forms/repository.ts +162 -1
  522. package/src/modules/forms/routes.ts +212 -2
  523. package/src/modules/forms/schema.ts +166 -4
  524. package/src/modules/forms/service.ts +565 -41
  525. package/src/modules/forms/submission.ts +718 -44
  526. package/src/modules/import-export/drafts.ts +20 -1
  527. package/src/modules/import-export/exportRows.ts +21 -5
  528. package/src/modules/import-export/plan.ts +47 -2
  529. package/src/modules/import-export/presets.ts +10 -0
  530. package/src/modules/import-export/repository.ts +73 -8
  531. package/src/modules/import-export/routes.ts +4 -0
  532. package/src/modules/import-export/schema.ts +11 -0
  533. package/src/modules/import-export/service.ts +28 -2
  534. package/src/modules/import-export/streams.ts +3 -1
  535. package/src/modules/import-export/tools.ts +10 -0
  536. package/src/modules/import-export/validation.ts +28 -0
  537. package/src/modules/import-export/writes.ts +70 -5
  538. package/src/modules/lists/repository.ts +30 -0
  539. package/src/modules/lists/routes.ts +8 -0
  540. package/src/modules/lists/schema.ts +10 -0
  541. package/src/modules/lists/service.ts +110 -9
  542. package/src/modules/mcp/index.ts +5 -0
  543. package/src/modules/opportunities/index.ts +3 -1
  544. package/src/modules/opportunities/repository.ts +11 -0
  545. package/src/modules/opportunities/routes.ts +13 -0
  546. package/src/modules/opportunities/schema.ts +7 -1
  547. package/src/modules/opportunities/service.ts +188 -22
  548. package/src/modules/opportunities/tools.ts +2 -0
  549. package/src/modules/partnerships/index.ts +3 -1
  550. package/src/modules/partnerships/repository.ts +6 -117
  551. package/src/modules/partnerships/routes.ts +7 -0
  552. package/src/modules/partnerships/schema.ts +7 -14
  553. package/src/modules/partnerships/service.ts +93 -22
  554. package/src/modules/people/consentHydration.ts +167 -0
  555. package/src/modules/people/index.ts +3 -1
  556. package/src/modules/people/personConsentWrites.ts +177 -0
  557. package/src/modules/people/repository.ts +5 -0
  558. package/src/modules/people/routes.ts +127 -18
  559. package/src/modules/people/schema.ts +109 -3
  560. package/src/modules/people/service.ts +186 -40
  561. package/src/modules/people/tools.ts +5 -1
  562. package/src/modules/personLinks.ts +278 -0
  563. package/src/modules/raises/index.ts +3 -1
  564. package/src/modules/raises/repository.ts +6 -107
  565. package/src/modules/raises/routes.ts +7 -0
  566. package/src/modules/raises/schema.ts +7 -14
  567. package/src/modules/raises/service.ts +91 -20
  568. package/src/modules/recordTargets.ts +2 -0
  569. package/src/modules/references.ts +43 -4
  570. package/src/modules/sample-data/fixture.ts +63 -0
  571. package/src/modules/sample-data/index.ts +1 -0
  572. package/src/modules/sample-data/routes.ts +1 -0
  573. package/src/modules/sample-data/service.ts +97 -8
  574. package/src/modules/search/index.ts +2 -1
  575. package/src/modules/search/repository.ts +33 -1
  576. package/src/modules/search/service.ts +7 -5
  577. package/src/modules/stagedRecords.ts +18 -3
  578. package/src/modules/webhooks/payloads.ts +20 -2
  579. package/src/modules/workspace/repository.ts +12 -0
  580. package/src/modules/workspace/service.ts +14 -0
  581. package/src/modules/workspace/starters.ts +5 -0
  582. package/src/runtime/events.ts +1 -0
  583. package/src/schema/index.ts +3 -0
  584. package/src/testing/database.ts +97 -11
@@ -1,3 +1,5 @@
1
+ import type { CustomFieldWireValue } from '@kelpie/schemas'
2
+
1
3
  import { changedKeys } from '../../lib/changes.ts'
2
4
  import type { Database } from '../../lib/database.ts'
3
5
  import { AppError } from '../../lib/errors.ts'
@@ -20,6 +22,8 @@ import { actorMemberId, requireWorkspaceId } from '../auth/actor.ts'
20
22
  import './events.ts'
21
23
  import { deleteRecordsAttachedTo } from '../attachedRecords.ts'
22
24
  import * as companyRepository from '../companies/repository.ts'
25
+ import type { CustomFieldValuesValidator } from '../custom-fields/values.ts'
26
+ import * as personLinks from '../personLinks.ts'
23
27
  import * as pipelineRepository from '../pipelines/repository.ts'
24
28
  import type { PipelineStageRecord } from '../pipelines/repository.ts'
25
29
  import * as repository from './repository.ts'
@@ -30,7 +34,7 @@ import type { PartnershipFilters, PartnershipRecord } from './repository.ts'
30
34
  * Partnerships: ongoing two-way relationships. Status is a stage of the
31
35
  * `partnership` pipeline; there is no favour ledger (`brief.md` non-goal).
32
36
  *
33
- * Key people attach through `partnership_people` and appear as `person_ids` on
37
+ * Key people attach through `person_links` and appear as `person_ids` on
34
38
  * the wire, the Deals mechanics; kind is free text, the Opportunities mechanics.
35
39
  * A stage move is an ordinary PATCH of `stage_id`, and it is the one change that
36
40
  * files a `stage_changed` activity and a `stage.changed` event instead of the
@@ -43,6 +47,7 @@ export interface PartnershipsDependencies {
43
47
  readonly createId: IdFactory
44
48
  readonly now: () => Date
45
49
  readonly recordActivity: ActivityRecorder
50
+ readonly customFields: CustomFieldValuesValidator
46
51
  }
47
52
 
48
53
  /** What a changed column is called on a timeline. `successLooksLike` is why these are written out. */
@@ -81,6 +86,8 @@ export interface CreatePartnershipInput {
81
86
  readonly personIds: readonly string[]
82
87
  readonly summary: string
83
88
  readonly tags: readonly string[]
89
+ /** Wire shape for a create body: `null` values are ignored, non-null are validated. */
90
+ readonly customFields: Readonly<Record<string, CustomFieldWireValue | null>> | undefined
84
91
  }
85
92
 
86
93
  /** PATCH semantics: an absent field is left alone, and null clears a nullable one. */
@@ -97,6 +104,11 @@ export interface UpdatePartnershipInput {
97
104
  readonly personIds?: readonly string[] | undefined
98
105
  readonly summary?: string | undefined
99
106
  readonly tags?: readonly string[] | undefined
107
+ /**
108
+ * Partial merge patch (wire shape): sent keys change, `null` clears a key,
109
+ * absent keys are left alone. Unknown keys are `422`.
110
+ */
111
+ readonly customFields?: Readonly<Record<string, CustomFieldWireValue | null>> | undefined
100
112
  }
101
113
 
102
114
  export interface PartnershipsService {
@@ -208,7 +220,7 @@ export function createPartnershipsService(
208
220
  workspaceId: string,
209
221
  personIds: readonly string[],
210
222
  ): Promise<ReadonlyMap<string, string>> {
211
- const named = await repository.findPeopleNamed(dependencies.db, workspaceId, personIds)
223
+ const named = await personLinks.findPeopleNamed(dependencies.db, workspaceId, personIds)
212
224
  const missing = personIds.filter((id) => !named.has(id))
213
225
 
214
226
  if (missing.length > 0) {
@@ -223,9 +235,14 @@ export function createPartnershipsService(
223
235
  }
224
236
 
225
237
  /** @returns The page's views, with every partnership's people fetched in one query. */
226
- async function toViews(records: readonly PartnershipRecord[]): Promise<PartnershipView[]> {
227
- const peopleByPartnership = await repository.listPersonIdsFor(
238
+ async function toViews(
239
+ workspaceId: string,
240
+ records: readonly PartnershipRecord[],
241
+ ): Promise<PartnershipView[]> {
242
+ const peopleByPartnership = await personLinks.listPersonIdsFor(
228
243
  dependencies.db,
244
+ workspaceId,
245
+ 'partnership',
229
246
  records.map((record) => record.id),
230
247
  )
231
248
 
@@ -239,14 +256,20 @@ export function createPartnershipsService(
239
256
  const rows = await repository.listPartnerships(dependencies.db, workspaceId, filters, window)
240
257
  const page = toPage(rows, window, (partnership) => partnership.id)
241
258
 
242
- return { items: await toViews(page.items), nextCursor: page.nextCursor }
259
+ return { items: await toViews(workspaceId, page.items), nextCursor: page.nextCursor }
243
260
  },
244
261
 
245
262
  async get(actor, id) {
246
263
  const workspaceId = requireWorkspaceId(actor)
247
264
  const partnership = await require(workspaceId, id)
248
265
 
249
- return toView(partnership, await repository.listPersonIds(dependencies.db, id))
266
+ return toView(
267
+ partnership,
268
+ await personLinks.listPersonIds(dependencies.db, workspaceId, {
269
+ targetType: 'partnership',
270
+ targetId: id,
271
+ }),
272
+ )
250
273
  },
251
274
 
252
275
  async create(actor, input) {
@@ -269,6 +292,12 @@ export function createPartnershipsService(
269
292
  const id = dependencies.createId('partnership')
270
293
 
271
294
  return dependencies.transaction(async ({ tx, events }) => {
295
+ const customFields = await dependencies.customFields.forCreate(
296
+ tx,
297
+ workspaceId,
298
+ 'partnership',
299
+ input.customFields,
300
+ )
272
301
  const created = await repository.insertPartnership(tx, {
273
302
  id,
274
303
  workspaceId,
@@ -282,9 +311,16 @@ export function createPartnershipsService(
282
311
  successLooksLike: input.successLooksLike,
283
312
  summary: input.summary,
284
313
  tags: [...input.tags],
314
+ customFields,
285
315
  })
286
316
 
287
- await repository.insertPartnershipPeople(tx, id, personIds)
317
+ await personLinks.linkPeople(
318
+ tx,
319
+ dependencies.createId,
320
+ workspaceId,
321
+ { targetType: 'partnership', targetId: id },
322
+ personIds,
323
+ )
288
324
 
289
325
  await dependencies.recordActivity(tx, workspaceId, actor, {
290
326
  targetType: 'partnership',
@@ -329,7 +365,10 @@ export function createPartnershipsService(
329
365
  await requireOwner(workspaceId, changes.ownerId)
330
366
  }
331
367
 
332
- const currentPeople = await repository.listPersonIds(dependencies.db, id)
368
+ const currentPeople = await personLinks.listPersonIds(dependencies.db, workspaceId, {
369
+ targetType: 'partnership',
370
+ targetId: id,
371
+ })
333
372
  const nextPeople =
334
373
  changes.personIds === undefined ? undefined : [...new Set(changes.personIds)]
335
374
  const added =
@@ -343,16 +382,26 @@ export function createPartnershipsService(
343
382
  const named = await requirePeople(workspaceId, [...added, ...removed])
344
383
 
345
384
  const columns = toStoredColumns(changes)
346
- const changed = changedKeys(existing, columns)
385
+ const scalarChanged = changedKeys(existing, columns)
347
386
  const linksChanged = added.length > 0 || removed.length > 0
348
387
 
349
- if (changed.length === 0 && !linksChanged) {
350
- return toView(existing, currentPeople)
351
- }
352
-
353
388
  return dependencies.transaction(async ({ tx, events }) => {
389
+ const cf = await dependencies.customFields.forUpdate(
390
+ tx,
391
+ workspaceId,
392
+ 'partnership',
393
+ existing.customFields,
394
+ changes.customFields,
395
+ )
396
+ const customFieldsChanged = cf !== undefined && cf.changedPaths.length > 0
397
+
398
+ if (scalarChanged.length === 0 && !linksChanged && !customFieldsChanged) {
399
+ return toView(existing, currentPeople)
400
+ }
401
+
354
402
  const updated = await repository.updatePartnership(tx, workspaceId, id, {
355
403
  ...columns,
404
+ ...(customFieldsChanged ? { customFields: cf.merged } : {}),
356
405
  updatedAt: dependencies.now(),
357
406
  })
358
407
 
@@ -360,8 +409,19 @@ export function createPartnershipsService(
360
409
  throw AppError.notFound('Partnership not found')
361
410
  }
362
411
 
363
- await repository.insertPartnershipPeople(tx, id, added)
364
- await repository.deletePartnershipPeople(tx, id, removed)
412
+ await personLinks.linkPeople(
413
+ tx,
414
+ dependencies.createId,
415
+ workspaceId,
416
+ { targetType: 'partnership', targetId: id },
417
+ added,
418
+ )
419
+ await personLinks.unlinkPeople(
420
+ tx,
421
+ workspaceId,
422
+ { targetType: 'partnership', targetId: id },
423
+ removed,
424
+ )
365
425
 
366
426
  if (stageMove !== undefined) {
367
427
  await dependencies.recordActivity(tx, workspaceId, actor, {
@@ -372,14 +432,19 @@ export function createPartnershipsService(
372
432
  })
373
433
  }
374
434
 
375
- const otherChanged = changed.filter((field) => field !== 'stageId')
435
+ const otherChanged = scalarChanged.filter((field) => field !== 'stageId')
436
+ const customFieldPaths = cf?.changedPaths ?? []
437
+ const activityChanged = [...otherChanged, ...customFieldPaths]
376
438
 
377
- if (otherChanged.length > 0) {
439
+ if (activityChanged.length > 0) {
440
+ const labels: Record<string, string> = { ...PARTNERSHIP_FIELD_LABELS, ...cf?.labels }
441
+ const before: Record<string, unknown> = { ...existing, ...cf?.flatBefore }
442
+ const after: Record<string, unknown> = { ...columns, ...cf?.flatAfter }
378
443
  await dependencies.recordActivity(tx, workspaceId, actor, {
379
444
  targetType: 'partnership',
380
445
  targetId: id,
381
446
  kind: 'updated',
382
- ...describeUpdate(otherChanged, PARTNERSHIP_FIELD_LABELS, existing, columns),
447
+ ...describeUpdate(activityChanged, labels, before, after),
383
448
  })
384
449
  }
385
450
 
@@ -407,7 +472,13 @@ export function createPartnershipsService(
407
472
  events.emit(
408
473
  'partnerships.partnership.updated',
409
474
  { type: 'partnership', id },
410
- { changed: linksChanged ? [...changed, 'personIds'] : changed },
475
+ {
476
+ changed: [
477
+ ...scalarChanged,
478
+ ...(linksChanged ? ['personIds'] : []),
479
+ ...customFieldPaths,
480
+ ],
481
+ },
411
482
  )
412
483
 
413
484
  if (stageMove !== undefined) {
@@ -428,9 +499,9 @@ export function createPartnershipsService(
428
499
  await dependencies.transaction(async ({ tx, events }) => {
429
500
  await require(workspaceId, id)
430
501
 
431
- // `partnership_people` dies with the partnership through its foreign key;
432
- // notes, activities, decisions and plan items have no key, so they are
433
- // removed here, in the same transaction.
502
+ // Notes, activities, decisions, plan items, and person_links have no
503
+ // key back to the partnership, so they are removed here, in the same
504
+ // transaction.
434
505
  await deleteRecordsAttachedTo(tx, workspaceId, 'partnership', id)
435
506
  await repository.deletePartnership(tx, workspaceId, id)
436
507
 
@@ -0,0 +1,167 @@
1
+ import type { ConsentPurposeStatus } from '@kelpie/schemas'
2
+ import { and, asc, eq, inArray } from 'drizzle-orm'
3
+
4
+ import type { Queryable } from '../../runtime/transaction.ts'
5
+ import { consentPurposes } from '../consent-purposes/schema.ts'
6
+ import { personConsents } from './schema.ts'
7
+
8
+ /**
9
+ * Merges a workspace's consent purposes with any explicit `person_consents`
10
+ * rows into the effective status agents and humans read on a Person.
11
+ *
12
+ * The rule is simple: an explicit row wins; absence means "inherits the
13
+ * purpose's `default_status`". This helper does the join and the merge in one
14
+ * place so every read of a Person resolves it the same way.
15
+ */
16
+
17
+ export interface EffectiveConsent {
18
+ readonly purposeSlug: string
19
+ readonly purposeLabel: string
20
+ readonly status: ConsentPurposeStatus
21
+ readonly source: string | null
22
+ readonly notedAt: Date | null
23
+ readonly inherited: boolean
24
+ }
25
+
26
+ /** The workspace purposes and any person-level rows, in one shape. */
27
+ interface PurposeRow {
28
+ readonly id: string
29
+ readonly slug: string
30
+ readonly label: string
31
+ readonly defaultStatus: ConsentPurposeStatus
32
+ readonly sortOrder: number
33
+ }
34
+
35
+ interface PersonConsentRow {
36
+ readonly personId: string
37
+ readonly purposeId: string
38
+ readonly status: 'granted' | 'withdrawn'
39
+ readonly source: string
40
+ readonly notedAt: Date
41
+ }
42
+
43
+ async function loadPurposes(
44
+ db: Queryable,
45
+ workspaceId: string,
46
+ ): Promise<readonly PurposeRow[]> {
47
+ const rows = await db
48
+ .select({
49
+ id: consentPurposes.id,
50
+ slug: consentPurposes.slug,
51
+ label: consentPurposes.label,
52
+ defaultStatus: consentPurposes.defaultStatus,
53
+ sortOrder: consentPurposes.sortOrder,
54
+ })
55
+ .from(consentPurposes)
56
+ .where(eq(consentPurposes.workspaceId, workspaceId))
57
+ .orderBy(asc(consentPurposes.sortOrder), asc(consentPurposes.id))
58
+
59
+ return rows.map((row) => ({
60
+ id: row.id,
61
+ slug: row.slug,
62
+ label: row.label,
63
+ defaultStatus: row.defaultStatus as ConsentPurposeStatus,
64
+ sortOrder: row.sortOrder,
65
+ }))
66
+ }
67
+
68
+ async function loadConsentsFor(
69
+ db: Queryable,
70
+ workspaceId: string,
71
+ personIds: readonly string[],
72
+ ): Promise<readonly PersonConsentRow[]> {
73
+ if (personIds.length === 0) return []
74
+ const rows = await db
75
+ .select({
76
+ personId: personConsents.personId,
77
+ purposeId: personConsents.purposeId,
78
+ status: personConsents.status,
79
+ source: personConsents.source,
80
+ notedAt: personConsents.notedAt,
81
+ })
82
+ .from(personConsents)
83
+ .where(
84
+ and(
85
+ eq(personConsents.workspaceId, workspaceId),
86
+ inArray(personConsents.personId, [...personIds]),
87
+ ),
88
+ )
89
+
90
+ return rows.map((row) => ({
91
+ personId: row.personId,
92
+ purposeId: row.purposeId,
93
+ status: row.status as 'granted' | 'withdrawn',
94
+ source: row.source,
95
+ notedAt: row.notedAt,
96
+ }))
97
+ }
98
+
99
+ function mergeFor(
100
+ purposes: readonly PurposeRow[],
101
+ explicitByPurpose: ReadonlyMap<string, PersonConsentRow>,
102
+ ): readonly EffectiveConsent[] {
103
+ return purposes.map((purpose) => {
104
+ const explicit = explicitByPurpose.get(purpose.id)
105
+ if (explicit === undefined) {
106
+ return {
107
+ purposeSlug: purpose.slug,
108
+ purposeLabel: purpose.label,
109
+ status: purpose.defaultStatus,
110
+ source: null,
111
+ notedAt: null,
112
+ inherited: true,
113
+ }
114
+ }
115
+ return {
116
+ purposeSlug: purpose.slug,
117
+ purposeLabel: purpose.label,
118
+ status: explicit.status,
119
+ source: explicit.source,
120
+ notedAt: explicit.notedAt,
121
+ inherited: false,
122
+ }
123
+ })
124
+ }
125
+
126
+ /** Consents for one person. */
127
+ export async function readConsentsFor(
128
+ db: Queryable,
129
+ workspaceId: string,
130
+ personId: string,
131
+ ): Promise<readonly EffectiveConsent[]> {
132
+ const [purposes, explicit] = await Promise.all([
133
+ loadPurposes(db, workspaceId),
134
+ loadConsentsFor(db, workspaceId, [personId]),
135
+ ])
136
+ const byPurpose = new Map(explicit.map((row) => [row.purposeId, row]))
137
+ return mergeFor(purposes, byPurpose)
138
+ }
139
+
140
+ /**
141
+ * Consents for many people. Loads purposes once and person rows once, then
142
+ * merges in memory — cheaper than a per-row read for a paged list.
143
+ */
144
+ export async function readConsentsForMany(
145
+ db: Queryable,
146
+ workspaceId: string,
147
+ personIds: readonly string[],
148
+ ): Promise<ReadonlyMap<string, readonly EffectiveConsent[]>> {
149
+ if (personIds.length === 0) return new Map()
150
+ const [purposes, explicit] = await Promise.all([
151
+ loadPurposes(db, workspaceId),
152
+ loadConsentsFor(db, workspaceId, personIds),
153
+ ])
154
+
155
+ const byPerson = new Map<string, Map<string, PersonConsentRow>>()
156
+ for (const row of explicit) {
157
+ const map = byPerson.get(row.personId) ?? new Map<string, PersonConsentRow>()
158
+ map.set(row.purposeId, row)
159
+ byPerson.set(row.personId, map)
160
+ }
161
+
162
+ const out = new Map<string, readonly EffectiveConsent[]>()
163
+ for (const personId of personIds) {
164
+ out.set(personId, mergeFor(purposes, byPerson.get(personId) ?? new Map()))
165
+ }
166
+ return out
167
+ }
@@ -1,5 +1,6 @@
1
1
  import type { KelpieModule } from '../../runtime/module.ts'
2
2
  import { createActivityRecorder } from '../activities/index.ts'
3
+ import { createCustomFieldValues } from '../custom-fields/index.ts'
3
4
  import { peopleEvents } from './events.ts'
4
5
  import { mountPeopleRoutes } from './routes.ts'
5
6
  import * as schema from './schema.ts'
@@ -15,7 +16,7 @@ import { registerPeopleTools } from './tools.ts'
15
16
  export function createPeopleModule(migrationsDirectory: string): KelpieModule {
16
17
  return {
17
18
  id: 'people',
18
- requires: ['workspace', 'activities'],
19
+ requires: ['workspace', 'activities', 'custom-fields'],
19
20
  structural: true,
20
21
  events: peopleEvents,
21
22
 
@@ -29,6 +30,7 @@ export function createPeopleModule(migrationsDirectory: string): KelpieModule {
29
30
  createId: context.createId,
30
31
  now: context.now,
31
32
  }),
33
+ customFields: createCustomFieldValues({ db: context.db }),
32
34
  })
33
35
 
34
36
  context.schema(schema, migrationsDirectory)
@@ -0,0 +1,177 @@
1
+ import type { ConsentStatus } from '@kelpie/schemas'
2
+ import { and, eq, inArray } from 'drizzle-orm'
3
+
4
+ import { AppError } from '../../lib/errors.ts'
5
+ import type { Transaction } from '../../runtime/transaction.ts'
6
+ import { consentPurposes } from '../consent-purposes/schema.ts'
7
+ import { personConsents } from './schema.ts'
8
+
9
+ /**
10
+ * Writes to `person_consents`, shared by the manual PATCH override and every
11
+ * capture site (forms, lists, imports). Every write is idempotent — a second
12
+ * grant for the same (person, purpose) with the same source is a no-op.
13
+ *
14
+ * `source` follows the shape in `docs/privacy.md`:
15
+ * `form:<form_id>` | `list:<list_id>` | `import` | `manual`.
16
+ */
17
+
18
+ export interface ConsentWriteChange {
19
+ readonly purposeSlug: string
20
+ readonly purposeLabel: string
21
+ readonly status: ConsentStatus | null
22
+ readonly previousStatus: ConsentStatus | null
23
+ }
24
+
25
+ export interface ConsentWriteInput {
26
+ readonly purposeSlug: string
27
+ readonly status: ConsentStatus | null
28
+ }
29
+
30
+ interface PurposeRow {
31
+ readonly id: string
32
+ readonly slug: string
33
+ readonly label: string
34
+ }
35
+
36
+ async function resolvePurposesBySlug(
37
+ tx: Transaction,
38
+ workspaceId: string,
39
+ slugs: readonly string[],
40
+ ): Promise<ReadonlyMap<string, PurposeRow>> {
41
+ if (slugs.length === 0) return new Map()
42
+ const rows = await tx
43
+ .select({
44
+ id: consentPurposes.id,
45
+ slug: consentPurposes.slug,
46
+ label: consentPurposes.label,
47
+ })
48
+ .from(consentPurposes)
49
+ .where(
50
+ and(
51
+ eq(consentPurposes.workspaceId, workspaceId),
52
+ inArray(consentPurposes.slug, [...slugs]),
53
+ ),
54
+ )
55
+ return new Map(rows.map((row) => [row.slug, row]))
56
+ }
57
+
58
+ /**
59
+ * Applies one `PersonConsent` write. `status: null` deletes the row (falls
60
+ * back to the purpose default); any other status upserts it.
61
+ *
62
+ * @returns The change that landed — with the previous status so a caller can
63
+ * file a "no change" as a no-op activity.
64
+ */
65
+ export async function upsertPersonConsent(
66
+ tx: Transaction,
67
+ workspaceId: string,
68
+ personId: string,
69
+ purposeId: string,
70
+ purposeSlug: string,
71
+ purposeLabel: string,
72
+ status: ConsentStatus | null,
73
+ source: string,
74
+ now: Date,
75
+ ): Promise<ConsentWriteChange> {
76
+ const [existing] = await tx
77
+ .select({ status: personConsents.status })
78
+ .from(personConsents)
79
+ .where(
80
+ and(eq(personConsents.personId, personId), eq(personConsents.purposeId, purposeId)),
81
+ )
82
+ .limit(1)
83
+
84
+ const previousStatus = (existing?.status ?? null) as ConsentStatus | null
85
+
86
+ if (status === null) {
87
+ if (existing !== undefined) {
88
+ await tx
89
+ .delete(personConsents)
90
+ .where(
91
+ and(eq(personConsents.personId, personId), eq(personConsents.purposeId, purposeId)),
92
+ )
93
+ }
94
+ return { purposeSlug, purposeLabel, status: null, previousStatus }
95
+ }
96
+
97
+ await tx
98
+ .insert(personConsents)
99
+ .values({
100
+ workspaceId,
101
+ personId,
102
+ purposeId,
103
+ status,
104
+ notedAt: now,
105
+ source,
106
+ updatedAt: now,
107
+ })
108
+ .onConflictDoUpdate({
109
+ target: [personConsents.personId, personConsents.purposeId],
110
+ set: {
111
+ status,
112
+ notedAt: now,
113
+ source,
114
+ updatedAt: now,
115
+ },
116
+ })
117
+
118
+ return { purposeSlug, purposeLabel, status, previousStatus }
119
+ }
120
+
121
+ /**
122
+ * Reads by slug for a manual PATCH: resolves each named purpose to its id,
123
+ * refuses an unknown slug with a `422`, and applies the writes. Every write
124
+ * ridden through here uses `source: 'manual'`.
125
+ */
126
+ export async function applyManualConsentWrites(
127
+ tx: Transaction,
128
+ workspaceId: string,
129
+ personId: string,
130
+ writes: readonly ConsentWriteInput[],
131
+ now: Date,
132
+ ): Promise<readonly ConsentWriteChange[]> {
133
+ if (writes.length === 0) return []
134
+ const slugs = writes.map((write) => write.purposeSlug)
135
+ const purposesBySlug = await resolvePurposesBySlug(tx, workspaceId, slugs)
136
+
137
+ const missing = slugs.filter((slug) => !purposesBySlug.has(slug))
138
+ if (missing.length > 0) {
139
+ throw AppError.validationFailed(
140
+ 'One or more consent purposes were not found in this workspace',
141
+ missing.map((slug) => ({
142
+ field: `consents.${slug}`,
143
+ message: `Unknown consent purpose "${slug}"`,
144
+ })),
145
+ )
146
+ }
147
+
148
+ const changes: ConsentWriteChange[] = []
149
+ for (const write of writes) {
150
+ const purpose = purposesBySlug.get(write.purposeSlug)
151
+ if (purpose === undefined) continue // impossible after the check above
152
+ const change = await upsertPersonConsent(
153
+ tx,
154
+ workspaceId,
155
+ personId,
156
+ purpose.id,
157
+ purpose.slug,
158
+ purpose.label,
159
+ write.status,
160
+ 'manual',
161
+ now,
162
+ )
163
+ changes.push(change)
164
+ }
165
+ return changes
166
+ }
167
+
168
+ /**
169
+ * The `changed` paths a person update event emits for consent writes. Names
170
+ * every purpose that actually moved, shaped as `consents.<slug>`.
171
+ */
172
+ export function consentChangedPaths(changes: readonly ConsentWriteChange[]): readonly string[] {
173
+ return changes
174
+ .filter((change) => change.status !== change.previousStatus)
175
+ .map((change) => `consents.${change.purposeSlug}`)
176
+ }
177
+
@@ -66,6 +66,11 @@ function matchesTerm(term: string): SQL | undefined {
66
66
 
67
67
  return or(
68
68
  ilike(people.name, pattern),
69
+ // The same two parts `search_vector` carries, so filtering this list and
70
+ // searching the workspace find a person by their surname alike. Salutation
71
+ // and suffix are in neither: "Dr" matches half a workspace.
72
+ ilike(people.firstName, pattern),
73
+ ilike(people.lastName, pattern),
69
74
  ilike(people.email, pattern),
70
75
  ilike(people.summary, pattern),
71
76
  arrayContainsPattern(people.tags, pattern),