@kelpie/server 0.7.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 (679) hide show
  1. package/dist/lib/consumerEmailDomains.d.ts +2 -0
  2. package/dist/lib/consumerEmailDomains.d.ts.map +1 -0
  3. package/dist/lib/consumerEmailDomains.js +62 -0
  4. package/dist/lib/consumerEmailDomains.js.map +1 -0
  5. package/dist/lib/email.d.ts +7 -0
  6. package/dist/lib/email.d.ts.map +1 -1
  7. package/dist/lib/email.js.map +1 -1
  8. package/dist/lib/emailContent.d.ts +33 -0
  9. package/dist/lib/emailContent.d.ts.map +1 -0
  10. package/dist/lib/emailContent.js +54 -0
  11. package/dist/lib/emailContent.js.map +1 -0
  12. package/dist/lib/emailDomainAutoLink.d.ts +27 -0
  13. package/dist/lib/emailDomainAutoLink.d.ts.map +1 -0
  14. package/dist/lib/emailDomainAutoLink.js +119 -0
  15. package/dist/lib/emailDomainAutoLink.js.map +1 -0
  16. package/dist/lib/ids.d.ts +13 -0
  17. package/dist/lib/ids.d.ts.map +1 -1
  18. package/dist/lib/ids.js +13 -0
  19. package/dist/lib/ids.js.map +1 -1
  20. package/dist/modules/activities/repository.d.ts.map +1 -1
  21. package/dist/modules/activities/repository.js +19 -20
  22. package/dist/modules/activities/repository.js.map +1 -1
  23. package/dist/modules/activities/wording.d.ts +12 -0
  24. package/dist/modules/activities/wording.d.ts.map +1 -1
  25. package/dist/modules/activities/wording.js +16 -0
  26. package/dist/modules/activities/wording.js.map +1 -1
  27. package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
  28. package/dist/modules/agent-tasks/catalog.js +62 -0
  29. package/dist/modules/agent-tasks/catalog.js.map +1 -1
  30. package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
  31. package/dist/modules/agent-tasks/resolve.js +42 -9
  32. package/dist/modules/agent-tasks/resolve.js.map +1 -1
  33. package/dist/modules/agent-tasks/routes.d.ts +2 -0
  34. package/dist/modules/agent-tasks/routes.d.ts.map +1 -1
  35. package/dist/modules/attachedRecords.d.ts +6 -1
  36. package/dist/modules/attachedRecords.d.ts.map +1 -1
  37. package/dist/modules/attachedRecords.js +18 -2
  38. package/dist/modules/attachedRecords.js.map +1 -1
  39. package/dist/modules/auth/preferences.d.ts +11 -1
  40. package/dist/modules/auth/preferences.d.ts.map +1 -1
  41. package/dist/modules/auth/preferences.js +11 -0
  42. package/dist/modules/auth/preferences.js.map +1 -1
  43. package/dist/modules/auth/routes.d.ts.map +1 -1
  44. package/dist/modules/auth/routes.js +18 -0
  45. package/dist/modules/auth/routes.js.map +1 -1
  46. package/dist/modules/auth/schema.d.ts +20 -0
  47. package/dist/modules/auth/schema.d.ts.map +1 -1
  48. package/dist/modules/auth/schema.js +11 -1
  49. package/dist/modules/auth/schema.js.map +1 -1
  50. package/dist/modules/auth/service.d.ts.map +1 -1
  51. package/dist/modules/auth/service.js +27 -3
  52. package/dist/modules/auth/service.js.map +1 -1
  53. package/dist/modules/companies/index.d.ts.map +1 -1
  54. package/dist/modules/companies/index.js +3 -1
  55. package/dist/modules/companies/index.js.map +1 -1
  56. package/dist/modules/companies/repository.d.ts +2 -0
  57. package/dist/modules/companies/repository.d.ts.map +1 -1
  58. package/dist/modules/companies/repository.js +1 -0
  59. package/dist/modules/companies/repository.js.map +1 -1
  60. package/dist/modules/companies/routes.d.ts +16 -0
  61. package/dist/modules/companies/routes.d.ts.map +1 -1
  62. package/dist/modules/companies/routes.js +18 -0
  63. package/dist/modules/companies/routes.js.map +1 -1
  64. package/dist/modules/companies/schema.d.ts +37 -0
  65. package/dist/modules/companies/schema.d.ts.map +1 -1
  66. package/dist/modules/companies/schema.js +10 -1
  67. package/dist/modules/companies/schema.js.map +1 -1
  68. package/dist/modules/companies/service.d.ts +6 -0
  69. package/dist/modules/companies/service.d.ts.map +1 -1
  70. package/dist/modules/companies/service.js +45 -11
  71. package/dist/modules/companies/service.js.map +1 -1
  72. package/dist/modules/consent-purposes/capabilities.d.ts +7 -0
  73. package/dist/modules/consent-purposes/capabilities.d.ts.map +1 -0
  74. package/dist/modules/consent-purposes/capabilities.js +10 -0
  75. package/dist/modules/consent-purposes/capabilities.js.map +1 -0
  76. package/dist/modules/consent-purposes/events.d.ts +38 -0
  77. package/dist/modules/consent-purposes/events.d.ts.map +1 -0
  78. package/dist/modules/consent-purposes/events.js +17 -0
  79. package/dist/modules/consent-purposes/events.js.map +1 -0
  80. package/dist/modules/consent-purposes/index.d.ts +13 -0
  81. package/dist/modules/consent-purposes/index.d.ts.map +1 -0
  82. package/dist/modules/consent-purposes/index.js +41 -0
  83. package/dist/modules/consent-purposes/index.js.map +1 -0
  84. package/dist/modules/consent-purposes/repository.d.ts +21 -0
  85. package/dist/modules/consent-purposes/repository.d.ts.map +1 -0
  86. package/dist/modules/consent-purposes/repository.js +98 -0
  87. package/dist/modules/consent-purposes/repository.js.map +1 -0
  88. package/dist/modules/consent-purposes/routes.d.ts +39 -0
  89. package/dist/modules/consent-purposes/routes.d.ts.map +1 -0
  90. package/dist/modules/consent-purposes/routes.js +79 -0
  91. package/dist/modules/consent-purposes/routes.js.map +1 -0
  92. package/dist/modules/consent-purposes/schema.d.ts +175 -0
  93. package/dist/modules/consent-purposes/schema.d.ts.map +1 -0
  94. package/dist/modules/consent-purposes/schema.js +35 -0
  95. package/dist/modules/consent-purposes/schema.js.map +1 -0
  96. package/dist/modules/consent-purposes/service.d.ts +50 -0
  97. package/dist/modules/consent-purposes/service.d.ts.map +1 -0
  98. package/dist/modules/consent-purposes/service.js +263 -0
  99. package/dist/modules/consent-purposes/service.js.map +1 -0
  100. package/dist/modules/consent-purposes/starters.d.ts +17 -0
  101. package/dist/modules/consent-purposes/starters.d.ts.map +1 -0
  102. package/dist/modules/consent-purposes/starters.js +15 -0
  103. package/dist/modules/consent-purposes/starters.js.map +1 -0
  104. package/dist/modules/consent-purposes/tools.d.ts +4 -0
  105. package/dist/modules/consent-purposes/tools.d.ts.map +1 -0
  106. package/dist/modules/consent-purposes/tools.js +29 -0
  107. package/dist/modules/consent-purposes/tools.js.map +1 -0
  108. package/dist/modules/core.d.ts.map +1 -1
  109. package/dist/modules/core.js +21 -0
  110. package/dist/modules/core.js.map +1 -1
  111. package/dist/modules/custom-fields/capabilities.d.ts +12 -0
  112. package/dist/modules/custom-fields/capabilities.d.ts.map +1 -0
  113. package/dist/modules/custom-fields/capabilities.js +15 -0
  114. package/dist/modules/custom-fields/capabilities.js.map +1 -0
  115. package/dist/modules/custom-fields/events.d.ts +49 -0
  116. package/dist/modules/custom-fields/events.d.ts.map +1 -0
  117. package/dist/modules/custom-fields/events.js +25 -0
  118. package/dist/modules/custom-fields/events.js.map +1 -0
  119. package/dist/modules/custom-fields/index.d.ts +19 -0
  120. package/dist/modules/custom-fields/index.d.ts.map +1 -0
  121. package/dist/modules/custom-fields/index.js +46 -0
  122. package/dist/modules/custom-fields/index.js.map +1 -0
  123. package/dist/modules/custom-fields/repository.d.ts +37 -0
  124. package/dist/modules/custom-fields/repository.d.ts.map +1 -0
  125. package/dist/modules/custom-fields/repository.js +144 -0
  126. package/dist/modules/custom-fields/repository.js.map +1 -0
  127. package/dist/modules/custom-fields/routes.d.ts +44 -0
  128. package/dist/modules/custom-fields/routes.d.ts.map +1 -0
  129. package/dist/modules/custom-fields/routes.js +103 -0
  130. package/dist/modules/custom-fields/routes.js.map +1 -0
  131. package/dist/modules/custom-fields/schema.d.ts +215 -0
  132. package/dist/modules/custom-fields/schema.d.ts.map +1 -0
  133. package/dist/modules/custom-fields/schema.js +43 -0
  134. package/dist/modules/custom-fields/schema.js.map +1 -0
  135. package/dist/modules/custom-fields/service.d.ts +57 -0
  136. package/dist/modules/custom-fields/service.d.ts.map +1 -0
  137. package/dist/modules/custom-fields/service.js +273 -0
  138. package/dist/modules/custom-fields/service.js.map +1 -0
  139. package/dist/modules/custom-fields/tools.d.ts +4 -0
  140. package/dist/modules/custom-fields/tools.d.ts.map +1 -0
  141. package/dist/modules/custom-fields/tools.js +38 -0
  142. package/dist/modules/custom-fields/tools.js.map +1 -0
  143. package/dist/modules/custom-fields/values.d.ts +49 -0
  144. package/dist/modules/custom-fields/values.d.ts.map +1 -0
  145. package/dist/modules/custom-fields/values.js +249 -0
  146. package/dist/modules/custom-fields/values.js.map +1 -0
  147. package/dist/modules/custom-fields/wire.d.ts +12 -0
  148. package/dist/modules/custom-fields/wire.d.ts.map +1 -0
  149. package/dist/modules/custom-fields/wire.js +30 -0
  150. package/dist/modules/custom-fields/wire.js.map +1 -0
  151. package/dist/modules/dashboard/repository.d.ts.map +1 -1
  152. package/dist/modules/dashboard/repository.js +4 -3
  153. package/dist/modules/dashboard/repository.js.map +1 -1
  154. package/dist/modules/deals/index.d.ts +2 -1
  155. package/dist/modules/deals/index.d.ts.map +1 -1
  156. package/dist/modules/deals/index.js +5 -2
  157. package/dist/modules/deals/index.js.map +1 -1
  158. package/dist/modules/deals/repository.d.ts +0 -16
  159. package/dist/modules/deals/repository.d.ts.map +1 -1
  160. package/dist/modules/deals/repository.js +6 -76
  161. package/dist/modules/deals/repository.js.map +1 -1
  162. package/dist/modules/deals/routes.d.ts +14 -0
  163. package/dist/modules/deals/routes.d.ts.map +1 -1
  164. package/dist/modules/deals/routes.js +7 -0
  165. package/dist/modules/deals/routes.js.map +1 -1
  166. package/dist/modules/deals/schema.d.ts +20 -42
  167. package/dist/modules/deals/schema.d.ts.map +1 -1
  168. package/dist/modules/deals/schema.js +6 -11
  169. package/dist/modules/deals/schema.js.map +1 -1
  170. package/dist/modules/deals/service.d.ts +13 -2
  171. package/dist/modules/deals/service.d.ts.map +1 -1
  172. package/dist/modules/deals/service.js +43 -20
  173. package/dist/modules/deals/service.js.map +1 -1
  174. package/dist/modules/decisions/repository.d.ts.map +1 -1
  175. package/dist/modules/decisions/repository.js +2 -0
  176. package/dist/modules/decisions/repository.js.map +1 -1
  177. package/dist/modules/decisions/routes.d.ts +1 -0
  178. package/dist/modules/decisions/routes.d.ts.map +1 -1
  179. package/dist/modules/email-domain-linker/index.d.ts +12 -0
  180. package/dist/modules/email-domain-linker/index.d.ts.map +1 -0
  181. package/dist/modules/email-domain-linker/index.js +34 -0
  182. package/dist/modules/email-domain-linker/index.js.map +1 -0
  183. package/dist/modules/email-domain-linker/routes.d.ts +14 -0
  184. package/dist/modules/email-domain-linker/routes.d.ts.map +1 -0
  185. package/dist/modules/email-domain-linker/routes.js +15 -0
  186. package/dist/modules/email-domain-linker/routes.js.map +1 -0
  187. package/dist/modules/email-domain-linker/service.d.ts +37 -0
  188. package/dist/modules/email-domain-linker/service.d.ts.map +1 -0
  189. package/dist/modules/email-domain-linker/service.js +63 -0
  190. package/dist/modules/email-domain-linker/service.js.map +1 -0
  191. package/dist/modules/enquiries/events.d.ts +44 -0
  192. package/dist/modules/enquiries/events.d.ts.map +1 -0
  193. package/dist/modules/enquiries/events.js +19 -0
  194. package/dist/modules/enquiries/events.js.map +1 -0
  195. package/dist/modules/enquiries/index.d.ts +13 -0
  196. package/dist/modules/enquiries/index.d.ts.map +1 -0
  197. package/dist/modules/enquiries/index.js +44 -0
  198. package/dist/modules/enquiries/index.js.map +1 -0
  199. package/dist/modules/enquiries/repository.d.ts +30 -0
  200. package/dist/modules/enquiries/repository.d.ts.map +1 -0
  201. package/dist/modules/enquiries/repository.js +94 -0
  202. package/dist/modules/enquiries/repository.js.map +1 -0
  203. package/dist/modules/enquiries/routes.d.ts +52 -0
  204. package/dist/modules/enquiries/routes.d.ts.map +1 -0
  205. package/dist/modules/enquiries/routes.js +127 -0
  206. package/dist/modules/enquiries/routes.js.map +1 -0
  207. package/dist/modules/enquiries/schema.d.ts +290 -0
  208. package/dist/modules/enquiries/schema.d.ts.map +1 -0
  209. package/dist/modules/enquiries/schema.js +52 -0
  210. package/dist/modules/enquiries/schema.js.map +1 -0
  211. package/dist/modules/enquiries/service.d.ts +85 -0
  212. package/dist/modules/enquiries/service.d.ts.map +1 -0
  213. package/dist/modules/enquiries/service.js +370 -0
  214. package/dist/modules/enquiries/service.js.map +1 -0
  215. package/dist/modules/enquiries/tools.d.ts +4 -0
  216. package/dist/modules/enquiries/tools.d.ts.map +1 -0
  217. package/dist/modules/enquiries/tools.js +50 -0
  218. package/dist/modules/enquiries/tools.js.map +1 -0
  219. package/dist/modules/eventCatalogs.d.ts +4 -0
  220. package/dist/modules/eventCatalogs.d.ts.map +1 -1
  221. package/dist/modules/eventCatalogs.js +4 -0
  222. package/dist/modules/eventCatalogs.js.map +1 -1
  223. package/dist/modules/forms/embed.d.ts +20 -6
  224. package/dist/modules/forms/embed.d.ts.map +1 -1
  225. package/dist/modules/forms/embed.js +359 -43
  226. package/dist/modules/forms/embed.js.map +1 -1
  227. package/dist/modules/forms/events.d.ts +20 -7
  228. package/dist/modules/forms/events.d.ts.map +1 -1
  229. package/dist/modules/forms/events.js +20 -2
  230. package/dist/modules/forms/events.js.map +1 -1
  231. package/dist/modules/forms/fields.d.ts +14 -1
  232. package/dist/modules/forms/fields.d.ts.map +1 -1
  233. package/dist/modules/forms/fields.js +87 -3
  234. package/dist/modules/forms/fields.js.map +1 -1
  235. package/dist/modules/forms/index.d.ts.map +1 -1
  236. package/dist/modules/forms/index.js +12 -1
  237. package/dist/modules/forms/index.js.map +1 -1
  238. package/dist/modules/forms/mapping.d.ts +62 -5
  239. package/dist/modules/forms/mapping.d.ts.map +1 -1
  240. package/dist/modules/forms/mapping.js +139 -5
  241. package/dist/modules/forms/mapping.js.map +1 -1
  242. package/dist/modules/forms/publicRoutes.d.ts.map +1 -1
  243. package/dist/modules/forms/publicRoutes.js +29 -1
  244. package/dist/modules/forms/publicRoutes.js.map +1 -1
  245. package/dist/modules/forms/repository.d.ts +31 -0
  246. package/dist/modules/forms/repository.d.ts.map +1 -1
  247. package/dist/modules/forms/repository.js +90 -1
  248. package/dist/modules/forms/repository.js.map +1 -1
  249. package/dist/modules/forms/routes.d.ts +83 -1
  250. package/dist/modules/forms/routes.d.ts.map +1 -1
  251. package/dist/modules/forms/routes.js +185 -2
  252. package/dist/modules/forms/routes.js.map +1 -1
  253. package/dist/modules/forms/schema.d.ts +672 -1
  254. package/dist/modules/forms/schema.d.ts.map +1 -1
  255. package/dist/modules/forms/schema.js +146 -3
  256. package/dist/modules/forms/schema.js.map +1 -1
  257. package/dist/modules/forms/service.d.ts +54 -1
  258. package/dist/modules/forms/service.d.ts.map +1 -1
  259. package/dist/modules/forms/service.js +338 -28
  260. package/dist/modules/forms/service.js.map +1 -1
  261. package/dist/modules/forms/submission.d.ts +15 -0
  262. package/dist/modules/forms/submission.d.ts.map +1 -1
  263. package/dist/modules/forms/submission.js +418 -40
  264. package/dist/modules/forms/submission.js.map +1 -1
  265. package/dist/modules/import-export/drafts.d.ts +10 -0
  266. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  267. package/dist/modules/import-export/drafts.js +16 -2
  268. package/dist/modules/import-export/drafts.js.map +1 -1
  269. package/dist/modules/import-export/exportRows.d.ts +7 -4
  270. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  271. package/dist/modules/import-export/exportRows.js +20 -5
  272. package/dist/modules/import-export/exportRows.js.map +1 -1
  273. package/dist/modules/import-export/plan.d.ts +12 -1
  274. package/dist/modules/import-export/plan.d.ts.map +1 -1
  275. package/dist/modules/import-export/plan.js +29 -2
  276. package/dist/modules/import-export/plan.js.map +1 -1
  277. package/dist/modules/import-export/presets.d.ts.map +1 -1
  278. package/dist/modules/import-export/presets.js +10 -0
  279. package/dist/modules/import-export/presets.js.map +1 -1
  280. package/dist/modules/import-export/repository.d.ts +11 -1
  281. package/dist/modules/import-export/repository.d.ts.map +1 -1
  282. package/dist/modules/import-export/repository.js +42 -9
  283. package/dist/modules/import-export/repository.js.map +1 -1
  284. package/dist/modules/import-export/routes.d.ts.map +1 -1
  285. package/dist/modules/import-export/routes.js +4 -0
  286. package/dist/modules/import-export/routes.js.map +1 -1
  287. package/dist/modules/import-export/schema.d.ts +17 -0
  288. package/dist/modules/import-export/schema.d.ts.map +1 -1
  289. package/dist/modules/import-export/schema.js +11 -0
  290. package/dist/modules/import-export/schema.js.map +1 -1
  291. package/dist/modules/import-export/service.d.ts +6 -0
  292. package/dist/modules/import-export/service.d.ts.map +1 -1
  293. package/dist/modules/import-export/service.js +14 -2
  294. package/dist/modules/import-export/service.js.map +1 -1
  295. package/dist/modules/import-export/streams.d.ts.map +1 -1
  296. package/dist/modules/import-export/streams.js +3 -3
  297. package/dist/modules/import-export/streams.js.map +1 -1
  298. package/dist/modules/import-export/tools.d.ts.map +1 -1
  299. package/dist/modules/import-export/tools.js +8 -0
  300. package/dist/modules/import-export/tools.js.map +1 -1
  301. package/dist/modules/import-export/validation.d.ts.map +1 -1
  302. package/dist/modules/import-export/validation.js +22 -1
  303. package/dist/modules/import-export/validation.js.map +1 -1
  304. package/dist/modules/import-export/writes.d.ts.map +1 -1
  305. package/dist/modules/import-export/writes.js +37 -4
  306. package/dist/modules/import-export/writes.js.map +1 -1
  307. package/dist/modules/lists/events.d.ts +42 -0
  308. package/dist/modules/lists/events.d.ts.map +1 -0
  309. package/dist/modules/lists/events.js +16 -0
  310. package/dist/modules/lists/events.js.map +1 -0
  311. package/dist/modules/lists/index.d.ts +10 -0
  312. package/dist/modules/lists/index.d.ts.map +1 -0
  313. package/dist/modules/lists/index.js +35 -0
  314. package/dist/modules/lists/index.js.map +1 -0
  315. package/dist/modules/lists/repository.d.ts +80 -0
  316. package/dist/modules/lists/repository.d.ts.map +1 -0
  317. package/dist/modules/lists/repository.js +178 -0
  318. package/dist/modules/lists/repository.js.map +1 -0
  319. package/dist/modules/lists/routes.d.ts +55 -0
  320. package/dist/modules/lists/routes.d.ts.map +1 -0
  321. package/dist/modules/lists/routes.js +168 -0
  322. package/dist/modules/lists/routes.js.map +1 -0
  323. package/dist/modules/lists/schema.d.ts +281 -0
  324. package/dist/modules/lists/schema.d.ts.map +1 -0
  325. package/dist/modules/lists/schema.js +83 -0
  326. package/dist/modules/lists/schema.js.map +1 -0
  327. package/dist/modules/lists/service.d.ts +82 -0
  328. package/dist/modules/lists/service.d.ts.map +1 -0
  329. package/dist/modules/lists/service.js +262 -0
  330. package/dist/modules/lists/service.js.map +1 -0
  331. package/dist/modules/lists/tools.d.ts +4 -0
  332. package/dist/modules/lists/tools.d.ts.map +1 -0
  333. package/dist/modules/lists/tools.js +86 -0
  334. package/dist/modules/lists/tools.js.map +1 -0
  335. package/dist/modules/mcp/index.d.ts.map +1 -1
  336. package/dist/modules/mcp/index.js +5 -0
  337. package/dist/modules/mcp/index.js.map +1 -1
  338. package/dist/modules/notes/routes.d.ts +1 -0
  339. package/dist/modules/notes/routes.d.ts.map +1 -1
  340. package/dist/modules/opportunities/index.d.ts.map +1 -1
  341. package/dist/modules/opportunities/index.js +3 -1
  342. package/dist/modules/opportunities/index.js.map +1 -1
  343. package/dist/modules/opportunities/repository.d.ts +2 -0
  344. package/dist/modules/opportunities/repository.d.ts.map +1 -1
  345. package/dist/modules/opportunities/repository.js +4 -0
  346. package/dist/modules/opportunities/repository.js.map +1 -1
  347. package/dist/modules/opportunities/routes.d.ts +16 -0
  348. package/dist/modules/opportunities/routes.d.ts.map +1 -1
  349. package/dist/modules/opportunities/routes.js +13 -0
  350. package/dist/modules/opportunities/routes.js.map +1 -1
  351. package/dist/modules/opportunities/schema.d.ts +20 -0
  352. package/dist/modules/opportunities/schema.d.ts.map +1 -1
  353. package/dist/modules/opportunities/schema.js +6 -1
  354. package/dist/modules/opportunities/schema.js.map +1 -1
  355. package/dist/modules/opportunities/service.d.ts +20 -3
  356. package/dist/modules/opportunities/service.d.ts.map +1 -1
  357. package/dist/modules/opportunities/service.js +99 -18
  358. package/dist/modules/opportunities/service.js.map +1 -1
  359. package/dist/modules/opportunities/tools.d.ts.map +1 -1
  360. package/dist/modules/opportunities/tools.js +2 -0
  361. package/dist/modules/opportunities/tools.js.map +1 -1
  362. package/dist/modules/partnerships/index.d.ts.map +1 -1
  363. package/dist/modules/partnerships/index.js +3 -1
  364. package/dist/modules/partnerships/index.js.map +1 -1
  365. package/dist/modules/partnerships/repository.d.ts +0 -17
  366. package/dist/modules/partnerships/repository.d.ts.map +1 -1
  367. package/dist/modules/partnerships/repository.js +6 -82
  368. package/dist/modules/partnerships/repository.js.map +1 -1
  369. package/dist/modules/partnerships/routes.d.ts +14 -0
  370. package/dist/modules/partnerships/routes.d.ts.map +1 -1
  371. package/dist/modules/partnerships/routes.js +7 -0
  372. package/dist/modules/partnerships/routes.js.map +1 -1
  373. package/dist/modules/partnerships/schema.d.ts +20 -41
  374. package/dist/modules/partnerships/schema.d.ts.map +1 -1
  375. package/dist/modules/partnerships/schema.js +6 -10
  376. package/dist/modules/partnerships/schema.js.map +1 -1
  377. package/dist/modules/partnerships/service.d.ts +11 -1
  378. package/dist/modules/partnerships/service.d.ts.map +1 -1
  379. package/dist/modules/partnerships/service.js +43 -20
  380. package/dist/modules/partnerships/service.js.map +1 -1
  381. package/dist/modules/people/consentHydration.d.ts +26 -0
  382. package/dist/modules/people/consentHydration.d.ts.map +1 -0
  383. package/dist/modules/people/consentHydration.js +100 -0
  384. package/dist/modules/people/consentHydration.js.map +1 -0
  385. package/dist/modules/people/index.d.ts.map +1 -1
  386. package/dist/modules/people/index.js +3 -1
  387. package/dist/modules/people/index.js.map +1 -1
  388. package/dist/modules/people/personConsentWrites.d.ts +40 -0
  389. package/dist/modules/people/personConsentWrites.d.ts.map +1 -0
  390. package/dist/modules/people/personConsentWrites.js +98 -0
  391. package/dist/modules/people/personConsentWrites.js.map +1 -0
  392. package/dist/modules/people/repository.d.ts +11 -0
  393. package/dist/modules/people/repository.d.ts.map +1 -1
  394. package/dist/modules/people/repository.js +21 -1
  395. package/dist/modules/people/repository.js.map +1 -1
  396. package/dist/modules/people/routes.d.ts +57 -4
  397. package/dist/modules/people/routes.d.ts.map +1 -1
  398. package/dist/modules/people/routes.js +104 -5
  399. package/dist/modules/people/routes.js.map +1 -1
  400. package/dist/modules/people/schema.d.ts +366 -1
  401. package/dist/modules/people/schema.d.ts.map +1 -1
  402. package/dist/modules/people/schema.js +92 -2
  403. package/dist/modules/people/schema.js.map +1 -1
  404. package/dist/modules/people/service.d.ts +30 -1
  405. package/dist/modules/people/service.d.ts.map +1 -1
  406. package/dist/modules/people/service.js +131 -36
  407. package/dist/modules/people/service.js.map +1 -1
  408. package/dist/modules/people/tools.d.ts.map +1 -1
  409. package/dist/modules/people/tools.js +4 -1
  410. package/dist/modules/people/tools.js.map +1 -1
  411. package/dist/modules/personLinks.d.ts +79 -0
  412. package/dist/modules/personLinks.d.ts.map +1 -0
  413. package/dist/modules/personLinks.js +155 -0
  414. package/dist/modules/personLinks.js.map +1 -0
  415. package/dist/modules/pipelines/routes.d.ts +1 -0
  416. package/dist/modules/pipelines/routes.d.ts.map +1 -1
  417. package/dist/modules/plans/routes.d.ts +1 -0
  418. package/dist/modules/plans/routes.d.ts.map +1 -1
  419. package/dist/modules/positions/routes.d.ts.map +1 -1
  420. package/dist/modules/positions/routes.js +4 -2
  421. package/dist/modules/positions/routes.js.map +1 -1
  422. package/dist/modules/raises/index.d.ts.map +1 -1
  423. package/dist/modules/raises/index.js +3 -1
  424. package/dist/modules/raises/index.js.map +1 -1
  425. package/dist/modules/raises/repository.d.ts +0 -17
  426. package/dist/modules/raises/repository.d.ts.map +1 -1
  427. package/dist/modules/raises/repository.js +6 -77
  428. package/dist/modules/raises/repository.js.map +1 -1
  429. package/dist/modules/raises/routes.d.ts +14 -0
  430. package/dist/modules/raises/routes.d.ts.map +1 -1
  431. package/dist/modules/raises/routes.js +7 -0
  432. package/dist/modules/raises/routes.js.map +1 -1
  433. package/dist/modules/raises/schema.d.ts +20 -41
  434. package/dist/modules/raises/schema.d.ts.map +1 -1
  435. package/dist/modules/raises/schema.js +6 -10
  436. package/dist/modules/raises/schema.js.map +1 -1
  437. package/dist/modules/raises/service.d.ts +11 -1
  438. package/dist/modules/raises/service.d.ts.map +1 -1
  439. package/dist/modules/raises/service.js +41 -18
  440. package/dist/modules/raises/service.js.map +1 -1
  441. package/dist/modules/recordTargets.d.ts.map +1 -1
  442. package/dist/modules/recordTargets.js +2 -0
  443. package/dist/modules/recordTargets.js.map +1 -1
  444. package/dist/modules/references.d.ts +10 -0
  445. package/dist/modules/references.d.ts.map +1 -1
  446. package/dist/modules/references.js +27 -4
  447. package/dist/modules/references.js.map +1 -1
  448. package/dist/modules/sample-data/fixture.d.ts +160 -0
  449. package/dist/modules/sample-data/fixture.d.ts.map +1 -0
  450. package/dist/modules/sample-data/fixture.js +501 -0
  451. package/dist/modules/sample-data/fixture.js.map +1 -0
  452. package/dist/modules/sample-data/index.d.ts +11 -0
  453. package/dist/modules/sample-data/index.d.ts.map +1 -0
  454. package/dist/modules/sample-data/index.js +44 -0
  455. package/dist/modules/sample-data/index.js.map +1 -0
  456. package/dist/modules/sample-data/routes.d.ts +15 -0
  457. package/dist/modules/sample-data/routes.d.ts.map +1 -0
  458. package/dist/modules/sample-data/routes.js +25 -0
  459. package/dist/modules/sample-data/routes.js.map +1 -0
  460. package/dist/modules/sample-data/service.d.ts +39 -0
  461. package/dist/modules/sample-data/service.d.ts.map +1 -0
  462. package/dist/modules/sample-data/service.js +481 -0
  463. package/dist/modules/sample-data/service.js.map +1 -0
  464. package/dist/modules/sample-data/tools.d.ts +4 -0
  465. package/dist/modules/sample-data/tools.d.ts.map +1 -0
  466. package/dist/modules/sample-data/tools.js +22 -0
  467. package/dist/modules/sample-data/tools.js.map +1 -0
  468. package/dist/modules/search/index.d.ts +1 -1
  469. package/dist/modules/search/index.d.ts.map +1 -1
  470. package/dist/modules/search/index.js +2 -1
  471. package/dist/modules/search/index.js.map +1 -1
  472. package/dist/modules/search/repository.d.ts +1 -0
  473. package/dist/modules/search/repository.d.ts.map +1 -1
  474. package/dist/modules/search/repository.js +23 -0
  475. package/dist/modules/search/repository.js.map +1 -1
  476. package/dist/modules/search/service.d.ts +3 -3
  477. package/dist/modules/search/service.d.ts.map +1 -1
  478. package/dist/modules/search/service.js +5 -4
  479. package/dist/modules/search/service.js.map +1 -1
  480. package/dist/modules/smtp-email/index.d.ts +1 -0
  481. package/dist/modules/smtp-email/index.d.ts.map +1 -1
  482. package/dist/modules/smtp-email/index.js +1 -0
  483. package/dist/modules/smtp-email/index.js.map +1 -1
  484. package/dist/modules/stagedRecords.d.ts +3 -3
  485. package/dist/modules/stagedRecords.d.ts.map +1 -1
  486. package/dist/modules/stagedRecords.js +9 -0
  487. package/dist/modules/stagedRecords.js.map +1 -1
  488. package/dist/modules/webhooks/payloads.d.ts.map +1 -1
  489. package/dist/modules/webhooks/payloads.js +15 -2
  490. package/dist/modules/webhooks/payloads.js.map +1 -1
  491. package/dist/modules/workspace/repository.d.ts +2 -0
  492. package/dist/modules/workspace/repository.d.ts.map +1 -1
  493. package/dist/modules/workspace/repository.js +7 -0
  494. package/dist/modules/workspace/repository.js.map +1 -1
  495. package/dist/modules/workspace/service.d.ts.map +1 -1
  496. package/dist/modules/workspace/service.js +20 -1
  497. package/dist/modules/workspace/service.js.map +1 -1
  498. package/dist/modules/workspace/starters.d.ts.map +1 -1
  499. package/dist/modules/workspace/starters.js +5 -0
  500. package/dist/modules/workspace/starters.js.map +1 -1
  501. package/dist/runtime/events.d.ts +1 -1
  502. package/dist/runtime/events.d.ts.map +1 -1
  503. package/dist/runtime/events.js +1 -0
  504. package/dist/runtime/events.js.map +1 -1
  505. package/dist/schema/index.d.ts +4 -0
  506. package/dist/schema/index.d.ts.map +1 -1
  507. package/dist/schema/index.js +4 -0
  508. package/dist/schema/index.js.map +1 -1
  509. package/dist/testing/database.d.ts +5 -1
  510. package/dist/testing/database.d.ts.map +1 -1
  511. package/dist/testing/database.js +81 -10
  512. package/dist/testing/database.js.map +1 -1
  513. package/migrations/0021_certain_maggott.sql +30 -0
  514. package/migrations/0022_stormy_manta.sql +1 -0
  515. package/migrations/0023_funny_maddog.sql +1 -0
  516. package/migrations/0024_third_king_cobra.sql +46 -0
  517. package/migrations/0025_worthless_chimera.sql +3 -0
  518. package/migrations/0026_late_aqueduct.sql +46 -0
  519. package/migrations/0027_brainy_silver_sable.sql +3 -0
  520. package/migrations/0028_freezing_scrambler.sql +19 -0
  521. package/migrations/0029_custom_fields.sql +26 -0
  522. package/migrations/0030_enquiries.sql +79 -0
  523. package/migrations/0031_consent.sql +45 -0
  524. package/migrations/0032_form_field_statement.sql +1 -0
  525. package/migrations/0033_form_field_consent_purpose_ids.sql +5 -0
  526. package/migrations/0034_drop_form_field_consent_purpose_id.sql +1 -0
  527. package/migrations/0035_form_field_consent_purpose_labels.sql +1 -0
  528. package/migrations/0036_form_field_notice_type.sql +2 -0
  529. package/migrations/meta/0021_snapshot.json +5389 -0
  530. package/migrations/meta/0022_snapshot.json +5396 -0
  531. package/migrations/meta/0023_snapshot.json +5403 -0
  532. package/migrations/meta/0024_snapshot.json +5516 -0
  533. package/migrations/meta/0025_snapshot.json +5336 -0
  534. package/migrations/meta/0026_snapshot.json +5710 -0
  535. package/migrations/meta/0027_snapshot.json +5716 -0
  536. package/migrations/meta/0028_snapshot.json +5740 -0
  537. package/migrations/meta/0029_snapshot.json +5935 -0
  538. package/migrations/meta/0030_snapshot.json +6245 -0
  539. package/migrations/meta/0031_snapshot.json +6572 -0
  540. package/migrations/meta/0032_snapshot.json +6578 -0
  541. package/migrations/meta/0033_snapshot.json +6572 -0
  542. package/migrations/meta/0034_snapshot.json +6566 -0
  543. package/migrations/meta/0035_snapshot.json +6573 -0
  544. package/migrations/meta/0036_snapshot.json +6573 -0
  545. package/migrations/meta/_journal.json +112 -0
  546. package/package.json +3 -2
  547. package/src/lib/consumerEmailDomains.ts +62 -0
  548. package/src/lib/email.ts +7 -0
  549. package/src/lib/emailContent.ts +91 -0
  550. package/src/lib/emailDomainAutoLink.ts +165 -0
  551. package/src/lib/ids.ts +13 -0
  552. package/src/modules/activities/repository.ts +22 -23
  553. package/src/modules/activities/wording.ts +18 -0
  554. package/src/modules/agent-tasks/catalog.ts +63 -0
  555. package/src/modules/agent-tasks/resolve.ts +64 -24
  556. package/src/modules/attachedRecords.ts +37 -3
  557. package/src/modules/auth/preferences.ts +13 -1
  558. package/src/modules/auth/routes.ts +22 -0
  559. package/src/modules/auth/schema.ts +12 -2
  560. package/src/modules/auth/service.ts +37 -3
  561. package/src/modules/companies/index.ts +3 -1
  562. package/src/modules/companies/repository.ts +3 -0
  563. package/src/modules/companies/routes.ts +20 -0
  564. package/src/modules/companies/schema.ts +11 -1
  565. package/src/modules/companies/service.ts +72 -12
  566. package/src/modules/consent-purposes/capabilities.ts +12 -0
  567. package/src/modules/consent-purposes/events.ts +38 -0
  568. package/src/modules/consent-purposes/index.ts +48 -0
  569. package/src/modules/consent-purposes/repository.ts +163 -0
  570. package/src/modules/consent-purposes/routes.ts +122 -0
  571. package/src/modules/consent-purposes/schema.ts +46 -0
  572. package/src/modules/consent-purposes/service.ts +423 -0
  573. package/src/modules/consent-purposes/starters.ts +32 -0
  574. package/src/modules/consent-purposes/tools.ts +44 -0
  575. package/src/modules/core.ts +21 -0
  576. package/src/modules/custom-fields/capabilities.ts +17 -0
  577. package/src/modules/custom-fields/events.ts +51 -0
  578. package/src/modules/custom-fields/index.ts +61 -0
  579. package/src/modules/custom-fields/repository.ts +225 -0
  580. package/src/modules/custom-fields/routes.ts +155 -0
  581. package/src/modules/custom-fields/schema.ts +61 -0
  582. package/src/modules/custom-fields/service.ts +439 -0
  583. package/src/modules/custom-fields/tools.ts +53 -0
  584. package/src/modules/custom-fields/values.ts +352 -0
  585. package/src/modules/custom-fields/wire.ts +32 -0
  586. package/src/modules/dashboard/repository.ts +4 -3
  587. package/src/modules/deals/index.ts +5 -2
  588. package/src/modules/deals/repository.ts +6 -106
  589. package/src/modules/deals/routes.ts +7 -0
  590. package/src/modules/deals/schema.ts +7 -15
  591. package/src/modules/deals/service.ts +92 -23
  592. package/src/modules/decisions/repository.ts +2 -0
  593. package/src/modules/email-domain-linker/index.ts +40 -0
  594. package/src/modules/email-domain-linker/routes.ts +40 -0
  595. package/src/modules/email-domain-linker/service.ts +122 -0
  596. package/src/modules/enquiries/events.ts +45 -0
  597. package/src/modules/enquiries/index.ts +50 -0
  598. package/src/modules/enquiries/repository.ts +164 -0
  599. package/src/modules/enquiries/routes.ts +172 -0
  600. package/src/modules/enquiries/schema.ts +59 -0
  601. package/src/modules/enquiries/service.ts +644 -0
  602. package/src/modules/enquiries/tools.ts +66 -0
  603. package/src/modules/eventCatalogs.ts +4 -0
  604. package/src/modules/forms/embed.ts +391 -44
  605. package/src/modules/forms/events.ts +30 -2
  606. package/src/modules/forms/fields.ts +102 -2
  607. package/src/modules/forms/index.ts +12 -1
  608. package/src/modules/forms/mapping.ts +183 -6
  609. package/src/modules/forms/publicRoutes.ts +43 -1
  610. package/src/modules/forms/repository.ts +162 -1
  611. package/src/modules/forms/routes.ts +212 -2
  612. package/src/modules/forms/schema.ts +166 -4
  613. package/src/modules/forms/service.ts +565 -41
  614. package/src/modules/forms/submission.ts +718 -44
  615. package/src/modules/import-export/drafts.ts +20 -1
  616. package/src/modules/import-export/exportRows.ts +21 -5
  617. package/src/modules/import-export/plan.ts +47 -2
  618. package/src/modules/import-export/presets.ts +10 -0
  619. package/src/modules/import-export/repository.ts +73 -8
  620. package/src/modules/import-export/routes.ts +4 -0
  621. package/src/modules/import-export/schema.ts +11 -0
  622. package/src/modules/import-export/service.ts +28 -2
  623. package/src/modules/import-export/streams.ts +3 -1
  624. package/src/modules/import-export/tools.ts +10 -0
  625. package/src/modules/import-export/validation.ts +28 -0
  626. package/src/modules/import-export/writes.ts +70 -5
  627. package/src/modules/lists/events.ts +41 -0
  628. package/src/modules/lists/index.ts +41 -0
  629. package/src/modules/lists/repository.ts +343 -0
  630. package/src/modules/lists/routes.ts +255 -0
  631. package/src/modules/lists/schema.ts +95 -0
  632. package/src/modules/lists/service.ts +505 -0
  633. package/src/modules/lists/tools.ts +128 -0
  634. package/src/modules/mcp/index.ts +5 -0
  635. package/src/modules/opportunities/index.ts +3 -1
  636. package/src/modules/opportunities/repository.ts +11 -0
  637. package/src/modules/opportunities/routes.ts +13 -0
  638. package/src/modules/opportunities/schema.ts +7 -1
  639. package/src/modules/opportunities/service.ts +188 -22
  640. package/src/modules/opportunities/tools.ts +2 -0
  641. package/src/modules/partnerships/index.ts +3 -1
  642. package/src/modules/partnerships/repository.ts +6 -117
  643. package/src/modules/partnerships/routes.ts +7 -0
  644. package/src/modules/partnerships/schema.ts +7 -14
  645. package/src/modules/partnerships/service.ts +93 -22
  646. package/src/modules/people/consentHydration.ts +167 -0
  647. package/src/modules/people/index.ts +3 -1
  648. package/src/modules/people/personConsentWrites.ts +177 -0
  649. package/src/modules/people/repository.ts +31 -0
  650. package/src/modules/people/routes.ts +127 -18
  651. package/src/modules/people/schema.ts +109 -3
  652. package/src/modules/people/service.ts +205 -39
  653. package/src/modules/people/tools.ts +5 -1
  654. package/src/modules/personLinks.ts +278 -0
  655. package/src/modules/positions/routes.ts +4 -2
  656. package/src/modules/raises/index.ts +3 -1
  657. package/src/modules/raises/repository.ts +6 -107
  658. package/src/modules/raises/routes.ts +7 -0
  659. package/src/modules/raises/schema.ts +7 -14
  660. package/src/modules/raises/service.ts +91 -20
  661. package/src/modules/recordTargets.ts +2 -0
  662. package/src/modules/references.ts +43 -4
  663. package/src/modules/sample-data/fixture.ts +690 -0
  664. package/src/modules/sample-data/index.ts +51 -0
  665. package/src/modules/sample-data/routes.ts +50 -0
  666. package/src/modules/sample-data/service.ts +679 -0
  667. package/src/modules/sample-data/tools.ts +32 -0
  668. package/src/modules/search/index.ts +2 -1
  669. package/src/modules/search/repository.ts +33 -1
  670. package/src/modules/search/service.ts +7 -5
  671. package/src/modules/smtp-email/index.ts +8 -1
  672. package/src/modules/stagedRecords.ts +18 -3
  673. package/src/modules/webhooks/payloads.ts +20 -2
  674. package/src/modules/workspace/repository.ts +12 -0
  675. package/src/modules/workspace/service.ts +27 -1
  676. package/src/modules/workspace/starters.ts +5 -0
  677. package/src/runtime/events.ts +1 -0
  678. package/src/schema/index.ts +4 -0
  679. package/src/testing/database.ts +97 -11
