@aglyn/aglyn 1.0.0-beta.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +11 -0
- package/package.json +66 -0
- package/src/index.d.ts +25 -0
- package/src/index.js +26 -0
- package/src/index.js.map +1 -0
- package/src/lib/aglyn.d.ts +31 -0
- package/src/lib/aglyn.js +114 -0
- package/src/lib/aglyn.js.map +1 -0
- package/src/lib/app-utils/abuse-report.d.ts +193 -0
- package/src/lib/app-utils/abuse-report.js +321 -0
- package/src/lib/app-utils/abuse-report.js.map +1 -0
- package/src/lib/app-utils/accept-negotiation.d.ts +129 -0
- package/src/lib/app-utils/accept-negotiation.js +266 -0
- package/src/lib/app-utils/accept-negotiation.js.map +1 -0
- package/src/lib/app-utils/account-emails.d.ts +263 -0
- package/src/lib/app-utils/account-emails.js +264 -0
- package/src/lib/app-utils/account-emails.js.map +1 -0
- package/src/lib/app-utils/actions.d.ts +717 -0
- package/src/lib/app-utils/actions.js +1031 -0
- package/src/lib/app-utils/actions.js.map +1 -0
- package/src/lib/app-utils/activity-presenter.d.ts +152 -0
- package/src/lib/app-utils/activity-presenter.js +326 -0
- package/src/lib/app-utils/activity-presenter.js.map +1 -0
- package/src/lib/app-utils/advertising-tag-mounts.d.ts +133 -0
- package/src/lib/app-utils/advertising-tag-mounts.js +118 -0
- package/src/lib/app-utils/advertising-tag-mounts.js.map +1 -0
- package/src/lib/app-utils/advertising-tags.d.ts +307 -0
- package/src/lib/app-utils/advertising-tags.js +525 -0
- package/src/lib/app-utils/advertising-tags.js.map +1 -0
- package/src/lib/app-utils/agent-api-catalog.d.ts +94 -0
- package/src/lib/app-utils/agent-api-catalog.js +106 -0
- package/src/lib/app-utils/agent-api-catalog.js.map +1 -0
- package/src/lib/app-utils/agent-openapi.d.ts +103 -0
- package/src/lib/app-utils/agent-openapi.js +1128 -0
- package/src/lib/app-utils/agent-openapi.js.map +1 -0
- package/src/lib/app-utils/analytics-beacon.d.ts +154 -0
- package/src/lib/app-utils/analytics-beacon.js +152 -0
- package/src/lib/app-utils/analytics-beacon.js.map +1 -0
- package/src/lib/app-utils/analytics-environment.d.ts +133 -0
- package/src/lib/app-utils/analytics-environment.js +152 -0
- package/src/lib/app-utils/analytics-environment.js.map +1 -0
- package/src/lib/app-utils/analytics-events.d.ts +744 -0
- package/src/lib/app-utils/analytics-events.js +650 -0
- package/src/lib/app-utils/analytics-events.js.map +1 -0
- package/src/lib/app-utils/analytics-link-clicks.d.ts +102 -0
- package/src/lib/app-utils/analytics-link-clicks.js +267 -0
- package/src/lib/app-utils/analytics-link-clicks.js.map +1 -0
- package/src/lib/app-utils/analytics-path-key.d.ts +46 -0
- package/src/lib/app-utils/analytics-path-key.js +46 -0
- package/src/lib/app-utils/analytics-path-key.js.map +1 -0
- package/src/lib/app-utils/api-adapter.d.ts +47 -0
- package/src/lib/app-utils/api-adapter.js +367 -0
- package/src/lib/app-utils/api-adapter.js.map +1 -0
- package/src/lib/app-utils/api-idempotency.d.ts +169 -0
- package/src/lib/app-utils/api-idempotency.js +213 -0
- package/src/lib/app-utils/api-idempotency.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +210 -0
- package/src/lib/app-utils/api-plugins.js +221 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -0
- package/src/lib/app-utils/assist-credits.d.ts +482 -0
- package/src/lib/app-utils/assist-credits.js +509 -0
- package/src/lib/app-utils/assist-credits.js.map +1 -0
- package/src/lib/app-utils/attribution-attribute.d.ts +34 -0
- package/src/lib/app-utils/attribution-attribute.js +34 -0
- package/src/lib/app-utils/attribution-attribute.js.map +1 -0
- package/src/lib/app-utils/attribution-guard.d.ts +130 -0
- package/src/lib/app-utils/attribution-guard.js +410 -0
- package/src/lib/app-utils/attribution-guard.js.map +1 -0
- package/src/lib/app-utils/author-css.d.ts +123 -0
- package/src/lib/app-utils/author-css.js +275 -0
- package/src/lib/app-utils/author-css.js.map +1 -0
- package/src/lib/app-utils/author-html-markdown.d.ts +31 -0
- package/src/lib/app-utils/author-html-markdown.js +497 -0
- package/src/lib/app-utils/author-html-markdown.js.map +1 -0
- package/src/lib/app-utils/author-html.d.ts +135 -0
- package/src/lib/app-utils/author-html.js +1037 -0
- package/src/lib/app-utils/author-html.js.map +1 -0
- package/src/lib/app-utils/automation-placeholders.d.ts +72 -0
- package/src/lib/app-utils/automation-placeholders.js +207 -0
- package/src/lib/app-utils/automation-placeholders.js.map +1 -0
- package/src/lib/app-utils/bandwidth-cap.d.ts +183 -0
- package/src/lib/app-utils/bandwidth-cap.js +193 -0
- package/src/lib/app-utils/bandwidth-cap.js.map +1 -0
- package/src/lib/app-utils/binding-token-catalog.d.ts +82 -0
- package/src/lib/app-utils/binding-token-catalog.js +293 -0
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -0
- package/src/lib/app-utils/binding-tokens.d.ts +157 -0
- package/src/lib/app-utils/binding-tokens.js +251 -0
- package/src/lib/app-utils/binding-tokens.js.map +1 -0
- package/src/lib/app-utils/breadcrumb-json-ld.d.ts +57 -0
- package/src/lib/app-utils/breadcrumb-json-ld.js +67 -0
- package/src/lib/app-utils/breadcrumb-json-ld.js.map +1 -0
- package/src/lib/app-utils/campaign-attribution.d.ts +117 -0
- package/src/lib/app-utils/campaign-attribution.js +162 -0
- package/src/lib/app-utils/campaign-attribution.js.map +1 -0
- package/src/lib/app-utils/campaign-forwarding.d.ts +220 -0
- package/src/lib/app-utils/campaign-forwarding.js +332 -0
- package/src/lib/app-utils/campaign-forwarding.js.map +1 -0
- package/src/lib/app-utils/campaign-membership.d.ts +109 -0
- package/src/lib/app-utils/campaign-membership.js +176 -0
- package/src/lib/app-utils/campaign-membership.js.map +1 -0
- package/src/lib/app-utils/campaign-touch.d.ts +206 -0
- package/src/lib/app-utils/campaign-touch.js +326 -0
- package/src/lib/app-utils/campaign-touch.js.map +1 -0
- package/src/lib/app-utils/child-contract-compose.d.ts +28 -0
- package/src/lib/app-utils/child-contract-compose.js +140 -0
- package/src/lib/app-utils/child-contract-compose.js.map +1 -0
- package/src/lib/app-utils/child-contract.d.ts +129 -0
- package/src/lib/app-utils/child-contract.js +153 -0
- package/src/lib/app-utils/child-contract.js.map +1 -0
- package/src/lib/app-utils/collection-delete.d.ts +113 -0
- package/src/lib/app-utils/collection-delete.js +120 -0
- package/src/lib/app-utils/collection-delete.js.map +1 -0
- package/src/lib/app-utils/collection-entries.d.ts +833 -0
- package/src/lib/app-utils/collection-entries.js +1285 -0
- package/src/lib/app-utils/collection-entries.js.map +1 -0
- package/src/lib/app-utils/collection-entry-date.d.ts +129 -0
- package/src/lib/app-utils/collection-entry-date.js +183 -0
- package/src/lib/app-utils/collection-entry-date.js.map +1 -0
- package/src/lib/app-utils/collection-kind.d.ts +55 -0
- package/src/lib/app-utils/collection-kind.js +69 -0
- package/src/lib/app-utils/collection-kind.js.map +1 -0
- package/src/lib/app-utils/collection-slug.d.ts +79 -0
- package/src/lib/app-utils/collection-slug.js +70 -0
- package/src/lib/app-utils/collection-slug.js.map +1 -0
- package/src/lib/app-utils/compose-layout-nodes.d.ts +147 -0
- package/src/lib/app-utils/compose-layout-nodes.js +261 -0
- package/src/lib/app-utils/compose-layout-nodes.js.map +1 -0
- package/src/lib/app-utils/compose-layout-props.d.ts +71 -0
- package/src/lib/app-utils/compose-layout-props.js +61 -0
- package/src/lib/app-utils/compose-layout-props.js.map +1 -0
- package/src/lib/app-utils/compose-reusable-components.d.ts +504 -0
- package/src/lib/app-utils/compose-reusable-components.js +1366 -0
- package/src/lib/app-utils/compose-reusable-components.js.map +1 -0
- package/src/lib/app-utils/compress.d.ts +35 -0
- package/src/lib/app-utils/compress.js +38 -0
- package/src/lib/app-utils/compress.js.map +1 -0
- package/src/lib/app-utils/consent-banner-ui.d.ts +226 -0
- package/src/lib/app-utils/consent-banner-ui.js +583 -0
- package/src/lib/app-utils/consent-banner-ui.js.map +1 -0
- package/src/lib/app-utils/consent-groups.d.ts +189 -0
- package/src/lib/app-utils/consent-groups.js +219 -0
- package/src/lib/app-utils/consent-groups.js.map +1 -0
- package/src/lib/app-utils/consent-preferences-dialog.d.ts +58 -0
- package/src/lib/app-utils/consent-preferences-dialog.js +106 -0
- package/src/lib/app-utils/consent-preferences-dialog.js.map +1 -0
- package/src/lib/app-utils/console-record-links.d.ts +163 -0
- package/src/lib/app-utils/console-record-links.js +178 -0
- package/src/lib/app-utils/console-record-links.js.map +1 -0
- package/src/lib/app-utils/console-routes.d.ts +658 -0
- package/src/lib/app-utils/console-routes.js +489 -0
- package/src/lib/app-utils/console-routes.js.map +1 -0
- package/src/lib/app-utils/console-widget-slot-context.d.ts +46 -0
- package/src/lib/app-utils/console-widget-slot-context.js +23 -0
- package/src/lib/app-utils/console-widget-slot-context.js.map +1 -0
- package/src/lib/app-utils/contact-custom-fields.d.ts +191 -0
- package/src/lib/app-utils/contact-custom-fields.js +349 -0
- package/src/lib/app-utils/contact-custom-fields.js.map +1 -0
- package/src/lib/app-utils/contact-holder.d.ts +52 -0
- package/src/lib/app-utils/contact-holder.js +98 -0
- package/src/lib/app-utils/contact-holder.js.map +1 -0
- package/src/lib/app-utils/contact-merge.d.ts +136 -0
- package/src/lib/app-utils/contact-merge.js +379 -0
- package/src/lib/app-utils/contact-merge.js.map +1 -0
- package/src/lib/app-utils/contacts.d.ts +554 -0
- package/src/lib/app-utils/contacts.js +401 -0
- package/src/lib/app-utils/contacts.js.map +1 -0
- package/src/lib/app-utils/content-author-profile.d.ts +68 -0
- package/src/lib/app-utils/content-author-profile.js +118 -0
- package/src/lib/app-utils/content-author-profile.js.map +1 -0
- package/src/lib/app-utils/content-authors.d.ts +662 -0
- package/src/lib/app-utils/content-authors.js +771 -0
- package/src/lib/app-utils/content-authors.js.map +1 -0
- package/src/lib/app-utils/content-schema-type.d.ts +81 -0
- package/src/lib/app-utils/content-schema-type.js +87 -0
- package/src/lib/app-utils/content-schema-type.js.map +1 -0
- package/src/lib/app-utils/contexts.d.ts +35 -0
- package/src/lib/app-utils/contexts.js +35 -0
- package/src/lib/app-utils/contexts.js.map +1 -0
- package/src/lib/app-utils/create-resource-uid.d.ts +18 -0
- package/src/lib/app-utils/create-resource-uid.js +23 -0
- package/src/lib/app-utils/create-resource-uid.js.map +1 -0
- package/src/lib/app-utils/crm-booking.d.ts +75 -0
- package/src/lib/app-utils/crm-booking.js +133 -0
- package/src/lib/app-utils/crm-booking.js.map +1 -0
- package/src/lib/app-utils/crm-csv.d.ts +232 -0
- package/src/lib/app-utils/crm-csv.js +432 -0
- package/src/lib/app-utils/crm-csv.js.map +1 -0
- package/src/lib/app-utils/crm-digest.d.ts +179 -0
- package/src/lib/app-utils/crm-digest.js +271 -0
- package/src/lib/app-utils/crm-digest.js.map +1 -0
- package/src/lib/app-utils/crm-email-templates.d.ts +172 -0
- package/src/lib/app-utils/crm-email-templates.js +382 -0
- package/src/lib/app-utils/crm-email-templates.js.map +1 -0
- package/src/lib/app-utils/crm-inbound.d.ts +245 -0
- package/src/lib/app-utils/crm-inbound.js +407 -0
- package/src/lib/app-utils/crm-inbound.js.map +1 -0
- package/src/lib/app-utils/crm-kinds.d.ts +73 -0
- package/src/lib/app-utils/crm-kinds.js +92 -0
- package/src/lib/app-utils/crm-kinds.js.map +1 -0
- package/src/lib/app-utils/crm-next-activity.d.ts +107 -0
- package/src/lib/app-utils/crm-next-activity.js +140 -0
- package/src/lib/app-utils/crm-next-activity.js.map +1 -0
- package/src/lib/app-utils/crm-reports.d.ts +479 -0
- package/src/lib/app-utils/crm-reports.js +680 -0
- package/src/lib/app-utils/crm-reports.js.map +1 -0
- package/src/lib/app-utils/crm-task-reminders.d.ts +129 -0
- package/src/lib/app-utils/crm-task-reminders.js +139 -0
- package/src/lib/app-utils/crm-task-reminders.js.map +1 -0
- package/src/lib/app-utils/crm.d.ts +1546 -0
- package/src/lib/app-utils/crm.js +1814 -0
- package/src/lib/app-utils/crm.js.map +1 -0
- package/src/lib/app-utils/csp-report.d.ts +84 -0
- package/src/lib/app-utils/csp-report.js +177 -0
- package/src/lib/app-utils/csp-report.js.map +1 -0
- package/src/lib/app-utils/csv-import.d.ts +192 -0
- package/src/lib/app-utils/csv-import.js +279 -0
- package/src/lib/app-utils/csv-import.js.map +1 -0
- package/src/lib/app-utils/dataset-csv.d.ts +109 -0
- package/src/lib/app-utils/dataset-csv.js +235 -0
- package/src/lib/app-utils/dataset-csv.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +194 -0
- package/src/lib/app-utils/dataset-models.js +409 -0
- package/src/lib/app-utils/dataset-models.js.map +1 -0
- package/src/lib/app-utils/dataset-query.d.ts +57 -0
- package/src/lib/app-utils/dataset-query.js +126 -0
- package/src/lib/app-utils/dataset-query.js.map +1 -0
- package/src/lib/app-utils/datasets.d.ts +136 -0
- package/src/lib/app-utils/datasets.js +177 -0
- package/src/lib/app-utils/datasets.js.map +1 -0
- package/src/lib/app-utils/decompress.d.ts +36 -0
- package/src/lib/app-utils/decompress.js +32 -0
- package/src/lib/app-utils/decompress.js.map +1 -0
- package/src/lib/app-utils/dedicated-sending-domain.d.ts +47 -0
- package/src/lib/app-utils/dedicated-sending-domain.js +114 -0
- package/src/lib/app-utils/dedicated-sending-domain.js.map +1 -0
- package/src/lib/app-utils/deferred-image.d.ts +86 -0
- package/src/lib/app-utils/deferred-image.js +83 -0
- package/src/lib/app-utils/deferred-image.js.map +1 -0
- package/src/lib/app-utils/definition-canvas-tree.d.ts +61 -0
- package/src/lib/app-utils/definition-canvas-tree.js +126 -0
- package/src/lib/app-utils/definition-canvas-tree.js.map +1 -0
- package/src/lib/app-utils/deployment-shape.d.ts +167 -0
- package/src/lib/app-utils/deployment-shape.js +238 -0
- package/src/lib/app-utils/deployment-shape.js.map +1 -0
- package/src/lib/app-utils/detect-template-placeholders.d.ts +30 -0
- package/src/lib/app-utils/detect-template-placeholders.js +53 -0
- package/src/lib/app-utils/detect-template-placeholders.js.map +1 -0
- package/src/lib/app-utils/dmca-counter-notice.d.ts +185 -0
- package/src/lib/app-utils/dmca-counter-notice.js +277 -0
- package/src/lib/app-utils/dmca-counter-notice.js.map +1 -0
- package/src/lib/app-utils/docs-deflection.d.ts +156 -0
- package/src/lib/app-utils/docs-deflection.js +547 -0
- package/src/lib/app-utils/docs-deflection.js.map +1 -0
- package/src/lib/app-utils/docs-help.d.ts +57 -0
- package/src/lib/app-utils/docs-help.generated.d.ts +303 -0
- package/src/lib/app-utils/docs-help.generated.js +867 -0
- package/src/lib/app-utils/docs-help.generated.js.map +1 -0
- package/src/lib/app-utils/docs-help.js +46 -0
- package/src/lib/app-utils/docs-help.js.map +1 -0
- package/src/lib/app-utils/docs-index.generated.d.ts +29 -0
- package/src/lib/app-utils/docs-index.generated.js +8388 -0
- package/src/lib/app-utils/docs-index.generated.js.map +1 -0
- package/src/lib/app-utils/docs-retrieval.d.ts +67 -0
- package/src/lib/app-utils/docs-retrieval.js +188 -0
- package/src/lib/app-utils/docs-retrieval.js.map +1 -0
- package/src/lib/app-utils/document-landmark.d.ts +50 -0
- package/src/lib/app-utils/document-landmark.js +100 -0
- package/src/lib/app-utils/document-landmark.js.map +1 -0
- package/src/lib/app-utils/duplicate-resource.d.ts +101 -0
- package/src/lib/app-utils/duplicate-resource.js +206 -0
- package/src/lib/app-utils/duplicate-resource.js.map +1 -0
- package/src/lib/app-utils/dynamic-list-rule.d.ts +471 -0
- package/src/lib/app-utils/dynamic-list-rule.js +914 -0
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -0
- package/src/lib/app-utils/element-animation.d.ts +200 -0
- package/src/lib/app-utils/element-animation.js +233 -0
- package/src/lib/app-utils/element-animation.js.map +1 -0
- package/src/lib/app-utils/element-hidden-style.d.ts +46 -0
- package/src/lib/app-utils/element-hidden-style.js +48 -0
- package/src/lib/app-utils/element-hidden-style.js.map +1 -0
- package/src/lib/app-utils/element-ui.d.ts +243 -0
- package/src/lib/app-utils/element-ui.js +459 -0
- package/src/lib/app-utils/element-ui.js.map +1 -0
- package/src/lib/app-utils/email-starter-policy.d.ts +160 -0
- package/src/lib/app-utils/email-starter-policy.js +327 -0
- package/src/lib/app-utils/email-starter-policy.js.map +1 -0
- package/src/lib/app-utils/email-topics.d.ts +310 -0
- package/src/lib/app-utils/email-topics.js +336 -0
- package/src/lib/app-utils/email-topics.js.map +1 -0
- package/src/lib/app-utils/enabled-plugins-context.d.ts +100 -0
- package/src/lib/app-utils/enabled-plugins-context.js +113 -0
- package/src/lib/app-utils/enabled-plugins-context.js.map +1 -0
- package/src/lib/app-utils/ensure-canvas-root.d.ts +38 -0
- package/src/lib/app-utils/ensure-canvas-root.js +61 -0
- package/src/lib/app-utils/ensure-canvas-root.js.map +1 -0
- package/src/lib/app-utils/entity-picker-context.d.ts +199 -0
- package/src/lib/app-utils/entity-picker-context.js +93 -0
- package/src/lib/app-utils/entity-picker-context.js.map +1 -0
- package/src/lib/app-utils/error-beacon.d.ts +107 -0
- package/src/lib/app-utils/error-beacon.js +296 -0
- package/src/lib/app-utils/error-beacon.js.map +1 -0
- package/src/lib/app-utils/expand-repeatables.d.ts +172 -0
- package/src/lib/app-utils/expand-repeatables.js +299 -0
- package/src/lib/app-utils/expand-repeatables.js.map +1 -0
- package/src/lib/app-utils/foreign-script.d.ts +82 -0
- package/src/lib/app-utils/foreign-script.js +102 -0
- package/src/lib/app-utils/foreign-script.js.map +1 -0
- package/src/lib/app-utils/form-abuse-ceiling.d.ts +146 -0
- package/src/lib/app-utils/form-abuse-ceiling.js +158 -0
- package/src/lib/app-utils/form-abuse-ceiling.js.map +1 -0
- package/src/lib/app-utils/form-contract.d.ts +198 -0
- package/src/lib/app-utils/form-contract.js +282 -0
- package/src/lib/app-utils/form-contract.js.map +1 -0
- package/src/lib/app-utils/form-dataset-binding.d.ts +50 -0
- package/src/lib/app-utils/form-dataset-binding.js +74 -0
- package/src/lib/app-utils/form-dataset-binding.js.map +1 -0
- package/src/lib/app-utils/forms.d.ts +727 -0
- package/src/lib/app-utils/forms.js +777 -0
- package/src/lib/app-utils/forms.js.map +1 -0
- package/src/lib/app-utils/functions.d.ts +188 -0
- package/src/lib/app-utils/functions.js +529 -0
- package/src/lib/app-utils/functions.js.map +1 -0
- package/src/lib/app-utils/guarded-version-save.d.ts +91 -0
- package/src/lib/app-utils/guarded-version-save.js +131 -0
- package/src/lib/app-utils/guarded-version-save.js.map +1 -0
- package/src/lib/app-utils/health-report.d.ts +1766 -0
- package/src/lib/app-utils/health-report.js +2072 -0
- package/src/lib/app-utils/health-report.js.map +1 -0
- package/src/lib/app-utils/host-naming.d.ts +135 -0
- package/src/lib/app-utils/host-naming.js +188 -0
- package/src/lib/app-utils/host-naming.js.map +1 -0
- package/src/lib/app-utils/host-permissions.d.ts +76 -0
- package/src/lib/app-utils/host-permissions.js +119 -0
- package/src/lib/app-utils/host-permissions.js.map +1 -0
- package/src/lib/app-utils/host-tokens.d.ts +228 -0
- package/src/lib/app-utils/host-tokens.js +304 -0
- package/src/lib/app-utils/host-tokens.js.map +1 -0
- package/src/lib/app-utils/idp-profile.d.ts +83 -0
- package/src/lib/app-utils/idp-profile.js +268 -0
- package/src/lib/app-utils/idp-profile.js.map +1 -0
- package/src/lib/app-utils/image-upload-types.d.ts +49 -0
- package/src/lib/app-utils/image-upload-types.js +86 -0
- package/src/lib/app-utils/image-upload-types.js.map +1 -0
- package/src/lib/app-utils/index.d.ts +18 -0
- package/src/lib/app-utils/index.js +23 -0
- package/src/lib/app-utils/index.js.map +1 -0
- package/src/lib/app-utils/internal-traffic.d.ts +197 -0
- package/src/lib/app-utils/internal-traffic.js +288 -0
- package/src/lib/app-utils/internal-traffic.js.map +1 -0
- package/src/lib/app-utils/lineal-order.d.ts +62 -0
- package/src/lib/app-utils/lineal-order.js +65 -0
- package/src/lib/app-utils/lineal-order.js.map +1 -0
- package/src/lib/app-utils/link-references.d.ts +36 -0
- package/src/lib/app-utils/link-references.js +89 -0
- package/src/lib/app-utils/link-references.js.map +1 -0
- package/src/lib/app-utils/link-target-search-context.d.ts +123 -0
- package/src/lib/app-utils/link-target-search-context.js +221 -0
- package/src/lib/app-utils/link-target-search-context.js.map +1 -0
- package/src/lib/app-utils/list-assignment-policy.d.ts +169 -0
- package/src/lib/app-utils/list-assignment-policy.js +170 -0
- package/src/lib/app-utils/list-assignment-policy.js.map +1 -0
- package/src/lib/app-utils/list-import.d.ts +158 -0
- package/src/lib/app-utils/list-import.js +332 -0
- package/src/lib/app-utils/list-import.js.map +1 -0
- package/src/lib/app-utils/llms-txt.d.ts +104 -0
- package/src/lib/app-utils/llms-txt.js +144 -0
- package/src/lib/app-utils/llms-txt.js.map +1 -0
- package/src/lib/app-utils/local-storage-budget.d.ts +75 -0
- package/src/lib/app-utils/local-storage-budget.js +153 -0
- package/src/lib/app-utils/local-storage-budget.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +698 -0
- package/src/lib/app-utils/lockdown.js +929 -0
- package/src/lib/app-utils/lockdown.js.map +1 -0
- package/src/lib/app-utils/margin-utilization.d.ts +267 -0
- package/src/lib/app-utils/margin-utilization.js +351 -0
- package/src/lib/app-utils/margin-utilization.js.map +1 -0
- package/src/lib/app-utils/markdown-lite.d.ts +297 -0
- package/src/lib/app-utils/markdown-lite.js +705 -0
- package/src/lib/app-utils/markdown-lite.js.map +1 -0
- package/src/lib/app-utils/marketing-consent.d.ts +704 -0
- package/src/lib/app-utils/marketing-consent.js +783 -0
- package/src/lib/app-utils/marketing-consent.js.map +1 -0
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +120 -0
- package/src/lib/app-utils/marketplace-listing-visibility.js +139 -0
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +1 -0
- package/src/lib/app-utils/marketplace-overrides.d.ts +271 -0
- package/src/lib/app-utils/marketplace-overrides.js +462 -0
- package/src/lib/app-utils/marketplace-overrides.js.map +1 -0
- package/src/lib/app-utils/marketplace-provenance.d.ts +150 -0
- package/src/lib/app-utils/marketplace-provenance.js +136 -0
- package/src/lib/app-utils/marketplace-provenance.js.map +1 -0
- package/src/lib/app-utils/marketplace-theme.d.ts +237 -0
- package/src/lib/app-utils/marketplace-theme.js +525 -0
- package/src/lib/app-utils/marketplace-theme.js.map +1 -0
- package/src/lib/app-utils/marketplace-update-state.d.ts +119 -0
- package/src/lib/app-utils/marketplace-update-state.js +132 -0
- package/src/lib/app-utils/marketplace-update-state.js.map +1 -0
- package/src/lib/app-utils/marketplace-verification.d.ts +95 -0
- package/src/lib/app-utils/marketplace-verification.js +81 -0
- package/src/lib/app-utils/marketplace-verification.js.map +1 -0
- package/src/lib/app-utils/measure-node-map.d.ts +76 -0
- package/src/lib/app-utils/measure-node-map.js +111 -0
- package/src/lib/app-utils/measure-node-map.js.map +1 -0
- package/src/lib/app-utils/media-alt.d.ts +55 -0
- package/src/lib/app-utils/media-alt.js +58 -0
- package/src/lib/app-utils/media-alt.js.map +1 -0
- package/src/lib/app-utils/media-asset-facts.d.ts +125 -0
- package/src/lib/app-utils/media-asset-facts.js +467 -0
- package/src/lib/app-utils/media-asset-facts.js.map +1 -0
- package/src/lib/app-utils/media-cdn-scope.d.ts +65 -0
- package/src/lib/app-utils/media-cdn-scope.js +75 -0
- package/src/lib/app-utils/media-cdn-scope.js.map +1 -0
- package/src/lib/app-utils/media-folders.d.ts +161 -0
- package/src/lib/app-utils/media-folders.js +230 -0
- package/src/lib/app-utils/media-folders.js.map +1 -0
- package/src/lib/app-utils/media-metadata.d.ts +277 -0
- package/src/lib/app-utils/media-metadata.js +388 -0
- package/src/lib/app-utils/media-metadata.js.map +1 -0
- package/src/lib/app-utils/media-picker-context.d.ts +93 -0
- package/src/lib/app-utils/media-picker-context.js +26 -0
- package/src/lib/app-utils/media-picker-context.js.map +1 -0
- package/src/lib/app-utils/media-quarantine.d.ts +247 -0
- package/src/lib/app-utils/media-quarantine.js +323 -0
- package/src/lib/app-utils/media-quarantine.js.map +1 -0
- package/src/lib/app-utils/media-ref.d.ts +661 -0
- package/src/lib/app-utils/media-ref.js +1055 -0
- package/src/lib/app-utils/media-ref.js.map +1 -0
- package/src/lib/app-utils/media-takedown-reach.d.ts +126 -0
- package/src/lib/app-utils/media-takedown-reach.js +143 -0
- package/src/lib/app-utils/media-takedown-reach.js.map +1 -0
- package/src/lib/app-utils/member-email-aliases.d.ts +180 -0
- package/src/lib/app-utils/member-email-aliases.js +217 -0
- package/src/lib/app-utils/member-email-aliases.js.map +1 -0
- package/src/lib/app-utils/merge-node-sx.d.ts +47 -0
- package/src/lib/app-utils/merge-node-sx.js +123 -0
- package/src/lib/app-utils/merge-node-sx.js.map +1 -0
- package/src/lib/app-utils/name-match.d.ts +155 -0
- package/src/lib/app-utils/name-match.js +175 -0
- package/src/lib/app-utils/name-match.js.map +1 -0
- package/src/lib/app-utils/name-search.d.ts +117 -0
- package/src/lib/app-utils/name-search.js +145 -0
- package/src/lib/app-utils/name-search.js.map +1 -0
- package/src/lib/app-utils/node-capabilities.d.ts +85 -0
- package/src/lib/app-utils/node-capabilities.js +88 -0
- package/src/lib/app-utils/node-capabilities.js.map +1 -0
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +164 -0
- package/src/lib/app-utils/node-definition-sanitizer.js +402 -0
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -0
- package/src/lib/app-utils/node-identity.d.ts +47 -0
- package/src/lib/app-utils/node-identity.js +50 -0
- package/src/lib/app-utils/node-identity.js.map +1 -0
- package/src/lib/app-utils/node-interactions.d.ts +102 -0
- package/src/lib/app-utils/node-interactions.js +192 -0
- package/src/lib/app-utils/node-interactions.js.map +1 -0
- package/src/lib/app-utils/node-url-policy.d.ts +54 -0
- package/src/lib/app-utils/node-url-policy.js +72 -0
- package/src/lib/app-utils/node-url-policy.js.map +1 -0
- package/src/lib/app-utils/notifications.d.ts +71 -0
- package/src/lib/app-utils/notifications.js +101 -0
- package/src/lib/app-utils/notifications.js.map +1 -0
- package/src/lib/app-utils/onboarding-deep-link.d.ts +120 -0
- package/src/lib/app-utils/onboarding-deep-link.js +142 -0
- package/src/lib/app-utils/onboarding-deep-link.js.map +1 -0
- package/src/lib/app-utils/operator-identity.d.ts +207 -0
- package/src/lib/app-utils/operator-identity.js +186 -0
- package/src/lib/app-utils/operator-identity.js.map +1 -0
- package/src/lib/app-utils/org-billing-doc.d.ts +231 -0
- package/src/lib/app-utils/org-billing-doc.js +238 -0
- package/src/lib/app-utils/org-billing-doc.js.map +1 -0
- package/src/lib/app-utils/org-override-reason.d.ts +100 -0
- package/src/lib/app-utils/org-override-reason.js +116 -0
- package/src/lib/app-utils/org-override-reason.js.map +1 -0
- package/src/lib/app-utils/org-permissions.d.ts +194 -0
- package/src/lib/app-utils/org-permissions.js +357 -0
- package/src/lib/app-utils/org-permissions.js.map +1 -0
- package/src/lib/app-utils/org-roles.d.ts +72 -0
- package/src/lib/app-utils/org-roles.js +131 -0
- package/src/lib/app-utils/org-roles.js.map +1 -0
- package/src/lib/app-utils/organizations.d.ts +407 -0
- package/src/lib/app-utils/organizations.js +511 -0
- package/src/lib/app-utils/organizations.js.map +1 -0
- package/src/lib/app-utils/page-header-actions-context.d.ts +83 -0
- package/src/lib/app-utils/page-header-actions-context.js +58 -0
- package/src/lib/app-utils/page-header-actions-context.js.map +1 -0
- package/src/lib/app-utils/page-header-record-context.d.ts +80 -0
- package/src/lib/app-utils/page-header-record-context.js +64 -0
- package/src/lib/app-utils/page-header-record-context.js.map +1 -0
- package/src/lib/app-utils/page-markdown.d.ts +103 -0
- package/src/lib/app-utils/page-markdown.js +385 -0
- package/src/lib/app-utils/page-markdown.js.map +1 -0
- package/src/lib/app-utils/paid-media-source.d.ts +90 -0
- package/src/lib/app-utils/paid-media-source.js +184 -0
- package/src/lib/app-utils/paid-media-source.js.map +1 -0
- package/src/lib/app-utils/palette-sx.d.ts +34 -0
- package/src/lib/app-utils/palette-sx.js +150 -0
- package/src/lib/app-utils/palette-sx.js.map +1 -0
- package/src/lib/app-utils/password-policy.d.ts +47 -0
- package/src/lib/app-utils/password-policy.js +46 -0
- package/src/lib/app-utils/password-policy.js.map +1 -0
- package/src/lib/app-utils/payments-configured.d.ts +84 -0
- package/src/lib/app-utils/payments-configured.js +88 -0
- package/src/lib/app-utils/payments-configured.js.map +1 -0
- package/src/lib/app-utils/person-erasure.d.ts +126 -0
- package/src/lib/app-utils/person-erasure.js +121 -0
- package/src/lib/app-utils/person-erasure.js.map +1 -0
- package/src/lib/app-utils/person-key.d.ts +32 -0
- package/src/lib/app-utils/person-key.js +62 -0
- package/src/lib/app-utils/person-key.js.map +1 -0
- package/src/lib/app-utils/plan-entitlements.d.ts +2756 -0
- package/src/lib/app-utils/plan-entitlements.js +4085 -0
- package/src/lib/app-utils/plan-entitlements.js.map +1 -0
- package/src/lib/app-utils/platform-ad-conversions.d.ts +122 -0
- package/src/lib/app-utils/platform-ad-conversions.js +174 -0
- package/src/lib/app-utils/platform-ad-conversions.js.map +1 -0
- package/src/lib/app-utils/platform-advertising-tags.d.ts +139 -0
- package/src/lib/app-utils/platform-advertising-tags.js +203 -0
- package/src/lib/app-utils/platform-advertising-tags.js.map +1 -0
- package/src/lib/app-utils/platform-brand.d.ts +151 -0
- package/src/lib/app-utils/platform-brand.js +175 -0
- package/src/lib/app-utils/platform-brand.js.map +1 -0
- package/src/lib/app-utils/platform-consent-default.d.ts +142 -0
- package/src/lib/app-utils/platform-consent-default.js +295 -0
- package/src/lib/app-utils/platform-consent-default.js.map +1 -0
- package/src/lib/app-utils/platform-marketing-consent.d.ts +151 -0
- package/src/lib/app-utils/platform-marketing-consent.js +182 -0
- package/src/lib/app-utils/platform-marketing-consent.js.map +1 -0
- package/src/lib/app-utils/platform-marketing-host.d.ts +33 -0
- package/src/lib/app-utils/platform-marketing-host.js +97 -0
- package/src/lib/app-utils/platform-marketing-host.js.map +1 -0
- package/src/lib/app-utils/platform-visitor-consent.d.ts +252 -0
- package/src/lib/app-utils/platform-visitor-consent.js +533 -0
- package/src/lib/app-utils/platform-visitor-consent.js.map +1 -0
- package/src/lib/app-utils/plugin-api-cross-origin.d.ts +61 -0
- package/src/lib/app-utils/plugin-api-cross-origin.js +202 -0
- package/src/lib/app-utils/plugin-api-cross-origin.js.map +1 -0
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +192 -0
- package/src/lib/app-utils/plugin-api-rate-limit.js +270 -0
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -0
- package/src/lib/app-utils/plugin-artifact-path.d.ts +32 -0
- package/src/lib/app-utils/plugin-artifact-path.js +33 -0
- package/src/lib/app-utils/plugin-artifact-path.js.map +1 -0
- package/src/lib/app-utils/plugin-bundle-checks.d.ts +148 -0
- package/src/lib/app-utils/plugin-bundle-checks.js +989 -0
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -0
- package/src/lib/app-utils/plugin-manifest.d.ts +516 -0
- package/src/lib/app-utils/plugin-manifest.js +687 -0
- package/src/lib/app-utils/plugin-manifest.js.map +1 -0
- package/src/lib/app-utils/published-legal-pages.d.ts +71 -0
- package/src/lib/app-utils/published-legal-pages.js +90 -0
- package/src/lib/app-utils/published-legal-pages.js.map +1 -0
- package/src/lib/app-utils/publisher-agreement.d.ts +254 -0
- package/src/lib/app-utils/publisher-agreement.js +274 -0
- package/src/lib/app-utils/publisher-agreement.js.map +1 -0
- package/src/lib/app-utils/publisher-attestation.d.ts +99 -0
- package/src/lib/app-utils/publisher-attestation.js +158 -0
- package/src/lib/app-utils/publisher-attestation.js.map +1 -0
- package/src/lib/app-utils/recipient-email-render.d.ts +216 -0
- package/src/lib/app-utils/recipient-email-render.js +221 -0
- package/src/lib/app-utils/recipient-email-render.js.map +1 -0
- package/src/lib/app-utils/redispatch-caught-error.d.ts +38 -0
- package/src/lib/app-utils/redispatch-caught-error.js +46 -0
- package/src/lib/app-utils/redispatch-caught-error.js.map +1 -0
- package/src/lib/app-utils/registering-plugin.d.ts +19 -0
- package/src/lib/app-utils/registering-plugin.js +38 -0
- package/src/lib/app-utils/registering-plugin.js.map +1 -0
- package/src/lib/app-utils/release-flags.d.ts +283 -0
- package/src/lib/app-utils/release-flags.js +518 -0
- package/src/lib/app-utils/release-flags.js.map +1 -0
- package/src/lib/app-utils/repair-canvas-nodes.d.ts +130 -0
- package/src/lib/app-utils/repair-canvas-nodes.js +298 -0
- package/src/lib/app-utils/repair-canvas-nodes.js.map +1 -0
- package/src/lib/app-utils/repeat-infringer.d.ts +166 -0
- package/src/lib/app-utils/repeat-infringer.js +188 -0
- package/src/lib/app-utils/repeat-infringer.js.map +1 -0
- package/src/lib/app-utils/repeat-sources.d.ts +115 -0
- package/src/lib/app-utils/repeat-sources.js +86 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -0
- package/src/lib/app-utils/request-geo.d.ts +114 -0
- package/src/lib/app-utils/request-geo.js +247 -0
- package/src/lib/app-utils/request-geo.js.map +1 -0
- package/src/lib/app-utils/request-ip.d.ts +213 -0
- package/src/lib/app-utils/request-ip.js +344 -0
- package/src/lib/app-utils/request-ip.js.map +1 -0
- package/src/lib/app-utils/resolve-named-tokens.d.ts +26 -0
- package/src/lib/app-utils/resolve-named-tokens.js +59 -0
- package/src/lib/app-utils/resolve-named-tokens.js.map +1 -0
- package/src/lib/app-utils/responsive-typography-sx.d.ts +77 -0
- package/src/lib/app-utils/responsive-typography-sx.js +122 -0
- package/src/lib/app-utils/responsive-typography-sx.js.map +1 -0
- package/src/lib/app-utils/reusable-component-keys.d.ts +135 -0
- package/src/lib/app-utils/reusable-component-keys.js +140 -0
- package/src/lib/app-utils/reusable-component-keys.js.map +1 -0
- package/src/lib/app-utils/reusable-prop-values.d.ts +199 -0
- package/src/lib/app-utils/reusable-prop-values.js +494 -0
- package/src/lib/app-utils/reusable-prop-values.js.map +1 -0
- package/src/lib/app-utils/safe-json-ld.d.ts +29 -0
- package/src/lib/app-utils/safe-json-ld.js +37 -0
- package/src/lib/app-utils/safe-json-ld.js.map +1 -0
- package/src/lib/app-utils/sanitize-svg.d.ts +55 -0
- package/src/lib/app-utils/sanitize-svg.js +460 -0
- package/src/lib/app-utils/sanitize-svg.js.map +1 -0
- package/src/lib/app-utils/scheme-sx.d.ts +84 -0
- package/src/lib/app-utils/scheme-sx.js +148 -0
- package/src/lib/app-utils/scheme-sx.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +249 -0
- package/src/lib/app-utils/scope-tokens.js +331 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -0
- package/src/lib/app-utils/screen-link-context-value.d.ts +57 -0
- package/src/lib/app-utils/screen-link-context-value.js +43 -0
- package/src/lib/app-utils/screen-link-context-value.js.map +1 -0
- package/src/lib/app-utils/screen-link-context.d.ts +185 -0
- package/src/lib/app-utils/screen-link-context.js +304 -0
- package/src/lib/app-utils/screen-link-context.js.map +1 -0
- package/src/lib/app-utils/screen-link-value.d.ts +269 -0
- package/src/lib/app-utils/screen-link-value.js +384 -0
- package/src/lib/app-utils/screen-link-value.js.map +1 -0
- package/src/lib/app-utils/screen-route.d.ts +669 -0
- package/src/lib/app-utils/screen-route.js +751 -0
- package/src/lib/app-utils/screen-route.js.map +1 -0
- package/src/lib/app-utils/screen-seo-fields.d.ts +37 -0
- package/src/lib/app-utils/screen-seo-fields.js +42 -0
- package/src/lib/app-utils/screen-seo-fields.js.map +1 -0
- package/src/lib/app-utils/search-indexing.d.ts +162 -0
- package/src/lib/app-utils/search-indexing.js +207 -0
- package/src/lib/app-utils/search-indexing.js.map +1 -0
- package/src/lib/app-utils/seo-listing-fields.d.ts +70 -0
- package/src/lib/app-utils/seo-listing-fields.js +75 -0
- package/src/lib/app-utils/seo-listing-fields.js.map +1 -0
- package/src/lib/app-utils/seo-locale.d.ts +119 -0
- package/src/lib/app-utils/seo-locale.js +133 -0
- package/src/lib/app-utils/seo-locale.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.d.ts +149 -0
- package/src/lib/app-utils/seo-title-variables.js +190 -0
- package/src/lib/app-utils/seo-title-variables.js.map +1 -0
- package/src/lib/app-utils/seo-title.d.ts +70 -0
- package/src/lib/app-utils/seo-title.js +117 -0
- package/src/lib/app-utils/seo-title.js.map +1 -0
- package/src/lib/app-utils/server.d.ts +174 -0
- package/src/lib/app-utils/server.js +314 -0
- package/src/lib/app-utils/server.js.map +1 -0
- package/src/lib/app-utils/site-context.d.ts +106 -0
- package/src/lib/app-utils/site-context.js +100 -0
- package/src/lib/app-utils/site-context.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +117 -0
- package/src/lib/app-utils/sitemap.js +183 -0
- package/src/lib/app-utils/sitemap.js.map +1 -0
- package/src/lib/app-utils/social-image.d.ts +112 -0
- package/src/lib/app-utils/social-image.js +191 -0
- package/src/lib/app-utils/social-image.js.map +1 -0
- package/src/lib/app-utils/starter-templates.d.ts +99 -0
- package/src/lib/app-utils/starter-templates.js +579 -0
- package/src/lib/app-utils/starter-templates.js.map +1 -0
- package/src/lib/app-utils/stored-nodes.d.ts +120 -0
- package/src/lib/app-utils/stored-nodes.js +174 -0
- package/src/lib/app-utils/stored-nodes.js.map +1 -0
- package/src/lib/app-utils/strip-undefined.d.ts +59 -0
- package/src/lib/app-utils/strip-undefined.js +95 -0
- package/src/lib/app-utils/strip-undefined.js.map +1 -0
- package/src/lib/app-utils/stripe-deployment-mode.d.ts +47 -0
- package/src/lib/app-utils/stripe-deployment-mode.js +70 -0
- package/src/lib/app-utils/stripe-deployment-mode.js.map +1 -0
- package/src/lib/app-utils/support-tiers.d.ts +108 -0
- package/src/lib/app-utils/support-tiers.js +201 -0
- package/src/lib/app-utils/support-tiers.js.map +1 -0
- package/src/lib/app-utils/timezone-geo-hint.d.ts +36 -0
- package/src/lib/app-utils/timezone-geo-hint.js +180 -0
- package/src/lib/app-utils/timezone-geo-hint.js.map +1 -0
- package/src/lib/app-utils/upload-cors.d.ts +155 -0
- package/src/lib/app-utils/upload-cors.js +254 -0
- package/src/lib/app-utils/upload-cors.js.map +1 -0
- package/src/lib/app-utils/upload-inspection.d.ts +159 -0
- package/src/lib/app-utils/upload-inspection.js +539 -0
- package/src/lib/app-utils/upload-inspection.js.map +1 -0
- package/src/lib/app-utils/url-slug.d.ts +40 -0
- package/src/lib/app-utils/url-slug.js +42 -0
- package/src/lib/app-utils/url-slug.js.map +1 -0
- package/src/lib/app-utils/usage-budget.d.ts +429 -0
- package/src/lib/app-utils/usage-budget.js +421 -0
- package/src/lib/app-utils/usage-budget.js.map +1 -0
- package/src/lib/app-utils/variables.d.ts +96 -0
- package/src/lib/app-utils/variables.js +233 -0
- package/src/lib/app-utils/variables.js.map +1 -0
- package/src/lib/app-utils/video-asset-facts.d.ts +61 -0
- package/src/lib/app-utils/video-asset-facts.js +70 -0
- package/src/lib/app-utils/video-asset-facts.js.map +1 -0
- package/src/lib/app-utils/video-object.d.ts +89 -0
- package/src/lib/app-utils/video-object.js +245 -0
- package/src/lib/app-utils/video-object.js.map +1 -0
- package/src/lib/app-utils/visitor-consent.d.ts +757 -0
- package/src/lib/app-utils/visitor-consent.js +981 -0
- package/src/lib/app-utils/visitor-consent.js.map +1 -0
- package/src/lib/app-utils/visitor-record-ceiling.d.ts +223 -0
- package/src/lib/app-utils/visitor-record-ceiling.js +215 -0
- package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -0
- package/src/lib/app-utils/web-vitals-rum.d.ts +53 -0
- package/src/lib/app-utils/web-vitals-rum.js +278 -0
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -0
- package/src/lib/app-utils/webhook-delivery.d.ts +324 -0
- package/src/lib/app-utils/webhook-delivery.js +413 -0
- package/src/lib/app-utils/webhook-delivery.js.map +1 -0
- package/src/lib/app-utils/where-used.d.ts +57 -0
- package/src/lib/app-utils/where-used.js +59 -0
- package/src/lib/app-utils/where-used.js.map +1 -0
- package/src/lib/app-utils/wistia-embed.d.ts +86 -0
- package/src/lib/app-utils/wistia-embed.js +119 -0
- package/src/lib/app-utils/wistia-embed.js.map +1 -0
- package/src/lib/app-utils/workflows.d.ts +136 -0
- package/src/lib/app-utils/workflows.js +346 -0
- package/src/lib/app-utils/workflows.js.map +1 -0
- package/src/lib/canvas-manager/canvas-manager-tree.d.ts +109 -0
- package/src/lib/canvas-manager/canvas-manager-tree.js +139 -0
- package/src/lib/canvas-manager/canvas-manager-tree.js.map +1 -0
- package/src/lib/canvas-manager/canvas-manager.d.ts +549 -0
- package/src/lib/canvas-manager/canvas-manager.js +1311 -0
- package/src/lib/canvas-manager/canvas-manager.js.map +1 -0
- package/src/lib/canvas-manager/index.d.ts +20 -0
- package/src/lib/canvas-manager/index.js +21 -0
- package/src/lib/canvas-manager/index.js.map +1 -0
- package/src/lib/canvas-manager/stores/index.d.ts +17 -0
- package/src/lib/canvas-manager/stores/index.js +18 -0
- package/src/lib/canvas-manager/stores/index.js.map +1 -0
- package/src/lib/canvas-manager/stores/node.store.d.ts +30 -0
- package/src/lib/canvas-manager/stores/node.store.js +45 -0
- package/src/lib/canvas-manager/stores/node.store.js.map +1 -0
- package/src/lib/components-manager/components-manager.d.ts +56 -0
- package/src/lib/components-manager/components-manager.js +191 -0
- package/src/lib/components-manager/components-manager.js.map +1 -0
- package/src/lib/components-manager/index.d.ts +18 -0
- package/src/lib/components-manager/index.js +19 -0
- package/src/lib/components-manager/index.js.map +1 -0
- package/src/lib/emit-manager/emit-manager.d.ts +56 -0
- package/src/lib/emit-manager/emit-manager.js +60 -0
- package/src/lib/emit-manager/emit-manager.js.map +1 -0
- package/src/lib/emit-manager/index.d.ts +18 -0
- package/src/lib/emit-manager/index.js +19 -0
- package/src/lib/emit-manager/index.js.map +1 -0
- package/src/lib/foundation/constants/_internal.d.ts +18 -0
- package/src/lib/foundation/constants/_internal.js +62 -0
- package/src/lib/foundation/constants/_internal.js.map +1 -0
- package/src/lib/foundation/constants/app.d.ts +23 -0
- package/src/lib/foundation/constants/app.js +25 -0
- package/src/lib/foundation/constants/app.js.map +1 -0
- package/src/lib/foundation/constants/canvas.d.ts +18 -0
- package/src/lib/foundation/constants/canvas.js +18 -0
- package/src/lib/foundation/constants/canvas.js.map +1 -0
- package/src/lib/foundation/constants/components.d.ts +54 -0
- package/src/lib/foundation/constants/components.js +61 -0
- package/src/lib/foundation/constants/components.js.map +1 -0
- package/src/lib/foundation/constants/shared.d.ts +50 -0
- package/src/lib/foundation/constants/shared.js +49 -0
- package/src/lib/foundation/constants/shared.js.map +1 -0
- package/src/lib/foundation/constants/symbol.d.ts +63 -0
- package/src/lib/foundation/constants/symbol.js +75 -0
- package/src/lib/foundation/constants/symbol.js.map +1 -0
- package/src/lib/foundation/definitions/components.types.d.ts +372 -0
- package/src/lib/foundation/definitions/components.types.js +180 -0
- package/src/lib/foundation/definitions/components.types.js.map +1 -0
- package/src/lib/foundation/definitions/contact.types.d.ts +73 -0
- package/src/lib/foundation/definitions/contact.types.js +107 -0
- package/src/lib/foundation/definitions/contact.types.js.map +1 -0
- package/src/lib/foundation/definitions/host-content-collections.d.ts +137 -0
- package/src/lib/foundation/definitions/host-content-collections.js +219 -0
- package/src/lib/foundation/definitions/host-content-collections.js.map +1 -0
- package/src/lib/foundation/definitions/org-billing.types.d.ts +1361 -0
- package/src/lib/foundation/definitions/org-billing.types.js +77 -0
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -0
- package/src/lib/foundation/definitions/organization.types.d.ts +307 -0
- package/src/lib/foundation/definitions/organization.types.js +42 -0
- package/src/lib/foundation/definitions/organization.types.js.map +1 -0
- package/src/lib/foundation/definitions/platform.types.d.ts +1326 -0
- package/src/lib/foundation/definitions/platform.types.js +124 -0
- package/src/lib/foundation/definitions/platform.types.js.map +1 -0
- package/src/lib/foundation/definitions/property-kinds.d.ts +189 -0
- package/src/lib/foundation/definitions/property-kinds.js +565 -0
- package/src/lib/foundation/definitions/property-kinds.js.map +1 -0
- package/src/lib/foundation/definitions/shared.d.ts +23 -0
- package/src/lib/foundation/definitions/shared.js +18 -0
- package/src/lib/foundation/definitions/shared.js.map +1 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +249 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +499 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -0
- package/src/lib/foundation/index.d.ts +32 -0
- package/src/lib/foundation/index.js +67 -0
- package/src/lib/foundation/index.js.map +1 -0
- package/src/lib/lifecycle.d.ts +24 -0
- package/src/lib/lifecycle.js +39 -0
- package/src/lib/lifecycle.js.map +1 -0
- package/src/lib/mst/common.d.ts +17 -0
- package/src/lib/mst/common.js +23 -0
- package/src/lib/mst/common.js.map +1 -0
- package/src/lib/mst/index.d.ts +19 -0
- package/src/lib/mst/index.js +20 -0
- package/src/lib/mst/index.js.map +1 -0
- package/src/lib/mst/json.d.ts +22 -0
- package/src/lib/mst/json.js +23 -0
- package/src/lib/mst/json.js.map +1 -0
- package/src/lib/mst/types.d.ts +20 -0
- package/src/lib/mst/types.js +18 -0
- package/src/lib/mst/types.js.map +1 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.d.ts +77 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.js +55 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.js.map +1 -0
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +172 -0
- package/src/lib/plugin-manager/commerce-zone-props.js +31 -0
- package/src/lib/plugin-manager/commerce-zone-props.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +60 -0
- package/src/lib/plugin-manager/custom-fields.js +39 -0
- package/src/lib/plugin-manager/custom-fields.js.map +1 -0
- package/src/lib/plugin-manager/editor-sessions.d.ts +109 -0
- package/src/lib/plugin-manager/editor-sessions.js +137 -0
- package/src/lib/plugin-manager/editor-sessions.js.map +1 -0
- package/src/lib/plugin-manager/enabled-plugins.d.ts +438 -0
- package/src/lib/plugin-manager/enabled-plugins.js +403 -0
- package/src/lib/plugin-manager/enabled-plugins.js.map +1 -0
- package/src/lib/plugin-manager/feature-plugins.d.ts +1314 -0
- package/src/lib/plugin-manager/feature-plugins.js +609 -0
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +11 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +149 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -0
- package/src/lib/plugin-manager/index.d.ts +42 -0
- package/src/lib/plugin-manager/index.js +46 -0
- package/src/lib/plugin-manager/index.js.map +1 -0
- package/src/lib/plugin-manager/install-presets.d.ts +93 -0
- package/src/lib/plugin-manager/install-presets.js +86 -0
- package/src/lib/plugin-manager/install-presets.js.map +1 -0
- package/src/lib/plugin-manager/media-delivery-provider.d.ts +124 -0
- package/src/lib/plugin-manager/media-delivery-provider.js +53 -0
- package/src/lib/plugin-manager/media-delivery-provider.js.map +1 -0
- package/src/lib/plugin-manager/order-fulfilment.d.ts +142 -0
- package/src/lib/plugin-manager/order-fulfilment.js +104 -0
- package/src/lib/plugin-manager/order-fulfilment.js.map +1 -0
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +122 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +140 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-bridge.d.ts +98 -0
- package/src/lib/plugin-manager/plugin-bridge.js +154 -0
- package/src/lib/plugin-manager/plugin-bridge.js.map +1 -0
- package/src/lib/plugin-manager/plugin-config.d.ts +148 -0
- package/src/lib/plugin-manager/plugin-config.js +228 -0
- package/src/lib/plugin-manager/plugin-config.js.map +1 -0
- package/src/lib/plugin-manager/plugin-console-crons.d.ts +139 -0
- package/src/lib/plugin-manager/plugin-console-crons.js +177 -0
- package/src/lib/plugin-manager/plugin-console-crons.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contact-capture.d.ts +220 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js +89 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contributions.d.ts +244 -0
- package/src/lib/plugin-manager/plugin-contributions.js +283 -0
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.d.ts +169 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.js +84 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlements.d.ts +181 -0
- package/src/lib/plugin-manager/plugin-entitlements.js +188 -0
- package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-events.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-events.js +79 -0
- package/src/lib/plugin-manager/plugin-events.js.map +1 -0
- package/src/lib/plugin-manager/plugin-figures.d.ts +251 -0
- package/src/lib/plugin-manager/plugin-figures.js +252 -0
- package/src/lib/plugin-manager/plugin-figures.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +146 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +116 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-jobs.d.ts +130 -0
- package/src/lib/plugin-manager/plugin-jobs.js +182 -0
- package/src/lib/plugin-manager/plugin-jobs.js.map +1 -0
- package/src/lib/plugin-manager/plugin-loader.d.ts +86 -0
- package/src/lib/plugin-manager/plugin-loader.js +223 -0
- package/src/lib/plugin-manager/plugin-loader.js.map +1 -0
- package/src/lib/plugin-manager/plugin-manager.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-manager.js +343 -0
- package/src/lib/plugin-manager/plugin-manager.js.map +1 -0
- package/src/lib/plugin-manager/plugin-metered-lines.d.ts +97 -0
- package/src/lib/plugin-manager/plugin-metered-lines.js +123 -0
- package/src/lib/plugin-manager/plugin-metered-lines.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +52 -0
- package/src/lib/plugin-manager/plugin-org-erasure.js +100 -0
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-permissions.d.ts +69 -0
- package/src/lib/plugin-manager/plugin-permissions.js +77 -0
- package/src/lib/plugin-manager/plugin-permissions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-person-erasure.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-person-erasure.js +109 -0
- package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-cards.d.ts +99 -0
- package/src/lib/plugin-manager/plugin-record-cards.js +59 -0
- package/src/lib/plugin-manager/plugin-record-cards.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-facts.d.ts +111 -0
- package/src/lib/plugin-manager/plugin-record-facts.js +51 -0
- package/src/lib/plugin-manager/plugin-record-facts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-routes.d.ts +129 -0
- package/src/lib/plugin-manager/plugin-record-routes.js +93 -0
- package/src/lib/plugin-manager/plugin-record-routes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-timeline.d.ts +147 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js +39 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +137 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.js +51 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-services.d.ts +94 -0
- package/src/lib/plugin-manager/plugin-services.js +153 -0
- package/src/lib/plugin-manager/plugin-services.js.map +1 -0
- package/src/lib/plugin-manager/plugin-styles-ui.d.ts +71 -0
- package/src/lib/plugin-manager/plugin-styles-ui.js +80 -0
- package/src/lib/plugin-manager/plugin-styles-ui.js.map +1 -0
- package/src/lib/plugin-manager/plugin-styles.d.ts +176 -0
- package/src/lib/plugin-manager/plugin-styles.js +186 -0
- package/src/lib/plugin-manager/plugin-styles.js.map +1 -0
- package/src/lib/plugin-manager/plugin-subprocessors.d.ts +135 -0
- package/src/lib/plugin-manager/plugin-subprocessors.js +129 -0
- package/src/lib/plugin-manager/plugin-subprocessors.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +84 -0
- package/src/lib/plugin-manager/plugin-tax-profile.js +39 -0
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -0
- package/src/lib/plugin-manager/plugin-user-erasure.d.ts +53 -0
- package/src/lib/plugin-manager/plugin-user-erasure.js +84 -0
- package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +121 -0
- package/src/lib/plugin-manager/plugin-zones.js +74 -0
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -0
- package/src/lib/plugin-manager/realm-plugins.d.ts +112 -0
- package/src/lib/plugin-manager/realm-plugins.js +196 -0
- package/src/lib/plugin-manager/realm-plugins.js.map +1 -0
- package/src/lib/plugin-manager/realm-server.d.ts +54 -0
- package/src/lib/plugin-manager/realm-server.js +88 -0
- package/src/lib/plugin-manager/realm-server.js.map +1 -0
- package/src/lib/plugin-manager/record-zone-props.d.ts +126 -0
- package/src/lib/plugin-manager/record-zone-props.js +31 -0
- package/src/lib/plugin-manager/record-zone-props.js.map +1 -0
- package/src/lib/plugin-manager/site-page-hooks.d.ts +102 -0
- package/src/lib/plugin-manager/site-page-hooks.js +114 -0
- package/src/lib/plugin-manager/site-page-hooks.js.map +1 -0
- package/src/lib/plugin-manager/site-runtime.d.ts +57 -0
- package/src/lib/plugin-manager/site-runtime.js +25 -0
- package/src/lib/plugin-manager/site-runtime.js.map +1 -0
- package/src/lib/plugin-manager/usage-alert-contributors.d.ts +115 -0
- package/src/lib/plugin-manager/usage-alert-contributors.js +106 -0
- package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -0
- package/src/lib/types/ast.d.ts +199 -0
- package/src/lib/types/ast.js +20 -0
- package/src/lib/types/ast.js.map +1 -0
- package/src/lib/types/index.d.ts +20 -0
- package/src/lib/types/index.js +21 -0
- package/src/lib/types/index.js.map +1 -0
- package/src/lib/types/nodes.d.ts +608 -0
- package/src/lib/types/nodes.js +28 -0
- package/src/lib/types/nodes.js.map +1 -0
- package/src/lib/types/routing.d.ts +17 -0
- package/src/lib/types/routing.js +18 -0
- package/src/lib/types/routing.js.map +1 -0
- package/src/lib/types/screen.d.ts +23 -0
- package/src/lib/types/screen.js +18 -0
- package/src/lib/types/screen.js.map +1 -0
- package/src/lib/utils.d.ts +25 -0
- package/src/lib/utils.js +42 -0
- package/src/lib/utils.js.map +1 -0
- package/src/server.d.ts +37 -0
- package/src/server.js +55 -0
- package/src/server.js.map +1 -0
|
@@ -0,0 +1,332 @@
|
|
|
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
|
+
* Carry the campaign across the domain hop (AGL-1731).
|
|
18
|
+
*
|
|
19
|
+
* `campaign-attribution.ts` is the READER half of this contract and it works.
|
|
20
|
+
* This is the half that was missing, and without it the reader was fed
|
|
21
|
+
* nothing: `aglyn.com` is a tenant published site and `app.aglyn.com` is the
|
|
22
|
+
* console, a real cross-origin hop, and no code anywhere put a `utm_*`
|
|
23
|
+
* parameter on a console-bound link. So `users/{uid}.signupCampaign` was
|
|
24
|
+
* written for exactly one population — visitors whose CTA href had a campaign
|
|
25
|
+
* typed into it by hand.
|
|
26
|
+
*
|
|
27
|
+
* A hand-typed one is worse than none. It is STATIC: `utm_source=google`
|
|
28
|
+
* authored onto the pricing button attributes every clicker to Google whether
|
|
29
|
+
* they arrived from Google, from Hacker News or from a bookmark. Confidently
|
|
30
|
+
* wrong attribution reaches the same spend decisions as absent attribution and
|
|
31
|
+
* is much harder to notice, because the report looks populated.
|
|
32
|
+
*
|
|
33
|
+
* What is needed instead is PER-VISITOR forwarding: the landing page copies
|
|
34
|
+
* the campaign off its own inbound URL onto the console-bound href, at click
|
|
35
|
+
* time, for that one visitor.
|
|
36
|
+
*
|
|
37
|
+
* ## Why a delegated listener and not `AppLink`
|
|
38
|
+
*
|
|
39
|
+
* The same reason `analytics-link-clicks.ts` gives, and it is the reason that
|
|
40
|
+
* decides this file's shape. The CTAs on `aglyn.com` are authored besigner
|
|
41
|
+
* content, not repo files; rich-text and Custom HTML anchors are written with
|
|
42
|
+
* `dangerouslySetInnerHTML` and are plain DOM anchors with no React handler at
|
|
43
|
+
* all. A prop on `AppLink` would miss them, and reaching them from `AppLink`
|
|
44
|
+
* would mean `useSearchParams` in a component the console renders on every
|
|
45
|
+
* page — a dynamic-rendering hazard on statically generated surfaces, paid on
|
|
46
|
+
* every route to fix a link on one of them. A capture-phase listener on
|
|
47
|
+
* `document` sees every anchor, costs one listener, and renders nothing.
|
|
48
|
+
*
|
|
49
|
+
* ## The two tiers, and why the storage tier is the SECOND one
|
|
50
|
+
*
|
|
51
|
+
* A visitor rarely signs up from the page the ad landed on. They land on
|
|
52
|
+
* `/?utm_source=google&...`, read `/pricing`, then click. By then the campaign
|
|
53
|
+
* is off the address bar, so reading the live URL at click time alone would
|
|
54
|
+
* capture only the minority who convert without navigating.
|
|
55
|
+
*
|
|
56
|
+
* - **Tier 1 — the live URL.** Read `window.location.search` at click time.
|
|
57
|
+
* This touches NO storage: the parameters are already in the page the
|
|
58
|
+
* visitor asked for. Nothing is written to their device, so there is nothing
|
|
59
|
+
* here to consent to, and it works for every visitor including one who has
|
|
60
|
+
* declined analytics.
|
|
61
|
+
* - **Tier 2 — the first touch of the visit**, in `sessionStorage`, which is
|
|
62
|
+
* what survives the walk from the landing page to the pricing page.
|
|
63
|
+
*
|
|
64
|
+
* Tier 2 WINS when both exist, because first touch is the question being
|
|
65
|
+
* asked. Last touch — re-deriving the campaign from whatever URL happens to be
|
|
66
|
+
* current at signup — answers a different question and would disagree with
|
|
67
|
+
* GA4's own session attribution.
|
|
68
|
+
*
|
|
69
|
+
* ## Why tier 2 is gated on analytics consent, and tier 1 is not
|
|
70
|
+
*
|
|
71
|
+
* Tier 2 writes to the visitor's device for an analytics purpose, so it is
|
|
72
|
+
* `analytics_storage` in the consent-mode sense and it waits for the same
|
|
73
|
+
* grant the GA tag waits for (AGL-1498). The gate is not re-implemented here
|
|
74
|
+
* and no consent record is read here: the caller already computes
|
|
75
|
+
* `analyticsAllowed` for the tag and hands the same boolean down, so there is
|
|
76
|
+
* one gate and it cannot drift from itself.
|
|
77
|
+
*
|
|
78
|
+
* It is deliberately NOT gated on advertising storage. Nothing here reads or
|
|
79
|
+
* writes an advertising identifier, sets a cookie, or leaves anything that
|
|
80
|
+
* outlives the tab, and AGL-1649 has advertising denied with no route for a
|
|
81
|
+
* host to grant it — gating on a permission that cannot currently be given
|
|
82
|
+
* would be a feature that is dead by construction rather than one that is off.
|
|
83
|
+
*
|
|
84
|
+
* **Consent unresolved is not consent denied, and both are falsy.** With
|
|
85
|
+
* `strictNullChecks` off repo-wide that distinction is the sort that
|
|
86
|
+
* evaporates, so it is carried as an explicit tri-state: until the caller has
|
|
87
|
+
* actually resolved the visitor's state, tier 2 neither reads nor writes.
|
|
88
|
+
* Failing closed here costs an attribution; failing open would write to a
|
|
89
|
+
* device before the visitor answered.
|
|
90
|
+
*
|
|
91
|
+
* ## What is never done
|
|
92
|
+
*
|
|
93
|
+
* A value is only ever forwarded if this visitor literally arrived carrying
|
|
94
|
+
* it. There is no default, no inference from the referrer, and no
|
|
95
|
+
* `utm_source=direct` — a signup with no campaign must reach the console with
|
|
96
|
+
* no campaign, so that "arrived from nowhere" and "never asked" stay the
|
|
97
|
+
* distinct facts `campaign-attribution.ts` keeps them.
|
|
98
|
+
*
|
|
99
|
+
* Only links to OUR OWN console origin are touched, and the origin is supplied
|
|
100
|
+
* by the caller rather than written here — a self-host install points
|
|
101
|
+
* `NEXT_PUBLIC_CONSOLE_URL` somewhere else entirely. Decorating any other host
|
|
102
|
+
* would post our campaign labels to a third party, which is a data leak dressed
|
|
103
|
+
* up as attribution.
|
|
104
|
+
*
|
|
105
|
+
* ## One accepted consequence
|
|
106
|
+
*
|
|
107
|
+
* The tenant runtime serves `aglyn.com` AND every customer's published site,
|
|
108
|
+
* so a customer site that links to our signup forwards ITS OWN inbound
|
|
109
|
+
* campaign — an agency partner's `utm_source=their-newsletter` would land in our
|
|
110
|
+
* acquisition report describing their spend, not ours. It is not gated on
|
|
111
|
+
* "is this the operator's marketing host" deliberately: that gate needs a
|
|
112
|
+
* second configured origin to compare against, and a deployment that forgot to
|
|
113
|
+
* set it would forward NOTHING while looking perfectly healthy. A silent zero
|
|
114
|
+
* is the exact failure AGL-1731 is about, and it is worse than a few
|
|
115
|
+
* mislabelled rows that GA's own Hostname dimension can already separate.
|
|
116
|
+
*/ import { CAMPAIGN_QUERY_KEYS, campaignAttributionQuery, parseCampaignAttribution } from "./campaign-attribution.js";
|
|
117
|
+
/**
|
|
118
|
+
* Where the first touch of this visit is held. `sessionStorage`, so it dies
|
|
119
|
+
* with the tab: a campaign is a fact about one visit, and a value that
|
|
120
|
+
* outlived the visit would start attributing next week's organic return to
|
|
121
|
+
* this week's ad.
|
|
122
|
+
*/ export const CAMPAIGN_VISIT_STORAGE_KEY = 'aglyn:campaign';
|
|
123
|
+
/**
|
|
124
|
+
* Whether the visitor has granted analytics storage.
|
|
125
|
+
*
|
|
126
|
+
* `null` means NOT YET RESOLVED, and is not the same as `false`. The consent
|
|
127
|
+
* state is settled client-side after hydration, so there is a window in every
|
|
128
|
+
* pageview where the answer is genuinely unknown, and treating it as a denial
|
|
129
|
+
* would be as wrong as treating it as a grant. Tier 2 does nothing in it.
|
|
130
|
+
*/ let storageConsent = null;
|
|
131
|
+
/** The one listener pair on `document`, or null. Held, not flagged — the same
|
|
132
|
+
* reason `analytics-link-clicks.ts` holds its own: a boolean lets a caller
|
|
133
|
+
* install over a listener that is still attached, and re-entrant decoration is
|
|
134
|
+
* harder to see than a double-counted event. */ let installedHandler = null;
|
|
135
|
+
function sessionStore() {
|
|
136
|
+
if (typeof window === 'undefined') return null;
|
|
137
|
+
// Touching the property itself can throw, not just its methods.
|
|
138
|
+
try {
|
|
139
|
+
var _window_sessionStorage;
|
|
140
|
+
return (_window_sessionStorage = window.sessionStorage) != null ? _window_sessionStorage : null;
|
|
141
|
+
} catch (unused) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The campaign this visit began with, as far as the store can say.
|
|
147
|
+
*
|
|
148
|
+
* Re-parsed through the same allowlist that wrote it rather than trusted:
|
|
149
|
+
* `sessionStorage` is writable by anything running on the page, so the stored
|
|
150
|
+
* string can claim no more than an inbound URL could — three allowlisted keys,
|
|
151
|
+
* trimmed, email shapes refused, capped.
|
|
152
|
+
*/ export function readVisitCampaign() {
|
|
153
|
+
if (storageConsent !== true) return {
|
|
154
|
+
status: 'none'
|
|
155
|
+
};
|
|
156
|
+
const store = sessionStore();
|
|
157
|
+
if (!store) return {
|
|
158
|
+
status: 'unreadable'
|
|
159
|
+
};
|
|
160
|
+
let raw;
|
|
161
|
+
try {
|
|
162
|
+
raw = store.getItem(CAMPAIGN_VISIT_STORAGE_KEY);
|
|
163
|
+
} catch (unused) {
|
|
164
|
+
return {
|
|
165
|
+
status: 'unreadable'
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
if (!raw) return {
|
|
169
|
+
status: 'none'
|
|
170
|
+
};
|
|
171
|
+
const campaign = parseCampaignAttribution(new URLSearchParams(raw));
|
|
172
|
+
return campaign ? {
|
|
173
|
+
status: 'campaign',
|
|
174
|
+
campaign
|
|
175
|
+
} : {
|
|
176
|
+
status: 'none'
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Remember the campaign on the current URL as this visit's first touch.
|
|
181
|
+
*
|
|
182
|
+
* First touch means FIRST: an existing entry is never replaced. A second
|
|
183
|
+
* campaign arriving later in the same visit is a link the visitor followed
|
|
184
|
+
* after we already knew where they came from, and letting it overwrite would
|
|
185
|
+
* quietly turn this into last-touch.
|
|
186
|
+
*
|
|
187
|
+
* Returns what is now remembered so a caller can assert on it.
|
|
188
|
+
*/ export function rememberVisitCampaign(search) {
|
|
189
|
+
const existing = readVisitCampaign();
|
|
190
|
+
if (existing.status === 'campaign') return existing.campaign;
|
|
191
|
+
if (storageConsent !== true) return null;
|
|
192
|
+
const store = sessionStore();
|
|
193
|
+
if (!store) return null;
|
|
194
|
+
const source = typeof search === 'string' ? search : typeof window === 'undefined' ? '' : window.location.search;
|
|
195
|
+
const campaign = parseCampaignAttribution(new URLSearchParams(source));
|
|
196
|
+
if (!campaign) return null;
|
|
197
|
+
try {
|
|
198
|
+
store.setItem(CAMPAIGN_VISIT_STORAGE_KEY, campaignAttributionQuery(campaign));
|
|
199
|
+
} catch (unused) {
|
|
200
|
+
// A store that refuses the write costs the walk from the landing page to
|
|
201
|
+
// the pricing page, never the click itself — tier 1 still carries a
|
|
202
|
+
// visitor who converts without navigating.
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
205
|
+
return campaign;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Tell this module what the visitor's analytics consent state is.
|
|
209
|
+
*
|
|
210
|
+
* Called by whoever already computed it for the tag, on every render, so a
|
|
211
|
+
* grant seeds the first touch the moment it is given and a WITHDRAWAL takes
|
|
212
|
+
* effect immediately: the stored value is dropped, not merely ignored. A
|
|
213
|
+
* visitor who changes their mind mid-visit should not leave the thing they
|
|
214
|
+
* withdrew consent for sitting on their device.
|
|
215
|
+
*/ export function setCampaignForwardingConsent(allowed) {
|
|
216
|
+
storageConsent = allowed === true ? true : allowed === false ? false : null;
|
|
217
|
+
if (storageConsent === true) {
|
|
218
|
+
rememberVisitCampaign();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (storageConsent === false) {
|
|
222
|
+
const store = sessionStore();
|
|
223
|
+
if (!store) return;
|
|
224
|
+
try {
|
|
225
|
+
store.removeItem(CAMPAIGN_VISIT_STORAGE_KEY);
|
|
226
|
+
} catch (unused) {
|
|
227
|
+
// Nothing else to try, and a failed cleanup must not break the page.
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The campaign to forward, first touch preferred.
|
|
233
|
+
*
|
|
234
|
+
* The `unreadable` case falls through to the live URL rather than to nothing,
|
|
235
|
+
* which is the point of carrying that state at all: a broken store degrades
|
|
236
|
+
* this to tier 1 rather than to silence.
|
|
237
|
+
*/ export function campaignToForward(search) {
|
|
238
|
+
const stored = readVisitCampaign();
|
|
239
|
+
if (stored.status === 'campaign') return stored.campaign;
|
|
240
|
+
const live = typeof search === 'string' ? search : typeof window === 'undefined' ? '' : window.location.search;
|
|
241
|
+
return parseCampaignAttribution(new URLSearchParams(live));
|
|
242
|
+
}
|
|
243
|
+
function normalizeOrigin(value) {
|
|
244
|
+
if (!value) return '';
|
|
245
|
+
try {
|
|
246
|
+
return new URL(value).origin;
|
|
247
|
+
} catch (unused) {
|
|
248
|
+
return '';
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* The href a console-bound link should carry for this visitor, or null to
|
|
253
|
+
* leave it exactly as authored.
|
|
254
|
+
*
|
|
255
|
+
* Null — rather than "the href unchanged" — so that a caller cannot write back
|
|
256
|
+
* a value it did not mean to change, and so a test can tell "decided not to
|
|
257
|
+
* touch this" from "touched it and produced the same string".
|
|
258
|
+
*
|
|
259
|
+
* The three keys are replaced WHOLESALE, never merged key by key. A visitor
|
|
260
|
+
* who arrived with only `utm_source=hn` clicking a button authored with all
|
|
261
|
+
* three must not produce `source=hn` married to the author's `campaign=`: that
|
|
262
|
+
* row describes an event that never happened. Everything else on the href —
|
|
263
|
+
* `plan`, `interval`, the AGL-1535 intent — is preserved untouched.
|
|
264
|
+
*/ export function decorateCampaignHref(href, baseHref, consoleOrigin, campaign) {
|
|
265
|
+
if (!campaign) return null;
|
|
266
|
+
const origin = normalizeOrigin(consoleOrigin);
|
|
267
|
+
if (!origin) return null;
|
|
268
|
+
let url;
|
|
269
|
+
try {
|
|
270
|
+
url = new URL(href, baseHref);
|
|
271
|
+
} catch (unused) {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
if (url.origin !== origin) return null;
|
|
275
|
+
for (const key of CAMPAIGN_QUERY_KEYS)url.searchParams.delete(key);
|
|
276
|
+
const query = new URLSearchParams(campaignAttributionQuery(campaign));
|
|
277
|
+
query.forEach((value, key)=>url.searchParams.set(key, value));
|
|
278
|
+
const next = url.toString();
|
|
279
|
+
return next === href ? null : next;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Start forwarding the campaign onto console-bound links on this page.
|
|
283
|
+
*
|
|
284
|
+
* Idempotent and safe to call during render, the same contract as
|
|
285
|
+
* `installLinkClickTracking` and for the same AGL-1550 reason: an effect only
|
|
286
|
+
* runs if React commits, and a page that renders without committing would
|
|
287
|
+
* otherwise ship links with no campaign on them.
|
|
288
|
+
*
|
|
289
|
+
* Both `pointerdown` and `click` are listened for, in capture phase.
|
|
290
|
+
* `pointerdown` is what covers a middle-click, a modifier-click into a new
|
|
291
|
+
* tab, and "Copy link address" from the context menu — all of which read the
|
|
292
|
+
* href without ever firing `click`. `click` is what covers keyboard
|
|
293
|
+
* activation, which fires no pointer event at all. Decoration is idempotent,
|
|
294
|
+
* so a plain left click doing both is not a problem.
|
|
295
|
+
*
|
|
296
|
+
* Returns an uninstall function for tests and for a caller that owns the page
|
|
297
|
+
* lifecycle.
|
|
298
|
+
*/ export function installCampaignForwarding(options) {
|
|
299
|
+
if (typeof document === 'undefined' || typeof window === 'undefined') {
|
|
300
|
+
return ()=>undefined;
|
|
301
|
+
}
|
|
302
|
+
if (installedHandler) return ()=>undefined;
|
|
303
|
+
const origin = normalizeOrigin(options == null ? void 0 : options.consoleOrigin);
|
|
304
|
+
if (!origin) return ()=>undefined;
|
|
305
|
+
const onActivate = (event)=>{
|
|
306
|
+
try {
|
|
307
|
+
const target = event.target;
|
|
308
|
+
if (!target || typeof target.closest !== 'function') return;
|
|
309
|
+
const anchor = target.closest('a[href]');
|
|
310
|
+
if (!anchor) return;
|
|
311
|
+
const decorated = decorateCampaignHref(anchor.getAttribute('href') || '', window.location.href, origin, campaignToForward());
|
|
312
|
+
if (decorated) anchor.setAttribute('href', decorated);
|
|
313
|
+
} catch (unused) {
|
|
314
|
+
// Attribution never breaks a navigation. A link that throws here would
|
|
315
|
+
// be a link that does not work, which costs more than the campaign does.
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
installedHandler = onActivate;
|
|
319
|
+
document.addEventListener('pointerdown', onActivate, true);
|
|
320
|
+
document.addEventListener('click', onActivate, true);
|
|
321
|
+
return resetCampaignForwarding;
|
|
322
|
+
}
|
|
323
|
+
/** Test seam — removes both listeners, forgets them, and forgets consent. */ export function resetCampaignForwarding() {
|
|
324
|
+
if (installedHandler && typeof document !== 'undefined') {
|
|
325
|
+
document.removeEventListener('pointerdown', installedHandler, true);
|
|
326
|
+
document.removeEventListener('click', installedHandler, true);
|
|
327
|
+
}
|
|
328
|
+
installedHandler = null;
|
|
329
|
+
storageConsent = null;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
//# sourceMappingURL=campaign-forwarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/app-utils/campaign-forwarding.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 * Carry the campaign across the domain hop (AGL-1731).\n *\n * `campaign-attribution.ts` is the READER half of this contract and it works.\n * This is the half that was missing, and without it the reader was fed\n * nothing: `aglyn.com` is a tenant published site and `app.aglyn.com` is the\n * console, a real cross-origin hop, and no code anywhere put a `utm_*`\n * parameter on a console-bound link. So `users/{uid}.signupCampaign` was\n * written for exactly one population — visitors whose CTA href had a campaign\n * typed into it by hand.\n *\n * A hand-typed one is worse than none. It is STATIC: `utm_source=google`\n * authored onto the pricing button attributes every clicker to Google whether\n * they arrived from Google, from Hacker News or from a bookmark. Confidently\n * wrong attribution reaches the same spend decisions as absent attribution and\n * is much harder to notice, because the report looks populated.\n *\n * What is needed instead is PER-VISITOR forwarding: the landing page copies\n * the campaign off its own inbound URL onto the console-bound href, at click\n * time, for that one visitor.\n *\n * ## Why a delegated listener and not `AppLink`\n *\n * The same reason `analytics-link-clicks.ts` gives, and it is the reason that\n * decides this file's shape. The CTAs on `aglyn.com` are authored besigner\n * content, not repo files; rich-text and Custom HTML anchors are written with\n * `dangerouslySetInnerHTML` and are plain DOM anchors with no React handler at\n * all. A prop on `AppLink` would miss them, and reaching them from `AppLink`\n * would mean `useSearchParams` in a component the console renders on every\n * page — a dynamic-rendering hazard on statically generated surfaces, paid on\n * every route to fix a link on one of them. A capture-phase listener on\n * `document` sees every anchor, costs one listener, and renders nothing.\n *\n * ## The two tiers, and why the storage tier is the SECOND one\n *\n * A visitor rarely signs up from the page the ad landed on. They land on\n * `/?utm_source=google&...`, read `/pricing`, then click. By then the campaign\n * is off the address bar, so reading the live URL at click time alone would\n * capture only the minority who convert without navigating.\n *\n * - **Tier 1 — the live URL.** Read `window.location.search` at click time.\n * This touches NO storage: the parameters are already in the page the\n * visitor asked for. Nothing is written to their device, so there is nothing\n * here to consent to, and it works for every visitor including one who has\n * declined analytics.\n * - **Tier 2 — the first touch of the visit**, in `sessionStorage`, which is\n * what survives the walk from the landing page to the pricing page.\n *\n * Tier 2 WINS when both exist, because first touch is the question being\n * asked. Last touch — re-deriving the campaign from whatever URL happens to be\n * current at signup — answers a different question and would disagree with\n * GA4's own session attribution.\n *\n * ## Why tier 2 is gated on analytics consent, and tier 1 is not\n *\n * Tier 2 writes to the visitor's device for an analytics purpose, so it is\n * `analytics_storage` in the consent-mode sense and it waits for the same\n * grant the GA tag waits for (AGL-1498). The gate is not re-implemented here\n * and no consent record is read here: the caller already computes\n * `analyticsAllowed` for the tag and hands the same boolean down, so there is\n * one gate and it cannot drift from itself.\n *\n * It is deliberately NOT gated on advertising storage. Nothing here reads or\n * writes an advertising identifier, sets a cookie, or leaves anything that\n * outlives the tab, and AGL-1649 has advertising denied with no route for a\n * host to grant it — gating on a permission that cannot currently be given\n * would be a feature that is dead by construction rather than one that is off.\n *\n * **Consent unresolved is not consent denied, and both are falsy.** With\n * `strictNullChecks` off repo-wide that distinction is the sort that\n * evaporates, so it is carried as an explicit tri-state: until the caller has\n * actually resolved the visitor's state, tier 2 neither reads nor writes.\n * Failing closed here costs an attribution; failing open would write to a\n * device before the visitor answered.\n *\n * ## What is never done\n *\n * A value is only ever forwarded if this visitor literally arrived carrying\n * it. There is no default, no inference from the referrer, and no\n * `utm_source=direct` — a signup with no campaign must reach the console with\n * no campaign, so that \"arrived from nowhere\" and \"never asked\" stay the\n * distinct facts `campaign-attribution.ts` keeps them.\n *\n * Only links to OUR OWN console origin are touched, and the origin is supplied\n * by the caller rather than written here — a self-host install points\n * `NEXT_PUBLIC_CONSOLE_URL` somewhere else entirely. Decorating any other host\n * would post our campaign labels to a third party, which is a data leak dressed\n * up as attribution.\n *\n * ## One accepted consequence\n *\n * The tenant runtime serves `aglyn.com` AND every customer's published site,\n * so a customer site that links to our signup forwards ITS OWN inbound\n * campaign — an agency partner's `utm_source=their-newsletter` would land in our\n * acquisition report describing their spend, not ours. It is not gated on\n * \"is this the operator's marketing host\" deliberately: that gate needs a\n * second configured origin to compare against, and a deployment that forgot to\n * set it would forward NOTHING while looking perfectly healthy. A silent zero\n * is the exact failure AGL-1731 is about, and it is worse than a few\n * mislabelled rows that GA's own Hostname dimension can already separate.\n */\n\nimport {\n CAMPAIGN_QUERY_KEYS,\n campaignAttributionQuery,\n parseCampaignAttribution,\n type CampaignAttribution,\n} from './campaign-attribution'\n\n/**\n * Where the first touch of this visit is held. `sessionStorage`, so it dies\n * with the tab: a campaign is a fact about one visit, and a value that\n * outlived the visit would start attributing next week's organic return to\n * this week's ad.\n */\nexport const CAMPAIGN_VISIT_STORAGE_KEY = 'aglyn:campaign'\n\n/**\n * What a read of the first-touch store produced.\n *\n * Three states rather than \"a campaign or null\", and the third is the whole\n * point. `sessionStorage` throws outright in some privacy modes, and a\n * `catch` that returned null would report \"this visitor named no campaign\" —\n * indistinguishable from an organic arrival, which is how an unreadable source\n * becomes a measured zero. `unreadable` is a different answer and the caller\n * treats it differently: it falls through to the live URL instead of\n * concluding anything.\n */\nexport type VisitCampaignRead =\n | { status: 'campaign'; campaign: CampaignAttribution }\n | { status: 'none' }\n | { status: 'unreadable' }\n\n/**\n * Whether the visitor has granted analytics storage.\n *\n * `null` means NOT YET RESOLVED, and is not the same as `false`. The consent\n * state is settled client-side after hydration, so there is a window in every\n * pageview where the answer is genuinely unknown, and treating it as a denial\n * would be as wrong as treating it as a grant. Tier 2 does nothing in it.\n */\nlet storageConsent: boolean | null = null\n\n/** The one listener pair on `document`, or null. Held, not flagged — the same\n * reason `analytics-link-clicks.ts` holds its own: a boolean lets a caller\n * install over a listener that is still attached, and re-entrant decoration is\n * harder to see than a double-counted event. */\nlet installedHandler: ((event: Event) => void) | null = null\n\nfunction sessionStore(): Storage | null {\n if (typeof window === 'undefined') return null\n // Touching the property itself can throw, not just its methods.\n try {\n return window.sessionStorage ?? null\n } catch {\n return null\n }\n}\n\n/**\n * The campaign this visit began with, as far as the store can say.\n *\n * Re-parsed through the same allowlist that wrote it rather than trusted:\n * `sessionStorage` is writable by anything running on the page, so the stored\n * string can claim no more than an inbound URL could — three allowlisted keys,\n * trimmed, email shapes refused, capped.\n */\nexport function readVisitCampaign(): VisitCampaignRead {\n if (storageConsent !== true) return { status: 'none' }\n const store = sessionStore()\n if (!store) return { status: 'unreadable' }\n let raw: string | null\n try {\n raw = store.getItem(CAMPAIGN_VISIT_STORAGE_KEY)\n } catch {\n return { status: 'unreadable' }\n }\n if (!raw) return { status: 'none' }\n const campaign = parseCampaignAttribution(new URLSearchParams(raw))\n return campaign ? { status: 'campaign', campaign } : { status: 'none' }\n}\n\n/**\n * Remember the campaign on the current URL as this visit's first touch.\n *\n * First touch means FIRST: an existing entry is never replaced. A second\n * campaign arriving later in the same visit is a link the visitor followed\n * after we already knew where they came from, and letting it overwrite would\n * quietly turn this into last-touch.\n *\n * Returns what is now remembered so a caller can assert on it.\n */\nexport function rememberVisitCampaign(search?: string): CampaignAttribution | null {\n const existing = readVisitCampaign()\n if (existing.status === 'campaign') return existing.campaign\n if (storageConsent !== true) return null\n const store = sessionStore()\n if (!store) return null\n const source =\n typeof search === 'string'\n ? search\n : typeof window === 'undefined'\n ? ''\n : window.location.search\n const campaign = parseCampaignAttribution(new URLSearchParams(source))\n if (!campaign) return null\n try {\n store.setItem(CAMPAIGN_VISIT_STORAGE_KEY, campaignAttributionQuery(campaign))\n } catch {\n // A store that refuses the write costs the walk from the landing page to\n // the pricing page, never the click itself — tier 1 still carries a\n // visitor who converts without navigating.\n return null\n }\n return campaign\n}\n\n/**\n * Tell this module what the visitor's analytics consent state is.\n *\n * Called by whoever already computed it for the tag, on every render, so a\n * grant seeds the first touch the moment it is given and a WITHDRAWAL takes\n * effect immediately: the stored value is dropped, not merely ignored. A\n * visitor who changes their mind mid-visit should not leave the thing they\n * withdrew consent for sitting on their device.\n */\nexport function setCampaignForwardingConsent(allowed: boolean | null): void {\n storageConsent = allowed === true ? true : allowed === false ? false : null\n if (storageConsent === true) {\n rememberVisitCampaign()\n return\n }\n if (storageConsent === false) {\n const store = sessionStore()\n if (!store) return\n try {\n store.removeItem(CAMPAIGN_VISIT_STORAGE_KEY)\n } catch {\n // Nothing else to try, and a failed cleanup must not break the page.\n }\n }\n}\n\n/**\n * The campaign to forward, first touch preferred.\n *\n * The `unreadable` case falls through to the live URL rather than to nothing,\n * which is the point of carrying that state at all: a broken store degrades\n * this to tier 1 rather than to silence.\n */\nexport function campaignToForward(search?: string): CampaignAttribution | null {\n const stored = readVisitCampaign()\n if (stored.status === 'campaign') return stored.campaign\n const live =\n typeof search === 'string'\n ? search\n : typeof window === 'undefined'\n ? ''\n : window.location.search\n return parseCampaignAttribution(new URLSearchParams(live))\n}\n\nfunction normalizeOrigin(value: string | null | undefined): string {\n if (!value) return ''\n try {\n return new URL(value).origin\n } catch {\n return ''\n }\n}\n\n/**\n * The href a console-bound link should carry for this visitor, or null to\n * leave it exactly as authored.\n *\n * Null — rather than \"the href unchanged\" — so that a caller cannot write back\n * a value it did not mean to change, and so a test can tell \"decided not to\n * touch this\" from \"touched it and produced the same string\".\n *\n * The three keys are replaced WHOLESALE, never merged key by key. A visitor\n * who arrived with only `utm_source=hn` clicking a button authored with all\n * three must not produce `source=hn` married to the author's `campaign=`: that\n * row describes an event that never happened. Everything else on the href —\n * `plan`, `interval`, the AGL-1535 intent — is preserved untouched.\n */\nexport function decorateCampaignHref(\n href: string,\n baseHref: string,\n consoleOrigin: string,\n campaign: CampaignAttribution | null,\n): string | null {\n if (!campaign) return null\n const origin = normalizeOrigin(consoleOrigin)\n if (!origin) return null\n let url: URL\n try {\n url = new URL(href, baseHref)\n } catch {\n return null\n }\n if (url.origin !== origin) return null\n for (const key of CAMPAIGN_QUERY_KEYS) url.searchParams.delete(key)\n const query = new URLSearchParams(campaignAttributionQuery(campaign))\n query.forEach((value, key) => url.searchParams.set(key, value))\n const next = url.toString()\n return next === href ? null : next\n}\n\n/**\n * Start forwarding the campaign onto console-bound links on this page.\n *\n * Idempotent and safe to call during render, the same contract as\n * `installLinkClickTracking` and for the same AGL-1550 reason: an effect only\n * runs if React commits, and a page that renders without committing would\n * otherwise ship links with no campaign on them.\n *\n * Both `pointerdown` and `click` are listened for, in capture phase.\n * `pointerdown` is what covers a middle-click, a modifier-click into a new\n * tab, and \"Copy link address\" from the context menu — all of which read the\n * href without ever firing `click`. `click` is what covers keyboard\n * activation, which fires no pointer event at all. Decoration is idempotent,\n * so a plain left click doing both is not a problem.\n *\n * Returns an uninstall function for tests and for a caller that owns the page\n * lifecycle.\n */\nexport function installCampaignForwarding(options: {\n consoleOrigin: string\n}): () => void {\n if (typeof document === 'undefined' || typeof window === 'undefined') {\n return () => undefined\n }\n if (installedHandler) return () => undefined\n const origin = normalizeOrigin(options?.consoleOrigin)\n if (!origin) return () => undefined\n\n const onActivate = (event: Event) => {\n try {\n const target = event.target as Element | null\n if (!target || typeof target.closest !== 'function') return\n const anchor = target.closest('a[href]')\n if (!anchor) return\n const decorated = decorateCampaignHref(\n anchor.getAttribute('href') || '',\n window.location.href,\n origin,\n campaignToForward(),\n )\n if (decorated) anchor.setAttribute('href', decorated)\n } catch {\n // Attribution never breaks a navigation. A link that throws here would\n // be a link that does not work, which costs more than the campaign does.\n }\n }\n\n installedHandler = onActivate\n document.addEventListener('pointerdown', onActivate, true)\n document.addEventListener('click', onActivate, true)\n return resetCampaignForwarding\n}\n\n/** Test seam — removes both listeners, forgets them, and forgets consent. */\nexport function resetCampaignForwarding(): void {\n if (installedHandler && typeof document !== 'undefined') {\n document.removeEventListener('pointerdown', installedHandler, true)\n document.removeEventListener('click', installedHandler, true)\n }\n installedHandler = null\n storageConsent = null\n}\n"],"names":["CAMPAIGN_QUERY_KEYS","campaignAttributionQuery","parseCampaignAttribution","CAMPAIGN_VISIT_STORAGE_KEY","storageConsent","installedHandler","sessionStore","window","sessionStorage","readVisitCampaign","status","store","raw","getItem","campaign","URLSearchParams","rememberVisitCampaign","search","existing","source","location","setItem","setCampaignForwardingConsent","allowed","removeItem","campaignToForward","stored","live","normalizeOrigin","value","URL","origin","decorateCampaignHref","href","baseHref","consoleOrigin","url","key","searchParams","delete","query","forEach","set","next","toString","installCampaignForwarding","options","document","undefined","onActivate","event","target","closest","anchor","decorated","getAttribute","setAttribute","addEventListener","resetCampaignForwarding","removeEventListener"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGC,GAED,SACEA,mBAAmB,EACnBC,wBAAwB,EACxBC,wBAAwB,QAEnB,4BAAwB;AAE/B;;;;;CAKC,GACD,OAAO,MAAMC,6BAA6B,iBAAgB;AAkB1D;;;;;;;CAOC,GACD,IAAIC,iBAAiC;AAErC;;;8CAG8C,GAC9C,IAAIC,mBAAoD;AAExD,SAASC;IACP,IAAI,OAAOC,WAAW,aAAa,OAAO;IAC1C,gEAAgE;IAChE,IAAI;YACKA;QAAP,QAAOA,yBAAAA,OAAOC,cAAc,YAArBD,yBAAyB;IAClC,EAAE,eAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;;;CAOC,GACD,OAAO,SAASE;IACd,IAAIL,mBAAmB,MAAM,OAAO;QAAEM,QAAQ;IAAO;IACrD,MAAMC,QAAQL;IACd,IAAI,CAACK,OAAO,OAAO;QAAED,QAAQ;IAAa;IAC1C,IAAIE;IACJ,IAAI;QACFA,MAAMD,MAAME,OAAO,CAACV;IACtB,EAAE,eAAM;QACN,OAAO;YAAEO,QAAQ;QAAa;IAChC;IACA,IAAI,CAACE,KAAK,OAAO;QAAEF,QAAQ;IAAO;IAClC,MAAMI,WAAWZ,yBAAyB,IAAIa,gBAAgBH;IAC9D,OAAOE,WAAW;QAAEJ,QAAQ;QAAYI;IAAS,IAAI;QAAEJ,QAAQ;IAAO;AACxE;AAEA;;;;;;;;;CASC,GACD,OAAO,SAASM,sBAAsBC,MAAe;IACnD,MAAMC,WAAWT;IACjB,IAAIS,SAASR,MAAM,KAAK,YAAY,OAAOQ,SAASJ,QAAQ;IAC5D,IAAIV,mBAAmB,MAAM,OAAO;IACpC,MAAMO,QAAQL;IACd,IAAI,CAACK,OAAO,OAAO;IACnB,MAAMQ,SACJ,OAAOF,WAAW,WACdA,SACA,OAAOV,WAAW,cAChB,KACAA,OAAOa,QAAQ,CAACH,MAAM;IAC9B,MAAMH,WAAWZ,yBAAyB,IAAIa,gBAAgBI;IAC9D,IAAI,CAACL,UAAU,OAAO;IACtB,IAAI;QACFH,MAAMU,OAAO,CAAClB,4BAA4BF,yBAAyBa;IACrE,EAAE,eAAM;QACN,yEAAyE;QACzE,oEAAoE;QACpE,2CAA2C;QAC3C,OAAO;IACT;IACA,OAAOA;AACT;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASQ,6BAA6BC,OAAuB;IAClEnB,iBAAiBmB,YAAY,OAAO,OAAOA,YAAY,QAAQ,QAAQ;IACvE,IAAInB,mBAAmB,MAAM;QAC3BY;QACA;IACF;IACA,IAAIZ,mBAAmB,OAAO;QAC5B,MAAMO,QAAQL;QACd,IAAI,CAACK,OAAO;QACZ,IAAI;YACFA,MAAMa,UAAU,CAACrB;QACnB,EAAE,eAAM;QACN,qEAAqE;QACvE;IACF;AACF;AAEA;;;;;;CAMC,GACD,OAAO,SAASsB,kBAAkBR,MAAe;IAC/C,MAAMS,SAASjB;IACf,IAAIiB,OAAOhB,MAAM,KAAK,YAAY,OAAOgB,OAAOZ,QAAQ;IACxD,MAAMa,OACJ,OAAOV,WAAW,WACdA,SACA,OAAOV,WAAW,cAChB,KACAA,OAAOa,QAAQ,CAACH,MAAM;IAC9B,OAAOf,yBAAyB,IAAIa,gBAAgBY;AACtD;AAEA,SAASC,gBAAgBC,KAAgC;IACvD,IAAI,CAACA,OAAO,OAAO;IACnB,IAAI;QACF,OAAO,IAAIC,IAAID,OAAOE,MAAM;IAC9B,EAAE,eAAM;QACN,OAAO;IACT;AACF;AAEA;;;;;;;;;;;;;CAaC,GACD,OAAO,SAASC,qBACdC,IAAY,EACZC,QAAgB,EAChBC,aAAqB,EACrBrB,QAAoC;IAEpC,IAAI,CAACA,UAAU,OAAO;IACtB,MAAMiB,SAASH,gBAAgBO;IAC/B,IAAI,CAACJ,QAAQ,OAAO;IACpB,IAAIK;IACJ,IAAI;QACFA,MAAM,IAAIN,IAAIG,MAAMC;IACtB,EAAE,eAAM;QACN,OAAO;IACT;IACA,IAAIE,IAAIL,MAAM,KAAKA,QAAQ,OAAO;IAClC,KAAK,MAAMM,OAAOrC,oBAAqBoC,IAAIE,YAAY,CAACC,MAAM,CAACF;IAC/D,MAAMG,QAAQ,IAAIzB,gBAAgBd,yBAAyBa;IAC3D0B,MAAMC,OAAO,CAAC,CAACZ,OAAOQ,MAAQD,IAAIE,YAAY,CAACI,GAAG,CAACL,KAAKR;IACxD,MAAMc,OAAOP,IAAIQ,QAAQ;IACzB,OAAOD,SAASV,OAAO,OAAOU;AAChC;AAEA;;;;;;;;;;;;;;;;;CAiBC,GACD,OAAO,SAASE,0BAA0BC,OAEzC;IACC,IAAI,OAAOC,aAAa,eAAe,OAAOxC,WAAW,aAAa;QACpE,OAAO,IAAMyC;IACf;IACA,IAAI3C,kBAAkB,OAAO,IAAM2C;IACnC,MAAMjB,SAASH,gBAAgBkB,2BAAAA,QAASX,aAAa;IACrD,IAAI,CAACJ,QAAQ,OAAO,IAAMiB;IAE1B,MAAMC,aAAa,CAACC;QAClB,IAAI;YACF,MAAMC,SAASD,MAAMC,MAAM;YAC3B,IAAI,CAACA,UAAU,OAAOA,OAAOC,OAAO,KAAK,YAAY;YACrD,MAAMC,SAASF,OAAOC,OAAO,CAAC;YAC9B,IAAI,CAACC,QAAQ;YACb,MAAMC,YAAYtB,qBAChBqB,OAAOE,YAAY,CAAC,WAAW,IAC/BhD,OAAOa,QAAQ,CAACa,IAAI,EACpBF,QACAN;YAEF,IAAI6B,WAAWD,OAAOG,YAAY,CAAC,QAAQF;QAC7C,EAAE,eAAM;QACN,uEAAuE;QACvE,yEAAyE;QAC3E;IACF;IAEAjD,mBAAmB4C;IACnBF,SAASU,gBAAgB,CAAC,eAAeR,YAAY;IACrDF,SAASU,gBAAgB,CAAC,SAASR,YAAY;IAC/C,OAAOS;AACT;AAEA,2EAA2E,GAC3E,OAAO,SAASA;IACd,IAAIrD,oBAAoB,OAAO0C,aAAa,aAAa;QACvDA,SAASY,mBAAmB,CAAC,eAAetD,kBAAkB;QAC9D0C,SAASY,mBAAmB,CAAC,SAAStD,kBAAkB;IAC1D;IACAA,mBAAmB;IACnBD,iBAAiB;AACnB"}
|
|
@@ -0,0 +1,109 @@
|
|
|
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 field naming the campaigns a resource belongs to.
|
|
19
|
+
*
|
|
20
|
+
* Not `emailCampaignId`, which is the SEND's field: on a send document the
|
|
21
|
+
* word `campaignId` already means the send's own id — it is what `cid`
|
|
22
|
+
* carries into every unsubscribe footer — so that collection needed a
|
|
23
|
+
* different word. A form, a screen and a contact have no second meaning for
|
|
24
|
+
* it, and the plural says the resource may be in more than one.
|
|
25
|
+
*/
|
|
26
|
+
export declare const CAMPAIGN_MEMBERSHIP_FIELD = "campaignIds";
|
|
27
|
+
/**
|
|
28
|
+
* How many campaigns one resource may name.
|
|
29
|
+
*
|
|
30
|
+
* A ceiling on the FIELD, not on the product: an array Firestore has to index
|
|
31
|
+
* on every write is not the place to discover that a script has been adding
|
|
32
|
+
* an id a day for a year. Twenty is far past what a person assigns by hand
|
|
33
|
+
* and far short of anything that costs a write.
|
|
34
|
+
*/
|
|
35
|
+
export declare const CAMPAIGN_MEMBERSHIP_CAP = 20;
|
|
36
|
+
/**
|
|
37
|
+
* A stored membership array as a clean list of ids.
|
|
38
|
+
*
|
|
39
|
+
* Deduped, trimmed, non-strings dropped, capped. Every reader goes through
|
|
40
|
+
* this because the field is written by three consoles and one automation
|
|
41
|
+
* step, and a surface that trusted the raw value would render `undefined` as
|
|
42
|
+
* a chip the first time one of them wrote a blank.
|
|
43
|
+
*/
|
|
44
|
+
export declare function normalizeCampaignIds(raw: unknown): string[];
|
|
45
|
+
/**
|
|
46
|
+
* The campaigns a HOST resource — a form, a screen — belongs to.
|
|
47
|
+
*
|
|
48
|
+
* Host resources carry the field at the top of the document: they belong to
|
|
49
|
+
* one site, which is the same site the campaign belongs to, so there is no
|
|
50
|
+
* second holder to keep the edge away from.
|
|
51
|
+
*/
|
|
52
|
+
export declare function readCampaignIds(resource: Record<string, unknown> | null | undefined): string[];
|
|
53
|
+
/**
|
|
54
|
+
* The dotted path to a contact's membership, inside ONE holder's facet.
|
|
55
|
+
*
|
|
56
|
+
* A contact document is shared by every site in the org — one human who
|
|
57
|
+
* touched two sites is one row — and almost nothing on it is legitimately
|
|
58
|
+
* shared. Which campaigns a merchant has filed a person under is that
|
|
59
|
+
* merchant's business record on exactly the footing their notes and tags are,
|
|
60
|
+
* so it lives at `facets.{groupId}.campaignIds` and not at the top of the
|
|
61
|
+
* document, where every other site in an agency's account could read it.
|
|
62
|
+
*/
|
|
63
|
+
export declare function contactCampaignFieldPath(groupId: string): string;
|
|
64
|
+
/** The campaigns ONE holder has filed this contact under. */
|
|
65
|
+
export declare function readContactCampaignIds(contact: Record<string, unknown> | null | undefined, groupId: string): string[];
|
|
66
|
+
/**
|
|
67
|
+
* The membership a save should write, given what is on screen.
|
|
68
|
+
*
|
|
69
|
+
* Pure, and shared by the three consoles that offer the picker, because the
|
|
70
|
+
* decision each of them makes is identical and is not obvious: an EMPTY
|
|
71
|
+
* selection has to be stored as an empty array rather than as a removed
|
|
72
|
+
* field.
|
|
73
|
+
*
|
|
74
|
+
* Removing the field would read the same to every surface here — the readers
|
|
75
|
+
* above answer `[]` either way — and would be wrong for the one reader that
|
|
76
|
+
* is not a surface. `campaign-manage.ts` finds a campaign's members with
|
|
77
|
+
* `array-contains`, which matches on the automatic single-field index; that
|
|
78
|
+
* index has an entry only while the array does, so the two shapes are the
|
|
79
|
+
* same to a reader and different to a writer only in cost. Storing `[]` keeps
|
|
80
|
+
* one shape for "belongs to no campaign" across every writer, which is the
|
|
81
|
+
* property the send collection's own detach comment argues for one field
|
|
82
|
+
* over.
|
|
83
|
+
*
|
|
84
|
+
* @returns the value to store under {@link CAMPAIGN_MEMBERSHIP_FIELD}.
|
|
85
|
+
*/
|
|
86
|
+
export declare function campaignMembershipValue(selected: readonly string[]): string[];
|
|
87
|
+
/**
|
|
88
|
+
* Whether a document's stored membership already says what a save would.
|
|
89
|
+
*
|
|
90
|
+
* Order-insensitive: a picker hands back its options' order and the stored
|
|
91
|
+
* array is in the order it was written, so comparing them literally would
|
|
92
|
+
* report a change on every open and leave Save permanently enabled.
|
|
93
|
+
*/
|
|
94
|
+
export declare function campaignMembershipUnchanged(stored: readonly string[], selected: readonly string[]): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* The host subcollections whose documents may name a campaign.
|
|
97
|
+
*
|
|
98
|
+
* The list a campaign's deletion walks, and the list this feature's coverage
|
|
99
|
+
* spec reads — so a collection that grows the picker without growing the
|
|
100
|
+
* detach fails the build rather than shipping a campaign whose removal leaves
|
|
101
|
+
* that collection pointing at nothing.
|
|
102
|
+
*
|
|
103
|
+
* Contacts are deliberately NOT here. They live on the org
|
|
104
|
+
* (`orgs/{orgId}/contacts`), not the host, and carry the field inside a
|
|
105
|
+
* per-holder facet — so they are detached by their own pass, against a field
|
|
106
|
+
* path that names the group.
|
|
107
|
+
*/
|
|
108
|
+
export declare const CAMPAIGN_MEMBER_HOST_COLLECTIONS: readonly ["forms", "screens"];
|
|
109
|
+
export type CampaignMemberHostCollection = (typeof CAMPAIGN_MEMBER_HOST_COLLECTIONS)[number];
|
|
@@ -0,0 +1,176 @@
|
|
|
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
|
+
* WHAT ELSE IS IN A CAMPAIGN: the edge between a campaign and the forms,
|
|
18
|
+
* screens and people a push is coordinated across.
|
|
19
|
+
*
|
|
20
|
+
* ## The edge is a field on the RESOURCE, not a list on the campaign
|
|
21
|
+
*
|
|
22
|
+
* A campaign container lives at `hosts/{hostId}/emailCampaigns/{campaignId}`
|
|
23
|
+
* and names nothing outside itself. A send joins one by carrying
|
|
24
|
+
* `emailCampaignId`; every other member joins the same way, through
|
|
25
|
+
* {@link CAMPAIGN_MEMBERSHIP_FIELD} on its own document.
|
|
26
|
+
*
|
|
27
|
+
* Three properties decide it, and all three point the same way:
|
|
28
|
+
*
|
|
29
|
+
* - **Reading is free where it is asked.** A form's own page reads the form
|
|
30
|
+
* document to draw anything at all, so the campaign comes with it. A
|
|
31
|
+
* membership collection under the campaign would make "which campaign is
|
|
32
|
+
* this in" a query issued on mount by every resource page, for a fact one
|
|
33
|
+
* field already carries.
|
|
34
|
+
* - **The reduction is already gated this way.** `campaign-manage.ts` clears
|
|
35
|
+
* `emailCampaignId` from every send before it removes a container, so no
|
|
36
|
+
* send is left naming one that is gone. Extending that pass to the
|
|
37
|
+
* membership field is the SAME mechanism; a membership collection would be
|
|
38
|
+
* a second, different deletion story beside it.
|
|
39
|
+
* - **Deleting a MEMBER can leave nothing behind.** The campaign holds no
|
|
40
|
+
* list, so a deleted form takes its own edge with it. This matters most on
|
|
41
|
+
* a contact: an erasure removes the document, and a membership row stored
|
|
42
|
+
* anywhere else would survive it holding the id of a person who asked to
|
|
43
|
+
* be forgotten.
|
|
44
|
+
*
|
|
45
|
+
* ## Plural, because a landing page outlives one campaign
|
|
46
|
+
*
|
|
47
|
+
* The field is an ARRAY. A signup form built for the spring push is the same
|
|
48
|
+
* form the summer push places, and a single-valued field would make the
|
|
49
|
+
* second assignment silently erase the first — a campaign losing a member
|
|
50
|
+
* with nothing on screen to say so. The automation step that has always
|
|
51
|
+
* written this edge (`assignCampaign`) already used `arrayUnion`, so the
|
|
52
|
+
* product has treated it as many-to-many from the start.
|
|
53
|
+
*
|
|
54
|
+
* ## Ids, never names
|
|
55
|
+
*
|
|
56
|
+
* A campaign's name is editable, and every reader here resolves the name from
|
|
57
|
+
* the campaign document at read time. Renaming a campaign therefore moves no
|
|
58
|
+
* membership: the stored value is the container's document id, which nothing
|
|
59
|
+
* rewrites.
|
|
60
|
+
*/ import { contactFacetPath, readContactFacet } from "./contacts.js";
|
|
61
|
+
/**
|
|
62
|
+
* The field naming the campaigns a resource belongs to.
|
|
63
|
+
*
|
|
64
|
+
* Not `emailCampaignId`, which is the SEND's field: on a send document the
|
|
65
|
+
* word `campaignId` already means the send's own id — it is what `cid`
|
|
66
|
+
* carries into every unsubscribe footer — so that collection needed a
|
|
67
|
+
* different word. A form, a screen and a contact have no second meaning for
|
|
68
|
+
* it, and the plural says the resource may be in more than one.
|
|
69
|
+
*/ export const CAMPAIGN_MEMBERSHIP_FIELD = 'campaignIds';
|
|
70
|
+
/**
|
|
71
|
+
* How many campaigns one resource may name.
|
|
72
|
+
*
|
|
73
|
+
* A ceiling on the FIELD, not on the product: an array Firestore has to index
|
|
74
|
+
* on every write is not the place to discover that a script has been adding
|
|
75
|
+
* an id a day for a year. Twenty is far past what a person assigns by hand
|
|
76
|
+
* and far short of anything that costs a write.
|
|
77
|
+
*/ export const CAMPAIGN_MEMBERSHIP_CAP = 20;
|
|
78
|
+
/**
|
|
79
|
+
* A stored membership array as a clean list of ids.
|
|
80
|
+
*
|
|
81
|
+
* Deduped, trimmed, non-strings dropped, capped. Every reader goes through
|
|
82
|
+
* this because the field is written by three consoles and one automation
|
|
83
|
+
* step, and a surface that trusted the raw value would render `undefined` as
|
|
84
|
+
* a chip the first time one of them wrote a blank.
|
|
85
|
+
*/ export function normalizeCampaignIds(raw) {
|
|
86
|
+
if (!Array.isArray(raw)) return [];
|
|
87
|
+
const seen = [];
|
|
88
|
+
for (const entry of raw){
|
|
89
|
+
if (typeof entry !== 'string') continue;
|
|
90
|
+
const id = entry.trim();
|
|
91
|
+
if (!id || seen.includes(id)) continue;
|
|
92
|
+
seen.push(id);
|
|
93
|
+
if (seen.length >= CAMPAIGN_MEMBERSHIP_CAP) break;
|
|
94
|
+
}
|
|
95
|
+
return seen;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The campaigns a HOST resource — a form, a screen — belongs to.
|
|
99
|
+
*
|
|
100
|
+
* Host resources carry the field at the top of the document: they belong to
|
|
101
|
+
* one site, which is the same site the campaign belongs to, so there is no
|
|
102
|
+
* second holder to keep the edge away from.
|
|
103
|
+
*/ export function readCampaignIds(resource) {
|
|
104
|
+
return normalizeCampaignIds((resource != null ? resource : {})[CAMPAIGN_MEMBERSHIP_FIELD]);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The dotted path to a contact's membership, inside ONE holder's facet.
|
|
108
|
+
*
|
|
109
|
+
* A contact document is shared by every site in the org — one human who
|
|
110
|
+
* touched two sites is one row — and almost nothing on it is legitimately
|
|
111
|
+
* shared. Which campaigns a merchant has filed a person under is that
|
|
112
|
+
* merchant's business record on exactly the footing their notes and tags are,
|
|
113
|
+
* so it lives at `facets.{groupId}.campaignIds` and not at the top of the
|
|
114
|
+
* document, where every other site in an agency's account could read it.
|
|
115
|
+
*/ export function contactCampaignFieldPath(groupId) {
|
|
116
|
+
return contactFacetPath(groupId, CAMPAIGN_MEMBERSHIP_FIELD);
|
|
117
|
+
}
|
|
118
|
+
/** The campaigns ONE holder has filed this contact under. */ export function readContactCampaignIds(contact, groupId) {
|
|
119
|
+
return normalizeCampaignIds(readContactFacet(contact, groupId).campaignIds);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* The membership a save should write, given what is on screen.
|
|
123
|
+
*
|
|
124
|
+
* Pure, and shared by the three consoles that offer the picker, because the
|
|
125
|
+
* decision each of them makes is identical and is not obvious: an EMPTY
|
|
126
|
+
* selection has to be stored as an empty array rather than as a removed
|
|
127
|
+
* field.
|
|
128
|
+
*
|
|
129
|
+
* Removing the field would read the same to every surface here — the readers
|
|
130
|
+
* above answer `[]` either way — and would be wrong for the one reader that
|
|
131
|
+
* is not a surface. `campaign-manage.ts` finds a campaign's members with
|
|
132
|
+
* `array-contains`, which matches on the automatic single-field index; that
|
|
133
|
+
* index has an entry only while the array does, so the two shapes are the
|
|
134
|
+
* same to a reader and different to a writer only in cost. Storing `[]` keeps
|
|
135
|
+
* one shape for "belongs to no campaign" across every writer, which is the
|
|
136
|
+
* property the send collection's own detach comment argues for one field
|
|
137
|
+
* over.
|
|
138
|
+
*
|
|
139
|
+
* @returns the value to store under {@link CAMPAIGN_MEMBERSHIP_FIELD}.
|
|
140
|
+
*/ export function campaignMembershipValue(selected) {
|
|
141
|
+
return normalizeCampaignIds(selected);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Whether a document's stored membership already says what a save would.
|
|
145
|
+
*
|
|
146
|
+
* Order-insensitive: a picker hands back its options' order and the stored
|
|
147
|
+
* array is in the order it was written, so comparing them literally would
|
|
148
|
+
* report a change on every open and leave Save permanently enabled.
|
|
149
|
+
*/ export function campaignMembershipUnchanged(stored, selected) {
|
|
150
|
+
if (stored.length !== selected.length) return false;
|
|
151
|
+
const sortedStored = [
|
|
152
|
+
...stored
|
|
153
|
+
].sort();
|
|
154
|
+
const sortedSelected = [
|
|
155
|
+
...selected
|
|
156
|
+
].sort();
|
|
157
|
+
return sortedStored.every((id, index)=>id === sortedSelected[index]);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The host subcollections whose documents may name a campaign.
|
|
161
|
+
*
|
|
162
|
+
* The list a campaign's deletion walks, and the list this feature's coverage
|
|
163
|
+
* spec reads — so a collection that grows the picker without growing the
|
|
164
|
+
* detach fails the build rather than shipping a campaign whose removal leaves
|
|
165
|
+
* that collection pointing at nothing.
|
|
166
|
+
*
|
|
167
|
+
* Contacts are deliberately NOT here. They live on the org
|
|
168
|
+
* (`orgs/{orgId}/contacts`), not the host, and carry the field inside a
|
|
169
|
+
* per-holder facet — so they are detached by their own pass, against a field
|
|
170
|
+
* path that names the group.
|
|
171
|
+
*/ export const CAMPAIGN_MEMBER_HOST_COLLECTIONS = [
|
|
172
|
+
'forms',
|
|
173
|
+
'screens'
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
//# sourceMappingURL=campaign-membership.js.map
|