@aglyn/aglyn 1.0.0-beta.217 → 1.0.0-beta.219
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +14 -14
- package/src/lib/app-utils/actions.d.ts +25 -374
- package/src/lib/app-utils/actions.js +101 -561
- package/src/lib/app-utils/actions.js.map +1 -1
- package/src/lib/app-utils/activity-presenter.d.ts +3 -3
- package/src/lib/app-utils/activity-presenter.js +36 -52
- package/src/lib/app-utils/activity-presenter.js.map +1 -1
- package/src/lib/app-utils/admin-audit-index.js +2 -2
- package/src/lib/app-utils/admin-audit-index.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +11 -2
- package/src/lib/app-utils/analytics-events.js +11 -2
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/analytics-provider.d.ts +182 -0
- package/src/lib/app-utils/analytics-provider.js +133 -0
- package/src/lib/app-utils/analytics-provider.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +46 -0
- package/src/lib/app-utils/api-plugins.js +19 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -1
- package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
- package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
- package/src/lib/app-utils/artifact-overrides.js.map +1 -0
- package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
- package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
- package/src/lib/app-utils/artifact-provenance.js.map +1 -0
- package/src/lib/app-utils/assist-credits.js +2 -1
- package/src/lib/app-utils/assist-credits.js.map +1 -1
- package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
- package/src/lib/app-utils/binding-token-catalog.js +17 -41
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
- package/src/lib/app-utils/binding-tokens.js +1 -1
- package/src/lib/app-utils/binding-tokens.js.map +1 -1
- package/src/lib/app-utils/brand-support-line.d.ts +36 -0
- package/src/lib/app-utils/brand-support-line.js +38 -0
- package/src/lib/app-utils/brand-support-line.js.map +1 -0
- package/src/lib/app-utils/campaign-touch.d.ts +5 -5
- package/src/lib/app-utils/campaign-touch.js +8 -8
- package/src/lib/app-utils/campaign-touch.js.map +1 -1
- package/src/lib/app-utils/collection-entries.d.ts +2 -2
- package/src/lib/app-utils/collection-entries.js.map +1 -1
- package/src/lib/app-utils/consent-group-change.d.ts +4 -0
- package/src/lib/app-utils/consent-group-change.js.map +1 -1
- package/src/lib/app-utils/console-record-links.d.ts +10 -89
- package/src/lib/app-utils/console-record-links.js +3 -107
- package/src/lib/app-utils/console-record-links.js.map +1 -1
- package/src/lib/app-utils/console-routes.d.ts +16 -7
- package/src/lib/app-utils/console-routes.js +9 -3
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/contacts.d.ts +23 -1
- package/src/lib/app-utils/contacts.js +21 -5
- package/src/lib/app-utils/contacts.js.map +1 -1
- package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
- package/src/lib/app-utils/cross-pool-desync.js +47 -0
- package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
- package/src/lib/app-utils/csv-upload.d.ts +29 -0
- package/src/lib/app-utils/csv-upload.js +29 -0
- package/src/lib/app-utils/csv-upload.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +5 -5
- package/src/lib/app-utils/dataset-models.js +19 -2
- package/src/lib/app-utils/dataset-models.js.map +1 -1
- package/src/lib/app-utils/datasets.d.ts +65 -11
- package/src/lib/app-utils/datasets.js +74 -11
- package/src/lib/app-utils/datasets.js.map +1 -1
- package/src/lib/app-utils/docs-deflection.d.ts +6 -6
- package/src/lib/app-utils/docs-deflection.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +12 -6
- package/src/lib/app-utils/docs-help.generated.js +21 -6
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
- package/src/lib/app-utils/docs-index.generated.js +514 -318
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
- package/src/lib/app-utils/docs-retrieval.js +14 -10
- package/src/lib/app-utils/docs-retrieval.js.map +1 -1
- package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
- package/src/lib/app-utils/duplicate-resource.js +7 -4
- package/src/lib/app-utils/duplicate-resource.js.map +1 -1
- package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
- package/src/lib/app-utils/element-ui.d.ts +1 -1
- package/src/lib/app-utils/element-ui.js +1 -1
- package/src/lib/app-utils/element-ui.js.map +1 -1
- package/src/lib/app-utils/email-starter-policy.js +3 -3
- package/src/lib/app-utils/email-starter-policy.js.map +1 -1
- package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
- package/src/lib/app-utils/entity-picker-context.js.map +1 -1
- package/src/lib/app-utils/error-beacon.d.ts +75 -6
- package/src/lib/app-utils/error-beacon.js +160 -21
- package/src/lib/app-utils/error-beacon.js.map +1 -1
- package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
- package/src/lib/app-utils/expand-repeatables.js +10 -10
- package/src/lib/app-utils/expand-repeatables.js.map +1 -1
- package/src/lib/app-utils/host-events.d.ts +82 -0
- package/src/lib/app-utils/host-events.js +62 -0
- package/src/lib/app-utils/host-events.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +33 -1
- package/src/lib/app-utils/lockdown.js +45 -4
- package/src/lib/app-utils/lockdown.js.map +1 -1
- package/src/lib/app-utils/margin-utilization.d.ts +4 -69
- package/src/lib/app-utils/margin-utilization.js +82 -69
- package/src/lib/app-utils/margin-utilization.js.map +1 -1
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
- package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
- package/src/lib/app-utils/node-interactions.d.ts +7 -7
- package/src/lib/app-utils/node-interactions.js.map +1 -1
- package/src/lib/app-utils/notifications.d.ts +78 -47
- package/src/lib/app-utils/notifications.js +63 -44
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/payments-configured.d.ts +8 -21
- package/src/lib/app-utils/payments-configured.js +8 -23
- package/src/lib/app-utils/payments-configured.js.map +1 -1
- package/src/lib/app-utils/plan-entitlements.d.ts +43 -128
- package/src/lib/app-utils/plan-entitlements.js +145 -304
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/platform-brand.d.ts +10 -0
- package/src/lib/app-utils/platform-brand.js +14 -3
- package/src/lib/app-utils/platform-brand.js.map +1 -1
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
- package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
- package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
- package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
- package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
- package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
- package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +14 -5
- package/src/lib/app-utils/release-flags.js +21 -125
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/repeat-sources.d.ts +9 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -1
- package/src/lib/app-utils/retained-refusals.d.ts +73 -0
- package/src/lib/app-utils/retained-refusals.js +186 -0
- package/src/lib/app-utils/retained-refusals.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +27 -0
- package/src/lib/app-utils/scope-tokens.js +61 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -1
- package/src/lib/app-utils/screen-link-context.js +3 -3
- package/src/lib/app-utils/screen-link-context.js.map +1 -1
- package/src/lib/app-utils/screen-route.d.ts +15 -0
- package/src/lib/app-utils/screen-route.js +21 -1
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/seo-audit.d.ts +132 -0
- package/src/lib/app-utils/seo-audit.js +246 -0
- package/src/lib/app-utils/seo-audit.js.map +1 -0
- package/src/lib/app-utils/seo-keywords.d.ts +48 -0
- package/src/lib/app-utils/seo-keywords.js +60 -0
- package/src/lib/app-utils/seo-keywords.js.map +1 -0
- package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
- package/src/lib/app-utils/seo-page-facts.js +155 -0
- package/src/lib/app-utils/seo-page-facts.js.map +1 -0
- package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
- package/src/lib/app-utils/seo-site-scan.js +162 -0
- package/src/lib/app-utils/seo-site-scan.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.js +1 -1
- package/src/lib/app-utils/seo-title-variables.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +6 -9
- package/src/lib/app-utils/server.js +17 -27
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-interactions.d.ts +501 -0
- package/src/lib/app-utils/site-interactions.js +554 -0
- package/src/lib/app-utils/site-interactions.js.map +1 -0
- package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
- package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +5 -2
- package/src/lib/app-utils/site-theme.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +4 -3
- package/src/lib/app-utils/sitemap.js +9 -7
- package/src/lib/app-utils/sitemap.js.map +1 -1
- package/src/lib/app-utils/stale-build-error.d.ts +51 -0
- package/src/lib/app-utils/stale-build-error.js +100 -1
- package/src/lib/app-utils/stale-build-error.js.map +1 -1
- package/src/lib/app-utils/starter-templates.d.ts +20 -0
- package/src/lib/app-utils/starter-templates.js +49 -0
- package/src/lib/app-utils/starter-templates.js.map +1 -1
- package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
- package/src/lib/app-utils/theme-library.d.ts +10 -3
- package/src/lib/app-utils/theme-library.js +13 -4
- package/src/lib/app-utils/theme-library.js.map +1 -1
- package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
- package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
- package/src/lib/app-utils/utm-attribution.js.map +1 -0
- package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
- package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
- package/src/lib/app-utils/utm-forwarding.js.map +1 -0
- package/src/lib/app-utils/video-object.js +6 -5
- package/src/lib/app-utils/video-object.js.map +1 -1
- package/src/lib/app-utils/visitor-consent.d.ts +41 -164
- package/src/lib/app-utils/visitor-consent.js +66 -277
- package/src/lib/app-utils/visitor-consent.js.map +1 -1
- package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
- package/src/lib/app-utils/web-vitals-rum.js +31 -63
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
- package/src/lib/app-utils/where-used.d.ts +11 -6
- package/src/lib/app-utils/where-used.js +3 -8
- package/src/lib/app-utils/where-used.js.map +1 -1
- package/src/lib/canvas-manager/canvas-manager.js +3 -3
- package/src/lib/canvas-manager/canvas-manager.js.map +1 -1
- package/src/lib/foundation/definitions/components.types.d.ts +1 -1
- package/src/lib/foundation/definitions/components.types.js +1 -1
- package/src/lib/foundation/definitions/components.types.js.map +1 -1
- package/src/lib/foundation/definitions/org-billing.types.d.ts +18 -135
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +6 -3
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +27 -5
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
- package/src/lib/foundation/index.d.ts +1 -1
- package/src/lib/foundation/index.js.map +1 -1
- package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
- package/src/lib/plugin-manager/besigner-documents.js +61 -0
- package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
- package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
- package/src/lib/plugin-manager/computed-variables.js +74 -0
- package/src/lib/plugin-manager/computed-variables.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
- package/src/lib/plugin-manager/custom-fields.js +47 -1
- package/src/lib/plugin-manager/custom-fields.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +292 -20
- package/src/lib/plugin-manager/feature-plugins.js +105 -17
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +123 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +785 -14
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
- package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
- package/src/lib/plugin-manager/plugin-dependents.js +75 -0
- package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
- package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
- package/src/lib/plugin-manager/plugin-distribution.js +45 -0
- package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
- package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
- package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-record-index.js +51 -0
- package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-record-written.js +42 -0
- package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
- package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
- package/src/lib/plugin-manager/plugin-site-export.js +40 -0
- package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
- package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
- package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
- package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-axes.d.ts +107 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js +107 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
- package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
- package/src/lib/plugin-manager/record-captured-contact.js +10 -32
- package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
- package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
- package/src/lib/plugin-manager/repeat-rows.js +108 -0
- package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
- package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
- package/src/lib/plugin-manager/submission-record-target.js +125 -0
- package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
- package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
- package/src/lib/plugin-manager/video-embed-provider.js +165 -0
- package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
- package/src/lib/types/nodes.d.ts +2 -2
- package/src/lib/types/nodes.js.map +1 -1
- package/src/lib/app-utils/campaign-attribution.js.map +0 -1
- package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
- package/src/lib/app-utils/contact-holder.d.ts +0 -68
- package/src/lib/app-utils/contact-holder.js +0 -129
- package/src/lib/app-utils/contact-holder.js.map +0 -1
- package/src/lib/app-utils/contact-merge.d.ts +0 -136
- package/src/lib/app-utils/contact-merge.js +0 -412
- package/src/lib/app-utils/contact-merge.js.map +0 -1
- package/src/lib/app-utils/crm-csv.d.ts +0 -239
- package/src/lib/app-utils/crm-csv.js +0 -467
- package/src/lib/app-utils/crm-csv.js.map +0 -1
- package/src/lib/app-utils/crm-digest.d.ts +0 -185
- package/src/lib/app-utils/crm-digest.js +0 -272
- package/src/lib/app-utils/crm-digest.js.map +0 -1
- package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
- package/src/lib/app-utils/form-dataset-binding.js +0 -74
- package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
- package/src/lib/app-utils/list-import.d.ts +0 -158
- package/src/lib/app-utils/list-import.js +0 -332
- package/src/lib/app-utils/list-import.js.map +0 -1
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
- package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
- package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
- package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
- package/src/lib/app-utils/marketplace-theme.js.map +0 -1
- package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
- package/src/lib/app-utils/marketplace-update-state.js +0 -132
- package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
- package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
- package/src/lib/app-utils/publisher-agreement.js +0 -321
- package/src/lib/app-utils/publisher-agreement.js.map +0 -1
- package/src/lib/app-utils/wistia-embed.d.ts +0 -104
- package/src/lib/app-utils/wistia-embed.js +0 -138
- package/src/lib/app-utils/wistia-embed.js.map +0 -1
- package/src/lib/app-utils/workflows.d.ts +0 -136
- package/src/lib/app-utils/workflows.js +0 -346
- package/src/lib/app-utils/workflows.js.map +0 -1
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
- package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
- package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/aglyn/src/lib/foundation/definitions/write-deny-coverage.util.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 * Shared parsing for the write-deny coverage guards (AGL-1355, AGL-1361).\n *\n * Extracted from `org-write-deny-coverage.spec.ts` when the same property was\n * extended to `hosts/{hostId}` and `marketplaceListings/{listingId}`. Three\n * documents, three different rule shapes, one parser — a second copy of this\n * would be a second thing to keep true, which is the disease these guards\n * exist to treat.\n *\n * Deliberately PURE: every function takes source text and returns data, with\n * no file I/O and no imports. That keeps the module free of `node:fs` (this\n * lib is bundled for the browser) and makes each helper testable on a string\n * literal. The specs own the reading.\n *\n * Not exported from the foundation barrel — nothing at runtime should reach\n * for it.\n */\n\n/**\n * Comments are stripped from every source before parsing. Prose in this repo\n * quotes rules fragments and field names constantly — the org block's own\n * comment names all four AGL-1354 keys, and the listing block's names half its\n * deny-list — so parsing with comments in place would read the explanation of\n * a hole as the fix for it.\n *\n * A single left-to-right scan, NOT two regex passes, and that distinction is\n * load-bearing (AGL-2004). The previous version removed block comments first\n * and line comments second, so a line comment that merely QUOTED a path opened\n * a block comment that was never meant to exist:\n *\n * // the name, so `hosts/<hostId>/datasets/*` stayed a client-writable\n *\n * The `/` before `*` reads as an opening delimiter, and the strip then ran to\n * the next closing delimiter 571 lines away, swallowing real rule text — and\n * with it two closing braces, which left the block walker unable to find the\n * end of the root `match` and threw `never closes`. Every deny-coverage guard\n * in this directory failed to RUN, which is the worst way for a guard to fail:\n * the suite is red, so nobody reads it as coverage, but the thing it protects\n * (the AGL-1775 `registers` deny-list) is unwatched until someone does.\n *\n * Scanning once fixes it in both directions: whichever delimiter appears first\n * wins, so `/*` inside a line comment is just text, and `//` inside a block\n * comment cannot eat the block's own terminator.\n */\nexport function stripComments(source: string): string {\n let out = ''\n let index = 0\n while (index < source.length) {\n const pair = source.slice(index, index + 2)\n if (pair === '/*') {\n const end = source.indexOf('*/', index + 2)\n index = end < 0 ? source.length : end + 2\n continue\n }\n if (pair === '//') {\n const end = source.indexOf('\\n', index + 2)\n if (end < 0) break\n // Keep the newline: line numbers and statement separation survive.\n out += '\\n'\n index = end + 1\n continue\n }\n out += source[index]\n index += 1\n }\n return out\n}\n\n/**\n * Quoted strings, blanked. `org-permissions.ts` declares permission KEYS\n * spelled `'org.settings'` and `'org.auditLog'`, which read exactly like a\n * field access — the first run of the org guard demanded the rules deny two\n * fields that do not exist. Template literals are left alone: a real read can\n * legitimately live inside `${…}`.\n */\nexport function stripQuotedStrings(source: string): string {\n return source\n .replace(/'(?:\\\\.|[^'\\\\\\n])*'/g, \"''\")\n .replace(/\"(?:\\\\.|[^\"\\\\\\n])*\"/g, '\"\"')\n}\n\n/**\n * Firestore path variables (`{orgId}`, `{document=**}`) carry braces that a\n * block-depth walker reads as nesting. Rewriting them to angle brackets makes\n * the rules parseable by brace counting without losing the path text — which\n * matters, because `{document=**}` IS the wildcard these guards have to see.\n */\nexport function normalizePathVariables(rules: string): string {\n return rules.replace(/\\{([A-Za-z_][A-Za-z0-9_]*(?:=\\*\\*)?)\\}/g, '<$1>')\n}\n\n/**\n * The text of a `{ … }` block, keeping only what sits at the block's own\n * depth. Nested blocks — sub-`match` rules, inline object types — are dropped,\n * so a nested `allow` or a nested property can never be mistaken for one\n * belonging to the block asked for.\n *\n * `header` must end with the opening brace.\n */\nexport function topLevelBody(source: string, header: string): string {\n const at = source.indexOf(header)\n if (at < 0) throw new Error(`Guard cannot parse: no \\`${header}\\` found.`)\n let depth = 1\n let out = ''\n for (let index = at + header.length; index < source.length; index += 1) {\n const character = source[index]\n if (character === '{') {\n depth += 1\n continue\n }\n if (character === '}') {\n depth -= 1\n if (depth === 0) return out\n continue\n }\n if (depth === 1) out += character\n }\n throw new Error(`Guard cannot parse: \\`${header}\\` never closes.`)\n}\n\n/**\n * The FULL text of a `{ … }` block, nested blocks INCLUDED.\n *\n * The opposite of `topLevelBody`, and needed for the opposite question. That\n * one answers \"what does THIS block say\", so it drops nested bodies — which is\n * exactly right for a deny-list on one document, and exactly wrong for\n * `hosts/{hostId}`, whose subcollection rules all live in nested `match`\n * blocks. AGL-1367 lived in one of them.\n *\n * `header` must end with the opening brace.\n */\nexport function rawBlockBody(source: string, header: string): string {\n const at = source.indexOf(header)\n if (at < 0) throw new Error(`Guard cannot parse: no \\`${header}\\` found.`)\n let depth = 1\n let out = ''\n for (let index = at + header.length; index < source.length; index += 1) {\n const character = source[index]\n if (character === '{') depth += 1\n else if (character === '}') {\n depth -= 1\n if (depth === 0) return out\n }\n out += character\n }\n throw new Error(`Guard cannot parse: \\`${header}\\` never closes.`)\n}\n\n/** The subcollection write rules of `hosts/{hostId}`, as the rules state them. */\nexport interface ParsedSubcollectionRules {\n /** The `subcollection in […]` exclusion list of each catch-all allow. */\n excluded: { create: string[]; update: string[]; delete: string[] }\n /** Collections with a dedicated `match` block, which can RE-GRANT. */\n dedicated: string[]\n /** Excluded from all three AND re-granted by nothing: denied outright. */\n serverOnly: string[]\n}\n\n/**\n * Parse the host catch-all's three exclusion lists (AGL-1367).\n *\n * Membership in ONE list is not denial and never was — `variables` is\n * create-excluded and freely updatable, `webhooks` is create-excluded and\n * freely updatable on purpose (the soft delete is how a capped site frees a\n * slot). And a dedicated `match` block RE-GRANTS, because Firestore ORs its\n * allows and the LOOSER one wins: `screens`, `layouts` and `collections` all\n * sit in three lists and stay editor-writable through the blocks above.\n *\n * So \"denied outright\" is the intersection of the three lists MINUS everything\n * with a block of its own. That subtraction is the reason a dedicated\n * `allow write: if false` block would not have closed AGL-1367 — a deny can\n * never win an OR.\n */\nexport function parseHostSubcollectionRules(\n rulesSource: string,\n): ParsedSubcollectionRules {\n const rules = normalizePathVariables(stripComments(rulesSource))\n const host = rawBlockBody(rules, 'match /hosts/<hostId> {')\n\n const catchAllHeader = 'match /<subcollection>/<document=**> {'\n const occurrences = host.split(catchAllHeader).length - 1\n if (occurrences !== 1) {\n throw new Error(\n `Expected exactly one \\`${catchAllHeader}\\` under match /hosts/{hostId}, ` +\n `found ${occurrences}. A second one would OR another set of allows ` +\n `onto every subcollection, so these lists would be half the answer.`,\n )\n }\n const catchAll = rawBlockBody(host, catchAllHeader)\n\n const listFor = (operation: 'create' | 'update' | 'delete'): string[] => {\n const statement = catchAll\n .split(';')\n .find((entry) =>\n new RegExp(`\\\\ballow\\\\b[^:]*\\\\b${operation}\\\\b`).test(entry),\n )\n if (!statement) {\n throw new Error(\n `No \\`allow … ${operation}\\` in the host catch-all. The block has been ` +\n `restructured; re-read it before trusting this guard.`,\n )\n }\n const list = statement.match(/subcollection\\s+in\\s+\\[([^\\]]*)\\]/)\n if (!list) {\n throw new Error(\n `The host catch-all's \\`allow ${operation}\\` has no ` +\n `\\`subcollection in […]\\` exclusion list. Every server-owned host ` +\n `subcollection is denied by NAME in that list and nowhere else, so ` +\n `this guard cannot see what is protected any more.`,\n )\n }\n return [...list[1].matchAll(/'([^']+)'/g)].map((entry) => entry[1])\n }\n\n const excluded = {\n create: listFor('create'),\n update: listFor('update'),\n delete: listFor('delete'),\n }\n // Named `match` blocks only. After `normalizePathVariables` a wildcard\n // segment starts with `<`, so a leading letter is what distinguishes a\n // collection block from `match /<subcollection>/…` or the nested\n // `match /<sub>/…` inside the screens/layouts/components blocks.\n const dedicated = [\n ...new Set(\n [...host.matchAll(/match\\s+\\/([A-Za-z][A-Za-z0-9]*)\\//g)].map(\n (entry) => entry[1],\n ),\n ),\n ]\n const serverOnly = excluded.create.filter(\n (name) =>\n excluded.update.includes(name) &&\n excluded.delete.includes(name) &&\n !dedicated.includes(name),\n )\n return { excluded, dedicated, serverOnly }\n}\n\n/**\n * Split an expression on `||` at parenthesis depth 0 only.\n *\n * A naive `split('||')` tears a branch apart at any nested alternation, and\n * both of the documents AGL-1361 added have one. The host rule's client branch\n * is `(… && !hasAny(L1) && (role == 'admin' || !hasAny(L2)))` — its deny-list\n * is TIERED, six keys no site member may touch plus `disabledPlugins` which\n * only a site admin may — and a naive split drops L2 into a branch of its own\n * where nothing looks for it. The listing block's `function listingManager()`\n * produces the mirror problem, matching two branches instead of one.\n */\nexport function splitTopLevelOr(expression: string): string[] {\n const parts: string[] = []\n let depth = 0\n let current = ''\n for (let index = 0; index < expression.length; index += 1) {\n const character = expression[index]\n if (character === '(') depth += 1\n if (character === ')') depth -= 1\n if (depth === 0 && character === '|' && expression[index + 1] === '|') {\n parts.push(current)\n current = ''\n index += 1\n continue\n }\n current += character\n }\n parts.push(current)\n return parts.map((part) => part.trim()).filter(Boolean)\n}\n\n/** The keys of the FIRST `hasAny([...])` literal in a rules branch. */\nexport function hasAnyKeys(branch: string): string[] {\n const list = branch.match(/hasAny\\(\\s*\\[([^\\]]*)\\]/)\n if (!list) return []\n return [...list[1].matchAll(/'([^']+)'/g)].map((entry) => entry[1])\n}\n\n/**\n * The keys of EVERY `hasAny([...])` literal in a branch, flattened.\n *\n * The org rule has one list per branch; the host rule has two in a single\n * branch, because its deny-list is TIERED — six keys no site member may\n * touch, and `disabledPlugins` which only a site admin may. `hasAnyKeys`\n * returns the first list alone, so a host guard built on it would have\n * silently believed `disabledPlugins` was unprotected.\n */\nexport function allHasAnyKeys(branch: string): string[] {\n return [...branch.matchAll(/hasAny\\(\\s*\\[([^\\]]*)\\]/g)].flatMap((list) =>\n [...list[1].matchAll(/'([^']+)'/g)].map((entry) => entry[1]),\n )\n}\n\n/**\n * Top-level property names declared on an interface.\n *\n * `header` is the full declaration line up to and including the brace, because\n * the three documents do not share a shape: `AglynOrgBilling` and `AglynHost`\n * both `extends AglynDocument`, while `MarketplaceListing` extends nothing.\n */\nexport function declaredFields(source: string, header: string): string[] {\n const body = topLevelBody(stripComments(source), header)\n return [\n ...body.matchAll(/(?:^|\\n)\\s*(\\$?[A-Za-z_][A-Za-z0-9_$]*)\\s*\\??\\s*:/g),\n ].map((entry) => entry[1])\n}\n\n/**\n * The top-level recursive (`**`) matches that could reach a document in\n * `collection` — the ones that could OR a looser write onto it.\n *\n * A recursive wildcard matches only what its tail allows. A collection-group\n * match, `/{path=**}/formSubmissions/{submissionId}` (AGL-3303), reaches\n * documents in a collection named `formSubmissions` and nothing else; a\n * wildcard collection, or a recursive tail, reaches every document. So only\n * those, and a group match naming `collection` itself, are the hazard a\n * deny-list guard has to refuse.\n *\n * `topLevelMatches` are post-`normalizePathVariables`.\n */\nexport function recursiveMatchesReaching(\n topLevelMatches: readonly string[],\n collection: string,\n): string[] {\n return topLevelMatches.filter((path) => {\n if (!path.includes('**')) return false\n const segments = path.split('/').filter(Boolean)\n const last = segments[segments.length - 1] ?? ''\n const parent = segments[segments.length - 2] ?? ''\n return (\n last.includes('**') ||\n !parent ||\n parent.startsWith('<') ||\n parent === collection\n )\n })\n}\n\n/** A parsed `allow update` rule for one document. */\nexport interface ParsedUpdateRule {\n /** Every key denied to the client branch, across all its `hasAny` lists. */\n denied: string[]\n /** Every OR'd branch of the single `allow update` statement. */\n branches: string[]\n /** Depth-0 statements of the document's `match` block. */\n statements: string[]\n /** Depth-0 `match` headers under `/databases/{database}/documents`. */\n topLevelMatches: string[]\n}\n\n/**\n * Parse the single `allow update` of one top-level document block.\n *\n * `matchHeader` is post-`normalizePathVariables`, e.g.\n * `match /hosts/<hostId> {`. `clientPredicate` names the branch that a CLIENT\n * reaches — `canManageOrg()`, `canWriteHostContent(hostId)`, `listingManager()`\n * — as opposed to the staff branches, which are trusted by design.\n */\nexport function parseUpdateRule(\n rulesSource: string,\n matchHeader: string,\n clientPredicate: string,\n): ParsedUpdateRule {\n const rules = normalizePathVariables(stripComments(rulesSource))\n const root = topLevelBody(rules, 'match /databases/<database>/documents {')\n const topLevelMatches = [...root.matchAll(/match\\s+(\\/\\S*)/g)].map(\n (entry) => entry[1],\n )\n\n const block = topLevelBody(rules, matchHeader)\n const statements = block\n .split(';')\n .map((statement) => statement.trim())\n .filter(Boolean)\n\n // ONE `allow` statement may mention `update`. Firestore ORs every allow\n // across sibling statements AND sibling match blocks, and the LOOSER one\n // wins — so a second statement would mean this guard is reasoning about a\n // deny-list that some other statement quietly overrides.\n const updates = statements.filter((statement) =>\n /\\ballow\\b[^:]*\\bupdate\\b/.test(statement),\n )\n if (updates.length !== 1) {\n throw new Error(\n `Expected exactly one \\`allow … update\\` statement under ` +\n `${matchHeader}, found ${updates.length}. Firestore ORs them and the ` +\n `LOOSER wins, so the deny-list this guard reads would no longer be ` +\n `the whole answer. Fold the branches back into one statement, or ` +\n `teach this guard how they combine.`,\n )\n }\n\n // Start at the `allow` keyword. `topLevelBody` drops a nested block's BODY\n // but leaves its header text at depth 1, so the listing block's\n // `function listingManager()` declaration survives as an orphan with no\n // semicolon of its own — it merges into the following statement and makes\n // `listingManager()` appear in two branches instead of one. Slicing to\n // `allow` removes the remnant without pretending the function is not there.\n const statement = updates[0].slice(updates[0].indexOf('allow'))\n const branches = splitTopLevelOr(statement)\n const found = branches.filter((branch) => branch.includes(clientPredicate))\n if (found.length !== 1) {\n throw new Error(\n `Expected exactly one \\`allow update\\` branch guarded by ` +\n `${clientPredicate} under ${matchHeader}, found ${found.length}. The ` +\n `rule has been restructured; re-read it before trusting this guard.`,\n )\n }\n\n return {\n denied: allHasAnyKeys(found[0]),\n branches,\n statements,\n topLevelMatches,\n }\n}\n\n/**\n * Field names in an object literal a document is seeded with.\n *\n * `anchor` is a regex source locating the write; the literal's own braces are\n * matched by depth rather than `[^}]*`, because a seed can legitimately carry\n * a nested object (the host seed writes `screens: {}`) and a lazy class would\n * truncate the field list at the first inner brace — silently shrinking one of\n * the guard's sources rather than failing.\n */\nexport function seedFields(source: string, anchor: RegExp): string[] | null {\n const at = stripComments(source).search(anchor)\n if (at < 0) return null\n const text = stripComments(source)\n const open = text.indexOf('{', at)\n if (open < 0) return null\n let depth = 1\n let body = ''\n for (let index = open + 1; index < text.length; index += 1) {\n const character = text[index]\n if (character === '{') depth += 1\n else if (character === '}') {\n depth -= 1\n if (depth === 0) break\n }\n if (depth === 1) body += character\n }\n return [\n ...body.matchAll(/(?:^|,|\\n)\\s*([A-Za-z_$][A-Za-z0-9_$]*)\\s*[,:]/g),\n ].map((entry) => entry[1])\n}\n\n/**\n * Field names a document of `collection` is seeded with, in either shape a\n * seed write takes in this codebase (AGL-2100).\n *\n * The original parser understood only the CHAINED form —\n * `collection('hosts').doc(id).set({ … })` — because that is what every seed\n * route looked like when it was written. AGL-2063 rewrote the host create into\n * a transactional claim, which necessarily splits the chain: the ref has to be\n * built BEFORE `runTransaction` opens so the transaction body can both read\n * and write it, leaving `const hostRef = …doc(hostId)` in one statement and\n * `tx.set(hostRef, { … })` in another. The chained anchor then matched\n * nothing, `seedFields` returned null, and the guard threw — asserting nothing\n * about any of the four sources of the host field set until it was fixed.\n *\n * So resolve the REF BINDING rather than teaching the guard one more literal\n * spelling. Any `set`/`create` whose first argument is a ref bound to this\n * collection is a seed write, which covers `tx.`, `batch.` and a bare\n * `ref.set()` alike, and does not care what wraps them.\n *\n * Anchoring on the WRITE and not on the binding matters: the binding is\n * followed by the transaction callback's own `{`, so a binding-anchored parse\n * would happily return the arrow body's contents as the field list — a\n * silently wrong answer, which is worse than the throw.\n *\n * Returns null when neither shape is present, so the caller still throws.\n */\nexport function seedFieldsOfCollection(\n source: string,\n collection: string,\n): string[] | null {\n const name = collection.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const chained = seedFields(\n source,\n new RegExp(\n `collection\\\\('${name}'\\\\)\\\\s*\\\\.doc\\\\([^)]*\\\\)\\\\s*\\\\.\\\\s*(?:set|create)\\\\s*\\\\(`,\n ),\n )\n if (chained) return chained\n\n const text = stripComments(source)\n const bindings = [\n ...text.matchAll(\n new RegExp(\n `(?:const|let|var)\\\\s+([A-Za-z_$][A-Za-z0-9_$]*)\\\\s*=\\\\s*[^;\\\\n]*collection\\\\('${name}'\\\\)\\\\s*\\\\.doc\\\\(`,\n 'g',\n ),\n ),\n ].map((entry) => entry[1])\n\n for (const binding of bindings) {\n const fields = seedFields(\n source,\n new RegExp(\n `\\\\b(?:set|create)\\\\s*\\\\(\\\\s*${binding}\\\\s*,\\\\s*\\\\{`,\n ),\n )\n if (fields) return fields\n }\n return null\n}\n\n/**\n * Whether the property access ending at `index` is being CALLED (AGL-1719).\n *\n * The guard reads `hosts/{hostId}` fields by scanning for `host.<name>` across\n * a whole directory, which means it matches on the identifier NAME and cannot\n * see the type. `media-ref.ts` has `isFirstPartyHost(host: string)` whose body\n * is `host.toLowerCase()` — a hostname string, not the host document — so\n * `toLowerCase` entered the field universe and the guard demanded that a\n * `String.prototype` method be classified as server-owned or client-writable.\n *\n * Dropping method calls removes that whole class rather than that one name,\n * and it is sound in the only direction that matters. Firestore document data\n * is JSON: string, number, boolean, null, array, map, timestamp, geopoint,\n * reference. **No field of a document can be callable**, so `binding.X(` is\n * provably never a field read and this can never introduce a false negative —\n * which is the single failure mode a coverage guard has (AGL-1420).\n *\n * A chained read is untouched: in `host.disabledPlugins.includes(x)` the\n * character after the captured name is `.`, so `disabledPlugins` is still\n * collected and only `includes` is dropped. Optional calls (`host.foo?.()`)\n * and generic ones (`host.foo<T>()`) are calls too.\n *\n * An exclusion list of known method names was rejected: it would silence the\n * symptom, need tending forever, and still say nothing about the next method\n * on the next same-named local.\n */\nfunction isMethodCallAt(source: string, index: number): boolean {\n const rest = source.slice(index)\n return /^\\s*(?:\\?\\.)?\\s*(?:<[^<>()]*>\\s*)?\\(/.test(rest)\n}\n\n/**\n * Top-level fields of `binding` that the modules in `sources` read.\n *\n * Directory-wide on purpose. A per-file list would be one more thing to keep\n * up to date, and a NEW resolver reading a NEW field is covered the moment it\n * is written — the only way this stays true without anyone tending it.\n *\n * The document is identified by IDENTIFIER NAME, not by type — this is a text\n * scan, and it has no way to know what a local called `host` actually holds.\n * So an unrelated binding of the same name contributes its property reads too.\n * That direction is safe (a spurious field fails loudly and gets classified by\n * a human, and can never HIDE a real one), and it is deliberately left alone,\n * because the filter that would suppress it is the filter that could suppress\n * a real read. See {@link isMethodCallAt} for the one case that is not safe to\n * leave — it produced a name no human could classify.\n */\nexport function readFieldsOf(\n sources: Array<string>,\n binding: string,\n): string[] {\n const found = new Set<string>()\n for (const raw of sources) {\n const source = stripQuotedStrings(stripComments(raw))\n // `host?.field` / `host.field` — the ordinary read.\n for (const hit of source.matchAll(\n new RegExp(`\\\\b${binding}\\\\s*\\\\??\\\\.\\\\s*([A-Za-z_$][A-Za-z0-9_$]*)`, 'g'),\n )) {\n // `host.toLowerCase()` is a method INVOCATION, not a field (AGL-1719).\n if (isMethodCallAt(source, hit.index + hit[0].length)) continue\n // A lone `$` is the head of a `${…}` interpolation, not a field: it\n // comes from token-name construction like `` `{{host.${key}}}` ``.\n // Template literals are left unstripped on purpose — a real read can\n // live inside one — so this is the price, and a field named `$` cannot\n // exist. Anything else, including `$id`, is kept and must be classified.\n if (hit[1] !== '$') found.add(hit[1])\n }\n // `(host as { cname?: unknown })?.cname` — the cast a field that is real\n // but was undeclared gets read through.\n for (const hit of source.matchAll(\n new RegExp(\n `\\\\b${binding}\\\\s+as\\\\s*\\\\{\\\\s*([A-Za-z_$][A-Za-z0-9_$]*)\\\\s*\\\\??\\\\s*:`,\n 'g',\n ),\n )) {\n found.add(hit[1])\n }\n }\n return [...found].sort()\n}\n\n/**\n * Comments stripped from a TYPESCRIPT source, with string literals respected.\n *\n * `stripComments` above scans rules files, where no string ever contains a\n * comment delimiter. TypeScript sources are not that: `apps/console/app/api/\n * media/upload-url/route.ts` builds a download URL from a template literal\n * containing `https://`, and a scan that does not know it is inside a string\n * reads that `//` as a line comment and deletes the rest of the line. On a\n * guard that parses an object literal out of a route, that is not a crash —\n * it is a SHORTER field list, silently, which is the failure mode AGL-2004\n * described one level down.\n *\n * A separate function rather than a widened `stripComments`, because the two\n * inputs have genuinely different grammars and three shipped guards depend on\n * the rules-file behaviour exactly as it is. Same single left-to-right scan,\n * with quotes as a third state.\n */\nexport function stripTypeScriptComments(source: string): string {\n let out = ''\n let index = 0\n while (index < source.length) {\n const pair = source.slice(index, index + 2)\n if (pair === '/*') {\n const end = source.indexOf('*/', index + 2)\n index = end < 0 ? source.length : end + 2\n continue\n }\n if (pair === '//') {\n const end = source.indexOf('\\n', index + 2)\n if (end < 0) break\n // Keep the newline so line-oriented reasoning downstream survives.\n out += '\\n'\n index = end + 1\n continue\n }\n const character = source[index]\n if (character === \"'\" || character === '\"' || character === '`') {\n let cursor = index + 1\n while (cursor < source.length && source[cursor] !== character) {\n cursor += source[cursor] === '\\\\' ? 2 : 1\n }\n out += source.slice(index, Math.min(cursor + 1, source.length))\n index = cursor + 1\n continue\n }\n out += character\n index += 1\n }\n return out\n}\n"],"names":["stripComments","source","out","index","length","pair","slice","end","indexOf","stripQuotedStrings","replace","normalizePathVariables","rules","topLevelBody","header","at","Error","depth","character","rawBlockBody","parseHostSubcollectionRules","rulesSource","host","catchAllHeader","occurrences","split","catchAll","listFor","operation","statement","find","entry","RegExp","test","list","match","matchAll","map","excluded","create","update","delete","dedicated","Set","serverOnly","filter","name","includes","splitTopLevelOr","expression","parts","current","push","part","trim","Boolean","hasAnyKeys","branch","allHasAnyKeys","flatMap","declaredFields","body","recursiveMatchesReaching","topLevelMatches","collection","path","segments","last","parent","startsWith","parseUpdateRule","matchHeader","clientPredicate","root","block","statements","updates","branches","found","denied","seedFields","anchor","search","text","open","seedFieldsOfCollection","chained","bindings","binding","fields","isMethodCallAt","rest","readFieldsOf","sources","raw","hit","add","sort","stripTypeScriptComments","cursor","Math","min"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/aglyn/src/lib/foundation/definitions/write-deny-coverage.util.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 * Shared parsing for the write-deny coverage guards (AGL-1355, AGL-1361).\n *\n * Extracted from `org-write-deny-coverage.spec.ts` when the same property was\n * extended to `hosts/{hostId}` and `marketplaceListings/{listingId}`. Three\n * documents, three different rule shapes, one parser — a second copy of this\n * would be a second thing to keep true, which is the disease these guards\n * exist to treat.\n *\n * Deliberately PURE: every function takes source text and returns data, with\n * no file I/O and no imports. That keeps the module free of `node:fs` (this\n * lib is bundled for the browser) and makes each helper testable on a string\n * literal. The specs own the reading.\n *\n * Not exported from the foundation barrel — nothing at runtime should reach\n * for it.\n */\n\n/**\n * Comments are stripped from every source before parsing. Prose in this repo\n * quotes rules fragments and field names constantly — the org block's own\n * comment names all four AGL-1354 keys, and the listing block's names half its\n * deny-list — so parsing with comments in place would read the explanation of\n * a hole as the fix for it.\n *\n * A single left-to-right scan, NOT two regex passes, and that distinction is\n * load-bearing (AGL-2004). The previous version removed block comments first\n * and line comments second, so a line comment that merely QUOTED a path opened\n * a block comment that was never meant to exist:\n *\n * // the name, so `hosts/<hostId>/datasets/*` stayed a client-writable\n *\n * The `/` before `*` reads as an opening delimiter, and the strip then ran to\n * the next closing delimiter 571 lines away, swallowing real rule text — and\n * with it two closing braces, which left the block walker unable to find the\n * end of the root `match` and threw `never closes`. Every deny-coverage guard\n * in this directory failed to RUN, which is the worst way for a guard to fail:\n * the suite is red, so nobody reads it as coverage, but the thing it protects\n * (the AGL-1775 `registers` deny-list) is unwatched until someone does.\n *\n * Scanning once fixes it in both directions: whichever delimiter appears first\n * wins, so `/*` inside a line comment is just text, and `//` inside a block\n * comment cannot eat the block's own terminator.\n */\nexport function stripComments(source: string): string {\n let out = ''\n let index = 0\n while (index < source.length) {\n const pair = source.slice(index, index + 2)\n if (pair === '/*') {\n const end = source.indexOf('*/', index + 2)\n index = end < 0 ? source.length : end + 2\n continue\n }\n if (pair === '//') {\n const end = source.indexOf('\\n', index + 2)\n if (end < 0) break\n // Keep the newline: line numbers and statement separation survive.\n out += '\\n'\n index = end + 1\n continue\n }\n out += source[index]\n index += 1\n }\n return out\n}\n\n/**\n * Quoted strings, blanked. `org-permissions.ts` declares permission KEYS\n * spelled `'org.settings'` and `'org.auditLog'`, which read exactly like a\n * field access — the first run of the org guard demanded the rules deny two\n * fields that do not exist. Template literals are left alone: a real read can\n * legitimately live inside `${…}`.\n */\nexport function stripQuotedStrings(source: string): string {\n return source\n .replace(/'(?:\\\\.|[^'\\\\\\n])*'/g, \"''\")\n .replace(/\"(?:\\\\.|[^\"\\\\\\n])*\"/g, '\"\"')\n}\n\n/**\n * Firestore path variables (`{orgId}`, `{document=**}`) carry braces that a\n * block-depth walker reads as nesting. Rewriting them to angle brackets makes\n * the rules parseable by brace counting without losing the path text — which\n * matters, because `{document=**}` IS the wildcard these guards have to see.\n */\nexport function normalizePathVariables(rules: string): string {\n return rules.replace(/\\{([A-Za-z_][A-Za-z0-9_]*(?:=\\*\\*)?)\\}/g, '<$1>')\n}\n\n/**\n * The text of a `{ … }` block, keeping only what sits at the block's own\n * depth. Nested blocks — sub-`match` rules, inline object types — are dropped,\n * so a nested `allow` or a nested property can never be mistaken for one\n * belonging to the block asked for.\n *\n * `header` must end with the opening brace.\n */\nexport function topLevelBody(source: string, header: string): string {\n const at = source.indexOf(header)\n if (at < 0) throw new Error(`Guard cannot parse: no \\`${header}\\` found.`)\n let depth = 1\n let out = ''\n for (let index = at + header.length; index < source.length; index += 1) {\n const character = source[index]\n if (character === '{') {\n depth += 1\n continue\n }\n if (character === '}') {\n depth -= 1\n if (depth === 0) return out\n continue\n }\n if (depth === 1) out += character\n }\n throw new Error(`Guard cannot parse: \\`${header}\\` never closes.`)\n}\n\n/**\n * The FULL text of a `{ … }` block, nested blocks INCLUDED.\n *\n * The opposite of `topLevelBody`, and needed for the opposite question. That\n * one answers \"what does THIS block say\", so it drops nested bodies — which is\n * exactly right for a deny-list on one document, and exactly wrong for\n * `hosts/{hostId}`, whose subcollection rules all live in nested `match`\n * blocks. AGL-1367 lived in one of them.\n *\n * `header` must end with the opening brace.\n */\nexport function rawBlockBody(source: string, header: string): string {\n const at = source.indexOf(header)\n if (at < 0) throw new Error(`Guard cannot parse: no \\`${header}\\` found.`)\n let depth = 1\n let out = ''\n for (let index = at + header.length; index < source.length; index += 1) {\n const character = source[index]\n if (character === '{') depth += 1\n else if (character === '}') {\n depth -= 1\n if (depth === 0) return out\n }\n out += character\n }\n throw new Error(`Guard cannot parse: \\`${header}\\` never closes.`)\n}\n\n/** The subcollection write rules of `hosts/{hostId}`, as the rules state them. */\nexport interface ParsedSubcollectionRules {\n /** The `subcollection in […]` exclusion list of each catch-all allow. */\n excluded: { create: string[]; update: string[]; delete: string[] }\n /** Collections with a dedicated `match` block, which can RE-GRANT. */\n dedicated: string[]\n /** Excluded from all three AND re-granted by nothing: denied outright. */\n serverOnly: string[]\n}\n\n/**\n * Parse the host catch-all's three exclusion lists (AGL-1367).\n *\n * Membership in ONE list is not denial and never was — `variables` is\n * create-excluded and freely updatable, `webhooks` is create-excluded and\n * freely updatable on purpose (the soft delete is how a capped site frees a\n * slot). And a dedicated `match` block RE-GRANTS, because Firestore ORs its\n * allows and the LOOSER one wins: `screens`, `layouts` and `collections` all\n * sit in three lists and stay editor-writable through the blocks above.\n *\n * So \"denied outright\" is the intersection of the three lists MINUS everything\n * with a block of its own. That subtraction is the reason a dedicated\n * `allow write: if false` block would not have closed AGL-1367 — a deny can\n * never win an OR.\n */\nexport function parseHostSubcollectionRules(\n rulesSource: string,\n): ParsedSubcollectionRules {\n const rules = normalizePathVariables(stripComments(rulesSource))\n const host = rawBlockBody(rules, 'match /hosts/<hostId> {')\n\n const catchAllHeader = 'match /<subcollection>/<document=**> {'\n const occurrences = host.split(catchAllHeader).length - 1\n if (occurrences !== 1) {\n throw new Error(\n `Expected exactly one \\`${catchAllHeader}\\` under match /hosts/{hostId}, ` +\n `found ${occurrences}. A second one would OR another set of allows ` +\n `onto every subcollection, so these lists would be half the answer.`,\n )\n }\n const catchAll = rawBlockBody(host, catchAllHeader)\n\n const listFor = (operation: 'create' | 'update' | 'delete'): string[] => {\n const statement = catchAll\n .split(';')\n .find((entry) =>\n new RegExp(`\\\\ballow\\\\b[^:]*\\\\b${operation}\\\\b`).test(entry),\n )\n if (!statement) {\n throw new Error(\n `No \\`allow … ${operation}\\` in the host catch-all. The block has been ` +\n `restructured; re-read it before trusting this guard.`,\n )\n }\n const list = statement.match(/subcollection\\s+in\\s+\\[([^\\]]*)\\]/)\n if (!list) {\n throw new Error(\n `The host catch-all's \\`allow ${operation}\\` has no ` +\n `\\`subcollection in […]\\` exclusion list. Every server-owned host ` +\n `subcollection is denied by NAME in that list and nowhere else, so ` +\n `this guard cannot see what is protected any more.`,\n )\n }\n return [...list[1].matchAll(/'([^']+)'/g)].map((entry) => entry[1])\n }\n\n const excluded = {\n create: listFor('create'),\n update: listFor('update'),\n delete: listFor('delete'),\n }\n // Named `match` blocks only. After `normalizePathVariables` a wildcard\n // segment starts with `<`, so a leading letter is what distinguishes a\n // collection block from `match /<subcollection>/…` or the nested\n // `match /<sub>/…` inside the screens/layouts/components blocks.\n const dedicated = [\n ...new Set(\n [...host.matchAll(/match\\s+\\/([A-Za-z][A-Za-z0-9]*)\\//g)].map(\n (entry) => entry[1],\n ),\n ),\n ]\n const serverOnly = excluded.create.filter(\n (name) =>\n excluded.update.includes(name) &&\n excluded.delete.includes(name) &&\n !dedicated.includes(name),\n )\n return { excluded, dedicated, serverOnly }\n}\n\n/**\n * Split an expression on `||` at parenthesis depth 0 only.\n *\n * A naive `split('||')` tears a branch apart at any nested alternation, and\n * both of the documents AGL-1361 added have one. The host rule's client branch\n * is `(… && !hasAny(L1) && (role == 'admin' || !hasAny(L2)))` — its deny-list\n * is TIERED, six keys no site member may touch plus `disabledPlugins` which\n * only a site admin may — and a naive split drops L2 into a branch of its own\n * where nothing looks for it. The listing block's `function listingManager()`\n * produces the mirror problem, matching two branches instead of one.\n */\nexport function splitTopLevelOr(expression: string): string[] {\n const parts: string[] = []\n let depth = 0\n let current = ''\n for (let index = 0; index < expression.length; index += 1) {\n const character = expression[index]\n if (character === '(') depth += 1\n if (character === ')') depth -= 1\n if (depth === 0 && character === '|' && expression[index + 1] === '|') {\n parts.push(current)\n current = ''\n index += 1\n continue\n }\n current += character\n }\n parts.push(current)\n return parts.map((part) => part.trim()).filter(Boolean)\n}\n\n/** The keys of the FIRST `hasAny([...])` literal in a rules branch. */\nexport function hasAnyKeys(branch: string): string[] {\n const list = branch.match(/hasAny\\(\\s*\\[([^\\]]*)\\]/)\n if (!list) return []\n return [...list[1].matchAll(/'([^']+)'/g)].map((entry) => entry[1])\n}\n\n/**\n * The keys of EVERY `hasAny([...])` literal in a branch, flattened.\n *\n * The org rule has one list per branch; the host rule has two in a single\n * branch, because its deny-list is TIERED — six keys no site member may\n * touch, and `disabledPlugins` which only a site admin may. `hasAnyKeys`\n * returns the first list alone, so a host guard built on it would have\n * silently believed `disabledPlugins` was unprotected.\n */\nexport function allHasAnyKeys(branch: string): string[] {\n return [...branch.matchAll(/hasAny\\(\\s*\\[([^\\]]*)\\]/g)].flatMap((list) =>\n [...list[1].matchAll(/'([^']+)'/g)].map((entry) => entry[1]),\n )\n}\n\n/**\n * Top-level property names declared on an interface.\n *\n * `header` is the full declaration line up to and including the brace, because\n * the three documents do not share a shape: `AglynOrgBilling` and `AglynHost`\n * both `extends AglynDocument`, while `MarketplaceListing` extends nothing.\n */\nexport function declaredFields(source: string, header: string): string[] {\n const body = topLevelBody(stripComments(source), header)\n return [\n ...body.matchAll(/(?:^|\\n)\\s*(\\$?[A-Za-z_][A-Za-z0-9_$]*)\\s*\\??\\s*:/g),\n ].map((entry) => entry[1])\n}\n\n/**\n * The top-level recursive (`**`) matches that could reach a document in\n * `collection` — the ones that could OR a looser write onto it.\n *\n * A recursive wildcard matches only what its tail allows. A collection-group\n * match, `/{path=**}/formSubmissions/{submissionId}` (AGL-3303), reaches\n * documents in a collection named `formSubmissions` and nothing else; a\n * wildcard collection, or a recursive tail, reaches every document. So only\n * those, and a group match naming `collection` itself, are the hazard a\n * deny-list guard has to refuse.\n *\n * `topLevelMatches` are post-`normalizePathVariables`.\n */\nexport function recursiveMatchesReaching(\n topLevelMatches: readonly string[],\n collection: string,\n): string[] {\n return topLevelMatches.filter((path) => {\n if (!path.includes('**')) return false\n const segments = path.split('/').filter(Boolean)\n const last = segments[segments.length - 1] ?? ''\n const parent = segments[segments.length - 2] ?? ''\n return (\n last.includes('**') ||\n !parent ||\n parent.startsWith('<') ||\n parent === collection\n )\n })\n}\n\n/** A parsed `allow update` rule for one document. */\nexport interface ParsedUpdateRule {\n /** Every key denied to the client branch, across all its `hasAny` lists. */\n denied: string[]\n /** Every OR'd branch of the single `allow update` statement. */\n branches: string[]\n /** Depth-0 statements of the document's `match` block. */\n statements: string[]\n /** Depth-0 `match` headers under `/databases/{database}/documents`. */\n topLevelMatches: string[]\n}\n\n/**\n * Parse the single `allow update` of one top-level document block.\n *\n * `matchHeader` is post-`normalizePathVariables`, e.g.\n * `match /hosts/<hostId> {`. `clientPredicate` names the branch that a CLIENT\n * reaches — `canManageOrg()`, `canWriteHostContent(hostId)`, `listingManager()`\n * — as opposed to the staff branches, which are trusted by design.\n */\nexport function parseUpdateRule(\n rulesSource: string,\n matchHeader: string,\n clientPredicate: string,\n): ParsedUpdateRule {\n const rules = normalizePathVariables(stripComments(rulesSource))\n const root = topLevelBody(rules, 'match /databases/<database>/documents {')\n const topLevelMatches = [...root.matchAll(/match\\s+(\\/\\S*)/g)].map(\n (entry) => entry[1],\n )\n\n const block = topLevelBody(rules, matchHeader)\n const statements = block\n .split(';')\n .map((statement) => statement.trim())\n .filter(Boolean)\n\n // ONE `allow` statement may mention `update`. Firestore ORs every allow\n // across sibling statements AND sibling match blocks, and the LOOSER one\n // wins — so a second statement would mean this guard is reasoning about a\n // deny-list that some other statement quietly overrides.\n const updates = statements.filter((statement) =>\n /\\ballow\\b[^:]*\\bupdate\\b/.test(statement),\n )\n if (updates.length !== 1) {\n throw new Error(\n `Expected exactly one \\`allow … update\\` statement under ` +\n `${matchHeader}, found ${updates.length}. Firestore ORs them and the ` +\n `LOOSER wins, so the deny-list this guard reads would no longer be ` +\n `the whole answer. Fold the branches back into one statement, or ` +\n `teach this guard how they combine.`,\n )\n }\n\n // Start at the `allow` keyword. `topLevelBody` drops a nested block's BODY\n // but leaves its header text at depth 1, so the listing block's\n // `function listingManager()` declaration survives as an orphan with no\n // semicolon of its own — it merges into the following statement and makes\n // `listingManager()` appear in two branches instead of one. Slicing to\n // `allow` removes the remnant without pretending the function is not there.\n const statement = updates[0].slice(updates[0].indexOf('allow'))\n const branches = splitTopLevelOr(statement)\n const found = branches.filter((branch) => branch.includes(clientPredicate))\n if (found.length !== 1) {\n throw new Error(\n `Expected exactly one \\`allow update\\` branch guarded by ` +\n `${clientPredicate} under ${matchHeader}, found ${found.length}. The ` +\n `rule has been restructured; re-read it before trusting this guard.`,\n )\n }\n\n return {\n denied: allHasAnyKeys(found[0]),\n branches,\n statements,\n topLevelMatches,\n }\n}\n\n/**\n * Field names in an object literal a document is seeded with.\n *\n * `anchor` is a regex source locating the write; the literal's own braces are\n * matched by depth rather than `[^}]*`, because a seed can legitimately carry\n * a nested object (the host seed writes `screens: {}`) and a lazy class would\n * truncate the field list at the first inner brace — silently shrinking one of\n * the guard's sources rather than failing.\n */\nexport function seedFields(source: string, anchor: RegExp): string[] | null {\n const at = stripComments(source).search(anchor)\n if (at < 0) return null\n const text = stripComments(source)\n const open = text.indexOf('{', at)\n if (open < 0) return null\n let depth = 1\n let body = ''\n for (let index = open + 1; index < text.length; index += 1) {\n const character = text[index]\n if (character === '{') depth += 1\n else if (character === '}') {\n depth -= 1\n if (depth === 0) break\n }\n if (depth === 1) body += character\n }\n return [\n ...body.matchAll(/(?:^|,|\\n)\\s*([A-Za-z_$][A-Za-z0-9_$]*)\\s*[,:]/g),\n ].map((entry) => entry[1])\n}\n\n/**\n * Field names a document of `collection` is seeded with, in either shape a\n * seed write takes in this codebase (AGL-2100).\n *\n * The original parser understood only the CHAINED form —\n * `collection('hosts').doc(id).set({ … })` — because that is what every seed\n * route looked like when it was written. AGL-2063 rewrote the host create into\n * a transactional claim, which necessarily splits the chain: the ref has to be\n * built BEFORE `runTransaction` opens so the transaction body can both read\n * and write it, leaving `const hostRef = …doc(hostId)` in one statement and\n * `tx.set(hostRef, { … })` in another. The chained anchor then matched\n * nothing, `seedFields` returned null, and the guard threw — asserting nothing\n * about any of the four sources of the host field set until it was fixed.\n *\n * So resolve the REF BINDING rather than teaching the guard one more literal\n * spelling. Any `set`/`create` whose first argument is a ref bound to this\n * collection is a seed write, which covers `tx.`, `batch.` and a bare\n * `ref.set()` alike, and does not care what wraps them.\n *\n * Anchoring on the WRITE and not on the binding matters: the binding is\n * followed by the transaction callback's own `{`, so a binding-anchored parse\n * would happily return the arrow body's contents as the field list — a\n * silently wrong answer, which is worse than the throw.\n *\n * Returns null when neither shape is present, so the caller still throws.\n */\nexport function seedFieldsOfCollection(\n source: string,\n collection: string,\n): string[] | null {\n const name = collection.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const chained = seedFields(\n source,\n new RegExp(\n `collection\\\\('${name}'\\\\)\\\\s*\\\\.doc\\\\([^)]*\\\\)\\\\s*\\\\.\\\\s*(?:set|create)\\\\s*\\\\(`,\n ),\n )\n if (chained) return chained\n\n const text = stripComments(source)\n const bindings = [\n ...text.matchAll(\n new RegExp(\n `(?:const|let|var)\\\\s+([A-Za-z_$][A-Za-z0-9_$]*)\\\\s*=\\\\s*[^;\\\\n]*collection\\\\('${name}'\\\\)\\\\s*\\\\.doc\\\\(`,\n 'g',\n ),\n ),\n ].map((entry) => entry[1])\n\n for (const binding of bindings) {\n const fields = seedFields(\n source,\n new RegExp(\n `\\\\b(?:set|create)\\\\s*\\\\(\\\\s*${binding}\\\\s*,\\\\s*\\\\{`,\n ),\n )\n if (fields) return fields\n }\n return null\n}\n\n/**\n * Whether the property access ending at `index` is being CALLED (AGL-1719).\n *\n * The guard reads `hosts/{hostId}` fields by scanning for `host.<name>` across\n * a whole directory, which means it matches on the identifier NAME and cannot\n * see the type. `media-ref.ts` has `isFirstPartyHost(host: string)` whose body\n * is `host.toLowerCase()` — a hostname string, not the host document — so\n * `toLowerCase` entered the field universe and the guard demanded that a\n * `String.prototype` method be classified as server-owned or client-writable.\n *\n * Dropping method calls removes that whole class rather than that one name,\n * and it is sound in the only direction that matters. Firestore document data\n * is JSON: string, number, boolean, null, array, map, timestamp, geopoint,\n * reference. **No field of a document can be callable**, so `binding.X(` is\n * provably never a field read and this can never introduce a false negative —\n * which is the single failure mode a coverage guard has (AGL-1420).\n *\n * A chained read is untouched: in `host.disabledPlugins.includes(x)` the\n * character after the captured name is `.`, so `disabledPlugins` is still\n * collected and only `includes` is dropped. Optional calls (`host.foo?.()`)\n * and generic ones (`host.foo<T>()`) are calls too.\n *\n * An exclusion list of known method names was rejected: it would silence the\n * symptom, need tending forever, and still say nothing about the next method\n * on the next same-named local.\n */\nfunction isMethodCallAt(source: string, index: number): boolean {\n const rest = source.slice(index)\n return /^\\s*(?:\\?\\.)?\\s*(?:<[^<>()]*>\\s*)?\\(/.test(rest)\n}\n\n/**\n * Top-level fields of `binding` that the modules in `sources` read.\n *\n * Directory-wide on purpose. A per-file list would be one more thing to keep\n * up to date, and a NEW resolver reading a NEW field is covered the moment it\n * is written — the only way this stays true without anyone tending it.\n *\n * The document is identified by IDENTIFIER NAME, not by type — this is a text\n * scan, and it has no way to know what a local called `host` actually holds.\n * So an unrelated binding of the same name contributes its property reads too.\n * That direction is safe (a spurious field fails loudly and gets classified by\n * a human, and can never HIDE a real one), and it is deliberately left alone,\n * because the filter that would suppress it is the filter that could suppress\n * a real read. See {@link isMethodCallAt} for the one case that is not safe to\n * leave — it produced a name no human could classify.\n */\nexport function readFieldsOf(\n sources: Array<string>,\n binding: string,\n): string[] {\n const found = new Set<string>()\n for (const raw of sources) {\n const source = stripQuotedStrings(stripComments(raw))\n // `host?.field` / `host.field` — the ordinary read.\n for (const hit of source.matchAll(\n new RegExp(`\\\\b${binding}\\\\s*\\\\??\\\\.\\\\s*([A-Za-z_$][A-Za-z0-9_$]*)`, 'g'),\n )) {\n // `host.toLowerCase()` is a method INVOCATION, not a field (AGL-1719).\n if (isMethodCallAt(source, hit.index + hit[0].length)) continue\n // A lone `$` is the head of a `${…}` interpolation, not a field: it\n // comes from token-name construction like `` `{{host.${key}}}` ``.\n // Template literals are left unstripped on purpose — a real read can\n // live inside one — so this is the price, and a field named `$` cannot\n // exist. Anything else, including `$id`, is kept and must be classified.\n if (hit[1] !== '$') found.add(hit[1])\n }\n // `(host as { cname?: unknown })?.cname` — the cast a field that is real\n // but was undeclared gets read through.\n for (const hit of source.matchAll(\n new RegExp(\n `\\\\b${binding}\\\\s+as\\\\s*\\\\{\\\\s*([A-Za-z_$][A-Za-z0-9_$]*)\\\\s*\\\\??\\\\s*:`,\n 'g',\n ),\n )) {\n found.add(hit[1])\n }\n }\n return [...found].sort()\n}\n\n/**\n * Comments stripped from a TYPESCRIPT source, with string literals respected.\n *\n * `stripComments` above scans rules files, where no string ever contains a\n * comment delimiter. TypeScript sources are not that: `apps/console/app/api/\n * media/upload-url/route.ts` builds a download URL from a template literal\n * containing `https://`, and a scan that does not know it is inside a string\n * reads that `//` as a line comment and deletes the rest of the line. On a\n * guard that parses an object literal out of a route, that is not a crash —\n * it is a SHORTER field list, silently, which is the failure mode AGL-2004\n * described one level down.\n *\n * A separate function rather than a widened `stripComments`, because the two\n * inputs have genuinely different grammars and three shipped guards depend on\n * the rules-file behaviour exactly as it is. Same single left-to-right scan,\n * with quotes as a third state.\n */\nexport function stripTypeScriptComments(source: string): string {\n let out = ''\n let index = 0\n while (index < source.length) {\n const pair = source.slice(index, index + 2)\n if (pair === '/*') {\n const end = source.indexOf('*/', index + 2)\n index = end < 0 ? source.length : end + 2\n continue\n }\n if (pair === '//') {\n const end = source.indexOf('\\n', index + 2)\n if (end < 0) break\n // Keep the newline so line-oriented reasoning downstream survives.\n out += '\\n'\n index = end + 1\n continue\n }\n const character = source[index]\n if (character === \"'\" || character === '\"' || character === '`') {\n let cursor = index + 1\n while (cursor < source.length && source[cursor] !== character) {\n cursor += source[cursor] === '\\\\' ? 2 : 1\n }\n out += source.slice(index, Math.min(cursor + 1, source.length))\n index = cursor + 1\n continue\n }\n out += character\n index += 1\n }\n return out\n}\n\n/**\n * The fields of a document's universe that no partition claims.\n *\n * Unclassified means CLIENT-WRITABLE in production — the rules deny only what\n * is named — so every coverage guard reports this list and fails on any entry.\n * Shared because the documents are not all core's: the marketplace listing's\n * guard lives in the marketplace plugin beside the list it partitions, and a\n * second copy of the partition test would be a second thing to keep true.\n */\nexport function unclassifiedFields(\n universe: Iterable<string>,\n ...partitions: Array<ReadonlySet<string>>\n): string[] {\n return [...universe].filter(\n (field) => !partitions.some((partition) => partition.has(field)),\n )\n}\n\n/**\n * The fields both denied by the rules and declared client-writable (or\n * unpersisted). The two partitions disagreeing means one of them is a lie, so\n * the guards expect this to be empty.\n */\nexport function deniedAndDeclaredWritable(\n denied: ReadonlySet<string>,\n ...declared: Array<Readonly<Record<string, string>>>\n): string[] {\n return declared\n .flatMap((record) => Object.keys(record))\n .filter((field) => denied.has(field))\n}\n"],"names":["stripComments","source","out","index","length","pair","slice","end","indexOf","stripQuotedStrings","replace","normalizePathVariables","rules","topLevelBody","header","at","Error","depth","character","rawBlockBody","parseHostSubcollectionRules","rulesSource","host","catchAllHeader","occurrences","split","catchAll","listFor","operation","statement","find","entry","RegExp","test","list","match","matchAll","map","excluded","create","update","delete","dedicated","Set","serverOnly","filter","name","includes","splitTopLevelOr","expression","parts","current","push","part","trim","Boolean","hasAnyKeys","branch","allHasAnyKeys","flatMap","declaredFields","body","recursiveMatchesReaching","topLevelMatches","collection","path","segments","last","parent","startsWith","parseUpdateRule","matchHeader","clientPredicate","root","block","statements","updates","branches","found","denied","seedFields","anchor","search","text","open","seedFieldsOfCollection","chained","bindings","binding","fields","isMethodCallAt","rest","readFieldsOf","sources","raw","hit","add","sort","stripTypeScriptComments","cursor","Math","min","unclassifiedFields","universe","partitions","field","some","partition","has","deniedAndDeclaredWritable","declared","record","Object","keys"],"mappings":"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"}
|
|
@@ -22,7 +22,7 @@ export * from './definitions/property-kinds';
|
|
|
22
22
|
export * from './definitions/shared';
|
|
23
23
|
export { HOST_ERROR_SCREEN_SLOTS, HOST_UNPERSISTED_FIELDS, HostEntityType, HostRedirectParams, HostScreenStatus, HostScreenVisibility, HostViewFormat, HostViewType, } from './definitions/platform.types';
|
|
24
24
|
export { ORG_CLIENT_WRITABLE_FIELDS, ORG_UNPERSISTED_FIELDS, } from './definitions/org-billing.types';
|
|
25
|
-
export type { AglynOrgBilling, CoreOrgEntitlements, CoreOrgFeatureFlags, OrgBandwidthCap, OrgBrandingProfile, OrgCrmAssignmentRule, OrgCrmHostSettings,
|
|
25
|
+
export type { AglynOrgBilling, CoreOrgEntitlements, CoreOrgFeatureFlags, OrgBandwidthCap, OrgBrandingProfile, OrgCrmAssignmentRule, OrgCrmHostSettings, OrgCrmRoundRobin, OrgCrmSettings, OrgDiscount, OrgEntitlements, OrgFeatureFlags, OrgPlan, OrgPlanComp, OrgSeatAddons, OrgSubscription, OrgUid, } from './definitions/org-billing.types';
|
|
26
26
|
export type { AglynDocument, AglynHost, AglynHostComponent, AglynHostComponentVersion, AglynHostMedia, AglynHostMediaFolder, AglynHostTheme, AglynLayout, AglynRedirect, AglynScreen, AglynTemplate, AglynUser, ComponentDefUid, HostAnnouncementBar, HostErrorScreens, HostErrorScreenSlot, HostPopup, HostMediaUid, HostPath, HostUid, LayoutUid, LegacyNamedFieldKind, NonValueFieldKind, ProjectNumber, ProjectUid, PublishSchedule, RedirectUid, ReusableComponentIcon, ReusableComponentKind, ReusableComponentProp, ReusableComponentPropCondition, ReusableComponentPropOption, ReusableComponentPropRule, ReusableComponentPropType, ReusableComponentPropValue, ScopeToken, ScreenSlug, ScreenUid, TemplateKind, TemplatePlaceholder, TemplateSource, TemplateUid, UserUid, VersionUid, } from './definitions/platform.types';
|
|
27
27
|
export * from './constants/_internal';
|
|
28
28
|
export * from './constants/app';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/foundation/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\n// ____ _________________ ____________________ _ _______\n// / __ \\/ ____/ ____/ _/ | / / _/_ __/ _/ __ \\/ | / / ___/\n// / / / / __/ / /_ / // |/ // / / / / // / / / |/ /\\__ \\\n// / /_/ / /___/ __/ _/ // /| // / / / _/ // /_/ / /| /___/ /\n// /_____/_____/_/ /___/_/ |_/___/ /_/ /___/\\____/_/ |_//____/\n// 👇\n\nexport * from './definitions/components.types'\n// One postal address + one phone format, shared by the personal profile, the\n// org billing address and the Stripe customer (AGL-1133). The failure this\n// prevents is a phone number stored three ways in three collections.\nexport * from './definitions/contact.types'\n// Which host subcollections the media usage scan reads, and which it skips\n// with a written reason (AGL-1867). A VALUE, and exported here rather than\n// kept in the console, because the guard that keeps it equal to a repo-wide\n// sweep lives beside the other derived host-subcollection guards.\nexport * from './definitions/host-content-collections'\nexport * from './definitions/organization.types'\n// The component and layout property kinds (AGL-2893), VALUES because the\n// Properties dialog, the Attributes panel and the graft all read the same\n// table — one list per field kind, derived from `FieldComponentType`.\nexport * from './definitions/property-kinds'\nexport * from './definitions/shared'\n// `HOST_UNPERSISTED_FIELDS` is a VALUE for the same reason its org twin below\n// is: it states which `hosts/{hostId}` keys are never fields. It is exported\n// here so the write boundary can enforce that declaration at runtime\n// (AGL-1429), not only so the rules coverage guard can read it.\nexport {\n // The four error slots as a VALUE (AGL-2092). Exported because their COUNT\n // is now the bound on `kind: 'error'` exemptions (`ERROR_SCREEN_MAX_PER_HOST`)\n // as well as the console card's picker list — one list, so the pickers and\n // the bound cannot drift apart.\n HOST_ERROR_SCREEN_SLOTS,\n HOST_UNPERSISTED_FIELDS,\n HostEntityType,\n HostRedirectParams,\n HostScreenStatus,\n HostScreenVisibility,\n HostViewFormat,\n HostViewType,\n} from './definitions/platform.types'\n// AglynScreenVersion/AglynLayoutVersion are exported (specialized with the\n// SDK's NodeSchema) from ../types/screen instead of this generic form.\n// Org billing vocabulary (see definitions/org-billing.types.ts and the\n// glossary). The two ownership maps are VALUES, not types: they are the\n// declared client-writable/unpersisted partition of `orgs/{orgId}` that the\n// AGL-1355 coverage guard checks the Firestore rules against.\nexport {\n ORG_CLIENT_WRITABLE_FIELDS,\n ORG_UNPERSISTED_FIELDS,\n} from './definitions/org-billing.types'\nexport type {\n AglynOrgBilling,\n // The core halves of the two composed shapes (AGL-3124): what a plan table\n // declares exhaustively, beside the plugin half every reader gets through\n // `OrgEntitlements` / `OrgFeatureFlags`.\n CoreOrgEntitlements,\n CoreOrgFeatureFlags,\n OrgBandwidthCap,\n OrgBrandingProfile,\n OrgCrmAssignmentRule,\n OrgCrmHostSettings,\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/foundation/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\n// ____ _________________ ____________________ _ _______\n// / __ \\/ ____/ ____/ _/ | / / _/_ __/ _/ __ \\/ | / / ___/\n// / / / / __/ / /_ / // |/ // / / / / // / / / |/ /\\__ \\\n// / /_/ / /___/ __/ _/ // /| // / / / _/ // /_/ / /| /___/ /\n// /_____/_____/_/ /___/_/ |_/___/ /_/ /___/\\____/_/ |_//____/\n// 👇\n\nexport * from './definitions/components.types'\n// One postal address + one phone format, shared by the personal profile, the\n// org billing address and the Stripe customer (AGL-1133). The failure this\n// prevents is a phone number stored three ways in three collections.\nexport * from './definitions/contact.types'\n// Which host subcollections the media usage scan reads, and which it skips\n// with a written reason (AGL-1867). A VALUE, and exported here rather than\n// kept in the console, because the guard that keeps it equal to a repo-wide\n// sweep lives beside the other derived host-subcollection guards.\nexport * from './definitions/host-content-collections'\nexport * from './definitions/organization.types'\n// The component and layout property kinds (AGL-2893), VALUES because the\n// Properties dialog, the Attributes panel and the graft all read the same\n// table — one list per field kind, derived from `FieldComponentType`.\nexport * from './definitions/property-kinds'\nexport * from './definitions/shared'\n// `HOST_UNPERSISTED_FIELDS` is a VALUE for the same reason its org twin below\n// is: it states which `hosts/{hostId}` keys are never fields. It is exported\n// here so the write boundary can enforce that declaration at runtime\n// (AGL-1429), not only so the rules coverage guard can read it.\nexport {\n // The four error slots as a VALUE (AGL-2092). Exported because their COUNT\n // is now the bound on `kind: 'error'` exemptions (`ERROR_SCREEN_MAX_PER_HOST`)\n // as well as the console card's picker list — one list, so the pickers and\n // the bound cannot drift apart.\n HOST_ERROR_SCREEN_SLOTS,\n HOST_UNPERSISTED_FIELDS,\n HostEntityType,\n HostRedirectParams,\n HostScreenStatus,\n HostScreenVisibility,\n HostViewFormat,\n HostViewType,\n} from './definitions/platform.types'\n// AglynScreenVersion/AglynLayoutVersion are exported (specialized with the\n// SDK's NodeSchema) from ../types/screen instead of this generic form.\n// Org billing vocabulary (see definitions/org-billing.types.ts and the\n// glossary). The two ownership maps are VALUES, not types: they are the\n// declared client-writable/unpersisted partition of `orgs/{orgId}` that the\n// AGL-1355 coverage guard checks the Firestore rules against.\nexport {\n ORG_CLIENT_WRITABLE_FIELDS,\n ORG_UNPERSISTED_FIELDS,\n} from './definitions/org-billing.types'\nexport type {\n AglynOrgBilling,\n // The core halves of the two composed shapes (AGL-3124): what a plan table\n // declares exhaustively, beside the plugin half every reader gets through\n // `OrgEntitlements` / `OrgFeatureFlags`.\n CoreOrgEntitlements,\n CoreOrgFeatureFlags,\n OrgBandwidthCap,\n OrgBrandingProfile,\n OrgCrmAssignmentRule,\n OrgCrmHostSettings,\n OrgCrmRoundRobin,\n OrgCrmSettings,\n OrgDiscount,\n OrgEntitlements,\n OrgFeatureFlags,\n OrgPlan,\n OrgPlanComp,\n OrgSeatAddons,\n OrgSubscription,\n OrgUid,\n} from './definitions/org-billing.types'\nexport type {\n AglynDocument,\n AglynHost,\n AglynHostComponent,\n AglynHostComponentVersion,\n AglynHostMedia,\n AglynHostMediaFolder,\n AglynHostTheme,\n AglynLayout,\n AglynRedirect,\n AglynScreen,\n AglynTemplate,\n AglynUser,\n ComponentDefUid,\n HostAnnouncementBar,\n HostErrorScreens,\n HostErrorScreenSlot,\n HostPopup,\n HostMediaUid,\n HostPath,\n HostUid,\n LayoutUid,\n LegacyNamedFieldKind,\n NonValueFieldKind,\n ProjectNumber,\n ProjectUid,\n PublishSchedule,\n RedirectUid,\n ReusableComponentIcon,\n ReusableComponentKind,\n ReusableComponentProp,\n ReusableComponentPropCondition,\n ReusableComponentPropOption,\n ReusableComponentPropRule,\n ReusableComponentPropType,\n ReusableComponentPropValue,\n ScopeToken,\n ScreenSlug,\n ScreenUid,\n TemplateKind,\n TemplatePlaceholder,\n TemplateSource,\n TemplateUid,\n UserUid,\n VersionUid,\n} from './definitions/platform.types'\n\n// __________ _ ________________ _ _____________\n// / ____/ __ \\/ | / / ___/_ __/ | / | / /_ __/ ___/\n// / / / / / / |/ /\\__ \\ / / / /| | / |/ / / / \\__ \\\n// / /___/ /_/ / /| /___/ // / / ___ |/ /| / / / ___/ /\n// \\____/\\____/_/ |_//____//_/ /_/ |_/_/ |_/ /_/ /____/\n// 👇\n\nexport * from './constants/_internal'\nexport * from './constants/app'\nexport * from './constants/canvas'\nexport * from './constants/components'\nexport * from './constants/shared'\nexport * from './constants/symbol'\n"],"names":["HOST_ERROR_SCREEN_SLOTS","HOST_UNPERSISTED_FIELDS","HostEntityType","HostRedirectParams","HostScreenStatus","HostScreenVisibility","HostViewFormat","HostViewType","ORG_CLIENT_WRITABLE_FIELDS","ORG_UNPERSISTED_FIELDS"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,kEAAkE;AAClE,kEAAkE;AAClE,iEAAiE;AACjE,iEAAiE;AACjE,gEAAgE;AAChE,KAAK;AAEL,cAAc,oCAAgC;AAC9C,6EAA6E;AAC7E,2EAA2E;AAC3E,qEAAqE;AACrE,cAAc,iCAA6B;AAC3C,2EAA2E;AAC3E,2EAA2E;AAC3E,4EAA4E;AAC5E,kEAAkE;AAClE,cAAc,4CAAwC;AACtD,cAAc,sCAAkC;AAChD,yEAAyE;AACzE,0EAA0E;AAC1E,sEAAsE;AACtE,cAAc,kCAA8B;AAC5C,cAAc,0BAAsB;AACpC,8EAA8E;AAC9E,6EAA6E;AAC7E,qEAAqE;AACrE,gEAAgE;AAChE,SACE,2EAA2E;AAC3E,+EAA+E;AAC/E,2EAA2E;AAC3E,gCAAgC;AAChCA,uBAAuB,EACvBC,uBAAuB,EACvBC,cAAc,EACdC,kBAAkB,EAClBC,gBAAgB,EAChBC,oBAAoB,EACpBC,cAAc,EACdC,YAAY,QACP,kCAA8B;AACrC,2EAA2E;AAC3E,uEAAuE;AACvE,uEAAuE;AACvE,wEAAwE;AACxE,4EAA4E;AAC5E,8DAA8D;AAC9D,SACEC,0BAA0B,EAC1BC,sBAAsB,QACjB,qCAAiC;AAsExC,2DAA2D;AAC3D,2DAA2D;AAC3D,0DAA0D;AAC1D,0DAA0D;AAC1D,yDAAyD;AACzD,KAAK;AAEL,cAAc,2BAAuB;AACrC,cAAc,qBAAiB;AAC/B,cAAc,wBAAoB;AAClC,cAAc,4BAAwB;AACtC,cAAc,wBAAoB;AAClC,cAAc,wBAAoB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
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
|
+
* A DOCUMENT A PLUGIN KEEPS UNDER A SITE AND AUTHORS IN THE BESIGNER.
|
|
19
|
+
*
|
|
20
|
+
* Screens, layouts and components are the platform's own documents, and the
|
|
21
|
+
* console has an editor route for each. A plugin can keep one too — a
|
|
22
|
+
* versioned node tree under `hosts/{hostId}/{collection}/{docId}`, its
|
|
23
|
+
* working copies under `versions/{versionId}`, and a published copy on the
|
|
24
|
+
* document itself — and it gets the same editor without the console naming
|
|
25
|
+
* it: the console serves one besigner and one preview route for every
|
|
26
|
+
* declared kind, at `/{orgSlug}/hosts/{host}/{segment}/{docId}/versions/
|
|
27
|
+
* {versionId}/besigner` and `/preview`.
|
|
28
|
+
*
|
|
29
|
+
* ## Publishing belongs to the plugin
|
|
30
|
+
*
|
|
31
|
+
* The editor saves the working version itself; that is a plain node write,
|
|
32
|
+
* the same for every document. Making a version the one the site serves is
|
|
33
|
+
* not: a document can be a contract as well as a drawing, and only its
|
|
34
|
+
* plugin knows what the design owes. So the editor never writes the
|
|
35
|
+
* published copy. It POSTs `{ hostId, [idField]: docId, versionId }` to the
|
|
36
|
+
* plugin's declared `publish.path`, a server route that reads the stored
|
|
37
|
+
* version itself, refuses a design that breaks what the document promises,
|
|
38
|
+
* writes the published copy and drops the live pages that place it. A
|
|
39
|
+
* refusal answers `{ error, violations?: [{ message }] }`, and the editor
|
|
40
|
+
* shows it as {@link besignerPublishRefusal} words it.
|
|
41
|
+
*
|
|
42
|
+
* Compiled from `plugins.config.json` (`besignerDocuments`) rather than
|
|
43
|
+
* registered: the route resolves its segment on the server, in a layout that
|
|
44
|
+
* loads no plugin code, and a kind nothing had registered yet would 404 an
|
|
45
|
+
* editor link that works a second later.
|
|
46
|
+
*/
|
|
47
|
+
/** How the editor asks the plugin to publish a version. */
|
|
48
|
+
export interface BesignerDocumentPublish {
|
|
49
|
+
/** The console route that publishes, e.g. `/api/hosts/<segment>/promote`. */
|
|
50
|
+
path: string;
|
|
51
|
+
/** The body field that carries the document id. */
|
|
52
|
+
idField: string;
|
|
53
|
+
}
|
|
54
|
+
export interface BesignerDocumentDeclaration {
|
|
55
|
+
/**
|
|
56
|
+
* The kind the editor's shared machinery keys on — presence rooms, saved
|
|
57
|
+
* drafts and previews — and so a stored value: never renamed.
|
|
58
|
+
*/
|
|
59
|
+
kind: string;
|
|
60
|
+
/** The URL segment under a site, and the editor route's `[documentSegment]`. */
|
|
61
|
+
segment: string;
|
|
62
|
+
/** The subcollection under `hosts/{hostId}` its documents live in. */
|
|
63
|
+
collection: string;
|
|
64
|
+
/** What one is called in the editor's sentences, lower case: "form". */
|
|
65
|
+
noun: string;
|
|
66
|
+
publish: BesignerDocumentPublish;
|
|
67
|
+
}
|
|
68
|
+
/** A declaration with the plugin that made it. */
|
|
69
|
+
export type ResolvedBesignerDocument = BesignerDocumentDeclaration & {
|
|
70
|
+
pluginId: string;
|
|
71
|
+
};
|
|
72
|
+
/** Every declared kind, in declared order. */
|
|
73
|
+
export declare function besignerDocuments(): readonly ResolvedBesignerDocument[];
|
|
74
|
+
/** The kind served under a site's `segment`, or `null`. */
|
|
75
|
+
export declare function besignerDocumentForSegment(segment: string | undefined | null): ResolvedBesignerDocument | null;
|
|
76
|
+
/** The noun with its first letter raised, for the start of a sentence. */
|
|
77
|
+
export declare function besignerDocumentTitle(noun: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* What to tell the author when a publish is refused.
|
|
80
|
+
*
|
|
81
|
+
* The first violation in full plus a count, rather than every message
|
|
82
|
+
* joined: the messages are sentences, and a stack of six of them in one
|
|
83
|
+
* notice is read as a wall rather than as instructions. The count is what
|
|
84
|
+
* says the list does not end at the one being shown. A refusal with no
|
|
85
|
+
* violations says its `error`; one with neither says the publish failed.
|
|
86
|
+
*/
|
|
87
|
+
export declare function besignerPublishRefusal(body: unknown, noun: string): string;
|
|
88
|
+
/**
|
|
89
|
+
* Why a document cannot be published on a site that switched its plugin off.
|
|
90
|
+
*
|
|
91
|
+
* The plugin's publish route is behind the platform's per-site switch, so on
|
|
92
|
+
* such a site it would answer as if it did not exist. The editor asks the
|
|
93
|
+
* site's plugin set first and says this instead, naming the plugin the way
|
|
94
|
+
* the site's plugin settings do.
|
|
95
|
+
*/
|
|
96
|
+
export declare function besignerDocumentOffForSite(declared: ResolvedBesignerDocument): string;
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
*/ import { FIRST_PARTY_PLUGINS, PLUGIN_BESIGNER_DOCUMENTS_DECLARED } from "./first-party-plugins.generated.js";
|
|
17
|
+
/** Every declared kind, in declared order. */ export function besignerDocuments() {
|
|
18
|
+
return PLUGIN_BESIGNER_DOCUMENTS_DECLARED;
|
|
19
|
+
}
|
|
20
|
+
/** The kind served under a site's `segment`, or `null`. */ export function besignerDocumentForSegment(segment) {
|
|
21
|
+
var _PLUGIN_BESIGNER_DOCUMENTS_DECLARED_find;
|
|
22
|
+
if (!segment) return null;
|
|
23
|
+
return (_PLUGIN_BESIGNER_DOCUMENTS_DECLARED_find = PLUGIN_BESIGNER_DOCUMENTS_DECLARED.find((one)=>one.segment === segment)) != null ? _PLUGIN_BESIGNER_DOCUMENTS_DECLARED_find : null;
|
|
24
|
+
}
|
|
25
|
+
/** The noun with its first letter raised, for the start of a sentence. */ export function besignerDocumentTitle(noun) {
|
|
26
|
+
return noun ? noun.charAt(0).toUpperCase() + noun.slice(1) : noun;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* What to tell the author when a publish is refused.
|
|
30
|
+
*
|
|
31
|
+
* The first violation in full plus a count, rather than every message
|
|
32
|
+
* joined: the messages are sentences, and a stack of six of them in one
|
|
33
|
+
* notice is read as a wall rather than as instructions. The count is what
|
|
34
|
+
* says the list does not end at the one being shown. A refusal with no
|
|
35
|
+
* violations says its `error`; one with neither says the publish failed.
|
|
36
|
+
*/ export function besignerPublishRefusal(body, noun) {
|
|
37
|
+
const payload = body != null ? body : {};
|
|
38
|
+
const violations = Array.isArray(payload.violations) ? payload.violations.filter((violation)=>typeof (violation == null ? void 0 : violation.message) === 'string') : [];
|
|
39
|
+
const [first, ...rest] = violations;
|
|
40
|
+
if (first) {
|
|
41
|
+
const message = String(first.message);
|
|
42
|
+
if (!rest.length) return message;
|
|
43
|
+
return `${message} There ${rest.length === 1 ? 'is' : 'are'} ${rest.length} ` + `other problem${rest.length === 1 ? '' : 's'} to fix before this ` + `${noun} can be published.`;
|
|
44
|
+
}
|
|
45
|
+
return typeof payload.error === 'string' && payload.error ? payload.error : `The ${noun} could not be published.`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Why a document cannot be published on a site that switched its plugin off.
|
|
49
|
+
*
|
|
50
|
+
* The plugin's publish route is behind the platform's per-site switch, so on
|
|
51
|
+
* such a site it would answer as if it did not exist. The editor asks the
|
|
52
|
+
* site's plugin set first and says this instead, naming the plugin the way
|
|
53
|
+
* the site's plugin settings do.
|
|
54
|
+
*/ export function besignerDocumentOffForSite(declared) {
|
|
55
|
+
var _ref;
|
|
56
|
+
var _FIRST_PARTY_PLUGINS_find;
|
|
57
|
+
const label = (_ref = (_FIRST_PARTY_PLUGINS_find = FIRST_PARTY_PLUGINS.find((plugin)=>plugin.id === declared.pluginId)) == null ? void 0 : _FIRST_PARTY_PLUGINS_find.label) != null ? _ref : declared.pluginId;
|
|
58
|
+
return `${label} is switched off for this site, so a ${declared.noun} published ` + `here would not show on its pages. Switch ${label} back on for this site ` + `in Admin › Plugins to publish it.`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=besigner-documents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/besigner-documents.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 {\n FIRST_PARTY_PLUGINS,\n PLUGIN_BESIGNER_DOCUMENTS_DECLARED,\n} from './first-party-plugins.generated'\n\n/**\n * A DOCUMENT A PLUGIN KEEPS UNDER A SITE AND AUTHORS IN THE BESIGNER.\n *\n * Screens, layouts and components are the platform's own documents, and the\n * console has an editor route for each. A plugin can keep one too — a\n * versioned node tree under `hosts/{hostId}/{collection}/{docId}`, its\n * working copies under `versions/{versionId}`, and a published copy on the\n * document itself — and it gets the same editor without the console naming\n * it: the console serves one besigner and one preview route for every\n * declared kind, at `/{orgSlug}/hosts/{host}/{segment}/{docId}/versions/\n * {versionId}/besigner` and `/preview`.\n *\n * ## Publishing belongs to the plugin\n *\n * The editor saves the working version itself; that is a plain node write,\n * the same for every document. Making a version the one the site serves is\n * not: a document can be a contract as well as a drawing, and only its\n * plugin knows what the design owes. So the editor never writes the\n * published copy. It POSTs `{ hostId, [idField]: docId, versionId }` to the\n * plugin's declared `publish.path`, a server route that reads the stored\n * version itself, refuses a design that breaks what the document promises,\n * writes the published copy and drops the live pages that place it. A\n * refusal answers `{ error, violations?: [{ message }] }`, and the editor\n * shows it as {@link besignerPublishRefusal} words it.\n *\n * Compiled from `plugins.config.json` (`besignerDocuments`) rather than\n * registered: the route resolves its segment on the server, in a layout that\n * loads no plugin code, and a kind nothing had registered yet would 404 an\n * editor link that works a second later.\n */\n\n/** How the editor asks the plugin to publish a version. */\nexport interface BesignerDocumentPublish {\n /** The console route that publishes, e.g. `/api/hosts/<segment>/promote`. */\n path: string\n /** The body field that carries the document id. */\n idField: string\n}\n\nexport interface BesignerDocumentDeclaration {\n /**\n * The kind the editor's shared machinery keys on — presence rooms, saved\n * drafts and previews — and so a stored value: never renamed.\n */\n kind: string\n /** The URL segment under a site, and the editor route's `[documentSegment]`. */\n segment: string\n /** The subcollection under `hosts/{hostId}` its documents live in. */\n collection: string\n /** What one is called in the editor's sentences, lower case: \"form\". */\n noun: string\n publish: BesignerDocumentPublish\n}\n\n/** A declaration with the plugin that made it. */\nexport type ResolvedBesignerDocument = BesignerDocumentDeclaration & {\n pluginId: string\n}\n\n/** Every declared kind, in declared order. */\nexport function besignerDocuments(): readonly ResolvedBesignerDocument[] {\n return PLUGIN_BESIGNER_DOCUMENTS_DECLARED\n}\n\n/** The kind served under a site's `segment`, or `null`. */\nexport function besignerDocumentForSegment(\n segment: string | undefined | null,\n): ResolvedBesignerDocument | null {\n if (!segment) return null\n return (\n PLUGIN_BESIGNER_DOCUMENTS_DECLARED.find((one) => one.segment === segment) ??\n null\n )\n}\n\n/** The noun with its first letter raised, for the start of a sentence. */\nexport function besignerDocumentTitle(noun: string): string {\n return noun ? noun.charAt(0).toUpperCase() + noun.slice(1) : noun\n}\n\n/**\n * What to tell the author when a publish is refused.\n *\n * The first violation in full plus a count, rather than every message\n * joined: the messages are sentences, and a stack of six of them in one\n * notice is read as a wall rather than as instructions. The count is what\n * says the list does not end at the one being shown. A refusal with no\n * violations says its `error`; one with neither says the publish failed.\n */\nexport function besignerPublishRefusal(\n body: unknown,\n noun: string,\n): string {\n const payload = (body ?? {}) as {\n error?: unknown\n violations?: Array<{ message?: unknown }>\n }\n const violations = Array.isArray(payload.violations)\n ? payload.violations.filter(\n (violation) => typeof violation?.message === 'string',\n )\n : []\n const [first, ...rest] = violations\n if (first) {\n const message = String(first.message)\n if (!rest.length) return message\n return (\n `${message} There ${rest.length === 1 ? 'is' : 'are'} ${rest.length} ` +\n `other problem${rest.length === 1 ? '' : 's'} to fix before this ` +\n `${noun} can be published.`\n )\n }\n return typeof payload.error === 'string' && payload.error\n ? payload.error\n : `The ${noun} could not be published.`\n}\n\n/**\n * Why a document cannot be published on a site that switched its plugin off.\n *\n * The plugin's publish route is behind the platform's per-site switch, so on\n * such a site it would answer as if it did not exist. The editor asks the\n * site's plugin set first and says this instead, naming the plugin the way\n * the site's plugin settings do.\n */\nexport function besignerDocumentOffForSite(\n declared: ResolvedBesignerDocument,\n): string {\n const label =\n FIRST_PARTY_PLUGINS.find((plugin) => plugin.id === declared.pluginId)\n ?.label ?? declared.pluginId\n return (\n `${label} is switched off for this site, so a ${declared.noun} published ` +\n `here would not show on its pages. Switch ${label} back on for this site ` +\n `in Admin › Plugins to publish it.`\n )\n}\n"],"names":["FIRST_PARTY_PLUGINS","PLUGIN_BESIGNER_DOCUMENTS_DECLARED","besignerDocuments","besignerDocumentForSegment","segment","find","one","besignerDocumentTitle","noun","charAt","toUpperCase","slice","besignerPublishRefusal","body","payload","violations","Array","isArray","filter","violation","message","first","rest","String","length","error","besignerDocumentOffForSite","declared","label","plugin","id","pluginId"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,mBAAmB,EACnBC,kCAAkC,QAC7B,qCAAiC;AA6DxC,4CAA4C,GAC5C,OAAO,SAASC;IACd,OAAOD;AACT;AAEA,yDAAyD,GACzD,OAAO,SAASE,2BACdC,OAAkC;QAIhCH;IAFF,IAAI,CAACG,SAAS,OAAO;IACrB,QACEH,2CAAAA,mCAAmCI,IAAI,CAAC,CAACC,MAAQA,IAAIF,OAAO,KAAKA,oBAAjEH,2CACA;AAEJ;AAEA,wEAAwE,GACxE,OAAO,SAASM,sBAAsBC,IAAY;IAChD,OAAOA,OAAOA,KAAKC,MAAM,CAAC,GAAGC,WAAW,KAAKF,KAAKG,KAAK,CAAC,KAAKH;AAC/D;AAEA;;;;;;;;CAQC,GACD,OAAO,SAASI,uBACdC,IAAa,EACbL,IAAY;IAEZ,MAAMM,UAAWD,eAAAA,OAAQ,CAAC;IAI1B,MAAME,aAAaC,MAAMC,OAAO,CAACH,QAAQC,UAAU,IAC/CD,QAAQC,UAAU,CAACG,MAAM,CACvB,CAACC,YAAc,QAAOA,6BAAAA,UAAWC,OAAO,MAAK,YAE/C,EAAE;IACN,MAAM,CAACC,OAAO,GAAGC,KAAK,GAAGP;IACzB,IAAIM,OAAO;QACT,MAAMD,UAAUG,OAAOF,MAAMD,OAAO;QACpC,IAAI,CAACE,KAAKE,MAAM,EAAE,OAAOJ;QACzB,OACE,GAAGA,QAAQ,OAAO,EAAEE,KAAKE,MAAM,KAAK,IAAI,OAAO,MAAM,CAAC,EAAEF,KAAKE,MAAM,CAAC,CAAC,CAAC,GACtE,CAAC,aAAa,EAAEF,KAAKE,MAAM,KAAK,IAAI,KAAK,IAAI,oBAAoB,CAAC,GAClE,GAAGhB,KAAK,kBAAkB,CAAC;IAE/B;IACA,OAAO,OAAOM,QAAQW,KAAK,KAAK,YAAYX,QAAQW,KAAK,GACrDX,QAAQW,KAAK,GACb,CAAC,IAAI,EAAEjB,KAAK,wBAAwB,CAAC;AAC3C;AAEA;;;;;;;CAOC,GACD,OAAO,SAASkB,2BACdC,QAAkC;;QAGhC3B;IADF,MAAM4B,iBACJ5B,4BAAAA,oBAAoBK,IAAI,CAAC,CAACwB,SAAWA,OAAOC,EAAE,KAAKH,SAASI,QAAQ,sBAApE/B,0BACI4B,KAAK,mBAAID,SAASI,QAAQ;IAChC,OACE,GAAGH,MAAM,qCAAqC,EAAED,SAASnB,IAAI,CAAC,WAAW,CAAC,GAC1E,CAAC,yCAAyC,EAAEoB,MAAM,uBAAuB,CAAC,GAC1E,CAAC,iCAAiC,CAAC;AAEvC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { HostFunction } from '../app-utils/functions';
|
|
18
|
+
import type { HostVariable } from '../app-utils/variables';
|
|
19
|
+
/**
|
|
20
|
+
* A SITE VARIABLE WHOSE VALUE A PLUGIN COMPUTES when a page is composed.
|
|
21
|
+
*
|
|
22
|
+
* A site variable is the platform's: a typed value a page binds with
|
|
23
|
+
* `{{var:id}}`, resolved by the tenant's compose pipeline. Some variables are
|
|
24
|
+
* COMPUTED — their stored value is a fallback, and a record a plugin keeps
|
|
25
|
+
* produces the value the page shows (a workflow's result, AGL-129). Where
|
|
26
|
+
* that value comes from is the plugin's: its storage, the reference the
|
|
27
|
+
* variable carries, and how the record runs. The compose pipeline used to
|
|
28
|
+
* read the workflows plugin's collection and run its workflows itself.
|
|
29
|
+
*
|
|
30
|
+
* So a plugin that computes variables registers a VARIABLE COMPUTER, in two
|
|
31
|
+
* halves, because the page's reads are issued together before any of them is
|
|
32
|
+
* awaited (AGL-1428): `prepare(hostId)` starts whatever the computation reads
|
|
33
|
+
* and is issued beside the site's variables and functions; it resolves to a
|
|
34
|
+
* computation the pipeline applies once those are in hand.
|
|
35
|
+
*
|
|
36
|
+
* ## Failing open, as a missing record always has
|
|
37
|
+
*
|
|
38
|
+
* A computer that throws, or none registered, leaves every variable its
|
|
39
|
+
* stored value — the fallback a computed variable has always shown when its
|
|
40
|
+
* record was missing or its run failed. A page never fails to render because
|
|
41
|
+
* a value could not be computed. With none registered the app's declarations
|
|
42
|
+
* step is offered one more run first (`plugin-declarations-repair`), so a
|
|
43
|
+
* boot that lost a computer is repaired rather than published as fallbacks;
|
|
44
|
+
* the step memoizes itself, so this costs one attempt per process.
|
|
45
|
+
*/
|
|
46
|
+
/** What a computation is handed, keyed as the compose pipeline holds them. */
|
|
47
|
+
export interface VariableComputationInput {
|
|
48
|
+
variables: Record<string, HostVariable>;
|
|
49
|
+
functions: Record<string, HostFunction>;
|
|
50
|
+
}
|
|
51
|
+
/** The variables with the computed ones' values filled in; the rest unchanged. */
|
|
52
|
+
export type VariableComputation = (input: VariableComputationInput) => Record<string, HostVariable>;
|
|
53
|
+
export interface VariableComputer {
|
|
54
|
+
/** Starts reading what computing one site's variables needs; resolves to the computation. */
|
|
55
|
+
prepare(hostId: string): Promise<VariableComputation>;
|
|
56
|
+
}
|
|
57
|
+
export declare const VARIABLE_COMPUTERS: import("./plugin-services").PluginServiceContract<VariableComputer>;
|
|
58
|
+
/**
|
|
59
|
+
* Registers a plugin's variable computer. The owner is the loader's marker
|
|
60
|
+
* when a register fn is running, else `options.pluginId`; with neither the
|
|
61
|
+
* registration throws. Registering again replaces the plugin's own.
|
|
62
|
+
*/
|
|
63
|
+
export declare function registerVariableComputer(computer: VariableComputer, options?: {
|
|
64
|
+
pluginId?: string;
|
|
65
|
+
}): void;
|
|
66
|
+
/**
|
|
67
|
+
* Starts every registered computer for one site and resolves to their
|
|
68
|
+
* computations applied in registration order. A computer that fails to
|
|
69
|
+
* prepare, or whose computation throws, leaves the variables as they were.
|
|
70
|
+
*/
|
|
71
|
+
export declare function prepareComputedVariables(hostId: string): Promise<VariableComputation>;
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
*/ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
17
|
+
import { getRegisteringPluginId } from "../app-utils/registering-plugin.js";
|
|
18
|
+
import { runPluginDeclarationsRepair } from "./plugin-declarations-repair.js";
|
|
19
|
+
import { definePluginServiceContract, registerPluginService, resolvePluginServices } from "./plugin-services.js";
|
|
20
|
+
export const VARIABLE_COMPUTERS = definePluginServiceContract('core.variable-computer', {
|
|
21
|
+
multiple: true
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Registers a plugin's variable computer. The owner is the loader's marker
|
|
25
|
+
* when a register fn is running, else `options.pluginId`; with neither the
|
|
26
|
+
* registration throws. Registering again replaces the plugin's own.
|
|
27
|
+
*/ export function registerVariableComputer(computer, options) {
|
|
28
|
+
var _ref, _getRegisteringPluginId;
|
|
29
|
+
const pluginId = ((_ref = (_getRegisteringPluginId = getRegisteringPluginId()) != null ? _getRegisteringPluginId : options == null ? void 0 : options.pluginId) != null ? _ref : '').trim();
|
|
30
|
+
if (!pluginId) throw new Error('a variable computer was registered with no owner');
|
|
31
|
+
registerPluginService(VARIABLE_COMPUTERS, computer, {
|
|
32
|
+
pluginId
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const unchanged = ({ variables })=>variables;
|
|
36
|
+
/**
|
|
37
|
+
* Starts every registered computer for one site and resolves to their
|
|
38
|
+
* computations applied in registration order. A computer that fails to
|
|
39
|
+
* prepare, or whose computation throws, leaves the variables as they were.
|
|
40
|
+
*/ export async function prepareComputedVariables(hostId) {
|
|
41
|
+
let computers = resolvePluginServices(VARIABLE_COMPUTERS);
|
|
42
|
+
if (!computers.length) {
|
|
43
|
+
try {
|
|
44
|
+
if (await runPluginDeclarationsRepair()) computers = resolvePluginServices(VARIABLE_COMPUTERS);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error('[computed-variables] the declarations repair failed', error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (!computers.length) return unchanged;
|
|
50
|
+
const prepared = await Promise.all(computers.map(async ({ pluginId, impl })=>{
|
|
51
|
+
try {
|
|
52
|
+
return {
|
|
53
|
+
pluginId,
|
|
54
|
+
compute: await impl.prepare(hostId)
|
|
55
|
+
};
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(`variable computer of "${pluginId}" failed to prepare`, error);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}));
|
|
61
|
+
return (input)=>prepared.reduce((variables, entry)=>{
|
|
62
|
+
if (!entry) return variables;
|
|
63
|
+
try {
|
|
64
|
+
return entry.compute(_extends({}, input, {
|
|
65
|
+
variables
|
|
66
|
+
}));
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.error(`variable computer of "${entry.pluginId}" failed`, error);
|
|
69
|
+
return variables;
|
|
70
|
+
}
|
|
71
|
+
}, input.variables);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=computed-variables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/computed-variables.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 type { HostFunction } from '../app-utils/functions'\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport type { HostVariable } from '../app-utils/variables'\nimport { runPluginDeclarationsRepair } from './plugin-declarations-repair'\nimport {\n definePluginServiceContract,\n registerPluginService,\n resolvePluginServices,\n} from './plugin-services'\n\n/**\n * A SITE VARIABLE WHOSE VALUE A PLUGIN COMPUTES when a page is composed.\n *\n * A site variable is the platform's: a typed value a page binds with\n * `{{var:id}}`, resolved by the tenant's compose pipeline. Some variables are\n * COMPUTED — their stored value is a fallback, and a record a plugin keeps\n * produces the value the page shows (a workflow's result, AGL-129). Where\n * that value comes from is the plugin's: its storage, the reference the\n * variable carries, and how the record runs. The compose pipeline used to\n * read the workflows plugin's collection and run its workflows itself.\n *\n * So a plugin that computes variables registers a VARIABLE COMPUTER, in two\n * halves, because the page's reads are issued together before any of them is\n * awaited (AGL-1428): `prepare(hostId)` starts whatever the computation reads\n * and is issued beside the site's variables and functions; it resolves to a\n * computation the pipeline applies once those are in hand.\n *\n * ## Failing open, as a missing record always has\n *\n * A computer that throws, or none registered, leaves every variable its\n * stored value — the fallback a computed variable has always shown when its\n * record was missing or its run failed. A page never fails to render because\n * a value could not be computed. With none registered the app's declarations\n * step is offered one more run first (`plugin-declarations-repair`), so a\n * boot that lost a computer is repaired rather than published as fallbacks;\n * the step memoizes itself, so this costs one attempt per process.\n */\n\n/** What a computation is handed, keyed as the compose pipeline holds them. */\nexport interface VariableComputationInput {\n variables: Record<string, HostVariable>\n functions: Record<string, HostFunction>\n}\n\n/** The variables with the computed ones' values filled in; the rest unchanged. */\nexport type VariableComputation = (\n input: VariableComputationInput,\n) => Record<string, HostVariable>\n\nexport interface VariableComputer {\n /** Starts reading what computing one site's variables needs; resolves to the computation. */\n prepare(hostId: string): Promise<VariableComputation>\n}\n\nexport const VARIABLE_COMPUTERS = definePluginServiceContract<VariableComputer>(\n 'core.variable-computer',\n { multiple: true },\n)\n\n/**\n * Registers a plugin's variable computer. The owner is the loader's marker\n * when a register fn is running, else `options.pluginId`; with neither the\n * registration throws. Registering again replaces the plugin's own.\n */\nexport function registerVariableComputer(\n computer: VariableComputer,\n options?: { pluginId?: string },\n): void {\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n if (!pluginId) throw new Error('a variable computer was registered with no owner')\n registerPluginService(VARIABLE_COMPUTERS, computer, { pluginId })\n}\n\nconst unchanged: VariableComputation = ({ variables }) => variables\n\n/**\n * Starts every registered computer for one site and resolves to their\n * computations applied in registration order. A computer that fails to\n * prepare, or whose computation throws, leaves the variables as they were.\n */\nexport async function prepareComputedVariables(hostId: string): Promise<VariableComputation> {\n let computers = resolvePluginServices(VARIABLE_COMPUTERS)\n if (!computers.length) {\n try {\n if (await runPluginDeclarationsRepair()) computers = resolvePluginServices(VARIABLE_COMPUTERS)\n } catch (error) {\n console.error('[computed-variables] the declarations repair failed', error)\n }\n }\n if (!computers.length) return unchanged\n const prepared = await Promise.all(\n computers.map(async ({ pluginId, impl }) => {\n try {\n return { pluginId, compute: await impl.prepare(hostId) }\n } catch (error) {\n console.error(`variable computer of \"${pluginId}\" failed to prepare`, error)\n return null\n }\n }),\n )\n return (input) =>\n prepared.reduce((variables, entry) => {\n if (!entry) return variables\n try {\n return entry.compute({ ...input, variables })\n } catch (error) {\n console.error(`variable computer of \"${entry.pluginId}\" failed`, error)\n return variables\n }\n }, input.variables)\n}\n"],"names":["getRegisteringPluginId","runPluginDeclarationsRepair","definePluginServiceContract","registerPluginService","resolvePluginServices","VARIABLE_COMPUTERS","multiple","registerVariableComputer","computer","options","pluginId","trim","Error","unchanged","variables","prepareComputedVariables","hostId","computers","length","error","console","prepared","Promise","all","map","impl","compute","prepare","input","reduce","entry"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC;AAGD,SAASA,sBAAsB,QAAQ,qCAAiC;AAExE,SAASC,2BAA2B,QAAQ,kCAA8B;AAC1E,SACEC,2BAA2B,EAC3BC,qBAAqB,EACrBC,qBAAqB,QAChB,uBAAmB;AA8C1B,OAAO,MAAMC,qBAAqBH,4BAChC,0BACA;IAAEI,UAAU;AAAK,GAClB;AAED;;;;CAIC,GACD,OAAO,SAASC,yBACdC,QAA0B,EAC1BC,OAA+B;QAEbT,MAAAA;IAAlB,MAAMU,WAAW,EAACV,QAAAA,0BAAAA,oCAAAA,0BAA4BS,2BAAAA,QAASC,QAAQ,YAA7CV,OAAiD,IAAIW,IAAI;IAC3E,IAAI,CAACD,UAAU,MAAM,IAAIE,MAAM;IAC/BT,sBAAsBE,oBAAoBG,UAAU;QAAEE;IAAS;AACjE;AAEA,MAAMG,YAAiC,CAAC,EAAEC,SAAS,EAAE,GAAKA;AAE1D;;;;CAIC,GACD,OAAO,eAAeC,yBAAyBC,MAAc;IAC3D,IAAIC,YAAYb,sBAAsBC;IACtC,IAAI,CAACY,UAAUC,MAAM,EAAE;QACrB,IAAI;YACF,IAAI,MAAMjB,+BAA+BgB,YAAYb,sBAAsBC;QAC7E,EAAE,OAAOc,OAAO;YACdC,QAAQD,KAAK,CAAC,uDAAuDA;QACvE;IACF;IACA,IAAI,CAACF,UAAUC,MAAM,EAAE,OAAOL;IAC9B,MAAMQ,WAAW,MAAMC,QAAQC,GAAG,CAChCN,UAAUO,GAAG,CAAC,OAAO,EAAEd,QAAQ,EAAEe,IAAI,EAAE;QACrC,IAAI;YACF,OAAO;gBAAEf;gBAAUgB,SAAS,MAAMD,KAAKE,OAAO,CAACX;YAAQ;QACzD,EAAE,OAAOG,OAAO;YACdC,QAAQD,KAAK,CAAC,CAAC,sBAAsB,EAAET,SAAS,mBAAmB,CAAC,EAAES;YACtE,OAAO;QACT;IACF;IAEF,OAAO,CAACS,QACNP,SAASQ,MAAM,CAAC,CAACf,WAAWgB;YAC1B,IAAI,CAACA,OAAO,OAAOhB;YACnB,IAAI;gBACF,OAAOgB,MAAMJ,OAAO,CAAC,aAAKE;oBAAOd;;YACnC,EAAE,OAAOK,OAAO;gBACdC,QAAQD,KAAK,CAAC,CAAC,sBAAsB,EAAEW,MAAMpB,QAAQ,CAAC,QAAQ,CAAC,EAAES;gBACjE,OAAOL;YACT;QACF,GAAGc,MAAMd,SAAS;AACtB"}
|