@@ -1,6 +1,9 @@
1
+ import type { ConsentStatus, CustomFieldWireValue } from '@kelpie/schemas'
2
+
1
3
  import { changedKeys } from '../../lib/changes.ts'
2
4
  import { UNIQUE_VIOLATION, isReferenceViolation, postgresErrorCode } from '../../lib/database.ts'
3
5
  import type { Database } from '../../lib/database.ts'
6
+ import { autoLinkPersonByEmailDomain } from '../../lib/emailDomainAutoLink.ts'
4
7
  import { AppError } from '../../lib/errors.ts'
5
8
  import type { IdFactory } from '../../lib/ids.ts'
6
9
  import { normaliseEmail } from '../../lib/normalisation.ts'
@@ -18,11 +21,17 @@ import {
18
21
  deleteRecordsAttachedTo,
19
22
  deleteRecordsAttachedToCandidaciesOf,
20
23
  } from '../attachedRecords.ts'
21
- import { referencedElsewhere } from '../references.ts'
24
+ import type { CustomFieldValuesValidator } from '../custom-fields/values.ts'
25
+ import * as personLinks from '../personLinks.ts'
26
+ import { referenceViolationTable } from '../../lib/database.ts'
27
+ import { referencedByPipelineRecords, referencedElsewhere } from '../references.ts'
22
28
  import * as repository from './repository.ts'
