@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
|
@@ -0,0 +1,144 @@
|
|
|
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
|
+
* WHERE A FORM'S SUBMISSION IS ALSO SAVED AS A RECORD (AGL-3080).
|
|
19
|
+
*
|
|
20
|
+
* A form on a published page can file every submission as a record another
|
|
21
|
+
* plugin keeps — a row in a dataset, today. The form is one plugin's element
|
|
22
|
+
* and the record is another plugin's storage, so neither may know the other:
|
|
23
|
+
* this is the contract between them, and core names neither the target nor
|
|
24
|
+
* where it keeps anything.
|
|
25
|
+
*
|
|
26
|
+
* It has two halves, because the decision of where a record lands must be
|
|
27
|
+
* made where the visitor cannot reach it:
|
|
28
|
+
*
|
|
29
|
+
* 1. {@link stampFormRecordTargets} — the page's composition hands the target
|
|
30
|
+
* the tree it is about to ship, and the target stamps each form it will
|
|
31
|
+
* write for with whatever it needs to trust at submit time (a signed
|
|
32
|
+
* binding). The submit route is public and unauthenticated, so nothing
|
|
33
|
+
* the body says on its own may choose a destination.
|
|
34
|
+
* 2. {@link writeFormRecordTarget} — the submit route hands the target the
|
|
35
|
+
* submission as posted, after the submission itself is stored. The target
|
|
36
|
+
* reads back what it stamped, writes the record or refuses it, and answers
|
|
37
|
+
* what to note on the submission (`routing`) so the Inbox can say where it
|
|
38
|
+
* went or why it did not.
|
|
39
|
+
*
|
|
40
|
+
* ## Declared, then registered — and an absent target is loud
|
|
41
|
+
*
|
|
42
|
+
* The target registers from its plugin's `serverDeclarations` entry, which
|
|
43
|
+
* every app runs at boot, and also DECLARES itself in `plugins.config.json`
|
|
44
|
+
* (`formRecordTarget`), compiled into core. A registry alone would read a
|
|
45
|
+
* failed boot as "no form writes anywhere", and every bound form would keep
|
|
46
|
+
* accepting submissions while its records quietly stopped — the AGL-3025
|
|
47
|
+
* shape. With the declaration the three cases are distinct:
|
|
48
|
+
*
|
|
49
|
+
* - nothing declared — this deployment ships no plugin that keeps records; no
|
|
50
|
+
* form is stamped and no submission writes one, which is a real answer;
|
|
51
|
+
* - declared and registered — the target answers;
|
|
52
|
+
* - declared and NOT registered — the app's declarations step runs again. If
|
|
53
|
+
* the target is still missing, a page carrying a form THROWS at render (the
|
|
54
|
+
* cache keeps the last good page, and the logs are red), and a submission
|
|
55
|
+
* is kept — the Inbox copy is written before this is asked — with the
|
|
56
|
+
* failure logged and noted on it under `routing.recordTargetUnavailable`.
|
|
57
|
+
*
|
|
58
|
+
* Server-only, and reached by path, never through a barrel.
|
|
59
|
+
*/
|
|
60
|
+
/** One submission, as the route stored it. */
|
|
61
|
+
export interface FormRecordWriteRequest {
|
|
62
|
+
/** The site the form was submitted on. */
|
|
63
|
+
hostId: string;
|
|
64
|
+
/** The organization that owns the site, when it has one. */
|
|
65
|
+
orgId: string | null;
|
|
66
|
+
/** The organization's billing document — the entitlements a write is held to. */
|
|
67
|
+
orgBilling: unknown;
|
|
68
|
+
/**
|
|
69
|
+
* The request body as posted. The target reads back only what it stamped
|
|
70
|
+
* onto the form, and must trust nothing else in it.
|
|
71
|
+
*/
|
|
72
|
+
body: Readonly<Record<string, unknown>>;
|
|
73
|
+
/** The submitted values, sanitized, keyed by the name each field submits under. */
|
|
74
|
+
fields: Readonly<Record<string, string>>;
|
|
75
|
+
}
|
|
76
|
+
/** What a target answers for one submission. */
|
|
77
|
+
export interface FormRecordWriteOutcome {
|
|
78
|
+
/**
|
|
79
|
+
* Written as the stored submission's `routing` when present: where the
|
|
80
|
+
* record went, or why it was refused. Absent when the form writes nowhere.
|
|
81
|
+
*/
|
|
82
|
+
routing?: Record<string, unknown>;
|
|
83
|
+
}
|
|
84
|
+
/** A plugin that keeps the records forms may file into. */
|
|
85
|
+
export interface FormRecordTarget {
|
|
86
|
+
/**
|
|
87
|
+
* Stamps each form in a composed tree this target will write for. Never
|
|
88
|
+
* mutates `nodes`, and answers the same object when it stamps nothing.
|
|
89
|
+
*/
|
|
90
|
+
stamp<N extends Record<string, unknown>>(nodes: N, hostId: string): Promise<N>;
|
|
91
|
+
/**
|
|
92
|
+
* Writes one submission's record, or refuses it. Never rejects: a record
|
|
93
|
+
* that cannot be written is no reason to fail a submission already stored.
|
|
94
|
+
*/
|
|
95
|
+
write(request: FormRecordWriteRequest): Promise<FormRecordWriteOutcome>;
|
|
96
|
+
}
|
|
97
|
+
/** The compiled declaration: which plugin keeps the records forms file into. */
|
|
98
|
+
export interface FormRecordTargetDeclaration {
|
|
99
|
+
pluginId: string;
|
|
100
|
+
id: string;
|
|
101
|
+
}
|
|
102
|
+
/** The plugin declared as the forms' record target, or `null` when none is. */
|
|
103
|
+
export declare function declaredFormRecordTarget(): FormRecordTargetDeclaration | null;
|
|
104
|
+
interface RegisteredTarget {
|
|
105
|
+
pluginId: string;
|
|
106
|
+
target: FormRecordTarget;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Registers the target. The owner is the plugin whose register fn is running,
|
|
110
|
+
* or the `pluginId` passed for a boot declaration; with neither, or from a
|
|
111
|
+
* plugin other than the one declared, it throws. The same plugin registering
|
|
112
|
+
* again replaces its target. Returns the unregister.
|
|
113
|
+
*/
|
|
114
|
+
export declare function registerFormRecordTarget(target: FormRecordTarget, options?: {
|
|
115
|
+
pluginId?: string;
|
|
116
|
+
}): () => void;
|
|
117
|
+
/** The registered target with its owner, or `null`. */
|
|
118
|
+
export declare function formRecordTarget(): RegisteredTarget | null;
|
|
119
|
+
/** Only for specs: forgets the registered target. */
|
|
120
|
+
export declare function resetFormRecordTargetForTests(): void;
|
|
121
|
+
/**
|
|
122
|
+
* The declared target's registration was not found, even after the app's
|
|
123
|
+
* declarations step ran again.
|
|
124
|
+
*/
|
|
125
|
+
export declare class FormRecordTargetUnavailableError extends Error {
|
|
126
|
+
readonly declared: FormRecordTargetDeclaration;
|
|
127
|
+
constructor(declared: FormRecordTargetDeclaration);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The tree a page ships, with each form the target writes for stamped.
|
|
131
|
+
*
|
|
132
|
+
* A tree with no form asks nobody and comes back as the same object. A tree
|
|
133
|
+
* with one THROWS when the declared target is missing — see the module note.
|
|
134
|
+
*/
|
|
135
|
+
export declare function stampFormRecordTargets<N extends Record<string, unknown>>(nodes: N, hostId: string): Promise<N>;
|
|
136
|
+
/**
|
|
137
|
+
* Files one stored submission as a record where the page's form said to.
|
|
138
|
+
*
|
|
139
|
+
* Never rejects. With no target declared it answers nothing; with the declared
|
|
140
|
+
* target missing it logs the failure and answers a `routing` note saying so,
|
|
141
|
+
* because the submission is already kept and losing it now would be worse.
|
|
142
|
+
*/
|
|
143
|
+
export declare function writeFormRecordTarget(request: FormRecordWriteRequest): Promise<FormRecordWriteOutcome>;
|
|
144
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
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 { getRegisteringPluginId } from "../app-utils/registering-plugin.js";
|
|
17
|
+
import { FORM_COMPONENT_ID } from "../app-utils/forms.js";
|
|
18
|
+
import { PLUGIN_FORM_RECORD_TARGET_DECLARED } from "./first-party-plugins.generated.js";
|
|
19
|
+
import { runPluginDeclarationsRepair } from "./plugin-declarations-repair.js";
|
|
20
|
+
/** The plugin declared as the forms' record target, or `null` when none is. */ export function declaredFormRecordTarget() {
|
|
21
|
+
return PLUGIN_FORM_RECORD_TARGET_DECLARED;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One slot per process, on `globalThis` (AGL-3412): the app registers from
|
|
25
|
+
* `instrumentation.ts`, which Next compiles apart from the routes that read.
|
|
26
|
+
*/ const TARGET_KEY = Symbol.for('@aglyn/aglyn:submission-record-target');
|
|
27
|
+
const globalScope = globalThis;
|
|
28
|
+
/**
|
|
29
|
+
* Registers the target. The owner is the plugin whose register fn is running,
|
|
30
|
+
* or the `pluginId` passed for a boot declaration; with neither, or from a
|
|
31
|
+
* plugin other than the one declared, it throws. The same plugin registering
|
|
32
|
+
* again replaces its target. Returns the unregister.
|
|
33
|
+
*/ export function registerFormRecordTarget(target, options) {
|
|
34
|
+
var _ref, _getRegisteringPluginId;
|
|
35
|
+
const pluginId = ((_ref = (_getRegisteringPluginId = getRegisteringPluginId()) != null ? _getRegisteringPluginId : options == null ? void 0 : options.pluginId) != null ? _ref : '').trim();
|
|
36
|
+
if (!pluginId) {
|
|
37
|
+
throw new Error('the form record target was registered with no owner: pass ' + '{ pluginId } when registering outside a plugin register fn');
|
|
38
|
+
}
|
|
39
|
+
const declared = declaredFormRecordTarget();
|
|
40
|
+
if (declared && declared.pluginId !== pluginId) {
|
|
41
|
+
throw new Error(`the form record target is declared by "${declared.pluginId}"; ` + `refused "${pluginId}"`);
|
|
42
|
+
}
|
|
43
|
+
const held = globalScope[TARGET_KEY];
|
|
44
|
+
if (held && held.pluginId !== pluginId) {
|
|
45
|
+
throw new Error(`the form record target is already registered by "${held.pluginId}"; ` + `refused "${pluginId}"`);
|
|
46
|
+
}
|
|
47
|
+
const entry = {
|
|
48
|
+
pluginId,
|
|
49
|
+
target
|
|
50
|
+
};
|
|
51
|
+
globalScope[TARGET_KEY] = entry;
|
|
52
|
+
return ()=>{
|
|
53
|
+
if (globalScope[TARGET_KEY] === entry) globalScope[TARGET_KEY] = null;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** The registered target with its owner, or `null`. */ export function formRecordTarget() {
|
|
57
|
+
var _globalScope_TARGET_KEY;
|
|
58
|
+
return (_globalScope_TARGET_KEY = globalScope[TARGET_KEY]) != null ? _globalScope_TARGET_KEY : null;
|
|
59
|
+
}
|
|
60
|
+
/** Only for specs: forgets the registered target. */ export function resetFormRecordTargetForTests() {
|
|
61
|
+
globalScope[TARGET_KEY] = null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The declared target's registration was not found, even after the app's
|
|
65
|
+
* declarations step ran again.
|
|
66
|
+
*/ export class FormRecordTargetUnavailableError extends Error {
|
|
67
|
+
constructor(declared){
|
|
68
|
+
super(`the form record target is declared by "${declared.pluginId}" but none ` + 'is registered in this process — its server declarations did not run. ' + 'Refusing to treat bound forms as writing nowhere.'), this.declared = declared;
|
|
69
|
+
this.name = 'FormRecordTargetUnavailableError';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** The declared target, repaired once if missing; `null` when none is declared. */ async function requireDeclaredTarget() {
|
|
73
|
+
const declared = declaredFormRecordTarget();
|
|
74
|
+
if (!declared) return null;
|
|
75
|
+
let registered = formRecordTarget();
|
|
76
|
+
if (!registered) {
|
|
77
|
+
try {
|
|
78
|
+
await runPluginDeclarationsRepair();
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('[submission-record-target] the declarations repair failed', error);
|
|
81
|
+
}
|
|
82
|
+
registered = formRecordTarget();
|
|
83
|
+
}
|
|
84
|
+
if (!registered) throw new FormRecordTargetUnavailableError(declared);
|
|
85
|
+
return registered.target;
|
|
86
|
+
}
|
|
87
|
+
const placesAForm = (nodes)=>Object.values(nodes).some((node)=>(node == null ? void 0 : node.componentId) === FORM_COMPONENT_ID);
|
|
88
|
+
/**
|
|
89
|
+
* The tree a page ships, with each form the target writes for stamped.
|
|
90
|
+
*
|
|
91
|
+
* A tree with no form asks nobody and comes back as the same object. A tree
|
|
92
|
+
* with one THROWS when the declared target is missing — see the module note.
|
|
93
|
+
*/ export async function stampFormRecordTargets(nodes, hostId) {
|
|
94
|
+
if (!placesAForm(nodes)) return nodes;
|
|
95
|
+
const target = await requireDeclaredTarget();
|
|
96
|
+
return target ? target.stamp(nodes, hostId) : nodes;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Files one stored submission as a record where the page's form said to.
|
|
100
|
+
*
|
|
101
|
+
* Never rejects. With no target declared it answers nothing; with the declared
|
|
102
|
+
* target missing it logs the failure and answers a `routing` note saying so,
|
|
103
|
+
* because the submission is already kept and losing it now would be worse.
|
|
104
|
+
*/ export async function writeFormRecordTarget(request) {
|
|
105
|
+
let target;
|
|
106
|
+
try {
|
|
107
|
+
target = await requireDeclaredTarget();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('[submission-record-target] a submission could not be filed', error);
|
|
110
|
+
return {
|
|
111
|
+
routing: {
|
|
112
|
+
recordTargetUnavailable: true
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (!target) return {};
|
|
117
|
+
try {
|
|
118
|
+
return await target.write(request);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('[submission-record-target] the target failed a write', error);
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=submission-record-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/submission-record-target.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport { FORM_COMPONENT_ID } from '../app-utils/forms'\nimport { PLUGIN_FORM_RECORD_TARGET_DECLARED } from './first-party-plugins.generated'\nimport { runPluginDeclarationsRepair } from './plugin-declarations-repair'\n\n/**\n * WHERE A FORM'S SUBMISSION IS ALSO SAVED AS A RECORD (AGL-3080).\n *\n * A form on a published page can file every submission as a record another\n * plugin keeps — a row in a dataset, today. The form is one plugin's element\n * and the record is another plugin's storage, so neither may know the other:\n * this is the contract between them, and core names neither the target nor\n * where it keeps anything.\n *\n * It has two halves, because the decision of where a record lands must be\n * made where the visitor cannot reach it:\n *\n * 1. {@link stampFormRecordTargets} — the page's composition hands the target\n * the tree it is about to ship, and the target stamps each form it will\n * write for with whatever it needs to trust at submit time (a signed\n * binding). The submit route is public and unauthenticated, so nothing\n * the body says on its own may choose a destination.\n * 2. {@link writeFormRecordTarget} — the submit route hands the target the\n * submission as posted, after the submission itself is stored. The target\n * reads back what it stamped, writes the record or refuses it, and answers\n * what to note on the submission (`routing`) so the Inbox can say where it\n * went or why it did not.\n *\n * ## Declared, then registered — and an absent target is loud\n *\n * The target registers from its plugin's `serverDeclarations` entry, which\n * every app runs at boot, and also DECLARES itself in `plugins.config.json`\n * (`formRecordTarget`), compiled into core. A registry alone would read a\n * failed boot as \"no form writes anywhere\", and every bound form would keep\n * accepting submissions while its records quietly stopped — the AGL-3025\n * shape. With the declaration the three cases are distinct:\n *\n * - nothing declared — this deployment ships no plugin that keeps records; no\n * form is stamped and no submission writes one, which is a real answer;\n * - declared and registered — the target answers;\n * - declared and NOT registered — the app's declarations step runs again. If\n * the target is still missing, a page carrying a form THROWS at render (the\n * cache keeps the last good page, and the logs are red), and a submission\n * is kept — the Inbox copy is written before this is asked — with the\n * failure logged and noted on it under `routing.recordTargetUnavailable`.\n *\n * Server-only, and reached by path, never through a barrel.\n */\n\n/** One submission, as the route stored it. */\nexport interface FormRecordWriteRequest {\n /** The site the form was submitted on. */\n hostId: string\n /** The organization that owns the site, when it has one. */\n orgId: string | null\n /** The organization's billing document — the entitlements a write is held to. */\n orgBilling: unknown\n /**\n * The request body as posted. The target reads back only what it stamped\n * onto the form, and must trust nothing else in it.\n */\n body: Readonly<Record<string, unknown>>\n /** The submitted values, sanitized, keyed by the name each field submits under. */\n fields: Readonly<Record<string, string>>\n}\n\n/** What a target answers for one submission. */\nexport interface FormRecordWriteOutcome {\n /**\n * Written as the stored submission's `routing` when present: where the\n * record went, or why it was refused. Absent when the form writes nowhere.\n */\n routing?: Record<string, unknown>\n}\n\n/** A plugin that keeps the records forms may file into. */\nexport interface FormRecordTarget {\n /**\n * Stamps each form in a composed tree this target will write for. Never\n * mutates `nodes`, and answers the same object when it stamps nothing.\n */\n stamp<N extends Record<string, unknown>>(nodes: N, hostId: string): Promise<N>\n /**\n * Writes one submission's record, or refuses it. Never rejects: a record\n * that cannot be written is no reason to fail a submission already stored.\n */\n write(request: FormRecordWriteRequest): Promise<FormRecordWriteOutcome>\n}\n\n/** The compiled declaration: which plugin keeps the records forms file into. */\nexport interface FormRecordTargetDeclaration {\n pluginId: string\n id: string\n}\n\n/** The plugin declared as the forms' record target, or `null` when none is. */\nexport function declaredFormRecordTarget(): FormRecordTargetDeclaration | null {\n return PLUGIN_FORM_RECORD_TARGET_DECLARED\n}\n\ninterface RegisteredTarget {\n pluginId: string\n target: FormRecordTarget\n}\n\n/**\n * One slot per process, on `globalThis` (AGL-3412): the app registers from\n * `instrumentation.ts`, which Next compiles apart from the routes that read.\n */\nconst TARGET_KEY = Symbol.for('@aglyn/aglyn:submission-record-target')\n\nconst globalScope = globalThis as typeof globalThis & {\n [TARGET_KEY]?: RegisteredTarget | null\n}\n\n/**\n * Registers the target. The owner is the plugin whose register fn is running,\n * or the `pluginId` passed for a boot declaration; with neither, or from a\n * plugin other than the one declared, it throws. The same plugin registering\n * again replaces its target. Returns the unregister.\n */\nexport function registerFormRecordTarget(\n target: FormRecordTarget,\n options?: { pluginId?: string },\n): () => void {\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n if (!pluginId) {\n throw new Error(\n 'the form record target was registered with no owner: pass ' +\n '{ pluginId } when registering outside a plugin register fn',\n )\n }\n const declared = declaredFormRecordTarget()\n if (declared && declared.pluginId !== pluginId) {\n throw new Error(\n `the form record target is declared by \"${declared.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n const held = globalScope[TARGET_KEY]\n if (held && held.pluginId !== pluginId) {\n throw new Error(\n `the form record target is already registered by \"${held.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n const entry: RegisteredTarget = { pluginId, target }\n globalScope[TARGET_KEY] = entry\n return () => {\n if (globalScope[TARGET_KEY] === entry) globalScope[TARGET_KEY] = null\n }\n}\n\n/** The registered target with its owner, or `null`. */\nexport function formRecordTarget(): RegisteredTarget | null {\n return globalScope[TARGET_KEY] ?? null\n}\n\n/** Only for specs: forgets the registered target. */\nexport function resetFormRecordTargetForTests(): void {\n globalScope[TARGET_KEY] = null\n}\n\n/**\n * The declared target's registration was not found, even after the app's\n * declarations step ran again.\n */\nexport class FormRecordTargetUnavailableError extends Error {\n constructor(readonly declared: FormRecordTargetDeclaration) {\n super(\n `the form record target is declared by \"${declared.pluginId}\" but none ` +\n 'is registered in this process — its server declarations did not run. ' +\n 'Refusing to treat bound forms as writing nowhere.',\n )\n this.name = 'FormRecordTargetUnavailableError'\n }\n}\n\n/** The declared target, repaired once if missing; `null` when none is declared. */\nasync function requireDeclaredTarget(): Promise<FormRecordTarget | null> {\n const declared = declaredFormRecordTarget()\n if (!declared) return null\n let registered = formRecordTarget()\n if (!registered) {\n try {\n await runPluginDeclarationsRepair()\n } catch (error) {\n console.error('[submission-record-target] the declarations repair failed', error)\n }\n registered = formRecordTarget()\n }\n if (!registered) throw new FormRecordTargetUnavailableError(declared)\n return registered.target\n}\n\nconst placesAForm = (nodes: Record<string, unknown>): boolean =>\n Object.values(nodes).some(\n (node) =>\n (node as { componentId?: unknown } | null)?.componentId === FORM_COMPONENT_ID,\n )\n\n/**\n * The tree a page ships, with each form the target writes for stamped.\n *\n * A tree with no form asks nobody and comes back as the same object. A tree\n * with one THROWS when the declared target is missing — see the module note.\n */\nexport async function stampFormRecordTargets<N extends Record<string, unknown>>(\n nodes: N,\n hostId: string,\n): Promise<N> {\n if (!placesAForm(nodes)) return nodes\n const target = await requireDeclaredTarget()\n return target ? target.stamp(nodes, hostId) : nodes\n}\n\n/**\n * Files one stored submission as a record where the page's form said to.\n *\n * Never rejects. With no target declared it answers nothing; with the declared\n * target missing it logs the failure and answers a `routing` note saying so,\n * because the submission is already kept and losing it now would be worse.\n */\nexport async function writeFormRecordTarget(\n request: FormRecordWriteRequest,\n): Promise<FormRecordWriteOutcome> {\n let target: FormRecordTarget | null\n try {\n target = await requireDeclaredTarget()\n } catch (error) {\n console.error('[submission-record-target] a submission could not be filed', error)\n return { routing: { recordTargetUnavailable: true } }\n }\n if (!target) return {}\n try {\n return await target.write(request)\n } catch (error) {\n console.error('[submission-record-target] the target failed a write', error)\n return {}\n }\n}\n"],"names":["getRegisteringPluginId","FORM_COMPONENT_ID","PLUGIN_FORM_RECORD_TARGET_DECLARED","runPluginDeclarationsRepair","declaredFormRecordTarget","TARGET_KEY","Symbol","for","globalScope","globalThis","registerFormRecordTarget","target","options","pluginId","trim","Error","declared","held","entry","formRecordTarget","resetFormRecordTargetForTests","FormRecordTargetUnavailableError","name","requireDeclaredTarget","registered","error","console","placesAForm","nodes","Object","values","some","node","componentId","stampFormRecordTargets","hostId","stamp","writeFormRecordTarget","request","routing","recordTargetUnavailable","write"],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
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 choice the Video element makes for each player it frames. A declaration
|
|
19
|
+
* says how its player spells each one it supports; one it does not name is
|
|
20
|
+
* never sent.
|
|
21
|
+
*
|
|
22
|
+
* - `autoPlay` — start as soon as the player is ready. ON unless the caller
|
|
23
|
+
* passes exactly `false`: the usual frame is the one a visitor's press
|
|
24
|
+
* loads, and a second play button inside it would ask them twice.
|
|
25
|
+
* - `doNotTrack` — ask the host not to record the viewing session.
|
|
26
|
+
* - `muted` — start without sound.
|
|
27
|
+
* - `loop` — restart at the end.
|
|
28
|
+
*/
|
|
29
|
+
export type VideoEmbedPlayerOption = 'autoPlay' | 'doNotTrack' | 'muted' | 'loop';
|
|
30
|
+
export declare const VIDEO_EMBED_PLAYER_OPTIONS: readonly VideoEmbedPlayerOption[];
|
|
31
|
+
export type VideoEmbedPlayerOptions = Partial<Record<VideoEmbedPlayerOption, boolean>>;
|
|
32
|
+
/**
|
|
33
|
+
* One query parameter of a player address, in the order the declaration
|
|
34
|
+
* lists them. Either `value`, sent on every address, or an `option` whose
|
|
35
|
+
* state picks `on` or `off`; a state with no value leaves the parameter out.
|
|
36
|
+
*/
|
|
37
|
+
export type VideoEmbedPlayerParam = {
|
|
38
|
+
param: string;
|
|
39
|
+
value: string;
|
|
40
|
+
} | {
|
|
41
|
+
param: string;
|
|
42
|
+
option: VideoEmbedPlayerOption;
|
|
43
|
+
on?: string;
|
|
44
|
+
off?: string;
|
|
45
|
+
};
|
|
46
|
+
export interface VideoEmbedProviderDeclaration {
|
|
47
|
+
/** Stable id, unique across plugins. */
|
|
48
|
+
id: string;
|
|
49
|
+
/** The host's name as an author knows it, for labels and help text. */
|
|
50
|
+
label: string;
|
|
51
|
+
/**
|
|
52
|
+
* The domains a link's host must equal or end in (after a dot). Exact or
|
|
53
|
+
* dot-anchored only, so a domain that merely contains one is refused.
|
|
54
|
+
*/
|
|
55
|
+
domains: readonly string[];
|
|
56
|
+
/**
|
|
57
|
+
* Regular expressions over a link's PATH, anchored at both ends, whose
|
|
58
|
+
* first capture group is the media id. The host is checked separately,
|
|
59
|
+
* against {@link domains}.
|
|
60
|
+
*/
|
|
61
|
+
mediaIdPaths: readonly string[];
|
|
62
|
+
/** A regular expression, anchored at both ends, a media id must match. */
|
|
63
|
+
mediaIdPattern: string;
|
|
64
|
+
/** The one origin the host's player is framed from. */
|
|
65
|
+
playerOrigin: string;
|
|
66
|
+
/** The player page's path on {@link playerOrigin}; `{id}` is the media id. */
|
|
67
|
+
playerPath: string;
|
|
68
|
+
/** The query every player address carries, in this order. */
|
|
69
|
+
playerQuery?: readonly VideoEmbedPlayerParam[];
|
|
70
|
+
}
|
|
71
|
+
/** A declaration, with the plugin that made it. */
|
|
72
|
+
export interface ResolvedVideoEmbedProvider extends VideoEmbedProviderDeclaration {
|
|
73
|
+
pluginId: string;
|
|
74
|
+
}
|
|
75
|
+
/** A link a declared host recognized. */
|
|
76
|
+
export interface VideoEmbed {
|
|
77
|
+
provider: ResolvedVideoEmbedProvider;
|
|
78
|
+
/** The media id the link named, and nothing else of it. */
|
|
79
|
+
mediaId: string;
|
|
80
|
+
/**
|
|
81
|
+
* The player page with no per-visit options — what a `VideoObject`
|
|
82
|
+
* publishes as `embedUrl`.
|
|
83
|
+
*/
|
|
84
|
+
embedUrl: string;
|
|
85
|
+
}
|
|
86
|
+
/** Every host a first-party plugin declares. */
|
|
87
|
+
export declare function videoEmbedProviders(): readonly ResolvedVideoEmbedProvider[];
|
|
88
|
+
/**
|
|
89
|
+
* The declared host a link belongs to, with the media id it names, or
|
|
90
|
+
* `undefined` for anything else: a value that is not an http(s) URL, a host
|
|
91
|
+
* nothing declares, or a path that names no id the host's pattern accepts.
|
|
92
|
+
*/
|
|
93
|
+
export declare function videoEmbedOf(value: unknown, providers?: readonly ResolvedVideoEmbedProvider[]): VideoEmbed | undefined;
|
|
94
|
+
/** The player page for a declared host's link, with no per-visit options. */
|
|
95
|
+
export declare function videoEmbedUrl(value: unknown, providers?: readonly ResolvedVideoEmbedProvider[]): string | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* The address of a declared host's player frame for this visit, carrying the
|
|
98
|
+
* declaration's query in its own order. See {@link VideoEmbedPlayerOption}
|
|
99
|
+
* for what each option means and which way it defaults.
|
|
100
|
+
*/
|
|
101
|
+
export declare function videoEmbedPlayerSrc(value: unknown, options?: VideoEmbedPlayerOptions, providers?: readonly ResolvedVideoEmbedProvider[]): string | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Every origin a declared player is framed from: what a published page's
|
|
104
|
+
* `frame-src` admits for the Video element.
|
|
105
|
+
*/
|
|
106
|
+
export declare function videoEmbedPlayerOrigins(providers?: readonly ResolvedVideoEmbedProvider[]): string[];
|
|
107
|
+
/** The declared hosts' names, as an author knows them. */
|
|
108
|
+
export declare function videoEmbedProviderLabels(providers?: readonly ResolvedVideoEmbedProvider[]): string[];
|
|
@@ -0,0 +1,165 @@
|
|
|
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
|
+
* A VIDEO HOST WHOSE OWN PLAYER A VIDEO PLAYS IN (AGL-3080).
|
|
18
|
+
*
|
|
19
|
+
* Some video hosts hand an author a link to a page, not to a file: the film
|
|
20
|
+
* plays only inside the host's player, framed from the host's origin. The
|
|
21
|
+
* Video element recognizes such a link, keeps only the media id it names,
|
|
22
|
+
* and frames the host's player for it. Core never names a host. A plugin
|
|
23
|
+
* DECLARES one — the domains its links live on, where in the path the media
|
|
24
|
+
* id sits, the one origin its player is framed from, and the query that
|
|
25
|
+
* player reads — and core's resolvers answer from the declarations alone.
|
|
26
|
+
*
|
|
27
|
+
* This sits beside `media-delivery-provider.ts` and is not that seam. A
|
|
28
|
+
* delivery provider is where the platform serves ITS OWN copy of a file
|
|
29
|
+
* from; an embed provider is a host whose player the author chose, which the
|
|
30
|
+
* platform never serves a byte of.
|
|
31
|
+
*
|
|
32
|
+
* ## Only the media id survives
|
|
33
|
+
*
|
|
34
|
+
* The string an author pasted never reaches a frame. {@link videoEmbedOf}
|
|
35
|
+
* reads the media id out of it, and every address below is rebuilt from the
|
|
36
|
+
* declaration and that id alone, so a declared player is framed from its
|
|
37
|
+
* declared origin and nowhere else. That closed set is what lets a published
|
|
38
|
+
* page's `frame-src` name the origin for every site
|
|
39
|
+
* ({@link videoEmbedPlayerOrigins}). The id must match the declaration's own
|
|
40
|
+
* pattern AND {@link SAFE_MEDIA_ID}, so no declaration can widen the path it
|
|
41
|
+
* is put into.
|
|
42
|
+
*
|
|
43
|
+
* ## Compiled, and deliberately without a runtime registrar
|
|
44
|
+
*
|
|
45
|
+
* The readers are the published page and its policy: the Video element that
|
|
46
|
+
* plays the link, the `VideoObject` a crawler reads, the built-in entry page
|
|
47
|
+
* that decides whether a featured film can play, and the tenant middleware
|
|
48
|
+
* whose `frame-src` must admit the player. None of them loads a plugin's
|
|
49
|
+
* console code, and the middleware loads no plugin at all. A registry one of
|
|
50
|
+
* them had not filled would render a customer's link as a `<video>` pointed
|
|
51
|
+
* at an HTML page, or refuse the frame, and nothing would go red — the
|
|
52
|
+
* AGL-3025 shape, on the customer's own film. So a first-party plugin
|
|
53
|
+
* declares its hosts under `videoEmbedProviders` in `plugins.config.json`,
|
|
54
|
+
* `tools/scripts/generate-plugin-manifests.mjs` validates and compiles them,
|
|
55
|
+
* and this module reads the compiled list.
|
|
56
|
+
*
|
|
57
|
+
* A marketplace plugin cannot add a host this way, and that is the point
|
|
58
|
+
* rather than a gap: a declaration widens every published page's
|
|
59
|
+
* `frame-src`, which is a platform decision, not one a plugin's own code
|
|
60
|
+
* makes at runtime.
|
|
61
|
+
*
|
|
62
|
+
* ## What "absent" means
|
|
63
|
+
*
|
|
64
|
+
* A link no declaration recognizes is an ordinary URL, rendered exactly as
|
|
65
|
+
* any other link is. Removing a declaration therefore turns its links back
|
|
66
|
+
* into plain URLs, which play nothing — so the declaring plugin's spec holds
|
|
67
|
+
* the declaration to the links it must keep reading.
|
|
68
|
+
*/ import { FIRST_PARTY_VIDEO_EMBED_PROVIDERS } from "./first-party-plugins.generated.js";
|
|
69
|
+
export const VIDEO_EMBED_PLAYER_OPTIONS = [
|
|
70
|
+
'autoPlay',
|
|
71
|
+
'doNotTrack',
|
|
72
|
+
'muted',
|
|
73
|
+
'loop'
|
|
74
|
+
];
|
|
75
|
+
/**
|
|
76
|
+
* The floor every media id stands on, whatever a declaration's own pattern
|
|
77
|
+
* admits: no separator, dot, query or fragment can reach the player path.
|
|
78
|
+
*/ const SAFE_MEDIA_ID = /^[A-Za-z0-9_-]{1,64}$/;
|
|
79
|
+
/** The placeholder a `playerPath` names the media id with. */ const ID_PLACEHOLDER = '{id}';
|
|
80
|
+
/** Every host a first-party plugin declares. */ export function videoEmbedProviders() {
|
|
81
|
+
return FIRST_PARTY_VIDEO_EMBED_PROVIDERS;
|
|
82
|
+
}
|
|
83
|
+
const compiled = new WeakMap();
|
|
84
|
+
function compile(provider) {
|
|
85
|
+
let answer = compiled.get(provider);
|
|
86
|
+
if (!answer) {
|
|
87
|
+
answer = {
|
|
88
|
+
paths: provider.mediaIdPaths.map((source)=>new RegExp(source)),
|
|
89
|
+
mediaId: new RegExp(provider.mediaIdPattern)
|
|
90
|
+
};
|
|
91
|
+
compiled.set(provider, answer);
|
|
92
|
+
}
|
|
93
|
+
return answer;
|
|
94
|
+
}
|
|
95
|
+
function onDomain(hostname, domains) {
|
|
96
|
+
return domains.some((domain)=>hostname === domain || hostname.endsWith(`.${domain}`));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The declared host a link belongs to, with the media id it names, or
|
|
100
|
+
* `undefined` for anything else: a value that is not an http(s) URL, a host
|
|
101
|
+
* nothing declares, or a path that names no id the host's pattern accepts.
|
|
102
|
+
*/ export function videoEmbedOf(value, providers = videoEmbedProviders()) {
|
|
103
|
+
if (typeof value !== 'string' || !providers.length) return undefined;
|
|
104
|
+
let url;
|
|
105
|
+
try {
|
|
106
|
+
url = new URL(value.trim());
|
|
107
|
+
} catch (unused) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:') return undefined;
|
|
111
|
+
for (const provider of providers){
|
|
112
|
+
if (!onDomain(url.hostname, provider.domains)) continue;
|
|
113
|
+
const { paths, mediaId } = compile(provider);
|
|
114
|
+
for (const pattern of paths){
|
|
115
|
+
var _pattern_exec;
|
|
116
|
+
const id = (_pattern_exec = pattern.exec(url.pathname)) == null ? void 0 : _pattern_exec[1];
|
|
117
|
+
if (id && mediaId.test(id) && SAFE_MEDIA_ID.test(id)) {
|
|
118
|
+
return {
|
|
119
|
+
provider,
|
|
120
|
+
mediaId: id,
|
|
121
|
+
embedUrl: `${provider.playerOrigin}${provider.playerPath.replace(ID_PLACEHOLDER, id)}`
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
/** The player page for a declared host's link, with no per-visit options. */ export function videoEmbedUrl(value, providers) {
|
|
129
|
+
var _videoEmbedOf;
|
|
130
|
+
return (_videoEmbedOf = videoEmbedOf(value, providers)) == null ? void 0 : _videoEmbedOf.embedUrl;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The address of a declared host's player frame for this visit, carrying the
|
|
134
|
+
* declaration's query in its own order. See {@link VideoEmbedPlayerOption}
|
|
135
|
+
* for what each option means and which way it defaults.
|
|
136
|
+
*/ export function videoEmbedPlayerSrc(value, options = {}, providers) {
|
|
137
|
+
var _embed_provider_playerQuery;
|
|
138
|
+
const embed = videoEmbedOf(value, providers);
|
|
139
|
+
if (!embed) return undefined;
|
|
140
|
+
const params = new URLSearchParams();
|
|
141
|
+
for (const entry of (_embed_provider_playerQuery = embed.provider.playerQuery) != null ? _embed_provider_playerQuery : []){
|
|
142
|
+
if ('value' in entry) {
|
|
143
|
+
params.set(entry.param, entry.value);
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
const on = entry.option === 'autoPlay' ? options.autoPlay !== false : Boolean(options[entry.option]);
|
|
147
|
+
const sent = on ? entry.on : entry.off;
|
|
148
|
+
if (sent !== undefined) params.set(entry.param, sent);
|
|
149
|
+
}
|
|
150
|
+
const query = params.toString();
|
|
151
|
+
return query ? `${embed.embedUrl}?${query}` : embed.embedUrl;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Every origin a declared player is framed from: what a published page's
|
|
155
|
+
* `frame-src` admits for the Video element.
|
|
156
|
+
*/ export function videoEmbedPlayerOrigins(providers = videoEmbedProviders()) {
|
|
157
|
+
return [
|
|
158
|
+
...new Set(providers.map((provider)=>provider.playerOrigin))
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
/** The declared hosts' names, as an author knows them. */ export function videoEmbedProviderLabels(providers = videoEmbedProviders()) {
|
|
162
|
+
return providers.map((provider)=>provider.label);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=video-embed-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/video-embed-provider.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 * A VIDEO HOST WHOSE OWN PLAYER A VIDEO PLAYS IN (AGL-3080).\n *\n * Some video hosts hand an author a link to a page, not to a file: the film\n * plays only inside the host's player, framed from the host's origin. The\n * Video element recognizes such a link, keeps only the media id it names,\n * and frames the host's player for it. Core never names a host. A plugin\n * DECLARES one — the domains its links live on, where in the path the media\n * id sits, the one origin its player is framed from, and the query that\n * player reads — and core's resolvers answer from the declarations alone.\n *\n * This sits beside `media-delivery-provider.ts` and is not that seam. A\n * delivery provider is where the platform serves ITS OWN copy of a file\n * from; an embed provider is a host whose player the author chose, which the\n * platform never serves a byte of.\n *\n * ## Only the media id survives\n *\n * The string an author pasted never reaches a frame. {@link videoEmbedOf}\n * reads the media id out of it, and every address below is rebuilt from the\n * declaration and that id alone, so a declared player is framed from its\n * declared origin and nowhere else. That closed set is what lets a published\n * page's `frame-src` name the origin for every site\n * ({@link videoEmbedPlayerOrigins}). The id must match the declaration's own\n * pattern AND {@link SAFE_MEDIA_ID}, so no declaration can widen the path it\n * is put into.\n *\n * ## Compiled, and deliberately without a runtime registrar\n *\n * The readers are the published page and its policy: the Video element that\n * plays the link, the `VideoObject` a crawler reads, the built-in entry page\n * that decides whether a featured film can play, and the tenant middleware\n * whose `frame-src` must admit the player. None of them loads a plugin's\n * console code, and the middleware loads no plugin at all. A registry one of\n * them had not filled would render a customer's link as a `<video>` pointed\n * at an HTML page, or refuse the frame, and nothing would go red — the\n * AGL-3025 shape, on the customer's own film. So a first-party plugin\n * declares its hosts under `videoEmbedProviders` in `plugins.config.json`,\n * `tools/scripts/generate-plugin-manifests.mjs` validates and compiles them,\n * and this module reads the compiled list.\n *\n * A marketplace plugin cannot add a host this way, and that is the point\n * rather than a gap: a declaration widens every published page's\n * `frame-src`, which is a platform decision, not one a plugin's own code\n * makes at runtime.\n *\n * ## What \"absent\" means\n *\n * A link no declaration recognizes is an ordinary URL, rendered exactly as\n * any other link is. Removing a declaration therefore turns its links back\n * into plain URLs, which play nothing — so the declaring plugin's spec holds\n * the declaration to the links it must keep reading.\n */\n\nimport { FIRST_PARTY_VIDEO_EMBED_PROVIDERS } from './first-party-plugins.generated'\n\n/**\n * A choice the Video element makes for each player it frames. A declaration\n * says how its player spells each one it supports; one it does not name is\n * never sent.\n *\n * - `autoPlay` — start as soon as the player is ready. ON unless the caller\n * passes exactly `false`: the usual frame is the one a visitor's press\n * loads, and a second play button inside it would ask them twice.\n * - `doNotTrack` — ask the host not to record the viewing session.\n * - `muted` — start without sound.\n * - `loop` — restart at the end.\n */\nexport type VideoEmbedPlayerOption = 'autoPlay' | 'doNotTrack' | 'muted' | 'loop'\n\nexport const VIDEO_EMBED_PLAYER_OPTIONS: readonly VideoEmbedPlayerOption[] = [\n 'autoPlay',\n 'doNotTrack',\n 'muted',\n 'loop',\n]\n\nexport type VideoEmbedPlayerOptions = Partial<\n Record<VideoEmbedPlayerOption, boolean>\n>\n\n/**\n * One query parameter of a player address, in the order the declaration\n * lists them. Either `value`, sent on every address, or an `option` whose\n * state picks `on` or `off`; a state with no value leaves the parameter out.\n */\nexport type VideoEmbedPlayerParam =\n | { param: string; value: string }\n | {\n param: string\n option: VideoEmbedPlayerOption\n on?: string\n off?: string\n }\n\nexport interface VideoEmbedProviderDeclaration {\n /** Stable id, unique across plugins. */\n id: string\n /** The host's name as an author knows it, for labels and help text. */\n label: string\n /**\n * The domains a link's host must equal or end in (after a dot). Exact or\n * dot-anchored only, so a domain that merely contains one is refused.\n */\n domains: readonly string[]\n /**\n * Regular expressions over a link's PATH, anchored at both ends, whose\n * first capture group is the media id. The host is checked separately,\n * against {@link domains}.\n */\n mediaIdPaths: readonly string[]\n /** A regular expression, anchored at both ends, a media id must match. */\n mediaIdPattern: string\n /** The one origin the host's player is framed from. */\n playerOrigin: string\n /** The player page's path on {@link playerOrigin}; `{id}` is the media id. */\n playerPath: string\n /** The query every player address carries, in this order. */\n playerQuery?: readonly VideoEmbedPlayerParam[]\n}\n\n/** A declaration, with the plugin that made it. */\nexport interface ResolvedVideoEmbedProvider\n extends VideoEmbedProviderDeclaration {\n pluginId: string\n}\n\n/** A link a declared host recognized. */\nexport interface VideoEmbed {\n provider: ResolvedVideoEmbedProvider\n /** The media id the link named, and nothing else of it. */\n mediaId: string\n /**\n * The player page with no per-visit options — what a `VideoObject`\n * publishes as `embedUrl`.\n */\n embedUrl: string\n}\n\n/**\n * The floor every media id stands on, whatever a declaration's own pattern\n * admits: no separator, dot, query or fragment can reach the player path.\n */\nconst SAFE_MEDIA_ID = /^[A-Za-z0-9_-]{1,64}$/\n\n/** The placeholder a `playerPath` names the media id with. */\nconst ID_PLACEHOLDER = '{id}'\n\n/** Every host a first-party plugin declares. */\nexport function videoEmbedProviders(): readonly ResolvedVideoEmbedProvider[] {\n return FIRST_PARTY_VIDEO_EMBED_PROVIDERS\n}\n\ninterface CompiledProvider {\n paths: RegExp[]\n mediaId: RegExp\n}\n\nconst compiled = new WeakMap<VideoEmbedProviderDeclaration, CompiledProvider>()\n\nfunction compile(provider: VideoEmbedProviderDeclaration): CompiledProvider {\n let answer = compiled.get(provider)\n if (!answer) {\n answer = {\n paths: provider.mediaIdPaths.map((source) => new RegExp(source)),\n mediaId: new RegExp(provider.mediaIdPattern),\n }\n compiled.set(provider, answer)\n }\n return answer\n}\n\nfunction onDomain(hostname: string, domains: readonly string[]): boolean {\n return domains.some(\n (domain) => hostname === domain || hostname.endsWith(`.${domain}`),\n )\n}\n\n/**\n * The declared host a link belongs to, with the media id it names, or\n * `undefined` for anything else: a value that is not an http(s) URL, a host\n * nothing declares, or a path that names no id the host's pattern accepts.\n */\nexport function videoEmbedOf(\n value: unknown,\n providers: readonly ResolvedVideoEmbedProvider[] = videoEmbedProviders(),\n): VideoEmbed | undefined {\n if (typeof value !== 'string' || !providers.length) return undefined\n let url: URL\n try {\n url = new URL(value.trim())\n } catch {\n return undefined\n }\n if (url.protocol !== 'https:' && url.protocol !== 'http:') return undefined\n for (const provider of providers) {\n if (!onDomain(url.hostname, provider.domains)) continue\n const { paths, mediaId } = compile(provider)\n for (const pattern of paths) {\n const id = pattern.exec(url.pathname)?.[1]\n if (id && mediaId.test(id) && SAFE_MEDIA_ID.test(id)) {\n return {\n provider,\n mediaId: id,\n embedUrl: `${provider.playerOrigin}${provider.playerPath.replace(ID_PLACEHOLDER, id)}`,\n }\n }\n }\n }\n return undefined\n}\n\n/** The player page for a declared host's link, with no per-visit options. */\nexport function videoEmbedUrl(\n value: unknown,\n providers?: readonly ResolvedVideoEmbedProvider[],\n): string | undefined {\n return videoEmbedOf(value, providers)?.embedUrl\n}\n\n/**\n * The address of a declared host's player frame for this visit, carrying the\n * declaration's query in its own order. See {@link VideoEmbedPlayerOption}\n * for what each option means and which way it defaults.\n */\nexport function videoEmbedPlayerSrc(\n value: unknown,\n options: VideoEmbedPlayerOptions = {},\n providers?: readonly ResolvedVideoEmbedProvider[],\n): string | undefined {\n const embed = videoEmbedOf(value, providers)\n if (!embed) return undefined\n const params = new URLSearchParams()\n for (const entry of embed.provider.playerQuery ?? []) {\n if ('value' in entry) {\n params.set(entry.param, entry.value)\n continue\n }\n const on =\n entry.option === 'autoPlay'\n ? options.autoPlay !== false\n : Boolean(options[entry.option])\n const sent = on ? entry.on : entry.off\n if (sent !== undefined) params.set(entry.param, sent)\n }\n const query = params.toString()\n return query ? `${embed.embedUrl}?${query}` : embed.embedUrl\n}\n\n/**\n * Every origin a declared player is framed from: what a published page's\n * `frame-src` admits for the Video element.\n */\nexport function videoEmbedPlayerOrigins(\n providers: readonly ResolvedVideoEmbedProvider[] = videoEmbedProviders(),\n): string[] {\n return [...new Set(providers.map((provider) => provider.playerOrigin))]\n}\n\n/** The declared hosts' names, as an author knows them. */\nexport function videoEmbedProviderLabels(\n providers: readonly ResolvedVideoEmbedProvider[] = videoEmbedProviders(),\n): string[] {\n return providers.map((provider) => provider.label)\n}\n"],"names":["FIRST_PARTY_VIDEO_EMBED_PROVIDERS","VIDEO_EMBED_PLAYER_OPTIONS","SAFE_MEDIA_ID","ID_PLACEHOLDER","videoEmbedProviders","compiled","WeakMap","compile","provider","answer","get","paths","mediaIdPaths","map","source","RegExp","mediaId","mediaIdPattern","set","onDomain","hostname","domains","some","domain","endsWith","videoEmbedOf","value","providers","length","undefined","url","URL","trim","protocol","pattern","id","exec","pathname","test","embedUrl","playerOrigin","playerPath","replace","videoEmbedUrl","videoEmbedPlayerSrc","options","embed","params","URLSearchParams","entry","playerQuery","param","on","option","autoPlay","Boolean","sent","off","query","toString","videoEmbedPlayerOrigins","Set","videoEmbedProviderLabels","label"],"mappings":"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"}
|
package/src/lib/types/nodes.d.ts
CHANGED
|
@@ -363,8 +363,8 @@ export interface NodeSchema<P = JSX.AnyProps> extends NodeI<P> {
|
|
|
363
363
|
*
|
|
364
364
|
* ## Shape
|
|
365
365
|
*
|
|
366
|
-
* Deliberately the same `
|
|
367
|
-
*
|
|
366
|
+
* Deliberately the same `SiteInteraction` a site-wide interaction is, so
|
|
367
|
+
* nothing about the runtime changes: the selector is stamped from this
|
|
368
368
|
* node's own id when the page is composed, and the compiled result is the
|
|
369
369
|
* shape the client engine has always consumed. `trigger.selector` is
|
|
370
370
|
* therefore ignored here — the node IS the selector.
|