@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,154 @@
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
+ * BRINGING A SPREADSHEET OF COMPANIES INTO THE CRM — the pure half
19
+ * (AGL-2621).
20
+ *
21
+ * The contact import's three stages (`crm-import.ts`) over the company
22
+ * vocabulary: a header row is matched to a proposed mapping, one line is
23
+ * mapped to a raw row of verbatim strings, and the server normalizes each
24
+ * row through the SAME functions the company drawer runs —
25
+ * `normalizeCompanyDomain` for the key, `normalizeCompanyWebsite` for the
26
+ * link, `normalizePhone` for E.164, `normalizeAddress` for the postal shape
27
+ * — so an imported company and a typed one are the same document.
28
+ *
29
+ * ## The name is the one thing a row must have
30
+ *
31
+ * A company is matched by its DOMAIN first and its name second, because a
32
+ * domain is a key and a name is a spelling: two files calling one business
33
+ * "Acme" and "Acme Inc" meet at `acme.com`. But a row with a domain and no
34
+ * name would create a record the list cannot caption, so the name is
35
+ * required and the domain optional — the opposite of the contact import,
36
+ * where the address is both the key and the caption.
37
+ *
38
+ * ## A bad cell is dropped and named; a bad row is skipped and named
39
+ *
40
+ * The contact import's rule, unchanged: a domain that is not a hostname, a
41
+ * phone that is not a number, a website that is not a URL, a country that
42
+ * is not a code — each is left off the record and REPORTED under
43
+ * {@link CompanyImportRow.dropped}, never silently discarded.
44
+ */
45
+ import type { AglynPostalAddress } from '@aglyn/aglyn/foundation/definitions/contact.types';
46
+ import { type ContactFieldDefinition, type CrmCustomValue } from '@aglyn/aglyn/app-utils/crm';
47
+ import { type ImportChunkResult, type ImportDroppedValue } from '@aglyn/aglyn/app-utils/csv-import';
48
+ /** The shared ceilings, under this collection's names. */
49
+ export declare const COMPANY_IMPORT_MAX_ROWS = 5000;
50
+ export declare const COMPANY_IMPORT_CHUNK_SIZE = 200;
51
+ export declare const COMPANY_IMPORT_MAX_BODY_BYTES = 2000000;
52
+ export declare const COMPANY_IMPORT_PREVIEW_ROWS = 10;
53
+ /** The most tags one company may carry — the same cap a contact has. */
54
+ export declare const COMPANY_IMPORT_TAGS_MAX = 20;
55
+ /** The fields a column may be mapped to, in the order the mapping menu lists them. */
56
+ export declare const COMPANY_IMPORT_FIELDS: readonly ["name", "domain", "website", "phone", "industry", "ownerEmail", "addressLine1", "addressLine2", "addressCity", "addressState", "addressPostalCode", "addressCountry", "tags", "notes"];
57
+ export type CompanyImportField = (typeof COMPANY_IMPORT_FIELDS)[number];
58
+ /** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */
59
+ export declare const COMPANY_IMPORT_FIELD_LABELS: Record<CompanyImportField, string>;
60
+ /**
61
+ * Column index → field, or a company custom field as `custom:<key>` (AGL-2661).
62
+ * A column absent from the map is not imported.
63
+ */
64
+ export type CompanyImportMapping = Record<number, CompanyImportField | `custom:${string}`>;
65
+ /**
66
+ * A proposed mapping from a file's header row, each field taken at most
67
+ * once. `fields` is the org's COMPANY definitions (AGL-2661): a header
68
+ * matching one's label or key maps onto it, and wins over a standard
69
+ * alias, the contact import's rule.
70
+ */
71
+ export declare function guessCompanyImportMapping(columns: readonly string[], fields?: readonly Pick<ContactFieldDefinition, 'key' | 'label'>[]): CompanyImportMapping;
72
+ /**
73
+ * What the browser posts for one line: the cells the mapping selected,
74
+ * under the field they were mapped to, verbatim. `unknown` because the
75
+ * server reads this off an untrusted body.
76
+ */
77
+ export type CompanyImportRawRow = Partial<Record<CompanyImportField, unknown>> & {
78
+ /** Custom values by definition key, verbatim — judged by `normalizeCompanyImportRow`. */
79
+ custom?: unknown;
80
+ };
81
+ /**
82
+ * One parsed line under the mapping. Empty cells are left absent; custom
83
+ * values are gathered under `custom` by definition key (AGL-2661).
84
+ */
85
+ export declare function mapCompanyImportRow(cells: readonly string[], mapping: CompanyImportMapping): CompanyImportRawRow;
86
+ /** Why one row was not stored. */
87
+ export type CompanyImportSkipReason = 'missing-name' | 'duplicate' | 'records-band' | 'write-failed';
88
+ /** How a skip reason reads on screen and in the downloaded file. */
89
+ export declare const COMPANY_IMPORT_SKIP_LABELS: Record<CompanyImportSkipReason, string>;
90
+ /** One row, ready to be written. */
91
+ export interface CompanyImportRow {
92
+ name: string;
93
+ /** Lowercase hostname — the match key when present. */
94
+ domain?: string;
95
+ /** An absolute http(s) URL. */
96
+ website?: string;
97
+ /** E.164. */
98
+ phone?: string;
99
+ industry?: string;
100
+ /** Normalized, for the server to resolve against the org's members. */
101
+ ownerEmail?: string;
102
+ address?: AglynPostalAddress;
103
+ /** Lowercased, deduplicated, capped at {@link COMPANY_IMPORT_TAGS_MAX}. */
104
+ tags: string[];
105
+ notes?: string;
106
+ dropped: ImportDroppedValue[];
107
+ /**
108
+ * Custom values under the org's COMPANY definitions (AGL-2661), each
109
+ * coerced by its type the way a contact's are. Empty when the file
110
+ * mapped none, or none survived.
111
+ */
112
+ custom: Record<string, CrmCustomValue>;
113
+ }
114
+ export type CompanyImportRowVerdict = {
115
+ ok: true;
116
+ row: CompanyImportRow;
117
+ } | {
118
+ ok: false;
119
+ reason: 'missing-name';
120
+ input: string;
121
+ };
122
+ /**
123
+ * One raw row as the values that will be written, or the reason it cannot
124
+ * be. Refused only for a missing name; every other unreadable cell is
125
+ * dropped and named.
126
+ */
127
+ export declare function normalizeCompanyImportRow(raw: CompanyImportRawRow,
128
+ /**
129
+ * The org's live COMPANY definitions (AGL-2661): a value under a key
130
+ * with no definition is dropped and reported, because a value nobody
131
+ * defined a field for is a value no surface will ever show.
132
+ */
133
+ fields?: readonly Pick<ContactFieldDefinition, 'key' | 'type' | 'options'>[]): CompanyImportRowVerdict;
134
+ /**
135
+ * How two rows are recognized as one company: by domain when the row has
136
+ * one, else by the name's search key — the same `nameLower` the companies
137
+ * list searches on, so "Acme" and "ACME " are one key.
138
+ */
139
+ export declare function companyImportMatchKey(row: Pick<CompanyImportRow, 'name' | 'domain'>): string;
140
+ /** One row the server did not store, by its index in the request, named by the company. */
141
+ export interface CompanyImportSkippedRow {
142
+ index: number;
143
+ name: string;
144
+ reason: CompanyImportSkipReason;
145
+ }
146
+ /** What one request did. The drawer sums these across a file. */
147
+ export type CompanyImportChunkResult = ImportChunkResult<CompanyImportSkippedRow>;
148
+ export declare function emptyCompanyImportResult(): CompanyImportChunkResult;
149
+ export declare function mergeCompanyImportResults(total: CompanyImportChunkResult, chunk: CompanyImportChunkResult, offset?: number): CompanyImportChunkResult;
150
+ /** The skipped rows as a file the operator can fix and re-import. */
151
+ export declare function companyImportSkippedCsv(columns: readonly string[], entries: readonly {
152
+ cells: readonly string[];
153
+ reason: CompanyImportSkipReason;
154
+ }[]): string;
@@ -0,0 +1,331 @@
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
+ * BRINGING A SPREADSHEET OF COMPANIES INTO THE CRM — the pure half
18
+ * (AGL-2621).
19
+ *
20
+ * The contact import's three stages (`crm-import.ts`) over the company
21
+ * vocabulary: a header row is matched to a proposed mapping, one line is
22
+ * mapped to a raw row of verbatim strings, and the server normalizes each
23
+ * row through the SAME functions the company drawer runs —
24
+ * `normalizeCompanyDomain` for the key, `normalizeCompanyWebsite` for the
25
+ * link, `normalizePhone` for E.164, `normalizeAddress` for the postal shape
26
+ * — so an imported company and a typed one are the same document.
27
+ *
28
+ * ## The name is the one thing a row must have
29
+ *
30
+ * A company is matched by its DOMAIN first and its name second, because a
31
+ * domain is a key and a name is a spelling: two files calling one business
32
+ * "Acme" and "Acme Inc" meet at `acme.com`. But a row with a domain and no
33
+ * name would create a record the list cannot caption, so the name is
34
+ * required and the domain optional — the opposite of the contact import,
35
+ * where the address is both the key and the caption.
36
+ *
37
+ * ## A bad cell is dropped and named; a bad row is skipped and named
38
+ *
39
+ * The contact import's rule, unchanged: a domain that is not a hostname, a
40
+ * phone that is not a number, a website that is not a URL, a country that
41
+ * is not a code — each is left off the record and REPORTED under
42
+ * {@link CompanyImportRow.dropped}, never silently discarded.
43
+ */ import { normalizeAddress, normalizePhone } from "@aglyn/aglyn/foundation/definitions/contact.types";
44
+ import { normalizeContactEmail } from "@aglyn/aglyn/app-utils/contacts";
45
+ import { normalizeCompanyDomain, normalizeCompanyWebsite } from "@aglyn/aglyn/app-utils/crm";
46
+ import { parseContactImportCustomValue } from "./crm-import.js";
47
+ import { customImportTarget, CSV_IMPORT_CHUNK_SIZE, CSV_IMPORT_MAX_BODY_BYTES, CSV_IMPORT_MAX_ROWS, CSV_IMPORT_PREVIEW_ROWS, emptyImportResult, guessImportMapping, importAliasKeys, importSkippedCsv, importTextValue, mapImportRow, mergeImportResults, parseImportTags } from "@aglyn/aglyn/app-utils/csv-import";
48
+ import { nameSearchKey } from "@aglyn/aglyn/app-utils/name-search";
49
+ /** The shared ceilings, under this collection's names. */ export const COMPANY_IMPORT_MAX_ROWS = CSV_IMPORT_MAX_ROWS;
50
+ export const COMPANY_IMPORT_CHUNK_SIZE = CSV_IMPORT_CHUNK_SIZE;
51
+ export const COMPANY_IMPORT_MAX_BODY_BYTES = CSV_IMPORT_MAX_BODY_BYTES;
52
+ export const COMPANY_IMPORT_PREVIEW_ROWS = CSV_IMPORT_PREVIEW_ROWS;
53
+ /** The most tags one company may carry — the same cap a contact has. */ export const COMPANY_IMPORT_TAGS_MAX = 20;
54
+ const NAME_MAX = 120;
55
+ const INDUSTRY_MAX = 80;
56
+ const NOTES_MAX = 4000;
57
+ /** The fields a column may be mapped to, in the order the mapping menu lists them. */ export const COMPANY_IMPORT_FIELDS = [
58
+ 'name',
59
+ 'domain',
60
+ 'website',
61
+ 'phone',
62
+ 'industry',
63
+ 'ownerEmail',
64
+ 'addressLine1',
65
+ 'addressLine2',
66
+ 'addressCity',
67
+ 'addressState',
68
+ 'addressPostalCode',
69
+ 'addressCountry',
70
+ 'tags',
71
+ 'notes'
72
+ ];
73
+ /** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */ export const COMPANY_IMPORT_FIELD_LABELS = {
74
+ name: 'Company name (required)',
75
+ domain: 'Domain',
76
+ website: 'Website',
77
+ phone: 'Phone',
78
+ industry: 'Industry',
79
+ ownerEmail: 'Owner (team member email)',
80
+ addressLine1: 'Address line 1',
81
+ addressLine2: 'Address line 2',
82
+ addressCity: 'City',
83
+ addressState: 'State or region',
84
+ addressPostalCode: 'Postal code',
85
+ addressCountry: 'Country (two-letter code)',
86
+ tags: 'Tags (comma or | separated)',
87
+ notes: 'Notes'
88
+ };
89
+ /**
90
+ * Header aliases per field, matched after the shared header normalization.
91
+ *
92
+ * The vocabulary of the exports people arrive with, and — first in each
93
+ * list — the header this CRM's own companies export writes, so an export
94
+ * re-imports without a hand mapping.
95
+ */ const FIELD_ALIASES = {
96
+ name: [
97
+ 'company',
98
+ 'company name',
99
+ 'name',
100
+ 'organization',
101
+ 'organisation',
102
+ 'account',
103
+ 'account name'
104
+ ],
105
+ domain: [
106
+ 'domain',
107
+ 'company domain',
108
+ 'domain name',
109
+ 'web domain',
110
+ 'email domain'
111
+ ],
112
+ website: [
113
+ 'website',
114
+ 'web site',
115
+ 'url',
116
+ 'website url',
117
+ 'homepage',
118
+ 'web'
119
+ ],
120
+ phone: [
121
+ 'phone',
122
+ 'phone number',
123
+ 'telephone',
124
+ 'company phone',
125
+ 'main phone'
126
+ ],
127
+ industry: [
128
+ 'industry',
129
+ 'sector',
130
+ 'vertical',
131
+ 'category'
132
+ ],
133
+ ownerEmail: [
134
+ 'owner',
135
+ 'owner email',
136
+ 'company owner',
137
+ 'account owner',
138
+ 'assigned to'
139
+ ],
140
+ addressLine1: [
141
+ 'address line 1',
142
+ 'address',
143
+ 'street',
144
+ 'street address',
145
+ 'address 1'
146
+ ],
147
+ addressLine2: [
148
+ 'address line 2',
149
+ 'address 2',
150
+ 'street 2',
151
+ 'suite'
152
+ ],
153
+ addressCity: [
154
+ 'city',
155
+ 'town',
156
+ 'locality'
157
+ ],
158
+ addressState: [
159
+ 'state',
160
+ 'region',
161
+ 'province',
162
+ 'county',
163
+ 'state/region'
164
+ ],
165
+ addressPostalCode: [
166
+ 'postal code',
167
+ 'postcode',
168
+ 'zip',
169
+ 'zip code',
170
+ 'post code'
171
+ ],
172
+ addressCountry: [
173
+ 'country',
174
+ 'country code',
175
+ 'country/region'
176
+ ],
177
+ tags: [
178
+ 'tags',
179
+ 'tag',
180
+ 'labels',
181
+ 'groups'
182
+ ],
183
+ notes: [
184
+ 'notes',
185
+ 'note',
186
+ 'description',
187
+ 'comments'
188
+ ]
189
+ };
190
+ const FIELD_ALIAS_KEYS = importAliasKeys(COMPANY_IMPORT_FIELDS, FIELD_ALIASES);
191
+ /**
192
+ * A proposed mapping from a file's header row, each field taken at most
193
+ * once. `fields` is the org's COMPANY definitions (AGL-2661): a header
194
+ * matching one's label or key maps onto it, and wins over a standard
195
+ * alias, the contact import's rule.
196
+ */ export function guessCompanyImportMapping(columns, fields = []) {
197
+ return guessImportMapping(columns, COMPANY_IMPORT_FIELDS, FIELD_ALIAS_KEYS, fields);
198
+ }
199
+ /**
200
+ * One parsed line under the mapping. Empty cells are left absent; custom
201
+ * values are gathered under `custom` by definition key (AGL-2661).
202
+ */ export function mapCompanyImportRow(cells, mapping) {
203
+ return mapImportRow(cells, mapping);
204
+ }
205
+ /** How a skip reason reads on screen and in the downloaded file. */ export const COMPANY_IMPORT_SKIP_LABELS = {
206
+ 'missing-name': 'No company name',
207
+ duplicate: 'Appears earlier in the file',
208
+ 'records-band': 'CRM records limit reached',
209
+ 'write-failed': 'Could not be saved'
210
+ };
211
+ /**
212
+ * One raw row as the values that will be written, or the reason it cannot
213
+ * be. Refused only for a missing name; every other unreadable cell is
214
+ * dropped and named.
215
+ */ export function normalizeCompanyImportRow(raw, /**
216
+ * The org's live COMPANY definitions (AGL-2661): a value under a key
217
+ * with no definition is dropped and reported, because a value nobody
218
+ * defined a field for is a value no surface will ever show.
219
+ */ fields = []) {
220
+ var _importTextValue;
221
+ const name = (_importTextValue = importTextValue(raw.name, NAME_MAX)) == null ? void 0 : _importTextValue.replace(/\s+/g, ' ');
222
+ if (!name) {
223
+ var _raw_domain;
224
+ return {
225
+ ok: false,
226
+ reason: 'missing-name',
227
+ input: String((_raw_domain = raw.domain) != null ? _raw_domain : '').trim()
228
+ };
229
+ }
230
+ const dropped = [];
231
+ const drop = (field, value)=>{
232
+ dropped.push({
233
+ field,
234
+ value: String(value != null ? value : '').trim()
235
+ });
236
+ };
237
+ const row = {
238
+ name,
239
+ tags: parseImportTags(raw.tags, COMPANY_IMPORT_TAGS_MAX),
240
+ dropped,
241
+ custom: {}
242
+ };
243
+ const domainText = importTextValue(raw.domain, 300);
244
+ if (domainText) {
245
+ const domain = normalizeCompanyDomain(domainText);
246
+ if (domain) row.domain = domain;
247
+ else drop('domain', domainText);
248
+ }
249
+ const websiteText = importTextValue(raw.website, 600);
250
+ if (websiteText) {
251
+ const website = normalizeCompanyWebsite(websiteText);
252
+ if (website) row.website = website;
253
+ else drop('website', websiteText);
254
+ }
255
+ const phoneText = importTextValue(raw.phone, 64);
256
+ if (phoneText) {
257
+ const phone = normalizePhone(phoneText);
258
+ if (phone) row.phone = phone;
259
+ else drop('phone', phoneText);
260
+ }
261
+ const industry = importTextValue(raw.industry, INDUSTRY_MAX);
262
+ if (industry) row.industry = industry;
263
+ const ownerText = importTextValue(raw.ownerEmail, 320);
264
+ if (ownerText) {
265
+ const owner = normalizeContactEmail(ownerText);
266
+ if (owner) row.ownerEmail = owner;
267
+ else drop('ownerEmail', ownerText);
268
+ }
269
+ const address = normalizeAddress({
270
+ line1: importTextValue(raw.addressLine1, 200),
271
+ line2: importTextValue(raw.addressLine2, 200),
272
+ city: importTextValue(raw.addressCity, 120),
273
+ state: importTextValue(raw.addressState, 120),
274
+ postalCode: importTextValue(raw.addressPostalCode, 32),
275
+ country: importTextValue(raw.addressCountry, 8)
276
+ });
277
+ if (address) row.address = address;
278
+ // The country is the one address part the normalizer drops silently — a
279
+ // typed name is not a code — so it is the one part the report has to name.
280
+ const countryText = importTextValue(raw.addressCountry, 64);
281
+ if (countryText && !(address == null ? void 0 : address.country)) drop('addressCountry', countryText);
282
+ const notes = importTextValue(raw.notes, NOTES_MAX);
283
+ if (notes) row.notes = notes;
284
+ // The contact import's custom rule, over the company's definitions.
285
+ const custom = raw.custom && typeof raw.custom === 'object' && !Array.isArray(raw.custom) ? raw.custom : {};
286
+ const definitions = new Map(fields.map((field)=>[
287
+ field.key,
288
+ field
289
+ ]));
290
+ for (const [key, value] of Object.entries(custom)){
291
+ const definition = definitions.get(key);
292
+ if (!definition) {
293
+ dropped.push({
294
+ field: customImportTarget(key),
295
+ value: String(value != null ? value : '').trim()
296
+ });
297
+ continue;
298
+ }
299
+ const parsed = parseContactImportCustomValue(definition, value);
300
+ if (!parsed) {
301
+ dropped.push({
302
+ field: customImportTarget(key),
303
+ value: String(value != null ? value : '').trim()
304
+ });
305
+ } else if (parsed.value !== undefined) {
306
+ row.custom[key] = parsed.value;
307
+ }
308
+ }
309
+ return {
310
+ ok: true,
311
+ row
312
+ };
313
+ }
314
+ /**
315
+ * How two rows are recognized as one company: by domain when the row has
316
+ * one, else by the name's search key — the same `nameLower` the companies
317
+ * list searches on, so "Acme" and "ACME " are one key.
318
+ */ export function companyImportMatchKey(row) {
319
+ return row.domain ? `domain:${row.domain}` : `name:${nameSearchKey(row.name)}`;
320
+ }
321
+ export function emptyCompanyImportResult() {
322
+ return emptyImportResult();
323
+ }
324
+ export function mergeCompanyImportResults(total, chunk, offset = 0) {
325
+ return mergeImportResults(total, chunk, offset);
326
+ }
327
+ /** The skipped rows as a file the operator can fix and re-import. */ export function companyImportSkippedCsv(columns, entries) {
328
+ return importSkippedCsv(columns, entries, COMPANY_IMPORT_SKIP_LABELS);
329
+ }
330
+
331
+ //# sourceMappingURL=crm-company-import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/model/crm-company-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 * BRINGING A SPREADSHEET OF COMPANIES INTO THE CRM — the pure half\n * (AGL-2621).\n *\n * The contact import's three stages (`crm-import.ts`) over the company\n * vocabulary: a header row is matched to a proposed mapping, one line is\n * mapped to a raw row of verbatim strings, and the server normalizes each\n * row through the SAME functions the company drawer runs —\n * `normalizeCompanyDomain` for the key, `normalizeCompanyWebsite` for the\n * link, `normalizePhone` for E.164, `normalizeAddress` for the postal shape\n * — so an imported company and a typed one are the same document.\n *\n * ## The name is the one thing a row must have\n *\n * A company is matched by its DOMAIN first and its name second, because a\n * domain is a key and a name is a spelling: two files calling one business\n * \"Acme\" and \"Acme Inc\" meet at `acme.com`. But a row with a domain and no\n * name would create a record the list cannot caption, so the name is\n * required and the domain optional — the opposite of the contact import,\n * where the address is both the key and the caption.\n *\n * ## A bad cell is dropped and named; a bad row is skipped and named\n *\n * The contact import's rule, unchanged: a domain that is not a hostname, a\n * phone that is not a number, a website that is not a URL, a country that\n * is not a code — each is left off the record and REPORTED under\n * {@link CompanyImportRow.dropped}, never silently discarded.\n */\n\nimport type { AglynPostalAddress } from '@aglyn/aglyn/foundation/definitions/contact.types'\nimport { normalizeAddress, normalizePhone } from '@aglyn/aglyn/foundation/definitions/contact.types'\nimport { normalizeContactEmail } from '@aglyn/aglyn/app-utils/contacts'\nimport {\n type ContactFieldDefinition,\n type CrmCustomValue,\n normalizeCompanyDomain,\n normalizeCompanyWebsite,\n} from '@aglyn/aglyn/app-utils/crm'\nimport { parseContactImportCustomValue } from './crm-import'\nimport {\n customImportTarget,\n CSV_IMPORT_CHUNK_SIZE,\n CSV_IMPORT_MAX_BODY_BYTES,\n CSV_IMPORT_MAX_ROWS,\n CSV_IMPORT_PREVIEW_ROWS,\n emptyImportResult,\n guessImportMapping,\n importAliasKeys,\n type ImportChunkResult,\n type ImportDroppedValue,\n importSkippedCsv,\n importTextValue,\n mapImportRow,\n mergeImportResults,\n parseImportTags,\n} from '@aglyn/aglyn/app-utils/csv-import'\nimport { nameSearchKey } from '@aglyn/aglyn/app-utils/name-search'\n\n/** The shared ceilings, under this collection's names. */\nexport const COMPANY_IMPORT_MAX_ROWS = CSV_IMPORT_MAX_ROWS\nexport const COMPANY_IMPORT_CHUNK_SIZE = CSV_IMPORT_CHUNK_SIZE\nexport const COMPANY_IMPORT_MAX_BODY_BYTES = CSV_IMPORT_MAX_BODY_BYTES\nexport const COMPANY_IMPORT_PREVIEW_ROWS = CSV_IMPORT_PREVIEW_ROWS\n\n/** The most tags one company may carry — the same cap a contact has. */\nexport const COMPANY_IMPORT_TAGS_MAX = 20\n\nconst NAME_MAX = 120\nconst INDUSTRY_MAX = 80\nconst NOTES_MAX = 4000\n\n/** The fields a column may be mapped to, in the order the mapping menu lists them. */\nexport const COMPANY_IMPORT_FIELDS = [\n 'name',\n 'domain',\n 'website',\n 'phone',\n 'industry',\n 'ownerEmail',\n 'addressLine1',\n 'addressLine2',\n 'addressCity',\n 'addressState',\n 'addressPostalCode',\n 'addressCountry',\n 'tags',\n 'notes',\n] as const\n\nexport type CompanyImportField = (typeof COMPANY_IMPORT_FIELDS)[number]\n\n/** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */\nexport const COMPANY_IMPORT_FIELD_LABELS: Record<CompanyImportField, string> = {\n name: 'Company name (required)',\n domain: 'Domain',\n website: 'Website',\n phone: 'Phone',\n industry: 'Industry',\n ownerEmail: 'Owner (team member email)',\n addressLine1: 'Address line 1',\n addressLine2: 'Address line 2',\n addressCity: 'City',\n addressState: 'State or region',\n addressPostalCode: 'Postal code',\n addressCountry: 'Country (two-letter code)',\n tags: 'Tags (comma or | separated)',\n notes: 'Notes',\n}\n\n/**\n * Header aliases per field, matched after the shared header normalization.\n *\n * The vocabulary of the exports people arrive with, and — first in each\n * list — the header this CRM's own companies export writes, so an export\n * re-imports without a hand mapping.\n */\nconst FIELD_ALIASES: Record<CompanyImportField, readonly string[]> = {\n name: ['company', 'company name', 'name', 'organization', 'organisation', 'account', 'account name'],\n domain: ['domain', 'company domain', 'domain name', 'web domain', 'email domain'],\n website: ['website', 'web site', 'url', 'website url', 'homepage', 'web'],\n phone: ['phone', 'phone number', 'telephone', 'company phone', 'main phone'],\n industry: ['industry', 'sector', 'vertical', 'category'],\n ownerEmail: ['owner', 'owner email', 'company owner', 'account owner', 'assigned to'],\n addressLine1: ['address line 1', 'address', 'street', 'street address', 'address 1'],\n addressLine2: ['address line 2', 'address 2', 'street 2', 'suite'],\n addressCity: ['city', 'town', 'locality'],\n addressState: ['state', 'region', 'province', 'county', 'state/region'],\n addressPostalCode: ['postal code', 'postcode', 'zip', 'zip code', 'post code'],\n addressCountry: ['country', 'country code', 'country/region'],\n tags: ['tags', 'tag', 'labels', 'groups'],\n notes: ['notes', 'note', 'description', 'comments'],\n}\n\nconst FIELD_ALIAS_KEYS = importAliasKeys(COMPANY_IMPORT_FIELDS, FIELD_ALIASES)\n\n/**\n * Column index → field, or a company custom field as `custom:<key>` (AGL-2661).\n * A column absent from the map is not imported.\n */\nexport type CompanyImportMapping = Record<number, CompanyImportField | `custom:${string}`>\n\n/**\n * A proposed mapping from a file's header row, each field taken at most\n * once. `fields` is the org's COMPANY definitions (AGL-2661): a header\n * matching one's label or key maps onto it, and wins over a standard\n * alias, the contact import's rule.\n */\nexport function guessCompanyImportMapping(\n columns: readonly string[],\n fields: readonly Pick<ContactFieldDefinition, 'key' | 'label'>[] = [],\n): CompanyImportMapping {\n return guessImportMapping(columns, COMPANY_IMPORT_FIELDS, FIELD_ALIAS_KEYS, fields)\n}\n\n/**\n * What the browser posts for one line: the cells the mapping selected,\n * under the field they were mapped to, verbatim. `unknown` because the\n * server reads this off an untrusted body.\n */\nexport type CompanyImportRawRow = Partial<Record<CompanyImportField, unknown>> & {\n /** Custom values by definition key, verbatim — judged by `normalizeCompanyImportRow`. */\n custom?: unknown\n}\n\n/**\n * One parsed line under the mapping. Empty cells are left absent; custom\n * values are gathered under `custom` by definition key (AGL-2661).\n */\nexport function mapCompanyImportRow(\n cells: readonly string[],\n mapping: CompanyImportMapping,\n): CompanyImportRawRow {\n return mapImportRow(cells, mapping)\n}\n\n/** Why one row was not stored. */\nexport type CompanyImportSkipReason =\n | 'missing-name'\n | 'duplicate'\n | 'records-band'\n | 'write-failed'\n\n/** How a skip reason reads on screen and in the downloaded file. */\nexport const COMPANY_IMPORT_SKIP_LABELS: Record<CompanyImportSkipReason, string> = {\n 'missing-name': 'No company name',\n duplicate: 'Appears earlier in the file',\n 'records-band': 'CRM records limit reached',\n 'write-failed': 'Could not be saved',\n}\n\n/** One row, ready to be written. */\nexport interface CompanyImportRow {\n name: string\n /** Lowercase hostname — the match key when present. */\n domain?: string\n /** An absolute http(s) URL. */\n website?: string\n /** E.164. */\n phone?: string\n industry?: string\n /** Normalized, for the server to resolve against the org's members. */\n ownerEmail?: string\n address?: AglynPostalAddress\n /** Lowercased, deduplicated, capped at {@link COMPANY_IMPORT_TAGS_MAX}. */\n tags: string[]\n notes?: string\n dropped: ImportDroppedValue[]\n /**\n * Custom values under the org's COMPANY definitions (AGL-2661), each\n * coerced by its type the way a contact's are. Empty when the file\n * mapped none, or none survived.\n */\n custom: Record<string, CrmCustomValue>\n}\n\nexport type CompanyImportRowVerdict =\n | { ok: true; row: CompanyImportRow }\n | { ok: false; reason: 'missing-name'; input: string }\n\n/**\n * One raw row as the values that will be written, or the reason it cannot\n * be. Refused only for a missing name; every other unreadable cell is\n * dropped and named.\n */\nexport function normalizeCompanyImportRow(\n raw: CompanyImportRawRow,\n /**\n * The org's live COMPANY definitions (AGL-2661): a value under a key\n * with no definition is dropped and reported, because a value nobody\n * defined a field for is a value no surface will ever show.\n */\n fields: readonly Pick<ContactFieldDefinition, 'key' | 'type' | 'options'>[] = [],\n): CompanyImportRowVerdict {\n const name = importTextValue(raw.name, NAME_MAX)?.replace(/\\s+/g, ' ')\n if (!name) {\n return { ok: false, reason: 'missing-name', input: String(raw.domain ?? '').trim() }\n }\n const dropped: ImportDroppedValue[] = []\n const drop = (field: CompanyImportField, value: unknown) => {\n dropped.push({ field, value: String(value ?? '').trim() })\n }\n const row: CompanyImportRow = {\n name,\n tags: parseImportTags(raw.tags, COMPANY_IMPORT_TAGS_MAX),\n dropped,\n custom: {},\n }\n\n const domainText = importTextValue(raw.domain, 300)\n if (domainText) {\n const domain = normalizeCompanyDomain(domainText)\n if (domain) row.domain = domain\n else drop('domain', domainText)\n }\n\n const websiteText = importTextValue(raw.website, 600)\n if (websiteText) {\n const website = normalizeCompanyWebsite(websiteText)\n if (website) row.website = website\n else drop('website', websiteText)\n }\n\n const phoneText = importTextValue(raw.phone, 64)\n if (phoneText) {\n const phone = normalizePhone(phoneText)\n if (phone) row.phone = phone\n else drop('phone', phoneText)\n }\n\n const industry = importTextValue(raw.industry, INDUSTRY_MAX)\n if (industry) row.industry = industry\n\n const ownerText = importTextValue(raw.ownerEmail, 320)\n if (ownerText) {\n const owner = normalizeContactEmail(ownerText)\n if (owner) row.ownerEmail = owner\n else drop('ownerEmail', ownerText)\n }\n\n const address = normalizeAddress({\n line1: importTextValue(raw.addressLine1, 200),\n line2: importTextValue(raw.addressLine2, 200),\n city: importTextValue(raw.addressCity, 120),\n state: importTextValue(raw.addressState, 120),\n postalCode: importTextValue(raw.addressPostalCode, 32),\n country: importTextValue(raw.addressCountry, 8),\n })\n if (address) row.address = address\n // The country is the one address part the normalizer drops silently — a\n // typed name is not a code — so it is the one part the report has to name.\n const countryText = importTextValue(raw.addressCountry, 64)\n if (countryText && !address?.country) drop('addressCountry', countryText)\n\n const notes = importTextValue(raw.notes, NOTES_MAX)\n if (notes) row.notes = notes\n\n // The contact import's custom rule, over the company's definitions.\n const custom =\n raw.custom && typeof raw.custom === 'object' && !Array.isArray(raw.custom)\n ? (raw.custom as Record<string, unknown>)\n : {}\n const definitions = new Map(fields.map((field) => [field.key, field]))\n for (const [key, value] of Object.entries(custom)) {\n const definition = definitions.get(key)\n if (!definition) {\n dropped.push({ field: customImportTarget(key), value: String(value ?? '').trim() })\n continue\n }\n const parsed = parseContactImportCustomValue(definition, value)\n if (!parsed) {\n dropped.push({ field: customImportTarget(key), value: String(value ?? '').trim() })\n } else if (parsed.value !== undefined) {\n row.custom[key] = parsed.value\n }\n }\n\n return { ok: true, row }\n}\n\n/**\n * How two rows are recognized as one company: by domain when the row has\n * one, else by the name's search key — the same `nameLower` the companies\n * list searches on, so \"Acme\" and \"ACME \" are one key.\n */\nexport function companyImportMatchKey(\n row: Pick<CompanyImportRow, 'name' | 'domain'>,\n): string {\n return row.domain ? `domain:${row.domain}` : `name:${nameSearchKey(row.name)}`\n}\n\n/** One row the server did not store, by its index in the request, named by the company. */\nexport interface CompanyImportSkippedRow {\n index: number\n name: string\n reason: CompanyImportSkipReason\n}\n\n/** What one request did. The drawer sums these across a file. */\nexport type CompanyImportChunkResult = ImportChunkResult<CompanyImportSkippedRow>\n\nexport function emptyCompanyImportResult(): CompanyImportChunkResult {\n return emptyImportResult<CompanyImportSkippedRow>()\n}\n\nexport function mergeCompanyImportResults(\n total: CompanyImportChunkResult,\n chunk: CompanyImportChunkResult,\n offset = 0,\n): CompanyImportChunkResult {\n return mergeImportResults(total, chunk, offset)\n}\n\n/** The skipped rows as a file the operator can fix and re-import. */\nexport function companyImportSkippedCsv(\n columns: readonly string[],\n entries: readonly { cells: readonly string[]; reason: CompanyImportSkipReason }[],\n): string {\n return importSkippedCsv(columns, entries, COMPANY_IMPORT_SKIP_LABELS)\n}\n"],"names":["normalizeAddress","normalizePhone","normalizeContactEmail","normalizeCompanyDomain","normalizeCompanyWebsite","parseContactImportCustomValue","customImportTarget","CSV_IMPORT_CHUNK_SIZE","CSV_IMPORT_MAX_BODY_BYTES","CSV_IMPORT_MAX_ROWS","CSV_IMPORT_PREVIEW_ROWS","emptyImportResult","guessImportMapping","importAliasKeys","importSkippedCsv","importTextValue","mapImportRow","mergeImportResults","parseImportTags","nameSearchKey","COMPANY_IMPORT_MAX_ROWS","COMPANY_IMPORT_CHUNK_SIZE","COMPANY_IMPORT_MAX_BODY_BYTES","COMPANY_IMPORT_PREVIEW_ROWS","COMPANY_IMPORT_TAGS_MAX","NAME_MAX","INDUSTRY_MAX","NOTES_MAX","COMPANY_IMPORT_FIELDS","COMPANY_IMPORT_FIELD_LABELS","name","domain","website","phone","industry","ownerEmail","addressLine1","addressLine2","addressCity","addressState","addressPostalCode","addressCountry","tags","notes","FIELD_ALIASES","FIELD_ALIAS_KEYS","guessCompanyImportMapping","columns","fields","mapCompanyImportRow","cells","mapping","COMPANY_IMPORT_SKIP_LABELS","duplicate","normalizeCompanyImportRow","raw","replace","ok","reason","input","String","trim","dropped","drop","field","value","push","row","custom","domainText","websiteText","phoneText","ownerText","owner","address","line1","line2","city","state","postalCode","country","countryText","Array","isArray","definitions","Map","map","key","Object","entries","definition","get","parsed","undefined","companyImportMatchKey","emptyCompanyImportResult","mergeCompanyImportResults","total","chunk","offset","companyImportSkippedCsv"],"mappings":"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"}
@@ -0,0 +1,62 @@
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
+ import type { ContactFieldDefinition, CrmCustomValue } from '@aglyn/aglyn';
18
+ /**
19
+ * A custom-field DRAFT: the keys a person touched, over what is stored
20
+ * (AGL-2661).
21
+ *
22
+ * Every surface that edits a `custom` map — the contact's card, the
23
+ * company's and the deal's drawers — holds the same two things: the map
24
+ * as it was read, and the keys the reader has changed since. What Save
25
+ * writes is the difference, key by key, because a `custom` map written
26
+ * whole would take every key the surface did not show out with it, and a
27
+ * write of every key would turn a one-field edit into a write of ten.
28
+ * Pure, so the three surfaces cannot drift on what "changed" means.
29
+ */
30
+ export type CrmCustomDraft = Record<string, CrmCustomValue>;
31
+ /** A stored `custom` map, as read — absent keys and `null` both read as nothing. */
32
+ export type CrmCustomStored = Readonly<Record<string, CrmCustomValue | undefined>>;
33
+ /** The value a key shows: the draft's where touched, else the stored one. */
34
+ export declare function crmCustomDraftValue(stored: CrmCustomStored, draft: CrmCustomDraft, key: string): CrmCustomValue | undefined;
35
+ /**
36
+ * The keys whose draft differs from what is stored, with the value to
37
+ * write — `null` for a cleared one, the explicit "nothing" that keeps the
38
+ * key present for a `where` clause to find.
39
+ */
40
+ export declare function crmCustomDraftChanges(stored: CrmCustomStored, draft: CrmCustomDraft): Array<[key: string, value: CrmCustomValue]>;
41
+ /**
42
+ * The changes as an `update()` payload: one dotted path per key, so the
43
+ * map is merged rather than replaced. Empty when nothing changed, so a
44
+ * caller can spread it into a larger write unconditionally.
45
+ */
46
+ export declare function crmCustomDraftWrites(stored: CrmCustomStored, draft: CrmCustomDraft): Record<`custom.${string}`, CrmCustomValue>;
47
+ /**
48
+ * The draft as the `custom` map a CREATE stores: every key with a value,
49
+ * `null` and absent both left out because a fresh document has nothing to
50
+ * clear. `undefined` when nothing would be stored, so a caller spreads
51
+ * `{ custom }` only when there is one.
52
+ */
53
+ export declare function crmCustomDraftDocument(draft: CrmCustomDraft): Record<string, CrmCustomValue> | undefined;
54
+ /**
55
+ * The required definitions the draft leaves empty — which Save refuses.
56
+ *
57
+ * On an EDIT only a key the reader cleared counts: a required field a
58
+ * record has always lacked is not this save's to demand, or a rename
59
+ * could be refused for a field added last week. On a CREATE every
60
+ * required field counts, because the record is being made whole.
61
+ */
62
+ export declare function crmCustomDraftMissingRequired(definitions: readonly Pick<ContactFieldDefinition, 'key' | 'required' | 'label'>[], stored: CrmCustomStored, draft: CrmCustomDraft, mode: 'create' | 'edit'): string[];
@@ -0,0 +1,67 @@
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
+ */ /** The value a key shows: the draft's where touched, else the stored one. */ export function crmCustomDraftValue(stored, draft, key) {
17
+ return key in draft ? draft[key] : stored[key];
18
+ }
19
+ /**
20
+ * The keys whose draft differs from what is stored, with the value to
21
+ * write — `null` for a cleared one, the explicit "nothing" that keeps the
22
+ * key present for a `where` clause to find.
23
+ */ export function crmCustomDraftChanges(stored, draft) {
24
+ return Object.entries(draft).filter(([key, value])=>{
25
+ var _stored_key;
26
+ return (value != null ? value : null) !== ((_stored_key = stored[key]) != null ? _stored_key : null);
27
+ }).map(([key, value])=>[
28
+ key,
29
+ value != null ? value : null
30
+ ]);
31
+ }
32
+ /**
33
+ * The changes as an `update()` payload: one dotted path per key, so the
34
+ * map is merged rather than replaced. Empty when nothing changed, so a
35
+ * caller can spread it into a larger write unconditionally.
36
+ */ export function crmCustomDraftWrites(stored, draft) {
37
+ return Object.fromEntries(crmCustomDraftChanges(stored, draft).map(([key, value])=>[
38
+ `custom.${key}`,
39
+ value
40
+ ]));
41
+ }
42
+ /**
43
+ * The draft as the `custom` map a CREATE stores: every key with a value,
44
+ * `null` and absent both left out because a fresh document has nothing to
45
+ * clear. `undefined` when nothing would be stored, so a caller spreads
46
+ * `{ custom }` only when there is one.
47
+ */ export function crmCustomDraftDocument(draft) {
48
+ const stored = Object.fromEntries(Object.entries(draft).filter(([, value])=>value !== null && value !== undefined));
49
+ return Object.keys(stored).length ? stored : undefined;
50
+ }
51
+ /**
52
+ * The required definitions the draft leaves empty — which Save refuses.
53
+ *
54
+ * On an EDIT only a key the reader cleared counts: a required field a
55
+ * record has always lacked is not this save's to demand, or a rename
56
+ * could be refused for a field added last week. On a CREATE every
57
+ * required field counts, because the record is being made whole.
58
+ */ export function crmCustomDraftMissingRequired(definitions, stored, draft, mode) {
59
+ return definitions.filter((definition)=>{
60
+ if (!definition.required) return false;
61
+ const value = crmCustomDraftValue(stored, draft, definition.key);
62
+ const empty = value === null || value === undefined || value === '';
63
+ return mode === 'create' ? empty : definition.key in draft && empty;
64
+ }).map((definition)=>definition.label || definition.key);
65
+ }
66
+
67
+ //# sourceMappingURL=crm-custom-draft.js.map