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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (541) hide show
  1. package/README.md +2 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/activity-list.js +12 -5
  4. package/src/lib/components/activity-list.js.map +1 -1
  5. package/src/lib/components/companies-bulk-bar.d.ts +1 -4
  6. package/src/lib/components/companies-bulk-bar.js +7 -20
  7. package/src/lib/components/companies-bulk-bar.js.map +1 -1
  8. package/src/lib/components/companies-section.d.ts +3 -3
  9. package/src/lib/components/companies-section.js +149 -46
  10. package/src/lib/components/companies-section.js.map +1 -1
  11. package/src/lib/components/company-edit-drawer.js +281 -20
  12. package/src/lib/components/company-edit-drawer.js.map +1 -1
  13. package/src/lib/components/company-properties-card.js +99 -8
  14. package/src/lib/components/company-properties-card.js.map +1 -1
  15. package/src/lib/components/contact-detail-page.js +3 -1
  16. package/src/lib/components/contact-detail-page.js.map +1 -1
  17. package/src/lib/components/contact-merge-dialog.js +33 -10
  18. package/src/lib/components/contact-merge-dialog.js.map +1 -1
  19. package/src/lib/components/contact-properties-card.d.ts +0 -69
  20. package/src/lib/components/contact-properties-card.js +350 -60
  21. package/src/lib/components/contact-properties-card.js.map +1 -1
  22. package/src/lib/components/contact-reports-to-field.d.ts +46 -0
  23. package/src/lib/components/contact-reports-to-field.js +67 -0
  24. package/src/lib/components/contact-reports-to-field.js.map +1 -0
  25. package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
  26. package/src/lib/components/contacts-bulk-bar.js +7 -19
  27. package/src/lib/components/contacts-bulk-bar.js.map +1 -1
  28. package/src/lib/components/contacts-section.js +46 -33
  29. package/src/lib/components/contacts-section.js.map +1 -1
  30. package/src/lib/components/crm-call-actions.d.ts +10 -0
  31. package/src/lib/components/crm-call-actions.js +26 -9
  32. package/src/lib/components/crm-call-actions.js.map +1 -1
  33. package/src/lib/components/crm-next-activity-column.js +1 -1
  34. package/src/lib/components/crm-next-activity-column.js.map +1 -1
  35. package/src/lib/components/crm-record-picker.d.ts +15 -0
  36. package/src/lib/components/crm-record-picker.js +16 -10
  37. package/src/lib/components/crm-record-picker.js.map +1 -1
  38. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  39. package/src/lib/components/crm-transfer-buttons.js +167 -0
  40. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  41. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  42. package/src/lib/components/deal-contact-roles-card.js +368 -0
  43. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  44. package/src/lib/components/deal-detail-page.d.ts +3 -2
  45. package/src/lib/components/deal-detail-page.js +25 -6
  46. package/src/lib/components/deal-detail-page.js.map +1 -1
  47. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  48. package/src/lib/components/deal-edit-drawer.js +219 -10
  49. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  50. package/src/lib/components/deal-properties-card.d.ts +7 -0
  51. package/src/lib/components/deal-properties-card.js +34 -3
  52. package/src/lib/components/deal-properties-card.js.map +1 -1
  53. package/src/lib/components/deal-stage-card.d.ts +4 -0
  54. package/src/lib/components/deal-stage-card.js +10 -2
  55. package/src/lib/components/deal-stage-card.js.map +1 -1
  56. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  57. package/src/lib/components/deals-bulk-bar.js +7 -20
  58. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  59. package/src/lib/components/deals-section.d.ts +3 -3
  60. package/src/lib/components/deals-section.js +123 -63
  61. package/src/lib/components/deals-section.js.map +1 -1
  62. package/src/lib/components/fields-section.js +31 -17
  63. package/src/lib/components/fields-section.js.map +1 -1
  64. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  65. package/src/lib/components/lead-convert-dialog.js +23 -1
  66. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  67. package/src/lib/components/lead-detail-page.js +8 -2
  68. package/src/lib/components/lead-detail-page.js.map +1 -1
  69. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  70. package/src/lib/components/lead-profile-fields.js +386 -0
  71. package/src/lib/components/lead-profile-fields.js.map +1 -0
  72. package/src/lib/components/lead-properties-card.d.ts +2 -1
  73. package/src/lib/components/lead-properties-card.js +85 -176
  74. package/src/lib/components/lead-properties-card.js.map +1 -1
  75. package/src/lib/components/lead-source-select.d.ts +4 -23
  76. package/src/lib/components/lead-source-select.js +9 -73
  77. package/src/lib/components/lead-source-select.js.map +1 -1
  78. package/src/lib/components/lead-status-chip.d.ts +9 -3
  79. package/src/lib/components/lead-status-chip.js +8 -4
  80. package/src/lib/components/lead-status-chip.js.map +1 -1
  81. package/src/lib/components/lead-status-options.d.ts +20 -0
  82. package/src/lib/components/lead-status-options.js +51 -0
  83. package/src/lib/components/lead-status-options.js.map +1 -0
  84. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  85. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  86. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  87. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  88. package/src/lib/components/leads-bulk-bar.js +29 -29
  89. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  90. package/src/lib/components/leads-section.js +120 -68
  91. package/src/lib/components/leads-section.js.map +1 -1
  92. package/src/lib/components/linked-deals-card.d.ts +4 -0
  93. package/src/lib/components/linked-deals-card.js +47 -3
  94. package/src/lib/components/linked-deals-card.js.map +1 -1
  95. package/src/lib/components/log-activity-dialog.js +43 -3
  96. package/src/lib/components/log-activity-dialog.js.map +1 -1
  97. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  98. package/src/lib/components/new-contact-drawer.js +108 -6
  99. package/src/lib/components/new-contact-drawer.js.map +1 -1
  100. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  101. package/src/lib/components/new-lead-drawer.js +88 -121
  102. package/src/lib/components/new-lead-drawer.js.map +1 -1
  103. package/src/lib/components/picklist-select.d.ts +36 -0
  104. package/src/lib/components/picklist-select.js +114 -0
  105. package/src/lib/components/picklist-select.js.map +1 -0
  106. package/src/lib/components/picklist-values-card.d.ts +34 -0
  107. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  108. package/src/lib/components/picklist-values-card.js.map +1 -0
  109. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  110. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  111. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  112. package/src/lib/components/pipelines-dialog.js +15 -6
  113. package/src/lib/components/pipelines-dialog.js.map +1 -1
  114. package/src/lib/components/recent-activity-feed.js +20 -5
  115. package/src/lib/components/recent-activity-feed.js.map +1 -1
  116. package/src/lib/components/recipes-card.js +4 -2
  117. package/src/lib/components/recipes-card.js.map +1 -1
  118. package/src/lib/components/record-tasks-card.js +15 -8
  119. package/src/lib/components/record-tasks-card.js.map +1 -1
  120. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  121. package/src/lib/components/reports/forecast-card.js +101 -3
  122. package/src/lib/components/reports/forecast-card.js.map +1 -1
  123. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  124. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  125. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  126. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  127. package/src/lib/components/reports/lead-source-card.js +318 -0
  128. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  129. package/src/lib/components/reports/pipeline-card.js +2 -1
  130. package/src/lib/components/reports/pipeline-card.js.map +1 -1
  131. package/src/lib/components/reports/report-export.js +1 -1
  132. package/src/lib/components/reports/report-export.js.map +1 -1
  133. package/src/lib/components/reports-section.js +8 -0
  134. package/src/lib/components/reports-section.js.map +1 -1
  135. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  136. package/src/lib/components/sharing-rule-drawer.js +108 -19
  137. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  138. package/src/lib/components/sharing-rules-card.js +11 -3
  139. package/src/lib/components/sharing-rules-card.js.map +1 -1
  140. package/src/lib/components/task-cells.d.ts +9 -1
  141. package/src/lib/components/task-cells.js +9 -4
  142. package/src/lib/components/task-cells.js.map +1 -1
  143. package/src/lib/components/task-edit-drawer.js +111 -43
  144. package/src/lib/components/task-edit-drawer.js.map +1 -1
  145. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  146. package/src/lib/components/tasks-bulk-bar.js +7 -20
  147. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  148. package/src/lib/components/tasks-calendar.d.ts +3 -0
  149. package/src/lib/components/tasks-calendar.js +8 -1
  150. package/src/lib/components/tasks-calendar.js.map +1 -1
  151. package/src/lib/components/tasks-section.d.ts +3 -3
  152. package/src/lib/components/tasks-section.js +58 -43
  153. package/src/lib/components/tasks-section.js.map +1 -1
  154. package/src/lib/constants/api-routes.d.ts +2 -9
  155. package/src/lib/constants/api-routes.js +1 -7
  156. package/src/lib/constants/api-routes.js.map +1 -1
  157. package/src/lib/constants/bundle-common.d.ts +6 -0
  158. package/src/lib/constants/bundle-common.js +11 -0
  159. package/src/lib/constants/bundle-common.js.map +1 -1
  160. package/src/lib/constants/company-filters.d.ts +14 -0
  161. package/src/lib/constants/company-filters.js +51 -1
  162. package/src/lib/constants/company-filters.js.map +1 -1
  163. package/src/lib/constants/contact-filters.d.ts +2 -0
  164. package/src/lib/constants/contact-filters.js +18 -1
  165. package/src/lib/constants/contact-filters.js.map +1 -1
  166. package/src/lib/constants/deal-filters.d.ts +22 -1
  167. package/src/lib/constants/deal-filters.js +67 -4
  168. package/src/lib/constants/deal-filters.js.map +1 -1
  169. package/src/lib/declarations.console-server.d.ts +3 -0
  170. package/src/lib/declarations.console-server.js +35 -0
  171. package/src/lib/declarations.console-server.js.map +1 -1
  172. package/src/lib/declarations.d.ts +26 -0
  173. package/src/lib/declarations.js +35 -0
  174. package/src/lib/declarations.js.map +1 -0
  175. package/src/lib/declarations.server.d.ts +11 -0
  176. package/src/lib/declarations.server.js +97 -1
  177. package/src/lib/declarations.server.js.map +1 -1
  178. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  179. package/src/lib/hooks/use-company-picklists.js +55 -0
  180. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  181. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  182. package/src/lib/hooks/use-crm-picklist.js +53 -0
  183. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  184. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  185. package/src/lib/hooks/use-crm-record-names.js +45 -19
  186. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  187. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  188. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  189. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  190. package/src/lib/hooks/use-deals.d.ts +14 -0
  191. package/src/lib/hooks/use-deals.js +29 -0
  192. package/src/lib/hooks/use-deals.js.map +1 -1
  193. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  194. package/src/lib/hooks/use-lead-picklists.js +46 -0
  195. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  196. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  197. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  198. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  199. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  200. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  201. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  202. package/src/lib/model/companies.d.ts +32 -3
  203. package/src/lib/model/companies.js +133 -16
  204. package/src/lib/model/companies.js.map +1 -1
  205. package/src/lib/model/contact-merge.d.ts +27 -3
  206. package/src/lib/model/contact-merge.js +81 -7
  207. package/src/lib/model/contact-merge.js.map +1 -1
  208. package/src/lib/model/contact-record.d.ts +17 -0
  209. package/src/lib/model/contact-record.js +17 -2
  210. package/src/lib/model/contact-record.js.map +1 -1
  211. package/src/lib/model/contact-update.d.ts +31 -2
  212. package/src/lib/model/contact-update.js +14 -0
  213. package/src/lib/model/contact-update.js.map +1 -1
  214. package/src/lib/model/crm-list-query.d.ts +5 -0
  215. package/src/lib/model/crm-list-query.js +8 -0
  216. package/src/lib/model/crm-list-query.js.map +1 -1
  217. package/src/lib/model/crm-next-activity.d.ts +107 -0
  218. package/src/lib/model/crm-next-activity.js +140 -0
  219. package/src/lib/model/crm-next-activity.js.map +1 -0
  220. package/src/lib/model/crm-recipes.d.ts +40 -0
  221. package/src/lib/model/crm-recipes.js +259 -0
  222. package/src/lib/model/crm-recipes.js.map +1 -0
  223. package/src/lib/model/crm-record-counts.d.ts +36 -0
  224. package/src/lib/model/crm-record-counts.js +54 -0
  225. package/src/lib/model/crm-record-counts.js.map +1 -0
  226. package/src/lib/model/crm-record-lists.d.ts +23 -0
  227. package/src/lib/model/crm-record-lists.js +161 -0
  228. package/src/lib/model/crm-record-lists.js.map +1 -0
  229. package/src/lib/model/crm-reports.d.ts +73 -3
  230. package/src/lib/model/crm-reports.js +120 -1
  231. package/src/lib/model/crm-reports.js.map +1 -1
  232. package/src/lib/model/crm-sharing.d.ts +21 -3
  233. package/src/lib/model/crm-sharing.js +27 -6
  234. package/src/lib/model/crm-sharing.js.map +1 -1
  235. package/src/lib/model/crm-task-reminders.d.ts +152 -0
  236. package/src/lib/model/crm-task-reminders.js +161 -0
  237. package/src/lib/model/crm-task-reminders.js.map +1 -0
  238. package/src/lib/model/deal-board-model.d.ts +8 -2
  239. package/src/lib/model/deal-board-model.js +15 -2
  240. package/src/lib/model/deal-board-model.js.map +1 -1
  241. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  242. package/src/lib/model/deal-contact-roles.js +73 -0
  243. package/src/lib/model/deal-contact-roles.js.map +1 -0
  244. package/src/lib/model/deal-form-model.d.ts +56 -0
  245. package/src/lib/model/deal-form-model.js +79 -7
  246. package/src/lib/model/deal-form-model.js.map +1 -1
  247. package/src/lib/model/download-text-file.d.ts +23 -0
  248. package/src/lib/model/download-text-file.js +34 -0
  249. package/src/lib/model/download-text-file.js.map +1 -0
  250. package/src/lib/model/lead-filters.d.ts +36 -2
  251. package/src/lib/model/lead-filters.js +123 -2
  252. package/src/lib/model/lead-filters.js.map +1 -1
  253. package/src/lib/model/lead-source-direction.d.ts +38 -0
  254. package/src/lib/model/lead-source-direction.js +52 -0
  255. package/src/lib/model/lead-source-direction.js.map +1 -0
  256. package/src/lib/model/next-activity.d.ts +1 -1
  257. package/src/lib/model/next-activity.js.map +1 -1
  258. package/src/lib/model/picklist-values.d.ts +119 -0
  259. package/src/lib/model/picklist-values.js +256 -0
  260. package/src/lib/model/picklist-values.js.map +1 -0
  261. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  262. package/src/lib/model/record-facts-disclosed.js +281 -0
  263. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  264. package/src/lib/model/record-facts.d.ts +215 -34
  265. package/src/lib/model/record-facts.js +307 -128
  266. package/src/lib/model/record-facts.js.map +1 -1
  267. package/src/lib/model/task-picklists.d.ts +52 -0
  268. package/src/lib/model/task-picklists.js +83 -0
  269. package/src/lib/model/task-picklists.js.map +1 -0
  270. package/src/lib/model/task-routes.d.ts +13 -0
  271. package/src/lib/model/task-routes.js +23 -4
  272. package/src/lib/model/task-routes.js.map +1 -1
  273. package/src/lib/plan-entitlements.js +6 -4
  274. package/src/lib/plan-entitlements.js.map +1 -1
  275. package/src/lib/plugin.js +17 -0
  276. package/src/lib/plugin.js.map +1 -1
  277. package/src/lib/server/api-v1/contacts.js +220 -14
  278. package/src/lib/server/api-v1/contacts.js.map +1 -1
  279. package/src/lib/server/api-v1/crm-activities.js +14 -1
  280. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  281. package/src/lib/server/api-v1/crm-companies.js +123 -14
  282. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  283. package/src/lib/server/api-v1/crm-deals.js +291 -26
  284. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  285. package/src/lib/server/api-v1/crm-leads.js +144 -38
  286. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  287. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  288. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  289. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  290. package/src/lib/server/api-v1/crm-tasks.js +78 -34
  291. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  292. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  293. package/src/lib/server/api-v1/openapi.js +171 -16
  294. package/src/lib/server/api-v1/openapi.js.map +1 -1
  295. package/src/lib/server/assign-contact-owner.d.ts +188 -0
  296. package/src/lib/server/assign-contact-owner.js +446 -0
  297. package/src/lib/server/assign-contact-owner.js.map +1 -0
  298. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  299. package/src/lib/server/associate-company-by-domain.js +153 -0
  300. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  301. package/src/lib/server/automation-steps.d.ts +140 -0
  302. package/src/lib/server/automation-steps.js +669 -0
  303. package/src/lib/server/automation-steps.js.map +1 -0
  304. package/src/lib/server/capture-contact.d.ts +17 -0
  305. package/src/lib/server/capture-contact.js +95 -26
  306. package/src/lib/server/capture-contact.js.map +1 -1
  307. package/src/lib/server/capture-host-contact.d.ts +104 -0
  308. package/src/lib/server/capture-host-contact.js +151 -0
  309. package/src/lib/server/capture-host-contact.js.map +1 -0
  310. package/src/lib/server/company-children.d.ts +25 -0
  311. package/src/lib/server/company-children.js +42 -0
  312. package/src/lib/server/company-children.js.map +1 -0
  313. package/src/lib/server/company-delete.d.ts +18 -0
  314. package/src/lib/server/company-delete.js +44 -21
  315. package/src/lib/server/company-delete.js.map +1 -1
  316. package/src/lib/server/contact-email-history.js +21 -19
  317. package/src/lib/server/contact-email-history.js.map +1 -1
  318. package/src/lib/server/contact-remove.js +27 -2
  319. package/src/lib/server/contact-remove.js.map +1 -1
  320. package/src/lib/server/contact-reports-to.d.ts +61 -0
  321. package/src/lib/server/contact-reports-to.js +114 -0
  322. package/src/lib/server/contact-reports-to.js.map +1 -0
  323. package/src/lib/server/contact-update.d.ts +42 -1
  324. package/src/lib/server/contact-update.js +204 -23
  325. package/src/lib/server/contact-update.js.map +1 -1
  326. package/src/lib/server/convert-host-lead.d.ts +46 -1
  327. package/src/lib/server/convert-host-lead.js +173 -15
  328. package/src/lib/server/convert-host-lead.js.map +1 -1
  329. package/src/lib/server/convert-open-lead.js +12 -5
  330. package/src/lib/server/convert-open-lead.js.map +1 -1
  331. package/src/lib/server/crm-email-activity.d.ts +118 -0
  332. package/src/lib/server/crm-email-activity.js +148 -0
  333. package/src/lib/server/crm-email-activity.js.map +1 -0
  334. package/src/lib/server/crm-inbound-email.js +1 -1
  335. package/src/lib/server/crm-inbound-email.js.map +1 -1
  336. package/src/lib/server/crm-next-activity.d.ts +74 -0
  337. package/src/lib/server/crm-next-activity.js +194 -0
  338. package/src/lib/server/crm-next-activity.js.map +1 -0
  339. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  340. package/src/lib/server/crm-record-indexes.js +78 -0
  341. package/src/lib/server/crm-record-indexes.js.map +1 -0
  342. package/src/lib/server/crm-sharing.d.ts +9 -1
  343. package/src/lib/server/crm-sharing.js +23 -3
  344. package/src/lib/server/crm-sharing.js.map +1 -1
  345. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  346. package/src/lib/server/deal-contact-roles.js +89 -0
  347. package/src/lib/server/deal-contact-roles.js.map +1 -0
  348. package/src/lib/server/email-send.js +2 -1
  349. package/src/lib/server/email-send.js.map +1 -1
  350. package/src/lib/server/lead-convert.d.ts +5 -0
  351. package/src/lib/server/lead-convert.js +19 -3
  352. package/src/lib/server/lead-convert.js.map +1 -1
  353. package/src/lib/server/lead-create.d.ts +17 -2
  354. package/src/lib/server/lead-create.js +46 -14
  355. package/src/lib/server/lead-create.js.map +1 -1
  356. package/src/lib/server/lead-nurturing.d.ts +6 -0
  357. package/src/lib/server/lead-nurturing.js +57 -20
  358. package/src/lib/server/lead-nurturing.js.map +1 -1
  359. package/src/lib/server/lead-picklists.d.ts +35 -0
  360. package/src/lib/server/lead-picklists.js +52 -0
  361. package/src/lib/server/lead-picklists.js.map +1 -0
  362. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  363. package/src/lib/server/lead-source-picklist.js +6 -33
  364. package/src/lib/server/lead-source-picklist.js.map +1 -1
  365. package/src/lib/server/merge-contacts.js +23 -5
  366. package/src/lib/server/merge-contacts.js.map +1 -1
  367. package/src/lib/server/next-activity-routes.js +2 -1
  368. package/src/lib/server/next-activity-routes.js.map +1 -1
  369. package/src/lib/server/person-eraser.d.ts +53 -0
  370. package/src/lib/server/person-eraser.js +149 -0
  371. package/src/lib/server/person-eraser.js.map +1 -0
  372. package/src/lib/server/person-records.d.ts +69 -0
  373. package/src/lib/server/person-records.js +317 -0
  374. package/src/lib/server/person-records.js.map +1 -0
  375. package/src/lib/server/person-refund.d.ts +97 -0
  376. package/src/lib/server/person-refund.js +221 -0
  377. package/src/lib/server/person-refund.js.map +1 -0
  378. package/src/lib/server/picklist-values.d.ts +21 -0
  379. package/src/lib/server/picklist-values.js +308 -0
  380. package/src/lib/server/picklist-values.js.map +1 -0
  381. package/src/lib/server/read-picklist.d.ts +44 -0
  382. package/src/lib/server/read-picklist.js +65 -0
  383. package/src/lib/server/read-picklist.js.map +1 -0
  384. package/src/lib/server/recipe-routes.js +22 -8
  385. package/src/lib/server/recipe-routes.js.map +1 -1
  386. package/src/lib/server/record-email-state.js +7 -1
  387. package/src/lib/server/record-email-state.js.map +1 -1
  388. package/src/lib/server/record-facts.d.ts +3 -0
  389. package/src/lib/server/record-facts.js +233 -31
  390. package/src/lib/server/record-facts.js.map +1 -1
  391. package/src/lib/server/record-origin.d.ts +27 -0
  392. package/src/lib/server/record-origin.js +104 -0
  393. package/src/lib/server/record-origin.js.map +1 -0
  394. package/src/lib/server/record-timeline.js +40 -3
  395. package/src/lib/server/record-timeline.js.map +1 -1
  396. package/src/lib/server/suite-gate.js +4 -3
  397. package/src/lib/server/suite-gate.js.map +1 -1
  398. package/src/lib/server/task-reminders-route.js +2 -1
  399. package/src/lib/server/task-reminders-route.js.map +1 -1
  400. package/src/lib/server/task-routes.js +33 -17
  401. package/src/lib/server/task-routes.js.map +1 -1
  402. package/src/lib/server-deal-stage.d.ts +5 -1
  403. package/src/lib/server-deal-stage.js +10 -5
  404. package/src/lib/server-deal-stage.js.map +1 -1
  405. package/src/lib/server.d.ts +8 -3
  406. package/src/lib/server.js +47 -43
  407. package/src/lib/server.js.map +1 -1
  408. package/src/lib/testing/memory-firestore.d.ts +55 -0
  409. package/src/lib/testing/memory-firestore.js +335 -0
  410. package/src/lib/testing/memory-firestore.js.map +1 -0
  411. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  412. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  413. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  414. package/src/lib/transfer/activities.d.ts +30 -0
  415. package/src/lib/transfer/activities.js +132 -0
  416. package/src/lib/transfer/activities.js.map +1 -0
  417. package/src/lib/transfer/aliases.d.ts +22 -0
  418. package/src/lib/transfer/aliases.js +1342 -0
  419. package/src/lib/transfer/aliases.js.map +1 -0
  420. package/src/lib/transfer/common.d.ts +222 -0
  421. package/src/lib/transfer/common.js +832 -0
  422. package/src/lib/transfer/common.js.map +1 -0
  423. package/src/lib/transfer/companies.d.ts +43 -0
  424. package/src/lib/transfer/companies.js +549 -0
  425. package/src/lib/transfer/companies.js.map +1 -0
  426. package/src/lib/transfer/contacts.d.ts +31 -0
  427. package/src/lib/transfer/contacts.js +727 -0
  428. package/src/lib/transfer/contacts.js.map +1 -0
  429. package/src/lib/transfer/deals.d.ts +66 -0
  430. package/src/lib/transfer/deals.js +698 -0
  431. package/src/lib/transfer/deals.js.map +1 -0
  432. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  433. package/src/lib/transfer/email-templates-package.js +76 -0
  434. package/src/lib/transfer/email-templates-package.js.map +1 -0
  435. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  436. package/src/lib/transfer/email-templates-package.server.js +176 -0
  437. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  438. package/src/lib/transfer/fields.d.ts +102 -0
  439. package/src/lib/transfer/fields.js +1755 -0
  440. package/src/lib/transfer/fields.js.map +1 -0
  441. package/src/lib/transfer/leads.d.ts +30 -0
  442. package/src/lib/transfer/leads.js +582 -0
  443. package/src/lib/transfer/leads.js.map +1 -0
  444. package/src/lib/transfer/pipelines.d.ts +21 -0
  445. package/src/lib/transfer/pipelines.js +172 -0
  446. package/src/lib/transfer/pipelines.js.map +1 -0
  447. package/src/lib/transfer/register.d.ts +47 -0
  448. package/src/lib/transfer/register.js +277 -0
  449. package/src/lib/transfer/register.js.map +1 -0
  450. package/src/lib/transfer/tasks.d.ts +30 -0
  451. package/src/lib/transfer/tasks.js +418 -0
  452. package/src/lib/transfer/tasks.js.map +1 -0
  453. package/src/lib/transfer/ui.d.ts +20 -0
  454. package/src/lib/transfer/ui.js +42 -0
  455. package/src/lib/transfer/ui.js.map +1 -0
  456. package/src/lib/components/company-import-drawer.d.ts +0 -42
  457. package/src/lib/components/company-import-drawer.js +0 -99
  458. package/src/lib/components/company-import-drawer.js.map +0 -1
  459. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  460. package/src/lib/components/contact-import-drawer.js +0 -149
  461. package/src/lib/components/contact-import-drawer.js.map +0 -1
  462. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  463. package/src/lib/components/crm-export-all-button.js +0 -98
  464. package/src/lib/components/crm-export-all-button.js.map +0 -1
  465. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  466. package/src/lib/components/csv-import-drawer.js +0 -757
  467. package/src/lib/components/csv-import-drawer.js.map +0 -1
  468. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  469. package/src/lib/components/deal-import-drawer.js +0 -83
  470. package/src/lib/components/deal-import-drawer.js.map +0 -1
  471. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  472. package/src/lib/components/lead-import-drawer.js +0 -118
  473. package/src/lib/components/lead-import-drawer.js.map +0 -1
  474. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  475. package/src/lib/components/lead-source-values-card.js.map +0 -1
  476. package/src/lib/components/task-import-drawer.d.ts +0 -24
  477. package/src/lib/components/task-import-drawer.js +0 -82
  478. package/src/lib/components/task-import-drawer.js.map +0 -1
  479. package/src/lib/model/companies-csv.d.ts +0 -36
  480. package/src/lib/model/companies-csv.js +0 -38
  481. package/src/lib/model/companies-csv.js.map +0 -1
  482. package/src/lib/model/contacts-csv.d.ts +0 -54
  483. package/src/lib/model/contacts-csv.js +0 -67
  484. package/src/lib/model/contacts-csv.js.map +0 -1
  485. package/src/lib/model/crm-company-import.d.ts +0 -154
  486. package/src/lib/model/crm-company-import.js +0 -331
  487. package/src/lib/model/crm-company-import.js.map +0 -1
  488. package/src/lib/model/crm-csv.d.ts +0 -239
  489. package/src/lib/model/crm-csv.js +0 -467
  490. package/src/lib/model/crm-csv.js.map +0 -1
  491. package/src/lib/model/crm-deal-import.d.ts +0 -112
  492. package/src/lib/model/crm-deal-import.js +0 -263
  493. package/src/lib/model/crm-deal-import.js.map +0 -1
  494. package/src/lib/model/crm-import.d.ts +0 -250
  495. package/src/lib/model/crm-import.js +0 -467
  496. package/src/lib/model/crm-import.js.map +0 -1
  497. package/src/lib/model/crm-lead-import.d.ts +0 -138
  498. package/src/lib/model/crm-lead-import.js +0 -446
  499. package/src/lib/model/crm-lead-import.js.map +0 -1
  500. package/src/lib/model/crm-task-import.d.ts +0 -94
  501. package/src/lib/model/crm-task-import.js +0 -275
  502. package/src/lib/model/crm-task-import.js.map +0 -1
  503. package/src/lib/model/deals-csv.d.ts +0 -32
  504. package/src/lib/model/deals-csv.js +0 -36
  505. package/src/lib/model/deals-csv.js.map +0 -1
  506. package/src/lib/model/import-column-shapes.d.ts +0 -36
  507. package/src/lib/model/import-column-shapes.js +0 -76
  508. package/src/lib/model/import-column-shapes.js.map +0 -1
  509. package/src/lib/model/lead-source-values.d.ts +0 -82
  510. package/src/lib/model/lead-source-values.js +0 -149
  511. package/src/lib/model/lead-source-values.js.map +0 -1
  512. package/src/lib/model/leads-csv.d.ts +0 -40
  513. package/src/lib/model/leads-csv.js +0 -40
  514. package/src/lib/model/leads-csv.js.map +0 -1
  515. package/src/lib/model/tasks-csv.d.ts +0 -28
  516. package/src/lib/model/tasks-csv.js +0 -28
  517. package/src/lib/model/tasks-csv.js.map +0 -1
  518. package/src/lib/server/companies-import.d.ts +0 -57
  519. package/src/lib/server/companies-import.js +0 -242
  520. package/src/lib/server/companies-import.js.map +0 -1
  521. package/src/lib/server/contacts-import.d.ts +0 -109
  522. package/src/lib/server/contacts-import.js +0 -393
  523. package/src/lib/server/contacts-import.js.map +0 -1
  524. package/src/lib/server/deals-import.d.ts +0 -76
  525. package/src/lib/server/deals-import.js +0 -248
  526. package/src/lib/server/deals-import.js.map +0 -1
  527. package/src/lib/server/export-route.d.ts +0 -60
  528. package/src/lib/server/export-route.js +0 -447
  529. package/src/lib/server/export-route.js.map +0 -1
  530. package/src/lib/server/import-context.d.ts +0 -87
  531. package/src/lib/server/import-context.js +0 -182
  532. package/src/lib/server/import-context.js.map +0 -1
  533. package/src/lib/server/lead-source-values.d.ts +0 -50
  534. package/src/lib/server/lead-source-values.js +0 -191
  535. package/src/lib/server/lead-source-values.js.map +0 -1
  536. package/src/lib/server/leads-import.d.ts +0 -84
  537. package/src/lib/server/leads-import.js +0 -367
  538. package/src/lib/server/leads-import.js.map +0 -1
  539. package/src/lib/server/tasks-import.d.ts +0 -54
  540. package/src/lib/server/tasks-import.js +0 -160
  541. package/src/lib/server/tasks-import.js.map +0 -1
