@aglyn/aglyn 1.0.0-beta.218 → 1.0.0-beta.220

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 (455) hide show
  1. package/package.json +12 -12
  2. package/src/lib/app-utils/actions.d.ts +26 -433
  3. package/src/lib/app-utils/actions.js +108 -633
  4. package/src/lib/app-utils/actions.js.map +1 -1
  5. package/src/lib/app-utils/activity-presenter.d.ts +3 -3
  6. package/src/lib/app-utils/activity-presenter.js +36 -52
  7. package/src/lib/app-utils/activity-presenter.js.map +1 -1
  8. package/src/lib/app-utils/analytics-events.d.ts +1 -1
  9. package/src/lib/app-utils/analytics-events.js.map +1 -1
  10. package/src/lib/app-utils/analytics-provider.d.ts +182 -0
  11. package/src/lib/app-utils/analytics-provider.js +133 -0
  12. package/src/lib/app-utils/analytics-provider.js.map +1 -0
  13. package/src/lib/app-utils/api-plugins.d.ts +46 -0
  14. package/src/lib/app-utils/api-plugins.js +19 -0
  15. package/src/lib/app-utils/api-plugins.js.map +1 -1
  16. package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
  17. package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
  18. package/src/lib/app-utils/artifact-overrides.js.map +1 -0
  19. package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
  20. package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
  21. package/src/lib/app-utils/artifact-provenance.js.map +1 -0
  22. package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
  23. package/src/lib/app-utils/binding-token-catalog.js +17 -41
  24. package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
  25. package/src/lib/app-utils/brand-support-line.d.ts +36 -0
  26. package/src/lib/app-utils/brand-support-line.js +38 -0
  27. package/src/lib/app-utils/brand-support-line.js.map +1 -0
  28. package/src/lib/app-utils/collection-entries.d.ts +2 -2
  29. package/src/lib/app-utils/collection-entries.js.map +1 -1
  30. package/src/lib/app-utils/consent-group-change.d.ts +4 -0
  31. package/src/lib/app-utils/consent-group-change.js.map +1 -1
  32. package/src/lib/app-utils/consent-groups.d.ts +1 -1
  33. package/src/lib/app-utils/consent-groups.js.map +1 -1
  34. package/src/lib/app-utils/console-routes.d.ts +15 -42
  35. package/src/lib/app-utils/console-routes.js +10 -39
  36. package/src/lib/app-utils/console-routes.js.map +1 -1
  37. package/src/lib/app-utils/contacts.d.ts +24 -2
  38. package/src/lib/app-utils/contacts.js +21 -5
  39. package/src/lib/app-utils/contacts.js.map +1 -1
  40. package/src/lib/app-utils/container-membership.d.ts +93 -0
  41. package/src/lib/app-utils/container-membership.js +165 -0
  42. package/src/lib/app-utils/container-membership.js.map +1 -0
  43. package/src/lib/app-utils/crm-task-reminders.d.ts +23 -6
  44. package/src/lib/app-utils/crm-task-reminders.js +32 -11
  45. package/src/lib/app-utils/crm-task-reminders.js.map +1 -1
  46. package/src/lib/app-utils/crm.d.ts +24 -4
  47. package/src/lib/app-utils/crm.js +23 -0
  48. package/src/lib/app-utils/crm.js.map +1 -1
  49. package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
  50. package/src/lib/app-utils/cross-pool-desync.js +47 -0
  51. package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
  52. package/src/lib/app-utils/csv-upload.d.ts +29 -0
  53. package/src/lib/app-utils/csv-upload.js +29 -0
  54. package/src/lib/app-utils/csv-upload.js.map +1 -0
  55. package/src/lib/app-utils/{dataset-csv.d.ts → csv.d.ts} +10 -43
  56. package/src/lib/app-utils/{dataset-csv.js → csv.js} +10 -81
  57. package/src/lib/app-utils/csv.js.map +1 -0
  58. package/src/lib/app-utils/dataset-models.d.ts +5 -5
  59. package/src/lib/app-utils/dataset-models.js +19 -2
  60. package/src/lib/app-utils/dataset-models.js.map +1 -1
  61. package/src/lib/app-utils/datasets.d.ts +65 -30
  62. package/src/lib/app-utils/datasets.js +74 -24
  63. package/src/lib/app-utils/datasets.js.map +1 -1
  64. package/src/lib/app-utils/docs-deflection.d.ts +6 -6
  65. package/src/lib/app-utils/docs-deflection.js.map +1 -1
  66. package/src/lib/app-utils/docs-help.generated.d.ts +14 -8
  67. package/src/lib/app-utils/docs-help.generated.js +23 -6
  68. package/src/lib/app-utils/docs-help.generated.js.map +1 -1
  69. package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
  70. package/src/lib/app-utils/docs-index.generated.js +570 -346
  71. package/src/lib/app-utils/docs-index.generated.js.map +1 -1
  72. package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
  73. package/src/lib/app-utils/docs-retrieval.js +14 -10
  74. package/src/lib/app-utils/docs-retrieval.js.map +1 -1
  75. package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
  76. package/src/lib/app-utils/duplicate-resource.js +7 -4
  77. package/src/lib/app-utils/duplicate-resource.js.map +1 -1
  78. package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
  79. package/src/lib/app-utils/dynamic-list-rule.js +3 -3
  80. package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
  81. package/src/lib/app-utils/element-ui.d.ts +1 -1
  82. package/src/lib/app-utils/element-ui.js +1 -1
  83. package/src/lib/app-utils/element-ui.js.map +1 -1
  84. package/src/lib/app-utils/email-starter-policy.js +3 -3
  85. package/src/lib/app-utils/email-starter-policy.js.map +1 -1
  86. package/src/lib/app-utils/email-text.d.ts +80 -0
  87. package/src/lib/app-utils/email-text.js +189 -0
  88. package/src/lib/app-utils/email-text.js.map +1 -0
  89. package/src/lib/app-utils/{list-assignment-policy.d.ts → enrollment-basis.d.ts} +4 -0
  90. package/src/lib/app-utils/{list-assignment-policy.js → enrollment-basis.js} +5 -1
  91. package/src/lib/app-utils/enrollment-basis.js.map +1 -0
  92. package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
  93. package/src/lib/app-utils/entity-picker-context.js.map +1 -1
  94. package/src/lib/app-utils/error-beacon.d.ts +75 -6
  95. package/src/lib/app-utils/error-beacon.js +160 -21
  96. package/src/lib/app-utils/error-beacon.js.map +1 -1
  97. package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
  98. package/src/lib/app-utils/expand-repeatables.js +14 -14
  99. package/src/lib/app-utils/expand-repeatables.js.map +1 -1
  100. package/src/lib/app-utils/forms.js +2 -2
  101. package/src/lib/app-utils/forms.js.map +1 -1
  102. package/src/lib/app-utils/health-report.d.ts +2 -3
  103. package/src/lib/app-utils/health-report.js +8 -6
  104. package/src/lib/app-utils/health-report.js.map +1 -1
  105. package/src/lib/app-utils/host-events.d.ts +82 -0
  106. package/src/lib/app-utils/host-events.js +62 -0
  107. package/src/lib/app-utils/host-events.js.map +1 -0
  108. package/src/lib/app-utils/inbound-mail-domain.d.ts +27 -0
  109. package/src/lib/app-utils/inbound-mail-domain.js +31 -0
  110. package/src/lib/app-utils/inbound-mail-domain.js.map +1 -0
  111. package/src/lib/app-utils/lockdown.d.ts +11 -0
  112. package/src/lib/app-utils/lockdown.js +33 -3
  113. package/src/lib/app-utils/lockdown.js.map +1 -1
  114. package/src/lib/app-utils/margin-utilization.d.ts +4 -69
  115. package/src/lib/app-utils/margin-utilization.js +82 -69
  116. package/src/lib/app-utils/margin-utilization.js.map +1 -1
  117. package/src/lib/app-utils/member-email-aliases.d.ts +25 -0
  118. package/src/lib/app-utils/member-email-aliases.js +29 -0
  119. package/src/lib/app-utils/member-email-aliases.js.map +1 -1
  120. package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
  121. package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
  122. package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
  123. package/src/lib/app-utils/node-interactions.d.ts +7 -7
  124. package/src/lib/app-utils/node-interactions.js.map +1 -1
  125. package/src/lib/app-utils/notifications.d.ts +147 -47
  126. package/src/lib/app-utils/notifications.js +182 -44
  127. package/src/lib/app-utils/notifications.js.map +1 -1
  128. package/src/lib/app-utils/operator-alerts.d.ts +15 -1
  129. package/src/lib/app-utils/operator-alerts.js +47 -10
  130. package/src/lib/app-utils/operator-alerts.js.map +1 -1
  131. package/src/lib/app-utils/payments-configured.d.ts +8 -21
  132. package/src/lib/app-utils/payments-configured.js +8 -23
  133. package/src/lib/app-utils/payments-configured.js.map +1 -1
  134. package/src/lib/app-utils/plan-entitlements.d.ts +207 -306
  135. package/src/lib/app-utils/plan-entitlements.js +345 -528
  136. package/src/lib/app-utils/plan-entitlements.js.map +1 -1
  137. package/src/lib/app-utils/platform-brand.d.ts +10 -0
  138. package/src/lib/app-utils/platform-brand.js +14 -3
  139. package/src/lib/app-utils/platform-brand.js.map +1 -1
  140. package/src/lib/app-utils/platform-marketing-consent.d.ts +56 -2
  141. package/src/lib/app-utils/platform-marketing-consent.js +6 -5
  142. package/src/lib/app-utils/platform-marketing-consent.js.map +1 -1
  143. package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
  144. package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
  145. package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
  146. package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
  147. package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
  148. package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
  149. package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
  150. package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
  151. package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
  152. package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
  153. package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
  154. package/src/lib/app-utils/plugin-starter-templates.generated.d.ts +12 -0
  155. package/src/lib/app-utils/plugin-starter-templates.generated.js +711 -0
  156. package/src/lib/app-utils/plugin-starter-templates.generated.js.map +1 -0
  157. package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
  158. package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
  159. package/src/lib/app-utils/release-flags.d.ts +14 -5
  160. package/src/lib/app-utils/release-flags.js +21 -125
  161. package/src/lib/app-utils/release-flags.js.map +1 -1
  162. package/src/lib/app-utils/repeat-query.d.ts +56 -0
  163. package/src/lib/app-utils/{dataset-query.js → repeat-query.js} +16 -16
  164. package/src/lib/app-utils/repeat-query.js.map +1 -0
  165. package/src/lib/app-utils/repeat-sources.d.ts +9 -0
  166. package/src/lib/app-utils/repeat-sources.js.map +1 -1
  167. package/src/lib/app-utils/retained-refusals.d.ts +73 -0
  168. package/src/lib/app-utils/retained-refusals.js +186 -0
  169. package/src/lib/app-utils/retained-refusals.js.map +1 -0
  170. package/src/lib/app-utils/scope-tokens.d.ts +27 -0
  171. package/src/lib/app-utils/scope-tokens.js +61 -0
  172. package/src/lib/app-utils/scope-tokens.js.map +1 -1
  173. package/src/lib/app-utils/screen-link-context.js +3 -3
  174. package/src/lib/app-utils/screen-link-context.js.map +1 -1
  175. package/src/lib/app-utils/screen-route.js +1 -1
  176. package/src/lib/app-utils/screen-route.js.map +1 -1
  177. package/src/lib/app-utils/seo-audit.d.ts +132 -0
  178. package/src/lib/app-utils/seo-audit.js +246 -0
  179. package/src/lib/app-utils/seo-audit.js.map +1 -0
  180. package/src/lib/app-utils/seo-keywords.d.ts +48 -0
  181. package/src/lib/app-utils/seo-keywords.js +60 -0
  182. package/src/lib/app-utils/seo-keywords.js.map +1 -0
  183. package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
  184. package/src/lib/app-utils/seo-page-facts.js +155 -0
  185. package/src/lib/app-utils/seo-page-facts.js.map +1 -0
  186. package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
  187. package/src/lib/app-utils/seo-site-scan.js +162 -0
  188. package/src/lib/app-utils/seo-site-scan.js.map +1 -0
  189. package/src/lib/app-utils/seo-title-variables.js +1 -1
  190. package/src/lib/app-utils/seo-title-variables.js.map +1 -1
  191. package/src/lib/app-utils/server.d.ts +13 -18
  192. package/src/lib/app-utils/server.js +33 -51
  193. package/src/lib/app-utils/server.js.map +1 -1
  194. package/src/lib/app-utils/site-interactions.d.ts +501 -0
  195. package/src/lib/app-utils/site-interactions.js +554 -0
  196. package/src/lib/app-utils/site-interactions.js.map +1 -0
  197. package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
  198. package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +2 -2
  199. package/src/lib/app-utils/site-theme.js.map +1 -0
  200. package/src/lib/app-utils/sitemap.d.ts +4 -3
  201. package/src/lib/app-utils/sitemap.js +9 -7
  202. package/src/lib/app-utils/sitemap.js.map +1 -1
  203. package/src/lib/app-utils/stale-build-error.d.ts +51 -0
  204. package/src/lib/app-utils/stale-build-error.js +100 -1
  205. package/src/lib/app-utils/stale-build-error.js.map +1 -1
  206. package/src/lib/app-utils/starter-template-nodes.d.ts +137 -0
  207. package/src/lib/app-utils/starter-template-nodes.js +129 -0
  208. package/src/lib/app-utils/starter-template-nodes.js.map +1 -0
  209. package/src/lib/app-utils/starter-templates.d.ts +11 -34
  210. package/src/lib/app-utils/starter-templates.js +19 -230
  211. package/src/lib/app-utils/starter-templates.js.map +1 -1
  212. package/src/lib/app-utils/{email-topics.d.ts → subscription-topics.d.ts} +64 -48
  213. package/src/lib/app-utils/{email-topics.js → subscription-topics.js} +39 -109
  214. package/src/lib/app-utils/subscription-topics.js.map +1 -0
  215. package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
  216. package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
  217. package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
  218. package/src/lib/app-utils/theme-library.d.ts +10 -3
  219. package/src/lib/app-utils/theme-library.js +13 -4
  220. package/src/lib/app-utils/theme-library.js.map +1 -1
  221. package/src/lib/app-utils/usage-budget.d.ts +73 -188
  222. package/src/lib/app-utils/usage-budget.js +58 -194
  223. package/src/lib/app-utils/usage-budget.js.map +1 -1
  224. package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
  225. package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
  226. package/src/lib/app-utils/utm-attribution.js.map +1 -0
  227. package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
  228. package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
  229. package/src/lib/app-utils/utm-forwarding.js.map +1 -0
  230. package/src/lib/app-utils/{campaign-touch.d.ts → utm-touch.d.ts} +25 -17
  231. package/src/lib/app-utils/{campaign-touch.js → utm-touch.js} +38 -30
  232. package/src/lib/app-utils/utm-touch.js.map +1 -0
  233. package/src/lib/app-utils/variables.d.ts +9 -9
  234. package/src/lib/app-utils/variables.js.map +1 -1
  235. package/src/lib/app-utils/video-object.js +6 -5
  236. package/src/lib/app-utils/video-object.js.map +1 -1
  237. package/src/lib/app-utils/visitor-consent.d.ts +41 -164
  238. package/src/lib/app-utils/visitor-consent.js +66 -277
  239. package/src/lib/app-utils/visitor-consent.js.map +1 -1
  240. package/src/lib/app-utils/visitor-record-ceiling.d.ts +32 -0
  241. package/src/lib/app-utils/visitor-record-ceiling.js +39 -0
  242. package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
  243. package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
  244. package/src/lib/app-utils/web-vitals-rum.js +31 -63
  245. package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
  246. package/src/lib/app-utils/where-used.d.ts +11 -6
  247. package/src/lib/app-utils/where-used.js +3 -8
  248. package/src/lib/app-utils/where-used.js.map +1 -1
  249. package/src/lib/foundation/definitions/components.types.d.ts +1 -1
  250. package/src/lib/foundation/definitions/components.types.js +1 -1
  251. package/src/lib/foundation/definitions/components.types.js.map +1 -1
  252. package/src/lib/foundation/definitions/org-billing.types.d.ts +11 -137
  253. package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
  254. package/src/lib/foundation/definitions/organization.types.d.ts +1 -3
  255. package/src/lib/foundation/definitions/organization.types.js.map +1 -1
  256. package/src/lib/foundation/definitions/platform.types.d.ts +11 -5
  257. package/src/lib/foundation/definitions/platform.types.js.map +1 -1
  258. package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
  259. package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
  260. package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
  261. package/src/lib/foundation/index.d.ts +1 -1
  262. package/src/lib/foundation/index.js.map +1 -1
  263. package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
  264. package/src/lib/plugin-manager/besigner-documents.js +61 -0
  265. package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
  266. package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
  267. package/src/lib/plugin-manager/computed-variables.js +74 -0
  268. package/src/lib/plugin-manager/computed-variables.js.map +1 -0
  269. package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
  270. package/src/lib/plugin-manager/custom-fields.js +47 -1
  271. package/src/lib/plugin-manager/custom-fields.js.map +1 -1
  272. package/src/lib/plugin-manager/feature-plugins.d.ts +372 -99
  273. package/src/lib/plugin-manager/feature-plugins.js +126 -51
  274. package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
  275. package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +134 -0
  276. package/src/lib/plugin-manager/first-party-plugins.generated.js +840 -10
  277. package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
  278. package/src/lib/plugin-manager/index.d.ts +0 -1
  279. package/src/lib/plugin-manager/index.js +0 -1
  280. package/src/lib/plugin-manager/index.js.map +1 -1
  281. package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
  282. package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
  283. package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
  284. package/src/lib/plugin-manager/plugin-contact-capture.d.ts +9 -4
  285. package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
  286. package/src/lib/plugin-manager/plugin-containers.d.ts +68 -0
  287. package/src/lib/plugin-manager/plugin-containers.generated.d.ts +10 -0
  288. package/src/lib/plugin-manager/plugin-containers.generated.js +20 -0
  289. package/src/lib/plugin-manager/plugin-containers.generated.js.map +1 -0
  290. package/src/lib/plugin-manager/plugin-containers.js +27 -0
  291. package/src/lib/plugin-manager/plugin-containers.js.map +1 -0
  292. package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
  293. package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
  294. package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
  295. package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
  296. package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
  297. package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
  298. package/src/lib/plugin-manager/plugin-dependents.js +75 -0
  299. package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
  300. package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
  301. package/src/lib/plugin-manager/plugin-distribution.js +45 -0
  302. package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
  303. package/src/lib/plugin-manager/plugin-entitlements.d.ts +8 -0
  304. package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -1
  305. package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
  306. package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
  307. package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
  308. package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
  309. package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
  310. package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
  311. package/src/lib/plugin-manager/plugin-membership-detach.js +1 -1
  312. package/src/lib/plugin-manager/plugin-membership-detach.js.map +1 -1
  313. package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
  314. package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
  315. package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
  316. package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
  317. package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
  318. package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
  319. package/src/lib/plugin-manager/plugin-record-email-state.d.ts +69 -0
  320. package/src/lib/plugin-manager/plugin-record-email-state.js +32 -0
  321. package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
  322. package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
  323. package/src/lib/plugin-manager/plugin-record-index.js +51 -0
  324. package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
  325. package/src/lib/plugin-manager/plugin-record-lists.d.ts +115 -0
  326. package/src/lib/plugin-manager/plugin-record-lists.js +75 -0
  327. package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -0
  328. package/src/lib/plugin-manager/plugin-record-timeline.d.ts +42 -8
  329. package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
  330. package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
  331. package/src/lib/plugin-manager/plugin-record-written.js +42 -0
  332. package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
  333. package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
  334. package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
  335. package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
  336. package/src/lib/plugin-manager/plugin-site-beacons.d.ts +71 -0
  337. package/src/lib/plugin-manager/plugin-site-beacons.js +54 -0
  338. package/src/lib/plugin-manager/plugin-site-beacons.js.map +1 -0
  339. package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
  340. package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
  341. package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
  342. package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
  343. package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
  344. package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
  345. package/src/lib/plugin-manager/plugin-site-export.js +40 -0
  346. package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
  347. package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
  348. package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
  349. package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
  350. package/src/lib/plugin-manager/plugin-subscription-topics.generated.d.ts +11 -0
  351. package/src/lib/plugin-manager/plugin-subscription-topics.generated.js +41 -0
  352. package/src/lib/plugin-manager/plugin-subscription-topics.generated.js.map +1 -0
  353. package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
  354. package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
  355. package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
  356. package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
  357. package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
  358. package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
  359. package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
  360. package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
  361. package/src/lib/plugin-manager/plugin-usage-axes.d.ts +319 -0
  362. package/src/lib/plugin-manager/plugin-usage-axes.js +186 -0
  363. package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
  364. package/src/lib/plugin-manager/plugin-usage-meters.d.ts +108 -0
  365. package/src/lib/plugin-manager/plugin-usage-meters.js +105 -0
  366. package/src/lib/plugin-manager/plugin-usage-meters.js.map +1 -0
  367. package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
  368. package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
  369. package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
  370. package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
  371. package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
  372. package/src/lib/plugin-manager/record-captured-contact.js +10 -32
  373. package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
  374. package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
  375. package/src/lib/plugin-manager/repeat-rows.js +108 -0
  376. package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
  377. package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
  378. package/src/lib/plugin-manager/submission-record-target.js +125 -0
  379. package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
  380. package/src/lib/plugin-manager/usage-alert-contributors.d.ts +76 -6
  381. package/src/lib/plugin-manager/usage-alert-contributors.js +23 -10
  382. package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -1
  383. package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
  384. package/src/lib/plugin-manager/video-embed-provider.js +165 -0
  385. package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
  386. package/src/lib/types/nodes.d.ts +2 -2
  387. package/src/lib/types/nodes.js.map +1 -1
  388. package/src/lib/app-utils/assist-credits.d.ts +0 -482
  389. package/src/lib/app-utils/assist-credits.js +0 -509
  390. package/src/lib/app-utils/assist-credits.js.map +0 -1
  391. package/src/lib/app-utils/campaign-attribution.js.map +0 -1
  392. package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
  393. package/src/lib/app-utils/campaign-membership.d.ts +0 -121
  394. package/src/lib/app-utils/campaign-membership.js +0 -189
  395. package/src/lib/app-utils/campaign-membership.js.map +0 -1
  396. package/src/lib/app-utils/campaign-touch.js.map +0 -1
  397. package/src/lib/app-utils/console-record-links.d.ts +0 -163
  398. package/src/lib/app-utils/console-record-links.js +0 -180
  399. package/src/lib/app-utils/console-record-links.js.map +0 -1
  400. package/src/lib/app-utils/contact-holder.d.ts +0 -68
  401. package/src/lib/app-utils/contact-holder.js +0 -129
  402. package/src/lib/app-utils/contact-holder.js.map +0 -1
  403. package/src/lib/app-utils/contact-merge.d.ts +0 -136
  404. package/src/lib/app-utils/contact-merge.js +0 -412
  405. package/src/lib/app-utils/contact-merge.js.map +0 -1
  406. package/src/lib/app-utils/crm-booking.d.ts +0 -75
  407. package/src/lib/app-utils/crm-booking.js +0 -133
  408. package/src/lib/app-utils/crm-booking.js.map +0 -1
  409. package/src/lib/app-utils/crm-csv.d.ts +0 -239
  410. package/src/lib/app-utils/crm-csv.js +0 -467
  411. package/src/lib/app-utils/crm-csv.js.map +0 -1
  412. package/src/lib/app-utils/crm-digest.d.ts +0 -185
  413. package/src/lib/app-utils/crm-digest.js +0 -272
  414. package/src/lib/app-utils/crm-digest.js.map +0 -1
  415. package/src/lib/app-utils/crm-inbound.d.ts +0 -245
  416. package/src/lib/app-utils/crm-inbound.js +0 -407
  417. package/src/lib/app-utils/crm-inbound.js.map +0 -1
  418. package/src/lib/app-utils/crm-reports.d.ts +0 -479
  419. package/src/lib/app-utils/crm-reports.js +0 -680
  420. package/src/lib/app-utils/crm-reports.js.map +0 -1
  421. package/src/lib/app-utils/dataset-csv.js.map +0 -1
  422. package/src/lib/app-utils/dataset-query.d.ts +0 -57
  423. package/src/lib/app-utils/dataset-query.js.map +0 -1
  424. package/src/lib/app-utils/email-topics.js.map +0 -1
  425. package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
  426. package/src/lib/app-utils/form-dataset-binding.js +0 -74
  427. package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
  428. package/src/lib/app-utils/list-assignment-policy.js.map +0 -1
  429. package/src/lib/app-utils/list-import.d.ts +0 -158
  430. package/src/lib/app-utils/list-import.js +0 -332
  431. package/src/lib/app-utils/list-import.js.map +0 -1
  432. package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
  433. package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
  434. package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
  435. package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
  436. package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
  437. package/src/lib/app-utils/marketplace-theme.js.map +0 -1
  438. package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
  439. package/src/lib/app-utils/marketplace-update-state.js +0 -132
  440. package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
  441. package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
  442. package/src/lib/app-utils/publisher-agreement.js +0 -321
  443. package/src/lib/app-utils/publisher-agreement.js.map +0 -1
  444. package/src/lib/app-utils/wistia-embed.d.ts +0 -104
  445. package/src/lib/app-utils/wistia-embed.js +0 -138
  446. package/src/lib/app-utils/wistia-embed.js.map +0 -1
  447. package/src/lib/app-utils/workflows.d.ts +0 -136
  448. package/src/lib/app-utils/workflows.js +0 -346
  449. package/src/lib/app-utils/workflows.js.map +0 -1
  450. package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
  451. package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
  452. package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
  453. package/src/lib/plugin-manager/plugin-metered-lines.d.ts +0 -97
  454. package/src/lib/plugin-manager/plugin-metered-lines.js +0 -123
  455. package/src/lib/plugin-manager/plugin-metered-lines.js.map +0 -1
