@aglyn/aglyn 1.0.0-beta.217 → 1.0.0-beta.219
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.
- package/package.json +14 -14
- package/src/lib/app-utils/actions.d.ts +25 -374
- package/src/lib/app-utils/actions.js +101 -561
- package/src/lib/app-utils/actions.js.map +1 -1
- package/src/lib/app-utils/activity-presenter.d.ts +3 -3
- package/src/lib/app-utils/activity-presenter.js +36 -52
- package/src/lib/app-utils/activity-presenter.js.map +1 -1
- package/src/lib/app-utils/admin-audit-index.js +2 -2
- package/src/lib/app-utils/admin-audit-index.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +11 -2
- package/src/lib/app-utils/analytics-events.js +11 -2
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/analytics-provider.d.ts +182 -0
- package/src/lib/app-utils/analytics-provider.js +133 -0
- package/src/lib/app-utils/analytics-provider.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +46 -0
- package/src/lib/app-utils/api-plugins.js +19 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -1
- package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
- package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
- package/src/lib/app-utils/artifact-overrides.js.map +1 -0
- package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
- package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
- package/src/lib/app-utils/artifact-provenance.js.map +1 -0
- package/src/lib/app-utils/assist-credits.js +2 -1
- package/src/lib/app-utils/assist-credits.js.map +1 -1
- package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
- package/src/lib/app-utils/binding-token-catalog.js +17 -41
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
- package/src/lib/app-utils/binding-tokens.js +1 -1
- package/src/lib/app-utils/binding-tokens.js.map +1 -1
- package/src/lib/app-utils/brand-support-line.d.ts +36 -0
- package/src/lib/app-utils/brand-support-line.js +38 -0
- package/src/lib/app-utils/brand-support-line.js.map +1 -0
- package/src/lib/app-utils/campaign-touch.d.ts +5 -5
- package/src/lib/app-utils/campaign-touch.js +8 -8
- package/src/lib/app-utils/campaign-touch.js.map +1 -1
- package/src/lib/app-utils/collection-entries.d.ts +2 -2
- package/src/lib/app-utils/collection-entries.js.map +1 -1
- package/src/lib/app-utils/consent-group-change.d.ts +4 -0
- package/src/lib/app-utils/consent-group-change.js.map +1 -1
- package/src/lib/app-utils/console-record-links.d.ts +10 -89
- package/src/lib/app-utils/console-record-links.js +3 -107
- package/src/lib/app-utils/console-record-links.js.map +1 -1
- package/src/lib/app-utils/console-routes.d.ts +16 -7
- package/src/lib/app-utils/console-routes.js +9 -3
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/contacts.d.ts +23 -1
- package/src/lib/app-utils/contacts.js +21 -5
- package/src/lib/app-utils/contacts.js.map +1 -1
- package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
- package/src/lib/app-utils/cross-pool-desync.js +47 -0
- package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
- package/src/lib/app-utils/csv-upload.d.ts +29 -0
- package/src/lib/app-utils/csv-upload.js +29 -0
- package/src/lib/app-utils/csv-upload.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +5 -5
- package/src/lib/app-utils/dataset-models.js +19 -2
- package/src/lib/app-utils/dataset-models.js.map +1 -1
- package/src/lib/app-utils/datasets.d.ts +65 -11
- package/src/lib/app-utils/datasets.js +74 -11
- package/src/lib/app-utils/datasets.js.map +1 -1
- package/src/lib/app-utils/docs-deflection.d.ts +6 -6
- package/src/lib/app-utils/docs-deflection.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +12 -6
- package/src/lib/app-utils/docs-help.generated.js +21 -6
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
- package/src/lib/app-utils/docs-index.generated.js +514 -318
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
- package/src/lib/app-utils/docs-retrieval.js +14 -10
- package/src/lib/app-utils/docs-retrieval.js.map +1 -1
- package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
- package/src/lib/app-utils/duplicate-resource.js +7 -4
- package/src/lib/app-utils/duplicate-resource.js.map +1 -1
- package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
- package/src/lib/app-utils/element-ui.d.ts +1 -1
- package/src/lib/app-utils/element-ui.js +1 -1
- package/src/lib/app-utils/element-ui.js.map +1 -1
- package/src/lib/app-utils/email-starter-policy.js +3 -3
- package/src/lib/app-utils/email-starter-policy.js.map +1 -1
- package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
- package/src/lib/app-utils/entity-picker-context.js.map +1 -1
- package/src/lib/app-utils/error-beacon.d.ts +75 -6
- package/src/lib/app-utils/error-beacon.js +160 -21
- package/src/lib/app-utils/error-beacon.js.map +1 -1
- package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
- package/src/lib/app-utils/expand-repeatables.js +10 -10
- package/src/lib/app-utils/expand-repeatables.js.map +1 -1
- package/src/lib/app-utils/host-events.d.ts +82 -0
- package/src/lib/app-utils/host-events.js +62 -0
- package/src/lib/app-utils/host-events.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +33 -1
- package/src/lib/app-utils/lockdown.js +45 -4
- package/src/lib/app-utils/lockdown.js.map +1 -1
- package/src/lib/app-utils/margin-utilization.d.ts +4 -69
- package/src/lib/app-utils/margin-utilization.js +82 -69
- package/src/lib/app-utils/margin-utilization.js.map +1 -1
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
- package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
- package/src/lib/app-utils/node-interactions.d.ts +7 -7
- package/src/lib/app-utils/node-interactions.js.map +1 -1
- package/src/lib/app-utils/notifications.d.ts +78 -47
- package/src/lib/app-utils/notifications.js +63 -44
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/payments-configured.d.ts +8 -21
- package/src/lib/app-utils/payments-configured.js +8 -23
- package/src/lib/app-utils/payments-configured.js.map +1 -1
- package/src/lib/app-utils/plan-entitlements.d.ts +43 -128
- package/src/lib/app-utils/plan-entitlements.js +145 -304
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/platform-brand.d.ts +10 -0
- package/src/lib/app-utils/platform-brand.js +14 -3
- package/src/lib/app-utils/platform-brand.js.map +1 -1
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
- package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
- package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
- package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
- package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
- package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
- package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +14 -5
- package/src/lib/app-utils/release-flags.js +21 -125
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/repeat-sources.d.ts +9 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -1
- package/src/lib/app-utils/retained-refusals.d.ts +73 -0
- package/src/lib/app-utils/retained-refusals.js +186 -0
- package/src/lib/app-utils/retained-refusals.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +27 -0
- package/src/lib/app-utils/scope-tokens.js +61 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -1
- package/src/lib/app-utils/screen-link-context.js +3 -3
- package/src/lib/app-utils/screen-link-context.js.map +1 -1
- package/src/lib/app-utils/screen-route.d.ts +15 -0
- package/src/lib/app-utils/screen-route.js +21 -1
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/seo-audit.d.ts +132 -0
- package/src/lib/app-utils/seo-audit.js +246 -0
- package/src/lib/app-utils/seo-audit.js.map +1 -0
- package/src/lib/app-utils/seo-keywords.d.ts +48 -0
- package/src/lib/app-utils/seo-keywords.js +60 -0
- package/src/lib/app-utils/seo-keywords.js.map +1 -0
- package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
- package/src/lib/app-utils/seo-page-facts.js +155 -0
- package/src/lib/app-utils/seo-page-facts.js.map +1 -0
- package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
- package/src/lib/app-utils/seo-site-scan.js +162 -0
- package/src/lib/app-utils/seo-site-scan.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.js +1 -1
- package/src/lib/app-utils/seo-title-variables.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +6 -9
- package/src/lib/app-utils/server.js +17 -27
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-interactions.d.ts +501 -0
- package/src/lib/app-utils/site-interactions.js +554 -0
- package/src/lib/app-utils/site-interactions.js.map +1 -0
- package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
- package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +5 -2
- package/src/lib/app-utils/site-theme.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +4 -3
- package/src/lib/app-utils/sitemap.js +9 -7
- package/src/lib/app-utils/sitemap.js.map +1 -1
- package/src/lib/app-utils/stale-build-error.d.ts +51 -0
- package/src/lib/app-utils/stale-build-error.js +100 -1
- package/src/lib/app-utils/stale-build-error.js.map +1 -1
- package/src/lib/app-utils/starter-templates.d.ts +20 -0
- package/src/lib/app-utils/starter-templates.js +49 -0
- package/src/lib/app-utils/starter-templates.js.map +1 -1
- package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
- package/src/lib/app-utils/theme-library.d.ts +10 -3
- package/src/lib/app-utils/theme-library.js +13 -4
- package/src/lib/app-utils/theme-library.js.map +1 -1
- package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
- package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
- package/src/lib/app-utils/utm-attribution.js.map +1 -0
- package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
- package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
- package/src/lib/app-utils/utm-forwarding.js.map +1 -0
- package/src/lib/app-utils/video-object.js +6 -5
- package/src/lib/app-utils/video-object.js.map +1 -1
- package/src/lib/app-utils/visitor-consent.d.ts +41 -164
- package/src/lib/app-utils/visitor-consent.js +66 -277
- package/src/lib/app-utils/visitor-consent.js.map +1 -1
- package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
- package/src/lib/app-utils/web-vitals-rum.js +31 -63
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
- package/src/lib/app-utils/where-used.d.ts +11 -6
- package/src/lib/app-utils/where-used.js +3 -8
- package/src/lib/app-utils/where-used.js.map +1 -1
- package/src/lib/canvas-manager/canvas-manager.js +3 -3
- package/src/lib/canvas-manager/canvas-manager.js.map +1 -1
- package/src/lib/foundation/definitions/components.types.d.ts +1 -1
- package/src/lib/foundation/definitions/components.types.js +1 -1
- package/src/lib/foundation/definitions/components.types.js.map +1 -1
- package/src/lib/foundation/definitions/org-billing.types.d.ts +18 -135
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +6 -3
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +27 -5
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
- package/src/lib/foundation/index.d.ts +1 -1
- package/src/lib/foundation/index.js.map +1 -1
- package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
- package/src/lib/plugin-manager/besigner-documents.js +61 -0
- package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
- package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
- package/src/lib/plugin-manager/computed-variables.js +74 -0
- package/src/lib/plugin-manager/computed-variables.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
- package/src/lib/plugin-manager/custom-fields.js +47 -1
- package/src/lib/plugin-manager/custom-fields.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +292 -20
- package/src/lib/plugin-manager/feature-plugins.js +105 -17
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +123 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +785 -14
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
- package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
- package/src/lib/plugin-manager/plugin-dependents.js +75 -0
- package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
- package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
- package/src/lib/plugin-manager/plugin-distribution.js +45 -0
- package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
- package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
- package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-record-index.js +51 -0
- package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-record-written.js +42 -0
- package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
- package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
- package/src/lib/plugin-manager/plugin-site-export.js +40 -0
- package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
- package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
- package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
- package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-axes.d.ts +107 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js +107 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
- package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
- package/src/lib/plugin-manager/record-captured-contact.js +10 -32
- package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
- package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
- package/src/lib/plugin-manager/repeat-rows.js +108 -0
- package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
- package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
- package/src/lib/plugin-manager/submission-record-target.js +125 -0
- package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
- package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
- package/src/lib/plugin-manager/video-embed-provider.js +165 -0
- package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
- package/src/lib/types/nodes.d.ts +2 -2
- package/src/lib/types/nodes.js.map +1 -1
- package/src/lib/app-utils/campaign-attribution.js.map +0 -1
- package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
- package/src/lib/app-utils/contact-holder.d.ts +0 -68
- package/src/lib/app-utils/contact-holder.js +0 -129
- package/src/lib/app-utils/contact-holder.js.map +0 -1
- package/src/lib/app-utils/contact-merge.d.ts +0 -136
- package/src/lib/app-utils/contact-merge.js +0 -412
- package/src/lib/app-utils/contact-merge.js.map +0 -1
- package/src/lib/app-utils/crm-csv.d.ts +0 -239
- package/src/lib/app-utils/crm-csv.js +0 -467
- package/src/lib/app-utils/crm-csv.js.map +0 -1
- package/src/lib/app-utils/crm-digest.d.ts +0 -185
- package/src/lib/app-utils/crm-digest.js +0 -272
- package/src/lib/app-utils/crm-digest.js.map +0 -1
- package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
- package/src/lib/app-utils/form-dataset-binding.js +0 -74
- package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
- package/src/lib/app-utils/list-import.d.ts +0 -158
- package/src/lib/app-utils/list-import.js +0 -332
- package/src/lib/app-utils/list-import.js.map +0 -1
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
- package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
- package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
- package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
- package/src/lib/app-utils/marketplace-theme.js.map +0 -1
- package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
- package/src/lib/app-utils/marketplace-update-state.js +0 -132
- package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
- package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
- package/src/lib/app-utils/publisher-agreement.js +0 -321
- package/src/lib/app-utils/publisher-agreement.js.map +0 -1
- package/src/lib/app-utils/wistia-embed.d.ts +0 -104
- package/src/lib/app-utils/wistia-embed.js +0 -138
- package/src/lib/app-utils/wistia-embed.js.map +0 -1
- package/src/lib/app-utils/workflows.d.ts +0 -136
- package/src/lib/app-utils/workflows.js +0 -346
- package/src/lib/app-utils/workflows.js.map +0 -1
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
- package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
- package/src/lib/plugin-manager/commerce-zone-props.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":";AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CC,GAED,SACEA,4BAA4B,EAC5BC,8BAA8B,EAC9BC,oBAAoB,EACpBC,oBAAoB,EACpBC,sBAAsB,EACtBC,wBAAwB,EAGxBC,kBAAkB,EAClBC,aAAa,EACbC,qBAAqB,EACrBC,gBAAgB,QACX,gBAAY;AACnB,SAASC,yBAAyB,EAAEC,8BAA8B,QAAQ,WAAO;AACjF,SACEC,+BAA+B,EAC/BC,uBAAuB,QAClB,yBAAqB;AAC5B,SAASC,gBAAgB,QAAQ,mBAAe;AAEhD,oEAAoE,GACpE,MAAMC,WAAW;AACjB,4DAA4D,GAC5D,MAAMC,YAAY;AAElB,uEAAuE,GACvE,MAAMC,aAAa;IACjB;IACA;IACA;IACA;CACD;AACD,qDAAqD,GACrD,MAAMC,gBAAgB;IACpB;IACA;IACA;CACD;AACD,uDAAuD,GACvD,MAAMC,kBAAkB;IAAC;CAAoB;AA0B7C,gEAAgE,GAChE,SAASC,QAAQC,KAAc;IAC7B,IAAIA,UAAUC,aAAaD,UAAU,MAAM,OAAO;IAClD,IAAI,OAAOA,UAAU,UAAU,OAAOA,MAAME,IAAI,OAAO;IACvD,IAAIC,MAAMC,OAAO,CAACJ,QAAQ,OAAOA,MAAMK,MAAM,KAAK;IAClD,IAAI,OAAOL,UAAU,UAAU,OAAOM,OAAOC,IAAI,CAACP,OAAiBK,MAAM,KAAK;IAC9E,OAAO;AACT;AAEA,SAASG,KAAKR,KAAc;IAC1B,OAAO,OAAOA,UAAU,WAAWA,QAAQ;AAC7C;AAEA,SAASS,QAAQT,KAAc;IAC7B,OAAOG,MAAMC,OAAO,CAACJ,SACjBA,MAAMU,MAAM,CAAC,CAACC,OAAyB,OAAOA,SAAS,YAAYA,SAAS,MAC5E,EAAE;AACR;AAEA,SAASC,OAAOZ,KAAc;IAC5B,OAAO,OAAOA,UAAU,YAAYa,OAAOC,QAAQ,CAACd,SAASA,QAAQ;AACvE;AAEA,2EAA2E,GAC3E,SAASe,MAAMC,CAAU,EAAEC,CAAU,EAAEC,MAAML,OAAOM,iBAAiB;IACnE,OAAO;WAAI,IAAIC,IAAI;eAAIX,QAAQO;eAAOP,QAAQQ;SAAG;KAAE,CAACI,KAAK,CAAC,GAAGH;AAC/D;AAEA,sEAAsE,GACtE,SAASI,KAAQC,QAAW,EAAEC,MAAS;IACrC,OAAOzB,QAAQwB,YAAYC,SAASD;AACtC;AAEA,qEAAqE,GACrE,SAASE,UAAUF,QAAiB,EAAEC,MAAe;IACnD,MAAMR,IAAIR,KAAKe,UAAUrB,IAAI;IAC7B,MAAMe,IAAIT,KAAKgB,QAAQtB,IAAI;IAC3B,IAAI,CAACe,KAAKD,MAAMC,GAAG,OAAOD;IAC1B,IAAI,CAACA,GAAG,OAAOC;IACf,OAAO,GAAGD,EAAE,IAAI,EAAEC,GAAG,CAACI,KAAK,CAAC,GAAG1B;AACjC;AAEA,oDAAoD,GACpD,SAAS+B,eAAeC,KAAyB;QAC3BA,cAA+BA;IAAnD,OAAO;QAACA,MAAMC,IAAI;SAAED,eAAAA,MAAME,KAAK,YAAXF,eAAe;QAAIA,MAAMG,IAAI;SAAEH,gBAAAA,MAAMI,MAAM,YAAZJ,gBAAgB;KAAG,CAACK,IAAI,CAAC;AAC9E;AAEA;;;;;CAKC,GACD,OAAO,SAASC,kBACdV,QAAmD,EACnDC,MAAiD;IAEjD,MAAMU,OAAO,IAAId;IACjB,MAAMe,MAA4B,EAAE;IACpC,KAAK,MAAMR,SAAS;WAAKJ,mBAAAA,WAAY,EAAE;WAAOC,iBAAAA,SAAU,EAAE;KAAE,CAAE;QAC5D,IAAI,CAACG,SAAS,OAAOA,UAAU,UAAU;QACzC,MAAMS,MAAMV,eAAeC;QAC3B,IAAIO,KAAKG,GAAG,CAACD,MAAM;QACnBF,KAAKI,GAAG,CAACF;QACTD,IAAII,IAAI,CAACZ;IACX;IACA,OAAOQ,IACJK,IAAI,CAAC,CAACxB,GAAGC;YAAOL,SAAwBA;eAAzB,EAACA,UAAAA,OAAOK,EAAEa,IAAI,aAAblB,UAAkB,OAAMA,WAAAA,OAAOI,EAAEc,IAAI,aAAblB,WAAkB;OAC1DS,KAAK,CAAC,GAAGrC;AACd;AAEA,wFAAwF,GACxF,SAASyD,YAAYlB,QAAiB,EAAEC,MAAe;IACrD,MAAMR,IAAKO,YAAY,OAAOA,aAAa,WAAWA,WAAW,CAAC;IAClE,MAAMN,IAAKO,UAAU,OAAOA,WAAW,WAAWA,SAAS,CAAC;IAC5D,MAAMW,MAAW,aAAKlB;IACtB,KAAK,MAAM,CAACmB,KAAKpC,MAAM,IAAIM,OAAOoC,OAAO,CAAC1B,GAAI;QAC5C,IAAI,CAACjB,QAAQC,UAAU,CAAEoC,CAAAA,OAAOnB,CAAAA,GAAIkB,GAAG,CAACC,IAAI,GAAGpC;IACjD;IACA,OAAOmC;AACT;AAEA;;;;;;CAMC,GACD,OAAO,SAASQ,kBACdpB,QAAyB,EACzBC,MAAuB;QAWAP,YAAsBD;IAT7C,IAAI,CAACQ,QAAQ,OAAO,aAAMD,mBAAAA,WAAY,CAAC;IACvC,IAAI,CAACA,UAAU,OAAO,aAAKC;IAC3B,MAAMW,MAAW,aAAKX;IACtB,oEAAoE;IACpE,KAAK,MAAM,CAACY,KAAKpC,MAAM,IAAIM,OAAOoC,OAAO,CAACnB,UAAW;QACnDY,GAAG,CAACC,IAAI,GAAGd,KAAKtB,OAAOwB,MAAM,CAACY,IAAI;IACpC;IACA,MAAMpB,IAAIO;IACV,MAAMN,IAAIO;IACVW,GAAG,CAAC,UAAU,GAAG,cAAMlB,aAAAA,EAAE2B,OAAO,YAAT3B,aAAa,CAAC,IAAQD,aAAAA,EAAE4B,OAAO,YAAT5B,aAAa,CAAC;IAC3DmB,GAAG,CAAC,eAAe,GAAGF,kBAAkBjB,EAAE6B,YAAY,EAAE5B,EAAE4B,YAAY;IACtE,MAAMC,OAAO/B,MAAMC,EAAE8B,IAAI,EAAE7B,EAAE6B,IAAI,EAAEpD;IACnC,IAAIoD,KAAKzC,MAAM,EAAE8B,GAAG,CAAC,OAAO,GAAGW;IAC/B,MAAMC,cAAchC,MAAMC,EAAE+B,WAAW,EAAE9B,EAAE8B,WAAW;IACtD,IAAIA,YAAY1C,MAAM,EAAE8B,GAAG,CAAC,cAAc,GAAGY;IAC7C,MAAMC,QAAQvB,UAAUT,EAAEgC,KAAK,EAAE/B,EAAE+B,KAAK;IACxC,IAAIA,OAAOb,GAAG,CAAC,QAAQ,GAAGa;IAC1B,IAAI,CAACjD,QAAQiB,EAAEiC,MAAM,KAAK,CAAClD,QAAQkB,EAAEgC,MAAM,GAAG;QAC5Cd,GAAG,CAAC,SAAS,GAAGM,YAAYzB,EAAEiC,MAAM,EAAEhC,EAAEgC,MAAM;IAChD;IACA,KAAK,MAAMC,SAAStD,WAAY;QAC9B,MAAMuD,OAAOvC,OAAOI,CAAC,CAACkC,MAAM;QAC5B,MAAME,QAAQxC,OAAOK,CAAC,CAACiC,MAAM;QAC7B,IAAIC,SAAS,QAAQC,UAAU,MAAMjB,GAAG,CAACe,MAAM,GAAG,CAACC,eAAAA,OAAQ,MAAMC,gBAAAA,QAAS;IAC5E;IACA,KAAK,MAAMF,SAASrD,cAAe;QACjC,MAAMsD,OAAOvC,OAAOI,CAAC,CAACkC,MAAM;QAC5B,MAAME,QAAQxC,OAAOK,CAAC,CAACiC,MAAM;QAC7B,IAAIC,SAAS,QAAQC,UAAU,MAAM;YACnCjB,GAAG,CAACe,MAAM,GAAGG,KAAKC,GAAG,CAACH,eAAAA,OAAQ,GAAGC,gBAAAA,QAAS;QAC5C;IACF;IACA,KAAK,MAAMF,SAASpD,gBAAiB;QACnC,MAAMqD,OAAOvC,OAAOI,CAAC,CAACkC,MAAM;QAC5B,MAAME,QAAQxC,OAAOK,CAAC,CAACiC,MAAM;QAC7B,IAAIC,SAAS,QAAQC,UAAU,MAAMjB,GAAG,CAACe,MAAM,GAAGG,KAAKE,GAAG,CAACJ,MAAMC;aAC5D,IAAID,SAAS,QAAQC,UAAU,MAAMjB,GAAG,CAACe,MAAM,GAAGC,eAAAA,OAAQC;IACjE;IACA,OAAOjB;AACT;AAEA,SAASqB,SAASC,GAAQ;IACxB,MAAMC,SAASD,GAAG,CAAC5E,qBAAqB;IACxC,OAAO6E,UAAU,OAAOA,WAAW,YAAY,CAACvD,MAAMC,OAAO,CAACsD,UACzDA,SACD,CAAC;AACP;AAEA,SAASC,MAAM3D,KAAc;IAC3B,OAAOA,SAAS,OAAOA,UAAU,YAAY,CAACG,MAAMC,OAAO,CAACJ,SACvDA,QACD,CAAC;AACP;AAEA;;;;;;;;;;;;;;CAcC,GACD,SAAS4D,YAAYC,OAAY,EAAEC,KAAU;IAC3C,MAAMnC,QAAa,aAAKkC;QAASE,iBAAiBD;;IAClD,KAAK,MAAM1B,OAAO9B,OAAOC,IAAI,CAACuD,OAAQ;QACpC,IAAI,CAAE1B,CAAAA,OAAOT,KAAI,GAAIA,KAAK,CAACS,IAAI,GAAG;IACpC;IACA,OAAOT;AACT;AAEA;;;;;CAKC,GACD,OAAO,SAASqC,iBAAiBzC,QAAa,EAAEC,MAAW;QACnCrC;IAAtB,MAAM8E,iBAAgB9E,yBAAAA,sBAAsBoC,QAAQ,CAAC,QAAQ,aAAvCpC,yBAA4C;IAClE,MAAM+E,eAAehF,cAAcsC;IACnC,MAAM2C,aAAa;WACd,IAAI/C,IAAI;eACNX,QAAQc,QAAQ,CAAC3C,+BAA+B;eAChDsF;SACJ;KACF,CACExD,MAAM,CAAC,CAAC0D,QAAUA,UAAUH,eAC5B5C,KAAK,CAAC,GAAG1C;IAEZ,MAAMwD,MAAW;QACf,CAACvD,+BAA+B,EAAEuF;IACpC;IACA,6EAA6E;IAC7E,MAAME,eAAe7D,KAAKe,QAAQ,CAAC,OAAO,EAAErB,IAAI;IAChD,MAAMoE,aAAa9D,KAAKgB,MAAM,CAAC,OAAO,EAAEtB,IAAI;IAC5C,IAAI,CAACmE,gBAAgBC,YAAYhE,OAAOiE,MAAM,CAACpC,KAAK1C,iBAAiB6E;IACrE,4CAA4C;IAC5C,KAAK,MAAMlC,OAAO;QAAC;QAAS;KAAc,CAAW;QACnD,IAAIrC,QAAQwB,QAAQ,CAACa,IAAI,KAAK,CAACrC,QAAQyB,MAAM,CAACY,IAAI,GAAGD,GAAG,CAACC,IAAI,GAAGZ,MAAM,CAACY,IAAI;IAC7E;IACA,2EAA2E;IAC3E,+BAA+B;IAC/B,MAAMoC,YAAYzD,MAAMQ,QAAQ,CAAC,YAAY,EAAEC,MAAM,CAAC,YAAY;IAClEW,GAAG,CAAC,YAAY,GAAGqC;IACnB,MAAMC,aAAa1D,MAAMQ,QAAQ,CAAC,oBAAoB,EAAEC,MAAM,CAAC,oBAAoB;IACnF,IAAIiD,WAAWpE,MAAM,EAAE8B,GAAG,CAAC,oBAAoB,GAAGsC;IAClD,MAAMC,UAAU3D,MACdQ,QAAQ,CAACxC,uBAAuB,EAChCyC,MAAM,CAACzC,uBAAuB,EAC9BD;IAEF,IAAI4F,QAAQrE,MAAM,EAAE8B,GAAG,CAACpD,uBAAuB,GAAG2F;IAClD,MAAMC,oBAAoBlE,QAAQc,QAAQ,CAAClC,0BAA0B;IACrE,MAAMuF,kBAAkBnE,QAAQe,MAAM,CAACnC,0BAA0B;IACjE,MAAMwF,aAAa;WAAI,IAAIzD,IAAI;eAAIuD;eAAsBC;SAAgB;KAAE;IAC3E,IAAIC,WAAWxE,MAAM,EAAE8B,GAAG,CAAC9C,0BAA0B,GAAGwF;IACxD,MAAMC,gBAAgBH,kBACnBjE,MAAM,CAAC,CAACqE,KAAOH,gBAAgBI,QAAQ,CAACD,KACxCE,GAAG,CAAC,CAACC,YAAe,CAAA;YAAEA;YAAWC,OAAO,CAAC;QAAW,CAAA;IACvD,+DAA+D;IAC/D,MAAMrC,OAAO/B,MAAMQ,QAAQ,CAAC,OAAO,EAAEC,MAAM,CAAC,OAAO;IACnD,IAAIsB,KAAKzC,MAAM,EAAE8B,GAAG,CAAC,OAAO,GAAGW;IAC/B,MAAME,QAAQvB,UAAUF,QAAQ,CAAC,QAAQ,EAAEC,MAAM,CAAC,QAAQ;IAC1D,IAAIwB,OAAOb,GAAG,CAAC,QAAQ,GAAGa;IAC1B,IAAI,CAACjD,QAAQwB,QAAQ,CAAC,SAAS,KAAK,CAACxB,QAAQyB,MAAM,CAAC,SAAS,GAAG;QAC9DW,GAAG,CAAC,SAAS,GAAGM,YAAYlB,QAAQ,CAAC,SAAS,EAAEC,MAAM,CAAC,SAAS;IAClE;IACA,0EAA0E;IAC1E,6EAA6E;IAC7E,MAAM4D,kBAAkBzB,MAAMpC,QAAQ,CAAChC,gCAAgC;IACvE,MAAM8F,gBAAgB1B,MAAMnC,MAAM,CAACjC,gCAAgC;IACnE,MAAM+F,gBAAqB,aAAKD,eAAkBD;IAClD,KAAK,MAAM,CAACrD,QAAQ/B,MAAM,IAAIM,OAAOoC,OAAO,CAAC2C,eAAgB;QAC3D,MAAMxB,UAAUF,MAAM3D;QACtB,IAAI6D,OAAO,CAACrE,wBAAwB,KAAK,OAAO;QAChD,IAAI,CAAEuC,CAAAA,UAAUqD,eAAc,GAAI;QAClC,MAAMG,WAAW5B,MAAMyB,eAAe,CAACrD,OAAO;QAC9C,IAAIwD,QAAQ,CAAC/F,wBAAwB,KAAK,OAAO;QACjD8F,aAAa,CAACvD,OAAO,GAAG6B,YAAYC,SAAS0B;IAC/C;IACA,IAAIjF,OAAOC,IAAI,CAAC+E,eAAejF,MAAM,EAAE;QACrC8B,GAAG,CAAC5C,gCAAgC,GAAG+F;IACzC;IACA,IAAI/D,QAAQ,CAAC,mBAAmB,KAAK,SAASC,MAAM,CAAC,mBAAmB,KAAK,OAAO;QAClFW,GAAG,CAAC,mBAAmB,GAAG;IAC5B,OAAO,IAAIZ,QAAQ,CAAC,mBAAmB,KAAK,QAAQC,MAAM,CAAC,mBAAmB,KAAK,MAAM;QACvFW,GAAG,CAAC,mBAAmB,GAAG;IAC5B;IACA,6EAA6E;IAC7E,MAAMqD,iBAAiBhC,SAASjC;IAChC,MAAMkE,eAAejC,SAAShC;IAC9B,MAAMkC,SAA8B,CAAC;IACrC,KAAK,MAAM,CAACgC,SAASC,MAAM,IAAIrF,OAAOoC,OAAO,CAAC+C,cAAe;QAC3D/B,MAAM,CAACgC,QAAQ,GAAG/C,kBAAkB6C,cAAc,CAACE,QAAQ,EAAEC;IAC/D;IACA,IAAIrF,OAAOC,IAAI,CAACmD,QAAQrD,MAAM,EAAE8B,GAAG,CAACtD,qBAAqB,GAAG6E;IAE5D,OAAO;QACLnC,UAAUY;QACVyD,QAAQ;YAAC3B;eAAkBE;SAAW,CAACzD,MAAM,CAACmF;QAC9C3B;QACAY;QACAN;IACF;AACF;AAuBA,SAASsB,YAAY9F,KAAc;IACjC,MAAM+F,UAAUpC,MAAM3D;IACtB,OAAO;QAAC;QAAS;QAAS;QAAQ;QAAS;QAAc;KAAU,CAChEiF,GAAG,CAAC,CAAC7C,MAAQ5B,KAAKuF,OAAO,CAAC3D,IAAI,EAAElC,IAAI,IACpCQ,MAAM,CAACmF,SACP7D,IAAI,CAAC;AACV;AAEA,SAASgE,SAASzE,QAAgB,EAAEC,MAAc,EAAEyE,MAAc;IAChE,IAAI,CAACA,QAAQ,OAAO;IACpB,IAAI1E,YAAYC,UAAUD,aAAaC,UAAUyE,WAAW1E,YAAY0E,WAAWzE,QAAQ;QACzF,OAAO;IACT;IACA,IAAIyE,WAAW1E,YAAYA,aAAaC,QAAQ,OAAO;IACvD,OAAOyE,WAAW1E,WAAW,aAAa;AAC5C;AAEA;;;;;;;;CAQC,GACD,OAAO,SAAS2E,oBACd3E,QAAa,EACbC,MAAW,EACXkE,OAAe,EACfS,UAAsC,CAAC,CAAC;QAcrBA;IAZnB,MAAMC,OAAOpC,iBAAiBzC,UAAUC;IACxC,MAAM6E,QAAa,aACd9E,UACA6E,KAAK7E,QAAQ;QAChB,CAAC1C,qBAAqB,EAAE,aACnB2E,SAASjC,WACToC,MAAMyC,KAAK7E,QAAQ,CAAC1C,qBAAqB;;IAGhD,MAAMmC,IAAI5B,iBAAiBmC,UAAUmE;IACrC,MAAMzE,IAAI7B,iBAAiBoC,QAAQkE;IACnC,MAAMY,IAAIlH,iBAAiBiH,OAAOX;IAClC,MAAMa,cAAaJ,sBAAAA,QAAQI,UAAU,YAAlBJ,sBAAuB,CAACK,MAAgBA;IAC3D,MAAMC,QAAQ,CAACzG,QACb,OAAOA,UAAU,YAAYA,SAASV,iCAClCA,8BAA8B,CAACU,MAAqD,GACpF;IACN,MAAM0G,QAAQ,CAAC1G,QAAoBQ,KAAKR,SAASuG,WAAW/F,KAAKR,UAAU;IAC3E,MAAM2G,OAAO,CAAC3G,QAAmBS,QAAQT,OAAOgC,IAAI,CAAC;IACrD,MAAM4E,QAAQ,CAACjB;YAEoBA;eADjCA,MAAMkB,WAAW,GACb,GAAGlB,MAAMkB,WAAW,CAAC,IAAI,EAAE,AAAC,CAAA,EAAClB,kBAAAA,MAAMmB,QAAQ,YAAdnB,kBAAkB,KAAK,GAAE,EAAGoB,OAAO,CAAC,IAAI,GACrE;;IACN,MAAMC,MAAM,CACV5E,KACA6E,OACA9D,MACAC,OACA6C,SAC4B,CAAA;YAC5B7D;YACA6E;YACA1F,UAAU4B;YACV3B,QAAQ4B;YACR6C;YACAiB,MAAMlB,SAAS7C,MAAMC,OAAO6C;QAC9B,CAAA;IACA,MAAMkB,OAAiC;QACrCH,IACE,QACA,QACA/H,mBAAmBsC,UAAUmE,UAC7BzG,mBAAmBuC,QAAQkE,UAC3BzG,mBAAmBoH,OAAOX;QAE5BsB,IACE,SACA,SACA9H,cAAcqC,UAAUS,IAAI,CAAC,OAC7B9C,cAAcsC,QAAQQ,IAAI,CAAC,OAC3BoE,KAAKR,MAAM,CAAC5D,IAAI,CAAC;QAEnBgF,IAAI,SAAS,SAASxG,KAAKQ,EAAEoG,KAAK,GAAG5G,KAAKS,EAAEmG,KAAK,GAAG5G,KAAK8F,EAAEc,KAAK;QAChEJ,IAAI,YAAY,aAAaxG,KAAKQ,EAAEqG,QAAQ,GAAG7G,KAAKS,EAAEoG,QAAQ,GAAG7G,KAAK8F,EAAEe,QAAQ;QAChFL,IACE,WACA,WACAxG,KAAKQ,EAAEsG,WAAW,GAClB9G,KAAKS,EAAEqG,WAAW,GAClB9G,KAAK8F,EAAEgB,WAAW;QAEpBN,IACE,kBACA,SACAP,MAAMzF,EAAEuG,cAAc,GACtBd,MAAMxF,EAAEsG,cAAc,GACtBd,MAAMH,EAAEiB,cAAc;QAExBP,IAAI,SAAS,SAASN,MAAM1F,EAAEwG,QAAQ,GAAGd,MAAMzF,EAAEuG,QAAQ,GAAGd,MAAMJ,EAAEkB,QAAQ;QAC5ER,IAAI,QAAQ,QAAQL,KAAK3F,EAAE8B,IAAI,GAAG6D,KAAK1F,EAAE6B,IAAI,GAAG6D,KAAKL,EAAExD,IAAI;QAC3DkE,IAAI,SAAS,SAASxG,KAAKQ,EAAEgC,KAAK,GAAGxC,KAAKS,EAAE+B,KAAK,GAAGxC,KAAK8F,EAAEtD,KAAK;QAChEgE,IACE,WACA,WACAlB,YAAY9E,EAAE+E,OAAO,GACrBD,YAAY7E,EAAE8E,OAAO,GACrBD,YAAYQ,EAAEP,OAAO;QAEvBiB,IAAI,UAAU,UAAUJ,MAAM5F,IAAI4F,MAAM3F,IAAI2F,MAAMN;QAClDU,IACE,YACA,oBACAhG,EAAE6B,YAAY,CAACxC,MAAM,GAAGoH,OAAOzG,EAAE6B,YAAY,CAACxC,MAAM,IAAI,IACxDY,EAAE4B,YAAY,CAACxC,MAAM,GAAGoH,OAAOxG,EAAE4B,YAAY,CAACxC,MAAM,IAAI,IACxDiG,EAAEzD,YAAY,CAACxC,MAAM,GAAGoH,OAAOnB,EAAEzD,YAAY,CAACxC,MAAM,IAAI;KAE3D;IACD,MAAMqH,aAAa;WACd,IAAItG,IAAI;eAAId,OAAOC,IAAI,CAACoD,MAAM3C,EAAEiC,MAAM;eAAO3C,OAAOC,IAAI,CAACoD,MAAM1C,EAAEgC,MAAM;SAAG;KAC9E,CAACT,IAAI;IACN,KAAK,MAAMJ,OAAOsF,WAAY;QAC5B,MAAMC,OAAO,CAAChC;YACZ,MAAM3F,QAAQ2D,MAAMgC,MAAM1C,MAAM,CAAC,CAACb,IAAI;YACtC,OAAOpC,UAAU,QAAQA,UAAUC,YAAY,KAAKwH,OAAOzH;QAC7D;QACAmH,KAAK5E,IAAI,CAACyE,IAAI,CAAC,OAAO,EAAE5E,KAAK,EAAEA,KAAKuF,KAAK3G,IAAI2G,KAAK1G,IAAI0G,KAAKrB;IAC7D;IACA,OAAOa;AACT"}
|