@aglyn/aglyn 1.0.0-beta.218 → 1.0.0-beta.220
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -12
- package/src/lib/app-utils/actions.d.ts +26 -433
- package/src/lib/app-utils/actions.js +108 -633
- package/src/lib/app-utils/actions.js.map +1 -1
- package/src/lib/app-utils/activity-presenter.d.ts +3 -3
- package/src/lib/app-utils/activity-presenter.js +36 -52
- package/src/lib/app-utils/activity-presenter.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +1 -1
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/analytics-provider.d.ts +182 -0
- package/src/lib/app-utils/analytics-provider.js +133 -0
- package/src/lib/app-utils/analytics-provider.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +46 -0
- package/src/lib/app-utils/api-plugins.js +19 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -1
- package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
- package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
- package/src/lib/app-utils/artifact-overrides.js.map +1 -0
- package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
- package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
- package/src/lib/app-utils/artifact-provenance.js.map +1 -0
- package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
- package/src/lib/app-utils/binding-token-catalog.js +17 -41
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
- package/src/lib/app-utils/brand-support-line.d.ts +36 -0
- package/src/lib/app-utils/brand-support-line.js +38 -0
- package/src/lib/app-utils/brand-support-line.js.map +1 -0
- package/src/lib/app-utils/collection-entries.d.ts +2 -2
- package/src/lib/app-utils/collection-entries.js.map +1 -1
- package/src/lib/app-utils/consent-group-change.d.ts +4 -0
- package/src/lib/app-utils/consent-group-change.js.map +1 -1
- package/src/lib/app-utils/consent-groups.d.ts +1 -1
- package/src/lib/app-utils/consent-groups.js.map +1 -1
- package/src/lib/app-utils/console-routes.d.ts +15 -42
- package/src/lib/app-utils/console-routes.js +10 -39
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/contacts.d.ts +24 -2
- package/src/lib/app-utils/contacts.js +21 -5
- package/src/lib/app-utils/contacts.js.map +1 -1
- package/src/lib/app-utils/container-membership.d.ts +93 -0
- package/src/lib/app-utils/container-membership.js +165 -0
- package/src/lib/app-utils/container-membership.js.map +1 -0
- package/src/lib/app-utils/crm-task-reminders.d.ts +23 -6
- package/src/lib/app-utils/crm-task-reminders.js +32 -11
- package/src/lib/app-utils/crm-task-reminders.js.map +1 -1
- package/src/lib/app-utils/crm.d.ts +24 -4
- package/src/lib/app-utils/crm.js +23 -0
- package/src/lib/app-utils/crm.js.map +1 -1
- package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
- package/src/lib/app-utils/cross-pool-desync.js +47 -0
- package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
- package/src/lib/app-utils/csv-upload.d.ts +29 -0
- package/src/lib/app-utils/csv-upload.js +29 -0
- package/src/lib/app-utils/csv-upload.js.map +1 -0
- package/src/lib/app-utils/{dataset-csv.d.ts → csv.d.ts} +10 -43
- package/src/lib/app-utils/{dataset-csv.js → csv.js} +10 -81
- package/src/lib/app-utils/csv.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +5 -5
- package/src/lib/app-utils/dataset-models.js +19 -2
- package/src/lib/app-utils/dataset-models.js.map +1 -1
- package/src/lib/app-utils/datasets.d.ts +65 -30
- package/src/lib/app-utils/datasets.js +74 -24
- package/src/lib/app-utils/datasets.js.map +1 -1
- package/src/lib/app-utils/docs-deflection.d.ts +6 -6
- package/src/lib/app-utils/docs-deflection.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +14 -8
- package/src/lib/app-utils/docs-help.generated.js +23 -6
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
- package/src/lib/app-utils/docs-index.generated.js +570 -346
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
- package/src/lib/app-utils/docs-retrieval.js +14 -10
- package/src/lib/app-utils/docs-retrieval.js.map +1 -1
- package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
- package/src/lib/app-utils/duplicate-resource.js +7 -4
- package/src/lib/app-utils/duplicate-resource.js.map +1 -1
- package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
- package/src/lib/app-utils/dynamic-list-rule.js +3 -3
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
- package/src/lib/app-utils/element-ui.d.ts +1 -1
- package/src/lib/app-utils/element-ui.js +1 -1
- package/src/lib/app-utils/element-ui.js.map +1 -1
- package/src/lib/app-utils/email-starter-policy.js +3 -3
- package/src/lib/app-utils/email-starter-policy.js.map +1 -1
- package/src/lib/app-utils/email-text.d.ts +80 -0
- package/src/lib/app-utils/email-text.js +189 -0
- package/src/lib/app-utils/email-text.js.map +1 -0
- package/src/lib/app-utils/{list-assignment-policy.d.ts → enrollment-basis.d.ts} +4 -0
- package/src/lib/app-utils/{list-assignment-policy.js → enrollment-basis.js} +5 -1
- package/src/lib/app-utils/enrollment-basis.js.map +1 -0
- package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
- package/src/lib/app-utils/entity-picker-context.js.map +1 -1
- package/src/lib/app-utils/error-beacon.d.ts +75 -6
- package/src/lib/app-utils/error-beacon.js +160 -21
- package/src/lib/app-utils/error-beacon.js.map +1 -1
- package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
- package/src/lib/app-utils/expand-repeatables.js +14 -14
- package/src/lib/app-utils/expand-repeatables.js.map +1 -1
- package/src/lib/app-utils/forms.js +2 -2
- package/src/lib/app-utils/forms.js.map +1 -1
- package/src/lib/app-utils/health-report.d.ts +2 -3
- package/src/lib/app-utils/health-report.js +8 -6
- package/src/lib/app-utils/health-report.js.map +1 -1
- package/src/lib/app-utils/host-events.d.ts +82 -0
- package/src/lib/app-utils/host-events.js +62 -0
- package/src/lib/app-utils/host-events.js.map +1 -0
- package/src/lib/app-utils/inbound-mail-domain.d.ts +27 -0
- package/src/lib/app-utils/inbound-mail-domain.js +31 -0
- package/src/lib/app-utils/inbound-mail-domain.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +11 -0
- package/src/lib/app-utils/lockdown.js +33 -3
- package/src/lib/app-utils/lockdown.js.map +1 -1
- package/src/lib/app-utils/margin-utilization.d.ts +4 -69
- package/src/lib/app-utils/margin-utilization.js +82 -69
- package/src/lib/app-utils/margin-utilization.js.map +1 -1
- package/src/lib/app-utils/member-email-aliases.d.ts +25 -0
- package/src/lib/app-utils/member-email-aliases.js +29 -0
- package/src/lib/app-utils/member-email-aliases.js.map +1 -1
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
- package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
- package/src/lib/app-utils/node-interactions.d.ts +7 -7
- package/src/lib/app-utils/node-interactions.js.map +1 -1
- package/src/lib/app-utils/notifications.d.ts +147 -47
- package/src/lib/app-utils/notifications.js +182 -44
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/operator-alerts.d.ts +15 -1
- package/src/lib/app-utils/operator-alerts.js +47 -10
- package/src/lib/app-utils/operator-alerts.js.map +1 -1
- package/src/lib/app-utils/payments-configured.d.ts +8 -21
- package/src/lib/app-utils/payments-configured.js +8 -23
- package/src/lib/app-utils/payments-configured.js.map +1 -1
- package/src/lib/app-utils/plan-entitlements.d.ts +207 -306
- package/src/lib/app-utils/plan-entitlements.js +345 -528
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/platform-brand.d.ts +10 -0
- package/src/lib/app-utils/platform-brand.js +14 -3
- package/src/lib/app-utils/platform-brand.js.map +1 -1
- package/src/lib/app-utils/platform-marketing-consent.d.ts +56 -2
- package/src/lib/app-utils/platform-marketing-consent.js +6 -5
- package/src/lib/app-utils/platform-marketing-consent.js.map +1 -1
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
- package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
- package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
- package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
- package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-starter-templates.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-starter-templates.generated.js +711 -0
- package/src/lib/app-utils/plugin-starter-templates.generated.js.map +1 -0
- package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
- package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +14 -5
- package/src/lib/app-utils/release-flags.js +21 -125
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/repeat-query.d.ts +56 -0
- package/src/lib/app-utils/{dataset-query.js → repeat-query.js} +16 -16
- package/src/lib/app-utils/repeat-query.js.map +1 -0
- package/src/lib/app-utils/repeat-sources.d.ts +9 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -1
- package/src/lib/app-utils/retained-refusals.d.ts +73 -0
- package/src/lib/app-utils/retained-refusals.js +186 -0
- package/src/lib/app-utils/retained-refusals.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +27 -0
- package/src/lib/app-utils/scope-tokens.js +61 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -1
- package/src/lib/app-utils/screen-link-context.js +3 -3
- package/src/lib/app-utils/screen-link-context.js.map +1 -1
- package/src/lib/app-utils/screen-route.js +1 -1
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/seo-audit.d.ts +132 -0
- package/src/lib/app-utils/seo-audit.js +246 -0
- package/src/lib/app-utils/seo-audit.js.map +1 -0
- package/src/lib/app-utils/seo-keywords.d.ts +48 -0
- package/src/lib/app-utils/seo-keywords.js +60 -0
- package/src/lib/app-utils/seo-keywords.js.map +1 -0
- package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
- package/src/lib/app-utils/seo-page-facts.js +155 -0
- package/src/lib/app-utils/seo-page-facts.js.map +1 -0
- package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
- package/src/lib/app-utils/seo-site-scan.js +162 -0
- package/src/lib/app-utils/seo-site-scan.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.js +1 -1
- package/src/lib/app-utils/seo-title-variables.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +13 -18
- package/src/lib/app-utils/server.js +33 -51
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-interactions.d.ts +501 -0
- package/src/lib/app-utils/site-interactions.js +554 -0
- package/src/lib/app-utils/site-interactions.js.map +1 -0
- package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
- package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +2 -2
- package/src/lib/app-utils/site-theme.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +4 -3
- package/src/lib/app-utils/sitemap.js +9 -7
- package/src/lib/app-utils/sitemap.js.map +1 -1
- package/src/lib/app-utils/stale-build-error.d.ts +51 -0
- package/src/lib/app-utils/stale-build-error.js +100 -1
- package/src/lib/app-utils/stale-build-error.js.map +1 -1
- package/src/lib/app-utils/starter-template-nodes.d.ts +137 -0
- package/src/lib/app-utils/starter-template-nodes.js +129 -0
- package/src/lib/app-utils/starter-template-nodes.js.map +1 -0
- package/src/lib/app-utils/starter-templates.d.ts +11 -34
- package/src/lib/app-utils/starter-templates.js +19 -230
- package/src/lib/app-utils/starter-templates.js.map +1 -1
- package/src/lib/app-utils/{email-topics.d.ts → subscription-topics.d.ts} +64 -48
- package/src/lib/app-utils/{email-topics.js → subscription-topics.js} +39 -109
- package/src/lib/app-utils/subscription-topics.js.map +1 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
- package/src/lib/app-utils/theme-library.d.ts +10 -3
- package/src/lib/app-utils/theme-library.js +13 -4
- package/src/lib/app-utils/theme-library.js.map +1 -1
- package/src/lib/app-utils/usage-budget.d.ts +73 -188
- package/src/lib/app-utils/usage-budget.js +58 -194
- package/src/lib/app-utils/usage-budget.js.map +1 -1
- package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
- package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
- package/src/lib/app-utils/utm-attribution.js.map +1 -0
- package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
- package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
- package/src/lib/app-utils/utm-forwarding.js.map +1 -0
- package/src/lib/app-utils/{campaign-touch.d.ts → utm-touch.d.ts} +25 -17
- package/src/lib/app-utils/{campaign-touch.js → utm-touch.js} +38 -30
- package/src/lib/app-utils/utm-touch.js.map +1 -0
- package/src/lib/app-utils/variables.d.ts +9 -9
- package/src/lib/app-utils/variables.js.map +1 -1
- package/src/lib/app-utils/video-object.js +6 -5
- package/src/lib/app-utils/video-object.js.map +1 -1
- package/src/lib/app-utils/visitor-consent.d.ts +41 -164
- package/src/lib/app-utils/visitor-consent.js +66 -277
- package/src/lib/app-utils/visitor-consent.js.map +1 -1
- package/src/lib/app-utils/visitor-record-ceiling.d.ts +32 -0
- package/src/lib/app-utils/visitor-record-ceiling.js +39 -0
- package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
- package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
- package/src/lib/app-utils/web-vitals-rum.js +31 -63
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
- package/src/lib/app-utils/where-used.d.ts +11 -6
- package/src/lib/app-utils/where-used.js +3 -8
- package/src/lib/app-utils/where-used.js.map +1 -1
- package/src/lib/foundation/definitions/components.types.d.ts +1 -1
- package/src/lib/foundation/definitions/components.types.js +1 -1
- package/src/lib/foundation/definitions/components.types.js.map +1 -1
- package/src/lib/foundation/definitions/org-billing.types.d.ts +11 -137
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +1 -3
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +11 -5
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
- package/src/lib/foundation/index.d.ts +1 -1
- package/src/lib/foundation/index.js.map +1 -1
- package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
- package/src/lib/plugin-manager/besigner-documents.js +61 -0
- package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
- package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
- package/src/lib/plugin-manager/computed-variables.js +74 -0
- package/src/lib/plugin-manager/computed-variables.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
- package/src/lib/plugin-manager/custom-fields.js +47 -1
- package/src/lib/plugin-manager/custom-fields.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +372 -99
- package/src/lib/plugin-manager/feature-plugins.js +126 -51
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +134 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +840 -10
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/index.d.ts +0 -1
- package/src/lib/plugin-manager/index.js +0 -1
- package/src/lib/plugin-manager/index.js.map +1 -1
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-contact-capture.d.ts +9 -4
- package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
- package/src/lib/plugin-manager/plugin-containers.d.ts +68 -0
- package/src/lib/plugin-manager/plugin-containers.generated.d.ts +10 -0
- package/src/lib/plugin-manager/plugin-containers.generated.js +20 -0
- package/src/lib/plugin-manager/plugin-containers.generated.js.map +1 -0
- package/src/lib/plugin-manager/plugin-containers.js +27 -0
- package/src/lib/plugin-manager/plugin-containers.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
- package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
- package/src/lib/plugin-manager/plugin-dependents.js +75 -0
- package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
- package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
- package/src/lib/plugin-manager/plugin-distribution.js +45 -0
- package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlements.d.ts +8 -0
- package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
- package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
- package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-membership-detach.js +1 -1
- package/src/lib/plugin-manager/plugin-membership-detach.js.map +1 -1
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-email-state.d.ts +69 -0
- package/src/lib/plugin-manager/plugin-record-email-state.js +32 -0
- package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-record-index.js +51 -0
- package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-lists.d.ts +115 -0
- package/src/lib/plugin-manager/plugin-record-lists.js +75 -0
- package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-timeline.d.ts +42 -8
- package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-record-written.js +42 -0
- package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-beacons.d.ts +71 -0
- package/src/lib/plugin-manager/plugin-site-beacons.js +54 -0
- package/src/lib/plugin-manager/plugin-site-beacons.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
- package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
- package/src/lib/plugin-manager/plugin-site-export.js +40 -0
- package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-subscription-topics.generated.d.ts +11 -0
- package/src/lib/plugin-manager/plugin-subscription-topics.generated.js +41 -0
- package/src/lib/plugin-manager/plugin-subscription-topics.generated.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
- package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
- package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
- package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-axes.d.ts +319 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js +186 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-meters.d.ts +108 -0
- package/src/lib/plugin-manager/plugin-usage-meters.js +105 -0
- package/src/lib/plugin-manager/plugin-usage-meters.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
- package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
- package/src/lib/plugin-manager/record-captured-contact.js +10 -32
- package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
- package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
- package/src/lib/plugin-manager/repeat-rows.js +108 -0
- package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
- package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
- package/src/lib/plugin-manager/submission-record-target.js +125 -0
- package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
- package/src/lib/plugin-manager/usage-alert-contributors.d.ts +76 -6
- package/src/lib/plugin-manager/usage-alert-contributors.js +23 -10
- package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -1
- package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
- package/src/lib/plugin-manager/video-embed-provider.js +165 -0
- package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
- package/src/lib/types/nodes.d.ts +2 -2
- package/src/lib/types/nodes.js.map +1 -1
- package/src/lib/app-utils/assist-credits.d.ts +0 -482
- package/src/lib/app-utils/assist-credits.js +0 -509
- package/src/lib/app-utils/assist-credits.js.map +0 -1
- package/src/lib/app-utils/campaign-attribution.js.map +0 -1
- package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
- package/src/lib/app-utils/campaign-membership.d.ts +0 -121
- package/src/lib/app-utils/campaign-membership.js +0 -189
- package/src/lib/app-utils/campaign-membership.js.map +0 -1
- package/src/lib/app-utils/campaign-touch.js.map +0 -1
- package/src/lib/app-utils/console-record-links.d.ts +0 -163
- package/src/lib/app-utils/console-record-links.js +0 -180
- package/src/lib/app-utils/console-record-links.js.map +0 -1
- package/src/lib/app-utils/contact-holder.d.ts +0 -68
- package/src/lib/app-utils/contact-holder.js +0 -129
- package/src/lib/app-utils/contact-holder.js.map +0 -1
- package/src/lib/app-utils/contact-merge.d.ts +0 -136
- package/src/lib/app-utils/contact-merge.js +0 -412
- package/src/lib/app-utils/contact-merge.js.map +0 -1
- package/src/lib/app-utils/crm-booking.d.ts +0 -75
- package/src/lib/app-utils/crm-booking.js +0 -133
- package/src/lib/app-utils/crm-booking.js.map +0 -1
- package/src/lib/app-utils/crm-csv.d.ts +0 -239
- package/src/lib/app-utils/crm-csv.js +0 -467
- package/src/lib/app-utils/crm-csv.js.map +0 -1
- package/src/lib/app-utils/crm-digest.d.ts +0 -185
- package/src/lib/app-utils/crm-digest.js +0 -272
- package/src/lib/app-utils/crm-digest.js.map +0 -1
- package/src/lib/app-utils/crm-inbound.d.ts +0 -245
- package/src/lib/app-utils/crm-inbound.js +0 -407
- package/src/lib/app-utils/crm-inbound.js.map +0 -1
- package/src/lib/app-utils/crm-reports.d.ts +0 -479
- package/src/lib/app-utils/crm-reports.js +0 -680
- package/src/lib/app-utils/crm-reports.js.map +0 -1
- package/src/lib/app-utils/dataset-csv.js.map +0 -1
- package/src/lib/app-utils/dataset-query.d.ts +0 -57
- package/src/lib/app-utils/dataset-query.js.map +0 -1
- package/src/lib/app-utils/email-topics.js.map +0 -1
- package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
- package/src/lib/app-utils/form-dataset-binding.js +0 -74
- package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
- package/src/lib/app-utils/list-assignment-policy.js.map +0 -1
- package/src/lib/app-utils/list-import.d.ts +0 -158
- package/src/lib/app-utils/list-import.js +0 -332
- package/src/lib/app-utils/list-import.js.map +0 -1
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
- package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
- package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
- package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
- package/src/lib/app-utils/marketplace-theme.js.map +0 -1
- package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
- package/src/lib/app-utils/marketplace-update-state.js +0 -132
- package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
- package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
- package/src/lib/app-utils/publisher-agreement.js +0 -321
- package/src/lib/app-utils/publisher-agreement.js.map +0 -1
- package/src/lib/app-utils/wistia-embed.d.ts +0 -104
- package/src/lib/app-utils/wistia-embed.js +0 -138
- package/src/lib/app-utils/wistia-embed.js.map +0 -1
- package/src/lib/app-utils/workflows.d.ts +0 -136
- package/src/lib/app-utils/workflows.js +0 -346
- package/src/lib/app-utils/workflows.js.map +0 -1
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
- package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
- package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
- package/src/lib/plugin-manager/plugin-metered-lines.d.ts +0 -97
- package/src/lib/plugin-manager/plugin-metered-lines.js +0 -123
- package/src/lib/plugin-manager/plugin-metered-lines.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/first-party-plugins.generated.ts"],"sourcesContent":["/**\n * GENERATED FILE — do not edit. Regenerate with:\n * node tools/scripts/generate-plugin-manifests.mjs\n *\n * The switchboard catalog (AGL-3080): one row per plugin and capability, each\n * declared by its own `catalog` block in plugins.config.json. The core holds\n * the types and the resolvers in `enabled-plugins.ts`; it holds no row.\n */\n\nimport type { FirstPartyPlugin, PluginEditBarLink, PublishedSiteImpact } from './enabled-plugins'\nimport type { ResolvedPluginHostCollection, ResolvedPluginOrgCollection } from './plugin-host-collections'\nimport type { ResolvedPluginOrgCapacity } from './plugin-org-capacity'\nimport type { FunctionBindings } from './plugin-contributions'\n\nexport const FIRST_PARTY_PLUGINS: readonly FirstPartyPlugin[] = [\n {\n \"id\": \"mui\",\n \"label\": \"Components\",\n \"alwaysOn\": true,\n \"description\": \"The base component and theme library every site builds on.\"\n },\n {\n \"id\": \"forms\",\n \"label\": \"Forms\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"Forms on the site and the catalog that owns them.\",\n \"siteOff\": {\n \"stops\": \"Switching Forms off for this site stops forms rendering on its published pages, refuses every submission sent to it, and blocks publishing a form, or a page that carries one, until Forms is back on.\",\n \"keeps\": \"Submissions already received, the workspace’s form catalog and the CRM leads its forms created are kept, and forms keep working on the workspace’s other sites.\",\n \"confirm\": true,\n \"pages\": {\n \"heading\": \"These published pages carry a form. Their forms stop rendering and stop accepting submissions:\",\n \"none\": \"No published page on this site carries a form.\"\n }\n }\n },\n {\n \"id\": \"ai\",\n \"label\": \"AI\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"The assistant, generative building and automation, and the AI add-on.\",\n \"siteOff\": {\n \"stops\": \"Switching AI off for this site hides the assistant, Describe it, the AI cards and the editor’s AI controls on this site, refuses every AI request made for it, and stops its queued AI jobs without spending credits.\",\n \"keeps\": \"It does not stop the workspace’s AI add-on, credits, allotments or overage billing, and AI keeps working on the workspace’s other sites.\"\n }\n },\n {\n \"id\": \"theme-presets\",\n \"label\": \"Themes\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"Built-in themes to pick from on Setup → Theme: Bootstrap, Minimal and Material 3.\",\n \"siteOff\": {\n \"stops\": \"Switching Themes off for this site removes its built-in themes from the theme picker.\",\n \"keeps\": \"A site already using one keeps it, with every edit made to it: picking a theme copies it onto the site, so nothing on the published site changes.\"\n }\n },\n {\n \"id\": \"accounts\",\n \"label\": \"User Accounts\",\n \"description\": \"Visitor accounts on the site: the /signin, /signup and /recover pages, and the Members blocks. On for a new site; a site created before that stays off until you turn it on.\",\n \"releaseFlag\": \"release_member_accounts\",\n \"defaultOffPerSite\": true,\n \"requires\": [\n \"commerce\"\n ]\n },\n {\n \"id\": \"bookings\",\n \"label\": \"Bookings\",\n \"description\": \"Services, open slots, and paid bookings.\",\n \"releaseFlag\": \"release_bookings\"\n },\n {\n \"id\": \"commerce\",\n \"label\": \"Commerce\",\n \"description\": \"Products, carts, checkout, orders, POS.\",\n \"releaseFlag\": \"release_commerce_v2\"\n },\n {\n \"id\": \"marketplace\",\n \"label\": \"Marketplace\",\n \"description\": \"Marketplace listings, templates, and installs.\",\n \"releaseFlag\": \"release_marketplace\"\n },\n {\n \"id\": \"crm\",\n \"label\": \"CRM\",\n \"description\": \"Leads, contacts, companies, deals, tasks and reports.\",\n \"releaseFlag\": \"release_crm\"\n },\n {\n \"id\": \"outreach\",\n \"label\": \"Sequences\",\n \"description\": \"One-to-one email sequences sent from connected mailboxes.\",\n \"releaseFlag\": \"release_outreach\"\n },\n {\n \"id\": \"data\",\n \"label\": \"Data\",\n \"description\": \"Datasets, records, and CSV import/export.\",\n \"releaseFlag\": \"release_data_store\"\n },\n {\n \"id\": \"email\",\n \"label\": \"Email\",\n \"description\": \"Designed emails and campaign sending.\",\n \"releaseFlag\": \"release_email\"\n },\n {\n \"id\": \"events-calendar\",\n \"label\": \"Events Calendar\",\n \"description\": \"Event lists and calendars.\",\n \"releaseFlag\": \"release_events\"\n },\n {\n \"id\": \"inbox\",\n \"label\": \"Inbox\",\n \"description\": \"Form submissions and lead inbox.\",\n \"releaseFlag\": \"release_inbox\"\n },\n {\n \"id\": \"logic\",\n \"label\": \"Logic\",\n \"description\": \"Variables, functions, and reference health.\",\n \"releaseFlag\": \"release_logic\"\n },\n {\n \"id\": \"marketing\",\n \"label\": \"Marketing\",\n \"description\": \"Overlays, campaigns, and experiments.\",\n \"releaseFlag\": \"release_marketing\"\n },\n {\n \"id\": \"redirects\",\n \"label\": \"Redirects\",\n \"description\": \"URL redirect rules.\",\n \"releaseFlag\": \"release_redirects\"\n },\n {\n \"id\": \"workflows\",\n \"label\": \"Automation\",\n \"description\": \"Workflows, actions, webhooks, and run logs.\",\n \"releaseFlag\": \"release_workflows\"\n },\n]\n\nexport const PUBLISHED_SITE_IMPACT: Readonly<Record<string, PublishedSiteImpact>> = {\n \"mui\": \"elements\",\n \"forms\": \"elements\",\n \"ai\": \"console-only\",\n \"theme-presets\": \"console-only\",\n \"accounts\": \"routes\",\n \"bookings\": \"elements\",\n \"commerce\": \"elements\",\n \"marketplace\": \"console-only\",\n \"crm\": \"console-only\",\n \"outreach\": \"console-only\",\n \"data\": \"console-only\",\n \"email\": \"elements\",\n \"events-calendar\": \"elements\",\n \"inbox\": \"console-only\",\n \"logic\": \"console-only\",\n \"marketing\": \"elements\",\n \"redirects\": \"routes\",\n \"workflows\": \"routes\",\n}\n\n/**\n * The admin edit bar's quick links, in the order they are drawn — each\n * declared by the plugin whose console page it opens (AGL-3080).\n */\nexport const PLUGIN_EDIT_BAR_LINKS: readonly PluginEditBarLink[] = [\n {\n \"pluginId\": \"inbox\",\n \"order\": 20,\n \"label\": \"Inbox\",\n \"path\": \"/inbox\"\n },\n {\n \"pluginId\": \"commerce\",\n \"order\": 30,\n \"label\": \"Orders\",\n \"path\": \"/products/orders\"\n },\n]\n\n/**\n * Every host subcollection a first-party plugin owns, declared by that plugin\n * (AGL-3080). Core's readers ask this list; core names no collection.\n */\nexport const PLUGIN_HOST_COLLECTIONS_DECLARED: readonly ResolvedPluginHostCollection[] = [\n {\n \"pluginId\": \"forms\",\n \"name\": \"forms\",\n \"routeSlug\": \"forms\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"services\",\n \"routeSlug\": \"bookings\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"bookings\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Booking records — a customer, a time and a service pointer. The service holds the imagery and IS scanned; a booking is the transaction against it.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"products\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"productCategories\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"suppliers\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"locations\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"coupons\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"discounts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reviews\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"memberPosts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"resources\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"settings\",\n \"label\": \"Store settings\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"siteMembers\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"siteMemberCredentials\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"A site member's password hash, one document per member, read and written only by the membership routes (AGL-3308). A credential with no content field, and no client may read it.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"orders\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Completed orders. Line items COPY a product's `imageUrl` at purchase time, so these would match — and matching would be the wrong answer: an order is an immutable record of what was sold, deleting the asset changes nothing about it, and no author can edit one. A busy store also holds more of these than the whole read budget.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"carts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Live and abandoned carts, with the same copied line-item image and the same reasoning, at higher volume — one document per shopper session.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"checkouts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"In-flight checkout sessions. Transient buyer state carrying the same line-item snapshot as `carts`.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reservations\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS and booking holds. Short-lived transaction rows pointing at a resource that is itself scanned.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stockHolds\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Inventory holds taken during checkout. Machine-written, short-lived, and a quantity rather than content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"subscriptions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Site membership subscriptions: a plan pointer, a status and Stripe ids. Server-written from the billing webhook.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"registers\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS register allocations — a count against the register add-on, read by billing (AGL-1775). No content field at all.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"giftCards\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Gift card balances and redemption history. Money, not content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"licenseKeys\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Digital-product license keys issued at fulfilment: a code, an order pointer and a revocation flag.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryAdjustments\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The append-only stock adjustment ledger (AGL-2269). One row per manual stock edit and per cancellation release, unbounded over a store's life.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryReconciliation\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Reconciliation runs comparing counted stock against recorded stock. Machine-written totals.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"restockAlerts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Back-in-stock requests: an email address and a product pointer, written by visitors.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stripeTaxRates\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Cached Stripe tax rate ids, written by the tax sync. Vendor ids.\"\n },\n {\n \"pluginId\": \"marketplace\",\n \"name\": \"installs\"\n },\n {\n \"pluginId\": \"crm\",\n \"name\": \"leads\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Captured leads, on the same footing as `formSubmissions`: visitor-submitted, unbounded, and never a place an author places an asset.\"\n },\n {\n \"pluginId\": \"email\",\n \"name\": \"suppressions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Unsubscribes, bounces and spam complaints. Email addresses and a reason.\"\n },\n {\n \"pluginId\": \"events-calendar\",\n \"name\": \"events\",\n \"routeSlug\": \"events\"\n },\n {\n \"pluginId\": \"inbox\",\n \"name\": \"formSubmissions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Visitor form submissions. Unbounded, PII-heavy, and a file attached to one is the visitor's upload — not a library asset an author picked, and not something deleting a library asset would break.\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"functions\",\n \"routeSlug\": \"logic\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"variables\",\n \"routeSlug\": \"logic\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"experiments\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"overlays\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaignAttributions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"One row per conversion — a form submission, a lead, a contact or a booking — recording which campaign the visitor arrived from. Written only by the Admin SDK, and the whole record is three sanitized UTM strings capped at a hundred characters: there is no field an asset could occupy and no surface that could pick one into it. Unbounded on the same footing as the conversions it credits.\"\n },\n {\n \"pluginId\": \"redirects\",\n \"name\": \"redirects\",\n \"routeSlug\": \"redirects\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"workflows\",\n \"routeSlug\": \"automation\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"webhooks\",\n \"routeSlug\": \"automation\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"actions\",\n \"routeSlug\": \"automation\"\n },\n]\n\n/**\n * Every org collection a first-party plugin owns whose documents the media\n * scan reads, declared by that plugin (AGL-3273).\n */\nexport const PLUGIN_ORG_COLLECTIONS_DECLARED: readonly ResolvedPluginOrgCollection[] = [\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaigns\",\n \"routeSlug\": \"marketing\",\n \"siteField\": \"hostId\",\n \"holdsTransferWhile\": {\n \"field\": \"status\",\n \"values\": [\n \"scheduled\",\n \"sending\"\n ]\n }\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"emailCampaigns\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The campaign CONTAINER — a name, a date window, the list ids it is aimed at, a topic and the sites it runs on. Distinct from `campaigns`, which holds the sends and IS scanned because a send carries the copy that went out. A container carries no copy and no asset reference: the design a send renders is a screen, and the screen is where the picker writes.\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"automations\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"An org automation (AGL-3302) — a trigger, its conditions, the sites it is placed on, and a step list drawn from the server steps only: email subject and body as plain text, list, dataset and campaign ids, CRM fields and waits. No step it may hold carries a media reference, the in-page steps that could (custom HTML, popups) are refused by its save route, and it is written only by that route.\"\n },\n]\n\n/**\n * Every org capacity a first-party plugin backs, declared by that plugin\n * (AGL-3080). Core owns the money; this says what is counted and what it is\n * called.\n */\nexport const PLUGIN_ORG_CAPACITIES_DECLARED: readonly ResolvedPluginOrgCapacity[] = [\n {\n \"pluginId\": \"data\",\n \"kind\": \"datasets\",\n \"order\": 30,\n \"collection\": \"datasets\",\n \"addonKind\": \"datasets\",\n \"includedEntitlement\": \"datasetsPerOrg\",\n \"purchaseCeilingEntitlement\": \"maxDatasetsPerOrg\",\n \"nouns\": {\n \"one\": \"dataset\",\n \"many\": \"datasets\",\n \"addon\": \"extra datasets\"\n }\n },\n]\n\n/**\n * Every first-party element that runs a site function, and the prop naming\n * it, declared by that element's plugin (AGL-3393). Core names no element.\n */\nexport const FIRST_PARTY_FUNCTION_BINDINGS: FunctionBindings = {}\n"],"names":["FIRST_PARTY_PLUGINS","PUBLISHED_SITE_IMPACT","PLUGIN_EDIT_BAR_LINKS","PLUGIN_HOST_COLLECTIONS_DECLARED","PLUGIN_ORG_COLLECTIONS_DECLARED","PLUGIN_ORG_CAPACITIES_DECLARED","FIRST_PARTY_FUNCTION_BINDINGS"],"mappings":"AAAA;;;;;;;CAOC,GAOD,OAAO,MAAMA,sBAAmD;IAC9D;QACE,MAAM;QACN,SAAS;QACT,YAAY;QACZ,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;YACT,WAAW;YACX,SAAS;gBACP,WAAW;gBACX,QAAQ;YACV;QACF;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;QACX;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;QACX;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;QACf,qBAAqB;QACrB,YAAY;YACV;SACD;IACH;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;CACD,CAAA;AAED,OAAO,MAAMC,wBAAuE;IAClF,OAAO;IACP,SAA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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/first-party-plugins.generated.ts"],"sourcesContent":["/**\n * GENERATED FILE — do not edit. Regenerate with:\n * node tools/scripts/generate-plugin-manifests.mjs\n *\n * The switchboard catalog (AGL-3080): one row per plugin and capability, each\n * declared by its own `catalog` block in plugins.config.json. The core holds\n * the types and the resolvers in `enabled-plugins.ts`; it holds no row.\n */\n\nimport type { FirstPartyPlugin, PluginEditBarLink, PublishedSiteImpact } from './enabled-plugins'\nimport type { ResolvedPluginHostCollection, ResolvedPluginOrgCollection } from './plugin-host-collections'\nimport type { ResolvedPluginSitemapSection } from './plugin-sitemap-sections'\nimport type { ResolvedPluginSiteBundleSectionDeclaration } from './plugin-site-bundle'\nimport type { ResolvedPluginOrgCapacity } from './plugin-org-capacity'\nimport type { ResolvedPluginCostAxis, ResolvedPluginSpendLine, ResolvedPluginUsageBand, ResolvedPluginUsageMeter } from './plugin-usage-axes'\nimport type { ResolvedPluginPlanFeature, ResolvedPluginPlanQuota } from './plugin-plan-entitlements'\nimport type { FunctionBindings } from './plugin-contributions'\nimport type { PluginDistribution } from './plugin-distribution'\nimport type { RepeatSourceDeclaration } from './repeat-rows'\nimport type { PluginTemplateSource } from './plugin-template-sources'\nimport type { FormRecordTargetDeclaration } from './submission-record-target'\nimport type { ResolvedBesignerDocument } from './besigner-documents'\nimport type { PluginOrgKeyedCollection } from './plugin-org-erasure'\nimport type { ResolvedVideoEmbedProvider } from './video-embed-provider'\nimport type { AnalyticsProviderDeclaration } from '../app-utils/analytics-provider'\nimport type { InteractionStepDeclaration } from '../app-utils/site-interactions'\nimport type { NotificationCategoryDeclaration, NotificationDigestDeclaration } from '../app-utils/notifications'\n\nexport const FIRST_PARTY_PLUGINS: readonly FirstPartyPlugin[] = [\n {\n \"id\": \"mui\",\n \"label\": \"Components\",\n \"alwaysOn\": true,\n \"description\": \"The base component and theme library every site builds on.\"\n },\n {\n \"id\": \"forms\",\n \"label\": \"Forms\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"Forms on the site and the catalog that owns them.\",\n \"siteOff\": {\n \"stops\": \"Switching Forms off for this site stops forms rendering on its published pages, refuses every submission sent to it, and blocks publishing a form, or a page that carries one, until Forms is back on.\",\n \"keeps\": \"Submissions already received, the workspace’s form catalog and the CRM leads its forms created are kept, and forms keep working on the workspace’s other sites.\",\n \"confirm\": true,\n \"pages\": {\n \"heading\": \"These published pages carry a form. Their forms stop rendering and stop accepting submissions:\",\n \"none\": \"No published page on this site carries a form.\"\n }\n }\n },\n {\n \"id\": \"ai\",\n \"label\": \"AI\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"The assistant, generative building and automation, and the AI add-on.\",\n \"siteOff\": {\n \"stops\": \"Switching AI off for this site hides the assistant, Describe it, the AI cards and the editor’s AI controls on this site, refuses every AI request made for it, and stops its queued AI jobs without spending credits.\",\n \"keeps\": \"It does not stop the workspace’s AI add-on, credits, allotments or overage billing, and AI keeps working on the workspace’s other sites.\"\n }\n },\n {\n \"id\": \"theme-presets\",\n \"label\": \"Themes\",\n \"alwaysOnForWorkspace\": true,\n \"description\": \"Built-in themes to pick from on Setup → Theme: Bootstrap, Minimal and Material 3.\",\n \"siteOff\": {\n \"stops\": \"Switching Themes off for this site removes its built-in themes from the theme picker.\",\n \"keeps\": \"A site already using one keeps it, with every edit made to it: picking a theme copies it onto the site, so nothing on the published site changes.\"\n }\n },\n {\n \"id\": \"accounts\",\n \"label\": \"User Accounts\",\n \"description\": \"Visitor accounts on the site: the /signin, /signup and /recover pages, and the Members blocks. On for a new site; a site created before that stays off until you turn it on.\",\n \"releaseFlag\": \"release_member_accounts\",\n \"defaultOffPerSite\": true,\n \"requires\": [\n \"commerce\"\n ]\n },\n {\n \"id\": \"bookings\",\n \"label\": \"Bookings\",\n \"description\": \"Services, open slots, and paid bookings.\",\n \"releaseFlag\": \"release_bookings\"\n },\n {\n \"id\": \"commerce\",\n \"label\": \"Commerce\",\n \"description\": \"Products, carts, checkout, orders, POS.\",\n \"releaseFlag\": \"release_commerce_v2\"\n },\n {\n \"id\": \"marketplace\",\n \"label\": \"Marketplace\",\n \"description\": \"Marketplace listings, templates, and installs.\",\n \"releaseFlag\": \"release_marketplace\"\n },\n {\n \"id\": \"crm\",\n \"label\": \"CRM\",\n \"description\": \"Leads, contacts, companies, deals, tasks and reports.\",\n \"releaseFlag\": \"release_crm\"\n },\n {\n \"id\": \"outreach\",\n \"label\": \"Sequences\",\n \"description\": \"One-to-one email sequences sent from connected mailboxes.\",\n \"releaseFlag\": \"release_outreach\"\n },\n {\n \"id\": \"data\",\n \"label\": \"Data\",\n \"description\": \"Datasets, records, and CSV import/export.\",\n \"releaseFlag\": \"release_data_store\"\n },\n {\n \"id\": \"email\",\n \"label\": \"Email\",\n \"description\": \"Designed emails and campaign sending.\",\n \"releaseFlag\": \"release_email\"\n },\n {\n \"id\": \"events-calendar\",\n \"label\": \"Events Calendar\",\n \"description\": \"Event lists and calendars.\",\n \"releaseFlag\": \"release_events\"\n },\n {\n \"id\": \"inbox\",\n \"label\": \"Inbox\",\n \"description\": \"Form submissions and lead inbox.\",\n \"releaseFlag\": \"release_inbox\"\n },\n {\n \"id\": \"logic\",\n \"label\": \"Logic\",\n \"description\": \"Variables, functions, and reference health.\",\n \"releaseFlag\": \"release_logic\"\n },\n {\n \"id\": \"marketing\",\n \"label\": \"Marketing\",\n \"description\": \"Overlays, campaigns, and experiments.\",\n \"releaseFlag\": \"release_marketing\"\n },\n {\n \"id\": \"redirects\",\n \"label\": \"Redirects\",\n \"description\": \"URL redirect rules.\",\n \"releaseFlag\": \"release_redirects\"\n },\n {\n \"id\": \"workflows\",\n \"label\": \"Automation\",\n \"description\": \"Workflows, actions, webhooks, and run logs.\",\n \"releaseFlag\": \"release_workflows\"\n },\n]\n\nexport const PUBLISHED_SITE_IMPACT: Readonly<Record<string, PublishedSiteImpact>> = {\n \"mui\": \"elements\",\n \"forms\": \"elements\",\n \"ai\": \"console-only\",\n \"theme-presets\": \"console-only\",\n \"accounts\": \"routes\",\n \"bookings\": \"elements\",\n \"commerce\": \"elements\",\n \"marketplace\": \"console-only\",\n \"crm\": \"console-only\",\n \"outreach\": \"console-only\",\n \"data\": \"console-only\",\n \"email\": \"elements\",\n \"events-calendar\": \"elements\",\n \"inbox\": \"console-only\",\n \"logic\": \"console-only\",\n \"marketing\": \"elements\",\n \"redirects\": \"routes\",\n \"workflows\": \"routes\",\n}\n\n/**\n * The admin edit bar's quick links, in the order they are drawn — each\n * declared by the plugin whose console page it opens (AGL-3080).\n */\nexport const PLUGIN_EDIT_BAR_LINKS: readonly PluginEditBarLink[] = [\n {\n \"pluginId\": \"inbox\",\n \"order\": 20,\n \"label\": \"Inbox\",\n \"path\": \"/inbox\"\n },\n {\n \"pluginId\": \"commerce\",\n \"order\": 30,\n \"label\": \"Orders\",\n \"path\": \"/products/orders\"\n },\n]\n\n/**\n * Every host subcollection a first-party plugin owns, declared by that plugin\n * (AGL-3080). Core's readers ask this list; core names no collection.\n */\nexport const PLUGIN_HOST_COLLECTIONS_DECLARED: readonly ResolvedPluginHostCollection[] = [\n {\n \"pluginId\": \"forms\",\n \"name\": \"forms\",\n \"routeSlug\": \"forms\"\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"services\",\n \"routeSlug\": \"bookings\",\n \"resource\": {\n \"kind\": \"service\",\n \"label\": \"services\",\n \"activityNoun\": \"service\",\n \"quotaKey\": \"servicesPerHost\",\n \"entitlement\": \"bookings\",\n \"fields\": [\n \"name\",\n \"description\",\n \"durationMinutes\",\n \"priceUsd\",\n \"timezone\",\n \"windows\",\n \"crmFollowUpTask\",\n \"crmMeetingActivity\"\n ]\n },\n \"siteExport\": {\n \"limit\": 50,\n \"fields\": [\n \"name\",\n \"description\",\n \"durationMinutes\",\n \"priceUsd\",\n \"timezone\",\n \"windows\",\n \"crmFollowUpTask\",\n \"crmMeetingActivity\"\n ]\n }\n },\n {\n \"pluginId\": \"bookings\",\n \"name\": \"bookings\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Booking records — a customer, a time and a service pointer. The service holds the imagery and IS scanned; a booking is the transaction against it.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"products\",\n \"routeSlug\": \"products\",\n \"resource\": {\n \"kind\": \"product\",\n \"label\": \"products\",\n \"activityNoun\": \"product\",\n \"quotaKey\": \"productsPerHost\",\n \"entitlement\": \"commerce\",\n \"fields\": [\n \"name\",\n \"slug\",\n \"description\",\n \"type\",\n \"status\",\n \"mediaUrls\",\n \"categoryIds\",\n \"tags\",\n \"options\",\n \"variants\",\n \"seo\",\n \"supplierId\",\n \"oversellPolicy\",\n \"taxExempt\",\n \"digitalFiles\",\n \"downloadLimit\",\n \"subscription\",\n \"subscriptionOptional\",\n \"gatedVideos\",\n \"relatedProductIds\",\n \"giftCard\",\n \"lowStockThreshold\",\n \"createdAtMs\",\n \"updatedAtMs\",\n \"nameLower\",\n \"nameTokens\",\n \"nameReversed\",\n \"skus\",\n \"barcodes\",\n \"priceFromCents\",\n \"soldOut\",\n \"collectionIds\",\n \"priceUsd\",\n \"inventory\",\n \"imageUrl\"\n ],\n \"stamps\": {\n \"deletedAt\": null\n }\n }\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"productCategories\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"suppliers\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"locations\",\n \"routeSlug\": \"products\",\n \"resource\": {\n \"kind\": \"location\",\n \"label\": \"inventory locations\",\n \"activityNoun\": \"inventory location\",\n \"quotaKey\": \"inventoryLocations\",\n \"entitlement\": \"commerce\",\n \"fields\": [\n \"name\",\n \"isDefault\",\n \"address\"\n ]\n }\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"coupons\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"discounts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reviews\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"memberPosts\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"resources\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"settings\",\n \"label\": \"Store settings\",\n \"routeSlug\": \"products\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"siteMembers\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"siteMemberCredentials\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"A site member's password hash, one document per member, read and written only by the membership routes (AGL-3308). A credential with no content field, and no client may read it.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"orders\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Completed orders. Line items COPY a product's `imageUrl` at purchase time, so these would match — and matching would be the wrong answer: an order is an immutable record of what was sold, deleting the asset changes nothing about it, and no author can edit one. A busy store also holds more of these than the whole read budget.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"carts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Live and abandoned carts, with the same copied line-item image and the same reasoning, at higher volume — one document per shopper session.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"checkouts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"In-flight checkout sessions. Transient buyer state carrying the same line-item snapshot as `carts`.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"reservations\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS and booking holds. Short-lived transaction rows pointing at a resource that is itself scanned.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stockHolds\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Inventory holds taken during checkout. Machine-written, short-lived, and a quantity rather than content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"subscriptions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Site membership subscriptions: a plan pointer, a status and Stripe ids. Server-written from the billing webhook.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"registers\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"POS register allocations — a count against the register add-on, read by billing (AGL-1775). No content field at all.\",\n \"resource\": {\n \"kind\": \"register\",\n \"label\": \"POS registers\",\n \"activityNoun\": \"POS register\",\n \"quotaKey\": \"posRegisters\",\n \"entitlement\": \"pos\",\n \"fields\": [\n \"name\",\n \"locationId\"\n ]\n }\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"giftCards\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Gift card balances and redemption history. Money, not content.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"licenseKeys\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Digital-product license keys issued at fulfilment: a code, an order pointer and a revocation flag.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryAdjustments\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The append-only stock adjustment ledger (AGL-2269). One row per manual stock edit and per cancellation release, unbounded over a store's life.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"inventoryReconciliation\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Reconciliation runs comparing counted stock against recorded stock. Machine-written totals.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"restockAlerts\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Back-in-stock requests: an email address and a product pointer, written by visitors.\"\n },\n {\n \"pluginId\": \"commerce\",\n \"name\": \"stripeTaxRates\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Cached Stripe tax rate ids, written by the tax sync. Vendor ids.\"\n },\n {\n \"pluginId\": \"marketplace\",\n \"name\": \"installs\"\n },\n {\n \"pluginId\": \"crm\",\n \"name\": \"leads\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Captured leads, on the same footing as `formSubmissions`: visitor-submitted, unbounded, and never a place an author places an asset.\"\n },\n {\n \"pluginId\": \"email\",\n \"name\": \"suppressions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Unsubscribes, bounces and spam complaints. Email addresses and a reason.\"\n },\n {\n \"pluginId\": \"events-calendar\",\n \"name\": \"events\",\n \"routeSlug\": \"events\"\n },\n {\n \"pluginId\": \"inbox\",\n \"name\": \"formSubmissions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"Visitor form submissions. Unbounded, PII-heavy, and a file attached to one is the visitor's upload — not a library asset an author picked, and not something deleting a library asset would break.\"\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"functions\",\n \"routeSlug\": \"logic\",\n \"resource\": {\n \"kind\": \"function\",\n \"label\": \"functions\",\n \"activityNoun\": \"function\",\n \"activityType\": \"function\",\n \"quotaKey\": \"functionsPerHost\",\n \"fields\": [\n \"name\",\n \"parameters\",\n \"variables\",\n \"operations\",\n \"returnValue\"\n ]\n },\n \"siteExport\": {\n \"limit\": 100,\n \"fields\": [\n \"name\",\n \"parameters\",\n \"variables\",\n \"operations\",\n \"returnValue\"\n ]\n }\n },\n {\n \"pluginId\": \"logic\",\n \"name\": \"variables\",\n \"routeSlug\": \"logic\",\n \"resource\": {\n \"kind\": \"variable\",\n \"label\": \"variables\",\n \"activityNoun\": \"variable\",\n \"activityType\": \"variable\",\n \"quotaKey\": \"variablesPerHost\",\n \"fields\": [\n \"name\",\n \"type\",\n \"value\",\n \"workflowId\",\n \"workflowName\"\n ]\n },\n \"siteExport\": {\n \"limit\": 100,\n \"fields\": [\n \"name\",\n \"type\",\n \"value\",\n \"workflowId\",\n \"workflowName\"\n ]\n }\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"experiments\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"overlays\",\n \"routeSlug\": \"marketing\"\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaignAttributions\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"One row per conversion — a form submission, a lead, a contact or a booking — recording which campaign the visitor arrived from. Written only by the Admin SDK, and the whole record is three sanitized UTM strings capped at a hundred characters: there is no field an asset could occupy and no surface that could pick one into it. Unbounded on the same footing as the conversions it credits.\"\n },\n {\n \"pluginId\": \"redirects\",\n \"name\": \"redirects\",\n \"routeSlug\": \"redirects\",\n \"resource\": {\n \"kind\": \"redirect\",\n \"label\": \"redirects\",\n \"activityNoun\": \"redirect\",\n \"quotaKey\": \"redirectsPerHost\",\n \"entitlement\": \"redirects\",\n \"requiresPublishRole\": true,\n \"fields\": [\n \"source\",\n \"destination\",\n \"statusCode\",\n \"kind\",\n \"priority\",\n \"enabled\"\n ],\n \"externalDestination\": {\n \"field\": \"destination\",\n \"approvedByField\": \"externalDestinationApprovedBy\"\n },\n \"livePathField\": \"source\"\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"workflows\",\n \"routeSlug\": \"automation\",\n \"resource\": {\n \"kind\": \"workflow\",\n \"label\": \"workflows\",\n \"activityNoun\": \"workflow\",\n \"activityType\": \"workflow\",\n \"quotaKey\": \"workflowsPerHost\",\n \"entitlement\": \"workflows\",\n \"fields\": [\n \"name\",\n \"steps\",\n \"returnValue\",\n \"trigger\"\n ],\n \"duplicate\": {\n \"nameField\": \"name\",\n \"fields\": [\n \"steps\",\n \"returnValue\"\n ],\n \"stamps\": {\n \"trigger\": null\n }\n }\n },\n \"siteExport\": {\n \"limit\": 100,\n \"fields\": [\n \"name\",\n \"steps\",\n \"returnValue\",\n \"trigger\"\n ]\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"webhooks\",\n \"routeSlug\": \"automation\",\n \"resource\": {\n \"kind\": \"webhook\",\n \"label\": \"webhooks\",\n \"activityNoun\": \"webhook\",\n \"entitlement\": \"webhooks\",\n \"platformCap\": \"WEBHOOK_MAX_PER_HOST\",\n \"softDeletes\": true,\n \"fields\": [\n \"name\",\n \"direction\",\n \"url\",\n \"workflowName\",\n \"secret\",\n \"enabled\"\n ]\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"actions\",\n \"routeSlug\": \"automation\",\n \"resource\": {\n \"kind\": \"action\",\n \"label\": \"interactions and actions\",\n \"activityNoun\": \"action\",\n \"platformCap\": \"ACTIONS_MAX_PER_HOST\",\n \"softDeletes\": true,\n \"fields\": [\n \"name\",\n \"description\",\n \"trigger\",\n \"steps\",\n \"enabled\",\n \"frequency\",\n \"cooldownMinutes\",\n \"audience\",\n \"nodeId\",\n \"screenId\"\n ]\n },\n \"siteExport\": {\n \"limit\": 100,\n \"fields\": [\n \"name\",\n \"trigger\",\n \"steps\",\n \"enabled\",\n \"recipe\"\n ]\n }\n },\n]\n\n/**\n * Every child sitemap a first-party plugin's documents fill, declared by that\n * plugin (AGL-3080), in the order the index lists them.\n */\nexport const PLUGIN_SITEMAP_SECTIONS_DECLARED: readonly ResolvedPluginSitemapSection[] = [\n {\n \"pluginId\": \"commerce\",\n \"section\": \"products\",\n \"collection\": \"products\",\n \"where\": {\n \"field\": \"status\",\n \"equals\": \"active\"\n },\n \"enabledBy\": {\n \"doc\": \"settings/store\",\n \"field\": \"pdpScreenId\"\n },\n \"path\": \"/products/{slug}\",\n \"skipWhen\": \"deletedAt\",\n \"lastmod\": [\n \"updatedAtMs\",\n \"createdAtMs\"\n ]\n },\n {\n \"pluginId\": \"commerce\",\n \"section\": \"catalog\",\n \"collection\": \"collections\",\n \"where\": {\n \"field\": \"kind\",\n \"equals\": \"catalog\"\n },\n \"enabledBy\": {\n \"doc\": \"settings/store\",\n \"field\": \"collectionScreenId\"\n },\n \"path\": \"/collections/{slug}\",\n \"lastmod\": [\n \"updatedAt\",\n \"createdAt\"\n ]\n },\n]\n\n/**\n * Every section of the whole-site backup a first-party plugin answers for,\n * declared by that plugin (AGL-3080), in the order the bundle carries them.\n */\nexport const PLUGIN_SITE_BUNDLE_SECTIONS_DECLARED: readonly ResolvedPluginSiteBundleSectionDeclaration[] = [\n {\n \"pluginId\": \"data\",\n \"key\": \"datasets\",\n \"limit\": 50\n }\n]\n\n/**\n * Every org collection a first-party plugin owns whose documents the media\n * scan reads, declared by that plugin (AGL-3273).\n */\nexport const PLUGIN_ORG_COLLECTIONS_DECLARED: readonly ResolvedPluginOrgCollection[] = [\n {\n \"pluginId\": \"marketing\",\n \"name\": \"campaigns\",\n \"routeSlug\": \"marketing\",\n \"siteField\": \"hostId\",\n \"holdsTransferWhile\": {\n \"field\": \"status\",\n \"values\": [\n \"scheduled\",\n \"sending\"\n ]\n }\n },\n {\n \"pluginId\": \"marketing\",\n \"name\": \"emailCampaigns\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"The campaign CONTAINER — a name, a date window, the list ids it is aimed at, a topic and the sites it runs on. Distinct from `campaigns`, which holds the sends and IS scanned because a send carries the copy that went out. A container carries no copy and no asset reference: the design a send renders is a screen, and the screen is where the picker writes.\"\n },\n {\n \"pluginId\": \"workflows\",\n \"name\": \"automations\",\n \"mediaScan\": \"none\",\n \"mediaScanReason\": \"An org automation (AGL-3302) — a trigger, its conditions, the sites it is placed on, and a step list drawn from the server steps only: email subject and body as plain text, list, dataset and campaign ids, CRM fields and waits. No step it may hold carries a media reference, the in-page steps that could (custom HTML, popups) are refused by its save route, and it is written only by that route.\"\n },\n]\n\n/**\n * Every org capacity a first-party plugin backs, declared by that plugin\n * (AGL-3080). Core owns the money; this says what is counted and what it is\n * called.\n */\nexport const PLUGIN_ORG_CAPACITIES_DECLARED: readonly ResolvedPluginOrgCapacity[] = [\n {\n \"pluginId\": \"data\",\n \"kind\": \"datasets\",\n \"order\": 30,\n \"collection\": \"datasets\",\n \"addonKind\": \"datasets\",\n \"includedEntitlement\": \"datasetsPerOrg\",\n \"purchaseCeilingEntitlement\": \"maxDatasetsPerOrg\",\n \"nouns\": {\n \"one\": \"dataset\",\n \"many\": \"datasets\",\n \"addon\": \"extra datasets\"\n }\n },\n]\n\n/**\n * What each plan includes of every quota a first-party plugin owns, declared\n * by that plugin (AGL-3080). `PLAN_ENTITLEMENTS` composes these; core names\n * no key.\n */\nexport const PLUGIN_PLAN_QUOTAS_DECLARED: readonly ResolvedPluginPlanQuota[] = [\n {\n \"pluginId\": \"forms\",\n \"key\": \"formSubmissionsPerMonth\",\n \"label\": \"Form subs / mo\",\n \"byPlan\": {\n \"free\": 20,\n \"starter\": 200,\n \"pro\": 1000,\n \"business\": 8000,\n \"scale\": 25000,\n \"advanced\": 40000,\n \"agency\": 25000,\n \"enterprise\": 50000\n }\n },\n {\n \"pluginId\": \"marketplace\",\n \"key\": \"marketplaceFeePct\",\n \"label\": \"Marketplace fee %\",\n \"price\": true,\n \"byPlan\": {\n \"free\": 30,\n \"starter\": 20,\n \"pro\": 20,\n \"business\": 20,\n \"scale\": 20,\n \"advanced\": 20,\n \"agency\": 20,\n \"enterprise\": 20\n }\n },\n {\n \"pluginId\": \"crm\",\n \"key\": \"crmEmailsPerDay\",\n \"label\": \"One-to-one emails / day\",\n \"byPlan\": {\n \"free\": 0,\n \"starter\": 50,\n \"pro\": 150,\n \"business\": 200,\n \"scale\": 300,\n \"advanced\": 500,\n \"agency\": 1000,\n \"enterprise\": 2000\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"key\": \"workflowRunsPerMonth\",\n \"label\": \"Workflow runs / mo\",\n \"byPlan\": {\n \"free\": 0,\n \"starter\": 500,\n \"pro\": 5000,\n \"business\": 50000,\n \"scale\": 150000,\n \"advanced\": 500000,\n \"agency\": 2000000,\n \"enterprise\": 4000000\n }\n },\n {\n \"pluginId\": \"ai\",\n \"key\": \"assistCreditsPerMonth\",\n \"label\": \"AI credits / mo\",\n \"byPlan\": {\n \"free\": 300,\n \"starter\": 750,\n \"pro\": 2750,\n \"business\": 7500,\n \"scale\": 10000,\n \"advanced\": 13000,\n \"agency\": 58000,\n \"enterprise\": 116000\n }\n },\n]\n\n/**\n * What each plan includes of every feature a first-party plugin owns,\n * declared by that plugin (AGL-3080).\n */\nexport const PLUGIN_PLAN_FEATURES_DECLARED: readonly ResolvedPluginPlanFeature[] = [\n {\n \"pluginId\": \"commerce\",\n \"key\": \"storefrontSubscriptions\",\n \"label\": \"Storefront subscriptions\",\n \"byPlan\": {\n \"free\": false,\n \"starter\": false,\n \"pro\": false,\n \"business\": true,\n \"scale\": true,\n \"advanced\": true,\n \"agency\": true,\n \"enterprise\": true\n }\n },\n {\n \"pluginId\": \"commerce\",\n \"key\": \"giftCards\",\n \"label\": \"Gift cards\",\n \"byPlan\": {\n \"free\": false,\n \"starter\": false,\n \"pro\": false,\n \"business\": true,\n \"scale\": true,\n \"advanced\": true,\n \"agency\": true,\n \"enterprise\": true\n }\n },\n {\n \"pluginId\": \"commerce\",\n \"key\": \"commerceAnalytics\",\n \"label\": \"Commerce analytics\",\n \"byPlan\": {\n \"free\": false,\n \"starter\": false,\n \"pro\": true,\n \"business\": true,\n \"scale\": true,\n \"advanced\": true,\n \"agency\": true,\n \"enterprise\": true\n }\n },\n {\n \"pluginId\": \"marketplace\",\n \"key\": \"marketplaceSelling\",\n \"label\": \"Sell on the marketplace\",\n \"byPlan\": {\n \"free\": false,\n \"starter\": false,\n \"pro\": true,\n \"business\": true,\n \"scale\": true,\n \"advanced\": true,\n \"agency\": true,\n \"enterprise\": true\n }\n },\n]\n\n/**\n * Every meter a first-party plugin contributes to the platform's cost model,\n * in breakdown order, declared by that plugin (AGL-3080). Core keeps the rates.\n */\nexport const PLUGIN_COST_AXES_DECLARED: readonly ResolvedPluginCostAxis[] = [\n {\n \"pluginId\": \"forms\",\n \"id\": \"formSubmissions\",\n \"order\": 30,\n \"fields\": [\n \"formSubmissions\"\n ],\n \"rate\": \"perFormSubmission\"\n },\n {\n \"pluginId\": \"crm\",\n \"id\": \"contacts\",\n \"order\": 60,\n \"fields\": [\n \"crmRecordsCount\"\n ],\n \"fallbackFields\": [\n \"contactsCount\"\n ],\n \"recordedFields\": [\n \"companiesCount\",\n \"dealsCount\"\n ],\n \"rate\": \"perContactMonth\"\n },\n {\n \"pluginId\": \"ai\",\n \"id\": \"assist\",\n \"order\": 80,\n \"fields\": [\n \"assistCostUsd\"\n ],\n \"staffFields\": [\n \"assistCredits\",\n \"assistOverageUsd\"\n ],\n \"live\": {\n \"collection\": \"assistUsage\",\n \"fields\": [\n \"providerCostUsd\",\n \"estCostUsd\"\n ]\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"id\": \"runs\",\n \"order\": 90,\n \"fields\": [\n \"workflowRuns\",\n \"actionRuns\"\n ],\n \"rate\": \"perRun\"\n },\n]\n\n/**\n * Every band a first-party plugin contributes to the utilization table, in\n * column order, declared by that plugin (AGL-3080).\n */\nexport const PLUGIN_USAGE_BANDS_DECLARED: readonly ResolvedPluginUsageBand[] = [\n {\n \"pluginId\": \"forms\",\n \"id\": \"formSubmissions\",\n \"label\": \"Form submissions\",\n \"order\": 40,\n \"fields\": [\n \"formSubmissions\"\n ],\n \"entitlement\": \"formSubmissionsPerMonth\",\n \"perHost\": true,\n \"hostCounter\": \"formSubmissions\",\n \"metered\": {\n \"rate\": \"perFormSubmission\",\n \"quotedPer\": 1000,\n \"noun\": \"form submissions\",\n \"withheldUntil\": \"release_inbox\"\n }\n },\n {\n \"pluginId\": \"crm\",\n \"id\": \"contactsCount\",\n \"label\": \"CRM records\",\n \"order\": 70,\n \"fields\": [\n \"crmRecordsCount\"\n ],\n \"fallbackFields\": [\n \"contactsCount\"\n ],\n \"entitlement\": \"contactsPerHost\"\n },\n {\n \"pluginId\": \"ai\",\n \"id\": \"assistCredits\",\n \"label\": \"Assist credits\",\n \"order\": 90,\n \"fields\": [\n \"assistCostUsd\"\n ],\n \"entitlement\": \"assistCreditsPerMonth\",\n \"unitCostUsd\": 0.001\n },\n {\n \"pluginId\": \"workflows\",\n \"id\": \"workflowRuns\",\n \"label\": \"Workflow runs\",\n \"order\": 100,\n \"fields\": [\n \"workflowRuns\"\n ],\n \"entitlement\": \"workflowRunsPerMonth\",\n \"hostCounter\": \"workflowRuns\",\n \"alert\": {\n \"label\": \"monthly workflow runs\",\n \"noun\": \"workflow runs\",\n \"outcome\": \"stops\",\n \"reached\": \"Workflows pause until next month and nothing is charged — upgrade in Billing to keep them running.\",\n \"approach\": \"Nothing changes and nothing is charged — at the included amount, workflows pause until next month unless you upgrade in Billing.\"\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"id\": \"actionRuns\",\n \"label\": \"Action runs\",\n \"order\": 110,\n \"fields\": [\n \"actionRuns\"\n ],\n \"entitlement\": \"actionRunsPerMonth\"\n },\n]\n\n/**\n * Every line of a workspace's monthly spend a first-party plugin contributes\n * to its usage budget, in catalog order, declared by that plugin (AGL-3080).\n */\nexport const PLUGIN_SPEND_LINES_DECLARED: readonly ResolvedPluginSpendLine[] = [\n {\n \"pluginId\": \"ai\",\n \"id\": \"assist\",\n \"label\": \"Assist\",\n \"live\": {\n \"collection\": \"assistUsage\",\n \"field\": \"estCostUsd\"\n },\n \"billedFromEnv\": \"BILL_ASSIST_TOKENS_FROM\",\n \"unit\": {\n \"costUsd\": 0.001,\n \"label\": \"Assist credits\"\n }\n },\n]\n\n/**\n * Every meter a first-party plugin measures in the monthly usage sweep, in\n * catalog order, declared by that plugin (AGL-3080). The sweep refuses to bill\n * a month while one of these is unregistered.\n */\nexport const PLUGIN_USAGE_METERS_DECLARED: readonly ResolvedPluginUsageMeter[] = [\n {\"pluginId\":\"crm\",\"id\":\"records\"},\n {\"pluginId\":\"data\",\"id\":\"dataset-storage\"},\n {\"pluginId\":\"ai\",\"id\":\"assist\"},\n]\n\n/**\n * Every top-level plugin collection a workspace erasure sweeps by the field\n * naming the organization, declared by the plugin that owns it (AGL-3080).\n */\nexport const PLUGIN_ORG_KEYED_COLLECTIONS: readonly PluginOrgKeyedCollection[] = [\n {\n \"pluginId\": \"outreach\",\n \"name\": \"outreachMailboxCredentials\",\n \"orgField\": \"orgId\"\n },\n {\n \"pluginId\": \"outreach\",\n \"name\": \"outreachLinks\",\n \"orgField\": \"orgId\"\n },\n]\n\n/**\n * The plugins whose org eraser a workspace erasure may not run without\n * (AGL-3080): each holds a record the erasure promises to destroy.\n */\nexport const PLUGIN_REQUIRED_ORG_ERASERS: readonly string[] = [\"marketplace\"]\n\n/**\n * The plugins whose sales the operator's sales tax return may not be filed\n * without (AGL-3080): each registers a tax return source, and one that did\n * not is refused rather than read as nothing sold.\n */\nexport const PLUGIN_TAX_RETURN_SOURCES: readonly string[] = [\"commerce\",\"marketplace\"]\n\n/**\n * The plugins whose earnings the operator's revenue report may not be read\n * without (AGL-3080): each registers a revenue source, and one that did not\n * is refused rather than read as nothing earned.\n */\nexport const PLUGIN_REVENUE_SOURCES: readonly string[] = [\"commerce\",\"marketplace\"]\n\n/**\n * Where published plugin versions and their kill switches are stored, declared\n * by the plugin that distributes them (AGL-3080). `null` when none does, and\n * the realm loader then resolves nothing.\n */\nexport const PLUGIN_DISTRIBUTION: PluginDistribution | null = {\n \"pluginId\": \"marketplace\",\n \"listings\": \"marketplaceListings\",\n \"versions\": \"pluginVersions\",\n \"revocations\": \"revocations\"\n}\n\n/**\n * The plugin that answers a published page's repeats, declared by that plugin\n * (AGL-3080). `null` when none does, and a repeat then renders its element\n * once, as written.\n */\nexport const PLUGIN_REPEAT_SOURCE_DECLARED: RepeatSourceDeclaration | null = {\n \"pluginId\": \"data\",\n \"id\": \"dataset\"\n}\n\n/**\n * The site documents a plugin authors in the besigner, declared by that\n * plugin (AGL-3080). Empty when none does, and the console's plugin-document\n * editor routes answer 404.\n */\nexport const PLUGIN_BESIGNER_DOCUMENTS_DECLARED: readonly ResolvedBesignerDocument[] = [\n {\n \"pluginId\": \"forms\",\n \"kind\": \"form\",\n \"segment\": \"forms\",\n \"collection\": \"forms\",\n \"noun\": \"form\",\n \"publish\": {\n \"path\": \"/api/forms/promote\",\n \"idField\": \"formId\"\n }\n },\n]\n\n/**\n * The plugin whose records a form's submission may also be filed as, declared\n * by that plugin (AGL-3080). `null` when none does, and no form writes one.\n */\nexport const PLUGIN_FORM_RECORD_TARGET_DECLARED: FormRecordTargetDeclaration | null = {\n \"pluginId\": \"data\",\n \"id\": \"dataset\"\n}\n\n/**\n * What a site's template library calls a template a plugin installed, by the\n * `source.type` that plugin stamps, declared by that plugin (AGL-3080).\n * Core names no installer.\n */\nexport const PLUGIN_TEMPLATE_SOURCES: readonly PluginTemplateSource[] = [\n {\n \"pluginId\": \"marketplace\",\n \"type\": \"marketplace\",\n \"label\": \"Marketplace\",\n \"description\": \"Installed from the marketplace\"\n },\n]\n\n/**\n * The analytics settings each provider mounts a tag for, declared by the\n * plugin that adapts the vendor (AGL-3080). Empty when none does, and then no\n * setting configures a tag.\n */\nexport const ANALYTICS_PROVIDERS_DECLARED: readonly AnalyticsProviderDeclaration[] = [\n {\n \"pluginId\": \"marketing\",\n \"settings\": [\n \"gaMeasurementId\",\n \"gtmContainerId\"\n ]\n },\n]\n\n/**\n * Every interaction step a first-party plugin offers in the interaction\n * builder, declared by that plugin (AGL-3080). Core names no plugin step.\n */\nexport const PLUGIN_INTERACTION_STEPS_DECLARED: readonly InteractionStepDeclaration[] = [\n {\n \"pluginId\": \"marketing\",\n \"type\": \"showOverlay\",\n \"label\": \"Open an overlay\",\n \"picks\": {\n \"collection\": \"overlays\",\n \"limit\": 50,\n \"idField\": \"overlayId\",\n \"nameField\": \"overlayName\",\n \"label\": \"Overlay\",\n \"missing\": \"pick an overlay\"\n }\n },\n {\n \"pluginId\": \"workflows\",\n \"type\": \"runWorkflow\",\n \"label\": \"Run a workflow\",\n \"picks\": {\n \"collection\": \"workflows\",\n \"limit\": 100,\n \"idField\": \"workflowId\",\n \"nameField\": \"workflowName\",\n \"label\": \"Workflow\",\n \"missing\": \"pick a workflow\"\n }\n },\n]\n\n/**\n * Every first-party element that runs a site function, and the prop naming\n * it, declared by that element's plugin (AGL-3393). Core names no element.\n */\nexport const FIRST_PARTY_FUNCTION_BINDINGS: FunctionBindings = {}\n\n/**\n * Every video host whose own player the Video element frames, declared by\n * the plugin that plays it (AGL-3080). Core names no host.\n */\nexport const FIRST_PARTY_VIDEO_EMBED_PROVIDERS: readonly ResolvedVideoEmbedProvider[] = [\n {\n \"pluginId\": \"mui\",\n \"id\": \"wistia\",\n \"label\": \"Wistia\",\n \"domains\": [\n \"wistia.com\",\n \"wistia.net\",\n \"wi.st\"\n ],\n \"mediaIdPaths\": [\n \"^\\\\/medias\\\\/([^/]+)(?:\\\\/manage)?\\\\/?$\",\n \"^\\\\/m\\\\/([^/]+)\\\\/?$\",\n \"^\\\\/embed\\\\/iframe\\\\/([^/]+)\\\\/?$\",\n \"^\\\\/embed\\\\/medias\\\\/([^/.]+)(?:\\\\.jsonp?)?\\\\/?$\"\n ],\n \"mediaIdPattern\": \"^[a-z0-9]{10}$\",\n \"playerOrigin\": \"https://fast.wistia.net\",\n \"playerPath\": \"/embed/iframe/{id}\",\n \"playerQuery\": [\n {\n \"param\": \"autoPlay\",\n \"option\": \"autoPlay\",\n \"on\": \"true\",\n \"off\": \"false\"\n },\n {\n \"param\": \"roundedPlayer\",\n \"value\": \"false\"\n },\n {\n \"param\": \"doNotTrack\",\n \"option\": \"doNotTrack\",\n \"on\": \"true\"\n },\n {\n \"param\": \"muted\",\n \"option\": \"muted\",\n \"on\": \"true\"\n },\n {\n \"param\": \"endVideoBehavior\",\n \"option\": \"loop\",\n \"on\": \"loop\"\n }\n ]\n },\n]\n\n/**\n * The notification categories first-party plugins add to the settings page\n * and to every recipient's preferences, declared by each plugin (AGL-3080).\n */\nexport const PLUGIN_NOTIFICATION_CATEGORIES_DECLARED: readonly NotificationCategoryDeclaration[] = [\n {\n \"pluginId\": \"marketplace\",\n \"id\": \"marketplace\",\n \"label\": \"Marketplace\",\n \"description\": \"Decisions on plugin listings you submitted for review.\",\n \"defaults\": {\n \"console\": true,\n \"email\": false\n }\n },\n]\n\n/**\n * The digests first-party plugins send on their own schedule, each with the\n * key its switch is stored under, declared by the plugin that sends it\n * (AGL-3080).\n */\nexport const PLUGIN_NOTIFICATION_DIGESTS_DECLARED: readonly NotificationDigestDeclaration[] = [\n {\n \"pluginId\": \"crm\",\n \"key\": \"crmDaily\",\n \"label\": \"Daily CRM digest\",\n \"description\": \"Each morning: your overdue and due-today tasks and the leads nobody has worked, here and by email.\"\n },\n]\n"],"names":["FIRST_PARTY_PLUGINS","PUBLISHED_SITE_IMPACT","PLUGIN_EDIT_BAR_LINKS","PLUGIN_HOST_COLLECTIONS_DECLARED","PLUGIN_SITEMAP_SECTIONS_DECLARED","PLUGIN_SITE_BUNDLE_SECTIONS_DECLARED","PLUGIN_ORG_COLLECTIONS_DECLARED","PLUGIN_ORG_CAPACITIES_DECLARED","PLUGIN_PLAN_QUOTAS_DECLARED","PLUGIN_PLAN_FEATURES_DECLARED","PLUGIN_COST_AXES_DECLARED","PLUGIN_USAGE_BANDS_DECLARED","PLUGIN_SPEND_LINES_DECLARED","PLUGIN_USAGE_METERS_DECLARED","PLUGIN_ORG_KEYED_COLLECTIONS","PLUGIN_REQUIRED_ORG_ERASERS","PLUGIN_TAX_RETURN_SOURCES","PLUGIN_REVENUE_SOURCES","PLUGIN_DISTRIBUTION","PLUGIN_REPEAT_SOURCE_DECLARED","PLUGIN_BESIGNER_DOCUMENTS_DECLARED","PLUGIN_FORM_RECORD_TARGET_DECLARED","PLUGIN_TEMPLATE_SOURCES","ANALYTICS_PROVIDERS_DECLARED","PLUGIN_INTERACTION_STEPS_DECLARED","FIRST_PARTY_FUNCTION_BINDINGS","FIRST_PARTY_VIDEO_EMBED_PROVIDERS","PLUGIN_NOTIFICATION_CATEGORIES_DECLARED","PLUGIN_NOTIFICATION_DIGESTS_DECLARED"],"mappings":"AAAA;;;;;;;CAOC,GAqBD,OAAO,MAAMA,sBAAmD;IAC9D;QACE,MAAM;QACN,SAAS;QACT,YAAY;QACZ,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;YACT,WAAW;YACX,SAAS;gBACP,WAAW;gBACX,QAAQ;YACV;QACF;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;QACX;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,wBAAwB;QACxB,eAAe;QACf,WAAW;YACT,SAAS;YACT,SAAS;QACX;IACF;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;QACf,qBAAqB;QACrB,YAAY;YACV;SACD;IACH;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;IACA;QACE,MAAM;QACN,SAAS;QACT,eAAe;QACf,eAAe;IACjB;CACD,CAAA;AAED,OAAO,MAAMC,wBAAuE;IAClF,OAAO;IACP,SAAS;IACT,MAAM;IACN,iBAAiB;IACjB,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,eAAe;IACf,OAAO;IACP,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,mBAAmB;IACnB,SAAS;IACT,SAAS;IACT,aAAa;IACb,aAAa;IACb,aAAa;AACf,EAAC;AAED;;;CAGC,GACD,OAAO,MAAMC,wBAAsD;IACjE;QACE,YAAY;QACZ,SAAS;QACT,SAAS;QACT,QAAQ;IACV;IACA;QACE,YAAY;QACZ,SAAS;QACT,SAAS;QACT,QAAQ;IACV;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,mCAA4E;IACvF;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,YAAY;YACZ,eAAe;YACf,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;aACD;QACH;QACA,cAAc;YACZ,SAAS;YACT,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,YAAY;YACZ,eAAe;YACf,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;aACD;YACD,UAAU;gBACR,aAAa;YACf;QACF;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,YAAY;YACZ,eAAe;YACf,UAAU;gBACR;gBACA;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;IACV;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;QACnB,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,YAAY;YACZ,eAAe;YACf,UAAU;gBACR;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;IACV;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,gBAAgB;YAChB,YAAY;YACZ,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;aACD;QACH;QACA,cAAc;YACZ,SAAS;YACT,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,gBAAgB;YAChB,YAAY;YACZ,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;aACD;QACH;QACA,cAAc;YACZ,SAAS;YACT,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;IACf;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,YAAY;YACZ,eAAe;YACf,uBAAuB;YACvB,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;gBACA;aACD;YACD,uBAAuB;gBACrB,SAAS;gBACT,mBAAmB;YACrB;YACA,iBAAiB;QACnB;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,gBAAgB;YAChB,YAAY;YACZ,eAAe;YACf,UAAU;gBACR;gBACA;gBACA;gBACA;aACD;YACD,aAAa;gBACX,aAAa;gBACb,UAAU;oBACR;oBACA;iBACD;gBACD,UAAU;oBACR,WAAW;gBACb;YACF;QACF;QACA,cAAc;YACZ,SAAS;YACT,UAAU;gBACR;gBACA;gBACA;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,eAAe;YACf,eAAe;YACf,eAAe;YACf,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,YAAY;YACV,QAAQ;YACR,SAAS;YACT,gBAAgB;YAChB,eAAe;YACf,eAAe;YACf,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;gBACA;aACD;QACH;QACA,cAAc;YACZ,SAAS;YACT,UAAU;gBACR;gBACA;gBACA;gBACA;gBACA;aACD;QACH;IACF;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,mCAA4E;IACvF;QACE,YAAY;QACZ,WAAW;QACX,cAAc;QACd,SAAS;YACP,SAAS;YACT,UAAU;QACZ;QACA,aAAa;YACX,OAAO;YACP,SAAS;QACX;QACA,QAAQ;QACR,YAAY;QACZ,WAAW;YACT;YACA;SACD;IACH;IACA;QACE,YAAY;QACZ,WAAW;QACX,cAAc;QACd,SAAS;YACP,SAAS;YACT,UAAU;QACZ;QACA,aAAa;YACX,OAAO;YACP,SAAS;QACX;QACA,QAAQ;QACR,WAAW;YACT;YACA;SACD;IACH;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,uCAA8F;IACzG;QACE,YAAY;QACZ,OAAO;QACP,SAAS;IACX;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,kCAA0E;IACrF;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,aAAa;QACb,sBAAsB;YACpB,SAAS;YACT,UAAU;gBACR;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;IACA;QACE,YAAY;QACZ,QAAQ;QACR,aAAa;QACb,mBAAmB;IACrB;CACD,CAAA;AAED;;;;CAIC,GACD,OAAO,MAAMC,iCAAuE;IAClF;QACE,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,cAAc;QACd,aAAa;QACb,uBAAuB;QACvB,8BAA8B;QAC9B,SAAS;YACP,OAAO;YACP,QAAQ;YACR,SAAS;QACX;IACF;CACD,CAAA;AAED;;;;CAIC,GACD,OAAO,MAAMC,8BAAkE;IAC7E;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,gCAAsE;IACjF;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;IACA;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,UAAU;YACR,QAAQ;YACR,WAAW;YACX,OAAO;YACP,YAAY;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,cAAc;QAChB;IACF;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,4BAA+D;IAC1E;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,UAAU;YACR;SACD;QACD,QAAQ;IACV;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,UAAU;YACR;SACD;QACD,kBAAkB;YAChB;SACD;QACD,kBAAkB;YAChB;YACA;SACD;QACD,QAAQ;IACV;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,UAAU;YACR;SACD;QACD,eAAe;YACb;YACA;SACD;QACD,QAAQ;YACN,cAAc;YACd,UAAU;gBACR;gBACA;aACD;QACH;IACF;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,UAAU;YACR;YACA;SACD;QACD,QAAQ;IACV;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,8BAAkE;IAC7E;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,SAAS;QACT,UAAU;YACR;SACD;QACD,eAAe;QACf,WAAW;QACX,eAAe;QACf,WAAW;YACT,QAAQ;YACR,aAAa;YACb,QAAQ;YACR,iBAAiB;QACnB;IACF;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,SAAS;QACT,UAAU;YACR;SACD;QACD,kBAAkB;YAChB;SACD;QACD,eAAe;IACjB;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,SAAS;QACT,UAAU;YACR;SACD;QACD,eAAe;QACf,eAAe;IACjB;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,SAAS;QACT,UAAU;YACR;SACD;QACD,eAAe;QACf,eAAe;QACf,SAAS;YACP,SAAS;YACT,QAAQ;YACR,WAAW;YACX,WAAW;YACX,YAAY;QACd;IACF;IACA;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,SAAS;QACT,UAAU;YACR;SACD;QACD,eAAe;IACjB;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,8BAAkE;IAC7E;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,QAAQ;YACN,cAAc;YACd,SAAS;QACX;QACA,iBAAiB;QACjB,QAAQ;YACN,WAAW;YACX,SAAS;QACX;IACF;CACD,CAAA;AAED;;;;CAIC,GACD,OAAO,MAAMC,+BAAoE;IAC/E;QAAC,YAAW;QAAM,MAAK;IAAS;IAChC;QAAC,YAAW;QAAO,MAAK;IAAiB;IACzC;QAAC,YAAW;QAAK,MAAK;IAAQ;CAC/B,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,+BAAoE;IAC/E;QACE,YAAY;QACZ,QAAQ;QACR,YAAY;IACd;IACA;QACE,YAAY;QACZ,QAAQ;QACR,YAAY;IACd;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,8BAAiD;IAAC;CAAc,CAAA;AAE7E;;;;CAIC,GACD,OAAO,MAAMC,4BAA+C;IAAC;IAAW;CAAc,CAAA;AAEtF;;;;CAIC,GACD,OAAO,MAAMC,yBAA4C;IAAC;IAAW;CAAc,CAAA;AAEnF;;;;CAIC,GACD,OAAO,MAAMC,sBAAiD;IAC5D,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,eAAe;AACjB,EAAC;AAED;;;;CAIC,GACD,OAAO,MAAMC,gCAAgE;IAC3E,YAAY;IACZ,MAAM;AACR,EAAC;AAED;;;;CAIC,GACD,OAAO,MAAMC,qCAA0E;IACrF;QACE,YAAY;QACZ,QAAQ;QACR,WAAW;QACX,cAAc;QACd,QAAQ;QACR,WAAW;YACT,QAAQ;YACR,WAAW;QACb;IACF;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,qCAAyE;IACpF,YAAY;IACZ,MAAM;AACR,EAAC;AAED;;;;CAIC,GACD,OAAO,MAAMC,0BAA2D;IACtE;QACE,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,eAAe;IACjB;CACD,CAAA;AAED;;;;CAIC,GACD,OAAO,MAAMC,+BAAwE;IACnF;QACE,YAAY;QACZ,YAAY;YACV;YACA;SACD;IACH;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,oCAA2E;IACtF;QACE,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,SAAS;YACP,cAAc;YACd,SAAS;YACT,WAAW;YACX,aAAa;YACb,SAAS;YACT,WAAW;QACb;IACF;IACA;QACE,YAAY;QACZ,QAAQ;QACR,SAAS;QACT,SAAS;YACP,cAAc;YACd,SAAS;YACT,WAAW;YACX,aAAa;YACb,SAAS;YACT,WAAW;QACb;IACF;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,gCAAkD,CAAC,EAAC;AAEjE;;;CAGC,GACD,OAAO,MAAMC,oCAA2E;IACtF;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,WAAW;YACT;YACA;YACA;SACD;QACD,gBAAgB;YACd;YACA;YACA;YACA;SACD;QACD,kBAAkB;QAClB,gBAAgB;QAChB,cAAc;QACd,eAAe;YACb;gBACE,SAAS;gBACT,UAAU;gBACV,MAAM;gBACN,OAAO;YACT;YACA;gBACE,SAAS;gBACT,SAAS;YACX;YACA;gBACE,SAAS;gBACT,UAAU;gBACV,MAAM;YACR;YACA;gBACE,SAAS;gBACT,UAAU;gBACV,MAAM;YACR;YACA;gBACE,SAAS;gBACT,UAAU;gBACV,MAAM;YACR;SACD;IACH;CACD,CAAA;AAED;;;CAGC,GACD,OAAO,MAAMC,0CAAsF;IACjG;QACE,YAAY;QACZ,MAAM;QACN,SAAS;QACT,eAAe;QACf,YAAY;YACV,WAAW;YACX,SAAS;QACX;IACF;CACD,CAAA;AAED;;;;CAIC,GACD,OAAO,MAAMC,uCAAiF;IAC5F;QACE,YAAY;QACZ,OAAO;QACP,SAAS;QACT,eAAe;IACjB;CACD,CAAA"}
|
|
@@ -30,7 +30,6 @@ export * from './plugin-resource-drafts';
|
|
|
30
30
|
export * from './plugin-activity-actions';
|
|
31
31
|
export * from './plugin-entitlements';
|
|
32
32
|
export * from './plugin-events';
|
|
33
|
-
export * from './plugin-metered-lines';
|
|
34
33
|
export * from './plugin-user-erasure';
|
|
35
34
|
export * from './plugin-styles';
|
|
36
35
|
export * from './plugin-contributions';
|
|
@@ -31,7 +31,6 @@ export * from "./plugin-resource-drafts.js";
|
|
|
31
31
|
export * from "./plugin-activity-actions.js";
|
|
32
32
|
export * from "./plugin-entitlements.js";
|
|
33
33
|
export * from "./plugin-events.js";
|
|
34
|
-
export * from "./plugin-metered-lines.js";
|
|
35
34
|
export * from "./plugin-user-erasure.js";
|
|
36
35
|
// `plugin-org-erasure` is server-only too: import it by its own path.
|
|
37
36
|
export * from "./plugin-styles.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 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\nexport { default } from './plugin-manager'\nexport * from './plugin-manager'\nexport * from './billing-webhook-hooks'\nexport * from './custom-fields'\nexport * from './editor-sessions'\nexport * from './enabled-plugins'\nexport * from './install-presets'\nexport * from './plugin-config'\nexport * from './order-fulfilment'\nexport * from './plugin-jobs'\nexport * from './plugin-permissions'\nexport * from './plugin-services'\nexport * from './plugin-resource-drafts'\n// `plugin-figures` is imported by its own path, never from here: it serves\n// server-side readers only, and this barrel is on every published page.\nexport * from './plugin-activity-actions'\nexport * from './plugin-entitlements'\nexport * from './plugin-events'\nexport * from './plugin-
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2022 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\nexport { default } from './plugin-manager'\nexport * from './plugin-manager'\nexport * from './billing-webhook-hooks'\nexport * from './custom-fields'\nexport * from './editor-sessions'\nexport * from './enabled-plugins'\nexport * from './install-presets'\nexport * from './plugin-config'\nexport * from './order-fulfilment'\nexport * from './plugin-jobs'\nexport * from './plugin-permissions'\nexport * from './plugin-services'\nexport * from './plugin-resource-drafts'\n// `plugin-figures` is imported by its own path, never from here: it serves\n// server-side readers only, and this barrel is on every published page.\nexport * from './plugin-activity-actions'\nexport * from './plugin-entitlements'\nexport * from './plugin-events'\nexport * from './plugin-user-erasure'\n// `plugin-org-erasure` is server-only too: import it by its own path.\nexport * from './plugin-styles'\nexport * from './plugin-contributions'\nexport * from './plugin-loader'\nexport * from './realm-plugins'\nexport * from './site-page-hooks'\nexport * from './site-runtime'\nexport * from './feature-plugins'\nexport * from './plugin-bridge'\n"],"names":["default"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,OAAO,QAAQ,sBAAkB;AAC1C,cAAc,sBAAkB;AAChC,cAAc,6BAAyB;AACvC,cAAc,qBAAiB;AAC/B,cAAc,uBAAmB;AACjC,cAAc,uBAAmB;AACjC,cAAc,uBAAmB;AACjC,cAAc,qBAAiB;AAC/B,cAAc,wBAAoB;AAClC,cAAc,mBAAe;AAC7B,cAAc,0BAAsB;AACpC,cAAc,uBAAmB;AACjC,cAAc,8BAA0B;AACxC,2EAA2E;AAC3E,wEAAwE;AACxE,cAAc,+BAA2B;AACzC,cAAc,2BAAuB;AACrC,cAAc,qBAAiB;AAC/B,cAAc,2BAAuB;AACrC,sEAAsE;AACtE,cAAc,qBAAiB;AAC/B,cAAc,4BAAwB;AACtC,cAAc,qBAAiB;AAC/B,cAAc,qBAAiB;AAC/B,cAAc,uBAAmB;AACjC,cAAc,oBAAgB;AAC9B,cAAc,uBAAmB;AACjC,cAAc,qBAAiB"}
|
|
@@ -85,6 +85,13 @@ export interface PluginActivityRegistration {
|
|
|
85
85
|
pluginId: string;
|
|
86
86
|
group: PluginActivityGroup;
|
|
87
87
|
actions: readonly PluginActivityAction[];
|
|
88
|
+
/**
|
|
89
|
+
* Target types the plugin's rows are filed under that are NOT namespaced,
|
|
90
|
+
* with the noun a reader sees for each (AGL-3080): rows written before
|
|
91
|
+
* `pluginId:noun` existed, whose stored type cannot change. A namespaced
|
|
92
|
+
* type needs no entry — the feed reads its noun off the type itself.
|
|
93
|
+
*/
|
|
94
|
+
targetTypes?: Readonly<Record<string, string>>;
|
|
88
95
|
}
|
|
89
96
|
/**
|
|
90
97
|
* The most codes one group may hold. A group's chip asks `action is any of`
|
|
@@ -100,6 +107,11 @@ export declare const PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS = 30;
|
|
|
100
107
|
* too, since its chip could never be applied.
|
|
101
108
|
*/
|
|
102
109
|
export declare function registerPluginActivityActions(registration: PluginActivityRegistration): void;
|
|
110
|
+
/**
|
|
111
|
+
* The noun a plugin declared for one of its un-namespaced target types, or
|
|
112
|
+
* `undefined` when no plugin declared the type.
|
|
113
|
+
*/
|
|
114
|
+
export declare function pluginActivityTargetLabel(type: unknown): string | undefined;
|
|
103
115
|
/** Every registration, in registration order. */
|
|
104
116
|
export declare function listPluginActivityRegistrations(): PluginActivityRegistration[];
|
|
105
117
|
/** Every declared action across plugins. */
|
|
@@ -53,6 +53,7 @@ const registrations = new Map();
|
|
|
53
53
|
* group of more than `PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS` codes is refused
|
|
54
54
|
* too, since its chip could never be applied.
|
|
55
55
|
*/ export function registerPluginActivityActions(registration) {
|
|
56
|
+
var _registration_targetTypes;
|
|
56
57
|
const pluginId = registration.pluginId.trim();
|
|
57
58
|
if (!pluginId) throw new Error('plugin activity actions need a pluginId');
|
|
58
59
|
if (registration.actions.length > PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS) {
|
|
@@ -64,8 +65,32 @@ const registrations = new Map();
|
|
|
64
65
|
throw new Error(`activity action "${action.key}" is already declared by "${owner}"; ` + `refused "${pluginId}"`);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
68
|
+
for (const type of Object.keys((_registration_targetTypes = registration.targetTypes) != null ? _registration_targetTypes : {})){
|
|
69
|
+
var _find;
|
|
70
|
+
const owner = (_find = [
|
|
71
|
+
...registrations.values()
|
|
72
|
+
].find((entry)=>{
|
|
73
|
+
var _entry_targetTypes;
|
|
74
|
+
return entry.pluginId !== pluginId && ((_entry_targetTypes = entry.targetTypes) == null ? void 0 : _entry_targetTypes[type]) !== undefined;
|
|
75
|
+
})) == null ? void 0 : _find.pluginId;
|
|
76
|
+
if (owner) {
|
|
77
|
+
throw new Error(`activity target type "${type}" is already declared by "${owner}"; ` + `refused "${pluginId}"`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
67
80
|
registrations.set(pluginId, registration);
|
|
68
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* The noun a plugin declared for one of its un-namespaced target types, or
|
|
84
|
+
* `undefined` when no plugin declared the type.
|
|
85
|
+
*/ export function pluginActivityTargetLabel(type) {
|
|
86
|
+
if (typeof type !== 'string') return undefined;
|
|
87
|
+
for (const registration of registrations.values()){
|
|
88
|
+
var _registration_targetTypes;
|
|
89
|
+
const label = (_registration_targetTypes = registration.targetTypes) == null ? void 0 : _registration_targetTypes[type];
|
|
90
|
+
if (label) return label;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
69
94
|
function ownerOfActivityAction(key) {
|
|
70
95
|
for (const registration of registrations.values()){
|
|
71
96
|
if (registration.actions.some((action)=>action.key === key)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-activity-actions.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 * Plugin-declared activity actions (AGL-2940).\n *\n * Most rows in `orgs/{orgId}/activity` and `hosts/{hostId}/activity` store\n * a prose action written at the call site. A plugin whose rows are read by\n * more than a person — a filter chip, a staff facet, an actor table — stores\n * a CODE (`ai.job.output`) and declares here what the code means: the label\n * a reader sees, the scope it is written at, and the group its filter chip\n * belongs to. The activity renderers read this catalog for labels and\n * filters, so a second plugin with coded rows gets a chip and a facet group\n * by registering, with no edit to the renderers.\n *\n * Declared at module scope from both the client barrel and the `/server`\n * entry (the AGL-428 pattern), with an explicit `pluginId`: module scope\n * runs before the loader's ownership marker is set.\n */\n\nexport type PluginActivityScope = 'org' | 'host' | 'staff'\n\n/**\n * A resource a PLUGIN files an org activity row under (AGL-2978): the\n * plugin's id, a colon and the plugin's own noun — `acme-mail:mailbox`.\n *\n * Core's activity targets are a closed list of core's own resources. A\n * plugin's resource is not one of them and is never added to that list; the\n * org log's target type accepts any namespaced type instead, and the feed\n * reads the noun after the colon for a reader. The namespace keeps two\n * plugins' nouns from meaning one thing.\n */\nexport type PluginActivityTargetType = `${string}:${string}`\n\n/** A namespaced type as the log stores it: `pluginId:noun`, both parts plain. */\nconst PLUGIN_TARGET_TYPE = /^([a-z][a-z0-9-]*):([A-Za-z][A-Za-z0-9]*)$/\n\n/** Whether a stored target type is a plugin's namespaced one. */\nexport function isPluginActivityTargetType(type: unknown): type is PluginActivityTargetType {\n return typeof type === 'string' && PLUGIN_TARGET_TYPE.test(type)\n}\n\n/**\n * The noun a plugin's namespaced type names — `acme-mail:mailbox` →\n * `mailbox` — or `undefined` for any other type.\n */\nexport function pluginActivityTargetNoun(type: unknown): string | undefined {\n if (typeof type !== 'string') return undefined\n return PLUGIN_TARGET_TYPE.exec(type)?.[2]\n}\n\nexport interface PluginActivityAction {\n /** The stored action code — dotted, stable, never a sentence. */\n key: string\n /** What a person reads for the code in the feed and the actor table. */\n label: string\n /** Which log(s) the writers put the code in. */\n scope: PluginActivityScope | readonly PluginActivityScope[]\n /** The feed target types rows carrying this code file their output under. */\n resourceTypes?: readonly string[]\n}\n\n/**\n * The filter a plugin's coded rows share: one chip in the org feed and the\n * actor table, one facet group on the staff audit page.\n */\nexport interface PluginActivityGroup {\n /** Stable group id — the facet's value (`ai`). */\n id: string\n /** The chip and the facet option (`AI`). */\n label: string\n /**\n * Staff audit actions that belong to the group without carrying one of the\n * registered codes — rows written by core on the plugin's behalf, matched\n * by prefix (`billing.assistOverage.`).\n */\n staffAuditPrefixes?: readonly string[]\n /**\n * Staff audit actions a plugin's staff doors write when staff READ\n * something rather than change it (AGL-2939): the audit log files them as\n * an access. Matched exactly.\n */\n staffAuditAccessActions?: readonly string[]\n}\n\nexport interface PluginActivityRegistration {\n pluginId: string\n group: PluginActivityGroup\n actions: readonly PluginActivityAction[]\n}\n\nconst registrations = new Map<string, PluginActivityRegistration>()\n\n/**\n * The most codes one group may hold. A group's chip asks `action is any of`\n * its codes, which the feeds' queries serve as one Firestore `in` — capped at\n * thirty values — so a larger group would be a chip the list always refuses.\n */\nexport const PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS = 30\n\n/**\n * Idempotent per plugin — re-registration replaces that plugin's catalog. A\n * code already declared by a DIFFERENT plugin is refused for the whole\n * registration: two owners for one code would give the row two labels. A\n * group of more than `PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS` codes is refused\n * too, since its chip could never be applied.\n */\nexport function registerPluginActivityActions(\n registration: PluginActivityRegistration,\n): void {\n const pluginId = registration.pluginId.trim()\n if (!pluginId) throw new Error('plugin activity actions need a pluginId')\n if (registration.actions.length > PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS) {\n throw new Error(\n `activity group \"${registration.group.id}\" declares ` +\n `${registration.actions.length} actions; its filter chip can ask for at most ` +\n `${PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS}, refused \"${pluginId}\"`,\n )\n }\n for (const action of registration.actions) {\n const owner = ownerOfActivityAction(action.key)\n if (owner && owner !== pluginId) {\n throw new Error(\n `activity action \"${action.key}\" is already declared by \"${owner}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n }\n registrations.set(pluginId, registration)\n}\n\nfunction ownerOfActivityAction(key: string): string | undefined {\n for (const registration of registrations.values()) {\n if (registration.actions.some((action) => action.key === key)) {\n return registration.pluginId\n }\n }\n return undefined\n}\n\n/** Every registration, in registration order. */\nexport function listPluginActivityRegistrations(): PluginActivityRegistration[] {\n return [...registrations.values()]\n}\n\n/** Every declared action across plugins. */\nexport function listPluginActivityActions(): PluginActivityAction[] {\n return listPluginActivityRegistrations().flatMap((entry) => [...entry.actions])\n}\n\n/** The readable label for a declared code; `undefined` for any other action. */\nexport function pluginActivityActionLabel(action: unknown): string | undefined {\n if (typeof action !== 'string') return undefined\n for (const registration of registrations.values()) {\n const match = registration.actions.find((entry) => entry.key === action)\n if (match) return match.label\n }\n return undefined\n}\n\n/** The group a stored action's code belongs to, or `undefined`. */\nexport function pluginActivityGroupForAction(\n action: unknown,\n): PluginActivityGroup | undefined {\n if (typeof action !== 'string') return undefined\n for (const registration of registrations.values()) {\n if (registration.actions.some((entry) => entry.key === action)) {\n return registration.group\n }\n }\n return undefined\n}\n\n/**\n * The filter chips the feeds offer: one per registered group, each with the\n * codes its chip keeps. What an `action isAnyOf …` request sends.\n */\nexport function listPluginActivityFilters(): Array<{\n group: PluginActivityGroup\n actions: string[]\n}> {\n return listPluginActivityRegistrations().map((entry) => ({\n group: entry.group,\n actions: entry.actions.map((action) => action.key),\n }))\n}\n\n/**\n * The staff audit facet group for an action: a registered group when the\n * action is one of its codes or starts with one of its prefixes, else the\n * action's leading namespace (`billing`, `org`, `plugins`).\n */\nexport function pluginStaffAuditActionGroup(action: unknown): string {\n const text = typeof action === 'string' ? action.trim() : ''\n if (!text) return ''\n const byCode = pluginActivityGroupForAction(text)\n if (byCode) return byCode.id\n for (const registration of registrations.values()) {\n const prefixes = registration.group.staffAuditPrefixes ?? []\n if (prefixes.some((prefix) => text.startsWith(prefix))) {\n return registration.group.id\n }\n }\n const dot = text.indexOf('.')\n return dot > 0 ? text.slice(0, dot) : text\n}\n\n/** Whether a staff audit action is a read some plugin declared (AGL-2939). */\nexport function isPluginStaffAuditAccess(action: unknown): boolean {\n if (typeof action !== 'string' || !action) return false\n for (const registration of registrations.values()) {\n if (registration.group.staffAuditAccessActions?.includes(action)) return true\n }\n return false\n}\n\n/** How a facet group reads in the menu: a registered label, else the id. */\nexport function pluginStaffAuditActionGroupLabel(group: string): string {\n for (const registration of registrations.values()) {\n if (registration.group.id === group) return registration.group.label\n }\n return group\n}\n\n/** Test seam: forget every registration. */\nexport function resetPluginActivityActionsForTests(): void {\n registrations.clear()\n}\n"],"names":["PLUGIN_TARGET_TYPE","isPluginActivityTargetType","type","test","pluginActivityTargetNoun","undefined","exec","registrations","Map","PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS","registerPluginActivityActions","registration","pluginId","trim","Error","actions","length","group","id","action","owner","ownerOfActivityAction","key","set","values","some","listPluginActivityRegistrations","listPluginActivityActions","flatMap","entry","pluginActivityActionLabel","match","find","label","pluginActivityGroupForAction","listPluginActivityFilters","map","pluginStaffAuditActionGroup","text","byCode","prefixes","staffAuditPrefixes","prefix","startsWith","dot","indexOf","slice","isPluginStaffAuditAccess","staffAuditAccessActions","includes","pluginStaffAuditActionGroupLabel","resetPluginActivityActionsForTests","clear"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-activity-actions.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 * Plugin-declared activity actions (AGL-2940).\n *\n * Most rows in `orgs/{orgId}/activity` and `hosts/{hostId}/activity` store\n * a prose action written at the call site. A plugin whose rows are read by\n * more than a person — a filter chip, a staff facet, an actor table — stores\n * a CODE (`ai.job.output`) and declares here what the code means: the label\n * a reader sees, the scope it is written at, and the group its filter chip\n * belongs to. The activity renderers read this catalog for labels and\n * filters, so a second plugin with coded rows gets a chip and a facet group\n * by registering, with no edit to the renderers.\n *\n * Declared at module scope from both the client barrel and the `/server`\n * entry (the AGL-428 pattern), with an explicit `pluginId`: module scope\n * runs before the loader's ownership marker is set.\n */\n\nexport type PluginActivityScope = 'org' | 'host' | 'staff'\n\n/**\n * A resource a PLUGIN files an org activity row under (AGL-2978): the\n * plugin's id, a colon and the plugin's own noun — `acme-mail:mailbox`.\n *\n * Core's activity targets are a closed list of core's own resources. A\n * plugin's resource is not one of them and is never added to that list; the\n * org log's target type accepts any namespaced type instead, and the feed\n * reads the noun after the colon for a reader. The namespace keeps two\n * plugins' nouns from meaning one thing.\n */\nexport type PluginActivityTargetType = `${string}:${string}`\n\n/** A namespaced type as the log stores it: `pluginId:noun`, both parts plain. */\nconst PLUGIN_TARGET_TYPE = /^([a-z][a-z0-9-]*):([A-Za-z][A-Za-z0-9]*)$/\n\n/** Whether a stored target type is a plugin's namespaced one. */\nexport function isPluginActivityTargetType(type: unknown): type is PluginActivityTargetType {\n return typeof type === 'string' && PLUGIN_TARGET_TYPE.test(type)\n}\n\n/**\n * The noun a plugin's namespaced type names — `acme-mail:mailbox` →\n * `mailbox` — or `undefined` for any other type.\n */\nexport function pluginActivityTargetNoun(type: unknown): string | undefined {\n if (typeof type !== 'string') return undefined\n return PLUGIN_TARGET_TYPE.exec(type)?.[2]\n}\n\nexport interface PluginActivityAction {\n /** The stored action code — dotted, stable, never a sentence. */\n key: string\n /** What a person reads for the code in the feed and the actor table. */\n label: string\n /** Which log(s) the writers put the code in. */\n scope: PluginActivityScope | readonly PluginActivityScope[]\n /** The feed target types rows carrying this code file their output under. */\n resourceTypes?: readonly string[]\n}\n\n/**\n * The filter a plugin's coded rows share: one chip in the org feed and the\n * actor table, one facet group on the staff audit page.\n */\nexport interface PluginActivityGroup {\n /** Stable group id — the facet's value (`ai`). */\n id: string\n /** The chip and the facet option (`AI`). */\n label: string\n /**\n * Staff audit actions that belong to the group without carrying one of the\n * registered codes — rows written by core on the plugin's behalf, matched\n * by prefix (`billing.assistOverage.`).\n */\n staffAuditPrefixes?: readonly string[]\n /**\n * Staff audit actions a plugin's staff doors write when staff READ\n * something rather than change it (AGL-2939): the audit log files them as\n * an access. Matched exactly.\n */\n staffAuditAccessActions?: readonly string[]\n}\n\nexport interface PluginActivityRegistration {\n pluginId: string\n group: PluginActivityGroup\n actions: readonly PluginActivityAction[]\n /**\n * Target types the plugin's rows are filed under that are NOT namespaced,\n * with the noun a reader sees for each (AGL-3080): rows written before\n * `pluginId:noun` existed, whose stored type cannot change. A namespaced\n * type needs no entry — the feed reads its noun off the type itself.\n */\n targetTypes?: Readonly<Record<string, string>>\n}\n\nconst registrations = new Map<string, PluginActivityRegistration>()\n\n/**\n * The most codes one group may hold. A group's chip asks `action is any of`\n * its codes, which the feeds' queries serve as one Firestore `in` — capped at\n * thirty values — so a larger group would be a chip the list always refuses.\n */\nexport const PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS = 30\n\n/**\n * Idempotent per plugin — re-registration replaces that plugin's catalog. A\n * code already declared by a DIFFERENT plugin is refused for the whole\n * registration: two owners for one code would give the row two labels. A\n * group of more than `PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS` codes is refused\n * too, since its chip could never be applied.\n */\nexport function registerPluginActivityActions(\n registration: PluginActivityRegistration,\n): void {\n const pluginId = registration.pluginId.trim()\n if (!pluginId) throw new Error('plugin activity actions need a pluginId')\n if (registration.actions.length > PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS) {\n throw new Error(\n `activity group \"${registration.group.id}\" declares ` +\n `${registration.actions.length} actions; its filter chip can ask for at most ` +\n `${PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS}, refused \"${pluginId}\"`,\n )\n }\n for (const action of registration.actions) {\n const owner = ownerOfActivityAction(action.key)\n if (owner && owner !== pluginId) {\n throw new Error(\n `activity action \"${action.key}\" is already declared by \"${owner}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n }\n for (const type of Object.keys(registration.targetTypes ?? {})) {\n const owner = [...registrations.values()].find(\n (entry) => entry.pluginId !== pluginId && entry.targetTypes?.[type] !== undefined,\n )?.pluginId\n if (owner) {\n throw new Error(\n `activity target type \"${type}\" is already declared by \"${owner}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n }\n registrations.set(pluginId, registration)\n}\n\n/**\n * The noun a plugin declared for one of its un-namespaced target types, or\n * `undefined` when no plugin declared the type.\n */\nexport function pluginActivityTargetLabel(type: unknown): string | undefined {\n if (typeof type !== 'string') return undefined\n for (const registration of registrations.values()) {\n const label = registration.targetTypes?.[type]\n if (label) return label\n }\n return undefined\n}\n\nfunction ownerOfActivityAction(key: string): string | undefined {\n for (const registration of registrations.values()) {\n if (registration.actions.some((action) => action.key === key)) {\n return registration.pluginId\n }\n }\n return undefined\n}\n\n/** Every registration, in registration order. */\nexport function listPluginActivityRegistrations(): PluginActivityRegistration[] {\n return [...registrations.values()]\n}\n\n/** Every declared action across plugins. */\nexport function listPluginActivityActions(): PluginActivityAction[] {\n return listPluginActivityRegistrations().flatMap((entry) => [...entry.actions])\n}\n\n/** The readable label for a declared code; `undefined` for any other action. */\nexport function pluginActivityActionLabel(action: unknown): string | undefined {\n if (typeof action !== 'string') return undefined\n for (const registration of registrations.values()) {\n const match = registration.actions.find((entry) => entry.key === action)\n if (match) return match.label\n }\n return undefined\n}\n\n/** The group a stored action's code belongs to, or `undefined`. */\nexport function pluginActivityGroupForAction(\n action: unknown,\n): PluginActivityGroup | undefined {\n if (typeof action !== 'string') return undefined\n for (const registration of registrations.values()) {\n if (registration.actions.some((entry) => entry.key === action)) {\n return registration.group\n }\n }\n return undefined\n}\n\n/**\n * The filter chips the feeds offer: one per registered group, each with the\n * codes its chip keeps. What an `action isAnyOf …` request sends.\n */\nexport function listPluginActivityFilters(): Array<{\n group: PluginActivityGroup\n actions: string[]\n}> {\n return listPluginActivityRegistrations().map((entry) => ({\n group: entry.group,\n actions: entry.actions.map((action) => action.key),\n }))\n}\n\n/**\n * The staff audit facet group for an action: a registered group when the\n * action is one of its codes or starts with one of its prefixes, else the\n * action's leading namespace (`billing`, `org`, `plugins`).\n */\nexport function pluginStaffAuditActionGroup(action: unknown): string {\n const text = typeof action === 'string' ? action.trim() : ''\n if (!text) return ''\n const byCode = pluginActivityGroupForAction(text)\n if (byCode) return byCode.id\n for (const registration of registrations.values()) {\n const prefixes = registration.group.staffAuditPrefixes ?? []\n if (prefixes.some((prefix) => text.startsWith(prefix))) {\n return registration.group.id\n }\n }\n const dot = text.indexOf('.')\n return dot > 0 ? text.slice(0, dot) : text\n}\n\n/** Whether a staff audit action is a read some plugin declared (AGL-2939). */\nexport function isPluginStaffAuditAccess(action: unknown): boolean {\n if (typeof action !== 'string' || !action) return false\n for (const registration of registrations.values()) {\n if (registration.group.staffAuditAccessActions?.includes(action)) return true\n }\n return false\n}\n\n/** How a facet group reads in the menu: a registered label, else the id. */\nexport function pluginStaffAuditActionGroupLabel(group: string): string {\n for (const registration of registrations.values()) {\n if (registration.group.id === group) return registration.group.label\n }\n return group\n}\n\n/** Test seam: forget every registration. */\nexport function resetPluginActivityActionsForTests(): void {\n registrations.clear()\n}\n"],"names":["PLUGIN_TARGET_TYPE","isPluginActivityTargetType","type","test","pluginActivityTargetNoun","undefined","exec","registrations","Map","PLUGIN_ACTIVITY_GROUP_MAX_ACTIONS","registerPluginActivityActions","registration","pluginId","trim","Error","actions","length","group","id","action","owner","ownerOfActivityAction","key","Object","keys","targetTypes","values","find","entry","set","pluginActivityTargetLabel","label","some","listPluginActivityRegistrations","listPluginActivityActions","flatMap","pluginActivityActionLabel","match","pluginActivityGroupForAction","listPluginActivityFilters","map","pluginStaffAuditActionGroup","text","byCode","prefixes","staffAuditPrefixes","prefix","startsWith","dot","indexOf","slice","isPluginStaffAuditAccess","staffAuditAccessActions","includes","pluginStaffAuditActionGroupLabel","resetPluginActivityActionsForTests","clear"],"mappings":"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"}
|
|
@@ -116,8 +116,9 @@ export interface PluginContactCaptureRequest {
|
|
|
116
116
|
interaction: PluginContactInteraction;
|
|
117
117
|
/**
|
|
118
118
|
* An explicit marketing opt-in the capture surface carried, recorded against
|
|
119
|
-
* `hostId
|
|
120
|
-
* not consent
|
|
119
|
+
* `hostId`: consent to the MARKETING send purpose (`marketing-consent.ts`),
|
|
120
|
+
* whichever plugin's mail later asks for it. Absent is not consent, and
|
|
121
|
+
* filing a capture under a container is not consent either.
|
|
121
122
|
*/
|
|
122
123
|
marketingConsent?: boolean;
|
|
123
124
|
/**
|
|
@@ -130,8 +131,12 @@ export interface PluginContactCaptureRequest {
|
|
|
130
131
|
disclosedConsentGroup?: string;
|
|
131
132
|
/** Tags the silo puts on this capture; the owner adds, never replaces. */
|
|
132
133
|
tags?: readonly string[];
|
|
133
|
-
/**
|
|
134
|
-
|
|
134
|
+
/**
|
|
135
|
+
* What the capture SURFACE is filed under — the merchant's own act — by
|
|
136
|
+
* container kind (`plugin-containers.ts`): `{ [kind]: ids }`. The owner
|
|
137
|
+
* files the person under the kinds it keeps. Filing is not consent.
|
|
138
|
+
*/
|
|
139
|
+
containers?: Readonly<Record<string, readonly string[]>>;
|
|
135
140
|
/** Money the capture was worth, in cents, where the silo took some. */
|
|
136
141
|
purchaseCents?: number;
|
|
137
142
|
/** The currency {@link purchaseCents} is in, lowercase, when the silo knows. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-contact-capture.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\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * A person met on a site, handed to whichever plugin keeps people (AGL-3124).\n *\n * Four silos capture the same thing and none of them is the record system: a\n * form submission, a site member signing up, an order, a booking. Each holds\n * an address, a name and the fact that something happened, and each wants the\n * workspace's person record to know. Today each one imports the writer, which\n * makes the highest-fan-in edge in the repo — thirty files in one plugin alone\n * — and makes the record system's plugin something a storefront cannot take a\n * payment without.\n *\n * So the silo stops importing and starts DECLARING: it registers the capture\n * door it owns, and hands a capture to this seam. The plugin that keeps people\n * registers the writer and does every part of the work that is a record\n * system's to do:\n *\n * - normalizing and keying the address, and deciding whether this is a new\n * person or a visit from one the workspace already holds;\n * - the audience band, the erasure rows, and every other refusal — answered,\n * never thrown, so a capture that is refused never costs the silo the order\n * or the submission it was recording;\n * - what a stage, an owner, a company and a tag mean, and what the arrival\n * of a new person sets off.\n *\n * The silo decides none of that. It reports what it saw.\n *\n * ## Why the profile is opaque\n *\n * `profile` is the owner's own field names with scalar values, not a core\n * type. A person's record shape belongs to the plugin that models it, and a\n * typed core shape would be that model spelled in the platform again — which\n * is the defect this seam exists to retire, not a smaller version of it. A key\n * the owner does not document is the owner's to ignore.\n *\n * `source` is the silo's own word for its door, and it is declared rather than\n * enumerated here for the same reason: core listing `form`, `member`, `order`\n * and `booking` would be core holding the plugin set again. A silo registers\n * its source with {@link registerPluginContactSource}, which is what lets a\n * timeline label an entry and a link point back at the thing that captured the\n * person, without the platform knowing what any of them are.\n *\n * ## One writer; many silos\n *\n * A workspace keeps one set of people, so the writer is a slot: a second\n * plugin's writer is refused naming both, and the incumbent keeps serving. A\n * SOURCE is per silo and there are many, but one source word has one owner —\n * two plugins claiming `order` would make the label and the link ambiguous at\n * the point they are read.\n *\n * ## The caller proves who is asking\n *\n * Like `plugin-record-timeline`, the registry authenticates nobody. A silo has\n * already decided, in its own terms and before it asks, that the capture is\n * the workspace's to record — that the submission was accepted, that the order\n * was paid.\n *\n * Server-side: reached by its own subpath, never through\n * `plugin-manager/index.ts`.\n */\n\n/** The person, as the capturing silo saw them. */\nexport interface PluginContactIdentity {\n /**\n * The address they gave. Raw: the owner normalizes and keys on it, and a\n * silo that normalized first would be keeping a second copy of that rule.\n */\n email: unknown\n name?: string | null\n}\n\n/** What happened, in the capturing silo's own words. */\nexport interface PluginContactInteraction {\n /** The silo's declared source word — see {@link registerPluginContactSource}. */\n source: string\n /** When it happened, epoch ms; the owner uses now when absent. */\n atMs?: number\n /**\n * The document it happened on, in the silo's terms\n * (`formSubmissions/{id}`, `orders/{id}`), so a timeline entry can point\n * back at it. Absent where the door leaves nothing to open.\n */\n refId?: string | null\n /** One line a person reads on the timeline. */\n summary?: string | null\n}\n\nexport interface PluginContactCaptureRequest {\n /**\n * Who caused the capture, when it was not the person captured (AGL-3376) —\n * a member adding someone by hand, an integration's key. A door where the\n * visitor acts for themselves (a form, a purchase) may leave it out.\n */\n actor?: {\n kind: 'member' | 'visitor' | 'apiKey' | 'platform'\n uid?: string | null\n email?: string | null\n apiKeyName?: string | null\n }\n orgId: string\n /** The site the person was met on: the brand whose form or checkout it was. */\n hostId: string\n identity: PluginContactIdentity\n interaction: PluginContactInteraction\n /**\n * An explicit marketing opt-in the capture surface carried, recorded against\n * `hostId`. Absent is not consent, and filing a capture under a campaign is\n * not consent either.\n */\n marketingConsent?: boolean\n /**\n * The disclosure key the capture surface rendered beside that opt-in\n * (`consentGroupDisclosureKey`, AGL-3320), passed through as the surface\n * sent it. The owner records the opt-in for the site's whole consent group\n * only when this is the group's current key, and for `hostId` alone\n * otherwise — so a silo whose surface shows no disclosure sends none.\n */\n disclosedConsentGroup?: string\n /** Tags the silo puts on this capture; the owner adds, never replaces. */\n tags?: readonly string[]\n /** The campaigns the capture SURFACE is filed under — the merchant's own act. */\n campaignIds?: readonly string[]\n /** Money the capture was worth, in cents, where the silo took some. */\n purchaseCents?: number\n /** The currency {@link purchaseCents} is in, lowercase, when the silo knows. */\n purchaseCurrency?: string\n /**\n * The earliest stage this capture describes, in the OWNER's words. A floor\n * and not a value: the owner fills an empty stage and advances an earlier\n * one, and never moves anybody back, so a repeat customer filling in a\n * contact form is still a customer.\n */\n lifecycleFloor?: string\n /**\n * What kind of door this is, which decides WHICH RECORD the person lands\n * on (AGL-3232) — the owner's rule is Salesforce's: one person is one\n * record, a lead until they are qualified and a contact after.\n *\n * - `lead`: a lead surface — a form whose author routes it to leads, a\n * booking request. The person is filed as a LEAD and nothing else,\n * unless the workspace already holds them as a contact, in which case\n * the capture lands on the contact and no lead is filed.\n * - `relationship`: an act that makes the person a known relationship —\n * a member account, a purchase. The person is filed as a CONTACT, and\n * an open lead the site held for them is stamped converted onto it.\n * - `touch`, the default: everything else — a form without lead routing,\n * a newsletter opt-in. The capture lands on the open lead when the site\n * holds one for the address, and on the contact otherwise.\n */\n surface?: 'lead' | 'relationship' | 'touch'\n /**\n * Profile fields the silo knows, keyed by the owner's own field names.\n * Only the keys given are written, so a silo that knows the phone number\n * does not blank a title somebody typed.\n */\n profile?: Readonly<Record<string, unknown>>\n /**\n * Facts about THIS CAPTURE that the owner models and the platform does not\n * (AGL-3080) — which form was filled in, which page it was on, where the\n * visitor arrived from.\n *\n * Opaque for the reason {@link profile} is: every one of these is a concept\n * belonging to the plugin that keeps people or to the silo that saw it, and\n * a typed core field for each would be those models spelled out in the\n * platform again. `profile` describes the PERSON and outlives the visit;\n * this describes the visit and does not.\n *\n * A key the owner does not recognize is the owner's to ignore, and a silo\n * that sends nothing here loses nothing: every field is an enrichment of a\n * capture that is already complete without it.\n */\n detail?: Readonly<Record<string, unknown>>\n}\n\n/**\n * The owner's answer. `created: false` is a visit by somebody the workspace\n * already held, which is an interaction and not a new person.\n *\n * A refusal is RETURNED. Every one of these silos has already done the thing\n * it was recording, so a throw here would cost an accepted submission or a\n * paid order for a record it could not keep.\n */\nexport type PluginContactCaptured =\n /** The capture landed on a contact — the record every capture used to make. */\n | { ok: true; record: 'contact'; contactId: string; created: boolean }\n /**\n * The capture landed on a LEAD (AGL-3232): a lead surface met somebody the\n * workspace does not hold as a contact, or a touch reached an open lead.\n * `leadId` is the person key the lead is filed under on `hostId`.\n */\n | {\n ok: true\n record: 'lead'\n leadId: string\n created: boolean\n /**\n * Whether this capture's surface was new on the lead — a new person,\n * or one first met through another door. A form counts its leads by\n * it (AGL-3330): the people it filed, not the times they came back.\n * Absent from a writer that does not say, which a caller reads as\n * `created`.\n */\n sourceAdded?: boolean\n }\n | {\n ok: false\n /**\n * `invalid-email`: nothing usable to key a person on. `band`: the\n * workspace is at the audience it may hold. `erased`: the workspace\n * erased this person and a capture must not quietly rebuild them.\n * `error`: the owner failed, and said so rather than silently.\n */\n reason: 'invalid-email' | 'band' | 'erased' | 'error'\n /** Customer-safe: a caller may show or log it as it stands. */\n error: string\n }\n\nexport interface PluginContactCaptureWriter {\n /** Records one capture; a refusal is returned, never thrown. */\n capture(\n request: PluginContactCaptureRequest,\n ): Promise<PluginContactCaptured>\n}\n\n/** A capture door a silo owns. */\nexport interface PluginContactSourceDeclaration {\n /** The silo's word for the door, as its captures carry it. */\n source: string\n /** What a timeline entry from this door says: `Form submission`. */\n label: string\n /**\n * What a link from that entry says when there is something to open —\n * `Open submission`. Absent where the door leaves nothing to open, which\n * is the honest answer for an import or a by-hand add.\n */\n openLabel?: string\n /**\n * The record kind the silo's own document is, for\n * `plugin-record-routes` to address it with. Absent where the door has no\n * record of its own to open.\n */\n recordKind?: string\n}\n\n/** A source declaration with the silo that made it. */\nexport type ResolvedPluginContactSource = PluginContactSourceDeclaration & {\n pluginId: string\n}\n\nexport const PLUGIN_CONTACT_CAPTURE =\n definePluginServiceContract<PluginContactCaptureWriter>(\n 'core.contact-capture',\n { multiple: false },\n )\n\nexport const PLUGIN_CONTACT_SOURCES =\n definePluginServiceContract<PluginContactSourceDeclaration>(\n 'core.contact-capture-sources',\n { multiple: true },\n )\n\n/**\n * Registers the plugin that keeps people. The owner is the loader's marker\n * when a register fn is running, else `options.pluginId`; with neither the\n * registration throws, and a second plugin's writer is refused naming both —\n * the incumbent keeps serving.\n */\nexport function registerPluginContactCaptureWriter(\n writer: PluginContactCaptureWriter,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_CONTACT_CAPTURE, writer, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/** Declares a capture door. One source word has one owner. */\nexport function registerPluginContactSource(\n declaration: PluginContactSourceDeclaration,\n options?: { pluginId?: string },\n): void {\n const key = declaration.source?.trim() ?? ''\n if (!key) throw new Error('a contact capture source needs a source word')\n if (!declaration.label?.trim()) {\n throw new Error(`contact capture source \"${key}\" needs a label`)\n }\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n const incumbent = resolvePluginServices(PLUGIN_CONTACT_SOURCES).find(\n (entry) => entry.key === key,\n )\n if (incumbent && pluginId && incumbent.pluginId !== pluginId) {\n throw new Error(\n `contact capture source \"${key}\" is already declared by ` +\n `\"${incumbent.pluginId}\"; refused \"${pluginId}\"`,\n )\n }\n registerPluginService(\n PLUGIN_CONTACT_SOURCES,\n { ...declaration, source: key },\n {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n key,\n },\n )\n}\n\nexport interface ResolvedPluginContactCaptureWriter {\n /** The plugin that keeps people. */\n pluginId: string\n writer: PluginContactCaptureWriter\n}\n\n/** The writer with its owner, or `null` when no plugin keeps people here. */\nexport function pluginContactCaptureWriter(): ResolvedPluginContactCaptureWriter | null {\n const entry = resolvePluginServices(PLUGIN_CONTACT_CAPTURE)[0]\n return entry ? { pluginId: entry.pluginId, writer: entry.impl } : null\n}\n\n/**\n * Hands one capture to the plugin that keeps people, or answers `null` when\n * no plugin does.\n *\n * `null` and a refusal are different answers and a silo treats them\n * differently: `null` is a workspace with no record system, where there is\n * nothing to record and nothing has gone wrong; a refusal is a record system\n * that considered this person and declined.\n */\nexport async function capturePluginContact(\n request: PluginContactCaptureRequest,\n): Promise<PluginContactCaptured | null> {\n const found = pluginContactCaptureWriter()\n if (!found) return null\n return found.writer.capture(request)\n}\n\n/** Every declared capture door, with its silo, in registration order. */\nexport function listPluginContactSources(): ResolvedPluginContactSource[] {\n return resolvePluginServices(PLUGIN_CONTACT_SOURCES).map((entry) => ({\n ...entry.impl,\n pluginId: entry.pluginId,\n }))\n}\n\n/** One declared capture door by its source word, or `null`. */\nexport function pluginContactSource(\n source: string,\n): ResolvedPluginContactSource | null {\n const key = source.trim()\n const entry = resolvePluginServices(PLUGIN_CONTACT_SOURCES).find(\n (one) => one.key === key,\n )\n return entry ? { ...entry.impl, pluginId: entry.pluginId } : null\n}\n"],"names":["getRegisteringPluginId","definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_CONTACT_CAPTURE","multiple","PLUGIN_CONTACT_SOURCES","registerPluginContactCaptureWriter","writer","options","pluginId","registerPluginContactSource","declaration","key","source","trim","Error","label","incumbent","find","entry","pluginContactCaptureWriter","impl","capturePluginContact","request","found","capture","listPluginContactSources","map","pluginContactSource","one"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,sBAAsB,QAAQ,qCAAiC;AACxE,SACEC,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AA0P1B,OAAO,MAAMC,yBACXH,4BACE,wBACA;IAAEI,UAAU;AAAM,GACnB;AAEH,OAAO,MAAMC,yBACXL,4BACE,gCACA;IAAEI,UAAU;AAAK,GAClB;AAEH;;;;;CAKC,GACD,OAAO,SAASE,mCACdC,MAAkC,EAClCC,OAA+B;IAE/BP,sBAAsBE,wBAAwBI,QAAQ,aAChDC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA,4DAA4D,GAC5D,OAAO,SAASC,4BACdC,WAA2C,EAC3CH,OAA+B;cAObT,OAAAA;QALNY,qBAEPA;IAFL,MAAMC,eAAMD,sBAAAA,YAAYE,MAAM,qBAAlBF,oBAAoBG,IAAI,qBAAM;IAC1C,IAAI,CAACF,KAAK,MAAM,IAAIG,MAAM;IAC1B,IAAI,GAACJ,qBAAAA,YAAYK,KAAK,qBAAjBL,mBAAmBG,IAAI,KAAI;QAC9B,MAAM,IAAIC,MAAM,CAAC,wBAAwB,EAAEH,IAAI,eAAe,CAAC;IACjE;IACA,MAAMH,WAAW,EAACV,SAAAA,0BAAAA,oCAAAA,0BAA4BS,2BAAAA,QAASC,QAAQ,YAA7CV,QAAiD,IAAIe,IAAI;IAC3E,MAAMG,YAAYf,sBAAsBG,wBAAwBa,IAAI,CAClE,CAACC,QAAUA,MAAMP,GAAG,KAAKA;IAE3B,IAAIK,aAAaR,YAAYQ,UAAUR,QAAQ,KAAKA,UAAU;QAC5D,MAAM,IAAIM,MACR,CAAC,wBAAwB,EAAEH,IAAI,yBAAyB,CAAC,GACvD,CAAC,CAAC,EAAEK,UAAUR,QAAQ,CAAC,YAAY,EAAEA,SAAS,CAAC,CAAC;IAEtD;IACAR,sBACEI,wBACA,aAAKM;QAAaE,QAAQD;QAC1B,aACMJ,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;QAC1DG;;AAGN;AAQA,2EAA2E,GAC3E,OAAO,SAASQ;IACd,MAAMD,QAAQjB,sBAAsBC,uBAAuB,CAAC,EAAE;IAC9D,OAAOgB,QAAQ;QAAEV,UAAUU,MAAMV,QAAQ;QAAEF,QAAQY,MAAME,IAAI;IAAC,IAAI;AACpE;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeC,qBACpBC,OAAoC;IAEpC,MAAMC,QAAQJ;IACd,IAAI,CAACI,OAAO,OAAO;IACnB,OAAOA,MAAMjB,MAAM,CAACkB,OAAO,CAACF;AAC9B;AAEA,uEAAuE,GACvE,OAAO,SAASG;IACd,OAAOxB,sBAAsBG,wBAAwBsB,GAAG,CAAC,CAACR,QAAW,aAChEA,MAAME,IAAI;YACbZ,UAAUU,MAAMV,QAAQ;;AAE5B;AAEA,6DAA6D,GAC7D,OAAO,SAASmB,oBACdf,MAAc;IAEd,MAAMD,MAAMC,OAAOC,IAAI;IACvB,MAAMK,QAAQjB,sBAAsBG,wBAAwBa,IAAI,CAC9D,CAACW,MAAQA,IAAIjB,GAAG,KAAKA;IAEvB,OAAOO,QAAQ,aAAKA,MAAME,IAAI;QAAEZ,UAAUU,MAAMV,QAAQ;SAAK;AAC/D"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/plugin-contact-capture.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\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * A person met on a site, handed to whichever plugin keeps people (AGL-3124).\n *\n * Four silos capture the same thing and none of them is the record system: a\n * form submission, a site member signing up, an order, a booking. Each holds\n * an address, a name and the fact that something happened, and each wants the\n * workspace's person record to know. Today each one imports the writer, which\n * makes the highest-fan-in edge in the repo — thirty files in one plugin alone\n * — and makes the record system's plugin something a storefront cannot take a\n * payment without.\n *\n * So the silo stops importing and starts DECLARING: it registers the capture\n * door it owns, and hands a capture to this seam. The plugin that keeps people\n * registers the writer and does every part of the work that is a record\n * system's to do:\n *\n * - normalizing and keying the address, and deciding whether this is a new\n * person or a visit from one the workspace already holds;\n * - the audience band, the erasure rows, and every other refusal — answered,\n * never thrown, so a capture that is refused never costs the silo the order\n * or the submission it was recording;\n * - what a stage, an owner, a company and a tag mean, and what the arrival\n * of a new person sets off.\n *\n * The silo decides none of that. It reports what it saw.\n *\n * ## Why the profile is opaque\n *\n * `profile` is the owner's own field names with scalar values, not a core\n * type. A person's record shape belongs to the plugin that models it, and a\n * typed core shape would be that model spelled in the platform again — which\n * is the defect this seam exists to retire, not a smaller version of it. A key\n * the owner does not document is the owner's to ignore.\n *\n * `source` is the silo's own word for its door, and it is declared rather than\n * enumerated here for the same reason: core listing `form`, `member`, `order`\n * and `booking` would be core holding the plugin set again. A silo registers\n * its source with {@link registerPluginContactSource}, which is what lets a\n * timeline label an entry and a link point back at the thing that captured the\n * person, without the platform knowing what any of them are.\n *\n * ## One writer; many silos\n *\n * A workspace keeps one set of people, so the writer is a slot: a second\n * plugin's writer is refused naming both, and the incumbent keeps serving. A\n * SOURCE is per silo and there are many, but one source word has one owner —\n * two plugins claiming `order` would make the label and the link ambiguous at\n * the point they are read.\n *\n * ## The caller proves who is asking\n *\n * Like `plugin-record-timeline`, the registry authenticates nobody. A silo has\n * already decided, in its own terms and before it asks, that the capture is\n * the workspace's to record — that the submission was accepted, that the order\n * was paid.\n *\n * Server-side: reached by its own subpath, never through\n * `plugin-manager/index.ts`.\n */\n\n/** The person, as the capturing silo saw them. */\nexport interface PluginContactIdentity {\n /**\n * The address they gave. Raw: the owner normalizes and keys on it, and a\n * silo that normalized first would be keeping a second copy of that rule.\n */\n email: unknown\n name?: string | null\n}\n\n/** What happened, in the capturing silo's own words. */\nexport interface PluginContactInteraction {\n /** The silo's declared source word — see {@link registerPluginContactSource}. */\n source: string\n /** When it happened, epoch ms; the owner uses now when absent. */\n atMs?: number\n /**\n * The document it happened on, in the silo's terms\n * (`formSubmissions/{id}`, `orders/{id}`), so a timeline entry can point\n * back at it. Absent where the door leaves nothing to open.\n */\n refId?: string | null\n /** One line a person reads on the timeline. */\n summary?: string | null\n}\n\nexport interface PluginContactCaptureRequest {\n /**\n * Who caused the capture, when it was not the person captured (AGL-3376) —\n * a member adding someone by hand, an integration's key. A door where the\n * visitor acts for themselves (a form, a purchase) may leave it out.\n */\n actor?: {\n kind: 'member' | 'visitor' | 'apiKey' | 'platform'\n uid?: string | null\n email?: string | null\n apiKeyName?: string | null\n }\n orgId: string\n /** The site the person was met on: the brand whose form or checkout it was. */\n hostId: string\n identity: PluginContactIdentity\n interaction: PluginContactInteraction\n /**\n * An explicit marketing opt-in the capture surface carried, recorded against\n * `hostId`: consent to the MARKETING send purpose (`marketing-consent.ts`),\n * whichever plugin's mail later asks for it. Absent is not consent, and\n * filing a capture under a container is not consent either.\n */\n marketingConsent?: boolean\n /**\n * The disclosure key the capture surface rendered beside that opt-in\n * (`consentGroupDisclosureKey`, AGL-3320), passed through as the surface\n * sent it. The owner records the opt-in for the site's whole consent group\n * only when this is the group's current key, and for `hostId` alone\n * otherwise — so a silo whose surface shows no disclosure sends none.\n */\n disclosedConsentGroup?: string\n /** Tags the silo puts on this capture; the owner adds, never replaces. */\n tags?: readonly string[]\n /**\n * What the capture SURFACE is filed under — the merchant's own act — by\n * container kind (`plugin-containers.ts`): `{ [kind]: ids }`. The owner\n * files the person under the kinds it keeps. Filing is not consent.\n */\n containers?: Readonly<Record<string, readonly string[]>>\n /** Money the capture was worth, in cents, where the silo took some. */\n purchaseCents?: number\n /** The currency {@link purchaseCents} is in, lowercase, when the silo knows. */\n purchaseCurrency?: string\n /**\n * The earliest stage this capture describes, in the OWNER's words. A floor\n * and not a value: the owner fills an empty stage and advances an earlier\n * one, and never moves anybody back, so a repeat customer filling in a\n * contact form is still a customer.\n */\n lifecycleFloor?: string\n /**\n * What kind of door this is, which decides WHICH RECORD the person lands\n * on (AGL-3232) — the owner's rule is Salesforce's: one person is one\n * record, a lead until they are qualified and a contact after.\n *\n * - `lead`: a lead surface — a form whose author routes it to leads, a\n * booking request. The person is filed as a LEAD and nothing else,\n * unless the workspace already holds them as a contact, in which case\n * the capture lands on the contact and no lead is filed.\n * - `relationship`: an act that makes the person a known relationship —\n * a member account, a purchase. The person is filed as a CONTACT, and\n * an open lead the site held for them is stamped converted onto it.\n * - `touch`, the default: everything else — a form without lead routing,\n * a newsletter opt-in. The capture lands on the open lead when the site\n * holds one for the address, and on the contact otherwise.\n */\n surface?: 'lead' | 'relationship' | 'touch'\n /**\n * Profile fields the silo knows, keyed by the owner's own field names.\n * Only the keys given are written, so a silo that knows the phone number\n * does not blank a title somebody typed.\n */\n profile?: Readonly<Record<string, unknown>>\n /**\n * Facts about THIS CAPTURE that the owner models and the platform does not\n * (AGL-3080) — which form was filled in, which page it was on, where the\n * visitor arrived from.\n *\n * Opaque for the reason {@link profile} is: every one of these is a concept\n * belonging to the plugin that keeps people or to the silo that saw it, and\n * a typed core field for each would be those models spelled out in the\n * platform again. `profile` describes the PERSON and outlives the visit;\n * this describes the visit and does not.\n *\n * A key the owner does not recognize is the owner's to ignore, and a silo\n * that sends nothing here loses nothing: every field is an enrichment of a\n * capture that is already complete without it.\n */\n detail?: Readonly<Record<string, unknown>>\n}\n\n/**\n * The owner's answer. `created: false` is a visit by somebody the workspace\n * already held, which is an interaction and not a new person.\n *\n * A refusal is RETURNED. Every one of these silos has already done the thing\n * it was recording, so a throw here would cost an accepted submission or a\n * paid order for a record it could not keep.\n */\nexport type PluginContactCaptured =\n /** The capture landed on a contact — the record every capture used to make. */\n | { ok: true; record: 'contact'; contactId: string; created: boolean }\n /**\n * The capture landed on a LEAD (AGL-3232): a lead surface met somebody the\n * workspace does not hold as a contact, or a touch reached an open lead.\n * `leadId` is the person key the lead is filed under on `hostId`.\n */\n | {\n ok: true\n record: 'lead'\n leadId: string\n created: boolean\n /**\n * Whether this capture's surface was new on the lead — a new person,\n * or one first met through another door. A form counts its leads by\n * it (AGL-3330): the people it filed, not the times they came back.\n * Absent from a writer that does not say, which a caller reads as\n * `created`.\n */\n sourceAdded?: boolean\n }\n | {\n ok: false\n /**\n * `invalid-email`: nothing usable to key a person on. `band`: the\n * workspace is at the audience it may hold. `erased`: the workspace\n * erased this person and a capture must not quietly rebuild them.\n * `error`: the owner failed, and said so rather than silently.\n */\n reason: 'invalid-email' | 'band' | 'erased' | 'error'\n /** Customer-safe: a caller may show or log it as it stands. */\n error: string\n }\n\nexport interface PluginContactCaptureWriter {\n /** Records one capture; a refusal is returned, never thrown. */\n capture(\n request: PluginContactCaptureRequest,\n ): Promise<PluginContactCaptured>\n}\n\n/** A capture door a silo owns. */\nexport interface PluginContactSourceDeclaration {\n /** The silo's word for the door, as its captures carry it. */\n source: string\n /** What a timeline entry from this door says: `Form submission`. */\n label: string\n /**\n * What a link from that entry says when there is something to open —\n * `Open submission`. Absent where the door leaves nothing to open, which\n * is the honest answer for an import or a by-hand add.\n */\n openLabel?: string\n /**\n * The record kind the silo's own document is, for\n * `plugin-record-routes` to address it with. Absent where the door has no\n * record of its own to open.\n */\n recordKind?: string\n}\n\n/** A source declaration with the silo that made it. */\nexport type ResolvedPluginContactSource = PluginContactSourceDeclaration & {\n pluginId: string\n}\n\nexport const PLUGIN_CONTACT_CAPTURE =\n definePluginServiceContract<PluginContactCaptureWriter>(\n 'core.contact-capture',\n { multiple: false },\n )\n\nexport const PLUGIN_CONTACT_SOURCES =\n definePluginServiceContract<PluginContactSourceDeclaration>(\n 'core.contact-capture-sources',\n { multiple: true },\n )\n\n/**\n * Registers the plugin that keeps people. The owner is the loader's marker\n * when a register fn is running, else `options.pluginId`; with neither the\n * registration throws, and a second plugin's writer is refused naming both —\n * the incumbent keeps serving.\n */\nexport function registerPluginContactCaptureWriter(\n writer: PluginContactCaptureWriter,\n options?: { pluginId?: string },\n): void {\n registerPluginService(PLUGIN_CONTACT_CAPTURE, writer, {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n })\n}\n\n/** Declares a capture door. One source word has one owner. */\nexport function registerPluginContactSource(\n declaration: PluginContactSourceDeclaration,\n options?: { pluginId?: string },\n): void {\n const key = declaration.source?.trim() ?? ''\n if (!key) throw new Error('a contact capture source needs a source word')\n if (!declaration.label?.trim()) {\n throw new Error(`contact capture source \"${key}\" needs a label`)\n }\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n const incumbent = resolvePluginServices(PLUGIN_CONTACT_SOURCES).find(\n (entry) => entry.key === key,\n )\n if (incumbent && pluginId && incumbent.pluginId !== pluginId) {\n throw new Error(\n `contact capture source \"${key}\" is already declared by ` +\n `\"${incumbent.pluginId}\"; refused \"${pluginId}\"`,\n )\n }\n registerPluginService(\n PLUGIN_CONTACT_SOURCES,\n { ...declaration, source: key },\n {\n ...(options?.pluginId ? { pluginId: options.pluginId } : {}),\n key,\n },\n )\n}\n\nexport interface ResolvedPluginContactCaptureWriter {\n /** The plugin that keeps people. */\n pluginId: string\n writer: PluginContactCaptureWriter\n}\n\n/** The writer with its owner, or `null` when no plugin keeps people here. */\nexport function pluginContactCaptureWriter(): ResolvedPluginContactCaptureWriter | null {\n const entry = resolvePluginServices(PLUGIN_CONTACT_CAPTURE)[0]\n return entry ? { pluginId: entry.pluginId, writer: entry.impl } : null\n}\n\n/**\n * Hands one capture to the plugin that keeps people, or answers `null` when\n * no plugin does.\n *\n * `null` and a refusal are different answers and a silo treats them\n * differently: `null` is a workspace with no record system, where there is\n * nothing to record and nothing has gone wrong; a refusal is a record system\n * that considered this person and declined.\n */\nexport async function capturePluginContact(\n request: PluginContactCaptureRequest,\n): Promise<PluginContactCaptured | null> {\n const found = pluginContactCaptureWriter()\n if (!found) return null\n return found.writer.capture(request)\n}\n\n/** Every declared capture door, with its silo, in registration order. */\nexport function listPluginContactSources(): ResolvedPluginContactSource[] {\n return resolvePluginServices(PLUGIN_CONTACT_SOURCES).map((entry) => ({\n ...entry.impl,\n pluginId: entry.pluginId,\n }))\n}\n\n/** One declared capture door by its source word, or `null`. */\nexport function pluginContactSource(\n source: string,\n): ResolvedPluginContactSource | null {\n const key = source.trim()\n const entry = resolvePluginServices(PLUGIN_CONTACT_SOURCES).find(\n (one) => one.key === key,\n )\n return entry ? { ...entry.impl, pluginId: entry.pluginId } : null\n}\n"],"names":["getRegisteringPluginId","definePluginServiceContract","registerPluginService","resolvePluginServices","PLUGIN_CONTACT_CAPTURE","multiple","PLUGIN_CONTACT_SOURCES","registerPluginContactCaptureWriter","writer","options","pluginId","registerPluginContactSource","declaration","key","source","trim","Error","label","incumbent","find","entry","pluginContactCaptureWriter","impl","capturePluginContact","request","found","capture","listPluginContactSources","map","pluginContactSource","one"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,SAASA,sBAAsB,QAAQ,qCAAiC;AACxE,SACEC,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AA+P1B,OAAO,MAAMC,yBACXH,4BACE,wBACA;IAAEI,UAAU;AAAM,GACnB;AAEH,OAAO,MAAMC,yBACXL,4BACE,gCACA;IAAEI,UAAU;AAAK,GAClB;AAEH;;;;;CAKC,GACD,OAAO,SAASE,mCACdC,MAAkC,EAClCC,OAA+B;IAE/BP,sBAAsBE,wBAAwBI,QAAQ,aAChDC,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;AAE9D;AAEA,4DAA4D,GAC5D,OAAO,SAASC,4BACdC,WAA2C,EAC3CH,OAA+B;cAObT,OAAAA;QALNY,qBAEPA;IAFL,MAAMC,eAAMD,sBAAAA,YAAYE,MAAM,qBAAlBF,oBAAoBG,IAAI,qBAAM;IAC1C,IAAI,CAACF,KAAK,MAAM,IAAIG,MAAM;IAC1B,IAAI,GAACJ,qBAAAA,YAAYK,KAAK,qBAAjBL,mBAAmBG,IAAI,KAAI;QAC9B,MAAM,IAAIC,MAAM,CAAC,wBAAwB,EAAEH,IAAI,eAAe,CAAC;IACjE;IACA,MAAMH,WAAW,EAACV,SAAAA,0BAAAA,oCAAAA,0BAA4BS,2BAAAA,QAASC,QAAQ,YAA7CV,QAAiD,IAAIe,IAAI;IAC3E,MAAMG,YAAYf,sBAAsBG,wBAAwBa,IAAI,CAClE,CAACC,QAAUA,MAAMP,GAAG,KAAKA;IAE3B,IAAIK,aAAaR,YAAYQ,UAAUR,QAAQ,KAAKA,UAAU;QAC5D,MAAM,IAAIM,MACR,CAAC,wBAAwB,EAAEH,IAAI,yBAAyB,CAAC,GACvD,CAAC,CAAC,EAAEK,UAAUR,QAAQ,CAAC,YAAY,EAAEA,SAAS,CAAC,CAAC;IAEtD;IACAR,sBACEI,wBACA,aAAKM;QAAaE,QAAQD;QAC1B,aACMJ,CAAAA,2BAAAA,QAASC,QAAQ,IAAG;QAAEA,UAAUD,QAAQC,QAAQ;IAAC,IAAI,CAAC;QAC1DG;;AAGN;AAQA,2EAA2E,GAC3E,OAAO,SAASQ;IACd,MAAMD,QAAQjB,sBAAsBC,uBAAuB,CAAC,EAAE;IAC9D,OAAOgB,QAAQ;QAAEV,UAAUU,MAAMV,QAAQ;QAAEF,QAAQY,MAAME,IAAI;IAAC,IAAI;AACpE;AAEA;;;;;;;;CAQC,GACD,OAAO,eAAeC,qBACpBC,OAAoC;IAEpC,MAAMC,QAAQJ;IACd,IAAI,CAACI,OAAO,OAAO;IACnB,OAAOA,MAAMjB,MAAM,CAACkB,OAAO,CAACF;AAC9B;AAEA,uEAAuE,GACvE,OAAO,SAASG;IACd,OAAOxB,sBAAsBG,wBAAwBsB,GAAG,CAAC,CAACR,QAAW,aAChEA,MAAME,IAAI;YACbZ,UAAUU,MAAMV,QAAQ;;AAE5B;AAEA,6DAA6D,GAC7D,OAAO,SAASmB,oBACdf,MAAc;IAEd,MAAMD,MAAMC,OAAOC,IAAI;IACvB,MAAMK,QAAQjB,sBAAsBG,wBAAwBa,IAAI,CAC9D,CAACW,MAAQA,IAAIjB,GAAG,KAAKA;IAEvB,OAAOO,QAAQ,aAAKA,MAAME,IAAI;QAAEZ,UAAUU,MAAMV,QAAQ;SAAK;AAC/D"}
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
* CONTAINER KINDS: the documents other records are FILED UNDER, declared by
|
|
19
|
+
* the plugin that keeps them.
|
|
20
|
+
*
|
|
21
|
+
* A container is a document other records join by naming its id in a
|
|
22
|
+
* membership array on their OWN documents — a form, a screen, a lead or a
|
|
23
|
+
* contact filed under a campaign. `app-utils/container-membership.ts` says
|
|
24
|
+
* why the edge lives on the member, and holds the helpers every member's
|
|
25
|
+
* writer and reader share.
|
|
26
|
+
*
|
|
27
|
+
* The plugin that keeps a kind declares it in the `containers` block of
|
|
28
|
+
* `plugins.config.json`, compiled into `plugin-containers.generated.ts`, so
|
|
29
|
+
* no surface that files a record has to know which plugin that is or where
|
|
30
|
+
* the containers are stored:
|
|
31
|
+
*
|
|
32
|
+
* - `kind` names the membership field: a member holds its containers in
|
|
33
|
+
* `<kind>Ids` (`containerMembershipField`). The name is the contract,
|
|
34
|
+
* which is what lets a record page in one plugin file itself under a kind
|
|
35
|
+
* another plugin keeps without importing it.
|
|
36
|
+
* - `orgCollection` is where the containers are stored, under the
|
|
37
|
+
* organization (`orgs/{orgId}/{orgCollection}`), one of the owner's own
|
|
38
|
+
* declared org collections. A container is placed on sites by the core's
|
|
39
|
+
* scope field (`visibleTo`) and retired by `deletedAt`, like every other
|
|
40
|
+
* org record a site hub lists.
|
|
41
|
+
* - `label` / `pluralLabel` / `ownerLabel` are what a picker calls one, several,
|
|
42
|
+
* and the plugin a merchant creates one in.
|
|
43
|
+
*
|
|
44
|
+
* Compiled rather than registered: the readers include a form submission
|
|
45
|
+
* that loads no plugin, and a registry that request had not filled would
|
|
46
|
+
* read every record as filed under nothing.
|
|
47
|
+
*/
|
|
48
|
+
/** One container kind, as its plugin declares it. */
|
|
49
|
+
export interface PluginContainerKind {
|
|
50
|
+
/** The plugin that keeps the containers. */
|
|
51
|
+
pluginId: string;
|
|
52
|
+
/** The kind, lowerCamelCase; its members hold it in `<kind>Ids`. */
|
|
53
|
+
kind: string;
|
|
54
|
+
/** What one container is called. */
|
|
55
|
+
label: string;
|
|
56
|
+
/** What several are called. */
|
|
57
|
+
pluralLabel: string;
|
|
58
|
+
/** The owner's catalog label: where a merchant creates one. */
|
|
59
|
+
ownerLabel: string;
|
|
60
|
+
/** The org collection the containers are stored in. */
|
|
61
|
+
orgCollection: string;
|
|
62
|
+
/** The field a container's name is stored in. */
|
|
63
|
+
nameField: string;
|
|
64
|
+
}
|
|
65
|
+
/** Every declared container kind, in catalog order. */
|
|
66
|
+
export declare function listPluginContainerKinds(): PluginContainerKind[];
|
|
67
|
+
/** One declared kind, or `null` when no plugin keeps it. */
|
|
68
|
+
export declare function pluginContainerKind(kind: string): PluginContainerKind | null;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED FILE — do not edit. Regenerate with:
|
|
3
|
+
* node tools/scripts/generate-plugin-manifests.mjs
|
|
4
|
+
*
|
|
5
|
+
* The container kinds plugins declare (AGL-3080): each plugin's
|
|
6
|
+
* `containers` block in plugins.config.json. Core's `plugin-containers.ts`
|
|
7
|
+
* reads them; core names no kind.
|
|
8
|
+
*/
|
|
9
|
+
import type { PluginContainerKind } from './plugin-containers';
|
|
10
|
+
export declare const PLUGIN_CONTAINER_KINDS_DECLARED: readonly PluginContainerKind[];
|