@aglyn/plugins-crm 1.0.0-beta.221 → 1.0.0-beta.223

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 (541) hide show
  1. package/README.md +2 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/activity-list.js +12 -5
  4. package/src/lib/components/activity-list.js.map +1 -1
  5. package/src/lib/components/companies-bulk-bar.d.ts +1 -4
  6. package/src/lib/components/companies-bulk-bar.js +7 -20
  7. package/src/lib/components/companies-bulk-bar.js.map +1 -1
  8. package/src/lib/components/companies-section.d.ts +3 -3
  9. package/src/lib/components/companies-section.js +149 -46
  10. package/src/lib/components/companies-section.js.map +1 -1
  11. package/src/lib/components/company-edit-drawer.js +281 -20
  12. package/src/lib/components/company-edit-drawer.js.map +1 -1
  13. package/src/lib/components/company-properties-card.js +99 -8
  14. package/src/lib/components/company-properties-card.js.map +1 -1
  15. package/src/lib/components/contact-detail-page.js +3 -1
  16. package/src/lib/components/contact-detail-page.js.map +1 -1
  17. package/src/lib/components/contact-merge-dialog.js +33 -10
  18. package/src/lib/components/contact-merge-dialog.js.map +1 -1
  19. package/src/lib/components/contact-properties-card.d.ts +0 -69
  20. package/src/lib/components/contact-properties-card.js +350 -60
  21. package/src/lib/components/contact-properties-card.js.map +1 -1
  22. package/src/lib/components/contact-reports-to-field.d.ts +46 -0
  23. package/src/lib/components/contact-reports-to-field.js +67 -0
  24. package/src/lib/components/contact-reports-to-field.js.map +1 -0
  25. package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
  26. package/src/lib/components/contacts-bulk-bar.js +7 -19
  27. package/src/lib/components/contacts-bulk-bar.js.map +1 -1
  28. package/src/lib/components/contacts-section.js +46 -33
  29. package/src/lib/components/contacts-section.js.map +1 -1
  30. package/src/lib/components/crm-call-actions.d.ts +10 -0
  31. package/src/lib/components/crm-call-actions.js +26 -9
  32. package/src/lib/components/crm-call-actions.js.map +1 -1
  33. package/src/lib/components/crm-next-activity-column.js +1 -1
  34. package/src/lib/components/crm-next-activity-column.js.map +1 -1
  35. package/src/lib/components/crm-record-picker.d.ts +15 -0
  36. package/src/lib/components/crm-record-picker.js +16 -10
  37. package/src/lib/components/crm-record-picker.js.map +1 -1
  38. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  39. package/src/lib/components/crm-transfer-buttons.js +167 -0
  40. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  41. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  42. package/src/lib/components/deal-contact-roles-card.js +368 -0
  43. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  44. package/src/lib/components/deal-detail-page.d.ts +3 -2
  45. package/src/lib/components/deal-detail-page.js +25 -6
  46. package/src/lib/components/deal-detail-page.js.map +1 -1
  47. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  48. package/src/lib/components/deal-edit-drawer.js +219 -10
  49. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  50. package/src/lib/components/deal-properties-card.d.ts +7 -0
  51. package/src/lib/components/deal-properties-card.js +34 -3
  52. package/src/lib/components/deal-properties-card.js.map +1 -1
  53. package/src/lib/components/deal-stage-card.d.ts +4 -0
  54. package/src/lib/components/deal-stage-card.js +10 -2
  55. package/src/lib/components/deal-stage-card.js.map +1 -1
  56. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  57. package/src/lib/components/deals-bulk-bar.js +7 -20
  58. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  59. package/src/lib/components/deals-section.d.ts +3 -3
  60. package/src/lib/components/deals-section.js +123 -63
  61. package/src/lib/components/deals-section.js.map +1 -1
  62. package/src/lib/components/fields-section.js +31 -17
  63. package/src/lib/components/fields-section.js.map +1 -1
  64. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  65. package/src/lib/components/lead-convert-dialog.js +23 -1
  66. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  67. package/src/lib/components/lead-detail-page.js +8 -2
  68. package/src/lib/components/lead-detail-page.js.map +1 -1
  69. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  70. package/src/lib/components/lead-profile-fields.js +386 -0
  71. package/src/lib/components/lead-profile-fields.js.map +1 -0
  72. package/src/lib/components/lead-properties-card.d.ts +2 -1
  73. package/src/lib/components/lead-properties-card.js +85 -176
  74. package/src/lib/components/lead-properties-card.js.map +1 -1
  75. package/src/lib/components/lead-source-select.d.ts +4 -23
  76. package/src/lib/components/lead-source-select.js +9 -73
  77. package/src/lib/components/lead-source-select.js.map +1 -1
  78. package/src/lib/components/lead-status-chip.d.ts +9 -3
  79. package/src/lib/components/lead-status-chip.js +8 -4
  80. package/src/lib/components/lead-status-chip.js.map +1 -1
  81. package/src/lib/components/lead-status-options.d.ts +20 -0
  82. package/src/lib/components/lead-status-options.js +51 -0
  83. package/src/lib/components/lead-status-options.js.map +1 -0
  84. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  85. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  86. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  87. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  88. package/src/lib/components/leads-bulk-bar.js +29 -29
  89. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  90. package/src/lib/components/leads-section.js +120 -68
  91. package/src/lib/components/leads-section.js.map +1 -1
  92. package/src/lib/components/linked-deals-card.d.ts +4 -0
  93. package/src/lib/components/linked-deals-card.js +47 -3
  94. package/src/lib/components/linked-deals-card.js.map +1 -1
  95. package/src/lib/components/log-activity-dialog.js +43 -3
  96. package/src/lib/components/log-activity-dialog.js.map +1 -1
  97. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  98. package/src/lib/components/new-contact-drawer.js +108 -6
  99. package/src/lib/components/new-contact-drawer.js.map +1 -1
  100. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  101. package/src/lib/components/new-lead-drawer.js +88 -121
  102. package/src/lib/components/new-lead-drawer.js.map +1 -1
  103. package/src/lib/components/picklist-select.d.ts +36 -0
  104. package/src/lib/components/picklist-select.js +114 -0
  105. package/src/lib/components/picklist-select.js.map +1 -0
  106. package/src/lib/components/picklist-values-card.d.ts +34 -0
  107. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  108. package/src/lib/components/picklist-values-card.js.map +1 -0
  109. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  110. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  111. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  112. package/src/lib/components/pipelines-dialog.js +15 -6
  113. package/src/lib/components/pipelines-dialog.js.map +1 -1
  114. package/src/lib/components/recent-activity-feed.js +20 -5
  115. package/src/lib/components/recent-activity-feed.js.map +1 -1
  116. package/src/lib/components/recipes-card.js +4 -2
  117. package/src/lib/components/recipes-card.js.map +1 -1
  118. package/src/lib/components/record-tasks-card.js +15 -8
  119. package/src/lib/components/record-tasks-card.js.map +1 -1
  120. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  121. package/src/lib/components/reports/forecast-card.js +101 -3
  122. package/src/lib/components/reports/forecast-card.js.map +1 -1
  123. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  124. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  125. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  126. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  127. package/src/lib/components/reports/lead-source-card.js +318 -0
  128. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  129. package/src/lib/components/reports/pipeline-card.js +2 -1
  130. package/src/lib/components/reports/pipeline-card.js.map +1 -1
  131. package/src/lib/components/reports/report-export.js +1 -1
  132. package/src/lib/components/reports/report-export.js.map +1 -1
  133. package/src/lib/components/reports-section.js +8 -0
  134. package/src/lib/components/reports-section.js.map +1 -1
  135. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  136. package/src/lib/components/sharing-rule-drawer.js +108 -19
  137. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  138. package/src/lib/components/sharing-rules-card.js +11 -3
  139. package/src/lib/components/sharing-rules-card.js.map +1 -1
  140. package/src/lib/components/task-cells.d.ts +9 -1
  141. package/src/lib/components/task-cells.js +9 -4
  142. package/src/lib/components/task-cells.js.map +1 -1
  143. package/src/lib/components/task-edit-drawer.js +111 -43
  144. package/src/lib/components/task-edit-drawer.js.map +1 -1
  145. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  146. package/src/lib/components/tasks-bulk-bar.js +7 -20
  147. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  148. package/src/lib/components/tasks-calendar.d.ts +3 -0
  149. package/src/lib/components/tasks-calendar.js +8 -1
  150. package/src/lib/components/tasks-calendar.js.map +1 -1
  151. package/src/lib/components/tasks-section.d.ts +3 -3
  152. package/src/lib/components/tasks-section.js +58 -43
  153. package/src/lib/components/tasks-section.js.map +1 -1
  154. package/src/lib/constants/api-routes.d.ts +2 -9
  155. package/src/lib/constants/api-routes.js +1 -7
  156. package/src/lib/constants/api-routes.js.map +1 -1
  157. package/src/lib/constants/bundle-common.d.ts +6 -0
  158. package/src/lib/constants/bundle-common.js +11 -0
  159. package/src/lib/constants/bundle-common.js.map +1 -1
  160. package/src/lib/constants/company-filters.d.ts +14 -0
  161. package/src/lib/constants/company-filters.js +51 -1
  162. package/src/lib/constants/company-filters.js.map +1 -1
  163. package/src/lib/constants/contact-filters.d.ts +2 -0
  164. package/src/lib/constants/contact-filters.js +18 -1
  165. package/src/lib/constants/contact-filters.js.map +1 -1
  166. package/src/lib/constants/deal-filters.d.ts +22 -1
  167. package/src/lib/constants/deal-filters.js +67 -4
  168. package/src/lib/constants/deal-filters.js.map +1 -1
  169. package/src/lib/declarations.console-server.d.ts +3 -0
  170. package/src/lib/declarations.console-server.js +35 -0
  171. package/src/lib/declarations.console-server.js.map +1 -1
  172. package/src/lib/declarations.d.ts +26 -0
  173. package/src/lib/declarations.js +35 -0
  174. package/src/lib/declarations.js.map +1 -0
  175. package/src/lib/declarations.server.d.ts +11 -0
  176. package/src/lib/declarations.server.js +97 -1
  177. package/src/lib/declarations.server.js.map +1 -1
  178. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  179. package/src/lib/hooks/use-company-picklists.js +55 -0
  180. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  181. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  182. package/src/lib/hooks/use-crm-picklist.js +53 -0
  183. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  184. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  185. package/src/lib/hooks/use-crm-record-names.js +45 -19
  186. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  187. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  188. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  189. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  190. package/src/lib/hooks/use-deals.d.ts +14 -0
  191. package/src/lib/hooks/use-deals.js +29 -0
  192. package/src/lib/hooks/use-deals.js.map +1 -1
  193. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  194. package/src/lib/hooks/use-lead-picklists.js +46 -0
  195. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  196. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  197. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  198. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  199. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  200. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  201. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  202. package/src/lib/model/companies.d.ts +32 -3
  203. package/src/lib/model/companies.js +133 -16
  204. package/src/lib/model/companies.js.map +1 -1
  205. package/src/lib/model/contact-merge.d.ts +27 -3
  206. package/src/lib/model/contact-merge.js +81 -7
  207. package/src/lib/model/contact-merge.js.map +1 -1
  208. package/src/lib/model/contact-record.d.ts +17 -0
  209. package/src/lib/model/contact-record.js +17 -2
  210. package/src/lib/model/contact-record.js.map +1 -1
  211. package/src/lib/model/contact-update.d.ts +31 -2
  212. package/src/lib/model/contact-update.js +14 -0
  213. package/src/lib/model/contact-update.js.map +1 -1
  214. package/src/lib/model/crm-list-query.d.ts +5 -0
  215. package/src/lib/model/crm-list-query.js +8 -0
  216. package/src/lib/model/crm-list-query.js.map +1 -1
  217. package/src/lib/model/crm-next-activity.d.ts +107 -0
  218. package/src/lib/model/crm-next-activity.js +140 -0
  219. package/src/lib/model/crm-next-activity.js.map +1 -0
  220. package/src/lib/model/crm-recipes.d.ts +40 -0
  221. package/src/lib/model/crm-recipes.js +259 -0
  222. package/src/lib/model/crm-recipes.js.map +1 -0
  223. package/src/lib/model/crm-record-counts.d.ts +36 -0
  224. package/src/lib/model/crm-record-counts.js +54 -0
  225. package/src/lib/model/crm-record-counts.js.map +1 -0
  226. package/src/lib/model/crm-record-lists.d.ts +23 -0
  227. package/src/lib/model/crm-record-lists.js +161 -0
  228. package/src/lib/model/crm-record-lists.js.map +1 -0
  229. package/src/lib/model/crm-reports.d.ts +73 -3
  230. package/src/lib/model/crm-reports.js +120 -1
  231. package/src/lib/model/crm-reports.js.map +1 -1
  232. package/src/lib/model/crm-sharing.d.ts +21 -3
  233. package/src/lib/model/crm-sharing.js +27 -6
  234. package/src/lib/model/crm-sharing.js.map +1 -1
  235. package/src/lib/model/crm-task-reminders.d.ts +152 -0
  236. package/src/lib/model/crm-task-reminders.js +161 -0
  237. package/src/lib/model/crm-task-reminders.js.map +1 -0
  238. package/src/lib/model/deal-board-model.d.ts +8 -2
  239. package/src/lib/model/deal-board-model.js +15 -2
  240. package/src/lib/model/deal-board-model.js.map +1 -1
  241. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  242. package/src/lib/model/deal-contact-roles.js +73 -0
  243. package/src/lib/model/deal-contact-roles.js.map +1 -0
  244. package/src/lib/model/deal-form-model.d.ts +56 -0
  245. package/src/lib/model/deal-form-model.js +79 -7
  246. package/src/lib/model/deal-form-model.js.map +1 -1
  247. package/src/lib/model/download-text-file.d.ts +23 -0
  248. package/src/lib/model/download-text-file.js +34 -0
  249. package/src/lib/model/download-text-file.js.map +1 -0
  250. package/src/lib/model/lead-filters.d.ts +36 -2
  251. package/src/lib/model/lead-filters.js +123 -2
  252. package/src/lib/model/lead-filters.js.map +1 -1
  253. package/src/lib/model/lead-source-direction.d.ts +38 -0
  254. package/src/lib/model/lead-source-direction.js +52 -0
  255. package/src/lib/model/lead-source-direction.js.map +1 -0
  256. package/src/lib/model/next-activity.d.ts +1 -1
  257. package/src/lib/model/next-activity.js.map +1 -1
  258. package/src/lib/model/picklist-values.d.ts +119 -0
  259. package/src/lib/model/picklist-values.js +256 -0
  260. package/src/lib/model/picklist-values.js.map +1 -0
  261. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  262. package/src/lib/model/record-facts-disclosed.js +281 -0
  263. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  264. package/src/lib/model/record-facts.d.ts +215 -34
  265. package/src/lib/model/record-facts.js +307 -128
  266. package/src/lib/model/record-facts.js.map +1 -1
  267. package/src/lib/model/task-picklists.d.ts +52 -0
  268. package/src/lib/model/task-picklists.js +83 -0
  269. package/src/lib/model/task-picklists.js.map +1 -0
  270. package/src/lib/model/task-routes.d.ts +13 -0
  271. package/src/lib/model/task-routes.js +23 -4
  272. package/src/lib/model/task-routes.js.map +1 -1
  273. package/src/lib/plan-entitlements.js +6 -4
  274. package/src/lib/plan-entitlements.js.map +1 -1
  275. package/src/lib/plugin.js +17 -0
  276. package/src/lib/plugin.js.map +1 -1
  277. package/src/lib/server/api-v1/contacts.js +220 -14
  278. package/src/lib/server/api-v1/contacts.js.map +1 -1
  279. package/src/lib/server/api-v1/crm-activities.js +14 -1
  280. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  281. package/src/lib/server/api-v1/crm-companies.js +123 -14
  282. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  283. package/src/lib/server/api-v1/crm-deals.js +291 -26
  284. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  285. package/src/lib/server/api-v1/crm-leads.js +144 -38
  286. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  287. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  288. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  289. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  290. package/src/lib/server/api-v1/crm-tasks.js +78 -34
  291. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  292. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  293. package/src/lib/server/api-v1/openapi.js +171 -16
  294. package/src/lib/server/api-v1/openapi.js.map +1 -1
  295. package/src/lib/server/assign-contact-owner.d.ts +188 -0
  296. package/src/lib/server/assign-contact-owner.js +446 -0
  297. package/src/lib/server/assign-contact-owner.js.map +1 -0
  298. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  299. package/src/lib/server/associate-company-by-domain.js +153 -0
  300. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  301. package/src/lib/server/automation-steps.d.ts +140 -0
  302. package/src/lib/server/automation-steps.js +669 -0
  303. package/src/lib/server/automation-steps.js.map +1 -0
  304. package/src/lib/server/capture-contact.d.ts +17 -0
  305. package/src/lib/server/capture-contact.js +95 -26
  306. package/src/lib/server/capture-contact.js.map +1 -1
  307. package/src/lib/server/capture-host-contact.d.ts +104 -0
  308. package/src/lib/server/capture-host-contact.js +151 -0
  309. package/src/lib/server/capture-host-contact.js.map +1 -0
  310. package/src/lib/server/company-children.d.ts +25 -0
  311. package/src/lib/server/company-children.js +42 -0
  312. package/src/lib/server/company-children.js.map +1 -0
  313. package/src/lib/server/company-delete.d.ts +18 -0
  314. package/src/lib/server/company-delete.js +44 -21
  315. package/src/lib/server/company-delete.js.map +1 -1
  316. package/src/lib/server/contact-email-history.js +21 -19
  317. package/src/lib/server/contact-email-history.js.map +1 -1
  318. package/src/lib/server/contact-remove.js +27 -2
  319. package/src/lib/server/contact-remove.js.map +1 -1
  320. package/src/lib/server/contact-reports-to.d.ts +61 -0
  321. package/src/lib/server/contact-reports-to.js +114 -0
  322. package/src/lib/server/contact-reports-to.js.map +1 -0
  323. package/src/lib/server/contact-update.d.ts +42 -1
  324. package/src/lib/server/contact-update.js +204 -23
  325. package/src/lib/server/contact-update.js.map +1 -1
  326. package/src/lib/server/convert-host-lead.d.ts +46 -1
  327. package/src/lib/server/convert-host-lead.js +173 -15
  328. package/src/lib/server/convert-host-lead.js.map +1 -1
  329. package/src/lib/server/convert-open-lead.js +12 -5
  330. package/src/lib/server/convert-open-lead.js.map +1 -1
  331. package/src/lib/server/crm-email-activity.d.ts +118 -0
  332. package/src/lib/server/crm-email-activity.js +148 -0
  333. package/src/lib/server/crm-email-activity.js.map +1 -0
  334. package/src/lib/server/crm-inbound-email.js +1 -1
  335. package/src/lib/server/crm-inbound-email.js.map +1 -1
  336. package/src/lib/server/crm-next-activity.d.ts +74 -0
  337. package/src/lib/server/crm-next-activity.js +194 -0
  338. package/src/lib/server/crm-next-activity.js.map +1 -0
  339. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  340. package/src/lib/server/crm-record-indexes.js +78 -0
  341. package/src/lib/server/crm-record-indexes.js.map +1 -0
  342. package/src/lib/server/crm-sharing.d.ts +9 -1
  343. package/src/lib/server/crm-sharing.js +23 -3
  344. package/src/lib/server/crm-sharing.js.map +1 -1
  345. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  346. package/src/lib/server/deal-contact-roles.js +89 -0
  347. package/src/lib/server/deal-contact-roles.js.map +1 -0
  348. package/src/lib/server/email-send.js +2 -1
  349. package/src/lib/server/email-send.js.map +1 -1
  350. package/src/lib/server/lead-convert.d.ts +5 -0
  351. package/src/lib/server/lead-convert.js +19 -3
  352. package/src/lib/server/lead-convert.js.map +1 -1
  353. package/src/lib/server/lead-create.d.ts +17 -2
  354. package/src/lib/server/lead-create.js +46 -14
  355. package/src/lib/server/lead-create.js.map +1 -1
  356. package/src/lib/server/lead-nurturing.d.ts +6 -0
  357. package/src/lib/server/lead-nurturing.js +57 -20
  358. package/src/lib/server/lead-nurturing.js.map +1 -1
  359. package/src/lib/server/lead-picklists.d.ts +35 -0
  360. package/src/lib/server/lead-picklists.js +52 -0
  361. package/src/lib/server/lead-picklists.js.map +1 -0
  362. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  363. package/src/lib/server/lead-source-picklist.js +6 -33
  364. package/src/lib/server/lead-source-picklist.js.map +1 -1
  365. package/src/lib/server/merge-contacts.js +23 -5
  366. package/src/lib/server/merge-contacts.js.map +1 -1
  367. package/src/lib/server/next-activity-routes.js +2 -1
  368. package/src/lib/server/next-activity-routes.js.map +1 -1
  369. package/src/lib/server/person-eraser.d.ts +53 -0
  370. package/src/lib/server/person-eraser.js +149 -0
  371. package/src/lib/server/person-eraser.js.map +1 -0
  372. package/src/lib/server/person-records.d.ts +69 -0
  373. package/src/lib/server/person-records.js +317 -0
  374. package/src/lib/server/person-records.js.map +1 -0
  375. package/src/lib/server/person-refund.d.ts +97 -0
  376. package/src/lib/server/person-refund.js +221 -0
  377. package/src/lib/server/person-refund.js.map +1 -0
  378. package/src/lib/server/picklist-values.d.ts +21 -0
  379. package/src/lib/server/picklist-values.js +308 -0
  380. package/src/lib/server/picklist-values.js.map +1 -0
  381. package/src/lib/server/read-picklist.d.ts +44 -0
  382. package/src/lib/server/read-picklist.js +65 -0
  383. package/src/lib/server/read-picklist.js.map +1 -0
  384. package/src/lib/server/recipe-routes.js +22 -8
  385. package/src/lib/server/recipe-routes.js.map +1 -1
  386. package/src/lib/server/record-email-state.js +7 -1
  387. package/src/lib/server/record-email-state.js.map +1 -1
  388. package/src/lib/server/record-facts.d.ts +3 -0
  389. package/src/lib/server/record-facts.js +233 -31
  390. package/src/lib/server/record-facts.js.map +1 -1
  391. package/src/lib/server/record-origin.d.ts +27 -0
  392. package/src/lib/server/record-origin.js +104 -0
  393. package/src/lib/server/record-origin.js.map +1 -0
  394. package/src/lib/server/record-timeline.js +40 -3
  395. package/src/lib/server/record-timeline.js.map +1 -1
  396. package/src/lib/server/suite-gate.js +4 -3
  397. package/src/lib/server/suite-gate.js.map +1 -1
  398. package/src/lib/server/task-reminders-route.js +2 -1
  399. package/src/lib/server/task-reminders-route.js.map +1 -1
  400. package/src/lib/server/task-routes.js +33 -17
  401. package/src/lib/server/task-routes.js.map +1 -1
  402. package/src/lib/server-deal-stage.d.ts +5 -1
  403. package/src/lib/server-deal-stage.js +10 -5
  404. package/src/lib/server-deal-stage.js.map +1 -1
  405. package/src/lib/server.d.ts +8 -3
  406. package/src/lib/server.js +47 -43
  407. package/src/lib/server.js.map +1 -1
  408. package/src/lib/testing/memory-firestore.d.ts +55 -0
  409. package/src/lib/testing/memory-firestore.js +335 -0
  410. package/src/lib/testing/memory-firestore.js.map +1 -0
  411. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  412. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  413. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  414. package/src/lib/transfer/activities.d.ts +30 -0
  415. package/src/lib/transfer/activities.js +132 -0
  416. package/src/lib/transfer/activities.js.map +1 -0
  417. package/src/lib/transfer/aliases.d.ts +22 -0
  418. package/src/lib/transfer/aliases.js +1342 -0
  419. package/src/lib/transfer/aliases.js.map +1 -0
  420. package/src/lib/transfer/common.d.ts +222 -0
  421. package/src/lib/transfer/common.js +832 -0
  422. package/src/lib/transfer/common.js.map +1 -0
  423. package/src/lib/transfer/companies.d.ts +43 -0
  424. package/src/lib/transfer/companies.js +549 -0
  425. package/src/lib/transfer/companies.js.map +1 -0
  426. package/src/lib/transfer/contacts.d.ts +31 -0
  427. package/src/lib/transfer/contacts.js +727 -0
  428. package/src/lib/transfer/contacts.js.map +1 -0
  429. package/src/lib/transfer/deals.d.ts +66 -0
  430. package/src/lib/transfer/deals.js +698 -0
  431. package/src/lib/transfer/deals.js.map +1 -0
  432. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  433. package/src/lib/transfer/email-templates-package.js +76 -0
  434. package/src/lib/transfer/email-templates-package.js.map +1 -0
  435. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  436. package/src/lib/transfer/email-templates-package.server.js +176 -0
  437. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  438. package/src/lib/transfer/fields.d.ts +102 -0
  439. package/src/lib/transfer/fields.js +1755 -0
  440. package/src/lib/transfer/fields.js.map +1 -0
  441. package/src/lib/transfer/leads.d.ts +30 -0
  442. package/src/lib/transfer/leads.js +582 -0
  443. package/src/lib/transfer/leads.js.map +1 -0
  444. package/src/lib/transfer/pipelines.d.ts +21 -0
  445. package/src/lib/transfer/pipelines.js +172 -0
  446. package/src/lib/transfer/pipelines.js.map +1 -0
  447. package/src/lib/transfer/register.d.ts +47 -0
  448. package/src/lib/transfer/register.js +277 -0
  449. package/src/lib/transfer/register.js.map +1 -0
  450. package/src/lib/transfer/tasks.d.ts +30 -0
  451. package/src/lib/transfer/tasks.js +418 -0
  452. package/src/lib/transfer/tasks.js.map +1 -0
  453. package/src/lib/transfer/ui.d.ts +20 -0
  454. package/src/lib/transfer/ui.js +42 -0
  455. package/src/lib/transfer/ui.js.map +1 -0
  456. package/src/lib/components/company-import-drawer.d.ts +0 -42
  457. package/src/lib/components/company-import-drawer.js +0 -99
  458. package/src/lib/components/company-import-drawer.js.map +0 -1
  459. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  460. package/src/lib/components/contact-import-drawer.js +0 -149
  461. package/src/lib/components/contact-import-drawer.js.map +0 -1
  462. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  463. package/src/lib/components/crm-export-all-button.js +0 -98
  464. package/src/lib/components/crm-export-all-button.js.map +0 -1
  465. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  466. package/src/lib/components/csv-import-drawer.js +0 -757
  467. package/src/lib/components/csv-import-drawer.js.map +0 -1
  468. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  469. package/src/lib/components/deal-import-drawer.js +0 -83
  470. package/src/lib/components/deal-import-drawer.js.map +0 -1
  471. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  472. package/src/lib/components/lead-import-drawer.js +0 -118
  473. package/src/lib/components/lead-import-drawer.js.map +0 -1
  474. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  475. package/src/lib/components/lead-source-values-card.js.map +0 -1
  476. package/src/lib/components/task-import-drawer.d.ts +0 -24
  477. package/src/lib/components/task-import-drawer.js +0 -82
  478. package/src/lib/components/task-import-drawer.js.map +0 -1
  479. package/src/lib/model/companies-csv.d.ts +0 -36
  480. package/src/lib/model/companies-csv.js +0 -38
  481. package/src/lib/model/companies-csv.js.map +0 -1
  482. package/src/lib/model/contacts-csv.d.ts +0 -54
  483. package/src/lib/model/contacts-csv.js +0 -67
  484. package/src/lib/model/contacts-csv.js.map +0 -1
  485. package/src/lib/model/crm-company-import.d.ts +0 -154
  486. package/src/lib/model/crm-company-import.js +0 -331
  487. package/src/lib/model/crm-company-import.js.map +0 -1
  488. package/src/lib/model/crm-csv.d.ts +0 -239
  489. package/src/lib/model/crm-csv.js +0 -467
  490. package/src/lib/model/crm-csv.js.map +0 -1
  491. package/src/lib/model/crm-deal-import.d.ts +0 -112
  492. package/src/lib/model/crm-deal-import.js +0 -263
  493. package/src/lib/model/crm-deal-import.js.map +0 -1
  494. package/src/lib/model/crm-import.d.ts +0 -250
  495. package/src/lib/model/crm-import.js +0 -467
  496. package/src/lib/model/crm-import.js.map +0 -1
  497. package/src/lib/model/crm-lead-import.d.ts +0 -138
  498. package/src/lib/model/crm-lead-import.js +0 -446
  499. package/src/lib/model/crm-lead-import.js.map +0 -1
  500. package/src/lib/model/crm-task-import.d.ts +0 -94
  501. package/src/lib/model/crm-task-import.js +0 -275
  502. package/src/lib/model/crm-task-import.js.map +0 -1
  503. package/src/lib/model/deals-csv.d.ts +0 -32
  504. package/src/lib/model/deals-csv.js +0 -36
  505. package/src/lib/model/deals-csv.js.map +0 -1
  506. package/src/lib/model/import-column-shapes.d.ts +0 -36
  507. package/src/lib/model/import-column-shapes.js +0 -76
  508. package/src/lib/model/import-column-shapes.js.map +0 -1
  509. package/src/lib/model/lead-source-values.d.ts +0 -82
  510. package/src/lib/model/lead-source-values.js +0 -149
  511. package/src/lib/model/lead-source-values.js.map +0 -1
  512. package/src/lib/model/leads-csv.d.ts +0 -40
  513. package/src/lib/model/leads-csv.js +0 -40
  514. package/src/lib/model/leads-csv.js.map +0 -1
  515. package/src/lib/model/tasks-csv.d.ts +0 -28
  516. package/src/lib/model/tasks-csv.js +0 -28
  517. package/src/lib/model/tasks-csv.js.map +0 -1
  518. package/src/lib/server/companies-import.d.ts +0 -57
  519. package/src/lib/server/companies-import.js +0 -242
  520. package/src/lib/server/companies-import.js.map +0 -1
  521. package/src/lib/server/contacts-import.d.ts +0 -109
  522. package/src/lib/server/contacts-import.js +0 -393
  523. package/src/lib/server/contacts-import.js.map +0 -1
  524. package/src/lib/server/deals-import.d.ts +0 -76
  525. package/src/lib/server/deals-import.js +0 -248
  526. package/src/lib/server/deals-import.js.map +0 -1
  527. package/src/lib/server/export-route.d.ts +0 -60
  528. package/src/lib/server/export-route.js +0 -447
  529. package/src/lib/server/export-route.js.map +0 -1
  530. package/src/lib/server/import-context.d.ts +0 -87
  531. package/src/lib/server/import-context.js +0 -182
  532. package/src/lib/server/import-context.js.map +0 -1
  533. package/src/lib/server/lead-source-values.d.ts +0 -50
  534. package/src/lib/server/lead-source-values.js +0 -191
  535. package/src/lib/server/lead-source-values.js.map +0 -1
  536. package/src/lib/server/leads-import.d.ts +0 -84
  537. package/src/lib/server/leads-import.js +0 -367
  538. package/src/lib/server/leads-import.js.map +0 -1
  539. package/src/lib/server/tasks-import.d.ts +0 -54
  540. package/src/lib/server/tasks-import.js +0 -160
  541. package/src/lib/server/tasks-import.js.map +0 -1