@@ -1,412 +0,0 @@
1
- import { _ as _extends } from "@swc/helpers/_/_extends";
2
- /**
3
- * @license
4
- * Copyright 2026 Aglyn LLC
5
- *
6
- * Licensed under the Apache License, Version 2.0 (the "License");
7
- * you may not use this file except in compliance with the License.
8
- * You may obtain a copy of the License at
9
- *
10
- * http://www.apache.org/licenses/LICENSE-2.0
11
- *
12
- * Unless required by applicable law or agreed to in writing, software
13
- * distributed under the License is distributed on an "AS IS" BASIS,
14
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- * See the License for the specific language governing permissions and
16
- * limitations under the License.
17
- */ /**
18
- * MERGING TWO CONTACT DOCUMENTS INTO ONE (AGL-2625) — the pure half.
19
- *
20
- * Contacts are keyed by email, so exact duplicates cannot exist; one human
21
- * with `jane@acme.com` and `jane@gmail.com` is two documents, with tags,
22
- * deals, tasks and a timeline split between them. A merge folds the second
23
- * into the first: the SURVIVOR keeps its address as the identity, the MERGED
24
- * record's address becomes an alternate on it, and every field is combined
25
- * by one rule the dialog can show before the write happens.
26
- *
27
- * ## The rule
28
- *
29
- * - A scalar — a name, a phone, a title, a stage, an owner — is the
30
- * survivor's where the survivor has one, and fills from the merged record
31
- * where the survivor is empty. Nothing the survivor holds is overwritten.
32
- * - A list — tags, campaign filings, the timeline, the sites that captured
33
- * the person, the forms, the companies — is the UNION, deduplicated and
34
- * bounded where the write paths bound it.
35
- * - A figure that counts something — orders, lifetime value, refunds — is
36
- * the SUM: two records of one person's purchases are one person's
37
- * purchases. A "first" is the earlier, a "last" is the later.
38
- * - Notes are appended, survivor first: a note is a list of sentences, and
39
- * dropping the merged record's would be the one silent loss in a merge
40
- * that is otherwise lossless.
41
- * - A recorded REFUSAL of marketing mail on either record stands on the
42
- * survivor. The merge asserts the two are one person, and that person
43
- * said no.
44
- *
45
- * Applied per holder: each group's facet on the merged record is folded
46
- * into the same group's facet on the survivor, and a group only the merged
47
- * record had comes across whole. No holder's records reach another holder's
48
- * facet, which is the guarantee the facet shape exists for.
49
- *
50
- * ## Why this is a plan and not a write
51
- *
52
- * The console shows the two records side by side and says which value wins
53
- * before anything is committed; the server performs the write. Both read
54
- * this function, so the preview cannot show one outcome and the write land
55
- * another. The plan is plain values — no sentinels — so it can be rendered,
56
- * and it is shaped for a merge-`set`, which deep-merges the facet map one
57
- * holder at a time and replaces an array whole: exactly the two behaviors
58
- * the rule above needs.
59
- */ import { CONTACT_ALTERNATE_EMAILS_CAP, CONTACT_ALTERNATE_EMAILS_FIELD, CONTACT_FACETS_FIELD, CONTACT_FORM_IDS_CAP, CONTACT_FORM_IDS_FIELD, CONTACT_INTERACTIONS_CAP, contactDisplayName, contactEmails, normalizeContactEmail, readContactFacet } from "./contacts.js";
60
- import { CONTACT_COMPANY_IDS_FIELD, CONTACT_LIFECYCLE_STAGE_LABELS } from "./crm.js";
61
- import { MARKETING_CONSENT_BY_HOST_FIELD, MARKETING_CONSENT_FIELD } from "./marketing-consent.js";
62
- import { nameSearchFields } from "./name-search.js";
63
- /** The tags cap every writer applies, so a union cannot exceed it. */ const TAGS_CAP = 20;
64
- /** The notes cap the record page applies to its About box. */ const NOTES_CAP = 5000;
65
- /** Facet figures that add up: two records of one buyer are one buyer. */ const SUM_FIELDS = [
66
- 'ltvCents',
67
- 'ordersCount',
68
- 'refundedCents',
69
- 'refundedOrdersCount'
70
- ];
71
- /** Facet instants where the later one is the truth. */ const LATEST_FIELDS = [
72
- 'lastPurchaseAtMs',
73
- 'lastRefundAtMs',
74
- 'lastEmailEngagementAtMs'
75
- ];
76
- /** Facet instants where the earlier one is the truth. */ const EARLIEST_FIELDS = [
77
- 'firstPurchaseAtMs'
78
- ];
79
- /** Whether a value counts as "nothing here" for the fill rule. */ function isEmpty(value) {
80
- if (value === undefined || value === null) return true;
81
- if (typeof value === 'string') return value.trim() === '';
82
- if (Array.isArray(value)) return value.length === 0;
83
- if (typeof value === 'object') return Object.keys(value).length === 0;
84
- return false;
85
- }
86
- function text(value) {
87
- return typeof value === 'string' ? value : '';
88
- }
89
- function strings(value) {
90
- return Array.isArray(value) ? value.filter((item)=>typeof item === 'string' && item !== '') : [];
91
- }
92
- function number(value) {
93
- return typeof value === 'number' && Number.isFinite(value) ? value : null;
94
- }
95
- /** The union of two string lists, first list's order first, deduplicated. */ function union(a, b, cap = Number.POSITIVE_INFINITY) {
96
- return [
97
- ...new Set([
98
- ...strings(a),
99
- ...strings(b)
100
- ])
101
- ].slice(0, cap);
102
- }
103
- /** Survivor's value where it has one, the merged record's otherwise. */ function fill(survivor, merged) {
104
- return isEmpty(survivor) ? merged : survivor;
105
- }
106
- /** Notes appended, survivor first, one blank line between, bounded. */ function joinNotes(survivor, merged) {
107
- const a = text(survivor).trim();
108
- const b = text(merged).trim();
109
- if (!b || a === b) return a;
110
- if (!a) return b;
111
- return `${a}\n\n${b}`.slice(0, NOTES_CAP);
112
- }
113
- /** What makes two timeline entries the same event. */ function interactionKey(entry) {
114
- var _entry_refId, _entry_hostId;
115
- return [
116
- entry.type,
117
- (_entry_refId = entry.refId) != null ? _entry_refId : '',
118
- entry.atMs,
119
- (_entry_hostId = entry.hostId) != null ? _entry_hostId : ''
120
- ].join('|');
121
- }
122
- /**
123
- * Both timelines as one: deduplicated by event, newest first, and capped
124
- * the way every capture caps it — so a merge of two full timelines keeps
125
- * the fifty most recent visits rather than growing the document past what
126
- * a capture may write.
127
- */ export function mergeInteractions(survivor, merged) {
128
- const seen = new Set();
129
- const out = [];
130
- for (const entry of [
131
- ...survivor != null ? survivor : [],
132
- ...merged != null ? merged : []
133
- ]){
134
- if (!entry || typeof entry !== 'object') continue;
135
- const key = interactionKey(entry);
136
- if (seen.has(key)) continue;
137
- seen.add(key);
138
- out.push(entry);
139
- }
140
- return out.sort((a, b)=>{
141
- var _number, _number1;
142
- return ((_number = number(b.atMs)) != null ? _number : 0) - ((_number1 = number(a.atMs)) != null ? _number1 : 0);
143
- }).slice(0, CONTACT_INTERACTIONS_CAP);
144
- }
145
- /** The custom values per key: the survivor's where set, the merged record's otherwise. */ function mergeCustom(survivor, merged) {
146
- const a = survivor && typeof survivor === 'object' ? survivor : {};
147
- const b = merged && typeof merged === 'object' ? merged : {};
148
- const out = _extends({}, b);
149
- for (const [key, value] of Object.entries(a)){
150
- if (!isEmpty(value) || !(key in b)) out[key] = value;
151
- }
152
- return out;
153
- }
154
- /**
155
- * One holder's facet after the merge.
156
- *
157
- * `survivor` is that holder's facet on the surviving record — possibly
158
- * absent, when only the merged record was held by this group — and `merged`
159
- * the same holder's facet on the record being folded in.
160
- */ export function mergeContactFacet(survivor, merged) {
161
- var _b_sources, _a_sources;
162
- if (!merged) return _extends({}, survivor != null ? survivor : {});
163
- if (!survivor) return _extends({}, merged);
164
- const out = _extends({}, merged);
165
- // Every scalar the survivor holds stands; every one it lacks fills.
166
- for (const [key, value] of Object.entries(survivor)){
167
- out[key] = fill(value, merged[key]);
168
- }
169
- const a = survivor;
170
- const b = merged;
171
- out['sources'] = _extends({}, (_b_sources = b.sources) != null ? _b_sources : {}, (_a_sources = a.sources) != null ? _a_sources : {});
172
- out['interactions'] = mergeInteractions(a.interactions, b.interactions);
173
- const tags = union(a.tags, b.tags, TAGS_CAP);
174
- if (tags.length) out['tags'] = tags;
175
- const campaignIds = union(a.campaignIds, b.campaignIds);
176
- if (campaignIds.length) out['campaignIds'] = campaignIds;
177
- const notes = joinNotes(a.notes, b.notes);
178
- if (notes) out['notes'] = notes;
179
- if (!isEmpty(a.custom) || !isEmpty(b.custom)) {
180
- out['custom'] = mergeCustom(a.custom, b.custom);
181
- }
182
- for (const field of SUM_FIELDS){
183
- const left = number(a[field]);
184
- const right = number(b[field]);
185
- if (left !== null || right !== null) out[field] = (left != null ? left : 0) + (right != null ? right : 0);
186
- }
187
- for (const field of LATEST_FIELDS){
188
- const left = number(a[field]);
189
- const right = number(b[field]);
190
- if (left !== null || right !== null) {
191
- out[field] = Math.max(left != null ? left : 0, right != null ? right : 0);
192
- }
193
- }
194
- for (const field of EARLIEST_FIELDS){
195
- const left = number(a[field]);
196
- const right = number(b[field]);
197
- if (left !== null && right !== null) out[field] = Math.min(left, right);
198
- else if (left !== null || right !== null) out[field] = left != null ? left : right;
199
- }
200
- return out;
201
- }
202
- function facetsOf(doc) {
203
- const facets = doc[CONTACT_FACETS_FIELD];
204
- return facets && typeof facets === 'object' && !Array.isArray(facets) ? facets : {};
205
- }
206
- function mapOf(value) {
207
- return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
208
- }
209
- /**
210
- * A refusal one record holds for a site, written over the other record's grant
211
- * for the same site (AGL-3320).
212
- *
213
- * The refusal outranks the grant, as it does when one person's refusal and
214
- * grant sit on two sites of one group: two records of one person who said no
215
- * to a site are a person who said no to it, and a merge that kept the grant
216
- * would start mailing them. The grant is kept beside it as `supersededEntry`,
217
- * so what the survivor held is still on the record.
218
- *
219
- * The merge is written with a merging `set`, which keeps every field of the
220
- * survivor's entry it does not name — so the grant's own fields are named
221
- * here, empty, or the refusal would read as carrying the grant's disclosure
222
- * and whoever recorded it.
223
- */ function refusalOver(refusal, grant) {
224
- const entry = _extends({}, refusal, {
225
- supersededEntry: grant
226
- });
227
- for (const key of Object.keys(grant)){
228
- if (!(key in entry)) entry[key] = null;
229
- }
230
- return entry;
231
- }
232
- /**
233
- * The plan for folding `merged` into `survivor`.
234
- *
235
- * Both are the stored documents as read. The survivor's `email` is the
236
- * identity that stands; the merged record's becomes an alternate.
237
- */ export function planContactMerge(survivor, merged) {
238
- var _normalizeContactEmail;
239
- const survivorEmail = (_normalizeContactEmail = normalizeContactEmail(survivor['email'])) != null ? _normalizeContactEmail : '';
240
- const mergedEmails = contactEmails(merged);
241
- const alternates = [
242
- ...new Set([
243
- ...strings(survivor[CONTACT_ALTERNATE_EMAILS_FIELD]),
244
- ...mergedEmails
245
- ])
246
- ].filter((email)=>email !== survivorEmail).slice(0, CONTACT_ALTERNATE_EMAILS_CAP);
247
- const out = {
248
- [CONTACT_ALTERNATE_EMAILS_FIELD]: alternates
249
- };
250
- // The canonical name, with its search keys, only when the survivor had none.
251
- const survivorName = text(survivor['name']).trim();
252
- const mergedName = text(merged['name']).trim();
253
- if (!survivorName && mergedName) Object.assign(out, nameSearchFields(mergedName));
254
- // The search echoes, on the same fill rule.
255
- for (const key of [
256
- 'phone',
257
- 'companyName'
258
- ]){
259
- if (isEmpty(survivor[key]) && !isEmpty(merged[key])) out[key] = merged[key];
260
- }
261
- // The shared lists: who may read the row, who captured it, which forms and
262
- // companies it is filed under.
263
- const visibleTo = union(survivor['visibleTo'], merged['visibleTo']);
264
- out['visibleTo'] = visibleTo;
265
- const capturedBy = union(survivor['capturedByHostIds'], merged['capturedByHostIds']);
266
- if (capturedBy.length) out['capturedByHostIds'] = capturedBy;
267
- const formIds = union(survivor[CONTACT_FORM_IDS_FIELD], merged[CONTACT_FORM_IDS_FIELD], CONTACT_FORM_IDS_CAP);
268
- if (formIds.length) out[CONTACT_FORM_IDS_FIELD] = formIds;
269
- const survivorCompanies = strings(survivor[CONTACT_COMPANY_IDS_FIELD]);
270
- const mergedCompanies = strings(merged[CONTACT_COMPANY_IDS_FIELD]);
271
- const companyIds = [
272
- ...new Set([
273
- ...survivorCompanies,
274
- ...mergedCompanies
275
- ])
276
- ];
277
- if (companyIds.length) out[CONTACT_COMPANY_IDS_FIELD] = companyIds;
278
- const companyCounts = survivorCompanies.filter((id)=>mergedCompanies.includes(id)).map((companyId)=>({
279
- companyId,
280
- delta: -1
281
- }));
282
- // The organization-level fields the REST API reads and writes.
283
- const tags = union(survivor['tags'], merged['tags']);
284
- if (tags.length) out['tags'] = tags;
285
- const notes = joinNotes(survivor['notes'], merged['notes']);
286
- if (notes) out['notes'] = notes;
287
- if (!isEmpty(survivor['custom']) || !isEmpty(merged['custom'])) {
288
- out['custom'] = mergeCustom(survivor['custom'], merged['custom']);
289
- }
290
- // Consent: a grant fills where the survivor has none for that site, and a
291
- // refusal on either record stands — per site as well as unscoped (AGL-3320).
292
- const survivorConsent = mapOf(survivor[MARKETING_CONSENT_BY_HOST_FIELD]);
293
- const mergedConsent = mapOf(merged[MARKETING_CONSENT_BY_HOST_FIELD]);
294
- const consentByHost = _extends({}, mergedConsent, survivorConsent);
295
- for (const [hostId, value] of Object.entries(mergedConsent)){
296
- const refusal = mapOf(value);
297
- if (refusal[MARKETING_CONSENT_FIELD] !== false) continue;
298
- if (!(hostId in survivorConsent)) continue;
299
- const standing = mapOf(survivorConsent[hostId]);
300
- if (standing[MARKETING_CONSENT_FIELD] === false) continue;
301
- consentByHost[hostId] = refusalOver(refusal, standing);
302
- }
303
- if (Object.keys(consentByHost).length) {
304
- out[MARKETING_CONSENT_BY_HOST_FIELD] = consentByHost;
305
- }
306
- if (survivor['marketingConsent'] === false || merged['marketingConsent'] === false) {
307
- out['marketingConsent'] = false;
308
- } else if (survivor['marketingConsent'] === true || merged['marketingConsent'] === true) {
309
- out['marketingConsent'] = true;
310
- }
311
- // Each holder's facet — only the groups the merged record held need a write.
312
- const survivorFacets = facetsOf(survivor);
313
- const mergedFacets = facetsOf(merged);
314
- const facets = {};
315
- for (const [groupId, facet] of Object.entries(mergedFacets)){
316
- facets[groupId] = mergeContactFacet(survivorFacets[groupId], facet);
317
- }
318
- if (Object.keys(facets).length) out[CONTACT_FACETS_FIELD] = facets;
319
- return {
320
- survivor: out,
321
- emails: [
322
- survivorEmail,
323
- ...alternates
324
- ].filter(Boolean),
325
- mergedEmails,
326
- companyCounts,
327
- visibleTo
328
- };
329
- }
330
- function addressLine(value) {
331
- const address = mapOf(value);
332
- return [
333
- 'line1',
334
- 'line2',
335
- 'city',
336
- 'state',
337
- 'postalCode',
338
- 'country'
339
- ].map((key)=>text(address[key]).trim()).filter(Boolean).join(', ');
340
- }
341
- function sourceOf(survivor, merged, result) {
342
- if (!result) return 'none';
343
- if (survivor && merged && survivor !== merged && result !== survivor && result !== merged) {
344
- return 'both';
345
- }
346
- if (result === survivor && survivor === merged) return 'both';
347
- return result === survivor ? 'survivor' : 'merged';
348
- }
349
- /**
350
- * The merge as the viewing group would see it, field by field.
351
- *
352
- * Reads through ONE group's facet, the way the record page does, so a
353
- * holder previewing a merge sees its own values and never another holder's.
354
- * Every row carries the survivor's value, the merged record's, and the
355
- * result the plan would write, so the dialog is a rendering and not a second
356
- * opinion.
357
- */ export function contactMergePreview(survivor, merged, groupId, options = {}) {
358
- var _options_memberName;
359
- const plan = planContactMerge(survivor, merged);
360
- const after = _extends({}, survivor, plan.survivor, {
361
- [CONTACT_FACETS_FIELD]: _extends({}, facetsOf(survivor), mapOf(plan.survivor[CONTACT_FACETS_FIELD]))
362
- });
363
- const a = readContactFacet(survivor, groupId);
364
- const b = readContactFacet(merged, groupId);
365
- const c = readContactFacet(after, groupId);
366
- const memberName = (_options_memberName = options.memberName) != null ? _options_memberName : (uid)=>uid;
367
- const stage = (value)=>typeof value === 'string' && value in CONTACT_LIFECYCLE_STAGE_LABELS ? CONTACT_LIFECYCLE_STAGE_LABELS[value] : '';
368
- const owner = (value)=>text(value) ? memberName(text(value)) : '';
369
- const list = (value)=>strings(value).join(', ');
370
- const money = (facet)=>{
371
- var _facet_ltvCents;
372
- return facet.ordersCount ? `${facet.ordersCount} · $${(((_facet_ltvCents = facet.ltvCents) != null ? _facet_ltvCents : 0) / 100).toFixed(2)}` : '';
373
- };
374
- const row = (key, label, left, right, result)=>({
375
- key,
376
- label,
377
- survivor: left,
378
- merged: right,
379
- result,
380
- from: sourceOf(left, right, result)
381
- });
382
- const rows = [
383
- row('name', 'Name', contactDisplayName(survivor, groupId), contactDisplayName(merged, groupId), contactDisplayName(after, groupId)),
384
- row('email', 'Email', contactEmails(survivor).join(', '), contactEmails(merged).join(', '), plan.emails.join(', ')),
385
- row('phone', 'Phone', text(a.phone), text(b.phone), text(c.phone)),
386
- row('jobTitle', 'Job title', text(a.jobTitle), text(b.jobTitle), text(c.jobTitle)),
387
- row('company', 'Company', text(a.companyName), text(b.companyName), text(c.companyName)),
388
- row('lifecycleStage', 'Stage', stage(a.lifecycleStage), stage(b.lifecycleStage), stage(c.lifecycleStage)),
389
- row('owner', 'Owner', owner(a.ownerUid), owner(b.ownerUid), owner(c.ownerUid)),
390
- row('tags', 'Tags', list(a.tags), list(b.tags), list(c.tags)),
391
- row('notes', 'Notes', text(a.notes), text(b.notes), text(c.notes)),
392
- row('address', 'Address', addressLine(a.address), addressLine(b.address), addressLine(c.address)),
393
- row('orders', 'Orders', money(a), money(b), money(c)),
394
- row('timeline', 'Timeline entries', a.interactions.length ? String(a.interactions.length) : '', b.interactions.length ? String(b.interactions.length) : '', c.interactions.length ? String(c.interactions.length) : '')
395
- ];
396
- const customKeys = [
397
- ...new Set([
398
- ...Object.keys(mapOf(a.custom)),
399
- ...Object.keys(mapOf(b.custom))
400
- ])
401
- ].sort();
402
- for (const key of customKeys){
403
- const show = (facet)=>{
404
- const value = mapOf(facet.custom)[key];
405
- return value === null || value === undefined ? '' : String(value);
406
- };
407
- rows.push(row(`custom.${key}`, key, show(a), show(b), show(c)));
408
- }
409
- return rows;
410
- }
411
-
412
- //# sourceMappingURL=contact-merge.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/contact-merge.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 * MERGING TWO CONTACT DOCUMENTS INTO ONE (AGL-2625) — the pure half.\n *\n * Contacts are keyed by email, so exact duplicates cannot exist; one human\n * with `jane@acme.com` and `jane@gmail.com` is two documents, with tags,\n * deals, tasks and a timeline split between them. A merge folds the second\n * into the first: the SURVIVOR keeps its address as the identity, the MERGED\n * record's address becomes an alternate on it, and every field is combined\n * by one rule the dialog can show before the write happens.\n *\n * ## The rule\n *\n * - A scalar — a name, a phone, a title, a stage, an owner — is the\n * survivor's where the survivor has one, and fills from the merged record\n * where the survivor is empty. Nothing the survivor holds is overwritten.\n * - A list — tags, campaign filings, the timeline, the sites that captured\n * the person, the forms, the companies — is the UNION, deduplicated and\n * bounded where the write paths bound it.\n * - A figure that counts something — orders, lifetime value, refunds — is\n * the SUM: two records of one person's purchases are one person's\n * purchases. A \"first\" is the earlier, a \"last\" is the later.\n * - Notes are appended, survivor first: a note is a list of sentences, and\n * dropping the merged record's would be the one silent loss in a merge\n * that is otherwise lossless.\n * - A recorded REFUSAL of marketing mail on either record stands on the\n * survivor. The merge asserts the two are one person, and that person\n * said no.\n *\n * Applied per holder: each group's facet on the merged record is folded\n * into the same group's facet on the survivor, and a group only the merged\n * record had comes across whole. No holder's records reach another holder's\n * facet, which is the guarantee the facet shape exists for.\n *\n * ## Why this is a plan and not a write\n *\n * The console shows the two records side by side and says which value wins\n * before anything is committed; the server performs the write. Both read\n * this function, so the preview cannot show one outcome and the write land\n * another. The plan is plain values — no sentinels — so it can be rendered,\n * and it is shaped for a merge-`set`, which deep-merges the facet map one\n * holder at a time and replaces an array whole: exactly the two behaviors\n * the rule above needs.\n */\n\nimport {\n CONTACT_ALTERNATE_EMAILS_CAP,\n CONTACT_ALTERNATE_EMAILS_FIELD,\n CONTACT_FACETS_FIELD,\n CONTACT_FORM_IDS_CAP,\n CONTACT_FORM_IDS_FIELD,\n CONTACT_INTERACTIONS_CAP,\n type ContactFacet,\n type ContactInteraction,\n contactDisplayName,\n contactEmails,\n normalizeContactEmail,\n readContactFacet,\n} from './contacts'\nimport { CONTACT_COMPANY_IDS_FIELD, CONTACT_LIFECYCLE_STAGE_LABELS } from './crm'\nimport {\n MARKETING_CONSENT_BY_HOST_FIELD,\n MARKETING_CONSENT_FIELD,\n} from './marketing-consent'\nimport { nameSearchFields } from './name-search'\n\n/** The tags cap every writer applies, so a union cannot exceed it. */\nconst TAGS_CAP = 20\n/** The notes cap the record page applies to its About box. */\nconst NOTES_CAP = 5000\n\n/** Facet figures that add up: two records of one buyer are one buyer. */\nconst SUM_FIELDS = [\n 'ltvCents',\n 'ordersCount',\n 'refundedCents',\n 'refundedOrdersCount',\n] as const\n/** Facet instants where the later one is the truth. */\nconst LATEST_FIELDS = [\n 'lastPurchaseAtMs',\n 'lastRefundAtMs',\n 'lastEmailEngagementAtMs',\n] as const\n/** Facet instants where the earlier one is the truth. */\nconst EARLIEST_FIELDS = ['firstPurchaseAtMs'] as const\n\nexport interface ContactMergePlan {\n /**\n * What the survivor becomes, as a merge-`set` payload: every derived\n * field with its full value, and only the groups the merged record held\n * under `facets`. Plain values throughout — the writer adds its own\n * `updatedAt`.\n */\n survivor: Record<string, unknown>\n /** Every address the survivor answers to afterwards, primary first. */\n emails: string[]\n /** The merged record's addresses — what its leads and index entries are keyed by. */\n mergedEmails: string[]\n /**\n * The companies that lose a contact: those BOTH records were filed under,\n * which counted two people and now count one. A company only one record\n * named keeps its count — the survivor still names it.\n */\n companyCounts: Array<{ companyId: string; delta: -1 }>\n /** The union of both records' scope tokens — who may read the survivor. */\n visibleTo: string[]\n}\n\ntype Doc = Record<string, unknown>\n\n/** Whether a value counts as \"nothing here\" for the fill rule. */\nfunction isEmpty(value: unknown): boolean {\n if (value === undefined || value === null) return true\n if (typeof value === 'string') return value.trim() === ''\n if (Array.isArray(value)) return value.length === 0\n if (typeof value === 'object') return Object.keys(value as object).length === 0\n return false\n}\n\nfunction text(value: unknown): string {\n return typeof value === 'string' ? value : ''\n}\n\nfunction strings(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string' && item !== '')\n : []\n}\n\nfunction number(value: unknown): number | null {\n return typeof value === 'number' && Number.isFinite(value) ? value : null\n}\n\n/** The union of two string lists, first list's order first, deduplicated. */\nfunction union(a: unknown, b: unknown, cap = Number.POSITIVE_INFINITY): string[] {\n return [...new Set([...strings(a), ...strings(b)])].slice(0, cap)\n}\n\n/** Survivor's value where it has one, the merged record's otherwise. */\nfunction fill<T>(survivor: T, merged: T): T {\n return isEmpty(survivor) ? merged : survivor\n}\n\n/** Notes appended, survivor first, one blank line between, bounded. */\nfunction joinNotes(survivor: unknown, merged: unknown): string {\n const a = text(survivor).trim()\n const b = text(merged).trim()\n if (!b || a === b) return a\n if (!a) return b\n return `${a}\\n\\n${b}`.slice(0, NOTES_CAP)\n}\n\n/** What makes two timeline entries the same event. */\nfunction interactionKey(entry: ContactInteraction): string {\n return [entry.type, entry.refId ?? '', entry.atMs, entry.hostId ?? ''].join('|')\n}\n\n/**\n * Both timelines as one: deduplicated by event, newest first, and capped\n * the way every capture caps it — so a merge of two full timelines keeps\n * the fifty most recent visits rather than growing the document past what\n * a capture may write.\n */\nexport function mergeInteractions(\n survivor: readonly ContactInteraction[] | undefined,\n merged: readonly ContactInteraction[] | undefined,\n): ContactInteraction[] {\n const seen = new Set<string>()\n const out: ContactInteraction[] = []\n for (const entry of [...(survivor ?? []), ...(merged ?? [])]) {\n if (!entry || typeof entry !== 'object') continue\n const key = interactionKey(entry)\n if (seen.has(key)) continue\n seen.add(key)\n out.push(entry)\n }\n return out\n .sort((a, b) => (number(b.atMs) ?? 0) - (number(a.atMs) ?? 0))\n .slice(0, CONTACT_INTERACTIONS_CAP)\n}\n\n/** The custom values per key: the survivor's where set, the merged record's otherwise. */\nfunction mergeCustom(survivor: unknown, merged: unknown): Record<string, unknown> {\n const a = (survivor && typeof survivor === 'object' ? survivor : {}) as Doc\n const b = (merged && typeof merged === 'object' ? merged : {}) as Doc\n const out: Doc = { ...b }\n for (const [key, value] of Object.entries(a)) {\n if (!isEmpty(value) || !(key in b)) out[key] = value\n }\n return out\n}\n\n/**\n * One holder's facet after the merge.\n *\n * `survivor` is that holder's facet on the surviving record — possibly\n * absent, when only the merged record was held by this group — and `merged`\n * the same holder's facet on the record being folded in.\n */\nexport function mergeContactFacet(\n survivor: Doc | undefined,\n merged: Doc | undefined,\n): Doc {\n if (!merged) return { ...(survivor ?? {}) }\n if (!survivor) return { ...merged }\n const out: Doc = { ...merged }\n // Every scalar the survivor holds stands; every one it lacks fills.\n for (const [key, value] of Object.entries(survivor)) {\n out[key] = fill(value, merged[key])\n }\n const a = survivor as unknown as ContactFacet\n const b = merged as unknown as ContactFacet\n out['sources'] = { ...(b.sources ?? {}), ...(a.sources ?? {}) }\n out['interactions'] = mergeInteractions(a.interactions, b.interactions)\n const tags = union(a.tags, b.tags, TAGS_CAP)\n if (tags.length) out['tags'] = tags\n const campaignIds = union(a.campaignIds, b.campaignIds)\n if (campaignIds.length) out['campaignIds'] = campaignIds\n const notes = joinNotes(a.notes, b.notes)\n if (notes) out['notes'] = notes\n if (!isEmpty(a.custom) || !isEmpty(b.custom)) {\n out['custom'] = mergeCustom(a.custom, b.custom)\n }\n for (const field of SUM_FIELDS) {\n const left = number(a[field])\n const right = number(b[field])\n if (left !== null || right !== null) out[field] = (left ?? 0) + (right ?? 0)\n }\n for (const field of LATEST_FIELDS) {\n const left = number(a[field])\n const right = number(b[field])\n if (left !== null || right !== null) {\n out[field] = Math.max(left ?? 0, right ?? 0)\n }\n }\n for (const field of EARLIEST_FIELDS) {\n const left = number(a[field])\n const right = number(b[field])\n if (left !== null && right !== null) out[field] = Math.min(left, right)\n else if (left !== null || right !== null) out[field] = left ?? right\n }\n return out\n}\n\nfunction facetsOf(doc: Doc): Record<string, Doc> {\n const facets = doc[CONTACT_FACETS_FIELD]\n return facets && typeof facets === 'object' && !Array.isArray(facets)\n ? (facets as Record<string, Doc>)\n : {}\n}\n\nfunction mapOf(value: unknown): Doc {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? (value as Doc)\n : {}\n}\n\n/**\n * A refusal one record holds for a site, written over the other record's grant\n * for the same site (AGL-3320).\n *\n * The refusal outranks the grant, as it does when one person's refusal and\n * grant sit on two sites of one group: two records of one person who said no\n * to a site are a person who said no to it, and a merge that kept the grant\n * would start mailing them. The grant is kept beside it as `supersededEntry`,\n * so what the survivor held is still on the record.\n *\n * The merge is written with a merging `set`, which keeps every field of the\n * survivor's entry it does not name — so the grant's own fields are named\n * here, empty, or the refusal would read as carrying the grant's disclosure\n * and whoever recorded it.\n */\nfunction refusalOver(refusal: Doc, grant: Doc): Doc {\n const entry: Doc = { ...refusal, supersededEntry: grant }\n for (const key of Object.keys(grant)) {\n if (!(key in entry)) entry[key] = null\n }\n return entry\n}\n\n/**\n * The plan for folding `merged` into `survivor`.\n *\n * Both are the stored documents as read. The survivor's `email` is the\n * identity that stands; the merged record's becomes an alternate.\n */\nexport function planContactMerge(survivor: Doc, merged: Doc): ContactMergePlan {\n const survivorEmail = normalizeContactEmail(survivor['email']) ?? ''\n const mergedEmails = contactEmails(merged)\n const alternates = [\n ...new Set([\n ...strings(survivor[CONTACT_ALTERNATE_EMAILS_FIELD]),\n ...mergedEmails,\n ]),\n ]\n .filter((email) => email !== survivorEmail)\n .slice(0, CONTACT_ALTERNATE_EMAILS_CAP)\n\n const out: Doc = {\n [CONTACT_ALTERNATE_EMAILS_FIELD]: alternates,\n }\n // The canonical name, with its search keys, only when the survivor had none.\n const survivorName = text(survivor['name']).trim()\n const mergedName = text(merged['name']).trim()\n if (!survivorName && mergedName) Object.assign(out, nameSearchFields(mergedName))\n // The search echoes, on the same fill rule.\n for (const key of ['phone', 'companyName'] as const) {\n if (isEmpty(survivor[key]) && !isEmpty(merged[key])) out[key] = merged[key]\n }\n // The shared lists: who may read the row, who captured it, which forms and\n // companies it is filed under.\n const visibleTo = union(survivor['visibleTo'], merged['visibleTo'])\n out['visibleTo'] = visibleTo\n const capturedBy = union(survivor['capturedByHostIds'], merged['capturedByHostIds'])\n if (capturedBy.length) out['capturedByHostIds'] = capturedBy\n const formIds = union(\n survivor[CONTACT_FORM_IDS_FIELD],\n merged[CONTACT_FORM_IDS_FIELD],\n CONTACT_FORM_IDS_CAP,\n )\n if (formIds.length) out[CONTACT_FORM_IDS_FIELD] = formIds\n const survivorCompanies = strings(survivor[CONTACT_COMPANY_IDS_FIELD])\n const mergedCompanies = strings(merged[CONTACT_COMPANY_IDS_FIELD])\n const companyIds = [...new Set([...survivorCompanies, ...mergedCompanies])]\n if (companyIds.length) out[CONTACT_COMPANY_IDS_FIELD] = companyIds\n const companyCounts = survivorCompanies\n .filter((id) => mergedCompanies.includes(id))\n .map((companyId) => ({ companyId, delta: -1 as const }))\n // The organization-level fields the REST API reads and writes.\n const tags = union(survivor['tags'], merged['tags'])\n if (tags.length) out['tags'] = tags\n const notes = joinNotes(survivor['notes'], merged['notes'])\n if (notes) out['notes'] = notes\n if (!isEmpty(survivor['custom']) || !isEmpty(merged['custom'])) {\n out['custom'] = mergeCustom(survivor['custom'], merged['custom'])\n }\n // Consent: a grant fills where the survivor has none for that site, and a\n // refusal on either record stands — per site as well as unscoped (AGL-3320).\n const survivorConsent = mapOf(survivor[MARKETING_CONSENT_BY_HOST_FIELD])\n const mergedConsent = mapOf(merged[MARKETING_CONSENT_BY_HOST_FIELD])\n const consentByHost: Doc = { ...mergedConsent, ...survivorConsent }\n for (const [hostId, value] of Object.entries(mergedConsent)) {\n const refusal = mapOf(value)\n if (refusal[MARKETING_CONSENT_FIELD] !== false) continue\n if (!(hostId in survivorConsent)) continue\n const standing = mapOf(survivorConsent[hostId])\n if (standing[MARKETING_CONSENT_FIELD] === false) continue\n consentByHost[hostId] = refusalOver(refusal, standing)\n }\n if (Object.keys(consentByHost).length) {\n out[MARKETING_CONSENT_BY_HOST_FIELD] = consentByHost\n }\n if (survivor['marketingConsent'] === false || merged['marketingConsent'] === false) {\n out['marketingConsent'] = false\n } else if (survivor['marketingConsent'] === true || merged['marketingConsent'] === true) {\n out['marketingConsent'] = true\n }\n // Each holder's facet — only the groups the merged record held need a write.\n const survivorFacets = facetsOf(survivor)\n const mergedFacets = facetsOf(merged)\n const facets: Record<string, Doc> = {}\n for (const [groupId, facet] of Object.entries(mergedFacets)) {\n facets[groupId] = mergeContactFacet(survivorFacets[groupId], facet)\n }\n if (Object.keys(facets).length) out[CONTACT_FACETS_FIELD] = facets\n\n return {\n survivor: out,\n emails: [survivorEmail, ...alternates].filter(Boolean),\n mergedEmails,\n companyCounts,\n visibleTo,\n }\n}\n\n/** Where a previewed value comes from. */\nexport type ContactMergeSource = 'survivor' | 'merged' | 'both' | 'none'\n\n/** One line of the side-by-side the dialog shows. */\nexport interface ContactMergePreviewRow {\n key: string\n label: string\n /** The surviving record's value, as text. */\n survivor: string\n /** The merged record's value, as text. */\n merged: string\n /** What the survivor carries afterwards. */\n result: string\n from: ContactMergeSource\n}\n\nexport interface ContactMergePreviewOptions {\n /** The owner's display name for a uid; the uid itself when absent. */\n memberName?: (uid: string) => string\n}\n\nfunction addressLine(value: unknown): string {\n const address = mapOf(value)\n return ['line1', 'line2', 'city', 'state', 'postalCode', 'country']\n .map((key) => text(address[key]).trim())\n .filter(Boolean)\n .join(', ')\n}\n\nfunction sourceOf(survivor: string, merged: string, result: string): ContactMergeSource {\n if (!result) return 'none'\n if (survivor && merged && survivor !== merged && result !== survivor && result !== merged) {\n return 'both'\n }\n if (result === survivor && survivor === merged) return 'both'\n return result === survivor ? 'survivor' : 'merged'\n}\n\n/**\n * The merge as the viewing group would see it, field by field.\n *\n * Reads through ONE group's facet, the way the record page does, so a\n * holder previewing a merge sees its own values and never another holder's.\n * Every row carries the survivor's value, the merged record's, and the\n * result the plan would write, so the dialog is a rendering and not a second\n * opinion.\n */\nexport function contactMergePreview(\n survivor: Doc,\n merged: Doc,\n groupId: string,\n options: ContactMergePreviewOptions = {},\n): ContactMergePreviewRow[] {\n const plan = planContactMerge(survivor, merged)\n const after: Doc = {\n ...survivor,\n ...plan.survivor,\n [CONTACT_FACETS_FIELD]: {\n ...facetsOf(survivor),\n ...mapOf(plan.survivor[CONTACT_FACETS_FIELD]),\n },\n }\n const a = readContactFacet(survivor, groupId)\n const b = readContactFacet(merged, groupId)\n const c = readContactFacet(after, groupId)\n const memberName = options.memberName ?? ((uid: string) => uid)\n const stage = (value: unknown) =>\n typeof value === 'string' && value in CONTACT_LIFECYCLE_STAGE_LABELS\n ? CONTACT_LIFECYCLE_STAGE_LABELS[value as keyof typeof CONTACT_LIFECYCLE_STAGE_LABELS]\n : ''\n const owner = (value: unknown) => (text(value) ? memberName(text(value)) : '')\n const list = (value: unknown) => strings(value).join(', ')\n const money = (facet: ContactFacet) =>\n facet.ordersCount\n ? `${facet.ordersCount} · $${((facet.ltvCents ?? 0) / 100).toFixed(2)}`\n : ''\n const row = (\n key: string,\n label: string,\n left: string,\n right: string,\n result: string,\n ): ContactMergePreviewRow => ({\n key,\n label,\n survivor: left,\n merged: right,\n result,\n from: sourceOf(left, right, result),\n })\n const rows: ContactMergePreviewRow[] = [\n row(\n 'name',\n 'Name',\n contactDisplayName(survivor, groupId),\n contactDisplayName(merged, groupId),\n contactDisplayName(after, groupId),\n ),\n row(\n 'email',\n 'Email',\n contactEmails(survivor).join(', '),\n contactEmails(merged).join(', '),\n plan.emails.join(', '),\n ),\n row('phone', 'Phone', text(a.phone), text(b.phone), text(c.phone)),\n row('jobTitle', 'Job title', text(a.jobTitle), text(b.jobTitle), text(c.jobTitle)),\n row(\n 'company',\n 'Company',\n text(a.companyName),\n text(b.companyName),\n text(c.companyName),\n ),\n row(\n 'lifecycleStage',\n 'Stage',\n stage(a.lifecycleStage),\n stage(b.lifecycleStage),\n stage(c.lifecycleStage),\n ),\n row('owner', 'Owner', owner(a.ownerUid), owner(b.ownerUid), owner(c.ownerUid)),\n row('tags', 'Tags', list(a.tags), list(b.tags), list(c.tags)),\n row('notes', 'Notes', text(a.notes), text(b.notes), text(c.notes)),\n row(\n 'address',\n 'Address',\n addressLine(a.address),\n addressLine(b.address),\n addressLine(c.address),\n ),\n row('orders', 'Orders', money(a), money(b), money(c)),\n row(\n 'timeline',\n 'Timeline entries',\n a.interactions.length ? String(a.interactions.length) : '',\n b.interactions.length ? String(b.interactions.length) : '',\n c.interactions.length ? String(c.interactions.length) : '',\n ),\n ]\n const customKeys = [\n ...new Set([...Object.keys(mapOf(a.custom)), ...Object.keys(mapOf(b.custom))]),\n ].sort()\n for (const key of customKeys) {\n const show = (facet: ContactFacet) => {\n const value = mapOf(facet.custom)[key]\n return value === null || value === undefined ? '' : String(value)\n }\n rows.push(row(`custom.${key}`, key, show(a), show(b), show(c)))\n }\n return rows\n}\n"],"names":["CONTACT_ALTERNATE_EMAILS_CAP","CONTACT_ALTERNATE_EMAILS_FIELD","CONTACT_FACETS_FIELD","CONTACT_FORM_IDS_CAP","CONTACT_FORM_IDS_FIELD","CONTACT_INTERACTIONS_CAP","contactDisplayName","contactEmails","normalizeContactEmail","readContactFacet","CONTACT_COMPANY_IDS_FIELD","CONTACT_LIFECYCLE_STAGE_LABELS","MARKETING_CONSENT_BY_HOST_FIELD","MARKETING_CONSENT_FIELD","nameSearchFields","TAGS_CAP","NOTES_CAP","SUM_FIELDS","LATEST_FIELDS","EARLIEST_FIELDS","isEmpty","value","undefined","trim","Array","isArray","length","Object","keys","text","strings","filter","item","number","Number","isFinite","union","a","b","cap","POSITIVE_INFINITY","Set","slice","fill","survivor","merged","joinNotes","interactionKey","entry","type","refId","atMs","hostId","join","mergeInteractions","seen","out","key","has","add","push","sort","mergeCustom","entries","mergeContactFacet","sources","interactions","tags","campaignIds","notes","custom","field","left","right","Math","max","min","facetsOf","doc","facets","mapOf","refusalOver","refusal","grant","supersededEntry","planContactMerge","survivorEmail","mergedEmails","alternates","email","survivorName","mergedName","assign","visibleTo","capturedBy","formIds","survivorCompanies","mergedCompanies","companyIds","companyCounts","id","includes","map","companyId","delta","survivorConsent","mergedConsent","consentByHost","standing","survivorFacets","mergedFacets","groupId","facet","emails","Boolean","addressLine","address","sourceOf","result","contactMergePreview","options","plan","after","c","memberName","uid","stage","owner","list","money","ordersCount","ltvCents","toFixed","row","label","from","rows","phone","jobTitle","companyName","lifecycleStage","ownerUid","String","customKeys","show"],"mappings":"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"}
@@ -1,75 +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
- /**
18
- * The query key a booking link carries the record on: `?crm=contact:abc`.
19
- *
20
- * The reference rides the LINK rather than relying on the booker's address
21
- * because the two routinely differ — a rep emails somebody's work address
22
- * and they book with a personal one — and a booking that could only be
23
- * matched by address would then land on nobody. The widget copies the value
24
- * onto the booking request, the booking row keeps it as `crmRef`, and the
25
- * server files the meeting under the record it names.
26
- */
27
- export declare const CRM_BOOKING_REF_PARAM = "crm";
28
- /**
29
- * The query key that preselects a service in the booking widget:
30
- * `?service={serviceId}`. The widget lists every active service and this
31
- * opens it on the one the link was about.
32
- */
33
- export declare const BOOKING_SERVICE_PARAM = "service";
34
- /** The three records a booking link can be dropped from. */
35
- export declare const CRM_BOOKING_REF_KINDS: readonly ["contact", "lead", "deal"];
36
- export type CrmBookingRefKind = (typeof CRM_BOOKING_REF_KINDS)[number];
37
- export interface CrmBookingRef {
38
- kind: CrmBookingRefKind;
39
- id: string;
40
- }
41
- /** `contact:abc` — the wire form of a reference. */
42
- export declare function formatCrmBookingRef(ref: CrmBookingRef): string;
43
- /**
44
- * The reference a query value names, or `null` for anything that is not one.
45
- *
46
- * Strict on purpose: the value arrives on a public, unauthenticated booking
47
- * request, so an unknown kind or a malformed id is dropped rather than
48
- * stored — a booking still lands, it simply matches by address instead.
49
- */
50
- export declare function parseCrmBookingRef(raw: unknown): CrmBookingRef | null;
51
- /**
52
- * What the meeting entry on the timeline says — the service and the slot,
53
- * in the service's own timezone, with the zone named so a rep in another
54
- * one is not misled. The body, not the subject: `subject` is the field a
55
- * sent email carries, and the timeline draws it as one.
56
- */
57
- export declare function crmBookingMeetingBody(input: {
58
- serviceName: string;
59
- startsAtMs: number;
60
- timezone?: string | null;
61
- }): string;
62
- /** The title of the task a service files when it asks for a follow-up. */
63
- export declare function crmBookingFollowUpTitle(serviceName: string): string;
64
- /**
65
- * When the follow-up falls due: ONE BUSINESS DAY after the slot, at the
66
- * slot's own clock time.
67
- *
68
- * A meeting on a Friday is followed up on Monday, one on a Saturday or a
69
- * Sunday on Monday too; any other day is followed up the next. Whole days
70
- * are added to the instant rather than a calendar walked, so the arithmetic
71
- * cannot land on a clock time that does not exist across a DST change —
72
- * the task is due "about this time tomorrow", and an hour either way is not
73
- * a fact the task keeps.
74
- */
75
- export declare function crmBookingFollowUpDueMs(endsAtMs: number, timezone?: string | null): number;