23
29
  import { DEFAULT_PERSON_SORT, PERSON_SORTS } from './repository.ts'
24
30
  import type { PersonFilters, PersonRecord } from './repository.ts'
25
31
  import type { Influence, PreferredChannel, Relationship, SocialProfile } from './schema.ts'
32
+ import { readConsentsFor, readConsentsForMany } from './consentHydration.ts'
33
+ import type { EffectiveConsent } from './consentHydration.ts'
34
+ import { applyManualConsentWrites, consentChangedPaths } from './personConsentWrites.ts'
26
35
 
27
36
  /**
28
37
  * People: who the workspace knows.
@@ -40,6 +49,7 @@ export interface PeopleDependencies {
40
49
  readonly createId: IdFactory
41
50
  readonly now: () => Date
42
51
  readonly recordActivity: ActivityRecorder
52
+ readonly customFields: CustomFieldValuesValidator
43
53
  }
44
54
 
45
55
  /**
@@ -51,6 +61,10 @@ export interface PeopleDependencies {
51
61
  */
52
62
  const PERSON_FIELD_LABELS: FieldLabels = {
53
63
  name: 'Name',
64
+ salutation: 'Salutation',
65
+ firstName: 'First name',
66
+ lastName: 'Last name',
67
+ suffix: 'Suffix',
54
68
  email: 'Email',
55
69
  phones: 'Phone numbers',
56
70
  socialProfiles: 'Social profiles',
@@ -62,6 +76,7 @@ const PERSON_FIELD_LABELS: FieldLabels = {
62
76
  summary: 'Summary',
63
77
  tags: 'Tags',
64
78
  lastContactedAt: 'Last contacted',
79
+ doNotContact: 'Do not contact',
65
80
  }
66
81
 
67
82
  /**
@@ -70,10 +85,27 @@ const PERSON_FIELD_LABELS: FieldLabels = {
70
85
  * Deliberately an alias rather than a parallel interface. A hand-written copy of
71
86
  * fifteen fields drifts from the table the first time one is added.
72
87
  */
73
- export type PersonView = Omit<PersonRecord, 'workspaceId'>
88
+ export type PersonView = Omit<PersonRecord, 'workspaceId'> & {
89
+ /**
90
+ * The effective consent status for every workspace purpose. An entry with
91
+ * `inherited: true` has no explicit `person_consents` row and carries the
92
+ * purpose's `default_status`; the rest have their own row.
93
+ */
94
+ readonly consents: readonly EffectiveConsent[]
95
+ }
96
+
97
+ export interface PersonConsentWriteInput {
98
+ readonly purposeSlug: string
99
+ readonly status: ConsentStatus | null
100
+ }
74
101
 
75
102
  export interface CreatePersonInput {
103
+ /** Already resolved. The route composes one from the parts when the caller sent none. */
76
104
  readonly name: string
105
+ readonly salutation: string | null
106
+ readonly firstName: string | null
107
+ readonly lastName: string | null
108
+ readonly suffix: string | null
77
109
  readonly email: string | null
78
110
  readonly phones: readonly string[]
79
111
  readonly socialProfiles: readonly SocialProfile[]
@@ -85,6 +117,15 @@ export interface CreatePersonInput {
85
117
  readonly summary: string
86
118
  readonly tags: readonly string[]
87
119
  readonly lastContactedAt: Date | null
120
+ readonly doNotContact: boolean
121
+ /**
122
+ * Consent writes for named purposes. `status: null` deletes the row and
123
+ * inherits the purpose default; anything else upserts `source: manual`.
124
+ * Absent purposes are left alone.
125
+ */
126
+ readonly consents: readonly PersonConsentWriteInput[]
127
+ /** Wire shape merge patch (undefined for a create without any): sent keys change, null clears. */
128
+ readonly customFields: Readonly<Record<string, CustomFieldWireValue | null>> | undefined
88
129
  }
89
130
 
90
131
  /** PATCH semantics: an absent field is left alone, and null clears a nullable one. */
@@ -98,10 +139,10 @@ export interface PeopleService {
98
139
  remove(actor: Actor, id: string): Promise<void>
99
140
  }
100
141
 
101
- function toView(record: PersonRecord): PersonView {
142
+ function toView(record: PersonRecord, consents: readonly EffectiveConsent[]): PersonView {
102
143
  const { workspaceId: _workspaceId, ...view } = record
103
144
 
104
- return view
145
+ return { ...view, consents }
105
146
  }
106
147
 
107
148
  /**
@@ -112,6 +153,10 @@ function toView(record: PersonRecord): PersonView {
112
153
  function toStoredColumns(input: UpdatePersonInput): Partial<repository.PersonColumns> {
113
154
  return {
114
155
  ...(input.name === undefined ? {} : { name: input.name }),
156
+ ...(input.salutation === undefined ? {} : { salutation: input.salutation }),
157
+ ...(input.firstName === undefined ? {} : { firstName: input.firstName }),
158
+ ...(input.lastName === undefined ? {} : { lastName: input.lastName }),
159
+ ...(input.suffix === undefined ? {} : { suffix: input.suffix }),
115
160
  ...(input.email === undefined ? {} : { email: input.email === null ? null : normaliseEmail(input.email) }),
116
161
  ...(input.phones === undefined ? {} : { phones: input.phones }),
117
162
  ...(input.socialProfiles === undefined ? {} : { socialProfiles: input.socialProfiles }),
@@ -123,6 +168,7 @@ function toStoredColumns(input: UpdatePersonInput): Partial<repository.PersonCol
123
168
  ...(input.summary === undefined ? {} : { summary: input.summary }),
124
169
  ...(input.tags === undefined ? {} : { tags: [...input.tags] }),
125
170
  ...(input.lastContactedAt === undefined ? {} : { lastContactedAt: input.lastContactedAt }),
171
+ ...(input.doNotContact === undefined ? {} : { doNotContact: input.doNotContact }),
126
172
  }
127
173
  }
128
174
 
@@ -150,12 +196,22 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
150
196
  const workspaceId = requireWorkspaceId(actor)
151
197
  const window = readListWindow(query, PERSON_SORTS, DEFAULT_PERSON_SORT)
152
198
  const rows = await repository.listPeople(dependencies.db, workspaceId, filters, window)
199
+ const consentsByPerson = await readConsentsForMany(
200
+ dependencies.db,
201
+ workspaceId,
202
+ rows.map((row) => row.id),
203
+ )
153
204
 
154
- return mapPage(toPage(rows, window, (person) => person.id), toView)
205
+ return mapPage(toPage(rows, window, (person) => person.id), (record) =>
206
+ toView(record, consentsByPerson.get(record.id) ?? []),
207
+ )
155
208
  },
156
209
 
157
210
  async get(actor, id) {
158
- return toView(await require(requireWorkspaceId(actor), id))
211
+ const workspaceId = requireWorkspaceId(actor)
212
+ const record = await require(workspaceId, id)
213
+ const consents = await readConsentsFor(dependencies.db, workspaceId, id)
214
+ return toView(record, consents)
159
215
  },
160
216
 
161
217
  async create(actor, input) {
@@ -164,6 +220,12 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
164
220
 
165
221
  return dependencies.transaction(
166
222
  async ({ tx, events }) => {
223
+ const customFields = await dependencies.customFields.forCreate(
224
+ tx,
225
+ workspaceId,
226
+ 'person',
227
+ input.customFields,
228
+ )
167
229
  let created: PersonRecord
168
230
 
169
231
  try {
@@ -171,6 +233,10 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
171
233
  id,
172
234
  workspaceId,
173
235
  name: input.name,
236
+ salutation: input.salutation,
237
+ firstName: input.firstName,
238
+ lastName: input.lastName,
239
+ suffix: input.suffix,
174
240
  email: input.email === null ? null : normaliseEmail(input.email),
175
241
  phones: input.phones,
176
242
  socialProfiles: input.socialProfiles,
@@ -182,6 +248,8 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
182
248
  summary: input.summary,
183
249
  tags: [...input.tags],
184
250
  lastContactedAt: input.lastContactedAt,
251
+ doNotContact: input.doNotContact,
252
+ customFields,
185
253
  })
186
254
  } catch (error: unknown) {
187
255
  if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
@@ -191,6 +259,16 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
191
259
  throw error
192
260
  }
193
261
 
262
+ if (input.consents.length > 0) {
263
+ await applyManualConsentWrites(
264
+ tx,
265
+ workspaceId,
266
+ created.id,
267
+ input.consents,
268
+ dependencies.now(),
269
+ )
270
+ }
271
+
194
272
  await dependencies.recordActivity(tx, workspaceId, actor, {
195
273
  targetType: 'person',
196
274
  targetId: created.id,
@@ -200,7 +278,17 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
200
278
 
201
279
  events.emit('people.person.created', { type: 'person', id: created.id }, {})
202
280
 
203
- return toView(created)
281
+ // Sync auto-link. Inside the same transaction so the response returns
282
+ // with the Position already visible to a follow-up read; without this
283
+ // the UI would not see the new Position until a manual refresh.
284
+ await autoLinkPersonByEmailDomain(tx, events, workspaceId, created, {
285
+ createId: dependencies.createId,
286
+ now: dependencies.now,
287
+ recordActivity: dependencies.recordActivity,
288
+ })
289
+
290
+ const consents = await readConsentsFor(tx, workspaceId, created.id)
291
+ return toView(created, consents)
204
292
  },
205
293
  { workspaceId, actor: toEventActor(actor) },
206
294
  )
@@ -210,50 +298,109 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
210
298
  const workspaceId = requireWorkspaceId(actor)
211
299
  const existing = await require(workspaceId, id)
212
300
  const columns = toStoredColumns(changes)
213
- const changed = changedKeys(existing, columns)
214
-
215
- // A PATCH that changes nothing is not a write. Bumping `updated_at` for it
216
- // would make the record look freshly touched to everything that sorts or
217
- // filters by it.
218
- if (changed.length === 0) {
219
- return toView(existing)
220
- }
301
+ const scalarChanged = changedKeys(existing, columns)
302
+ const consentWrites = changes.consents ?? []
221
303
 
222
304
  return dependencies.transaction(
223
305
  async ({ tx, events }) => {
306
+ const cf = await dependencies.customFields.forUpdate(
307
+ tx,
308
+ workspaceId,
309
+ 'person',
310
+ existing.customFields,
311
+ changes.customFields,
312
+ )
313
+ const customFieldsChanged = cf !== undefined && cf.changedPaths.length > 0
314
+
315
+ const consentChanges =
316
+ consentWrites.length > 0
317
+ ? await applyManualConsentWrites(
318
+ tx,
319
+ workspaceId,
320
+ id,
321
+ consentWrites,
322
+ dependencies.now(),
323
+ )
324
+ : []
325
+ const consentPaths = consentChangedPaths(consentChanges)
326
+ const consentActuallyChanged = consentPaths.length > 0
327
+
328
+ // A PATCH that changes nothing is not a write. Bumping `updated_at`
329
+ // would make the record look freshly touched to everything that sorts
330
+ // or filters by it.
331
+ if (
332
+ scalarChanged.length === 0 &&
333
+ !customFieldsChanged &&
334
+ !consentActuallyChanged
335
+ ) {
336
+ const consents = await readConsentsFor(tx, workspaceId, id)
337
+ return toView(existing, consents)
338
+ }
339
+
224
340
  let updated: PersonRecord | undefined
225
341
 
226
- try {
227
- updated = await repository.updatePerson(tx, workspaceId, id, {
228
- ...columns,
229
- updatedAt: dependencies.now(),
230
- })
231
- } catch (error: unknown) {
232
- if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
233
- throw duplicateEmail()
342
+ if (scalarChanged.length > 0 || customFieldsChanged) {
343
+ try {
344
+ updated = await repository.updatePerson(tx, workspaceId, id, {
345
+ ...columns,
346
+ ...(customFieldsChanged ? { customFields: cf.merged } : {}),
347
+ updatedAt: dependencies.now(),
348
+ })
349
+ } catch (error: unknown) {
350
+ if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
351
+ throw duplicateEmail()
352
+ }
353
+
354
+ throw error
234
355
  }
235
356
 
236
- throw error
357
+ if (updated === undefined) {
358
+ throw AppError.notFound('Person not found')
359
+ }
360
+ } else {
361
+ updated = existing
237
362
  }
238
363
 
239
- if (updated === undefined) {
240
- throw AppError.notFound('Person not found')
241
- }
364
+ const customFieldPaths = cf?.changedPaths ?? []
365
+ const activityChanged = [...scalarChanged, ...customFieldPaths, ...consentPaths]
242
366
 
243
- await dependencies.recordActivity(tx, workspaceId, actor, {
244
- targetType: 'person',
245
- targetId: id,
246
- kind: 'updated',
247
- ...describeUpdate(changed, PERSON_FIELD_LABELS, existing, columns),
248
- })
367
+ if (activityChanged.length > 0) {
368
+ const labels: Record<string, string> = { ...PERSON_FIELD_LABELS, ...cf?.labels }
369
+ for (const change of consentChanges) {
370
+ labels[`consents.${change.purposeSlug}`] = `Consent · ${change.purposeLabel}`
371
+ }
372
+ const before: Record<string, unknown> = { ...existing, ...cf?.flatBefore }
373
+ const after: Record<string, unknown> = { ...columns, ...cf?.flatAfter }
374
+ for (const change of consentChanges) {
375
+ before[`consents.${change.purposeSlug}`] = change.previousStatus ?? 'inherits'
376
+ after[`consents.${change.purposeSlug}`] = change.status ?? 'inherits'
377
+ }
378
+ await dependencies.recordActivity(tx, workspaceId, actor, {
379
+ targetType: 'person',
380
+ targetId: id,
381
+ kind: 'updated',
382
+ ...describeUpdate(activityChanged, labels, before, after),
383
+ })
384
+ }
249
385
 
250
386
  events.emit(
251
387
  'people.person.updated',
252
388
  { type: 'person', id },
253
- { changed },
389
+ { changed: activityChanged },
254
390
  )
255
391
 
256
- return toView(updated)
392
+ // Sync auto-link when the email moved. Same-transaction rationale as
393
+ // the create path above.
394
+ if (scalarChanged.includes('email')) {
395
+ await autoLinkPersonByEmailDomain(tx, events, workspaceId, updated, {
396
+ createId: dependencies.createId,
397
+ now: dependencies.now,
398
+ recordActivity: dependencies.recordActivity,
399
+ })
400
+ }
401
+
402
+ const consents = await readConsentsFor(tx, workspaceId, id)
403
+ return toView(updated, consents)
257
404
  },
258
405
  { workspaceId, actor: toEventActor(actor) },
259
406
  )
@@ -275,14 +422,33 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
275
422
  // notes have to be taken here: no hiring service sees that delete.
276
423
  await deleteRecordsAttachedToCandidaciesOf(tx, workspaceId, id)
277
424
 
425
+ // A person delete failing on a foreign key aborts the enclosing
426
+ // transaction, so the follow-up read that names the referring pipeline
427
+ // types would run against a dead tx. Wrap only the delete in a nested
428
+ // transaction: drizzle emits SAVEPOINT/ROLLBACK TO for it, so the
429
+ // outer tx survives the refusal and the listLinkedTargetTypes read
430
+ // below sees person_links.
431
+ let deleteError: unknown = null
432
+
278
433
  try {
279
- await repository.deletePerson(tx, workspaceId, id)
434
+ await tx.transaction(async (savepoint) => {
435
+ await repository.deletePerson(savepoint, workspaceId, id)
436
+ })
280
437
  } catch (error: unknown) {
281
- if (isReferenceViolation(error)) {
282
- throw referencedElsewhere(error, 'person')
438
+ deleteError = error
439
+ }
440
+
441
+ if (deleteError !== null) {
442
+ if (isReferenceViolation(deleteError)) {
443
+ if (referenceViolationTable(deleteError) === 'person_links') {
444
+ const types = await personLinks.listLinkedTargetTypes(tx, workspaceId, id)
445
+ throw referencedByPipelineRecords('person', types)
446
+ }
447
+
448
+ throw referencedElsewhere(deleteError, 'person')
283
449
  }
284
450
 
285
- throw error
451
+ throw deleteError
286
452
  }
287
453
 
288
454
  events.emit('people.person.deleted', { type: 'person', id }, {})
@@ -19,7 +19,11 @@ export function registerPeopleTools(mcp: McpToolRegistry, service: PeopleService
19
19
  registerCrudTools(mcp, {
20
20
  resource: 'people',
21
21
  subject: 'person',
22
- about: 'Someone the workspace knows. A job title belongs to a position, never to the person.',
22
+ about:
23
+ 'Someone the workspace knows. A job title belongs to a position, never to the person. ' +
24
+ 'name is the display name every list shows; first_name, last_name, salutation and suffix ' +
25
+ 'are optional parts beside it. A create with no name composes one from first_name and ' +
26
+ 'last_name. Changing a part never rewrites name.',
23
27
  service,
24
28
  render: personResponse,
25
29
  listArgs,
@@ -0,0 +1,278 @@
1
+ import { and, asc, eq, inArray, sql } from 'drizzle-orm'
2
+ import type { AnyPgColumn } from 'drizzle-orm/pg-core'
3
+ import type { PipelineKind } from '@kelpie/schemas'
4
+
5
+ import type { IdFactory } from '../lib/ids.ts'
6
+ import type { Queryable } from '../runtime/transaction.ts'
7
+ import { people, personLinks } from './people/schema.ts'
8
+
9
+ /**
10
+ * Shared reader/writer for `person_links`, the polymorphic table that holds a
11
+ * person's involvement in a pipeline record. Every deal/opportunity/raise/
12
+ * partnership service reaches through here rather than owning its own join
13
+ * table. `personLinks` is defined in `people/schema.ts` because the person
14
+ * side of the relation is what gives it the real foreign key.
15
+ *
16
+ * All functions take the caller's `Queryable` and `workspaceId` so every
17
+ * query rides the `(workspace_id, target_type, target_id)` index and lands in
18
+ * whatever transaction the caller opened.
19
+ */
20
+
21
+ /**
22
+ * One target the caller writes to. Kept named rather than positional so
23
+ * `linkPeople(db, ids, ws, 'deal', dealId, personIds)` cannot swap the last
24
+ * two arguments silently.
25
+ */
26
+ export interface PipelineTarget {
27
+ readonly targetType: PipelineKind
28
+ readonly targetId: string
29
+ }
30
+
31
+ /**
32
+ * The people on one pipeline record, ordered by person_id so a response is
33
+ * stable across reads. Mirrors the deals repository's old `listPersonIds`.
34
+ */
35
+ export async function listPersonIds(
36
+ db: Queryable,
37
+ workspaceId: string,
38
+ target: PipelineTarget,
39
+ ): Promise<string[]> {
40
+ const rows = await db
41
+ .select({ personId: personLinks.personId })
42
+ .from(personLinks)
43
+ .where(
44
+ and(
45
+ eq(personLinks.workspaceId, workspaceId),
46
+ eq(personLinks.targetType, target.targetType),
47
+ eq(personLinks.targetId, target.targetId),
48
+ ),
49
+ )
50
+ .orderBy(asc(personLinks.personId))
51
+
52
+ return rows.map((row) => row.personId)
53
+ }
54
+
55
+ /**
56
+ * The people on each of a page of pipeline records of one type, in one query
57
+ * rather than one per row. Ids missing from the map have no people.
58
+ */
59
+ export async function listPersonIdsFor(
60
+ db: Queryable,
61
+ workspaceId: string,
62
+ targetType: PipelineKind,
63
+ targetIds: readonly string[],
64
+ ): Promise<ReadonlyMap<string, readonly string[]>> {
65
+ if (targetIds.length === 0) {
66
+ return new Map()
67
+ }
68
+
69
+ const rows = await db
70
+ .select({ targetId: personLinks.targetId, personId: personLinks.personId })
71
+ .from(personLinks)
72
+ .where(
73
+ and(
74
+ eq(personLinks.workspaceId, workspaceId),
75
+ eq(personLinks.targetType, targetType),
76
+ inArray(personLinks.targetId, targetIds),
77
+ ),
78
+ )
79
+ .orderBy(asc(personLinks.personId))
80
+
81
+ const byTarget = new Map<string, string[]>()
82
+
83
+ for (const row of rows) {
84
+ const existing = byTarget.get(row.targetId)
85
+
86
+ if (existing === undefined) {
87
+ byTarget.set(row.targetId, [row.personId])
88
+ } else {
89
+ existing.push(row.personId)
90
+ }
91
+ }
92
+
93
+ return byTarget
94
+ }
95
+
96
+ /**
97
+ * Every pipeline record a person is on, in one query. Used by the person
98
+ * activity roll-up and the agent-tasks person case, which used to run one
99
+ * query per join table.
100
+ */
101
+ export async function listTargetsOfPerson(
102
+ db: Queryable,
103
+ workspaceId: string,
104
+ personId: string,
105
+ ): Promise<readonly PipelineTarget[]> {
106
+ const rows = await db
107
+ .select({ targetType: personLinks.targetType, targetId: personLinks.targetId })
108
+ .from(personLinks)
109
+ .where(and(eq(personLinks.workspaceId, workspaceId), eq(personLinks.personId, personId)))
110
+
111
+ return rows.map((row) => ({
112
+ targetType: row.targetType as PipelineKind,
113
+ targetId: row.targetId,
114
+ }))
115
+ }
116
+
117
+ /**
118
+ * The distinct target types still pointing at a person. Used by the 409 on
119
+ * person delete to name each pipeline the person is on, without loading every
120
+ * row.
121
+ */
122
+ export async function listLinkedTargetTypes(
123
+ db: Queryable,
124
+ workspaceId: string,
125
+ personId: string,
126
+ ): Promise<readonly PipelineKind[]> {
127
+ const rows = await db
128
+ .selectDistinct({ targetType: personLinks.targetType })
129
+ .from(personLinks)
130
+ .where(and(eq(personLinks.workspaceId, workspaceId), eq(personLinks.personId, personId)))
131
+
132
+ return rows.map((row) => row.targetType as PipelineKind)
133
+ }
134
+
135
+ /** Bulk insert; callers pre-dedupe as today. No-op on empty. */
136
+ export async function linkPeople(
137
+ db: Queryable,
138
+ createId: IdFactory,
139
+ workspaceId: string,
140
+ target: PipelineTarget,
141
+ personIds: readonly string[],
142
+ ): Promise<void> {
143
+ if (personIds.length === 0) {
144
+ return
145
+ }
146
+
147
+ await db.insert(personLinks).values(
148
+ personIds.map((personId) => ({
149
+ id: createId('personLink'),
150
+ workspaceId,
151
+ personId,
152
+ targetType: target.targetType,
153
+ targetId: target.targetId,
154
+ })),
155
+ )
156
+ }
157
+
158
+ /** Bulk delete matching a set of people. No-op on empty. */
159
+ export async function unlinkPeople(
160
+ db: Queryable,
161
+ workspaceId: string,
162
+ target: PipelineTarget,
163
+ personIds: readonly string[],
164
+ ): Promise<void> {
165
+ if (personIds.length === 0) {
166
+ return
167
+ }
168
+
169
+ await db
170
+ .delete(personLinks)
171
+ .where(
172
+ and(
173
+ eq(personLinks.workspaceId, workspaceId),
174
+ eq(personLinks.targetType, target.targetType),
175
+ eq(personLinks.targetId, target.targetId),
176
+ inArray(personLinks.personId, personIds),
177
+ ),
178
+ )
179
+ }
180
+
181
+ /**
182
+ * Link one person, skipping if the row already exists. Used by the forms
183
+ * post-submit actions: a resubmitting visitor does not double-attach.
184
+ *
185
+ * @returns `true` when a row was inserted, `false` when the link already existed.
186
+ */
187
+ export async function linkPersonIfAbsent(
188
+ db: Queryable,
189
+ createId: IdFactory,
190
+ workspaceId: string,
191
+ target: PipelineTarget,
192
+ personId: string,
193
+ ): Promise<boolean> {
194
+ const inserted = await db
195
+ .insert(personLinks)
196
+ .values({
197
+ id: createId('personLink'),
198
+ workspaceId,
199
+ personId,
200
+ targetType: target.targetType,
201
+ targetId: target.targetId,
202
+ })
203
+ .onConflictDoNothing({
204
+ target: [personLinks.personId, personLinks.targetType, personLinks.targetId],
205
+ })
206
+ .returning({ id: personLinks.id })
207
+
208
+ return inserted.length > 0
209
+ }
210
+
211
+ /**
212
+ * Target-side cleanup, called from `attachedRecords.deleteRecordsAttachedTo`
213
+ * when a pipeline record is deleted.
214
+ *
215
+ * @returns the number of rows removed.
216
+ */
217
+ export async function deleteLinksForTarget(
218
+ db: Queryable,
219
+ workspaceId: string,
220
+ target: PipelineTarget,
221
+ ): Promise<number> {
222
+ const deleted = await db
223
+ .delete(personLinks)
224
+ .where(
225
+ and(
226
+ eq(personLinks.workspaceId, workspaceId),
227
+ eq(personLinks.targetType, target.targetType),
228
+ eq(personLinks.targetId, target.targetId),
229
+ ),
230
+ )
231
+ .returning({ id: personLinks.id })
232
+
233
+ return deleted.length
234
+ }
235
+
236
+ /**
237
+ * The `?person_id=` exists-subquery SQL builder, correlated on the outer
238
+ * table's id and workspace columns. Replaces the identical `hasAnyOfPeople`
239
+ * helpers that used to live in each pipeline module's repository.
240
+ */
241
+ export function anyPersonLinked(
242
+ targetType: PipelineKind,
243
+ targetIdColumn: AnyPgColumn,
244
+ workspaceIdColumn: AnyPgColumn,
245
+ personIds: readonly string[],
246
+ ): ReturnType<typeof sql> {
247
+ return sql`exists (
248
+ select 1
249
+ from ${personLinks}
250
+ where ${personLinks.workspaceId} = ${workspaceIdColumn}
251
+ and ${personLinks.targetType} = ${targetType}
252
+ and ${personLinks.targetId} = ${targetIdColumn}
253
+ and ${inArray(personLinks.personId, personIds)}
254
+ )`
255
+ }
256
+
257
+ /**
258
+ * The names of these people in this workspace, keyed by id. Reads the
259
+ * `people` table because that is where names live; used by every pipeline
260
+ * service to validate `person_ids` and label the `linked`/`unlinked`
261
+ * activity. An id missing from the map does not exist in this workspace.
262
+ */
263
+ export async function findPeopleNamed(
264
+ db: Queryable,
265
+ workspaceId: string,
266
+ personIds: readonly string[],
267
+ ): Promise<ReadonlyMap<string, string>> {
268
+ if (personIds.length === 0) {
269
+ return new Map()
270
+ }
271
+
272
+ const rows = await db
273
+ .select({ id: people.id, name: people.name })
274
+ .from(people)
275
+ .where(and(eq(people.workspaceId, workspaceId), inArray(people.id, personIds)))
276
+
277
+ return new Map(rows.map((row) => [row.id, row.name]))
278
+ }