@@ -0,0 +1,832 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ /**
3
+ * @license
4
+ * Copyright 2026 Aglyn LLC
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */ /*==========================================
18
+ * WHAT EVERY CRM TRANSFER RESOURCE SHARES (AGL-3527) — the server half.
19
+ *
20
+ * The CRM's records live under the organization, each stamped with the
21
+ * site that captured it and the `visibleTo` tokens that say who reads it.
22
+ * A transfer is opened from the CRM under a site, or at the organization
23
+ * level; the job engine hands every hook the workspace and that site
24
+ * (`ctx.hostId`), and this module turns the pair into what the CRM's own
25
+ * routes compute from a request: the org document, the site's consent
26
+ * group, the tokens a record must carry to be seen from the site, and the
27
+ * stamp a record created by the import carries.
28
+ *
29
+ * ## Refusals are the routes' refusals
30
+ *
31
+ * The transfer routes check `data.manage`, and the CRM's suite on the plan
32
+ * through each resource's `planGate` (AGL-3555). What is particular to the
33
+ * CRM — the suite again where a hook reads or writes, a site to file new
34
+ * records under — is checked here and thrown as the engine's own errors
35
+ * (`TransferPlanRefusedError` carrying `suite-gate.ts`'s answer, else
36
+ * `TransferEngineError`), so the wizard shows the sentence a CRM route
37
+ * would have answered.
38
+ *=========================================*/ import { checkCrmRecordsQuota, consentGroupForHost, CRM_COLLECTIONS, crmPicklistDefinition, crmReadTokens, crmScopeTokens, effectiveCrmPicklist, fieldDefinitionsForObject, isCrmPicklistId, newResourceScopeFields, normalizeCrmPicklist, ORG_SCOPE_TOKEN, readCrmCustomInput, visibleToTokens } from "@aglyn/aglyn/server";
39
+ import { CONTACT_LIFECYCLE_STAGE_LABELS, CONTACT_LIFECYCLE_STAGES, CRM_FORECAST_CATEGORIES, CRM_FORECAST_CATEGORY_LABELS } from "@aglyn/aglyn/app-utils/crm";
40
+ import { visibleToHost } from "@aglyn/aglyn/app-utils/scope-tokens";
41
+ import { listOrgContainers } from "@aglyn/tenant-data-admin/server/org-containers";
42
+ import { normalizeAddress } from "@aglyn/aglyn/foundation/definitions/contact.types";
43
+ import { matchLookupKey, rankTransferLookupSuggestions, transferLookupKey } from "@aglyn/aglyn/data-transfer";
44
+ import { crmRecordsQuotaForOrg, firebaseAdmin, listOrgMembers } from "@aglyn/tenant-data-admin";
45
+ import { applyListQuery } from "@aglyn/tenant-data-admin/server/list-query";
46
+ import { TransferEngineError, TransferPlanRefusedError } from "@aglyn/tenant-data-admin/server/transfer-jobs";
47
+ import { FieldPath, FieldValue, Timestamp } from "firebase-admin/firestore";
48
+ import { crmSuiteRefusal } from "../server/suite-gate.js";
49
+ import { CRM_ADDRESS_PART_KEYS, CRM_ADDRESS_PARTS, CRM_CAMPAIGNS_PICKLIST, CRM_FORECAST_CATEGORY_PICKLIST, CRM_LIFECYCLE_STAGE_PICKLIST, crmCustomPicklistKey } from "./fields.js";
50
+ /** The most values one Firestore `in` filter takes. */ export const IN_LIMIT = 30;
51
+ /** Documents read per page of an export. */ export const EXPORT_PAGE = 500;
52
+ /** Rows written at once by an apply. */ export const APPLY_CONCURRENCY = 8;
53
+ /** A row is started only while this much of the chunk's budget is left. */ export const APPLY_ROW_BUDGET_MS = 3000;
54
+ /** The org, the site and its tokens, for one hook call. */ export async function crmTransferEnv(ctx) {
55
+ var _snapshot_data;
56
+ const firestore = firebaseAdmin.app().firestore();
57
+ const orgRef = firestore.collection('orgs').doc(ctx.orgId);
58
+ const snapshot = await orgRef.get();
59
+ if (!snapshot.exists) throw new TransferEngineError('notFound', 404, 'No such workspace.');
60
+ const org = (_snapshot_data = snapshot.data()) != null ? _snapshot_data : {};
61
+ const group = ctx.hostId ? consentGroupForHost(org, ctx.hostId) : null;
62
+ return {
63
+ firestore,
64
+ orgRef,
65
+ org,
66
+ orgId: ctx.orgId,
67
+ hostId: ctx.hostId,
68
+ group,
69
+ siteTokens: group ? crmReadTokens(group) : null
70
+ };
71
+ }
72
+ /**
73
+ * Refuses an act the organization's plan does not include, in the CRM
74
+ * routes' own answer (`suite-gate.ts`). The transfer gate already asked
75
+ * (AGL-3555, each resource's `planGate`); a hook asks again where it reads
76
+ * or writes, so a caller that reaches it without the gate is refused alike.
77
+ */ export function requireCrmSuite(env, act) {
78
+ const refusal = crmSuiteRefusal(env.org, act);
79
+ if (refusal) throw new TransferPlanRefusedError(refusal);
80
+ }
81
+ /**
82
+ * Refuses reading the CRM's own records (not the people files) on a plan
83
+ * without the CRM: the export route's rule since AGL-2839.
84
+ */ export function requireCrmRecords(env, what) {
85
+ requireCrmSuite(env, `Exporting ${what}`);
86
+ }
87
+ /**
88
+ * The site new records are filed under, or the refusal: every CRM record is
89
+ * a fact some site met, so an import opened at the organization level must
90
+ * name one first.
91
+ */ export function requireSite(env, what) {
92
+ if (!env.hostId || !env.group) {
93
+ throw new TransferEngineError('invalid', 400, `Choose the site these ${what} are imported into.`);
94
+ }
95
+ return {
96
+ hostId: env.hostId,
97
+ group: env.group
98
+ };
99
+ }
100
+ /** The stamp a record the import creates carries: the site, and who reads it. */ export function creationScope(env, actorUid) {
101
+ const { hostId, group } = requireSite(env, 'records');
102
+ return _extends({
103
+ hostId,
104
+ visibleTo: crmScopeTokens(env.org, group)
105
+ }, actorUid ? {
106
+ createdByUid: actorUid
107
+ } : {}, {
108
+ createdAt: FieldValue.serverTimestamp(),
109
+ updatedAt: FieldValue.serverTimestamp()
110
+ });
111
+ }
112
+ /** Whether a stored record may be read in this transfer: the site's view, and a scoped reader's own tokens. */ export function visibleIn(env, visibleTo, scopeTokens) {
113
+ const tokens = Array.isArray(visibleTo) ? visibleTo : [];
114
+ if (env.siteTokens && !visibleToTokens(tokens, env.siteTokens)) return false;
115
+ if ((scopeTokens == null ? void 0 : scopeTokens.length) && !visibleToTokens(tokens, scopeTokens)) return false;
116
+ return true;
117
+ }
118
+ /*==========================================
119
+ * CUSTOM FIELDS AND PICKLISTS
120
+ *=========================================*/ /** The organization's live custom field definitions for one kind of record, as the site reads them. */ export async function crmCustomDefinitions(env, object) {
121
+ const snapshot = await env.orgRef.collection(CRM_COLLECTIONS.contactFields).limit(200).get();
122
+ return fieldDefinitionsForObject(snapshot.docs.map((doc)=>doc.data()), object).filter((field)=>Boolean(field.key) && !field.retiredAt && (!env.siteTokens || visibleToTokens(field.visibleTo, env.siteTokens)));
123
+ }
124
+ /** The lifecycle stages as a fixed list: matched onto, never added to. */ const LIFECYCLE_LIST = {
125
+ spec: {
126
+ restricted: true,
127
+ standardValues: CONTACT_LIFECYCLE_STAGES.map((id)=>({
128
+ id,
129
+ label: CONTACT_LIFECYCLE_STAGE_LABELS[id]
130
+ }))
131
+ },
132
+ set: {
133
+ values: CONTACT_LIFECYCLE_STAGES.map((id)=>({
134
+ id,
135
+ label: CONTACT_LIFECYCLE_STAGE_LABELS[id],
136
+ active: true
137
+ })),
138
+ defaultValueId: null
139
+ }
140
+ };
141
+ /** The forecast categories: a fixed set a forecast rolls up by, matched onto and never added to. */ const FORECAST_LIST = {
142
+ spec: {
143
+ restricted: true,
144
+ standardValues: CRM_FORECAST_CATEGORIES.map((id)=>({
145
+ id,
146
+ label: CRM_FORECAST_CATEGORY_LABELS[id]
147
+ }))
148
+ },
149
+ set: {
150
+ values: CRM_FORECAST_CATEGORIES.map((id)=>({
151
+ id,
152
+ label: CRM_FORECAST_CATEGORY_LABELS[id],
153
+ active: true
154
+ })),
155
+ defaultValueId: null
156
+ }
157
+ };
158
+ /**
159
+ * The lists behind the picklist fields a catalog names: the CRM's own
160
+ * (`crmPicklists`), the lifecycle stages, and each custom `select` field's
161
+ * options — a select is a fixed list the import maps onto.
162
+ */ export async function crmPicklistLists(env, picklistIds, customDefinitions) {
163
+ const lists = {};
164
+ const crmIds = picklistIds.filter(isCrmPicklistId);
165
+ const snapshots = crmIds.length ? await env.firestore.getAll(...crmIds.map((id)=>env.orgRef.collection(CRM_COLLECTIONS.picklists).doc(id))) : [];
166
+ crmIds.forEach((id, at)=>{
167
+ var _snapshots_at;
168
+ const definition = crmPicklistDefinition(id);
169
+ if (!definition) return;
170
+ lists[id] = {
171
+ spec: definition,
172
+ set: effectiveCrmPicklist(id, (_snapshots_at = snapshots[at]) == null ? void 0 : _snapshots_at.data())
173
+ };
174
+ });
175
+ for (const id of picklistIds){
176
+ var _definition_options;
177
+ if (id === CRM_LIFECYCLE_STAGE_PICKLIST) {
178
+ lists[id] = LIFECYCLE_LIST;
179
+ continue;
180
+ }
181
+ if (id === CRM_FORECAST_CATEGORY_PICKLIST) {
182
+ lists[id] = FORECAST_LIST;
183
+ continue;
184
+ }
185
+ if (id === CRM_CAMPAIGNS_PICKLIST) {
186
+ const { byName, names } = await campaignDirectory(env);
187
+ const live = [
188
+ ...new Set(byName.values())
189
+ ].map((campaign)=>{
190
+ var _names_get;
191
+ return {
192
+ id: campaign,
193
+ label: (_names_get = names.get(campaign)) != null ? _names_get : campaign
194
+ };
195
+ });
196
+ lists[id] = {
197
+ spec: {
198
+ restricted: true,
199
+ standardValues: live
200
+ },
201
+ set: {
202
+ values: live.map((value)=>_extends({}, value, {
203
+ active: true
204
+ })),
205
+ defaultValueId: null
206
+ }
207
+ };
208
+ continue;
209
+ }
210
+ const custom = crmCustomPicklistKey(id);
211
+ if (!custom) continue;
212
+ const definition = customDefinitions.find((entry)=>entry.key === custom.key);
213
+ if (!definition) continue;
214
+ const options = ((_definition_options = definition.options) != null ? _definition_options : []).map((option)=>String(option)).filter(Boolean);
215
+ lists[id] = {
216
+ spec: {
217
+ restricted: true,
218
+ standardValues: options.map((label, index)=>({
219
+ id: `o${index}`,
220
+ label
221
+ }))
222
+ },
223
+ set: {
224
+ values: options.map((label, index)=>({
225
+ id: `o${index}`,
226
+ label,
227
+ active: true
228
+ })),
229
+ defaultValueId: null
230
+ }
231
+ };
232
+ }
233
+ return lists;
234
+ }
235
+ /**
236
+ * Adds the values the person chose to add to one of the CRM's picklists —
237
+ * in a transaction, so an admin editing the list at the same moment loses
238
+ * nothing — skipping an id or a label the list already holds, so a retried
239
+ * apply adds nothing twice. A value whose meaning only the platform sets
240
+ * (a lead Qualified by conversion) is never added. Fixed lists (the stages,
241
+ * a select's options) take nothing.
242
+ */ export async function addCrmPicklistValues(env, picklistId, values) {
243
+ if (!isCrmPicklistId(picklistId)) return;
244
+ const definition = crmPicklistDefinition(picklistId);
245
+ if (!definition) return;
246
+ const ref = env.orgRef.collection(CRM_COLLECTIONS.picklists).doc(picklistId);
247
+ await env.firestore.runTransaction(async (transaction)=>{
248
+ const snapshot = await transaction.get(ref);
249
+ const current = effectiveCrmPicklist(picklistId, snapshot.data());
250
+ const held = new Set(current.values.map((value)=>value.id));
251
+ const labels = new Set(current.values.map((value)=>value.label.toLowerCase()));
252
+ const added = values.filter((value)=>{
253
+ var _definition_reservedMeanings;
254
+ return !held.has(value.id) && !labels.has(value.label.toLowerCase()) && !(value.meaning && ((_definition_reservedMeanings = definition.reservedMeanings) == null ? void 0 : _definition_reservedMeanings.includes(value.meaning)));
255
+ });
256
+ if (!added.length) return;
257
+ const created = normalizeCrmPicklist(snapshot.data()) === null;
258
+ transaction.set(ref, _extends({
259
+ values: [
260
+ ...current.values,
261
+ ...added.map((value)=>_extends({}, value, {
262
+ active: true
263
+ }))
264
+ ],
265
+ defaultValueId: current.defaultValueId,
266
+ updatedAt: FieldValue.serverTimestamp()
267
+ }, created ? _extends({
268
+ hostId: env.hostId,
269
+ createdAt: FieldValue.serverTimestamp()
270
+ }, newResourceScopeFields([
271
+ ORG_SCOPE_TOKEN
272
+ ])) : {}), {
273
+ merge: true
274
+ });
275
+ });
276
+ }
277
+ /*==========================================
278
+ * CAMPAIGNS — named by a deal's and a lead's campaign columns
279
+ *=========================================*/ /** The most campaigns a file's names are resolved against — the lead import's own ceiling. */ const CAMPAIGN_CEILING = 200;
280
+ /**
281
+ * The organization's live campaigns, by lowercased name and by id. A name
282
+ * two campaigns share resolves to the one placed on the transfer's site
283
+ * first, as the lead import resolved it.
284
+ */ export async function campaignDirectory(env) {
285
+ const byName = new Map();
286
+ const names = new Map();
287
+ const containers = await listOrgContainers(env.firestore, 'campaign', env.orgId, CAMPAIGN_CEILING).catch(()=>[]);
288
+ const live = containers.filter((container)=>container.live);
289
+ const placed = (visibleTo)=>env.hostId ? visibleToHost(visibleTo, env.hostId) : true;
290
+ for (const container of [
291
+ ...live.filter((entry)=>placed(entry.visibleTo)),
292
+ ...live.filter((entry)=>!placed(entry.visibleTo))
293
+ ]){
294
+ const key = container.name.toLowerCase();
295
+ if (key && !byName.has(key)) byName.set(key, container.id);
296
+ }
297
+ for (const container of containers)if (container.name) names.set(container.id, container.name);
298
+ return {
299
+ byName,
300
+ names
301
+ };
302
+ }
303
+ async function memberEntries(orgId) {
304
+ return (await listOrgMembers(orgId)).filter((member)=>member.$id && member.orgSuspended !== true).map((member)=>{
305
+ var _member_email, _member_displayName;
306
+ return {
307
+ id: String(member.$id),
308
+ email: String((_member_email = member.email) != null ? _member_email : '').trim().toLowerCase(),
309
+ name: String((_member_displayName = member.displayName) != null ? _member_displayName : '').trim()
310
+ };
311
+ });
312
+ }
313
+ /**
314
+ * The workspace's members as a lookup target: by id, email or display name,
315
+ * with names like an unresolved one offered — so a Salesforce report's
316
+ * "Contact Owner" (a full name) resolves as well as an address does.
317
+ */ export function crmMembersTarget() {
318
+ return {
319
+ matchKeys: [
320
+ {
321
+ fieldId: 'email',
322
+ normalizer: 'email'
323
+ },
324
+ {
325
+ fieldId: 'name',
326
+ normalizer: 'caseless'
327
+ }
328
+ ],
329
+ async lookup (ctx, requests) {
330
+ const members = await memberEntries(ctx.orgId);
331
+ const lookup = new Map();
332
+ const records = new Map();
333
+ for (const request of requests){
334
+ for (const value of request.values){
335
+ const found = members.filter((member)=>request.fieldId === 'id' ? member.id === value : request.fieldId === 'email' ? member.email === value.toLowerCase() : member.name.toLowerCase() === value.toLowerCase());
336
+ if (!found.length) continue;
337
+ lookup.set(matchLookupKey(request.fieldId, value), found.map((member)=>member.id));
338
+ for (const member of found)records.set(member.id, {
339
+ name: member.name || member.email,
340
+ email: member.email
341
+ });
342
+ }
343
+ }
344
+ return {
345
+ lookup,
346
+ records
347
+ };
348
+ },
349
+ async suggest (ctx, request) {
350
+ const members = await memberEntries(ctx.orgId);
351
+ const candidates = members.flatMap((member)=>[
352
+ {
353
+ recordId: member.id,
354
+ label: member.email
355
+ },
356
+ ...member.name ? [
357
+ {
358
+ recordId: member.id,
359
+ label: member.name
360
+ }
361
+ ] : []
362
+ ]);
363
+ return Object.fromEntries(request.values.map((value)=>[
364
+ value,
365
+ rankTransferLookupSuggestions(value, candidates)
366
+ ]));
367
+ }
368
+ };
369
+ }
370
+ /** Member uid → email, for the owner columns of an export. */ export async function crmMemberEmails(orgId) {
371
+ return new Map((await memberEntries(orgId)).map((member)=>[
372
+ member.id,
373
+ member.email
374
+ ]));
375
+ }
376
+ const FILTER_OPS = new Set([
377
+ '<',
378
+ '<=',
379
+ '==',
380
+ '!=',
381
+ '>=',
382
+ '>',
383
+ 'array-contains',
384
+ 'in',
385
+ 'not-in',
386
+ 'array-contains-any'
387
+ ]);
388
+ /** A filter value as the list sent it: a date travels as `{ $date }`. */ function filterValue(value) {
389
+ if (value && typeof value === 'object' && !Array.isArray(value) && typeof value.$date === 'string') {
390
+ return Timestamp.fromDate(new Date(value.$date));
391
+ }
392
+ return Array.isArray(value) ? value.map(filterValue) : value;
393
+ }
394
+ /** The list's filter, read from an untrusted body, or the refusal. */ export function readExportFilter(raw) {
395
+ if (!raw) return null;
396
+ const filters = Array.isArray(raw['filters']) ? raw['filters'] : null;
397
+ const orderBy = raw['orderBy'];
398
+ if (!filters || !orderBy || typeof orderBy.path !== 'string') {
399
+ throw new TransferEngineError('invalid', 400, 'The list’s filter could not be read; export everything or a selection.');
400
+ }
401
+ return {
402
+ filters: filters.map((entry)=>{
403
+ const filter = entry;
404
+ if (typeof filter.path !== 'string' || !FILTER_OPS.has(String(filter.op))) {
405
+ throw new TransferEngineError('invalid', 400, 'The list’s filter could not be read; export everything or a selection.');
406
+ }
407
+ return {
408
+ path: filter.path,
409
+ op: filter.op,
410
+ value: filterValue(filter.value)
411
+ };
412
+ }),
413
+ orderBy: {
414
+ path: orderBy.path,
415
+ direction: orderBy.direction === 'desc' ? 'desc' : 'asc'
416
+ }
417
+ };
418
+ }
419
+ /**
420
+ * The query an export reads: the list's filter, or every record the site
421
+ * (or the scoped reader) sees, in document order. A list filter already
422
+ * carries the reader's `visibleTo` clause when they are scoped, as the
423
+ * rules require of the list; a filter that lacks it gets one, when it has
424
+ * no other array clause, and is refused otherwise — so the count is exact
425
+ * and no record outside the reader's scope is ever read.
426
+ */ export function crmExportQuery(env, collection, options) {
427
+ var _options_scopeTokens;
428
+ const filter = readExportFilter(options == null ? void 0 : options.filter);
429
+ const tokens = (options == null ? void 0 : (_options_scopeTokens = options.scopeTokens) == null ? void 0 : _options_scopeTokens.length) ? [
430
+ ...options.scopeTokens
431
+ ] : env.siteTokens;
432
+ if (filter) {
433
+ const scoped = filter.filters.some((entry)=>entry.path === 'visibleTo');
434
+ const array = filter.filters.some((entry)=>entry.op === 'array-contains' || entry.op === 'array-contains-any');
435
+ if (tokens && !scoped) {
436
+ if (array) {
437
+ throw new TransferEngineError('invalid', 400, 'This filter cannot be exported from here; export everything or a selection.');
438
+ }
439
+ return applyListQuery(collection.where('visibleTo', 'array-contains-any', tokens), filter);
440
+ }
441
+ return applyListQuery(collection, filter);
442
+ }
443
+ const base = tokens ? collection.where('visibleTo', 'array-contains-any', tokens) : collection;
444
+ return base.orderBy(FieldPath.documentId());
445
+ }
446
+ /** How many records an export with these options reads. */ export async function countCrmExport(env, collection, options, visible) {
447
+ var _data_count;
448
+ if (options.ids) {
449
+ let count = 0;
450
+ for(let at = 0; at < options.ids.length; at += EXPORT_PAGE){
451
+ const refs = options.ids.slice(at, at + EXPORT_PAGE).filter((id)=>id && !id.includes('/')).map((id)=>collection.doc(id));
452
+ if (!refs.length) continue;
453
+ for (const snapshot of (await env.firestore.getAll(...refs))){
454
+ var _snapshot_data;
455
+ if (snapshot.exists && visible((_snapshot_data = snapshot.data()) != null ? _snapshot_data : {})) count += 1;
456
+ }
457
+ }
458
+ return count;
459
+ }
460
+ return Number((_data_count = (await crmExportQuery(env, collection, options).count().get()).data().count) != null ? _data_count : 0);
461
+ }
462
+ /**
463
+ * One page of an export: the selection by id (in the order given), or the
464
+ * query's next page after the cursor. Every document is checked against the
465
+ * site's and the reader's tokens before it becomes a row.
466
+ */ export async function readCrmExportPage(env, collection, cursor, options, visible, toRows) {
467
+ var _ref;
468
+ const size = Math.min((_ref = options == null ? void 0 : options.pageSize) != null ? _ref : EXPORT_PAGE, EXPORT_PAGE);
469
+ if (options == null ? void 0 : options.ids) {
470
+ const start = cursor ? Number(cursor) || 0 : 0;
471
+ const ids = options.ids.slice(start, start + size).filter((id)=>id && !id.includes('/'));
472
+ const snapshots = ids.length ? await env.firestore.getAll(...ids.map((id)=>collection.doc(id))) : [];
473
+ const docs = snapshots.filter((snapshot)=>{
474
+ var _snapshot_data;
475
+ return snapshot.exists && visible((_snapshot_data = snapshot.data()) != null ? _snapshot_data : {});
476
+ }).map((snapshot)=>{
477
+ var _snapshot_data;
478
+ return {
479
+ id: snapshot.id,
480
+ data: (_snapshot_data = snapshot.data()) != null ? _snapshot_data : {}
481
+ };
482
+ });
483
+ const next = start + size < options.ids.length ? String(start + size) : null;
484
+ return {
485
+ rows: await toRows(docs),
486
+ next
487
+ };
488
+ }
489
+ let query = crmExportQuery(env, collection, options).limit(size);
490
+ if (cursor) {
491
+ const after = await collection.doc(cursor).get();
492
+ if (after.exists) query = query.startAfter(after);
493
+ }
494
+ const snapshot = await query.get();
495
+ const docs = snapshot.docs.filter((doc)=>{
496
+ var _doc_data;
497
+ return visible((_doc_data = doc.data()) != null ? _doc_data : {});
498
+ }).map((doc)=>{
499
+ var _doc_data;
500
+ return {
501
+ id: doc.id,
502
+ data: (_doc_data = doc.data()) != null ? _doc_data : {}
503
+ };
504
+ });
505
+ const last = snapshot.docs[snapshot.docs.length - 1];
506
+ return {
507
+ rows: await toRows(docs),
508
+ next: snapshot.docs.length === size && last ? last.id : null
509
+ };
510
+ }
511
+ /**
512
+ * Records by each requested value of one stored field, thirty to an `in`
513
+ * query; `fold` turns a requested value into the stored one. The answer is
514
+ * filed under the value AS REQUESTED, which is the key the engine asks by.
515
+ */ export async function lookupByField(collection, request, storedField, fold, visible, into) {
516
+ const byStored = new Map();
517
+ for (const value of request.values){
518
+ var _byStored_get;
519
+ const stored = fold(value);
520
+ if (!stored) continue;
521
+ byStored.set(stored, [
522
+ ...(_byStored_get = byStored.get(stored)) != null ? _byStored_get : [],
523
+ value
524
+ ]);
525
+ }
526
+ const keys = [
527
+ ...byStored.keys()
528
+ ];
529
+ for(let at = 0; at < keys.length; at += IN_LIMIT){
530
+ const page = keys.slice(at, at + IN_LIMIT);
531
+ const snapshot = await collection.where(storedField, 'in', page).get();
532
+ for (const doc of snapshot.docs){
533
+ var _doc_data, _byStored_get1, _data_storedField;
534
+ const data = (_doc_data = doc.data()) != null ? _doc_data : {};
535
+ if (!visible(data)) continue;
536
+ into.docs.set(doc.id, data);
537
+ for (const value of (_byStored_get1 = byStored.get(String((_data_storedField = data[storedField]) != null ? _data_storedField : ''))) != null ? _byStored_get1 : []){
538
+ var _into_lookup_get;
539
+ const key = matchLookupKey(request.fieldId, value);
540
+ into.lookup.set(key, [
541
+ ...new Set([
542
+ ...(_into_lookup_get = into.lookup.get(key)) != null ? _into_lookup_get : [],
543
+ doc.id
544
+ ])
545
+ ]);
546
+ }
547
+ }
548
+ }
549
+ }
550
+ /** Records by id, the ones the transfer may read. */ export async function lookupById(env, collection, request, visible, into) {
551
+ const ids = request.values.filter((id)=>id && !id.includes('/'));
552
+ for(let at = 0; at < ids.length; at += EXPORT_PAGE){
553
+ const page = ids.slice(at, at + EXPORT_PAGE);
554
+ const snapshots = await env.firestore.getAll(...page.map((id)=>collection.doc(id)));
555
+ for (const snapshot of snapshots){
556
+ const data = snapshot.data();
557
+ if (!snapshot.exists || !data || !visible(data)) continue;
558
+ into.docs.set(snapshot.id, data);
559
+ into.lookup.set(matchLookupKey(request.fieldId, snapshot.id), [
560
+ snapshot.id
561
+ ]);
562
+ }
563
+ }
564
+ }
565
+ /** A lookup answer from the documents found, each read into values by `read`. */ export function lookupResult(found, read) {
566
+ const records = new Map();
567
+ for (const [id, data] of found.docs)records.set(id, read(id, data));
568
+ return {
569
+ lookup: found.lookup,
570
+ records
571
+ };
572
+ }
573
+ /*==========================================
574
+ * VALUES
575
+ *=========================================*/ /** Epoch milliseconds from a stored timestamp (a Firestore `Timestamp`, a `Date` or a number), or `null`. */ export function storedMs(value) {
576
+ var _value_toDate;
577
+ if (typeof value === 'number' && Number.isFinite(value)) return value;
578
+ if (value instanceof Date) return value.getTime();
579
+ const date = value == null ? void 0 : (_value_toDate = value.toDate) == null ? void 0 : _value_toDate.call(value);
580
+ return date ? date.getTime() : null;
581
+ }
582
+ /** An instant as the export writes it (ISO), or `null`. */ export function isoOf(value) {
583
+ const ms = storedMs(value);
584
+ return ms === null ? null : new Date(ms).toISOString();
585
+ }
586
+ /** A postal address as the six values `<prefix>Street` … `<prefix>Country`. */ export function addressValues(prefix, address) {
587
+ const stored = address && typeof address === 'object' ? address : {};
588
+ return Object.fromEntries(CRM_ADDRESS_PARTS.map((part)=>{
589
+ const value = stored[CRM_ADDRESS_PART_KEYS[part]];
590
+ return [
591
+ `${prefix}${part}`,
592
+ typeof value === 'string' && value ? value : null
593
+ ];
594
+ }));
595
+ }
596
+ /**
597
+ * The address a row's parts make, over the one the record holds: a part
598
+ * the row names (blank clears it) replaces the stored part. `undefined`
599
+ * when the row names no part; `null` when nothing of the address is left.
600
+ */ export function addressFromValues(prefix, values, stored) {
601
+ var _base_country, _base_line1, _base_line2, _base_city, _base_state, _base_postalCode;
602
+ const named = CRM_ADDRESS_PARTS.filter((part)=>`${prefix}${part}` in values);
603
+ if (!named.length) return undefined;
604
+ const base = stored && typeof stored === 'object' ? _extends({}, stored) : {};
605
+ for (const part of named){
606
+ const value = values[`${prefix}${part}`];
607
+ base[CRM_ADDRESS_PART_KEYS[part]] = typeof value === 'string' ? value.trim() : '';
608
+ }
609
+ const country = String((_base_country = base['country']) != null ? _base_country : '').trim();
610
+ return normalizeAddress({
611
+ line1: String((_base_line1 = base['line1']) != null ? _base_line1 : ''),
612
+ line2: String((_base_line2 = base['line2']) != null ? _base_line2 : ''),
613
+ city: String((_base_city = base['city']) != null ? _base_city : ''),
614
+ state: String((_base_state = base['state']) != null ? _base_state : ''),
615
+ postalCode: String((_base_postalCode = base['postalCode']) != null ? _base_postalCode : ''),
616
+ country: country.length === 2 ? country.toUpperCase() : country
617
+ });
618
+ }
619
+ /** A planned row's values: each changed field's new value. */ export function plannedValues(row) {
620
+ return Object.fromEntries(row.diff.map((change)=>[
621
+ change.fieldId,
622
+ change.after
623
+ ]));
624
+ }
625
+ /** Only `keys` of `values`, each present (a missing one as `null`). */ export function pickValues(values, keys) {
626
+ return Object.fromEntries([
627
+ ...keys
628
+ ].map((key)=>{
629
+ var _values_key;
630
+ return [
631
+ key,
632
+ (_values_key = values[key]) != null ? _values_key : null
633
+ ];
634
+ }));
635
+ }
636
+ /** A text value, trimmed, or `''`. */ export function textOf(value) {
637
+ return value === null || value === undefined ? '' : String(value).trim();
638
+ }
639
+ /** A lookup cell's display key, for caching records a chunk creates by name. */ export function nameKey(value) {
640
+ return transferLookupKey(value);
641
+ }
642
+ /*------------------------------------------
643
+ * Custom values
644
+ *-----------------------------------------*/ /** The custom key a `custom:<key>` field id names, or `null`. */ export function customKeyOf(fieldId) {
645
+ return fieldId.startsWith('custom:') ? fieldId.slice('custom:'.length) : null;
646
+ }
647
+ /**
648
+ * A stored custom value as the file reads it: a date (stored as epoch
649
+ * milliseconds) as its day, `YYYY-MM-DD`; anything else as stored.
650
+ */ export function customTransferValue(definition, value) {
651
+ if (value === null || value === undefined) return null;
652
+ if ((definition == null ? void 0 : definition.type) === 'date') {
653
+ const ms = storedMs(value);
654
+ return ms === null ? null : new Date(ms).toISOString().slice(0, 10);
655
+ }
656
+ return value;
657
+ }
658
+ /** Every custom field a record holds, as `custom:<key>` values. */ export function customTransferValues(definitions, stored) {
659
+ const custom = stored && typeof stored === 'object' ? stored : {};
660
+ return Object.fromEntries(definitions.map((definition)=>[
661
+ `custom:${definition.key}`,
662
+ customTransferValue(definition, custom[definition.key])
663
+ ]));
664
+ }
665
+ /**
666
+ * The custom values a row writes, judged by the CRM's own reader
667
+ * (`readCrmCustomInput`): a blank clears (`null`), a date is read from its
668
+ * day. Answers the values, or the first refusal.
669
+ */ export function customWriteValues(values, definitions, object) {
670
+ var _Object_values_;
671
+ const raw = {};
672
+ for (const [fieldId, value] of Object.entries(values)){
673
+ const key = customKeyOf(fieldId);
674
+ if (key) raw[key] = value === undefined || value === '' ? null : value;
675
+ }
676
+ if (!Object.keys(raw).length) return {
677
+ values: {}
678
+ };
679
+ const judged = readCrmCustomInput(raw, definitions, object);
680
+ if ('errors' in judged) return {
681
+ error: (_Object_values_ = Object.values(judged.errors)[0]) != null ? _Object_values_ : 'A custom value could not be saved.'
682
+ };
683
+ return {
684
+ values: judged.values
685
+ };
686
+ }
687
+ /*==========================================
688
+ * PLANS — values a plugin rule holds back
689
+ *=========================================*/ /**
690
+ * Removes the changes `decide` refuses from a plan, as a locked rule's: the
691
+ * field is listed in the row's `heldBack`, the row gains a `lockedRule`
692
+ * warning (acknowledged before Apply), and an update left with nothing to
693
+ * write becomes `unchanged`. For a rule no field policy can say — a stage
694
+ * that only moves forward, a flag a file may set and never clear.
695
+ */ export function holdBackChanges(plan, decide) {
696
+ const warnings = new Map(plan.warnings.map((warning)=>[
697
+ warning.class,
698
+ _extends({}, warning)
699
+ ]));
700
+ const rows = plan.rows.map((row)=>{
701
+ var _warnings_get;
702
+ if (row.verdict !== 'update' && row.verdict !== 'create') return row;
703
+ const held = [];
704
+ const diff = row.diff.filter((change)=>{
705
+ const reason = decide(row, change);
706
+ if (!reason) return true;
707
+ held.push({
708
+ fieldId: change.fieldId,
709
+ reason,
710
+ value: change.after
711
+ });
712
+ return false;
713
+ });
714
+ if (!held.length) return row;
715
+ const warning = (_warnings_get = warnings.get('lockedRule')) != null ? _warnings_get : {
716
+ class: 'lockedRule',
717
+ count: 0,
718
+ rows: 0,
719
+ fieldIds: [],
720
+ samples: [],
721
+ requiresAcknowledgement: true
722
+ };
723
+ warning.rows += 1;
724
+ for (const entry of held){
725
+ warning.count += 1;
726
+ if (!warning.fieldIds.includes(entry.fieldId)) warning.fieldIds = [
727
+ ...warning.fieldIds,
728
+ entry.fieldId
729
+ ];
730
+ if (warning.samples.length < 5) {
731
+ warning.samples = [
732
+ ...warning.samples,
733
+ {
734
+ row: row.index,
735
+ fieldId: entry.fieldId,
736
+ value: textOf(entry.value),
737
+ detail: entry.reason
738
+ }
739
+ ];
740
+ }
741
+ }
742
+ warnings.set('lockedRule', warning);
743
+ const verdict = row.verdict === 'update' && !diff.length ? 'unchanged' : row.verdict;
744
+ return _extends({}, row, {
745
+ verdict,
746
+ diff,
747
+ heldBack: [
748
+ ...new Set([
749
+ ...row.heldBack,
750
+ ...held.map((entry)=>entry.fieldId)
751
+ ])
752
+ ],
753
+ warnings: [
754
+ ...new Set([
755
+ ...row.warnings,
756
+ 'lockedRule'
757
+ ])
758
+ ]
759
+ });
760
+ });
761
+ const summary = {
762
+ create: 0,
763
+ update: 0,
764
+ unchanged: 0,
765
+ skip: 0,
766
+ fail: 0,
767
+ total: rows.length
768
+ };
769
+ for (const row of rows)summary[row.verdict] += 1;
770
+ const list = plan.warnings.map((warning)=>{
771
+ var _warnings_get;
772
+ return (_warnings_get = warnings.get(warning.class)) != null ? _warnings_get : warning;
773
+ });
774
+ const locked = warnings.get('lockedRule');
775
+ if (locked && !plan.warnings.some((warning)=>warning.class === 'lockedRule')) list.push(locked);
776
+ return {
777
+ rows,
778
+ summary,
779
+ warnings: list,
780
+ acknowledgementsRequired: [
781
+ ...new Set([
782
+ ...plan.acknowledgementsRequired,
783
+ ...locked ? [
784
+ 'lockedRule'
785
+ ] : []
786
+ ])
787
+ ]
788
+ };
789
+ }
790
+ /*==========================================
791
+ * WRITING
792
+ *=========================================*/ /**
793
+ * `write` over `items`, {@link APPLY_CONCURRENCY} at a time, starting an
794
+ * item only while the chunk's budget lasts — the engine resumes the chunk
795
+ * at the next call for whatever is left.
796
+ */ export async function eachWithinBudget(items, timeLeftMs, write) {
797
+ let next = 0;
798
+ const worker = async ()=>{
799
+ while(next < items.length){
800
+ if (timeLeftMs() < APPLY_ROW_BUDGET_MS) return;
801
+ const item = items[next];
802
+ next += 1;
803
+ await write(item);
804
+ }
805
+ };
806
+ await Promise.all(Array.from({
807
+ length: Math.min(APPLY_CONCURRENCY, items.length)
808
+ }, worker));
809
+ }
810
+ /**
811
+ * The CRM records band for the records one apply call creates beside the
812
+ * rows' own (a company a contact's company column names): counted once,
813
+ * then each create admitted from that tally. A plan with an overage rate
814
+ * always admits.
815
+ */ export function crmRecordsRoom(env) {
816
+ let counted = null;
817
+ let created = 0;
818
+ return async ()=>{
819
+ counted != null ? counted : counted = crmRecordsQuotaForOrg(env.org, env.orgRef);
820
+ const { crmRecordsCount } = await counted;
821
+ if (!checkCrmRecordsQuota(env.org, crmRecordsCount + created).allowed) return false;
822
+ created += 1;
823
+ return true;
824
+ };
825
+ }
826
+ /** A thrown write as the sentence a row's result carries. */ export function failureMessage(error) {
827
+ if (error instanceof TransferEngineError) return error.message;
828
+ return 'The record could not be saved.';
829
+ }
830
+ export { TransferEngineError };
831
+
832
+ //# sourceMappingURL=common.js.map