@@ -1,138 +0,0 @@
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 CrmLeadProfile, type CrmLeadStatus, type CrmPicklist } from '@aglyn/aglyn/app-utils/crm';
18
- import { type ImportChunkResult, type ImportDroppedValue } from '@aglyn/aglyn/app-utils/csv-import';
19
- /** The shared ceilings, under this collection's names. */
20
- export declare const LEAD_IMPORT_MAX_ROWS = 5000;
21
- export declare const LEAD_IMPORT_CHUNK_SIZE = 200;
22
- export declare const LEAD_IMPORT_MAX_BODY_BYTES = 2000000;
23
- export declare const LEAD_IMPORT_PREVIEW_ROWS = 10;
24
- /** The same caps the lead's own cards hold a typed value to. */
25
- export declare const LEAD_IMPORT_NOTES_MAX = 4000;
26
- export declare const LEAD_IMPORT_REASON_MAX = 500;
27
- /**
28
- * The statuses a file may set.
29
- *
30
- * The list's own status control offers exactly these four, and for the
31
- * reason given above: `qualified` is written by the conversion, beside the
32
- * contact it produced.
33
- */
34
- export declare const LEAD_IMPORT_STATUSES: readonly CrmLeadStatus[];
35
- /**
36
- * The fields a column may be mapped to, in the order the mapping menu
37
- * lists them.
38
- *
39
- * The lead's own profile (AGL-3231) — company, title, phone, website, the
40
- * lead source, the address parts and tags — is what a list from another
41
- * tool actually carries, and the reason a lead can be worked without a
42
- * contact beside it. They read under the same labels the contacts import
43
- * uses, so one spreadsheet maps the same way into either.
44
- */
45
- export declare const LEAD_IMPORT_FIELDS: readonly ["email", "name", "company", "jobTitle", "phone", "website", "leadSource", "status", "ownerEmail", "addressLine1", "addressLine2", "addressCity", "addressState", "addressPostalCode", "addressCountry", "tags", "campaigns", "unqualifiedReason", "notes"];
46
- export type LeadImportField = (typeof LEAD_IMPORT_FIELDS)[number];
47
- /** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */
48
- export declare const LEAD_IMPORT_FIELD_LABELS: Record<LeadImportField, string>;
49
- /** Column index → field. A column absent from the map is not imported. */
50
- export type LeadImportMapping = Record<number, LeadImportField>;
51
- /** A proposed mapping from a file's header row, each field taken at most once. */
52
- export declare function guessLeadImportMapping(columns: readonly string[]): LeadImportMapping;
53
- /**
54
- * What the browser posts for one line: the cells the mapping selected,
55
- * under the field they were mapped to, verbatim. `unknown` because the
56
- * server reads this off an untrusted body.
57
- */
58
- export type LeadImportRawRow = Partial<Record<LeadImportField, unknown>>;
59
- /** One parsed line under the mapping. Empty cells are left absent; a lead has no custom fields. */
60
- export declare function mapLeadImportRow(cells: readonly string[], mapping: Record<number, LeadImportField | `custom:${string}`>): LeadImportRawRow;
61
- export type LeadImportSkipReason = 'invalid-email' | 'duplicate' | 'lead-ceiling' | 'campaign-unknown' | 'lead-source-unknown' | 'write-failed';
62
- /** How a skip reason reads on screen and in the downloaded file. */
63
- export declare const LEAD_IMPORT_SKIP_LABELS: Record<LeadImportSkipReason, string>;
64
- /** The most campaigns one row may name — the membership field's own cap. */
65
- export declare const LEAD_IMPORT_CAMPAIGNS_MAX = 20;
66
- /** One row, ready for the server to resolve and write. */
67
- export interface LeadImportRow {
68
- /** Normalized — the address `personKey` derives the document id from. */
69
- email: string;
70
- name?: string;
71
- /**
72
- * The lead's own profile, already normalized the way the record stores
73
- * it (AGL-3231): a key present is a value to write, a key absent leaves
74
- * an existing lead's value alone. Never a clear — a blank cell in a file
75
- * is a cell nobody filled, not a decision to erase what the site knows.
76
- */
77
- profile: CrmLeadProfile;
78
- /**
79
- * The campaigns the row files the lead under (AGL-3254), by NAME as the
80
- * file wrote them: the server resolves each against the site's own
81
- * containers and refuses the row whole when one is not there, because a
82
- * row filed under half its campaigns is a row nobody asked for.
83
- */
84
- campaigns?: string[];
85
- /** Absent leaves an existing lead's status alone and a new one reading as `new`. */
86
- status?: CrmLeadStatus;
87
- /** Normalized, for the server to resolve against the org's members. */
88
- ownerEmail?: string;
89
- /** Only ever set beside `status: 'unqualified'` — the pair is one fact. */
90
- unqualifiedReason?: string;
91
- notes?: string;
92
- dropped: ImportDroppedValue[];
93
- }
94
- export type LeadImportRowVerdict = {
95
- ok: true;
96
- row: LeadImportRow;
97
- } | {
98
- ok: false;
99
- reason: 'invalid-email';
100
- input: string;
101
- };
102
- /**
103
- * A status cell by id or by label — `working`, `Working` and `WORKING` are
104
- * one status. `null` for a cell naming no status a file may set, which
105
- * includes the well-spelled `Qualified` the export writes for a converted
106
- * lead.
107
- */
108
- export declare function parseImportLeadStatus(value: unknown): CrmLeadStatus | null;
109
- /**
110
- * One raw row as the values that will be written, or the reason it cannot
111
- * be. Refused here only for an unusable address, because the address is
112
- * the document id; the owner is refused by the server, which alone can
113
- * look them up.
114
- */
115
- export declare function normalizeLeadImportRow(raw: LeadImportRawRow): LeadImportRowVerdict;
116
- /** One row the server did not store, by its index in the request, named by the address. */
117
- export interface LeadImportSkippedRow {
118
- index: number;
119
- email: string;
120
- reason: LeadImportSkipReason;
121
- }
122
- /** What one request did. The drawer sums these across a file. */
123
- export type LeadImportChunkResult = ImportChunkResult<LeadImportSkippedRow>;
124
- export declare function emptyLeadImportResult(): LeadImportChunkResult;
125
- export declare function mergeLeadImportResults(total: LeadImportChunkResult, chunk: LeadImportChunkResult, offset?: number): LeadImportChunkResult;
126
- /** The skipped rows as a file the operator can fix and re-import. */
127
- export declare function leadImportSkippedCsv(columns: readonly string[], entries: readonly {
128
- cells: readonly string[];
129
- reason: LeadImportSkipReason;
130
- }[]): string;
131
- /**
132
- * The lead sources a file names that the org's list would refuse
133
- * (AGL-3298), each once, as the file spelled it — the drawer's warning
134
- * before anything is sent. Judged the way the server judges a NEW lead,
135
- * so a value the list holds but has deactivated is named too; a row
136
- * merging onto a lead that already holds that value would still pass.
137
- */
138
- export declare function leadImportUnknownLeadSources(rows: readonly LeadImportRawRow[], picklist: CrmPicklist): string[];
@@ -1,446 +0,0 @@
1
- import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
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
- * BRINGING A SPREADSHEET OF LEADS INTO THE CRM — the pure half (AGL-2701).
19
- *
20
- * The contact import's three stages (`crm-import.ts`) over the lead
21
- * vocabulary. A lead is the one CRM record a person does not type: it is
22
- * what a capture door wrote when somebody signed up, booked or submitted a
23
- * form, plus the working state the team wrote on top. A file therefore
24
- * carries HALF a lead — the person, and the team's annotations — and the
25
- * capture half is the door's to write.
26
- *
27
- * ## The address is the identity, because it is the document id
28
- *
29
- * A lead lives at `hosts/{hostId}/leads/{personKey}`, and `personKey` is
30
- * the sha256 of the normalized address. So the address is not merely the
31
- * one required cell: it is the row's name. A cell the normalizer cannot
32
- * read is refused as `invalid-email`, and two rows of one file that
33
- * normalize to the same address are one person — the second is skipped as
34
- * `duplicate` rather than merged onto the first, for the reason the
35
- * contacts import gives: one person reported once created and once merged
36
- * is a number the operator cannot reconcile against the rows they sent.
37
- *
38
- * ## What a file may NOT say
39
- *
40
- * The export's `Sources`, `First seen`, `Last seen` and `Captures` columns
41
- * are the capture door's own record of what the visitor did, and
42
- * `Converted` is stamped by `crm/lead-convert` after the contact exists.
43
- * None of them is a field here, so the mapping leaves those columns
44
- * unmapped rather than mis-mapping them — a file that could write
45
- * "first seen" could rewrite the history it is supposed to describe. The
46
- * organization-level file's `Site` column is left out for a second reason:
47
- * the site is the drawer's question and the route's permission is granted
48
- * for that ONE site, so a cell must not be able to redirect a row to
49
- * another.
50
- *
51
- * ## Qualified is a conversion, not a status a cell can claim
52
- *
53
- * `qualified` means a lead BECAME a contact, and `convertedContactId`
54
- * beside it names the contact that was really created. Only the convert
55
- * route writes the pair, so the list's own status control offers new,
56
- * working and unqualified and nothing else. A cell naming `qualified` is
57
- * dropped and reported here for the same reason: a status claiming a
58
- * conversion that never happened would show a contact link to nowhere.
59
- *
60
- * ## A bad cell is dropped and named; a bad row is skipped and named
61
- *
62
- * The address is the only cell that can make a row unstorable. An
63
- * unreadable status, or an unqualified reason with no unqualified status
64
- * to belong to, is left off the lead and REPORTED under
65
- * {@link LeadImportRow.dropped}, so the operator learns that a column went
66
- * nowhere rather than discovering it weeks later.
67
- */ import { CONTAINER_MEMBERSHIP_CAP } from "@aglyn/aglyn/app-utils/container-membership";
68
- import { normalizeContactEmail } from "@aglyn/aglyn/app-utils/contacts";
69
- import { CRM_LEAD_STATUS_LABELS, CRM_LEAD_STATUSES, CRM_LEAD_TEXT_MAX, isCrmLeadStatus, judgeCrmLeadSource, normalizeCrmPicklistLabel, normalizeCrmLeadTags, normalizeCompanyWebsite } from "@aglyn/aglyn/app-utils/crm";
70
- import { normalizeAddress, normalizePhone } from "@aglyn/aglyn/foundation/definitions/contact.types";
71
- import { CSV_IMPORT_CHUNK_SIZE, CSV_IMPORT_MAX_BODY_BYTES, CSV_IMPORT_MAX_ROWS, CSV_IMPORT_PREVIEW_ROWS, emptyImportResult, guessImportMapping, importAliasKeys, importSkippedCsv, importTextValue, mapImportRow, mergeImportResults } from "@aglyn/aglyn/app-utils/csv-import";
72
- /** The shared ceilings, under this collection's names. */ export const LEAD_IMPORT_MAX_ROWS = CSV_IMPORT_MAX_ROWS;
73
- export const LEAD_IMPORT_CHUNK_SIZE = CSV_IMPORT_CHUNK_SIZE;
74
- export const LEAD_IMPORT_MAX_BODY_BYTES = CSV_IMPORT_MAX_BODY_BYTES;
75
- export const LEAD_IMPORT_PREVIEW_ROWS = CSV_IMPORT_PREVIEW_ROWS;
76
- /** The same caps the lead's own cards hold a typed value to. */ export const LEAD_IMPORT_NOTES_MAX = 4000;
77
- export const LEAD_IMPORT_REASON_MAX = 500;
78
- /** A person's name, capped where every other import caps one. */ const NAME_MAX = 120;
79
- /**
80
- * The statuses a file may set.
81
- *
82
- * The list's own status control offers exactly these four, and for the
83
- * reason given above: `qualified` is written by the conversion, beside the
84
- * contact it produced.
85
- */ export const LEAD_IMPORT_STATUSES = CRM_LEAD_STATUSES.filter((status)=>status !== 'qualified');
86
- /**
87
- * The fields a column may be mapped to, in the order the mapping menu
88
- * lists them.
89
- *
90
- * The lead's own profile (AGL-3231) — company, title, phone, website, the
91
- * lead source, the address parts and tags — is what a list from another
92
- * tool actually carries, and the reason a lead can be worked without a
93
- * contact beside it. They read under the same labels the contacts import
94
- * uses, so one spreadsheet maps the same way into either.
95
- */ export const LEAD_IMPORT_FIELDS = [
96
- 'email',
97
- 'name',
98
- 'company',
99
- 'jobTitle',
100
- 'phone',
101
- 'website',
102
- 'leadSource',
103
- 'status',
104
- 'ownerEmail',
105
- 'addressLine1',
106
- 'addressLine2',
107
- 'addressCity',
108
- 'addressState',
109
- 'addressPostalCode',
110
- 'addressCountry',
111
- 'tags',
112
- 'campaigns',
113
- 'unqualifiedReason',
114
- 'notes'
115
- ];
116
- /** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */ export const LEAD_IMPORT_FIELD_LABELS = {
117
- email: 'Email (required)',
118
- name: 'Name',
119
- company: 'Company name',
120
- jobTitle: 'Job title',
121
- phone: 'Phone',
122
- website: 'Website',
123
- leadSource: 'Lead source',
124
- status: 'Status (new, nurturing, working, unqualified)',
125
- ownerEmail: 'Owner (team member email)',
126
- addressLine1: 'Address line 1',
127
- addressLine2: 'Address line 2',
128
- addressCity: 'City',
129
- addressState: 'State or region',
130
- addressPostalCode: 'Postal code',
131
- addressCountry: 'Country (two-letter code)',
132
- tags: 'Tags (comma or | separated)',
133
- campaigns: 'Campaigns (by name, comma or | separated)',
134
- unqualifiedReason: 'Unqualified reason',
135
- notes: 'Notes'
136
- };
137
- /**
138
- * Header aliases per field, matched after the shared header normalization.
139
- *
140
- * First in each list is the header this CRM's own leads export writes, so
141
- * an export re-imports without a hand mapping; the export's Sources, First
142
- * seen, Last seen, Captures, Converted and Site columns are deliberately
143
- * absent from every list, so they land on "Do not import".
144
- */ const FIELD_ALIASES = {
145
- email: [
146
- 'email',
147
- 'email address',
148
- 'e mail',
149
- 'mail',
150
- 'contact email',
151
- 'work email'
152
- ],
153
- name: [
154
- 'name',
155
- 'full name',
156
- 'lead',
157
- 'lead name',
158
- 'contact',
159
- 'contact name',
160
- 'person'
161
- ],
162
- company: [
163
- 'company',
164
- 'company name',
165
- 'organization',
166
- 'organisation',
167
- 'account',
168
- 'account name',
169
- 'employer'
170
- ],
171
- jobTitle: [
172
- 'job title',
173
- 'title',
174
- 'position',
175
- 'role',
176
- 'headline'
177
- ],
178
- phone: [
179
- 'phone',
180
- 'phone number',
181
- 'mobile',
182
- 'mobile phone',
183
- 'telephone',
184
- 'tel',
185
- 'cell'
186
- ],
187
- website: [
188
- 'website',
189
- 'web site',
190
- 'url',
191
- 'company website',
192
- 'company domain',
193
- 'domain'
194
- ],
195
- leadSource: [
196
- 'lead source',
197
- 'source',
198
- 'origin',
199
- 'channel',
200
- 'campaign'
201
- ],
202
- status: [
203
- 'status',
204
- 'lead status',
205
- 'stage',
206
- 'lead stage'
207
- ],
208
- ownerEmail: [
209
- 'owner',
210
- 'owner email',
211
- 'assigned to',
212
- 'assignee',
213
- 'rep',
214
- 'sales rep'
215
- ],
216
- addressLine1: [
217
- 'address',
218
- 'address line 1',
219
- 'street',
220
- 'street address',
221
- 'address 1'
222
- ],
223
- addressLine2: [
224
- 'address line 2',
225
- 'address 2',
226
- 'suite',
227
- 'apartment'
228
- ],
229
- addressCity: [
230
- 'city',
231
- 'town',
232
- 'locality'
233
- ],
234
- addressState: [
235
- 'state',
236
- 'state or region',
237
- 'region',
238
- 'province',
239
- 'county'
240
- ],
241
- addressPostalCode: [
242
- 'postal code',
243
- 'postcode',
244
- 'zip',
245
- 'zip code'
246
- ],
247
- addressCountry: [
248
- 'country',
249
- 'country code'
250
- ],
251
- tags: [
252
- 'tags',
253
- 'tag',
254
- 'labels',
255
- 'lists'
256
- ],
257
- // `campaign` alone stays the lead source's: another tool's "Campaign"
258
- // column names where the person came from, not one of this site's
259
- // containers (AGL-3254).
260
- campaigns: [
261
- 'campaigns',
262
- 'campaign names',
263
- 'in campaigns',
264
- 'email campaigns'
265
- ],
266
- unqualifiedReason: [
267
- 'unqualified reason',
268
- 'reason',
269
- 'disqualified reason',
270
- 'lost reason',
271
- 'reason lost'
272
- ],
273
- notes: [
274
- 'notes',
275
- 'note',
276
- 'description',
277
- 'comments',
278
- 'details'
279
- ]
280
- };
281
- const FIELD_ALIAS_KEYS = importAliasKeys(LEAD_IMPORT_FIELDS, FIELD_ALIASES);
282
- /** A proposed mapping from a file's header row, each field taken at most once. */ export function guessLeadImportMapping(columns) {
283
- return guessImportMapping(columns, LEAD_IMPORT_FIELDS, FIELD_ALIAS_KEYS);
284
- }
285
- /** One parsed line under the mapping. Empty cells are left absent; a lead has no custom fields. */ export function mapLeadImportRow(cells, mapping) {
286
- const _mapImportRow = mapImportRow(cells, mapping), { custom: _custom } = _mapImportRow, row = _object_without_properties_loose(_mapImportRow, [
287
- "custom"
288
- ]);
289
- return row;
290
- }
291
- /** How a skip reason reads on screen and in the downloaded file. */ export const LEAD_IMPORT_SKIP_LABELS = {
292
- 'invalid-email': 'No usable email address',
293
- duplicate: 'The same address appears earlier in this file',
294
- 'lead-ceiling': 'This site is at the platform lead limit',
295
- 'campaign-unknown': 'Names a campaign this site does not have',
296
- 'lead-source-unknown': "Names a lead source that isn't one of this organization's active values",
297
- 'write-failed': 'Could not be saved'
298
- };
299
- /** The most campaigns one row may name — the membership field's own cap. */ export const LEAD_IMPORT_CAMPAIGNS_MAX = CONTAINER_MEMBERSHIP_CAP;
300
- /**
301
- * A status cell by id or by label — `working`, `Working` and `WORKING` are
302
- * one status. `null` for a cell naming no status a file may set, which
303
- * includes the well-spelled `Qualified` the export writes for a converted
304
- * lead.
305
- */ export function parseImportLeadStatus(value) {
306
- var _LEAD_IMPORT_STATUSES_find;
307
- const text = String(value != null ? value : '').trim().toLowerCase();
308
- if (!text) return null;
309
- const byId = isCrmLeadStatus(text) ? text : null;
310
- const byLabel = (_LEAD_IMPORT_STATUSES_find = LEAD_IMPORT_STATUSES.find((status)=>CRM_LEAD_STATUS_LABELS[status].toLowerCase() === text)) != null ? _LEAD_IMPORT_STATUSES_find : null;
311
- const status = byId != null ? byId : byLabel;
312
- return status && LEAD_IMPORT_STATUSES.includes(status) ? status : null;
313
- }
314
- /**
315
- * One raw row as the values that will be written, or the reason it cannot
316
- * be. Refused here only for an unusable address, because the address is
317
- * the document id; the owner is refused by the server, which alone can
318
- * look them up.
319
- */ export function normalizeLeadImportRow(raw) {
320
- var _importTextValue, _raw_tags, _raw_campaigns;
321
- var _importTextValue1, _importTextValue2, _importTextValue3, _importTextValue4;
322
- const emailText = (_importTextValue = importTextValue(raw.email, 320)) != null ? _importTextValue : '';
323
- const email = normalizeContactEmail(emailText);
324
- if (!email) {
325
- return {
326
- ok: false,
327
- reason: 'invalid-email',
328
- input: emailText
329
- };
330
- }
331
- const dropped = [];
332
- const drop = (field, value)=>{
333
- dropped.push({
334
- field,
335
- value: String(value != null ? value : '').trim()
336
- });
337
- };
338
- const row = {
339
- email,
340
- profile: {},
341
- dropped
342
- };
343
- const name = (_importTextValue1 = importTextValue(raw.name, NAME_MAX)) == null ? void 0 : _importTextValue1.replace(/\s+/g, ' ');
344
- if (name) row.name = name;
345
- /*
346
- * The profile (AGL-3231), field by field, each through the normalizer
347
- * the record's own card runs. A phone or a website the normalizer cannot
348
- * read is dropped and reported rather than stored as typed, because the
349
- * record renders both as links; the country is the one address part the
350
- * address normalizer drops silently — a typed name is not a code — so it
351
- * is the one part the report has to name.
352
- */ const company = (_importTextValue2 = importTextValue(raw.company, CRM_LEAD_TEXT_MAX)) == null ? void 0 : _importTextValue2.replace(/\s+/g, ' ');
353
- if (company) row.profile.company = company;
354
- const jobTitle = (_importTextValue3 = importTextValue(raw.jobTitle, CRM_LEAD_TEXT_MAX)) == null ? void 0 : _importTextValue3.replace(/\s+/g, ' ');
355
- if (jobTitle) row.profile.jobTitle = jobTitle;
356
- const leadSource = (_importTextValue4 = importTextValue(raw.leadSource, CRM_LEAD_TEXT_MAX)) == null ? void 0 : _importTextValue4.replace(/\s+/g, ' ');
357
- if (leadSource) row.profile.leadSource = leadSource;
358
- const phoneText = importTextValue(raw.phone, 64);
359
- if (phoneText) {
360
- const phone = normalizePhone(phoneText);
361
- if (phone) row.profile.phone = phone;
362
- else drop('phone', phoneText);
363
- }
364
- const websiteText = importTextValue(raw.website, 320);
365
- if (websiteText) {
366
- const website = normalizeCompanyWebsite(websiteText);
367
- if (website) row.profile.website = website;
368
- else drop('website', websiteText);
369
- }
370
- const address = normalizeAddress({
371
- line1: importTextValue(raw.addressLine1, 200),
372
- line2: importTextValue(raw.addressLine2, 200),
373
- city: importTextValue(raw.addressCity, 120),
374
- state: importTextValue(raw.addressState, 120),
375
- postalCode: importTextValue(raw.addressPostalCode, 32),
376
- country: importTextValue(raw.addressCountry, 8)
377
- });
378
- if (address) row.profile.address = address;
379
- const countryText = importTextValue(raw.addressCountry, 64);
380
- if (countryText && !(address == null ? void 0 : address.country)) drop('addressCountry', countryText);
381
- const tags = normalizeCrmLeadTags(String((_raw_tags = raw.tags) != null ? _raw_tags : '').split(/[,|]/).map((tag)=>tag.trim()));
382
- if (tags.length) row.profile.tags = tags;
383
- // Names, trimmed and deduplicated as typed; the server matches them to
384
- // the site's campaigns without regard to case.
385
- const campaigns = [
386
- ...new Set(String((_raw_campaigns = raw.campaigns) != null ? _raw_campaigns : '').split(/[,|]/).map((name)=>name.trim().replace(/\s+/g, ' ')).filter(Boolean))
387
- ].slice(0, LEAD_IMPORT_CAMPAIGNS_MAX);
388
- if (campaigns.length) row.campaigns = campaigns;
389
- const statusText = importTextValue(raw.status, 32);
390
- if (statusText) {
391
- const status = parseImportLeadStatus(statusText);
392
- if (status) row.status = status;
393
- else drop('status', statusText);
394
- }
395
- const ownerText = importTextValue(raw.ownerEmail, 320);
396
- if (ownerText) {
397
- const owner = normalizeContactEmail(ownerText);
398
- if (owner) row.ownerEmail = owner;
399
- else drop('ownerEmail', ownerText);
400
- }
401
- /*
402
- * The reason belongs to the status: it is what an unqualified lead was
403
- * closed FOR, and on a lead that is not unqualified it describes
404
- * nothing. A row that carries one without the other keeps the status and
405
- * reports the reason, so a mis-mapped column is visible rather than
406
- * stored where nothing reads it.
407
- */ const reasonText = importTextValue(raw.unqualifiedReason, LEAD_IMPORT_REASON_MAX);
408
- if (reasonText) {
409
- if (row.status === 'unqualified') row.unqualifiedReason = reasonText;
410
- else drop('unqualifiedReason', reasonText);
411
- }
412
- const notes = importTextValue(raw.notes, LEAD_IMPORT_NOTES_MAX);
413
- if (notes) row.notes = notes;
414
- return {
415
- ok: true,
416
- row
417
- };
418
- }
419
- export function emptyLeadImportResult() {
420
- return emptyImportResult();
421
- }
422
- export function mergeLeadImportResults(total, chunk, offset = 0) {
423
- return mergeImportResults(total, chunk, offset);
424
- }
425
- /** The skipped rows as a file the operator can fix and re-import. */ export function leadImportSkippedCsv(columns, entries) {
426
- return importSkippedCsv(columns, entries, LEAD_IMPORT_SKIP_LABELS);
427
- }
428
- /**
429
- * The lead sources a file names that the org's list would refuse
430
- * (AGL-3298), each once, as the file spelled it — the drawer's warning
431
- * before anything is sent. Judged the way the server judges a NEW lead,
432
- * so a value the list holds but has deactivated is named too; a row
433
- * merging onto a lead that already holds that value would still pass.
434
- */ export function leadImportUnknownLeadSources(rows, picklist) {
435
- const unknown = new Map();
436
- for (const row of rows){
437
- const label = normalizeCrmPicklistLabel(row.leadSource);
438
- if (!label || unknown.has(label.toLowerCase())) continue;
439
- if (!judgeCrmLeadSource(picklist, label).ok) unknown.set(label.toLowerCase(), label);
440
- }
441
- return [
442
- ...unknown.values()
443
- ];
444
- }
445
-
446
- //# sourceMappingURL=crm-lead-import.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/model/crm-lead-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 LEADS INTO THE CRM — the pure half (AGL-2701).\n *\n * The contact import's three stages (`crm-import.ts`) over the lead\n * vocabulary. A lead is the one CRM record a person does not type: it is\n * what a capture door wrote when somebody signed up, booked or submitted a\n * form, plus the working state the team wrote on top. A file therefore\n * carries HALF a lead — the person, and the team's annotations — and the\n * capture half is the door's to write.\n *\n * ## The address is the identity, because it is the document id\n *\n * A lead lives at `hosts/{hostId}/leads/{personKey}`, and `personKey` is\n * the sha256 of the normalized address. So the address is not merely the\n * one required cell: it is the row's name. A cell the normalizer cannot\n * read is refused as `invalid-email`, and two rows of one file that\n * normalize to the same address are one person — the second is skipped as\n * `duplicate` rather than merged onto the first, for the reason the\n * contacts import gives: one person reported once created and once merged\n * is a number the operator cannot reconcile against the rows they sent.\n *\n * ## What a file may NOT say\n *\n * The export's `Sources`, `First seen`, `Last seen` and `Captures` columns\n * are the capture door's own record of what the visitor did, and\n * `Converted` is stamped by `crm/lead-convert` after the contact exists.\n * None of them is a field here, so the mapping leaves those columns\n * unmapped rather than mis-mapping them — a file that could write\n * \"first seen\" could rewrite the history it is supposed to describe. The\n * organization-level file's `Site` column is left out for a second reason:\n * the site is the drawer's question and the route's permission is granted\n * for that ONE site, so a cell must not be able to redirect a row to\n * another.\n *\n * ## Qualified is a conversion, not a status a cell can claim\n *\n * `qualified` means a lead BECAME a contact, and `convertedContactId`\n * beside it names the contact that was really created. Only the convert\n * route writes the pair, so the list's own status control offers new,\n * working and unqualified and nothing else. A cell naming `qualified` is\n * dropped and reported here for the same reason: a status claiming a\n * conversion that never happened would show a contact link to nowhere.\n *\n * ## A bad cell is dropped and named; a bad row is skipped and named\n *\n * The address is the only cell that can make a row unstorable. An\n * unreadable status, or an unqualified reason with no unqualified status\n * to belong to, is left off the lead and REPORTED under\n * {@link LeadImportRow.dropped}, so the operator learns that a column went\n * nowhere rather than discovering it weeks later.\n */\n\nimport { CONTAINER_MEMBERSHIP_CAP } from '@aglyn/aglyn/app-utils/container-membership'\nimport { normalizeContactEmail } from '@aglyn/aglyn/app-utils/contacts'\nimport {\n CRM_LEAD_STATUS_LABELS,\n CRM_LEAD_STATUSES,\n CRM_LEAD_TEXT_MAX,\n type CrmLeadProfile,\n type CrmLeadStatus,\n type CrmPicklist,\n isCrmLeadStatus,\n judgeCrmLeadSource,\n normalizeCrmPicklistLabel,\n normalizeCrmLeadTags,\n normalizeCompanyWebsite,\n} from '@aglyn/aglyn/app-utils/crm'\nimport {\n normalizeAddress,\n normalizePhone,\n} from '@aglyn/aglyn/foundation/definitions/contact.types'\nimport {\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} from '@aglyn/aglyn/app-utils/csv-import'\n\n/** The shared ceilings, under this collection's names. */\nexport const LEAD_IMPORT_MAX_ROWS = CSV_IMPORT_MAX_ROWS\nexport const LEAD_IMPORT_CHUNK_SIZE = CSV_IMPORT_CHUNK_SIZE\nexport const LEAD_IMPORT_MAX_BODY_BYTES = CSV_IMPORT_MAX_BODY_BYTES\nexport const LEAD_IMPORT_PREVIEW_ROWS = CSV_IMPORT_PREVIEW_ROWS\n\n/** The same caps the lead's own cards hold a typed value to. */\nexport const LEAD_IMPORT_NOTES_MAX = 4000\nexport const LEAD_IMPORT_REASON_MAX = 500\n\n/** A person's name, capped where every other import caps one. */\nconst NAME_MAX = 120\n\n/**\n * The statuses a file may set.\n *\n * The list's own status control offers exactly these four, and for the\n * reason given above: `qualified` is written by the conversion, beside the\n * contact it produced.\n */\nexport const LEAD_IMPORT_STATUSES: readonly CrmLeadStatus[] =\n CRM_LEAD_STATUSES.filter((status) => status !== 'qualified')\n\n/**\n * The fields a column may be mapped to, in the order the mapping menu\n * lists them.\n *\n * The lead's own profile (AGL-3231) — company, title, phone, website, the\n * lead source, the address parts and tags — is what a list from another\n * tool actually carries, and the reason a lead can be worked without a\n * contact beside it. They read under the same labels the contacts import\n * uses, so one spreadsheet maps the same way into either.\n */\nexport const LEAD_IMPORT_FIELDS = [\n 'email',\n 'name',\n 'company',\n 'jobTitle',\n 'phone',\n 'website',\n 'leadSource',\n 'status',\n 'ownerEmail',\n 'addressLine1',\n 'addressLine2',\n 'addressCity',\n 'addressState',\n 'addressPostalCode',\n 'addressCountry',\n 'tags',\n 'campaigns',\n 'unqualifiedReason',\n 'notes',\n] as const\n\nexport type LeadImportField = (typeof LEAD_IMPORT_FIELDS)[number]\n\n/** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */\nexport const LEAD_IMPORT_FIELD_LABELS: Record<LeadImportField, string> = {\n email: 'Email (required)',\n name: 'Name',\n company: 'Company name',\n jobTitle: 'Job title',\n phone: 'Phone',\n website: 'Website',\n leadSource: 'Lead source',\n status: 'Status (new, nurturing, working, unqualified)',\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 campaigns: 'Campaigns (by name, comma or | separated)',\n unqualifiedReason: 'Unqualified reason',\n notes: 'Notes',\n}\n\n/**\n * Header aliases per field, matched after the shared header normalization.\n *\n * First in each list is the header this CRM's own leads export writes, so\n * an export re-imports without a hand mapping; the export's Sources, First\n * seen, Last seen, Captures, Converted and Site columns are deliberately\n * absent from every list, so they land on \"Do not import\".\n */\nconst FIELD_ALIASES: Record<LeadImportField, readonly string[]> = {\n email: ['email', 'email address', 'e mail', 'mail', 'contact email', 'work email'],\n name: ['name', 'full name', 'lead', 'lead name', 'contact', 'contact name', 'person'],\n company: [\n 'company',\n 'company name',\n 'organization',\n 'organisation',\n 'account',\n 'account name',\n 'employer',\n ],\n jobTitle: ['job title', 'title', 'position', 'role', 'headline'],\n phone: ['phone', 'phone number', 'mobile', 'mobile phone', 'telephone', 'tel', 'cell'],\n website: ['website', 'web site', 'url', 'company website', 'company domain', 'domain'],\n leadSource: ['lead source', 'source', 'origin', 'channel', 'campaign'],\n status: ['status', 'lead status', 'stage', 'lead stage'],\n ownerEmail: ['owner', 'owner email', 'assigned to', 'assignee', 'rep', 'sales rep'],\n addressLine1: ['address', 'address line 1', 'street', 'street address', 'address 1'],\n addressLine2: ['address line 2', 'address 2', 'suite', 'apartment'],\n addressCity: ['city', 'town', 'locality'],\n addressState: ['state', 'state or region', 'region', 'province', 'county'],\n addressPostalCode: ['postal code', 'postcode', 'zip', 'zip code'],\n addressCountry: ['country', 'country code'],\n tags: ['tags', 'tag', 'labels', 'lists'],\n // `campaign` alone stays the lead source's: another tool's \"Campaign\"\n // column names where the person came from, not one of this site's\n // containers (AGL-3254).\n campaigns: ['campaigns', 'campaign names', 'in campaigns', 'email campaigns'],\n unqualifiedReason: [\n 'unqualified reason',\n 'reason',\n 'disqualified reason',\n 'lost reason',\n 'reason lost',\n ],\n notes: ['notes', 'note', 'description', 'comments', 'details'],\n}\n\nconst FIELD_ALIAS_KEYS = importAliasKeys(LEAD_IMPORT_FIELDS, FIELD_ALIASES)\n\n/** Column index → field. A column absent from the map is not imported. */\nexport type LeadImportMapping = Record<number, LeadImportField>\n\n/** A proposed mapping from a file's header row, each field taken at most once. */\nexport function guessLeadImportMapping(columns: readonly string[]): LeadImportMapping {\n return guessImportMapping(columns, LEAD_IMPORT_FIELDS, FIELD_ALIAS_KEYS)\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 LeadImportRawRow = Partial<Record<LeadImportField, unknown>>\n\n/** One parsed line under the mapping. Empty cells are left absent; a lead has no custom fields. */\nexport function mapLeadImportRow(\n cells: readonly string[],\n mapping: Record<number, LeadImportField | `custom:${string}`>,\n): LeadImportRawRow {\n const { custom: _custom, ...row } = mapImportRow(cells, mapping)\n return row\n}\n\nexport type LeadImportSkipReason =\n | 'invalid-email'\n | 'duplicate'\n | 'lead-ceiling'\n | 'campaign-unknown'\n | 'lead-source-unknown'\n | 'write-failed'\n\n/** How a skip reason reads on screen and in the downloaded file. */\nexport const LEAD_IMPORT_SKIP_LABELS: Record<LeadImportSkipReason, string> = {\n 'invalid-email': 'No usable email address',\n duplicate: 'The same address appears earlier in this file',\n 'lead-ceiling': 'This site is at the platform lead limit',\n 'campaign-unknown': 'Names a campaign this site does not have',\n 'lead-source-unknown':\n \"Names a lead source that isn't one of this organization's active values\",\n 'write-failed': 'Could not be saved',\n}\n\n/** The most campaigns one row may name — the membership field's own cap. */\nexport const LEAD_IMPORT_CAMPAIGNS_MAX = CONTAINER_MEMBERSHIP_CAP\n\n/** One row, ready for the server to resolve and write. */\nexport interface LeadImportRow {\n /** Normalized — the address `personKey` derives the document id from. */\n email: string\n name?: string\n /**\n * The lead's own profile, already normalized the way the record stores\n * it (AGL-3231): a key present is a value to write, a key absent leaves\n * an existing lead's value alone. Never a clear — a blank cell in a file\n * is a cell nobody filled, not a decision to erase what the site knows.\n */\n profile: CrmLeadProfile\n /**\n * The campaigns the row files the lead under (AGL-3254), by NAME as the\n * file wrote them: the server resolves each against the site's own\n * containers and refuses the row whole when one is not there, because a\n * row filed under half its campaigns is a row nobody asked for.\n */\n campaigns?: string[]\n /** Absent leaves an existing lead's status alone and a new one reading as `new`. */\n status?: CrmLeadStatus\n /** Normalized, for the server to resolve against the org's members. */\n ownerEmail?: string\n /** Only ever set beside `status: 'unqualified'` — the pair is one fact. */\n unqualifiedReason?: string\n notes?: string\n dropped: ImportDroppedValue[]\n}\n\nexport type LeadImportRowVerdict =\n | { ok: true; row: LeadImportRow }\n | { ok: false; reason: 'invalid-email'; input: string }\n\n/**\n * A status cell by id or by label — `working`, `Working` and `WORKING` are\n * one status. `null` for a cell naming no status a file may set, which\n * includes the well-spelled `Qualified` the export writes for a converted\n * lead.\n */\nexport function parseImportLeadStatus(value: unknown): CrmLeadStatus | null {\n const text = String(value ?? '')\n .trim()\n .toLowerCase()\n if (!text) return null\n const byId = isCrmLeadStatus(text) ? text : null\n const byLabel =\n LEAD_IMPORT_STATUSES.find(\n (status) => CRM_LEAD_STATUS_LABELS[status].toLowerCase() === text,\n ) ?? null\n const status = byId ?? byLabel\n return status && LEAD_IMPORT_STATUSES.includes(status) ? status : null\n}\n\n/**\n * One raw row as the values that will be written, or the reason it cannot\n * be. Refused here only for an unusable address, because the address is\n * the document id; the owner is refused by the server, which alone can\n * look them up.\n */\nexport function normalizeLeadImportRow(raw: LeadImportRawRow): LeadImportRowVerdict {\n const emailText = importTextValue(raw.email, 320) ?? ''\n const email = normalizeContactEmail(emailText)\n if (!email) {\n return { ok: false, reason: 'invalid-email', input: emailText }\n }\n const dropped: ImportDroppedValue[] = []\n const drop = (field: LeadImportField, value: unknown) => {\n dropped.push({ field, value: String(value ?? '').trim() })\n }\n const row: LeadImportRow = { email, profile: {}, dropped }\n\n const name = importTextValue(raw.name, NAME_MAX)?.replace(/\\s+/g, ' ')\n if (name) row.name = name\n\n /*\n * The profile (AGL-3231), field by field, each through the normalizer\n * the record's own card runs. A phone or a website the normalizer cannot\n * read is dropped and reported rather than stored as typed, because the\n * record renders both as links; the country is the one address part the\n * address normalizer drops silently — a typed name is not a code — so it\n * is the one part the report has to name.\n */\n const company = importTextValue(raw.company, CRM_LEAD_TEXT_MAX)?.replace(/\\s+/g, ' ')\n if (company) row.profile.company = company\n const jobTitle = importTextValue(raw.jobTitle, CRM_LEAD_TEXT_MAX)?.replace(/\\s+/g, ' ')\n if (jobTitle) row.profile.jobTitle = jobTitle\n const leadSource = importTextValue(raw.leadSource, CRM_LEAD_TEXT_MAX)?.replace(\n /\\s+/g,\n ' ',\n )\n if (leadSource) row.profile.leadSource = leadSource\n const phoneText = importTextValue(raw.phone, 64)\n if (phoneText) {\n const phone = normalizePhone(phoneText)\n if (phone) row.profile.phone = phone\n else drop('phone', phoneText)\n }\n const websiteText = importTextValue(raw.website, 320)\n if (websiteText) {\n const website = normalizeCompanyWebsite(websiteText)\n if (website) row.profile.website = website\n else drop('website', websiteText)\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.profile.address = address\n const countryText = importTextValue(raw.addressCountry, 64)\n if (countryText && !address?.country) drop('addressCountry', countryText)\n const tags = normalizeCrmLeadTags(\n String(raw.tags ?? '')\n .split(/[,|]/)\n .map((tag) => tag.trim()),\n )\n if (tags.length) row.profile.tags = tags\n\n // Names, trimmed and deduplicated as typed; the server matches them to\n // the site's campaigns without regard to case.\n const campaigns = [\n ...new Set(\n String(raw.campaigns ?? '')\n .split(/[,|]/)\n .map((name) => name.trim().replace(/\\s+/g, ' '))\n .filter(Boolean),\n ),\n ].slice(0, LEAD_IMPORT_CAMPAIGNS_MAX)\n if (campaigns.length) row.campaigns = campaigns\n\n const statusText = importTextValue(raw.status, 32)\n if (statusText) {\n const status = parseImportLeadStatus(statusText)\n if (status) row.status = status\n else drop('status', statusText)\n }\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 /*\n * The reason belongs to the status: it is what an unqualified lead was\n * closed FOR, and on a lead that is not unqualified it describes\n * nothing. A row that carries one without the other keeps the status and\n * reports the reason, so a mis-mapped column is visible rather than\n * stored where nothing reads it.\n */\n const reasonText = importTextValue(raw.unqualifiedReason, LEAD_IMPORT_REASON_MAX)\n if (reasonText) {\n if (row.status === 'unqualified') row.unqualifiedReason = reasonText\n else drop('unqualifiedReason', reasonText)\n }\n\n const notes = importTextValue(raw.notes, LEAD_IMPORT_NOTES_MAX)\n if (notes) row.notes = notes\n\n return { ok: true, row }\n}\n\n/** One row the server did not store, by its index in the request, named by the address. */\nexport interface LeadImportSkippedRow {\n index: number\n email: string\n reason: LeadImportSkipReason\n}\n\n/** What one request did. The drawer sums these across a file. */\nexport type LeadImportChunkResult = ImportChunkResult<LeadImportSkippedRow>\n\nexport function emptyLeadImportResult(): LeadImportChunkResult {\n return emptyImportResult<LeadImportSkippedRow>()\n}\n\nexport function mergeLeadImportResults(\n total: LeadImportChunkResult,\n chunk: LeadImportChunkResult,\n offset = 0,\n): LeadImportChunkResult {\n return mergeImportResults(total, chunk, offset)\n}\n\n/** The skipped rows as a file the operator can fix and re-import. */\nexport function leadImportSkippedCsv(\n columns: readonly string[],\n entries: readonly { cells: readonly string[]; reason: LeadImportSkipReason }[],\n): string {\n return importSkippedCsv(columns, entries, LEAD_IMPORT_SKIP_LABELS)\n}\n\n/**\n * The lead sources a file names that the org's list would refuse\n * (AGL-3298), each once, as the file spelled it — the drawer's warning\n * before anything is sent. Judged the way the server judges a NEW lead,\n * so a value the list holds but has deactivated is named too; a row\n * merging onto a lead that already holds that value would still pass.\n */\nexport function leadImportUnknownLeadSources(\n rows: readonly LeadImportRawRow[],\n picklist: CrmPicklist,\n): string[] {\n const unknown = new Map<string, string>()\n for (const row of rows) {\n const label = normalizeCrmPicklistLabel(row.leadSource)\n if (!label || unknown.has(label.toLowerCase())) continue\n if (!judgeCrmLeadSource(picklist, label).ok) unknown.set(label.toLowerCase(), label)\n }\n return [...unknown.values()]\n}\n"],"names":["CONTAINER_MEMBERSHIP_CAP","normalizeContactEmail","CRM_LEAD_STATUS_LABELS","CRM_LEAD_STATUSES","CRM_LEAD_TEXT_MAX","isCrmLeadStatus","judgeCrmLeadSource","normalizeCrmPicklistLabel","normalizeCrmLeadTags","normalizeCompanyWebsite","normalizeAddress","normalizePhone","CSV_IMPORT_CHUNK_SIZE","CSV_IMPORT_MAX_BODY_BYTES","CSV_IMPORT_MAX_ROWS","CSV_IMPORT_PREVIEW_ROWS","emptyImportResult","guessImportMapping","importAliasKeys","importSkippedCsv","importTextValue","mapImportRow","mergeImportResults","LEAD_IMPORT_MAX_ROWS","LEAD_IMPORT_CHUNK_SIZE","LEAD_IMPORT_MAX_BODY_BYTES","LEAD_IMPORT_PREVIEW_ROWS","LEAD_IMPORT_NOTES_MAX","LEAD_IMPORT_REASON_MAX","NAME_MAX","LEAD_IMPORT_STATUSES","filter","status","LEAD_IMPORT_FIELDS","LEAD_IMPORT_FIELD_LABELS","email","name","company","jobTitle","phone","website","leadSource","ownerEmail","addressLine1","addressLine2","addressCity","addressState","addressPostalCode","addressCountry","tags","campaigns","unqualifiedReason","notes","FIELD_ALIASES","FIELD_ALIAS_KEYS","guessLeadImportMapping","columns","mapLeadImportRow","cells","mapping","custom","_custom","row","LEAD_IMPORT_SKIP_LABELS","duplicate","LEAD_IMPORT_CAMPAIGNS_MAX","parseImportLeadStatus","value","text","String","trim","toLowerCase","byId","byLabel","find","includes","normalizeLeadImportRow","raw","emailText","ok","reason","input","dropped","drop","field","push","profile","replace","phoneText","websiteText","address","line1","line2","city","state","postalCode","country","countryText","split","map","tag","length","Set","Boolean","slice","statusText","ownerText","owner","reasonText","emptyLeadImportResult","mergeLeadImportResults","total","chunk","offset","leadImportSkippedCsv","entries","leadImportUnknownLeadSources","rows","picklist","unknown","Map","label","has","set","values"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkDC,GAED,SAASA,wBAAwB,QAAQ,8CAA6C;AACtF,SAASC,qBAAqB,QAAQ,kCAAiC;AACvE,SACEC,sBAAsB,EACtBC,iBAAiB,EACjBC,iBAAiB,EAIjBC,eAAe,EACfC,kBAAkB,EAClBC,yBAAyB,EACzBC,oBAAoB,EACpBC,uBAAuB,QAClB,6BAA4B;AACnC,SACEC,gBAAgB,EAChBC,cAAc,QACT,oDAAmD;AAC1D,SACEC,qBAAqB,EACrBC,yBAAyB,EACzBC,mBAAmB,EACnBC,uBAAuB,EACvBC,iBAAiB,EACjBC,kBAAkB,EAClBC,eAAe,EAGfC,gBAAgB,EAChBC,eAAe,EACfC,YAAY,EACZC,kBAAkB,QACb,oCAAmC;AAE1C,wDAAwD,GACxD,OAAO,MAAMC,uBAAuBT,oBAAmB;AACvD,OAAO,MAAMU,yBAAyBZ,sBAAqB;AAC3D,OAAO,MAAMa,6BAA6BZ,0BAAyB;AACnE,OAAO,MAAMa,2BAA2BX,wBAAuB;AAE/D,8DAA8D,GAC9D,OAAO,MAAMY,wBAAwB,KAAI;AACzC,OAAO,MAAMC,yBAAyB,IAAG;AAEzC,+DAA+D,GAC/D,MAAMC,WAAW;AAEjB;;;;;;CAMC,GACD,OAAO,MAAMC,uBACX3B,kBAAkB4B,MAAM,CAAC,CAACC,SAAWA,WAAW,aAAY;AAE9D;;;;;;;;;CASC,GACD,OAAO,MAAMC,qBAAqB;IAChC;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAIV,sFAAsF,GACtF,OAAO,MAAMC,2BAA4D;IACvEC,OAAO;IACPC,MAAM;IACNC,SAAS;IACTC,UAAU;IACVC,OAAO;IACPC,SAAS;IACTC,YAAY;IACZT,QAAQ;IACRU,YAAY;IACZC,cAAc;IACdC,cAAc;IACdC,aAAa;IACbC,cAAc;IACdC,mBAAmB;IACnBC,gBAAgB;IAChBC,MAAM;IACNC,WAAW;IACXC,mBAAmB;IACnBC,OAAO;AACT,EAAC;AAED;;;;;;;CAOC,GACD,MAAMC,gBAA4D;IAChElB,OAAO;QAAC;QAAS;QAAiB;QAAU;QAAQ;QAAiB;KAAa;IAClFC,MAAM;QAAC;QAAQ;QAAa;QAAQ;QAAa;QAAW;QAAgB;KAAS;IACrFC,SAAS;QACP;QACA;QACA;QACA;QACA;QACA;QACA;KACD;IACDC,UAAU;QAAC;QAAa;QAAS;QAAY;QAAQ;KAAW;IAChEC,OAAO;QAAC;QAAS;QAAgB;QAAU;QAAgB;QAAa;QAAO;KAAO;IACtFC,SAAS;QAAC;QAAW;QAAY;QAAO;QAAmB;QAAkB;KAAS;IACtFC,YAAY;QAAC;QAAe;QAAU;QAAU;QAAW;KAAW;IACtET,QAAQ;QAAC;QAAU;QAAe;QAAS;KAAa;IACxDU,YAAY;QAAC;QAAS;QAAe;QAAe;QAAY;QAAO;KAAY;IACnFC,cAAc;QAAC;QAAW;QAAkB;QAAU;QAAkB;KAAY;IACpFC,cAAc;QAAC;QAAkB;QAAa;QAAS;KAAY;IACnEC,aAAa;QAAC;QAAQ;QAAQ;KAAW;IACzCC,cAAc;QAAC;QAAS;QAAmB;QAAU;QAAY;KAAS;IAC1EC,mBAAmB;QAAC;QAAe;QAAY;QAAO;KAAW;IACjEC,gBAAgB;QAAC;QAAW;KAAe;IAC3CC,MAAM;QAAC;QAAQ;QAAO;QAAU;KAAQ;IACxC,sEAAsE;IACtE,kEAAkE;IAClE,yBAAyB;IACzBC,WAAW;QAAC;QAAa;QAAkB;QAAgB;KAAkB;IAC7EC,mBAAmB;QACjB;QACA;QACA;QACA;QACA;KACD;IACDC,OAAO;QAAC;QAAS;QAAQ;QAAe;QAAY;KAAU;AAChE;AAEA,MAAME,mBAAmBpC,gBAAgBe,oBAAoBoB;AAK7D,gFAAgF,GAChF,OAAO,SAASE,uBAAuBC,OAA0B;IAC/D,OAAOvC,mBAAmBuC,SAASvB,oBAAoBqB;AACzD;AASA,iGAAiG,GACjG,OAAO,SAASG,iBACdC,KAAwB,EACxBC,OAA6D;IAE7D,MAAoCtC,gBAAAA,aAAaqC,OAAOC,UAAlD,EAAEC,QAAQC,OAAO,EAAU,GAAGxC,eAARyC,uCAAQzC;;;IACpC,OAAOyC;AACT;AAUA,kEAAkE,GAClE,OAAO,MAAMC,0BAAgE;IAC3E,iBAAiB;IACjBC,WAAW;IACX,gBAAgB;IAChB,oBAAoB;IACpB,uBACE;IACF,gBAAgB;AAClB,EAAC;AAED,0EAA0E,GAC1E,OAAO,MAAMC,4BAA4BjE,yBAAwB;AAmCjE;;;;;CAKC,GACD,OAAO,SAASkE,sBAAsBC,KAAc;QAOhDrC;IANF,MAAMsC,OAAOC,OAAOF,gBAAAA,QAAS,IAC1BG,IAAI,GACJC,WAAW;IACd,IAAI,CAACH,MAAM,OAAO;IAClB,MAAMI,OAAOnE,gBAAgB+D,QAAQA,OAAO;IAC5C,MAAMK,WACJ3C,6BAAAA,qBAAqB4C,IAAI,CACvB,CAAC1C,SAAW9B,sBAAsB,CAAC8B,OAAO,CAACuC,WAAW,OAAOH,iBAD/DtC,6BAEK;IACP,MAAME,SAASwC,eAAAA,OAAQC;IACvB,OAAOzC,UAAUF,qBAAqB6C,QAAQ,CAAC3C,UAAUA,SAAS;AACpE;AAEA;;;;;CAKC,GACD,OAAO,SAAS4C,uBAAuBC,GAAqB;QACxCzD,kBAuDTyD,WAUEA;QAtDEzD,mBAWGA,mBAECA,mBAEEA;IA1BnB,MAAM0D,aAAY1D,mBAAAA,gBAAgByD,IAAI1C,KAAK,EAAE,gBAA3Bf,mBAAmC;IACrD,MAAMe,QAAQlC,sBAAsB6E;IACpC,IAAI,CAAC3C,OAAO;QACV,OAAO;YAAE4C,IAAI;YAAOC,QAAQ;YAAiBC,OAAOH;QAAU;IAChE;IACA,MAAMI,UAAgC,EAAE;IACxC,MAAMC,OAAO,CAACC,OAAwBjB;QACpCe,QAAQG,IAAI,CAAC;YAAED;YAAOjB,OAAOE,OAAOF,gBAAAA,QAAS,IAAIG,IAAI;QAAG;IAC1D;IACA,MAAMR,MAAqB;QAAE3B;QAAOmD,SAAS,CAAC;QAAGJ;IAAQ;IAEzD,MAAM9C,QAAOhB,oBAAAA,gBAAgByD,IAAIzC,IAAI,EAAEP,8BAA1BT,kBAAqCmE,OAAO,CAAC,QAAQ;IAClE,IAAInD,MAAM0B,IAAI1B,IAAI,GAAGA;IAErB;;;;;;;GAOC,GACD,MAAMC,WAAUjB,oBAAAA,gBAAgByD,IAAIxC,OAAO,EAAEjC,uCAA7BgB,kBAAiDmE,OAAO,CAAC,QAAQ;IACjF,IAAIlD,SAASyB,IAAIwB,OAAO,CAACjD,OAAO,GAAGA;IACnC,MAAMC,YAAWlB,oBAAAA,gBAAgByD,IAAIvC,QAAQ,EAAElC,uCAA9BgB,kBAAkDmE,OAAO,CAAC,QAAQ;IACnF,IAAIjD,UAAUwB,IAAIwB,OAAO,CAAChD,QAAQ,GAAGA;IACrC,MAAMG,cAAarB,oBAAAA,gBAAgByD,IAAIpC,UAAU,EAAErC,uCAAhCgB,kBAAoDmE,OAAO,CAC5E,QACA;IAEF,IAAI9C,YAAYqB,IAAIwB,OAAO,CAAC7C,UAAU,GAAGA;IACzC,MAAM+C,YAAYpE,gBAAgByD,IAAItC,KAAK,EAAE;IAC7C,IAAIiD,WAAW;QACb,MAAMjD,QAAQ5B,eAAe6E;QAC7B,IAAIjD,OAAOuB,IAAIwB,OAAO,CAAC/C,KAAK,GAAGA;aAC1B4C,KAAK,SAASK;IACrB;IACA,MAAMC,cAAcrE,gBAAgByD,IAAIrC,OAAO,EAAE;IACjD,IAAIiD,aAAa;QACf,MAAMjD,UAAU/B,wBAAwBgF;QACxC,IAAIjD,SAASsB,IAAIwB,OAAO,CAAC9C,OAAO,GAAGA;aAC9B2C,KAAK,WAAWM;IACvB;IACA,MAAMC,UAAUhF,iBAAiB;QAC/BiF,OAAOvE,gBAAgByD,IAAIlC,YAAY,EAAE;QACzCiD,OAAOxE,gBAAgByD,IAAIjC,YAAY,EAAE;QACzCiD,MAAMzE,gBAAgByD,IAAIhC,WAAW,EAAE;QACvCiD,OAAO1E,gBAAgByD,IAAI/B,YAAY,EAAE;QACzCiD,YAAY3E,gBAAgByD,IAAI9B,iBAAiB,EAAE;QACnDiD,SAAS5E,gBAAgByD,IAAI7B,cAAc,EAAE;IAC/C;IACA,IAAI0C,SAAS5B,IAAIwB,OAAO,CAACI,OAAO,GAAGA;IACnC,MAAMO,cAAc7E,gBAAgByD,IAAI7B,cAAc,EAAE;IACxD,IAAIiD,eAAe,EAACP,2BAAAA,QAASM,OAAO,GAAEb,KAAK,kBAAkBc;IAC7D,MAAMhD,OAAOzC,qBACX6D,QAAOQ,YAAAA,IAAI5B,IAAI,YAAR4B,YAAY,IAChBqB,KAAK,CAAC,QACNC,GAAG,CAAC,CAACC,MAAQA,IAAI9B,IAAI;IAE1B,IAAIrB,KAAKoD,MAAM,EAAEvC,IAAIwB,OAAO,CAACrC,IAAI,GAAGA;IAEpC,uEAAuE;IACvE,+CAA+C;IAC/C,MAAMC,YAAY;WACb,IAAIoD,IACLjC,QAAOQ,iBAAAA,IAAI3B,SAAS,YAAb2B,iBAAiB,IACrBqB,KAAK,CAAC,QACNC,GAAG,CAAC,CAAC/D,OAASA,KAAKkC,IAAI,GAAGiB,OAAO,CAAC,QAAQ,MAC1CxD,MAAM,CAACwE;KAEb,CAACC,KAAK,CAAC,GAAGvC;IACX,IAAIf,UAAUmD,MAAM,EAAEvC,IAAIZ,SAAS,GAAGA;IAEtC,MAAMuD,aAAarF,gBAAgByD,IAAI7C,MAAM,EAAE;IAC/C,IAAIyE,YAAY;QACd,MAAMzE,SAASkC,sBAAsBuC;QACrC,IAAIzE,QAAQ8B,IAAI9B,MAAM,GAAGA;aACpBmD,KAAK,UAAUsB;IACtB;IAEA,MAAMC,YAAYtF,gBAAgByD,IAAInC,UAAU,EAAE;IAClD,IAAIgE,WAAW;QACb,MAAMC,QAAQ1G,sBAAsByG;QACpC,IAAIC,OAAO7C,IAAIpB,UAAU,GAAGiE;aACvBxB,KAAK,cAAcuB;IAC1B;IAEA;;;;;;GAMC,GACD,MAAME,aAAaxF,gBAAgByD,IAAI1B,iBAAiB,EAAEvB;IAC1D,IAAIgF,YAAY;QACd,IAAI9C,IAAI9B,MAAM,KAAK,eAAe8B,IAAIX,iBAAiB,GAAGyD;aACrDzB,KAAK,qBAAqByB;IACjC;IAEA,MAAMxD,QAAQhC,gBAAgByD,IAAIzB,KAAK,EAAEzB;IACzC,IAAIyB,OAAOU,IAAIV,KAAK,GAAGA;IAEvB,OAAO;QAAE2B,IAAI;QAAMjB;IAAI;AACzB;AAYA,OAAO,SAAS+C;IACd,OAAO7F;AACT;AAEA,OAAO,SAAS8F,uBACdC,KAA4B,EAC5BC,KAA4B,EAC5BC,SAAS,CAAC;IAEV,OAAO3F,mBAAmByF,OAAOC,OAAOC;AAC1C;AAEA,mEAAmE,GACnE,OAAO,SAASC,qBACd1D,OAA0B,EAC1B2D,OAA8E;IAE9E,OAAOhG,iBAAiBqC,SAAS2D,SAASpD;AAC5C;AAEA;;;;;;CAMC,GACD,OAAO,SAASqD,6BACdC,IAAiC,EACjCC,QAAqB;IAErB,MAAMC,UAAU,IAAIC;IACpB,KAAK,MAAM1D,OAAOuD,KAAM;QACtB,MAAMI,QAAQlH,0BAA0BuD,IAAIrB,UAAU;QACtD,IAAI,CAACgF,SAASF,QAAQG,GAAG,CAACD,MAAMlD,WAAW,KAAK;QAChD,IAAI,CAACjE,mBAAmBgH,UAAUG,OAAO1C,EAAE,EAAEwC,QAAQI,GAAG,CAACF,MAAMlD,WAAW,IAAIkD;IAChF;IACA,OAAO;WAAIF,QAAQK,MAAM;KAAG;AAC9B"}