@aglyn/plugins-crm 1.0.0-beta.143

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 (669) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +57 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +29 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/activity-list.d.ts +98 -0
  8. package/src/lib/components/activity-list.js +321 -0
  9. package/src/lib/components/activity-list.js.map +1 -0
  10. package/src/lib/components/activity-queries.d.ts +117 -0
  11. package/src/lib/components/activity-queries.js +198 -0
  12. package/src/lib/components/activity-queries.js.map +1 -0
  13. package/src/lib/components/add-to-list-button.d.ts +25 -0
  14. package/src/lib/components/add-to-list-button.js +64 -0
  15. package/src/lib/components/add-to-list-button.js.map +1 -0
  16. package/src/lib/components/add-to-list-dialog.d.ts +24 -0
  17. package/src/lib/components/add-to-list-dialog.js +327 -0
  18. package/src/lib/components/add-to-list-dialog.js.map +1 -0
  19. package/src/lib/components/assignment-rule-drawer.d.ts +43 -0
  20. package/src/lib/components/assignment-rule-drawer.js +293 -0
  21. package/src/lib/components/assignment-rule-drawer.js.map +1 -0
  22. package/src/lib/components/companies-bulk-bar.d.ts +29 -0
  23. package/src/lib/components/companies-bulk-bar.js +274 -0
  24. package/src/lib/components/companies-bulk-bar.js.map +1 -0
  25. package/src/lib/components/companies-section.d.ts +54 -0
  26. package/src/lib/components/companies-section.js +522 -0
  27. package/src/lib/components/companies-section.js.map +1 -0
  28. package/src/lib/components/company-contacts-card.d.ts +49 -0
  29. package/src/lib/components/company-contacts-card.js +435 -0
  30. package/src/lib/components/company-contacts-card.js.map +1 -0
  31. package/src/lib/components/company-deals-card.d.ts +20 -0
  32. package/src/lib/components/company-deals-card.js +38 -0
  33. package/src/lib/components/company-deals-card.js.map +1 -0
  34. package/src/lib/components/company-detail-page.d.ts +20 -0
  35. package/src/lib/components/company-detail-page.js +165 -0
  36. package/src/lib/components/company-detail-page.js.map +1 -0
  37. package/src/lib/components/company-edit-drawer.d.ts +65 -0
  38. package/src/lib/components/company-edit-drawer.js +433 -0
  39. package/src/lib/components/company-edit-drawer.js.map +1 -0
  40. package/src/lib/components/company-import-drawer.d.ts +42 -0
  41. package/src/lib/components/company-import-drawer.js +99 -0
  42. package/src/lib/components/company-import-drawer.js.map +1 -0
  43. package/src/lib/components/company-picker.d.ts +127 -0
  44. package/src/lib/components/company-picker.js +323 -0
  45. package/src/lib/components/company-picker.js.map +1 -0
  46. package/src/lib/components/company-properties-card.d.ts +47 -0
  47. package/src/lib/components/company-properties-card.js +289 -0
  48. package/src/lib/components/company-properties-card.js.map +1 -0
  49. package/src/lib/components/contact-address-fields.d.ts +29 -0
  50. package/src/lib/components/contact-address-fields.js +149 -0
  51. package/src/lib/components/contact-address-fields.js.map +1 -0
  52. package/src/lib/components/contact-associations-card.d.ts +72 -0
  53. package/src/lib/components/contact-associations-card.js +296 -0
  54. package/src/lib/components/contact-associations-card.js.map +1 -0
  55. package/src/lib/components/contact-custom-columns.d.ts +38 -0
  56. package/src/lib/components/contact-custom-columns.js +102 -0
  57. package/src/lib/components/contact-custom-columns.js.map +1 -0
  58. package/src/lib/components/contact-custom-fields-card.d.ts +39 -0
  59. package/src/lib/components/contact-custom-fields-card.js +204 -0
  60. package/src/lib/components/contact-custom-fields-card.js.map +1 -0
  61. package/src/lib/components/contact-deals-card.d.ts +20 -0
  62. package/src/lib/components/contact-deals-card.js +38 -0
  63. package/src/lib/components/contact-deals-card.js.map +1 -0
  64. package/src/lib/components/contact-detail-page.d.ts +46 -0
  65. package/src/lib/components/contact-detail-page.js +535 -0
  66. package/src/lib/components/contact-detail-page.js.map +1 -0
  67. package/src/lib/components/contact-duplicates-card.d.ts +42 -0
  68. package/src/lib/components/contact-duplicates-card.js +167 -0
  69. package/src/lib/components/contact-duplicates-card.js.map +1 -0
  70. package/src/lib/components/contact-field-drawer.d.ts +64 -0
  71. package/src/lib/components/contact-field-drawer.js +251 -0
  72. package/src/lib/components/contact-field-drawer.js.map +1 -0
  73. package/src/lib/components/contact-import-drawer.d.ts +46 -0
  74. package/src/lib/components/contact-import-drawer.js +149 -0
  75. package/src/lib/components/contact-import-drawer.js.map +1 -0
  76. package/src/lib/components/contact-known-by-card.d.ts +39 -0
  77. package/src/lib/components/contact-known-by-card.js +142 -0
  78. package/src/lib/components/contact-known-by-card.js.map +1 -0
  79. package/src/lib/components/contact-list-columns.d.ts +53 -0
  80. package/src/lib/components/contact-list-columns.js +288 -0
  81. package/src/lib/components/contact-list-columns.js.map +1 -0
  82. package/src/lib/components/contact-merge-dialog.d.ts +79 -0
  83. package/src/lib/components/contact-merge-dialog.js +405 -0
  84. package/src/lib/components/contact-merge-dialog.js.map +1 -0
  85. package/src/lib/components/contact-properties-card.d.ts +89 -0
  86. package/src/lib/components/contact-properties-card.js +492 -0
  87. package/src/lib/components/contact-properties-card.js.map +1 -0
  88. package/src/lib/components/contact-timeline-card.d.ts +68 -0
  89. package/src/lib/components/contact-timeline-card.js +435 -0
  90. package/src/lib/components/contact-timeline-card.js.map +1 -0
  91. package/src/lib/components/contacts-bulk-bar.d.ts +91 -0
  92. package/src/lib/components/contacts-bulk-bar.js +493 -0
  93. package/src/lib/components/contacts-bulk-bar.js.map +1 -0
  94. package/src/lib/components/contacts-section.d.ts +26 -0
  95. package/src/lib/components/contacts-section.js +1025 -0
  96. package/src/lib/components/contacts-section.js.map +1 -0
  97. package/src/lib/components/copy-capture-address-button.d.ts +33 -0
  98. package/src/lib/components/copy-capture-address-button.js +60 -0
  99. package/src/lib/components/copy-capture-address-button.js.map +1 -0
  100. package/src/lib/components/crm-attribution-zone.d.ts +38 -0
  101. package/src/lib/components/crm-attribution-zone.js +36 -0
  102. package/src/lib/components/crm-attribution-zone.js.map +1 -0
  103. package/src/lib/components/crm-booking-zone.d.ts +61 -0
  104. package/src/lib/components/crm-booking-zone.js +50 -0
  105. package/src/lib/components/crm-booking-zone.js.map +1 -0
  106. package/src/lib/components/crm-bulk-bar-frame.d.ts +47 -0
  107. package/src/lib/components/crm-bulk-bar-frame.js +137 -0
  108. package/src/lib/components/crm-bulk-bar-frame.js.map +1 -0
  109. package/src/lib/components/crm-call-actions.d.ts +65 -0
  110. package/src/lib/components/crm-call-actions.js +110 -0
  111. package/src/lib/components/crm-call-actions.js.map +1 -0
  112. package/src/lib/components/crm-column-menu.d.ts +21 -0
  113. package/src/lib/components/crm-column-menu.js +103 -0
  114. package/src/lib/components/crm-column-menu.js.map +1 -0
  115. package/src/lib/components/crm-console-page.d.ts +19 -0
  116. package/src/lib/components/crm-console-page.js +151 -0
  117. package/src/lib/components/crm-console-page.js.map +1 -0
  118. package/src/lib/components/crm-console-sections.d.ts +52 -0
  119. package/src/lib/components/crm-console-sections.js +83 -0
  120. package/src/lib/components/crm-console-sections.js.map +1 -0
  121. package/src/lib/components/crm-custom-field-control.d.ts +26 -0
  122. package/src/lib/components/crm-custom-field-control.js +131 -0
  123. package/src/lib/components/crm-custom-field-control.js.map +1 -0
  124. package/src/lib/components/crm-email-template-tools.d.ts +69 -0
  125. package/src/lib/components/crm-email-template-tools.js +240 -0
  126. package/src/lib/components/crm-email-template-tools.js.map +1 -0
  127. package/src/lib/components/crm-export-all-button.d.ts +39 -0
  128. package/src/lib/components/crm-export-all-button.js +98 -0
  129. package/src/lib/components/crm-export-all-button.js.map +1 -0
  130. package/src/lib/components/crm-filter-bar.d.ts +53 -0
  131. package/src/lib/components/crm-filter-bar.js +294 -0
  132. package/src/lib/components/crm-filter-bar.js.map +1 -0
  133. package/src/lib/components/crm-glance-card.d.ts +54 -0
  134. package/src/lib/components/crm-glance-card.js +219 -0
  135. package/src/lib/components/crm-glance-card.js.map +1 -0
  136. package/src/lib/components/crm-next-activity-column.d.ts +35 -0
  137. package/src/lib/components/crm-next-activity-column.js +100 -0
  138. package/src/lib/components/crm-next-activity-column.js.map +1 -0
  139. package/src/lib/components/crm-record-header.d.ts +97 -0
  140. package/src/lib/components/crm-record-header.js +160 -0
  141. package/src/lib/components/crm-record-header.js.map +1 -0
  142. package/src/lib/components/crm-record-insights-zone.d.ts +50 -0
  143. package/src/lib/components/crm-record-insights-zone.js +169 -0
  144. package/src/lib/components/crm-record-insights-zone.js.map +1 -0
  145. package/src/lib/components/crm-record-picker.d.ts +42 -0
  146. package/src/lib/components/crm-record-picker.js +104 -0
  147. package/src/lib/components/crm-record-picker.js.map +1 -0
  148. package/src/lib/components/crm-send-email-button.d.ts +39 -0
  149. package/src/lib/components/crm-send-email-button.js +81 -0
  150. package/src/lib/components/crm-send-email-button.js.map +1 -0
  151. package/src/lib/components/crm-send-email-dialog.d.ts +61 -0
  152. package/src/lib/components/crm-send-email-dialog.js +851 -0
  153. package/src/lib/components/crm-send-email-dialog.js.map +1 -0
  154. package/src/lib/components/crm-site-picker.d.ts +61 -0
  155. package/src/lib/components/crm-site-picker.js +99 -0
  156. package/src/lib/components/crm-site-picker.js.map +1 -0
  157. package/src/lib/components/crm-suite-lock.d.ts +29 -0
  158. package/src/lib/components/crm-suite-lock.js +114 -0
  159. package/src/lib/components/crm-suite-lock.js.map +1 -0
  160. package/src/lib/components/crm-tasks-due-card.d.ts +42 -0
  161. package/src/lib/components/crm-tasks-due-card.js +225 -0
  162. package/src/lib/components/crm-tasks-due-card.js.map +1 -0
  163. package/src/lib/components/crm-views-control.d.ts +65 -0
  164. package/src/lib/components/crm-views-control.js +518 -0
  165. package/src/lib/components/crm-views-control.js.map +1 -0
  166. package/src/lib/components/csv-import-drawer.d.ts +132 -0
  167. package/src/lib/components/csv-import-drawer.js +746 -0
  168. package/src/lib/components/csv-import-drawer.js.map +1 -0
  169. package/src/lib/components/deal-board.d.ts +70 -0
  170. package/src/lib/components/deal-board.js +478 -0
  171. package/src/lib/components/deal-board.js.map +1 -0
  172. package/src/lib/components/deal-detail-page.d.ts +18 -0
  173. package/src/lib/components/deal-detail-page.js +323 -0
  174. package/src/lib/components/deal-detail-page.js.map +1 -0
  175. package/src/lib/components/deal-edit-drawer.d.ts +59 -0
  176. package/src/lib/components/deal-edit-drawer.js +640 -0
  177. package/src/lib/components/deal-edit-drawer.js.map +1 -0
  178. package/src/lib/components/deal-import-drawer.d.ts +24 -0
  179. package/src/lib/components/deal-import-drawer.js +83 -0
  180. package/src/lib/components/deal-import-drawer.js.map +1 -0
  181. package/src/lib/components/deal-products-card.d.ts +48 -0
  182. package/src/lib/components/deal-products-card.js +614 -0
  183. package/src/lib/components/deal-products-card.js.map +1 -0
  184. package/src/lib/components/deal-properties-card.d.ts +29 -0
  185. package/src/lib/components/deal-properties-card.js +144 -0
  186. package/src/lib/components/deal-properties-card.js.map +1 -0
  187. package/src/lib/components/deal-stage-card.d.ts +24 -0
  188. package/src/lib/components/deal-stage-card.js +199 -0
  189. package/src/lib/components/deal-stage-card.js.map +1 -0
  190. package/src/lib/components/deals-bulk-bar.d.ts +31 -0
  191. package/src/lib/components/deals-bulk-bar.js +340 -0
  192. package/src/lib/components/deals-bulk-bar.js.map +1 -0
  193. package/src/lib/components/deals-section.d.ts +49 -0
  194. package/src/lib/components/deals-section.js +767 -0
  195. package/src/lib/components/deals-section.js.map +1 -0
  196. package/src/lib/components/email-capture-card.d.ts +42 -0
  197. package/src/lib/components/email-capture-card.js +134 -0
  198. package/src/lib/components/email-capture-card.js.map +1 -0
  199. package/src/lib/components/email-template-drawer.d.ts +33 -0
  200. package/src/lib/components/email-template-drawer.js +209 -0
  201. package/src/lib/components/email-template-drawer.js.map +1 -0
  202. package/src/lib/components/email-templates-card.d.ts +33 -0
  203. package/src/lib/components/email-templates-card.js +370 -0
  204. package/src/lib/components/email-templates-card.js.map +1 -0
  205. package/src/lib/components/erase-person-action.d.ts +92 -0
  206. package/src/lib/components/erase-person-action.js +261 -0
  207. package/src/lib/components/erase-person-action.js.map +1 -0
  208. package/src/lib/components/fields-section.d.ts +37 -0
  209. package/src/lib/components/fields-section.js +641 -0
  210. package/src/lib/components/fields-section.js.map +1 -0
  211. package/src/lib/components/form-contact-fields-card.d.ts +46 -0
  212. package/src/lib/components/form-contact-fields-card.js +253 -0
  213. package/src/lib/components/form-contact-fields-card.js.map +1 -0
  214. package/src/lib/components/insert-link-at-caret.d.ts +28 -0
  215. package/src/lib/components/insert-link-at-caret.js +37 -0
  216. package/src/lib/components/insert-link-at-caret.js.map +1 -0
  217. package/src/lib/components/lead-convert-dialog.d.ts +32 -0
  218. package/src/lib/components/lead-convert-dialog.js +493 -0
  219. package/src/lib/components/lead-convert-dialog.js.map +1 -0
  220. package/src/lib/components/lead-detail-page.d.ts +16 -0
  221. package/src/lib/components/lead-detail-page.js +163 -0
  222. package/src/lib/components/lead-detail-page.js.map +1 -0
  223. package/src/lib/components/lead-history-card.d.ts +32 -0
  224. package/src/lib/components/lead-history-card.js +165 -0
  225. package/src/lib/components/lead-history-card.js.map +1 -0
  226. package/src/lib/components/lead-import-drawer.d.ts +24 -0
  227. package/src/lib/components/lead-import-drawer.js +95 -0
  228. package/src/lib/components/lead-import-drawer.js.map +1 -0
  229. package/src/lib/components/lead-owner-select.d.ts +35 -0
  230. package/src/lib/components/lead-owner-select.js +91 -0
  231. package/src/lib/components/lead-owner-select.js.map +1 -0
  232. package/src/lib/components/lead-properties-card.d.ts +61 -0
  233. package/src/lib/components/lead-properties-card.js +395 -0
  234. package/src/lib/components/lead-properties-card.js.map +1 -0
  235. package/src/lib/components/lead-status-chip.d.ts +12 -0
  236. package/src/lib/components/lead-status-chip.js +43 -0
  237. package/src/lib/components/lead-status-chip.js.map +1 -0
  238. package/src/lib/components/lead-surfaces-note.d.ts +126 -0
  239. package/src/lib/components/lead-surfaces-note.js +262 -0
  240. package/src/lib/components/lead-surfaces-note.js.map +1 -0
  241. package/src/lib/components/lead-unqualify-dialog.d.ts +24 -0
  242. package/src/lib/components/lead-unqualify-dialog.js +125 -0
  243. package/src/lib/components/lead-unqualify-dialog.js.map +1 -0
  244. package/src/lib/components/leads-bulk-bar.d.ts +58 -0
  245. package/src/lib/components/leads-bulk-bar.js +307 -0
  246. package/src/lib/components/leads-bulk-bar.js.map +1 -0
  247. package/src/lib/components/leads-section.d.ts +23 -0
  248. package/src/lib/components/leads-section.js +664 -0
  249. package/src/lib/components/leads-section.js.map +1 -0
  250. package/src/lib/components/linked-deals-card.d.ts +32 -0
  251. package/src/lib/components/linked-deals-card.js +163 -0
  252. package/src/lib/components/linked-deals-card.js.map +1 -0
  253. package/src/lib/components/log-activity-dialog.d.ts +60 -0
  254. package/src/lib/components/log-activity-dialog.js +368 -0
  255. package/src/lib/components/log-activity-dialog.js.map +1 -0
  256. package/src/lib/components/lost-reason-dialog.d.ts +26 -0
  257. package/src/lib/components/lost-reason-dialog.js +95 -0
  258. package/src/lib/components/lost-reason-dialog.js.map +1 -0
  259. package/src/lib/components/new-contact-drawer.d.ts +78 -0
  260. package/src/lib/components/new-contact-drawer.js +343 -0
  261. package/src/lib/components/new-contact-drawer.js.map +1 -0
  262. package/src/lib/components/org-lead-surfaces-note.d.ts +57 -0
  263. package/src/lib/components/org-lead-surfaces-note.js +172 -0
  264. package/src/lib/components/org-lead-surfaces-note.js.map +1 -0
  265. package/src/lib/components/owner-avatar.d.ts +18 -0
  266. package/src/lib/components/owner-avatar.js +61 -0
  267. package/src/lib/components/owner-avatar.js.map +1 -0
  268. package/src/lib/components/pipeline-stages-dialog.d.ts +43 -0
  269. package/src/lib/components/pipeline-stages-dialog.js +339 -0
  270. package/src/lib/components/pipeline-stages-dialog.js.map +1 -0
  271. package/src/lib/components/pipelines-dialog.d.ts +55 -0
  272. package/src/lib/components/pipelines-dialog.js +517 -0
  273. package/src/lib/components/pipelines-dialog.js.map +1 -0
  274. package/src/lib/components/recent-activity-feed.d.ts +39 -0
  275. package/src/lib/components/recent-activity-feed.js +103 -0
  276. package/src/lib/components/recent-activity-feed.js.map +1 -0
  277. package/src/lib/components/recipes-card.d.ts +39 -0
  278. package/src/lib/components/recipes-card.js +485 -0
  279. package/src/lib/components/recipes-card.js.map +1 -0
  280. package/src/lib/components/record-activity-card.d.ts +26 -0
  281. package/src/lib/components/record-activity-card.js +121 -0
  282. package/src/lib/components/record-activity-card.js.map +1 -0
  283. package/src/lib/components/record-files-card.d.ts +67 -0
  284. package/src/lib/components/record-files-card.js +290 -0
  285. package/src/lib/components/record-files-card.js.map +1 -0
  286. package/src/lib/components/record-tasks-card.d.ts +32 -0
  287. package/src/lib/components/record-tasks-card.js +306 -0
  288. package/src/lib/components/record-tasks-card.js.map +1 -0
  289. package/src/lib/components/reports/activity-card.d.ts +57 -0
  290. package/src/lib/components/reports/activity-card.js +281 -0
  291. package/src/lib/components/reports/activity-card.js.map +1 -0
  292. package/src/lib/components/reports/closed-deals-card.d.ts +20 -0
  293. package/src/lib/components/reports/closed-deals-card.js +194 -0
  294. package/src/lib/components/reports/closed-deals-card.js.map +1 -0
  295. package/src/lib/components/reports/contacts-mix-card.d.ts +27 -0
  296. package/src/lib/components/reports/contacts-mix-card.js +161 -0
  297. package/src/lib/components/reports/contacts-mix-card.js.map +1 -0
  298. package/src/lib/components/reports/contacts-trend-card.d.ts +31 -0
  299. package/src/lib/components/reports/contacts-trend-card.js +144 -0
  300. package/src/lib/components/reports/contacts-trend-card.js.map +1 -0
  301. package/src/lib/components/reports/forecast-card.d.ts +22 -0
  302. package/src/lib/components/reports/forecast-card.js +251 -0
  303. package/src/lib/components/reports/forecast-card.js.map +1 -0
  304. package/src/lib/components/reports/lead-counts.d.ts +32 -0
  305. package/src/lib/components/reports/lead-counts.js +44 -0
  306. package/src/lib/components/reports/lead-counts.js.map +1 -0
  307. package/src/lib/components/reports/lead-funnel-card.d.ts +38 -0
  308. package/src/lib/components/reports/lead-funnel-card.js +375 -0
  309. package/src/lib/components/reports/lead-funnel-card.js.map +1 -0
  310. package/src/lib/components/reports/pipeline-card.d.ts +19 -0
  311. package/src/lib/components/reports/pipeline-card.js +338 -0
  312. package/src/lib/components/reports/pipeline-card.js.map +1 -0
  313. package/src/lib/components/reports/report-bar-chart.d.ts +39 -0
  314. package/src/lib/components/reports/report-bar-chart.js +133 -0
  315. package/src/lib/components/reports/report-bar-chart.js.map +1 -0
  316. package/src/lib/components/reports/report-breakdown.d.ts +32 -0
  317. package/src/lib/components/reports/report-breakdown.js +105 -0
  318. package/src/lib/components/reports/report-breakdown.js.map +1 -0
  319. package/src/lib/components/reports/report-export.d.ts +37 -0
  320. package/src/lib/components/reports/report-export.js +66 -0
  321. package/src/lib/components/reports/report-export.js.map +1 -0
  322. package/src/lib/components/reports/report-format.d.ts +36 -0
  323. package/src/lib/components/reports/report-format.js +43 -0
  324. package/src/lib/components/reports/report-format.js.map +1 -0
  325. package/src/lib/components/reports/report-scope.d.ts +81 -0
  326. package/src/lib/components/reports/report-scope.js +58 -0
  327. package/src/lib/components/reports/report-scope.js.map +1 -0
  328. package/src/lib/components/reports/report-stat-tile.d.ts +47 -0
  329. package/src/lib/components/reports/report-stat-tile.js +96 -0
  330. package/src/lib/components/reports/report-stat-tile.js.map +1 -0
  331. package/src/lib/components/reports/source-conversion-card.d.ts +28 -0
  332. package/src/lib/components/reports/source-conversion-card.js +205 -0
  333. package/src/lib/components/reports/source-conversion-card.js.map +1 -0
  334. package/src/lib/components/reports/tasks-card.d.ts +26 -0
  335. package/src/lib/components/reports/tasks-card.js +279 -0
  336. package/src/lib/components/reports/tasks-card.js.map +1 -0
  337. package/src/lib/components/reports/use-aggregate-read.d.ts +99 -0
  338. package/src/lib/components/reports/use-aggregate-read.js +195 -0
  339. package/src/lib/components/reports/use-aggregate-read.js.map +1 -0
  340. package/src/lib/components/reports/won-lost-by-owner-card.d.ts +30 -0
  341. package/src/lib/components/reports/won-lost-by-owner-card.js +168 -0
  342. package/src/lib/components/reports/won-lost-by-owner-card.js.map +1 -0
  343. package/src/lib/components/reports-section.d.ts +42 -0
  344. package/src/lib/components/reports-section.js +308 -0
  345. package/src/lib/components/reports-section.js.map +1 -0
  346. package/src/lib/components/sending-addresses-card.d.ts +49 -0
  347. package/src/lib/components/sending-addresses-card.js +262 -0
  348. package/src/lib/components/sending-addresses-card.js.map +1 -0
  349. package/src/lib/components/settings-section.d.ts +151 -0
  350. package/src/lib/components/settings-section.js +783 -0
  351. package/src/lib/components/settings-section.js.map +1 -0
  352. package/src/lib/components/task-cells.d.ts +51 -0
  353. package/src/lib/components/task-cells.js +139 -0
  354. package/src/lib/components/task-cells.js.map +1 -0
  355. package/src/lib/components/task-edit-drawer.d.ts +53 -0
  356. package/src/lib/components/task-edit-drawer.js +483 -0
  357. package/src/lib/components/task-edit-drawer.js.map +1 -0
  358. package/src/lib/components/task-import-drawer.d.ts +24 -0
  359. package/src/lib/components/task-import-drawer.js +82 -0
  360. package/src/lib/components/task-import-drawer.js.map +1 -0
  361. package/src/lib/components/task-snooze-menu.d.ts +65 -0
  362. package/src/lib/components/task-snooze-menu.js +207 -0
  363. package/src/lib/components/task-snooze-menu.js.map +1 -0
  364. package/src/lib/components/tasks-bulk-bar.d.ts +25 -0
  365. package/src/lib/components/tasks-bulk-bar.js +348 -0
  366. package/src/lib/components/tasks-bulk-bar.js.map +1 -0
  367. package/src/lib/components/tasks-calendar.d.ts +38 -0
  368. package/src/lib/components/tasks-calendar.js +228 -0
  369. package/src/lib/components/tasks-calendar.js.map +1 -0
  370. package/src/lib/components/tasks-section.d.ts +27 -0
  371. package/src/lib/components/tasks-section.js +579 -0
  372. package/src/lib/components/tasks-section.js.map +1 -0
  373. package/src/lib/components/use-contact-campaign-emails.d.ts +32 -0
  374. package/src/lib/components/use-contact-campaign-emails.js +83 -0
  375. package/src/lib/components/use-contact-campaign-emails.js.map +1 -0
  376. package/src/lib/components/use-crm-api.d.ts +44 -0
  377. package/src/lib/components/use-crm-api.js +84 -0
  378. package/src/lib/components/use-crm-api.js.map +1 -0
  379. package/src/lib/components/use-crm-inbound-address.d.ts +60 -0
  380. package/src/lib/components/use-crm-inbound-address.js +124 -0
  381. package/src/lib/components/use-crm-inbound-address.js.map +1 -0
  382. package/src/lib/components/use-emails-hub-path.d.ts +24 -0
  383. package/src/lib/components/use-emails-hub-path.js +59 -0
  384. package/src/lib/components/use-emails-hub-path.js.map +1 -0
  385. package/src/lib/components/use-member-email-aliases.d.ts +54 -0
  386. package/src/lib/components/use-member-email-aliases.js +186 -0
  387. package/src/lib/components/use-member-email-aliases.js.map +1 -0
  388. package/src/lib/components/use-org-members.d.ts +40 -0
  389. package/src/lib/components/use-org-members.js +100 -0
  390. package/src/lib/components/use-org-members.js.map +1 -0
  391. package/src/lib/constants/api-routes.d.ts +109 -0
  392. package/src/lib/constants/api-routes.js +74 -0
  393. package/src/lib/constants/api-routes.js.map +1 -0
  394. package/src/lib/constants/bundle-common.d.ts +14 -0
  395. package/src/lib/constants/bundle-common.js +14 -0
  396. package/src/lib/constants/bundle-common.js.map +1 -0
  397. package/src/lib/constants/company-filters.d.ts +18 -0
  398. package/src/lib/constants/company-filters.js +51 -0
  399. package/src/lib/constants/company-filters.js.map +1 -0
  400. package/src/lib/constants/contact-filters.d.ts +38 -0
  401. package/src/lib/constants/contact-filters.js +294 -0
  402. package/src/lib/constants/contact-filters.js.map +1 -0
  403. package/src/lib/hooks/use-contact-field-definitions.d.ts +48 -0
  404. package/src/lib/hooks/use-contact-field-definitions.js +72 -0
  405. package/src/lib/hooks/use-contact-field-definitions.js.map +1 -0
  406. package/src/lib/hooks/use-contact-update.d.ts +25 -0
  407. package/src/lib/hooks/use-contact-update.js +80 -0
  408. package/src/lib/hooks/use-contact-update.js.map +1 -0
  409. package/src/lib/hooks/use-crm-activity-logger.d.ts +73 -0
  410. package/src/lib/hooks/use-crm-activity-logger.js +101 -0
  411. package/src/lib/hooks/use-crm-activity-logger.js.map +1 -0
  412. package/src/lib/hooks/use-crm-bulk-apply.d.ts +52 -0
  413. package/src/lib/hooks/use-crm-bulk-apply.js +112 -0
  414. package/src/lib/hooks/use-crm-bulk-apply.js.map +1 -0
  415. package/src/lib/hooks/use-crm-default-view.d.ts +24 -0
  416. package/src/lib/hooks/use-crm-default-view.js +64 -0
  417. package/src/lib/hooks/use-crm-default-view.js.map +1 -0
  418. package/src/lib/hooks/use-crm-email-templates.d.ts +59 -0
  419. package/src/lib/hooks/use-crm-email-templates.js +103 -0
  420. package/src/lib/hooks/use-crm-email-templates.js.map +1 -0
  421. package/src/lib/hooks/use-crm-hub-path.d.ts +29 -0
  422. package/src/lib/hooks/use-crm-hub-path.js +41 -0
  423. package/src/lib/hooks/use-crm-hub-path.js.map +1 -0
  424. package/src/lib/hooks/use-crm-org-mount.d.ts +97 -0
  425. package/src/lib/hooks/use-crm-org-mount.js +215 -0
  426. package/src/lib/hooks/use-crm-org-mount.js.map +1 -0
  427. package/src/lib/hooks/use-crm-record-names.d.ts +52 -0
  428. package/src/lib/hooks/use-crm-record-names.js +126 -0
  429. package/src/lib/hooks/use-crm-record-names.js.map +1 -0
  430. package/src/lib/hooks/use-crm-records-quota.d.ts +68 -0
  431. package/src/lib/hooks/use-crm-records-quota.js +118 -0
  432. package/src/lib/hooks/use-crm-records-quota.js.map +1 -0
  433. package/src/lib/hooks/use-crm-saved-view.d.ts +96 -0
  434. package/src/lib/hooks/use-crm-saved-view.js +329 -0
  435. package/src/lib/hooks/use-crm-saved-view.js.map +1 -0
  436. package/src/lib/hooks/use-crm-scope.d.ts +117 -0
  437. package/src/lib/hooks/use-crm-scope.js +147 -0
  438. package/src/lib/hooks/use-crm-scope.js.map +1 -0
  439. package/src/lib/hooks/use-crm-tasks.d.ts +85 -0
  440. package/src/lib/hooks/use-crm-tasks.js +153 -0
  441. package/src/lib/hooks/use-crm-tasks.js.map +1 -0
  442. package/src/lib/hooks/use-crm-view-grid.d.ts +55 -0
  443. package/src/lib/hooks/use-crm-view-grid.js +170 -0
  444. package/src/lib/hooks/use-crm-view-grid.js.map +1 -0
  445. package/src/lib/hooks/use-crm-views.d.ts +42 -0
  446. package/src/lib/hooks/use-crm-views.js +84 -0
  447. package/src/lib/hooks/use-crm-views.js.map +1 -0
  448. package/src/lib/hooks/use-deal-stage-api.d.ts +69 -0
  449. package/src/lib/hooks/use-deal-stage-api.js +78 -0
  450. package/src/lib/hooks/use-deal-stage-api.js.map +1 -0
  451. package/src/lib/hooks/use-deals.d.ts +47 -0
  452. package/src/lib/hooks/use-deals.js +105 -0
  453. package/src/lib/hooks/use-deals.js.map +1 -0
  454. package/src/lib/hooks/use-org-leads.d.ts +53 -0
  455. package/src/lib/hooks/use-org-leads.js +114 -0
  456. package/src/lib/hooks/use-org-leads.js.map +1 -0
  457. package/src/lib/hooks/use-org-member-directory.d.ts +36 -0
  458. package/src/lib/hooks/use-org-member-directory.js +116 -0
  459. package/src/lib/hooks/use-org-member-directory.js.map +1 -0
  460. package/src/lib/hooks/use-org-member-options.d.ts +38 -0
  461. package/src/lib/hooks/use-org-member-options.js +131 -0
  462. package/src/lib/hooks/use-org-member-options.js.map +1 -0
  463. package/src/lib/hooks/use-pipeline.d.ts +71 -0
  464. package/src/lib/hooks/use-pipeline.js +159 -0
  465. package/src/lib/hooks/use-pipeline.js.map +1 -0
  466. package/src/lib/model/companies-bulk-writes.d.ts +40 -0
  467. package/src/lib/model/companies-bulk-writes.js +103 -0
  468. package/src/lib/model/companies-bulk-writes.js.map +1 -0
  469. package/src/lib/model/companies-csv.d.ts +36 -0
  470. package/src/lib/model/companies-csv.js +38 -0
  471. package/src/lib/model/companies-csv.js.map +1 -0
  472. package/src/lib/model/companies.d.ts +99 -0
  473. package/src/lib/model/companies.js +168 -0
  474. package/src/lib/model/companies.js.map +1 -0
  475. package/src/lib/model/company-delete-route.d.ts +43 -0
  476. package/src/lib/model/company-delete-route.js +31 -0
  477. package/src/lib/model/company-delete-route.js.map +1 -0
  478. package/src/lib/model/company-delete.d.ts +42 -0
  479. package/src/lib/model/company-delete.js +52 -0
  480. package/src/lib/model/company-delete.js.map +1 -0
  481. package/src/lib/model/contact-duplicates.d.ts +58 -0
  482. package/src/lib/model/contact-duplicates.js +67 -0
  483. package/src/lib/model/contact-duplicates.js.map +1 -0
  484. package/src/lib/model/contact-record.d.ts +113 -0
  485. package/src/lib/model/contact-record.js +70 -0
  486. package/src/lib/model/contact-record.js.map +1 -0
  487. package/src/lib/model/contact-update.d.ts +93 -0
  488. package/src/lib/model/contact-update.js +50 -0
  489. package/src/lib/model/contact-update.js.map +1 -0
  490. package/src/lib/model/contacts-bulk-writes.d.ts +173 -0
  491. package/src/lib/model/contacts-bulk-writes.js +196 -0
  492. package/src/lib/model/contacts-bulk-writes.js.map +1 -0
  493. package/src/lib/model/contacts-csv.d.ts +54 -0
  494. package/src/lib/model/contacts-csv.js +67 -0
  495. package/src/lib/model/contacts-csv.js.map +1 -0
  496. package/src/lib/model/contacts-list-seed.d.ts +51 -0
  497. package/src/lib/model/contacts-list-seed.js +63 -0
  498. package/src/lib/model/contacts-list-seed.js.map +1 -0
  499. package/src/lib/model/crm-activity-report.d.ts +27 -0
  500. package/src/lib/model/crm-activity-report.js +56 -0
  501. package/src/lib/model/crm-activity-report.js.map +1 -0
  502. package/src/lib/model/crm-api.d.ts +49 -0
  503. package/src/lib/model/crm-api.js +47 -0
  504. package/src/lib/model/crm-api.js.map +1 -0
  505. package/src/lib/model/crm-bulk-writes.d.ts +147 -0
  506. package/src/lib/model/crm-bulk-writes.js +207 -0
  507. package/src/lib/model/crm-bulk-writes.js.map +1 -0
  508. package/src/lib/model/crm-company-import.d.ts +154 -0
  509. package/src/lib/model/crm-company-import.js +331 -0
  510. package/src/lib/model/crm-company-import.js.map +1 -0
  511. package/src/lib/model/crm-custom-draft.d.ts +62 -0
  512. package/src/lib/model/crm-custom-draft.js +67 -0
  513. package/src/lib/model/crm-custom-draft.js.map +1 -0
  514. package/src/lib/model/crm-deal-import.d.ts +112 -0
  515. package/src/lib/model/crm-deal-import.js +263 -0
  516. package/src/lib/model/crm-deal-import.js.map +1 -0
  517. package/src/lib/model/crm-import.d.ts +244 -0
  518. package/src/lib/model/crm-import.js +466 -0
  519. package/src/lib/model/crm-import.js.map +1 -0
  520. package/src/lib/model/crm-lead-import.d.ts +105 -0
  521. package/src/lib/model/crm-lead-import.js +255 -0
  522. package/src/lib/model/crm-lead-import.js.map +1 -0
  523. package/src/lib/model/crm-record-routes.d.ts +21 -0
  524. package/src/lib/model/crm-record-routes.js +70 -0
  525. package/src/lib/model/crm-record-routes.js.map +1 -0
  526. package/src/lib/model/crm-routes.d.ts +101 -0
  527. package/src/lib/model/crm-routes.js +92 -0
  528. package/src/lib/model/crm-routes.js.map +1 -0
  529. package/src/lib/model/crm-task-import.d.ts +94 -0
  530. package/src/lib/model/crm-task-import.js +275 -0
  531. package/src/lib/model/crm-task-import.js.map +1 -0
  532. package/src/lib/model/crm-view-param.d.ts +43 -0
  533. package/src/lib/model/crm-view-param.js +49 -0
  534. package/src/lib/model/crm-view-param.js.map +1 -0
  535. package/src/lib/model/deal-board-model.d.ts +241 -0
  536. package/src/lib/model/deal-board-model.js +439 -0
  537. package/src/lib/model/deal-board-model.js.map +1 -0
  538. package/src/lib/model/deal-form-model.d.ts +114 -0
  539. package/src/lib/model/deal-form-model.js +218 -0
  540. package/src/lib/model/deal-form-model.js.map +1 -0
  541. package/src/lib/model/deals-csv.d.ts +32 -0
  542. package/src/lib/model/deals-csv.js +37 -0
  543. package/src/lib/model/deals-csv.js.map +1 -0
  544. package/src/lib/model/import-column-shapes.d.ts +36 -0
  545. package/src/lib/model/import-column-shapes.js +76 -0
  546. package/src/lib/model/import-column-shapes.js.map +1 -0
  547. package/src/lib/model/lead-company-suggestion.d.ts +61 -0
  548. package/src/lib/model/lead-company-suggestion.js +65 -0
  549. package/src/lib/model/lead-company-suggestion.js.map +1 -0
  550. package/src/lib/model/lead-filters.d.ts +29 -0
  551. package/src/lib/model/lead-filters.js +39 -0
  552. package/src/lib/model/lead-filters.js.map +1 -0
  553. package/src/lib/model/lead-surfaces.d.ts +58 -0
  554. package/src/lib/model/lead-surfaces.js +67 -0
  555. package/src/lib/model/lead-surfaces.js.map +1 -0
  556. package/src/lib/model/leads-csv.d.ts +40 -0
  557. package/src/lib/model/leads-csv.js +40 -0
  558. package/src/lib/model/leads-csv.js.map +1 -0
  559. package/src/lib/model/next-activity-api.d.ts +31 -0
  560. package/src/lib/model/next-activity-api.js +57 -0
  561. package/src/lib/model/next-activity-api.js.map +1 -0
  562. package/src/lib/model/next-activity.d.ts +64 -0
  563. package/src/lib/model/next-activity.js +47 -0
  564. package/src/lib/model/next-activity.js.map +1 -0
  565. package/src/lib/model/person-key-web.d.ts +43 -0
  566. package/src/lib/model/person-key-web.js +52 -0
  567. package/src/lib/model/person-key-web.js.map +1 -0
  568. package/src/lib/model/record-facts.d.ts +282 -0
  569. package/src/lib/model/record-facts.js +434 -0
  570. package/src/lib/model/record-facts.js.map +1 -0
  571. package/src/lib/model/task-api.d.ts +28 -0
  572. package/src/lib/model/task-api.js +57 -0
  573. package/src/lib/model/task-api.js.map +1 -0
  574. package/src/lib/model/task-calendar.d.ts +108 -0
  575. package/src/lib/model/task-calendar.js +139 -0
  576. package/src/lib/model/task-calendar.js.map +1 -0
  577. package/src/lib/model/task-routes.d.ts +177 -0
  578. package/src/lib/model/task-routes.js +197 -0
  579. package/src/lib/model/task-routes.js.map +1 -0
  580. package/src/lib/model/task-scope.d.ts +45 -0
  581. package/src/lib/model/task-scope.js +51 -0
  582. package/src/lib/model/task-scope.js.map +1 -0
  583. package/src/lib/model/task-views.d.ts +149 -0
  584. package/src/lib/model/task-views.js +286 -0
  585. package/src/lib/model/task-views.js.map +1 -0
  586. package/src/lib/model/tasks-csv.d.ts +28 -0
  587. package/src/lib/model/tasks-csv.js +28 -0
  588. package/src/lib/model/tasks-csv.js.map +1 -0
  589. package/src/lib/plugin.d.ts +32 -0
  590. package/src/lib/plugin.js +208 -0
  591. package/src/lib/plugin.js.map +1 -0
  592. package/src/lib/server/companies-import.d.ts +57 -0
  593. package/src/lib/server/companies-import.js +242 -0
  594. package/src/lib/server/companies-import.js.map +1 -0
  595. package/src/lib/server/company-delete.d.ts +59 -0
  596. package/src/lib/server/company-delete.js +146 -0
  597. package/src/lib/server/company-delete.js.map +1 -0
  598. package/src/lib/server/contact-email-history.d.ts +82 -0
  599. package/src/lib/server/contact-email-history.js +264 -0
  600. package/src/lib/server/contact-email-history.js.map +1 -0
  601. package/src/lib/server/contact-profile.d.ts +41 -0
  602. package/src/lib/server/contact-profile.js +45 -0
  603. package/src/lib/server/contact-profile.js.map +1 -0
  604. package/src/lib/server/contact-update.d.ts +92 -0
  605. package/src/lib/server/contact-update.js +512 -0
  606. package/src/lib/server/contact-update.js.map +1 -0
  607. package/src/lib/server/contacts-import.d.ts +73 -0
  608. package/src/lib/server/contacts-import.js +263 -0
  609. package/src/lib/server/contacts-import.js.map +1 -0
  610. package/src/lib/server/contacts-merge.d.ts +86 -0
  611. package/src/lib/server/contacts-merge.js +206 -0
  612. package/src/lib/server/contacts-merge.js.map +1 -0
  613. package/src/lib/server/deals-import.d.ts +76 -0
  614. package/src/lib/server/deals-import.js +246 -0
  615. package/src/lib/server/deals-import.js.map +1 -0
  616. package/src/lib/server/email-send.d.ts +119 -0
  617. package/src/lib/server/email-send.js +667 -0
  618. package/src/lib/server/email-send.js.map +1 -0
  619. package/src/lib/server/email-template-duplicate.d.ts +19 -0
  620. package/src/lib/server/email-template-duplicate.js +206 -0
  621. package/src/lib/server/email-template-duplicate.js.map +1 -0
  622. package/src/lib/server/erase-person.d.ts +108 -0
  623. package/src/lib/server/erase-person.js +309 -0
  624. package/src/lib/server/erase-person.js.map +1 -0
  625. package/src/lib/server/import-context.d.ts +85 -0
  626. package/src/lib/server/import-context.js +181 -0
  627. package/src/lib/server/import-context.js.map +1 -0
  628. package/src/lib/server/inbound-address.d.ts +61 -0
  629. package/src/lib/server/inbound-address.js +188 -0
  630. package/src/lib/server/inbound-address.js.map +1 -0
  631. package/src/lib/server/lead-convert.d.ts +78 -0
  632. package/src/lib/server/lead-convert.js +250 -0
  633. package/src/lib/server/lead-convert.js.map +1 -0
  634. package/src/lib/server/leads-import.d.ts +84 -0
  635. package/src/lib/server/leads-import.js +261 -0
  636. package/src/lib/server/leads-import.js.map +1 -0
  637. package/src/lib/server/next-activity-routes.d.ts +33 -0
  638. package/src/lib/server/next-activity-routes.js +110 -0
  639. package/src/lib/server/next-activity-routes.js.map +1 -0
  640. package/src/lib/server/org-activity.d.ts +61 -0
  641. package/src/lib/server/org-activity.js +120 -0
  642. package/src/lib/server/org-activity.js.map +1 -0
  643. package/src/lib/server/org-caller.d.ts +110 -0
  644. package/src/lib/server/org-caller.js +154 -0
  645. package/src/lib/server/org-caller.js.map +1 -0
  646. package/src/lib/server/recipe-routes.d.ts +75 -0
  647. package/src/lib/server/recipe-routes.js +442 -0
  648. package/src/lib/server/recipe-routes.js.map +1 -0
  649. package/src/lib/server/record-facts.d.ts +65 -0
  650. package/src/lib/server/record-facts.js +337 -0
  651. package/src/lib/server/record-facts.js.map +1 -0
  652. package/src/lib/server/record-timeline.d.ts +51 -0
  653. package/src/lib/server/record-timeline.js +215 -0
  654. package/src/lib/server/record-timeline.js.map +1 -0
  655. package/src/lib/server/suite-gate.d.ts +42 -0
  656. package/src/lib/server/suite-gate.js +87 -0
  657. package/src/lib/server/suite-gate.js.map +1 -0
  658. package/src/lib/server/task-routes.d.ts +132 -0
  659. package/src/lib/server/task-routes.js +699 -0
  660. package/src/lib/server/task-routes.js.map +1 -0
  661. package/src/lib/server/tasks-import.d.ts +54 -0
  662. package/src/lib/server/tasks-import.js +157 -0
  663. package/src/lib/server/tasks-import.js.map +1 -0
  664. package/src/lib/server-deal-stage.d.ts +88 -0
  665. package/src/lib/server-deal-stage.js +316 -0
  666. package/src/lib/server-deal-stage.js.map +1 -0
  667. package/src/lib/server.d.ts +149 -0
  668. package/src/lib/server.js +615 -0
  669. package/src/lib/server.js.map +1 -0
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ /**
17
+ * The tasks CSV — one file from the section's Export button and the bulk
18
+ * bar's (AGL-2621).
19
+ *
20
+ * A task hangs off a contact, a company or a deal by id; the file names
21
+ * each by the name the list already resolved for the row, so a spreadsheet
22
+ * reads "Acme" and not a document id. The assignee is written by address
23
+ * for the same reason. A due date is an INSTANT — a task due at nine is due
24
+ * at nine in the assignee's zone — so it is written as an ISO timestamp,
25
+ * and a spreadsheet renders it in whatever zone it is opened in.
26
+ */ /* The writer moved to `@aglyn/aglyn` under AGL-2662 — see `deals-csv.ts`. */ export { TASK_CSV_COLUMNS, tasksCsv } from "@aglyn/aglyn";
27
+
28
+ //# sourceMappingURL=tasks-csv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/model/tasks-csv.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The tasks CSV — one file from the section's Export button and the bulk\n * bar's (AGL-2621).\n *\n * A task hangs off a contact, a company or a deal by id; the file names\n * each by the name the list already resolved for the row, so a spreadsheet\n * reads \"Acme\" and not a document id. The assignee is written by address\n * for the same reason. A due date is an INSTANT — a task due at nine is due\n * at nine in the assignee's zone — so it is written as an ISO timestamp,\n * and a spreadsheet renders it in whatever zone it is opened in.\n */\n\n/* The writer moved to `@aglyn/aglyn` under AGL-2662 — see `deals-csv.ts`. */\nexport {\n TASK_CSV_COLUMNS,\n tasksCsv,\n type TaskCsvOptions,\n type TaskCsvRow,\n} from '@aglyn/aglyn'\n"],"names":["TASK_CSV_COLUMNS","tasksCsv"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;CAUC,GAED,2EAA2E,GAC3E,SACEA,gBAAgB,EAChBC,QAAQ,QAGH,eAAc"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * CRM feature plugin (AGL-395, the hub since AGL-2595). Console-only — its
19
+ * records live in Firestore and have no canvas element, so there is no UI
20
+ * bundle. The console half declares the CRM nav + hub through the
21
+ * ConsoleExtension registry (release_crm gate via the nav tab); the
22
+ * contacts section reads the `contactsPerHost` quota off the shell-passed
23
+ * `org`.
24
+ *
25
+ * The plugin id is `crm` (AGL-2595). It was `contacts` while the surface was
26
+ * one list; the id is persisted in every org's `enabledPlugins` and every
27
+ * host's `disabledPlugins`, so the runtime read the old value as this one
28
+ * until the stored documents had been rewritten, and the alias was retired
29
+ * once that backfill reported nothing left (AGL-2614). The `/contacts`
30
+ * address is a URL, not a stored id, and the nav item keeps redirecting it.
31
+ */
32
+ export declare function registerCrmConsole(): void;
@@ -0,0 +1,208 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import * as Aglyn from "@aglyn/aglyn";
17
+ import { mdiCardAccountDetailsOutline } from "@aglyn/shared-data-mdi";
18
+ import { lazy } from "react";
19
+ import { CRM_CONSOLE_SECTIONS } from "./components/crm-console-sections.js";
20
+ import { CrmGlanceCard } from "./components/crm-glance-card.js";
21
+ import { BUNDLE_ID } from "./constants/bundle-common.js";
22
+ import { withCrmOrgMount } from "./hooks/use-crm-org-mount.js";
23
+ import { registerCrmRecordRoutes } from "./model/crm-record-routes.js";
24
+ import { registerPluginZone } from "@aglyn/aglyn/plugin-manager/plugin-zones";
25
+ import { CRM_RECORD_ATTRIBUTION_ZONE } from "./components/crm-attribution-zone.js";
26
+ import { CRM_RECORD_BOOKING_ZONE } from "./components/crm-booking-zone.js";
27
+ /** Code-split: the CRM hub only loads when opened. */ const CrmConsolePage = lazy(()=>import("./components/crm-console-page.js"));
28
+ /** The dashboard glance, split the same way: it loads where the slot mounts it. */ /** Where a form's fields save on a contact, drawn on the form's own page. */ const FormContactFieldsCard = lazy(()=>import("./components/form-contact-fields-card.js"));
29
+ const CrmTasksDueCard = lazy(()=>import("./components/crm-tasks-due-card.js"));
30
+ /**
31
+ * CRM feature plugin (AGL-395, the hub since AGL-2595). Console-only — its
32
+ * records live in Firestore and have no canvas element, so there is no UI
33
+ * bundle. The console half declares the CRM nav + hub through the
34
+ * ConsoleExtension registry (release_crm gate via the nav tab); the
35
+ * contacts section reads the `contactsPerHost` quota off the shell-passed
36
+ * `org`.
37
+ *
38
+ * The plugin id is `crm` (AGL-2595). It was `contacts` while the surface was
39
+ * one list; the id is persisted in every org's `enabledPlugins` and every
40
+ * host's `disabledPlugins`, so the runtime read the old value as this one
41
+ * until the stored documents had been rewritten, and the alias was retired
42
+ * once that backfill reported nothing left (AGL-2614). The `/contacts`
43
+ * address is a URL, not a stored id, and the nav item keeps redirecting it.
44
+ */ export function registerCrmConsole() {
45
+ registerCrmRecordRoutes();
46
+ registerPluginZone({
47
+ zone: CRM_RECORD_BOOKING_ZONE,
48
+ label: 'Book a meeting from a CRM record',
49
+ surface: 'console',
50
+ // One control in a record header's row of actions, and one beside the
51
+ // composer's fields: the page lays them out, so the zone adds nothing.
52
+ layout: 'bare',
53
+ description: 'In a record’s header and beside the one-to-one composer. A widget here offers the site’s bookable services and the link a visitor books one at; it is handed the site, the record and, from the composer, a way to insert the chosen link. It writes nothing.'
54
+ }, {
55
+ pluginId: BUNDLE_ID
56
+ });
57
+ registerPluginZone({
58
+ zone: CRM_RECORD_ATTRIBUTION_ZONE,
59
+ label: 'Where a CRM record came from',
60
+ surface: 'console',
61
+ description: 'On a contact’s page and in a lead’s history. A widget here says which campaign or link brought the person; it is handed the site, what the record is and its id, and it writes nothing.'
62
+ }, {
63
+ pluginId: BUNDLE_ID
64
+ });
65
+ Aglyn.registerConsoleExtension({
66
+ pluginId: BUNDLE_ID,
67
+ displayName: 'CRM',
68
+ /*
69
+ * WHO may open the CRM, declared so the shell enforces it.
70
+ *
71
+ * `navTabId` below is a release flag, not authorization: it says whether
72
+ * the surface has shipped, and `FeatureGate` reads it as
73
+ * `released || isStaff`. Nothing above this page decided who among a
74
+ * workspace's members may read it, and the page is a full editor over
75
+ * org-shared people data — names, addresses, order history, notes,
76
+ * consent, and a CSV export of all of it.
77
+ *
78
+ * `data.manage` rather than a key of this plugin's own, because it is
79
+ * the catalog key whose subject is exactly this data. The Firestore
80
+ * rules place contacts in the org-shared data block with datasets and
81
+ * gate writes on `canWriteOrgData()` — owner, admin, editor — which is
82
+ * the population `data.manage` defaults to, so the console gate and the
83
+ * rules agree on the built-in roles by construction. A custom role or a
84
+ * per-member override then narrows the console further, and the rules
85
+ * stay the boundary for the data itself.
86
+ *
87
+ * Minting a `contacts.*` key instead would advertise a control that does
88
+ * not exist. Console contact writes are client-direct against the rules,
89
+ * so a new key would have no server enforcement point to sit on, and a
90
+ * permission a customer can untick that changes nothing is worse than
91
+ * its absence.
92
+ *
93
+ * A SITE COLLABORATOR holding it reaches this page deliberately. They
94
+ * are a real org member document, so this gate is the first thing that
95
+ * has ever asked about them here — and the answer is yes, scoped: the
96
+ * listener filters on `visibleTo`, the rules prove the same predicate
97
+ * per document, and every field the page shows is read through the
98
+ * viewing group's own facet. Refusing them outright would delete a
99
+ * shipped capability rather than close a hole.
100
+ */ permission: 'data.manage',
101
+ /*
102
+ * WHAT the workspace must have bought (AGL-2851). The CRM is included
103
+ * from Starter and a Free workspace has none of it, so the flag is
104
+ * declared once, here, and the shell refuses every surface this
105
+ * registers on a plan without it: the hub body at both mounts, every
106
+ * section and record beneath it, drawn locked beside the upgrade notice,
107
+ * and the dashboard cards. The nav tab stays, as every plan-locked tab
108
+ * does, because it is the way to that notice. The CRM's routes, `/v1`
109
+ * and the Firestore rules ask the same question where the data is
110
+ * (`server/suite-gate.ts`).
111
+ */ featureFlag: 'crm',
112
+ /*
113
+ * Dashboard cards (AGL-2599, AGL-2604): the site dashboard's `hostDashboard`
114
+ * slot composes this extension's permission over each, so a card appears
115
+ * only where the CRM is enabled and only for a reader who may open it —
116
+ * registered here rather than imported by the dashboard so the shell's
117
+ * enablement and entitlement gate decides whether a site that never turned
118
+ * the CRM on sees them, the rule every card on that row follows. The tasks
119
+ * card is a glance at the reader's own overdue and due-today work and
120
+ * renders nothing on a workspace that has never made a task; the glance
121
+ * card is four server-counted figures, each a link into the hub.
122
+ *
123
+ * Both name `features.crm`, as the extension does (AGL-2611, AGL-2851):
124
+ * the slot composes the two, so a plan without the CRM gets neither card
125
+ * — absent, not upsold, the treatment every gated card gets.
126
+ *
127
+ * The same two cards again on the organization's `orgDashboard` slot
128
+ * (AGL-2636) — the org's sites page — under the same flag, with the same
129
+ * ids: the id names the card, and it is one card totaling the whole
130
+ * organization there instead of one site. The shell hands that slot the
131
+ * org mount as a prop, and `withCrmOrgMount` is what puts the mount's
132
+ * provider around each card, since the sites page cannot import one.
133
+ */ widgets: [
134
+ // Which contact field each of a form's fields saves to, on the form's
135
+ // own page. The forms plugin hosts the zone and writes the form
136
+ // document; what a contact's fields ARE is this plugin's, so the card
137
+ // is too.
138
+ {
139
+ slot: 'formContactFields',
140
+ widgetId: 'crm-form-contact-fields',
141
+ title: 'Saves to contact fields',
142
+ // A contact's custom fields are part of the suite, so a workspace
143
+ // without it has none to map a form's field onto.
144
+ featureFlag: 'crm',
145
+ Component: FormContactFieldsCard
146
+ },
147
+ {
148
+ slot: Aglyn.CONSOLE_WIDGET_SLOTS.hostDashboard,
149
+ widgetId: 'crm-tasks-due',
150
+ title: 'Tasks due',
151
+ featureFlag: 'crm',
152
+ Component: CrmTasksDueCard
153
+ },
154
+ {
155
+ slot: Aglyn.CONSOLE_WIDGET_SLOTS.hostDashboard,
156
+ widgetId: 'crm-glance',
157
+ title: 'CRM at a glance',
158
+ featureFlag: 'crm',
159
+ Component: CrmGlanceCard
160
+ },
161
+ {
162
+ slot: Aglyn.CONSOLE_WIDGET_SLOTS.orgDashboard,
163
+ widgetId: 'crm-tasks-due',
164
+ title: 'Tasks due',
165
+ featureFlag: 'crm',
166
+ Component: withCrmOrgMount(CrmTasksDueCard)
167
+ },
168
+ {
169
+ slot: Aglyn.CONSOLE_WIDGET_SLOTS.orgDashboard,
170
+ widgetId: 'crm-glance',
171
+ title: 'CRM at a glance',
172
+ featureFlag: 'crm',
173
+ Component: withCrmOrgMount(CrmGlanceCard)
174
+ }
175
+ ],
176
+ navItems: [
177
+ {
178
+ label: 'CRM',
179
+ href: '/crm',
180
+ // The address the surface had while it was one list. A link kept
181
+ // from then — a bookmark, a docs page, an email — still opens the
182
+ // hub rather than the shell's "not available" notice.
183
+ legacyHrefs: [
184
+ '/contacts'
185
+ ],
186
+ // Sections as ROUTES (AGL-2595): each is a real URL the shell
187
+ // resolves and gates, so the page mounts the one being read and a
188
+ // bare `/crm` lands on the first. Every section inherits this
189
+ // item's `release_crm` gate.
190
+ sections: CRM_CONSOLE_SECTIONS,
191
+ navTabId: 'nav-tab-contacts',
192
+ icon: {
193
+ path: mdiCardAccountDetailsOutline.path
194
+ },
195
+ header: {
196
+ title: 'CRM',
197
+ icon: {
198
+ path: mdiCardAccountDetailsOutline.path
199
+ },
200
+ docsTopic: 'crm'
201
+ },
202
+ Component: CrmConsolePage
203
+ }
204
+ ]
205
+ });
206
+ }
207
+
208
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../libs/plugins/crm/src/lib/plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn'\nimport { mdiCardAccountDetailsOutline } from '@aglyn/shared-data-mdi'\nimport { lazy } from 'react'\nimport { CRM_CONSOLE_SECTIONS } from './components/crm-console-sections'\nimport { CrmGlanceCard } from './components/crm-glance-card'\nimport { BUNDLE_ID } from './constants/bundle-common'\nimport { withCrmOrgMount } from './hooks/use-crm-org-mount'\nimport { registerCrmRecordRoutes } from './model/crm-record-routes'\nimport { registerPluginZone } from '@aglyn/aglyn/plugin-manager/plugin-zones'\nimport { CRM_RECORD_ATTRIBUTION_ZONE } from './components/crm-attribution-zone'\nimport { CRM_RECORD_BOOKING_ZONE } from './components/crm-booking-zone'\n\n/** Code-split: the CRM hub only loads when opened. */\nconst CrmConsolePage = lazy(\n () => import('./components/crm-console-page'),\n)\n/** The dashboard glance, split the same way: it loads where the slot mounts it. */\n/** Where a form's fields save on a contact, drawn on the form's own page. */\nconst FormContactFieldsCard = lazy(\n () => import('./components/form-contact-fields-card'),\n)\n\nconst CrmTasksDueCard = lazy(\n () => import('./components/crm-tasks-due-card'),\n)\n\n/**\n * CRM feature plugin (AGL-395, the hub since AGL-2595). Console-only — its\n * records live in Firestore and have no canvas element, so there is no UI\n * bundle. The console half declares the CRM nav + hub through the\n * ConsoleExtension registry (release_crm gate via the nav tab); the\n * contacts section reads the `contactsPerHost` quota off the shell-passed\n * `org`.\n *\n * The plugin id is `crm` (AGL-2595). It was `contacts` while the surface was\n * one list; the id is persisted in every org's `enabledPlugins` and every\n * host's `disabledPlugins`, so the runtime read the old value as this one\n * until the stored documents had been rewritten, and the alias was retired\n * once that backfill reported nothing left (AGL-2614). The `/contacts`\n * address is a URL, not a stored id, and the nav item keeps redirecting it.\n */\nexport function registerCrmConsole(): void {\n registerCrmRecordRoutes()\n registerPluginZone(\n {\n zone: CRM_RECORD_BOOKING_ZONE,\n label: 'Book a meeting from a CRM record',\n surface: 'console',\n // One control in a record header's row of actions, and one beside the\n // composer's fields: the page lays them out, so the zone adds nothing.\n layout: 'bare',\n description:\n 'In a record’s header and beside the one-to-one composer. A widget here offers the site’s bookable services and the link a visitor books one at; it is handed the site, the record and, from the composer, a way to insert the chosen link. It writes nothing.',\n },\n { pluginId: BUNDLE_ID },\n )\n registerPluginZone(\n {\n zone: CRM_RECORD_ATTRIBUTION_ZONE,\n label: 'Where a CRM record came from',\n surface: 'console',\n description:\n 'On a contact’s page and in a lead’s history. A widget here says which campaign or link brought the person; it is handed the site, what the record is and its id, and it writes nothing.',\n },\n { pluginId: BUNDLE_ID },\n )\n Aglyn.registerConsoleExtension({\n pluginId: BUNDLE_ID,\n displayName: 'CRM',\n /*\n * WHO may open the CRM, declared so the shell enforces it.\n *\n * `navTabId` below is a release flag, not authorization: it says whether\n * the surface has shipped, and `FeatureGate` reads it as\n * `released || isStaff`. Nothing above this page decided who among a\n * workspace's members may read it, and the page is a full editor over\n * org-shared people data — names, addresses, order history, notes,\n * consent, and a CSV export of all of it.\n *\n * `data.manage` rather than a key of this plugin's own, because it is\n * the catalog key whose subject is exactly this data. The Firestore\n * rules place contacts in the org-shared data block with datasets and\n * gate writes on `canWriteOrgData()` — owner, admin, editor — which is\n * the population `data.manage` defaults to, so the console gate and the\n * rules agree on the built-in roles by construction. A custom role or a\n * per-member override then narrows the console further, and the rules\n * stay the boundary for the data itself.\n *\n * Minting a `contacts.*` key instead would advertise a control that does\n * not exist. Console contact writes are client-direct against the rules,\n * so a new key would have no server enforcement point to sit on, and a\n * permission a customer can untick that changes nothing is worse than\n * its absence.\n *\n * A SITE COLLABORATOR holding it reaches this page deliberately. They\n * are a real org member document, so this gate is the first thing that\n * has ever asked about them here — and the answer is yes, scoped: the\n * listener filters on `visibleTo`, the rules prove the same predicate\n * per document, and every field the page shows is read through the\n * viewing group's own facet. Refusing them outright would delete a\n * shipped capability rather than close a hole.\n */\n permission: 'data.manage',\n /*\n * WHAT the workspace must have bought (AGL-2851). The CRM is included\n * from Starter and a Free workspace has none of it, so the flag is\n * declared once, here, and the shell refuses every surface this\n * registers on a plan without it: the hub body at both mounts, every\n * section and record beneath it, drawn locked beside the upgrade notice,\n * and the dashboard cards. The nav tab stays, as every plan-locked tab\n * does, because it is the way to that notice. The CRM's routes, `/v1`\n * and the Firestore rules ask the same question where the data is\n * (`server/suite-gate.ts`).\n */\n featureFlag: 'crm',\n /*\n * Dashboard cards (AGL-2599, AGL-2604): the site dashboard's `hostDashboard`\n * slot composes this extension's permission over each, so a card appears\n * only where the CRM is enabled and only for a reader who may open it —\n * registered here rather than imported by the dashboard so the shell's\n * enablement and entitlement gate decides whether a site that never turned\n * the CRM on sees them, the rule every card on that row follows. The tasks\n * card is a glance at the reader's own overdue and due-today work and\n * renders nothing on a workspace that has never made a task; the glance\n * card is four server-counted figures, each a link into the hub.\n *\n * Both name `features.crm`, as the extension does (AGL-2611, AGL-2851):\n * the slot composes the two, so a plan without the CRM gets neither card\n * — absent, not upsold, the treatment every gated card gets.\n *\n * The same two cards again on the organization's `orgDashboard` slot\n * (AGL-2636) — the org's sites page — under the same flag, with the same\n * ids: the id names the card, and it is one card totaling the whole\n * organization there instead of one site. The shell hands that slot the\n * org mount as a prop, and `withCrmOrgMount` is what puts the mount's\n * provider around each card, since the sites page cannot import one.\n */\n widgets: [\n // Which contact field each of a form's fields saves to, on the form's\n // own page. The forms plugin hosts the zone and writes the form\n // document; what a contact's fields ARE is this plugin's, so the card\n // is too.\n {\n slot: 'formContactFields',\n widgetId: 'crm-form-contact-fields',\n title: 'Saves to contact fields',\n // A contact's custom fields are part of the suite, so a workspace\n // without it has none to map a form's field onto.\n featureFlag: 'crm',\n Component: FormContactFieldsCard,\n },\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.hostDashboard,\n widgetId: 'crm-tasks-due',\n title: 'Tasks due',\n featureFlag: 'crm',\n Component: CrmTasksDueCard,\n },\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.hostDashboard,\n widgetId: 'crm-glance',\n title: 'CRM at a glance',\n featureFlag: 'crm',\n Component: CrmGlanceCard,\n },\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.orgDashboard,\n widgetId: 'crm-tasks-due',\n title: 'Tasks due',\n featureFlag: 'crm',\n Component: withCrmOrgMount(CrmTasksDueCard),\n },\n {\n slot: Aglyn.CONSOLE_WIDGET_SLOTS.orgDashboard,\n widgetId: 'crm-glance',\n title: 'CRM at a glance',\n featureFlag: 'crm',\n Component: withCrmOrgMount(CrmGlanceCard),\n },\n ],\n navItems: [\n {\n label: 'CRM',\n href: '/crm',\n // The address the surface had while it was one list. A link kept\n // from then — a bookmark, a docs page, an email — still opens the\n // hub rather than the shell's \"not available\" notice.\n legacyHrefs: ['/contacts'],\n // Sections as ROUTES (AGL-2595): each is a real URL the shell\n // resolves and gates, so the page mounts the one being read and a\n // bare `/crm` lands on the first. Every section inherits this\n // item's `release_crm` gate.\n sections: CRM_CONSOLE_SECTIONS,\n navTabId: 'nav-tab-contacts',\n icon: { path: mdiCardAccountDetailsOutline.path },\n header: {\n title: 'CRM',\n icon: { path: mdiCardAccountDetailsOutline.path },\n docsTopic: 'crm',\n },\n Component: CrmConsolePage,\n },\n ],\n })\n}\n"],"names":["Aglyn","mdiCardAccountDetailsOutline","lazy","CRM_CONSOLE_SECTIONS","CrmGlanceCard","BUNDLE_ID","withCrmOrgMount","registerCrmRecordRoutes","registerPluginZone","CRM_RECORD_ATTRIBUTION_ZONE","CRM_RECORD_BOOKING_ZONE","CrmConsolePage","FormContactFieldsCard","CrmTasksDueCard","registerCrmConsole","zone","label","surface","layout","description","pluginId","registerConsoleExtension","displayName","permission","featureFlag","widgets","slot","widgetId","title","Component","CONSOLE_WIDGET_SLOTS","hostDashboard","orgDashboard","navItems","href","legacyHrefs","sections","navTabId","icon","path","header","docsTopic"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,eAAc;AACrC,SAASC,4BAA4B,QAAQ,yBAAwB;AACrE,SAASC,IAAI,QAAQ,QAAO;AAC5B,SAASC,oBAAoB,QAAQ,uCAAmC;AACxE,SAASC,aAAa,QAAQ,kCAA8B;AAC5D,SAASC,SAAS,QAAQ,+BAA2B;AACrD,SAASC,eAAe,QAAQ,+BAA2B;AAC3D,SAASC,uBAAuB,QAAQ,+BAA2B;AACnE,SAASC,kBAAkB,QAAQ,2CAA0C;AAC7E,SAASC,2BAA2B,QAAQ,uCAAmC;AAC/E,SAASC,uBAAuB,QAAQ,mCAA+B;AAEvE,oDAAoD,GACpD,MAAMC,iBAAiBT,KACrB,IAAM,MAAM,CAAC;AAEf,iFAAiF,GACjF,2EAA2E,GAC3E,MAAMU,wBAAwBV,KAC5B,IAAM,MAAM,CAAC;AAGf,MAAMW,kBAAkBX,KACtB,IAAM,MAAM,CAAC;AAGf;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASY;IACdP;IACAC,mBACE;QACEO,MAAML;QACNM,OAAO;QACPC,SAAS;QACT,sEAAsE;QACtE,uEAAuE;QACvEC,QAAQ;QACRC,aACE;IACJ,GACA;QAAEC,UAAUf;IAAU;IAExBG,mBACE;QACEO,MAAMN;QACNO,OAAO;QACPC,SAAS;QACTE,aACE;IACJ,GACA;QAAEC,UAAUf;IAAU;IAExBL,MAAMqB,wBAAwB,CAAC;QAC7BD,UAAUf;QACViB,aAAa;QACb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAgCC,GACDC,YAAY;QACZ;;;;;;;;;;KAUC,GACDC,aAAa;QACb;;;;;;;;;;;;;;;;;;;;;KAqBC,GACDC,SAAS;YACP,sEAAsE;YACtE,gEAAgE;YAChE,sEAAsE;YACtE,UAAU;YACV;gBACEC,MAAM;gBACNC,UAAU;gBACVC,OAAO;gBACP,kEAAkE;gBAClE,kDAAkD;gBAClDJ,aAAa;gBACbK,WAAWjB;YACb;YACA;gBACEc,MAAM1B,MAAM8B,oBAAoB,CAACC,aAAa;gBAC9CJ,UAAU;gBACVC,OAAO;gBACPJ,aAAa;gBACbK,WAAWhB;YACb;YACA;gBACEa,MAAM1B,MAAM8B,oBAAoB,CAACC,aAAa;gBAC9CJ,UAAU;gBACVC,OAAO;gBACPJ,aAAa;gBACbK,WAAWzB;YACb;YACA;gBACEsB,MAAM1B,MAAM8B,oBAAoB,CAACE,YAAY;gBAC7CL,UAAU;gBACVC,OAAO;gBACPJ,aAAa;gBACbK,WAAWvB,gBAAgBO;YAC7B;YACA;gBACEa,MAAM1B,MAAM8B,oBAAoB,CAACE,YAAY;gBAC7CL,UAAU;gBACVC,OAAO;gBACPJ,aAAa;gBACbK,WAAWvB,gBAAgBF;YAC7B;SACD;QACD6B,UAAU;YACR;gBACEjB,OAAO;gBACPkB,MAAM;gBACN,iEAAiE;gBACjE,kEAAkE;gBAClE,sDAAsD;gBACtDC,aAAa;oBAAC;iBAAY;gBAC1B,8DAA8D;gBAC9D,kEAAkE;gBAClE,8DAA8D;gBAC9D,6BAA6B;gBAC7BC,UAAUjC;gBACVkC,UAAU;gBACVC,MAAM;oBAAEC,MAAMtC,6BAA6BsC,IAAI;gBAAC;gBAChDC,QAAQ;oBACNZ,OAAO;oBACPU,MAAM;wBAAEC,MAAMtC,6BAA6BsC,IAAI;oBAAC;oBAChDE,WAAW;gBACb;gBACAZ,WAAWlB;YACb;SACD;IACH;AACF"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * `POST /api/crm/companies-import` — one chunk of a companies file, written
19
+ * (AGL-2621).
20
+ *
21
+ * The browser has already read the file and applied the operator's column
22
+ * mapping; what arrives here is up to {@link COMPANY_IMPORT_CHUNK_SIZE} raw
23
+ * rows in the vocabulary `crm-company-import.ts` defines. This route judges
24
+ * each one through the same normalizers the company drawer runs, and
25
+ * writes it — the ONLY place either happens, so a stale tab cannot store
26
+ * something the server would have refused.
27
+ *
28
+ * ## Matched by domain, then by name
29
+ *
30
+ * A row is one company the org may already have. The domain is a key and
31
+ * the name a spelling, so a row with a domain is looked up by it first,
32
+ * and by the name's search key when no company carries the domain or the
33
+ * row has none — two files calling one business "Acme" and "Acme Inc" meet
34
+ * at `acme.com`, and a file with no domain column still finds "Acme" by
35
+ * name. Both lookups are narrowed to what the caller's scope can see: two
36
+ * clients of one agency may each have an "Acme" and must each get their
37
+ * own. A match is UPDATED with what the row carries, tags unioned; no
38
+ * match is CREATED with the stamp every CRM creator writes.
39
+ *
40
+ * ## The band is counted once per request
41
+ *
42
+ * A created company is a CRM record and meets the records band (AGL-2611).
43
+ * The aggregate is taken once at the first create and the verdict re-judged
44
+ * locally as the request creates more — `checkCrmRecordsQuota` is pure over
45
+ * a count — so two hundred rows cost three aggregate reads, not six
46
+ * hundred. A metered plan never refuses; a hard band refuses the rows past
47
+ * it as `records-band`, and updates to matched companies go through either
48
+ * way, because an update adds no record.
49
+ */
50
+ import { type PluginApiHandler } from '@aglyn/aglyn/server';
51
+ /**
52
+ * `POST crm/companies-import` — `{ hostId, rows }` → a {@link CompanyImportChunkResult}.
53
+ *
54
+ * Rows are written one after another rather than in parallel: two rows
55
+ * for one company racing each other would each miss the other's create.
56
+ */
57
+ export declare const crmCompaniesImportHandler: PluginApiHandler;
@@ -0,0 +1,242 @@
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
+ * `POST /api/crm/companies-import` — one chunk of a companies file, written
19
+ * (AGL-2621).
20
+ *
21
+ * The browser has already read the file and applied the operator's column
22
+ * mapping; what arrives here is up to {@link COMPANY_IMPORT_CHUNK_SIZE} raw
23
+ * rows in the vocabulary `crm-company-import.ts` defines. This route judges
24
+ * each one through the same normalizers the company drawer runs, and
25
+ * writes it — the ONLY place either happens, so a stale tab cannot store
26
+ * something the server would have refused.
27
+ *
28
+ * ## Matched by domain, then by name
29
+ *
30
+ * A row is one company the org may already have. The domain is a key and
31
+ * the name a spelling, so a row with a domain is looked up by it first,
32
+ * and by the name's search key when no company carries the domain or the
33
+ * row has none — two files calling one business "Acme" and "Acme Inc" meet
34
+ * at `acme.com`, and a file with no domain column still finds "Acme" by
35
+ * name. Both lookups are narrowed to what the caller's scope can see: two
36
+ * clients of one agency may each have an "Acme" and must each get their
37
+ * own. A match is UPDATED with what the row carries, tags unioned; no
38
+ * match is CREATED with the stamp every CRM creator writes.
39
+ *
40
+ * ## The band is counted once per request
41
+ *
42
+ * A created company is a CRM record and meets the records band (AGL-2611).
43
+ * The aggregate is taken once at the first create and the verdict re-judged
44
+ * locally as the request creates more — `checkCrmRecordsQuota` is pure over
45
+ * a count — so two hundred rows cost three aggregate reads, not six
46
+ * hundred. A metered plan never refuses; a hard band refuses the rows past
47
+ * it as `records-band`, and updates to matched companies go through either
48
+ * way, because an update adds no record.
49
+ */ import { checkCrmRecordsQuota, CRM_COLLECTIONS, fieldDefinitionsForObject, nameSearchFields, visibleToTokens } from "@aglyn/aglyn/server";
50
+ import { COMPANY_IMPORT_CHUNK_SIZE, COMPANY_IMPORT_MAX_BODY_BYTES, companyImportMatchKey, normalizeCompanyImportRow } from "../model/crm-company-import.js";
51
+ import { crmRecordsQuotaForOrg, firebaseAdmin } from "@aglyn/tenant-data-admin";
52
+ import { FieldValue } from "firebase-admin/firestore";
53
+ import { ownerDirectory, readImportRows, resolveImportContext } from "./import-context.js";
54
+ /** The company a row refers to in this scope — by domain, then by name — or `null`. */ async function findCompany(companies, readTokens, row) {
55
+ const seen = (snapshot)=>{
56
+ var _snapshot_docs_find;
57
+ return (_snapshot_docs_find = snapshot.docs.find((doc)=>visibleToTokens(doc.get('visibleTo'), readTokens))) != null ? _snapshot_docs_find : null;
58
+ };
59
+ if (row.domain) {
60
+ const byDomain = seen(await companies.where('domain', '==', row.domain).limit(10).get());
61
+ if (byDomain) return byDomain;
62
+ }
63
+ return seen(await companies.where('nameLower', '==', nameSearchFields(row.name).nameLower).limit(10).get());
64
+ }
65
+ /**
66
+ * The fields a row writes — on a create and on an update alike. Only what
67
+ * the row carries: an update must not clear a website the file did not
68
+ * mention, so an absent optional is left absent here rather than deleted.
69
+ */ function storedFields(row, ownerUid) {
70
+ return _extends({}, nameSearchFields(row.name), row.domain ? {
71
+ domain: row.domain
72
+ } : {}, row.website ? {
73
+ website: row.website
74
+ } : {}, row.phone ? {
75
+ phone: row.phone
76
+ } : {}, row.industry ? {
77
+ industry: row.industry
78
+ } : {}, ownerUid ? {
79
+ ownerUid
80
+ } : {}, row.address ? {
81
+ address: row.address
82
+ } : {}, row.notes ? {
83
+ notes: row.notes
84
+ } : {});
85
+ }
86
+ /**
87
+ * The row's custom values as a MERGE writes them: one dotted path per key,
88
+ * so a company already filed keeps every value the file did not carry
89
+ * (AGL-2661). A create spreads the map itself — see the loop below.
90
+ */ function customUpdate(row) {
91
+ return Object.fromEntries(Object.entries(row.custom).map(([key, value])=>[
92
+ `custom.${key}`,
93
+ value
94
+ ]));
95
+ }
96
+ /**
97
+ * The org's live COMPANY field definitions (AGL-2661) — the contact
98
+ * import's read, narrowed to the object this import writes. Read in full
99
+ * and filtered in memory: a holder has a handful of fields, and a `where`
100
+ * on `object` would need an index for a collection that fits in one page.
101
+ */ async function loadCompanyFieldDefinitions(orgId, readTokens) {
102
+ const snapshot = await firebaseAdmin.app().firestore().collection('orgs').doc(orgId).collection(CRM_COLLECTIONS.contactFields).limit(200).get();
103
+ return fieldDefinitionsForObject(snapshot.docs.map((doc)=>doc.data()), 'company').filter((field)=>!!field.key && !field.retiredAt && visibleToTokens(field.visibleTo, readTokens));
104
+ }
105
+ /**
106
+ * `POST crm/companies-import` — `{ hostId, rows }` → a {@link CompanyImportChunkResult}.
107
+ *
108
+ * Rows are written one after another rather than in parallel: two rows
109
+ * for one company racing each other would each miss the other's create.
110
+ */ export const crmCompaniesImportHandler = async (req, res)=>{
111
+ if (req.method !== 'POST') {
112
+ res.setHeader('Allow', 'POST');
113
+ return res.status(405).json({
114
+ error: 'Method not allowed'
115
+ });
116
+ }
117
+ const read = readImportRows(req, {
118
+ maxBodyBytes: COMPANY_IMPORT_MAX_BODY_BYTES,
119
+ chunkSize: COMPANY_IMPORT_CHUNK_SIZE
120
+ });
121
+ if ('error' in read) return res.status(read.status).json({
122
+ error: read.error
123
+ });
124
+ try {
125
+ const context = await resolveImportContext(req);
126
+ if (context.ok === false) return res.status(context.status).json(context.body);
127
+ const skipped = [];
128
+ const dropped = {};
129
+ const normalized = [];
130
+ const fields = await loadCompanyFieldDefinitions(context.orgId, context.readTokens);
131
+ /*
132
+ * A duplicate WITHIN the request is skipped rather than merged: the
133
+ * second row would update the first's record and the count would read
134
+ * one created and one merged for one company in one file. Across
135
+ * requests the lookup answers, and reports a merge.
136
+ */ const seen = new Set();
137
+ read.rows.forEach((raw, index)=>{
138
+ const verdict = normalizeCompanyImportRow(raw, fields);
139
+ if (verdict.ok === false) {
140
+ skipped.push({
141
+ index,
142
+ name: verdict.input,
143
+ reason: verdict.reason
144
+ });
145
+ return;
146
+ }
147
+ const key = companyImportMatchKey(verdict.row);
148
+ if (seen.has(key)) {
149
+ skipped.push({
150
+ index,
151
+ name: verdict.row.name,
152
+ reason: 'duplicate'
153
+ });
154
+ return;
155
+ }
156
+ seen.add(key);
157
+ for (const entry of verdict.row.dropped){
158
+ var _dropped_entry_field;
159
+ dropped[entry.field] = ((_dropped_entry_field = dropped[entry.field]) != null ? _dropped_entry_field : 0) + 1;
160
+ }
161
+ normalized.push({
162
+ index,
163
+ row: verdict.row
164
+ });
165
+ });
166
+ const owners = await ownerDirectory(context.orgId, normalized.map((entry)=>entry.row));
167
+ const ownersUnresolved = new Set();
168
+ const orgRef = firebaseAdmin.app().firestore().collection('orgs').doc(context.orgId);
169
+ const companies = orgRef.collection(CRM_COLLECTIONS.companies);
170
+ const stamp = creationStamp(context);
171
+ let counted = null;
172
+ let createdHere = 0;
173
+ let created = 0;
174
+ let merged = 0;
175
+ for (const { index, row } of normalized){
176
+ let ownerUid;
177
+ if (row.ownerEmail) {
178
+ ownerUid = owners.get(row.ownerEmail);
179
+ if (!ownerUid) ownersUnresolved.add(row.ownerEmail);
180
+ }
181
+ const existing = await findCompany(companies, context.readTokens, row);
182
+ const stored = storedFields(row, ownerUid);
183
+ if (existing) {
184
+ await existing.ref.update(_extends({}, stored, row.tags.length ? {
185
+ tags: FieldValue.arrayUnion(...row.tags)
186
+ } : {}, customUpdate(row), {
187
+ updatedAt: FieldValue.serverTimestamp()
188
+ }));
189
+ merged += 1;
190
+ continue;
191
+ }
192
+ if (!counted) counted = await crmRecordsQuotaForOrg(context.org, orgRef);
193
+ const room = checkCrmRecordsQuota(context.org, counted.crmRecordsCount + createdHere);
194
+ if (!room.allowed) {
195
+ skipped.push({
196
+ index,
197
+ name: row.name,
198
+ reason: 'records-band'
199
+ });
200
+ continue;
201
+ }
202
+ await companies.add(_extends({}, stored, {
203
+ tags: row.tags
204
+ }, Object.keys(row.custom).length ? {
205
+ custom: row.custom
206
+ } : {}, stamp));
207
+ createdHere += 1;
208
+ created += 1;
209
+ }
210
+ const result = {
211
+ received: read.rows.length,
212
+ created,
213
+ merged,
214
+ skipped: skipped.sort((a, b)=>a.index - b.index),
215
+ dropped,
216
+ ownersUnresolved: [
217
+ ...ownersUnresolved
218
+ ]
219
+ };
220
+ return res.status(200).json(result);
221
+ } catch (error) {
222
+ console.error('crm/companies-import failed', error);
223
+ return res.status(500).json({
224
+ error: 'The import could not continue.'
225
+ });
226
+ }
227
+ };
228
+ /**
229
+ * What every company this import CREATES carries beside its fields: the
230
+ * scope every CRM creator stamps, the site as provenance, who imported it,
231
+ * and the clocks. A record written without `visibleTo` is seen by nobody.
232
+ */ function creationStamp(context) {
233
+ return {
234
+ hostId: context.hostId,
235
+ visibleTo: context.scopeTokens,
236
+ createdByUid: context.uid,
237
+ createdAt: FieldValue.serverTimestamp(),
238
+ updatedAt: FieldValue.serverTimestamp()
239
+ };
240
+ }
241
+
242
+ //# sourceMappingURL=companies-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/server/companies-import.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * `POST /api/crm/companies-import` — one chunk of a companies file, written\n * (AGL-2621).\n *\n * The browser has already read the file and applied the operator's column\n * mapping; what arrives here is up to {@link COMPANY_IMPORT_CHUNK_SIZE} raw\n * rows in the vocabulary `crm-company-import.ts` defines. This route judges\n * each one through the same normalizers the company drawer runs, and\n * writes it — the ONLY place either happens, so a stale tab cannot store\n * something the server would have refused.\n *\n * ## Matched by domain, then by name\n *\n * A row is one company the org may already have. The domain is a key and\n * the name a spelling, so a row with a domain is looked up by it first,\n * and by the name's search key when no company carries the domain or the\n * row has none — two files calling one business \"Acme\" and \"Acme Inc\" meet\n * at `acme.com`, and a file with no domain column still finds \"Acme\" by\n * name. Both lookups are narrowed to what the caller's scope can see: two\n * clients of one agency may each have an \"Acme\" and must each get their\n * own. A match is UPDATED with what the row carries, tags unioned; no\n * match is CREATED with the stamp every CRM creator writes.\n *\n * ## The band is counted once per request\n *\n * A created company is a CRM record and meets the records band (AGL-2611).\n * The aggregate is taken once at the first create and the verdict re-judged\n * locally as the request creates more — `checkCrmRecordsQuota` is pure over\n * a count — so two hundred rows cost three aggregate reads, not six\n * hundred. A metered plan never refuses; a hard band refuses the rows past\n * it as `records-band`, and updates to matched companies go through either\n * way, because an update adds no record.\n */\n\nimport {\n checkCrmRecordsQuota,\n type ContactFieldDefinition,\n CRM_COLLECTIONS,\n fieldDefinitionsForObject,\n nameSearchFields,\n type PluginApiHandler,\n visibleToTokens,\n} from '@aglyn/aglyn/server'\nimport {\n COMPANY_IMPORT_CHUNK_SIZE,\n COMPANY_IMPORT_MAX_BODY_BYTES,\n type CompanyImportChunkResult,\n type CompanyImportRawRow,\n type CompanyImportRow,\n type CompanyImportSkippedRow,\n companyImportMatchKey,\n normalizeCompanyImportRow,\n} from '../model/crm-company-import'\nimport { crmRecordsQuotaForOrg, firebaseAdmin } from '@aglyn/tenant-data-admin'\nimport { FieldValue } from 'firebase-admin/firestore'\nimport {\n type ImportContext,\n ownerDirectory,\n readImportRows,\n resolveImportContext,\n} from './import-context'\n\ntype Companies = FirebaseFirestore.CollectionReference\n\n/** The company a row refers to in this scope — by domain, then by name — or `null`. */\nasync function findCompany(\n companies: Companies,\n readTokens: readonly string[],\n row: Pick<CompanyImportRow, 'name' | 'domain'>,\n): Promise<FirebaseFirestore.QueryDocumentSnapshot | null> {\n const seen = (snapshot: FirebaseFirestore.QuerySnapshot) =>\n snapshot.docs.find((doc) => visibleToTokens(doc.get('visibleTo'), readTokens)) ?? null\n if (row.domain) {\n const byDomain = seen(\n await companies.where('domain', '==', row.domain).limit(10).get(),\n )\n if (byDomain) return byDomain\n }\n return seen(\n await companies\n .where('nameLower', '==', nameSearchFields(row.name).nameLower)\n .limit(10)\n .get(),\n )\n}\n\n/**\n * The fields a row writes — on a create and on an update alike. Only what\n * the row carries: an update must not clear a website the file did not\n * mention, so an absent optional is left absent here rather than deleted.\n */\nfunction storedFields(\n row: CompanyImportRow,\n ownerUid: string | undefined,\n): Record<string, unknown> {\n return {\n ...nameSearchFields(row.name),\n ...(row.domain ? { domain: row.domain } : {}),\n ...(row.website ? { website: row.website } : {}),\n ...(row.phone ? { phone: row.phone } : {}),\n ...(row.industry ? { industry: row.industry } : {}),\n ...(ownerUid ? { ownerUid } : {}),\n ...(row.address ? { address: row.address } : {}),\n ...(row.notes ? { notes: row.notes } : {}),\n }\n}\n\n/**\n * The row's custom values as a MERGE writes them: one dotted path per key,\n * so a company already filed keeps every value the file did not carry\n * (AGL-2661). A create spreads the map itself — see the loop below.\n */\nfunction customUpdate(row: CompanyImportRow): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(row.custom).map(([key, value]) => [`custom.${key}`, value]),\n )\n}\n\n/**\n * The org's live COMPANY field definitions (AGL-2661) — the contact\n * import's read, narrowed to the object this import writes. Read in full\n * and filtered in memory: a holder has a handful of fields, and a `where`\n * on `object` would need an index for a collection that fits in one page.\n */\nasync function loadCompanyFieldDefinitions(\n orgId: string,\n readTokens: readonly string[],\n): Promise<ContactFieldDefinition[]> {\n const snapshot = await firebaseAdmin\n .app()\n .firestore()\n .collection('orgs')\n .doc(orgId)\n .collection(CRM_COLLECTIONS.contactFields)\n .limit(200)\n .get()\n return fieldDefinitionsForObject(\n snapshot.docs.map((doc) => doc.data() as ContactFieldDefinition),\n 'company',\n ).filter(\n (field) =>\n !!field.key && !field.retiredAt && visibleToTokens(field.visibleTo, readTokens),\n )\n}\n\n/**\n * `POST crm/companies-import` — `{ hostId, rows }` → a {@link CompanyImportChunkResult}.\n *\n * Rows are written one after another rather than in parallel: two rows\n * for one company racing each other would each miss the other's create.\n */\nexport const crmCompaniesImportHandler: PluginApiHandler = async (req, res) => {\n if (req.method !== 'POST') {\n res.setHeader('Allow', 'POST')\n return res.status(405).json({ error: 'Method not allowed' })\n }\n const read = readImportRows<CompanyImportRawRow>(req, {\n maxBodyBytes: COMPANY_IMPORT_MAX_BODY_BYTES,\n chunkSize: COMPANY_IMPORT_CHUNK_SIZE,\n })\n if ('error' in read) return res.status(read.status).json({ error: read.error })\n try {\n const context = await resolveImportContext(req)\n if (context.ok === false) return res.status(context.status).json(context.body)\n\n const skipped: CompanyImportSkippedRow[] = []\n const dropped: Record<string, number> = {}\n const normalized: { index: number; row: CompanyImportRow }[] = []\n const fields = await loadCompanyFieldDefinitions(context.orgId, context.readTokens)\n /*\n * A duplicate WITHIN the request is skipped rather than merged: the\n * second row would update the first's record and the count would read\n * one created and one merged for one company in one file. Across\n * requests the lookup answers, and reports a merge.\n */\n const seen = new Set<string>()\n read.rows.forEach((raw, index) => {\n const verdict = normalizeCompanyImportRow(raw, fields)\n if (verdict.ok === false) {\n skipped.push({ index, name: verdict.input, reason: verdict.reason })\n return\n }\n const key = companyImportMatchKey(verdict.row)\n if (seen.has(key)) {\n skipped.push({ index, name: verdict.row.name, reason: 'duplicate' })\n return\n }\n seen.add(key)\n for (const entry of verdict.row.dropped) {\n dropped[entry.field] = (dropped[entry.field] ?? 0) + 1\n }\n normalized.push({ index, row: verdict.row })\n })\n\n const owners = await ownerDirectory(\n context.orgId,\n normalized.map((entry) => entry.row),\n )\n const ownersUnresolved = new Set<string>()\n const orgRef = firebaseAdmin.app().firestore().collection('orgs').doc(context.orgId)\n const companies = orgRef.collection(CRM_COLLECTIONS.companies)\n const stamp = creationStamp(context)\n let counted: { crmRecordsCount: number } | null = null\n let createdHere = 0\n let created = 0\n let merged = 0\n\n for (const { index, row } of normalized) {\n let ownerUid: string | undefined\n if (row.ownerEmail) {\n ownerUid = owners.get(row.ownerEmail)\n if (!ownerUid) ownersUnresolved.add(row.ownerEmail)\n }\n const existing = await findCompany(companies, context.readTokens, row)\n const stored = storedFields(row, ownerUid)\n if (existing) {\n await existing.ref.update({\n ...stored,\n ...(row.tags.length ? { tags: FieldValue.arrayUnion(...row.tags) } : {}),\n ...customUpdate(row),\n updatedAt: FieldValue.serverTimestamp(),\n })\n merged += 1\n continue\n }\n if (!counted) counted = await crmRecordsQuotaForOrg(context.org as never, orgRef)\n const room = checkCrmRecordsQuota(\n context.org as never,\n counted.crmRecordsCount + createdHere,\n )\n if (!room.allowed) {\n skipped.push({ index, name: row.name, reason: 'records-band' })\n continue\n }\n await companies.add({\n ...stored,\n tags: row.tags,\n ...(Object.keys(row.custom).length ? { custom: row.custom } : {}),\n ...stamp,\n })\n createdHere += 1\n created += 1\n }\n\n const result: CompanyImportChunkResult = {\n received: read.rows.length,\n created,\n merged,\n skipped: skipped.sort((a, b) => a.index - b.index),\n dropped,\n ownersUnresolved: [...ownersUnresolved],\n }\n return res.status(200).json(result)\n } catch (error) {\n console.error('crm/companies-import failed', error)\n return res.status(500).json({ error: 'The import could not continue.' })\n }\n}\n\n/**\n * What every company this import CREATES carries beside its fields: the\n * scope every CRM creator stamps, the site as provenance, who imported it,\n * and the clocks. A record written without `visibleTo` is seen by nobody.\n */\nfunction creationStamp(\n context: Extract<ImportContext, { ok: true }>,\n): Record<string, unknown> {\n return {\n hostId: context.hostId,\n visibleTo: context.scopeTokens,\n createdByUid: context.uid,\n createdAt: FieldValue.serverTimestamp(),\n updatedAt: FieldValue.serverTimestamp(),\n }\n}\n"],"names":["checkCrmRecordsQuota","CRM_COLLECTIONS","fieldDefinitionsForObject","nameSearchFields","visibleToTokens","COMPANY_IMPORT_CHUNK_SIZE","COMPANY_IMPORT_MAX_BODY_BYTES","companyImportMatchKey","normalizeCompanyImportRow","crmRecordsQuotaForOrg","firebaseAdmin","FieldValue","ownerDirectory","readImportRows","resolveImportContext","findCompany","companies","readTokens","row","seen","snapshot","docs","find","doc","get","domain","byDomain","where","limit","name","nameLower","storedFields","ownerUid","website","phone","industry","address","notes","customUpdate","Object","fromEntries","entries","custom","map","key","value","loadCompanyFieldDefinitions","orgId","app","firestore","collection","contactFields","data","filter","field","retiredAt","visibleTo","crmCompaniesImportHandler","req","res","method","setHeader","status","json","error","read","maxBodyBytes","chunkSize","context","ok","body","skipped","dropped","normalized","fields","Set","rows","forEach","raw","index","verdict","push","input","reason","has","add","entry","owners","ownersUnresolved","orgRef","stamp","creationStamp","counted","createdHere","created","merged","ownerEmail","existing","stored","ref","update","tags","length","arrayUnion","updatedAt","serverTimestamp","org","room","crmRecordsCount","allowed","keys","result","received","sort","a","b","console","hostId","scopeTokens","createdByUid","uid","createdAt"],"mappings":"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"}