@aglyn/aglyn 1.0.0-beta.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +11 -0
- package/package.json +66 -0
- package/src/index.d.ts +25 -0
- package/src/index.js +26 -0
- package/src/index.js.map +1 -0
- package/src/lib/aglyn.d.ts +31 -0
- package/src/lib/aglyn.js +114 -0
- package/src/lib/aglyn.js.map +1 -0
- package/src/lib/app-utils/abuse-report.d.ts +193 -0
- package/src/lib/app-utils/abuse-report.js +321 -0
- package/src/lib/app-utils/abuse-report.js.map +1 -0
- package/src/lib/app-utils/accept-negotiation.d.ts +129 -0
- package/src/lib/app-utils/accept-negotiation.js +266 -0
- package/src/lib/app-utils/accept-negotiation.js.map +1 -0
- package/src/lib/app-utils/account-emails.d.ts +263 -0
- package/src/lib/app-utils/account-emails.js +264 -0
- package/src/lib/app-utils/account-emails.js.map +1 -0
- package/src/lib/app-utils/actions.d.ts +717 -0
- package/src/lib/app-utils/actions.js +1031 -0
- package/src/lib/app-utils/actions.js.map +1 -0
- package/src/lib/app-utils/activity-presenter.d.ts +152 -0
- package/src/lib/app-utils/activity-presenter.js +326 -0
- package/src/lib/app-utils/activity-presenter.js.map +1 -0
- package/src/lib/app-utils/advertising-tag-mounts.d.ts +133 -0
- package/src/lib/app-utils/advertising-tag-mounts.js +118 -0
- package/src/lib/app-utils/advertising-tag-mounts.js.map +1 -0
- package/src/lib/app-utils/advertising-tags.d.ts +307 -0
- package/src/lib/app-utils/advertising-tags.js +525 -0
- package/src/lib/app-utils/advertising-tags.js.map +1 -0
- package/src/lib/app-utils/agent-api-catalog.d.ts +94 -0
- package/src/lib/app-utils/agent-api-catalog.js +106 -0
- package/src/lib/app-utils/agent-api-catalog.js.map +1 -0
- package/src/lib/app-utils/agent-openapi.d.ts +103 -0
- package/src/lib/app-utils/agent-openapi.js +1128 -0
- package/src/lib/app-utils/agent-openapi.js.map +1 -0
- package/src/lib/app-utils/analytics-beacon.d.ts +154 -0
- package/src/lib/app-utils/analytics-beacon.js +152 -0
- package/src/lib/app-utils/analytics-beacon.js.map +1 -0
- package/src/lib/app-utils/analytics-environment.d.ts +133 -0
- package/src/lib/app-utils/analytics-environment.js +152 -0
- package/src/lib/app-utils/analytics-environment.js.map +1 -0
- package/src/lib/app-utils/analytics-events.d.ts +744 -0
- package/src/lib/app-utils/analytics-events.js +650 -0
- package/src/lib/app-utils/analytics-events.js.map +1 -0
- package/src/lib/app-utils/analytics-link-clicks.d.ts +102 -0
- package/src/lib/app-utils/analytics-link-clicks.js +267 -0
- package/src/lib/app-utils/analytics-link-clicks.js.map +1 -0
- package/src/lib/app-utils/analytics-path-key.d.ts +46 -0
- package/src/lib/app-utils/analytics-path-key.js +46 -0
- package/src/lib/app-utils/analytics-path-key.js.map +1 -0
- package/src/lib/app-utils/api-adapter.d.ts +47 -0
- package/src/lib/app-utils/api-adapter.js +367 -0
- package/src/lib/app-utils/api-adapter.js.map +1 -0
- package/src/lib/app-utils/api-idempotency.d.ts +169 -0
- package/src/lib/app-utils/api-idempotency.js +213 -0
- package/src/lib/app-utils/api-idempotency.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +210 -0
- package/src/lib/app-utils/api-plugins.js +221 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -0
- package/src/lib/app-utils/assist-credits.d.ts +482 -0
- package/src/lib/app-utils/assist-credits.js +509 -0
- package/src/lib/app-utils/assist-credits.js.map +1 -0
- package/src/lib/app-utils/attribution-attribute.d.ts +34 -0
- package/src/lib/app-utils/attribution-attribute.js +34 -0
- package/src/lib/app-utils/attribution-attribute.js.map +1 -0
- package/src/lib/app-utils/attribution-guard.d.ts +130 -0
- package/src/lib/app-utils/attribution-guard.js +410 -0
- package/src/lib/app-utils/attribution-guard.js.map +1 -0
- package/src/lib/app-utils/author-css.d.ts +123 -0
- package/src/lib/app-utils/author-css.js +275 -0
- package/src/lib/app-utils/author-css.js.map +1 -0
- package/src/lib/app-utils/author-html-markdown.d.ts +31 -0
- package/src/lib/app-utils/author-html-markdown.js +497 -0
- package/src/lib/app-utils/author-html-markdown.js.map +1 -0
- package/src/lib/app-utils/author-html.d.ts +135 -0
- package/src/lib/app-utils/author-html.js +1037 -0
- package/src/lib/app-utils/author-html.js.map +1 -0
- package/src/lib/app-utils/automation-placeholders.d.ts +72 -0
- package/src/lib/app-utils/automation-placeholders.js +207 -0
- package/src/lib/app-utils/automation-placeholders.js.map +1 -0
- package/src/lib/app-utils/bandwidth-cap.d.ts +183 -0
- package/src/lib/app-utils/bandwidth-cap.js +193 -0
- package/src/lib/app-utils/bandwidth-cap.js.map +1 -0
- package/src/lib/app-utils/binding-token-catalog.d.ts +82 -0
- package/src/lib/app-utils/binding-token-catalog.js +293 -0
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -0
- package/src/lib/app-utils/binding-tokens.d.ts +157 -0
- package/src/lib/app-utils/binding-tokens.js +251 -0
- package/src/lib/app-utils/binding-tokens.js.map +1 -0
- package/src/lib/app-utils/breadcrumb-json-ld.d.ts +57 -0
- package/src/lib/app-utils/breadcrumb-json-ld.js +67 -0
- package/src/lib/app-utils/breadcrumb-json-ld.js.map +1 -0
- package/src/lib/app-utils/campaign-attribution.d.ts +117 -0
- package/src/lib/app-utils/campaign-attribution.js +162 -0
- package/src/lib/app-utils/campaign-attribution.js.map +1 -0
- package/src/lib/app-utils/campaign-forwarding.d.ts +220 -0
- package/src/lib/app-utils/campaign-forwarding.js +332 -0
- package/src/lib/app-utils/campaign-forwarding.js.map +1 -0
- package/src/lib/app-utils/campaign-membership.d.ts +109 -0
- package/src/lib/app-utils/campaign-membership.js +176 -0
- package/src/lib/app-utils/campaign-membership.js.map +1 -0
- package/src/lib/app-utils/campaign-touch.d.ts +206 -0
- package/src/lib/app-utils/campaign-touch.js +326 -0
- package/src/lib/app-utils/campaign-touch.js.map +1 -0
- package/src/lib/app-utils/child-contract-compose.d.ts +28 -0
- package/src/lib/app-utils/child-contract-compose.js +140 -0
- package/src/lib/app-utils/child-contract-compose.js.map +1 -0
- package/src/lib/app-utils/child-contract.d.ts +129 -0
- package/src/lib/app-utils/child-contract.js +153 -0
- package/src/lib/app-utils/child-contract.js.map +1 -0
- package/src/lib/app-utils/collection-delete.d.ts +113 -0
- package/src/lib/app-utils/collection-delete.js +120 -0
- package/src/lib/app-utils/collection-delete.js.map +1 -0
- package/src/lib/app-utils/collection-entries.d.ts +833 -0
- package/src/lib/app-utils/collection-entries.js +1285 -0
- package/src/lib/app-utils/collection-entries.js.map +1 -0
- package/src/lib/app-utils/collection-entry-date.d.ts +129 -0
- package/src/lib/app-utils/collection-entry-date.js +183 -0
- package/src/lib/app-utils/collection-entry-date.js.map +1 -0
- package/src/lib/app-utils/collection-kind.d.ts +55 -0
- package/src/lib/app-utils/collection-kind.js +69 -0
- package/src/lib/app-utils/collection-kind.js.map +1 -0
- package/src/lib/app-utils/collection-slug.d.ts +79 -0
- package/src/lib/app-utils/collection-slug.js +70 -0
- package/src/lib/app-utils/collection-slug.js.map +1 -0
- package/src/lib/app-utils/compose-layout-nodes.d.ts +147 -0
- package/src/lib/app-utils/compose-layout-nodes.js +261 -0
- package/src/lib/app-utils/compose-layout-nodes.js.map +1 -0
- package/src/lib/app-utils/compose-layout-props.d.ts +71 -0
- package/src/lib/app-utils/compose-layout-props.js +61 -0
- package/src/lib/app-utils/compose-layout-props.js.map +1 -0
- package/src/lib/app-utils/compose-reusable-components.d.ts +504 -0
- package/src/lib/app-utils/compose-reusable-components.js +1366 -0
- package/src/lib/app-utils/compose-reusable-components.js.map +1 -0
- package/src/lib/app-utils/compress.d.ts +35 -0
- package/src/lib/app-utils/compress.js +38 -0
- package/src/lib/app-utils/compress.js.map +1 -0
- package/src/lib/app-utils/consent-banner-ui.d.ts +226 -0
- package/src/lib/app-utils/consent-banner-ui.js +583 -0
- package/src/lib/app-utils/consent-banner-ui.js.map +1 -0
- package/src/lib/app-utils/consent-groups.d.ts +189 -0
- package/src/lib/app-utils/consent-groups.js +219 -0
- package/src/lib/app-utils/consent-groups.js.map +1 -0
- package/src/lib/app-utils/consent-preferences-dialog.d.ts +58 -0
- package/src/lib/app-utils/consent-preferences-dialog.js +106 -0
- package/src/lib/app-utils/consent-preferences-dialog.js.map +1 -0
- package/src/lib/app-utils/console-record-links.d.ts +163 -0
- package/src/lib/app-utils/console-record-links.js +178 -0
- package/src/lib/app-utils/console-record-links.js.map +1 -0
- package/src/lib/app-utils/console-routes.d.ts +658 -0
- package/src/lib/app-utils/console-routes.js +489 -0
- package/src/lib/app-utils/console-routes.js.map +1 -0
- package/src/lib/app-utils/console-widget-slot-context.d.ts +46 -0
- package/src/lib/app-utils/console-widget-slot-context.js +23 -0
- package/src/lib/app-utils/console-widget-slot-context.js.map +1 -0
- package/src/lib/app-utils/contact-custom-fields.d.ts +191 -0
- package/src/lib/app-utils/contact-custom-fields.js +349 -0
- package/src/lib/app-utils/contact-custom-fields.js.map +1 -0
- package/src/lib/app-utils/contact-holder.d.ts +52 -0
- package/src/lib/app-utils/contact-holder.js +98 -0
- package/src/lib/app-utils/contact-holder.js.map +1 -0
- package/src/lib/app-utils/contact-merge.d.ts +136 -0
- package/src/lib/app-utils/contact-merge.js +379 -0
- package/src/lib/app-utils/contact-merge.js.map +1 -0
- package/src/lib/app-utils/contacts.d.ts +554 -0
- package/src/lib/app-utils/contacts.js +401 -0
- package/src/lib/app-utils/contacts.js.map +1 -0
- package/src/lib/app-utils/content-author-profile.d.ts +68 -0
- package/src/lib/app-utils/content-author-profile.js +118 -0
- package/src/lib/app-utils/content-author-profile.js.map +1 -0
- package/src/lib/app-utils/content-authors.d.ts +662 -0
- package/src/lib/app-utils/content-authors.js +771 -0
- package/src/lib/app-utils/content-authors.js.map +1 -0
- package/src/lib/app-utils/content-schema-type.d.ts +81 -0
- package/src/lib/app-utils/content-schema-type.js +87 -0
- package/src/lib/app-utils/content-schema-type.js.map +1 -0
- package/src/lib/app-utils/contexts.d.ts +35 -0
- package/src/lib/app-utils/contexts.js +35 -0
- package/src/lib/app-utils/contexts.js.map +1 -0
- package/src/lib/app-utils/create-resource-uid.d.ts +18 -0
- package/src/lib/app-utils/create-resource-uid.js +23 -0
- package/src/lib/app-utils/create-resource-uid.js.map +1 -0
- package/src/lib/app-utils/crm-booking.d.ts +75 -0
- package/src/lib/app-utils/crm-booking.js +133 -0
- package/src/lib/app-utils/crm-booking.js.map +1 -0
- package/src/lib/app-utils/crm-csv.d.ts +232 -0
- package/src/lib/app-utils/crm-csv.js +432 -0
- package/src/lib/app-utils/crm-csv.js.map +1 -0
- package/src/lib/app-utils/crm-digest.d.ts +179 -0
- package/src/lib/app-utils/crm-digest.js +271 -0
- package/src/lib/app-utils/crm-digest.js.map +1 -0
- package/src/lib/app-utils/crm-email-templates.d.ts +172 -0
- package/src/lib/app-utils/crm-email-templates.js +382 -0
- package/src/lib/app-utils/crm-email-templates.js.map +1 -0
- package/src/lib/app-utils/crm-inbound.d.ts +245 -0
- package/src/lib/app-utils/crm-inbound.js +407 -0
- package/src/lib/app-utils/crm-inbound.js.map +1 -0
- package/src/lib/app-utils/crm-kinds.d.ts +73 -0
- package/src/lib/app-utils/crm-kinds.js +92 -0
- package/src/lib/app-utils/crm-kinds.js.map +1 -0
- package/src/lib/app-utils/crm-next-activity.d.ts +107 -0
- package/src/lib/app-utils/crm-next-activity.js +140 -0
- package/src/lib/app-utils/crm-next-activity.js.map +1 -0
- package/src/lib/app-utils/crm-reports.d.ts +479 -0
- package/src/lib/app-utils/crm-reports.js +680 -0
- package/src/lib/app-utils/crm-reports.js.map +1 -0
- package/src/lib/app-utils/crm-task-reminders.d.ts +129 -0
- package/src/lib/app-utils/crm-task-reminders.js +139 -0
- package/src/lib/app-utils/crm-task-reminders.js.map +1 -0
- package/src/lib/app-utils/crm.d.ts +1546 -0
- package/src/lib/app-utils/crm.js +1814 -0
- package/src/lib/app-utils/crm.js.map +1 -0
- package/src/lib/app-utils/csp-report.d.ts +84 -0
- package/src/lib/app-utils/csp-report.js +177 -0
- package/src/lib/app-utils/csp-report.js.map +1 -0
- package/src/lib/app-utils/csv-import.d.ts +192 -0
- package/src/lib/app-utils/csv-import.js +279 -0
- package/src/lib/app-utils/csv-import.js.map +1 -0
- package/src/lib/app-utils/dataset-csv.d.ts +109 -0
- package/src/lib/app-utils/dataset-csv.js +235 -0
- package/src/lib/app-utils/dataset-csv.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +194 -0
- package/src/lib/app-utils/dataset-models.js +409 -0
- package/src/lib/app-utils/dataset-models.js.map +1 -0
- package/src/lib/app-utils/dataset-query.d.ts +57 -0
- package/src/lib/app-utils/dataset-query.js +126 -0
- package/src/lib/app-utils/dataset-query.js.map +1 -0
- package/src/lib/app-utils/datasets.d.ts +136 -0
- package/src/lib/app-utils/datasets.js +177 -0
- package/src/lib/app-utils/datasets.js.map +1 -0
- package/src/lib/app-utils/decompress.d.ts +36 -0
- package/src/lib/app-utils/decompress.js +32 -0
- package/src/lib/app-utils/decompress.js.map +1 -0
- package/src/lib/app-utils/dedicated-sending-domain.d.ts +47 -0
- package/src/lib/app-utils/dedicated-sending-domain.js +114 -0
- package/src/lib/app-utils/dedicated-sending-domain.js.map +1 -0
- package/src/lib/app-utils/deferred-image.d.ts +86 -0
- package/src/lib/app-utils/deferred-image.js +83 -0
- package/src/lib/app-utils/deferred-image.js.map +1 -0
- package/src/lib/app-utils/definition-canvas-tree.d.ts +61 -0
- package/src/lib/app-utils/definition-canvas-tree.js +126 -0
- package/src/lib/app-utils/definition-canvas-tree.js.map +1 -0
- package/src/lib/app-utils/deployment-shape.d.ts +167 -0
- package/src/lib/app-utils/deployment-shape.js +238 -0
- package/src/lib/app-utils/deployment-shape.js.map +1 -0
- package/src/lib/app-utils/detect-template-placeholders.d.ts +30 -0
- package/src/lib/app-utils/detect-template-placeholders.js +53 -0
- package/src/lib/app-utils/detect-template-placeholders.js.map +1 -0
- package/src/lib/app-utils/dmca-counter-notice.d.ts +185 -0
- package/src/lib/app-utils/dmca-counter-notice.js +277 -0
- package/src/lib/app-utils/dmca-counter-notice.js.map +1 -0
- package/src/lib/app-utils/docs-deflection.d.ts +156 -0
- package/src/lib/app-utils/docs-deflection.js +547 -0
- package/src/lib/app-utils/docs-deflection.js.map +1 -0
- package/src/lib/app-utils/docs-help.d.ts +57 -0
- package/src/lib/app-utils/docs-help.generated.d.ts +303 -0
- package/src/lib/app-utils/docs-help.generated.js +867 -0
- package/src/lib/app-utils/docs-help.generated.js.map +1 -0
- package/src/lib/app-utils/docs-help.js +46 -0
- package/src/lib/app-utils/docs-help.js.map +1 -0
- package/src/lib/app-utils/docs-index.generated.d.ts +29 -0
- package/src/lib/app-utils/docs-index.generated.js +8388 -0
- package/src/lib/app-utils/docs-index.generated.js.map +1 -0
- package/src/lib/app-utils/docs-retrieval.d.ts +67 -0
- package/src/lib/app-utils/docs-retrieval.js +188 -0
- package/src/lib/app-utils/docs-retrieval.js.map +1 -0
- package/src/lib/app-utils/document-landmark.d.ts +50 -0
- package/src/lib/app-utils/document-landmark.js +100 -0
- package/src/lib/app-utils/document-landmark.js.map +1 -0
- package/src/lib/app-utils/duplicate-resource.d.ts +101 -0
- package/src/lib/app-utils/duplicate-resource.js +206 -0
- package/src/lib/app-utils/duplicate-resource.js.map +1 -0
- package/src/lib/app-utils/dynamic-list-rule.d.ts +471 -0
- package/src/lib/app-utils/dynamic-list-rule.js +914 -0
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -0
- package/src/lib/app-utils/element-animation.d.ts +200 -0
- package/src/lib/app-utils/element-animation.js +233 -0
- package/src/lib/app-utils/element-animation.js.map +1 -0
- package/src/lib/app-utils/element-hidden-style.d.ts +46 -0
- package/src/lib/app-utils/element-hidden-style.js +48 -0
- package/src/lib/app-utils/element-hidden-style.js.map +1 -0
- package/src/lib/app-utils/element-ui.d.ts +243 -0
- package/src/lib/app-utils/element-ui.js +459 -0
- package/src/lib/app-utils/element-ui.js.map +1 -0
- package/src/lib/app-utils/email-starter-policy.d.ts +160 -0
- package/src/lib/app-utils/email-starter-policy.js +327 -0
- package/src/lib/app-utils/email-starter-policy.js.map +1 -0
- package/src/lib/app-utils/email-topics.d.ts +310 -0
- package/src/lib/app-utils/email-topics.js +336 -0
- package/src/lib/app-utils/email-topics.js.map +1 -0
- package/src/lib/app-utils/enabled-plugins-context.d.ts +100 -0
- package/src/lib/app-utils/enabled-plugins-context.js +113 -0
- package/src/lib/app-utils/enabled-plugins-context.js.map +1 -0
- package/src/lib/app-utils/ensure-canvas-root.d.ts +38 -0
- package/src/lib/app-utils/ensure-canvas-root.js +61 -0
- package/src/lib/app-utils/ensure-canvas-root.js.map +1 -0
- package/src/lib/app-utils/entity-picker-context.d.ts +199 -0
- package/src/lib/app-utils/entity-picker-context.js +93 -0
- package/src/lib/app-utils/entity-picker-context.js.map +1 -0
- package/src/lib/app-utils/error-beacon.d.ts +107 -0
- package/src/lib/app-utils/error-beacon.js +296 -0
- package/src/lib/app-utils/error-beacon.js.map +1 -0
- package/src/lib/app-utils/expand-repeatables.d.ts +172 -0
- package/src/lib/app-utils/expand-repeatables.js +299 -0
- package/src/lib/app-utils/expand-repeatables.js.map +1 -0
- package/src/lib/app-utils/foreign-script.d.ts +82 -0
- package/src/lib/app-utils/foreign-script.js +102 -0
- package/src/lib/app-utils/foreign-script.js.map +1 -0
- package/src/lib/app-utils/form-abuse-ceiling.d.ts +146 -0
- package/src/lib/app-utils/form-abuse-ceiling.js +158 -0
- package/src/lib/app-utils/form-abuse-ceiling.js.map +1 -0
- package/src/lib/app-utils/form-contract.d.ts +198 -0
- package/src/lib/app-utils/form-contract.js +282 -0
- package/src/lib/app-utils/form-contract.js.map +1 -0
- package/src/lib/app-utils/form-dataset-binding.d.ts +50 -0
- package/src/lib/app-utils/form-dataset-binding.js +74 -0
- package/src/lib/app-utils/form-dataset-binding.js.map +1 -0
- package/src/lib/app-utils/forms.d.ts +727 -0
- package/src/lib/app-utils/forms.js +777 -0
- package/src/lib/app-utils/forms.js.map +1 -0
- package/src/lib/app-utils/functions.d.ts +188 -0
- package/src/lib/app-utils/functions.js +529 -0
- package/src/lib/app-utils/functions.js.map +1 -0
- package/src/lib/app-utils/guarded-version-save.d.ts +91 -0
- package/src/lib/app-utils/guarded-version-save.js +131 -0
- package/src/lib/app-utils/guarded-version-save.js.map +1 -0
- package/src/lib/app-utils/health-report.d.ts +1766 -0
- package/src/lib/app-utils/health-report.js +2072 -0
- package/src/lib/app-utils/health-report.js.map +1 -0
- package/src/lib/app-utils/host-naming.d.ts +135 -0
- package/src/lib/app-utils/host-naming.js +188 -0
- package/src/lib/app-utils/host-naming.js.map +1 -0
- package/src/lib/app-utils/host-permissions.d.ts +76 -0
- package/src/lib/app-utils/host-permissions.js +119 -0
- package/src/lib/app-utils/host-permissions.js.map +1 -0
- package/src/lib/app-utils/host-tokens.d.ts +228 -0
- package/src/lib/app-utils/host-tokens.js +304 -0
- package/src/lib/app-utils/host-tokens.js.map +1 -0
- package/src/lib/app-utils/idp-profile.d.ts +83 -0
- package/src/lib/app-utils/idp-profile.js +268 -0
- package/src/lib/app-utils/idp-profile.js.map +1 -0
- package/src/lib/app-utils/image-upload-types.d.ts +49 -0
- package/src/lib/app-utils/image-upload-types.js +86 -0
- package/src/lib/app-utils/image-upload-types.js.map +1 -0
- package/src/lib/app-utils/index.d.ts +18 -0
- package/src/lib/app-utils/index.js +23 -0
- package/src/lib/app-utils/index.js.map +1 -0
- package/src/lib/app-utils/internal-traffic.d.ts +197 -0
- package/src/lib/app-utils/internal-traffic.js +288 -0
- package/src/lib/app-utils/internal-traffic.js.map +1 -0
- package/src/lib/app-utils/lineal-order.d.ts +62 -0
- package/src/lib/app-utils/lineal-order.js +65 -0
- package/src/lib/app-utils/lineal-order.js.map +1 -0
- package/src/lib/app-utils/link-references.d.ts +36 -0
- package/src/lib/app-utils/link-references.js +89 -0
- package/src/lib/app-utils/link-references.js.map +1 -0
- package/src/lib/app-utils/link-target-search-context.d.ts +123 -0
- package/src/lib/app-utils/link-target-search-context.js +221 -0
- package/src/lib/app-utils/link-target-search-context.js.map +1 -0
- package/src/lib/app-utils/list-assignment-policy.d.ts +169 -0
- package/src/lib/app-utils/list-assignment-policy.js +170 -0
- package/src/lib/app-utils/list-assignment-policy.js.map +1 -0
- package/src/lib/app-utils/list-import.d.ts +158 -0
- package/src/lib/app-utils/list-import.js +332 -0
- package/src/lib/app-utils/list-import.js.map +1 -0
- package/src/lib/app-utils/llms-txt.d.ts +104 -0
- package/src/lib/app-utils/llms-txt.js +144 -0
- package/src/lib/app-utils/llms-txt.js.map +1 -0
- package/src/lib/app-utils/local-storage-budget.d.ts +75 -0
- package/src/lib/app-utils/local-storage-budget.js +153 -0
- package/src/lib/app-utils/local-storage-budget.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +698 -0
- package/src/lib/app-utils/lockdown.js +929 -0
- package/src/lib/app-utils/lockdown.js.map +1 -0
- package/src/lib/app-utils/margin-utilization.d.ts +267 -0
- package/src/lib/app-utils/margin-utilization.js +351 -0
- package/src/lib/app-utils/margin-utilization.js.map +1 -0
- package/src/lib/app-utils/markdown-lite.d.ts +297 -0
- package/src/lib/app-utils/markdown-lite.js +705 -0
- package/src/lib/app-utils/markdown-lite.js.map +1 -0
- package/src/lib/app-utils/marketing-consent.d.ts +704 -0
- package/src/lib/app-utils/marketing-consent.js +783 -0
- package/src/lib/app-utils/marketing-consent.js.map +1 -0
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +120 -0
- package/src/lib/app-utils/marketplace-listing-visibility.js +139 -0
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +1 -0
- package/src/lib/app-utils/marketplace-overrides.d.ts +271 -0
- package/src/lib/app-utils/marketplace-overrides.js +462 -0
- package/src/lib/app-utils/marketplace-overrides.js.map +1 -0
- package/src/lib/app-utils/marketplace-provenance.d.ts +150 -0
- package/src/lib/app-utils/marketplace-provenance.js +136 -0
- package/src/lib/app-utils/marketplace-provenance.js.map +1 -0
- package/src/lib/app-utils/marketplace-theme.d.ts +237 -0
- package/src/lib/app-utils/marketplace-theme.js +525 -0
- package/src/lib/app-utils/marketplace-theme.js.map +1 -0
- package/src/lib/app-utils/marketplace-update-state.d.ts +119 -0
- package/src/lib/app-utils/marketplace-update-state.js +132 -0
- package/src/lib/app-utils/marketplace-update-state.js.map +1 -0
- package/src/lib/app-utils/marketplace-verification.d.ts +95 -0
- package/src/lib/app-utils/marketplace-verification.js +81 -0
- package/src/lib/app-utils/marketplace-verification.js.map +1 -0
- package/src/lib/app-utils/measure-node-map.d.ts +76 -0
- package/src/lib/app-utils/measure-node-map.js +111 -0
- package/src/lib/app-utils/measure-node-map.js.map +1 -0
- package/src/lib/app-utils/media-alt.d.ts +55 -0
- package/src/lib/app-utils/media-alt.js +58 -0
- package/src/lib/app-utils/media-alt.js.map +1 -0
- package/src/lib/app-utils/media-asset-facts.d.ts +125 -0
- package/src/lib/app-utils/media-asset-facts.js +467 -0
- package/src/lib/app-utils/media-asset-facts.js.map +1 -0
- package/src/lib/app-utils/media-cdn-scope.d.ts +65 -0
- package/src/lib/app-utils/media-cdn-scope.js +75 -0
- package/src/lib/app-utils/media-cdn-scope.js.map +1 -0
- package/src/lib/app-utils/media-folders.d.ts +161 -0
- package/src/lib/app-utils/media-folders.js +230 -0
- package/src/lib/app-utils/media-folders.js.map +1 -0
- package/src/lib/app-utils/media-metadata.d.ts +277 -0
- package/src/lib/app-utils/media-metadata.js +388 -0
- package/src/lib/app-utils/media-metadata.js.map +1 -0
- package/src/lib/app-utils/media-picker-context.d.ts +93 -0
- package/src/lib/app-utils/media-picker-context.js +26 -0
- package/src/lib/app-utils/media-picker-context.js.map +1 -0
- package/src/lib/app-utils/media-quarantine.d.ts +247 -0
- package/src/lib/app-utils/media-quarantine.js +323 -0
- package/src/lib/app-utils/media-quarantine.js.map +1 -0
- package/src/lib/app-utils/media-ref.d.ts +661 -0
- package/src/lib/app-utils/media-ref.js +1055 -0
- package/src/lib/app-utils/media-ref.js.map +1 -0
- package/src/lib/app-utils/media-takedown-reach.d.ts +126 -0
- package/src/lib/app-utils/media-takedown-reach.js +143 -0
- package/src/lib/app-utils/media-takedown-reach.js.map +1 -0
- package/src/lib/app-utils/member-email-aliases.d.ts +180 -0
- package/src/lib/app-utils/member-email-aliases.js +217 -0
- package/src/lib/app-utils/member-email-aliases.js.map +1 -0
- package/src/lib/app-utils/merge-node-sx.d.ts +47 -0
- package/src/lib/app-utils/merge-node-sx.js +123 -0
- package/src/lib/app-utils/merge-node-sx.js.map +1 -0
- package/src/lib/app-utils/name-match.d.ts +155 -0
- package/src/lib/app-utils/name-match.js +175 -0
- package/src/lib/app-utils/name-match.js.map +1 -0
- package/src/lib/app-utils/name-search.d.ts +117 -0
- package/src/lib/app-utils/name-search.js +145 -0
- package/src/lib/app-utils/name-search.js.map +1 -0
- package/src/lib/app-utils/node-capabilities.d.ts +85 -0
- package/src/lib/app-utils/node-capabilities.js +88 -0
- package/src/lib/app-utils/node-capabilities.js.map +1 -0
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +164 -0
- package/src/lib/app-utils/node-definition-sanitizer.js +402 -0
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -0
- package/src/lib/app-utils/node-identity.d.ts +47 -0
- package/src/lib/app-utils/node-identity.js +50 -0
- package/src/lib/app-utils/node-identity.js.map +1 -0
- package/src/lib/app-utils/node-interactions.d.ts +102 -0
- package/src/lib/app-utils/node-interactions.js +192 -0
- package/src/lib/app-utils/node-interactions.js.map +1 -0
- package/src/lib/app-utils/node-url-policy.d.ts +54 -0
- package/src/lib/app-utils/node-url-policy.js +72 -0
- package/src/lib/app-utils/node-url-policy.js.map +1 -0
- package/src/lib/app-utils/notifications.d.ts +71 -0
- package/src/lib/app-utils/notifications.js +101 -0
- package/src/lib/app-utils/notifications.js.map +1 -0
- package/src/lib/app-utils/onboarding-deep-link.d.ts +120 -0
- package/src/lib/app-utils/onboarding-deep-link.js +142 -0
- package/src/lib/app-utils/onboarding-deep-link.js.map +1 -0
- package/src/lib/app-utils/operator-identity.d.ts +207 -0
- package/src/lib/app-utils/operator-identity.js +186 -0
- package/src/lib/app-utils/operator-identity.js.map +1 -0
- package/src/lib/app-utils/org-billing-doc.d.ts +231 -0
- package/src/lib/app-utils/org-billing-doc.js +238 -0
- package/src/lib/app-utils/org-billing-doc.js.map +1 -0
- package/src/lib/app-utils/org-override-reason.d.ts +100 -0
- package/src/lib/app-utils/org-override-reason.js +116 -0
- package/src/lib/app-utils/org-override-reason.js.map +1 -0
- package/src/lib/app-utils/org-permissions.d.ts +194 -0
- package/src/lib/app-utils/org-permissions.js +357 -0
- package/src/lib/app-utils/org-permissions.js.map +1 -0
- package/src/lib/app-utils/org-roles.d.ts +72 -0
- package/src/lib/app-utils/org-roles.js +131 -0
- package/src/lib/app-utils/org-roles.js.map +1 -0
- package/src/lib/app-utils/organizations.d.ts +407 -0
- package/src/lib/app-utils/organizations.js +511 -0
- package/src/lib/app-utils/organizations.js.map +1 -0
- package/src/lib/app-utils/page-header-actions-context.d.ts +83 -0
- package/src/lib/app-utils/page-header-actions-context.js +58 -0
- package/src/lib/app-utils/page-header-actions-context.js.map +1 -0
- package/src/lib/app-utils/page-header-record-context.d.ts +80 -0
- package/src/lib/app-utils/page-header-record-context.js +64 -0
- package/src/lib/app-utils/page-header-record-context.js.map +1 -0
- package/src/lib/app-utils/page-markdown.d.ts +103 -0
- package/src/lib/app-utils/page-markdown.js +385 -0
- package/src/lib/app-utils/page-markdown.js.map +1 -0
- package/src/lib/app-utils/paid-media-source.d.ts +90 -0
- package/src/lib/app-utils/paid-media-source.js +184 -0
- package/src/lib/app-utils/paid-media-source.js.map +1 -0
- package/src/lib/app-utils/palette-sx.d.ts +34 -0
- package/src/lib/app-utils/palette-sx.js +150 -0
- package/src/lib/app-utils/palette-sx.js.map +1 -0
- package/src/lib/app-utils/password-policy.d.ts +47 -0
- package/src/lib/app-utils/password-policy.js +46 -0
- package/src/lib/app-utils/password-policy.js.map +1 -0
- package/src/lib/app-utils/payments-configured.d.ts +84 -0
- package/src/lib/app-utils/payments-configured.js +88 -0
- package/src/lib/app-utils/payments-configured.js.map +1 -0
- package/src/lib/app-utils/person-erasure.d.ts +126 -0
- package/src/lib/app-utils/person-erasure.js +121 -0
- package/src/lib/app-utils/person-erasure.js.map +1 -0
- package/src/lib/app-utils/person-key.d.ts +32 -0
- package/src/lib/app-utils/person-key.js +62 -0
- package/src/lib/app-utils/person-key.js.map +1 -0
- package/src/lib/app-utils/plan-entitlements.d.ts +2756 -0
- package/src/lib/app-utils/plan-entitlements.js +4085 -0
- package/src/lib/app-utils/plan-entitlements.js.map +1 -0
- package/src/lib/app-utils/platform-ad-conversions.d.ts +122 -0
- package/src/lib/app-utils/platform-ad-conversions.js +174 -0
- package/src/lib/app-utils/platform-ad-conversions.js.map +1 -0
- package/src/lib/app-utils/platform-advertising-tags.d.ts +139 -0
- package/src/lib/app-utils/platform-advertising-tags.js +203 -0
- package/src/lib/app-utils/platform-advertising-tags.js.map +1 -0
- package/src/lib/app-utils/platform-brand.d.ts +151 -0
- package/src/lib/app-utils/platform-brand.js +175 -0
- package/src/lib/app-utils/platform-brand.js.map +1 -0
- package/src/lib/app-utils/platform-consent-default.d.ts +142 -0
- package/src/lib/app-utils/platform-consent-default.js +295 -0
- package/src/lib/app-utils/platform-consent-default.js.map +1 -0
- package/src/lib/app-utils/platform-marketing-consent.d.ts +151 -0
- package/src/lib/app-utils/platform-marketing-consent.js +182 -0
- package/src/lib/app-utils/platform-marketing-consent.js.map +1 -0
- package/src/lib/app-utils/platform-marketing-host.d.ts +33 -0
- package/src/lib/app-utils/platform-marketing-host.js +97 -0
- package/src/lib/app-utils/platform-marketing-host.js.map +1 -0
- package/src/lib/app-utils/platform-visitor-consent.d.ts +252 -0
- package/src/lib/app-utils/platform-visitor-consent.js +533 -0
- package/src/lib/app-utils/platform-visitor-consent.js.map +1 -0
- package/src/lib/app-utils/plugin-api-cross-origin.d.ts +61 -0
- package/src/lib/app-utils/plugin-api-cross-origin.js +202 -0
- package/src/lib/app-utils/plugin-api-cross-origin.js.map +1 -0
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +192 -0
- package/src/lib/app-utils/plugin-api-rate-limit.js +270 -0
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -0
- package/src/lib/app-utils/plugin-artifact-path.d.ts +32 -0
- package/src/lib/app-utils/plugin-artifact-path.js +33 -0
- package/src/lib/app-utils/plugin-artifact-path.js.map +1 -0
- package/src/lib/app-utils/plugin-bundle-checks.d.ts +148 -0
- package/src/lib/app-utils/plugin-bundle-checks.js +989 -0
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -0
- package/src/lib/app-utils/plugin-manifest.d.ts +516 -0
- package/src/lib/app-utils/plugin-manifest.js +687 -0
- package/src/lib/app-utils/plugin-manifest.js.map +1 -0
- package/src/lib/app-utils/published-legal-pages.d.ts +71 -0
- package/src/lib/app-utils/published-legal-pages.js +90 -0
- package/src/lib/app-utils/published-legal-pages.js.map +1 -0
- package/src/lib/app-utils/publisher-agreement.d.ts +254 -0
- package/src/lib/app-utils/publisher-agreement.js +274 -0
- package/src/lib/app-utils/publisher-agreement.js.map +1 -0
- package/src/lib/app-utils/publisher-attestation.d.ts +99 -0
- package/src/lib/app-utils/publisher-attestation.js +158 -0
- package/src/lib/app-utils/publisher-attestation.js.map +1 -0
- package/src/lib/app-utils/recipient-email-render.d.ts +216 -0
- package/src/lib/app-utils/recipient-email-render.js +221 -0
- package/src/lib/app-utils/recipient-email-render.js.map +1 -0
- package/src/lib/app-utils/redispatch-caught-error.d.ts +38 -0
- package/src/lib/app-utils/redispatch-caught-error.js +46 -0
- package/src/lib/app-utils/redispatch-caught-error.js.map +1 -0
- package/src/lib/app-utils/registering-plugin.d.ts +19 -0
- package/src/lib/app-utils/registering-plugin.js +38 -0
- package/src/lib/app-utils/registering-plugin.js.map +1 -0
- package/src/lib/app-utils/release-flags.d.ts +283 -0
- package/src/lib/app-utils/release-flags.js +518 -0
- package/src/lib/app-utils/release-flags.js.map +1 -0
- package/src/lib/app-utils/repair-canvas-nodes.d.ts +130 -0
- package/src/lib/app-utils/repair-canvas-nodes.js +298 -0
- package/src/lib/app-utils/repair-canvas-nodes.js.map +1 -0
- package/src/lib/app-utils/repeat-infringer.d.ts +166 -0
- package/src/lib/app-utils/repeat-infringer.js +188 -0
- package/src/lib/app-utils/repeat-infringer.js.map +1 -0
- package/src/lib/app-utils/repeat-sources.d.ts +115 -0
- package/src/lib/app-utils/repeat-sources.js +86 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -0
- package/src/lib/app-utils/request-geo.d.ts +114 -0
- package/src/lib/app-utils/request-geo.js +247 -0
- package/src/lib/app-utils/request-geo.js.map +1 -0
- package/src/lib/app-utils/request-ip.d.ts +213 -0
- package/src/lib/app-utils/request-ip.js +344 -0
- package/src/lib/app-utils/request-ip.js.map +1 -0
- package/src/lib/app-utils/resolve-named-tokens.d.ts +26 -0
- package/src/lib/app-utils/resolve-named-tokens.js +59 -0
- package/src/lib/app-utils/resolve-named-tokens.js.map +1 -0
- package/src/lib/app-utils/responsive-typography-sx.d.ts +77 -0
- package/src/lib/app-utils/responsive-typography-sx.js +122 -0
- package/src/lib/app-utils/responsive-typography-sx.js.map +1 -0
- package/src/lib/app-utils/reusable-component-keys.d.ts +135 -0
- package/src/lib/app-utils/reusable-component-keys.js +140 -0
- package/src/lib/app-utils/reusable-component-keys.js.map +1 -0
- package/src/lib/app-utils/reusable-prop-values.d.ts +199 -0
- package/src/lib/app-utils/reusable-prop-values.js +494 -0
- package/src/lib/app-utils/reusable-prop-values.js.map +1 -0
- package/src/lib/app-utils/safe-json-ld.d.ts +29 -0
- package/src/lib/app-utils/safe-json-ld.js +37 -0
- package/src/lib/app-utils/safe-json-ld.js.map +1 -0
- package/src/lib/app-utils/sanitize-svg.d.ts +55 -0
- package/src/lib/app-utils/sanitize-svg.js +460 -0
- package/src/lib/app-utils/sanitize-svg.js.map +1 -0
- package/src/lib/app-utils/scheme-sx.d.ts +84 -0
- package/src/lib/app-utils/scheme-sx.js +148 -0
- package/src/lib/app-utils/scheme-sx.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +249 -0
- package/src/lib/app-utils/scope-tokens.js +331 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -0
- package/src/lib/app-utils/screen-link-context-value.d.ts +57 -0
- package/src/lib/app-utils/screen-link-context-value.js +43 -0
- package/src/lib/app-utils/screen-link-context-value.js.map +1 -0
- package/src/lib/app-utils/screen-link-context.d.ts +185 -0
- package/src/lib/app-utils/screen-link-context.js +304 -0
- package/src/lib/app-utils/screen-link-context.js.map +1 -0
- package/src/lib/app-utils/screen-link-value.d.ts +269 -0
- package/src/lib/app-utils/screen-link-value.js +384 -0
- package/src/lib/app-utils/screen-link-value.js.map +1 -0
- package/src/lib/app-utils/screen-route.d.ts +669 -0
- package/src/lib/app-utils/screen-route.js +751 -0
- package/src/lib/app-utils/screen-route.js.map +1 -0
- package/src/lib/app-utils/screen-seo-fields.d.ts +37 -0
- package/src/lib/app-utils/screen-seo-fields.js +42 -0
- package/src/lib/app-utils/screen-seo-fields.js.map +1 -0
- package/src/lib/app-utils/search-indexing.d.ts +162 -0
- package/src/lib/app-utils/search-indexing.js +207 -0
- package/src/lib/app-utils/search-indexing.js.map +1 -0
- package/src/lib/app-utils/seo-listing-fields.d.ts +70 -0
- package/src/lib/app-utils/seo-listing-fields.js +75 -0
- package/src/lib/app-utils/seo-listing-fields.js.map +1 -0
- package/src/lib/app-utils/seo-locale.d.ts +119 -0
- package/src/lib/app-utils/seo-locale.js +133 -0
- package/src/lib/app-utils/seo-locale.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.d.ts +149 -0
- package/src/lib/app-utils/seo-title-variables.js +190 -0
- package/src/lib/app-utils/seo-title-variables.js.map +1 -0
- package/src/lib/app-utils/seo-title.d.ts +70 -0
- package/src/lib/app-utils/seo-title.js +117 -0
- package/src/lib/app-utils/seo-title.js.map +1 -0
- package/src/lib/app-utils/server.d.ts +174 -0
- package/src/lib/app-utils/server.js +314 -0
- package/src/lib/app-utils/server.js.map +1 -0
- package/src/lib/app-utils/site-context.d.ts +106 -0
- package/src/lib/app-utils/site-context.js +100 -0
- package/src/lib/app-utils/site-context.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +117 -0
- package/src/lib/app-utils/sitemap.js +183 -0
- package/src/lib/app-utils/sitemap.js.map +1 -0
- package/src/lib/app-utils/social-image.d.ts +112 -0
- package/src/lib/app-utils/social-image.js +191 -0
- package/src/lib/app-utils/social-image.js.map +1 -0
- package/src/lib/app-utils/starter-templates.d.ts +99 -0
- package/src/lib/app-utils/starter-templates.js +579 -0
- package/src/lib/app-utils/starter-templates.js.map +1 -0
- package/src/lib/app-utils/stored-nodes.d.ts +120 -0
- package/src/lib/app-utils/stored-nodes.js +174 -0
- package/src/lib/app-utils/stored-nodes.js.map +1 -0
- package/src/lib/app-utils/strip-undefined.d.ts +59 -0
- package/src/lib/app-utils/strip-undefined.js +95 -0
- package/src/lib/app-utils/strip-undefined.js.map +1 -0
- package/src/lib/app-utils/stripe-deployment-mode.d.ts +47 -0
- package/src/lib/app-utils/stripe-deployment-mode.js +70 -0
- package/src/lib/app-utils/stripe-deployment-mode.js.map +1 -0
- package/src/lib/app-utils/support-tiers.d.ts +108 -0
- package/src/lib/app-utils/support-tiers.js +201 -0
- package/src/lib/app-utils/support-tiers.js.map +1 -0
- package/src/lib/app-utils/timezone-geo-hint.d.ts +36 -0
- package/src/lib/app-utils/timezone-geo-hint.js +180 -0
- package/src/lib/app-utils/timezone-geo-hint.js.map +1 -0
- package/src/lib/app-utils/upload-cors.d.ts +155 -0
- package/src/lib/app-utils/upload-cors.js +254 -0
- package/src/lib/app-utils/upload-cors.js.map +1 -0
- package/src/lib/app-utils/upload-inspection.d.ts +159 -0
- package/src/lib/app-utils/upload-inspection.js +539 -0
- package/src/lib/app-utils/upload-inspection.js.map +1 -0
- package/src/lib/app-utils/url-slug.d.ts +40 -0
- package/src/lib/app-utils/url-slug.js +42 -0
- package/src/lib/app-utils/url-slug.js.map +1 -0
- package/src/lib/app-utils/usage-budget.d.ts +429 -0
- package/src/lib/app-utils/usage-budget.js +421 -0
- package/src/lib/app-utils/usage-budget.js.map +1 -0
- package/src/lib/app-utils/variables.d.ts +96 -0
- package/src/lib/app-utils/variables.js +233 -0
- package/src/lib/app-utils/variables.js.map +1 -0
- package/src/lib/app-utils/video-asset-facts.d.ts +61 -0
- package/src/lib/app-utils/video-asset-facts.js +70 -0
- package/src/lib/app-utils/video-asset-facts.js.map +1 -0
- package/src/lib/app-utils/video-object.d.ts +89 -0
- package/src/lib/app-utils/video-object.js +245 -0
- package/src/lib/app-utils/video-object.js.map +1 -0
- package/src/lib/app-utils/visitor-consent.d.ts +757 -0
- package/src/lib/app-utils/visitor-consent.js +981 -0
- package/src/lib/app-utils/visitor-consent.js.map +1 -0
- package/src/lib/app-utils/visitor-record-ceiling.d.ts +223 -0
- package/src/lib/app-utils/visitor-record-ceiling.js +215 -0
- package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -0
- package/src/lib/app-utils/web-vitals-rum.d.ts +53 -0
- package/src/lib/app-utils/web-vitals-rum.js +278 -0
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -0
- package/src/lib/app-utils/webhook-delivery.d.ts +324 -0
- package/src/lib/app-utils/webhook-delivery.js +413 -0
- package/src/lib/app-utils/webhook-delivery.js.map +1 -0
- package/src/lib/app-utils/where-used.d.ts +57 -0
- package/src/lib/app-utils/where-used.js +59 -0
- package/src/lib/app-utils/where-used.js.map +1 -0
- package/src/lib/app-utils/wistia-embed.d.ts +86 -0
- package/src/lib/app-utils/wistia-embed.js +119 -0
- package/src/lib/app-utils/wistia-embed.js.map +1 -0
- package/src/lib/app-utils/workflows.d.ts +136 -0
- package/src/lib/app-utils/workflows.js +346 -0
- package/src/lib/app-utils/workflows.js.map +1 -0
- package/src/lib/canvas-manager/canvas-manager-tree.d.ts +109 -0
- package/src/lib/canvas-manager/canvas-manager-tree.js +139 -0
- package/src/lib/canvas-manager/canvas-manager-tree.js.map +1 -0
- package/src/lib/canvas-manager/canvas-manager.d.ts +549 -0
- package/src/lib/canvas-manager/canvas-manager.js +1311 -0
- package/src/lib/canvas-manager/canvas-manager.js.map +1 -0
- package/src/lib/canvas-manager/index.d.ts +20 -0
- package/src/lib/canvas-manager/index.js +21 -0
- package/src/lib/canvas-manager/index.js.map +1 -0
- package/src/lib/canvas-manager/stores/index.d.ts +17 -0
- package/src/lib/canvas-manager/stores/index.js +18 -0
- package/src/lib/canvas-manager/stores/index.js.map +1 -0
- package/src/lib/canvas-manager/stores/node.store.d.ts +30 -0
- package/src/lib/canvas-manager/stores/node.store.js +45 -0
- package/src/lib/canvas-manager/stores/node.store.js.map +1 -0
- package/src/lib/components-manager/components-manager.d.ts +56 -0
- package/src/lib/components-manager/components-manager.js +191 -0
- package/src/lib/components-manager/components-manager.js.map +1 -0
- package/src/lib/components-manager/index.d.ts +18 -0
- package/src/lib/components-manager/index.js +19 -0
- package/src/lib/components-manager/index.js.map +1 -0
- package/src/lib/emit-manager/emit-manager.d.ts +56 -0
- package/src/lib/emit-manager/emit-manager.js +60 -0
- package/src/lib/emit-manager/emit-manager.js.map +1 -0
- package/src/lib/emit-manager/index.d.ts +18 -0
- package/src/lib/emit-manager/index.js +19 -0
- package/src/lib/emit-manager/index.js.map +1 -0
- package/src/lib/foundation/constants/_internal.d.ts +18 -0
- package/src/lib/foundation/constants/_internal.js +62 -0
- package/src/lib/foundation/constants/_internal.js.map +1 -0
- package/src/lib/foundation/constants/app.d.ts +23 -0
- package/src/lib/foundation/constants/app.js +25 -0
- package/src/lib/foundation/constants/app.js.map +1 -0
- package/src/lib/foundation/constants/canvas.d.ts +18 -0
- package/src/lib/foundation/constants/canvas.js +18 -0
- package/src/lib/foundation/constants/canvas.js.map +1 -0
- package/src/lib/foundation/constants/components.d.ts +54 -0
- package/src/lib/foundation/constants/components.js +61 -0
- package/src/lib/foundation/constants/components.js.map +1 -0
- package/src/lib/foundation/constants/shared.d.ts +50 -0
- package/src/lib/foundation/constants/shared.js +49 -0
- package/src/lib/foundation/constants/shared.js.map +1 -0
- package/src/lib/foundation/constants/symbol.d.ts +63 -0
- package/src/lib/foundation/constants/symbol.js +75 -0
- package/src/lib/foundation/constants/symbol.js.map +1 -0
- package/src/lib/foundation/definitions/components.types.d.ts +372 -0
- package/src/lib/foundation/definitions/components.types.js +180 -0
- package/src/lib/foundation/definitions/components.types.js.map +1 -0
- package/src/lib/foundation/definitions/contact.types.d.ts +73 -0
- package/src/lib/foundation/definitions/contact.types.js +107 -0
- package/src/lib/foundation/definitions/contact.types.js.map +1 -0
- package/src/lib/foundation/definitions/host-content-collections.d.ts +137 -0
- package/src/lib/foundation/definitions/host-content-collections.js +219 -0
- package/src/lib/foundation/definitions/host-content-collections.js.map +1 -0
- package/src/lib/foundation/definitions/org-billing.types.d.ts +1361 -0
- package/src/lib/foundation/definitions/org-billing.types.js +77 -0
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -0
- package/src/lib/foundation/definitions/organization.types.d.ts +307 -0
- package/src/lib/foundation/definitions/organization.types.js +42 -0
- package/src/lib/foundation/definitions/organization.types.js.map +1 -0
- package/src/lib/foundation/definitions/platform.types.d.ts +1326 -0
- package/src/lib/foundation/definitions/platform.types.js +124 -0
- package/src/lib/foundation/definitions/platform.types.js.map +1 -0
- package/src/lib/foundation/definitions/property-kinds.d.ts +189 -0
- package/src/lib/foundation/definitions/property-kinds.js +565 -0
- package/src/lib/foundation/definitions/property-kinds.js.map +1 -0
- package/src/lib/foundation/definitions/shared.d.ts +23 -0
- package/src/lib/foundation/definitions/shared.js +18 -0
- package/src/lib/foundation/definitions/shared.js.map +1 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +249 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +499 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -0
- package/src/lib/foundation/index.d.ts +32 -0
- package/src/lib/foundation/index.js +67 -0
- package/src/lib/foundation/index.js.map +1 -0
- package/src/lib/lifecycle.d.ts +24 -0
- package/src/lib/lifecycle.js +39 -0
- package/src/lib/lifecycle.js.map +1 -0
- package/src/lib/mst/common.d.ts +17 -0
- package/src/lib/mst/common.js +23 -0
- package/src/lib/mst/common.js.map +1 -0
- package/src/lib/mst/index.d.ts +19 -0
- package/src/lib/mst/index.js +20 -0
- package/src/lib/mst/index.js.map +1 -0
- package/src/lib/mst/json.d.ts +22 -0
- package/src/lib/mst/json.js +23 -0
- package/src/lib/mst/json.js.map +1 -0
- package/src/lib/mst/types.d.ts +20 -0
- package/src/lib/mst/types.js +18 -0
- package/src/lib/mst/types.js.map +1 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.d.ts +77 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.js +55 -0
- package/src/lib/plugin-manager/billing-webhook-hooks.js.map +1 -0
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +172 -0
- package/src/lib/plugin-manager/commerce-zone-props.js +31 -0
- package/src/lib/plugin-manager/commerce-zone-props.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +60 -0
- package/src/lib/plugin-manager/custom-fields.js +39 -0
- package/src/lib/plugin-manager/custom-fields.js.map +1 -0
- package/src/lib/plugin-manager/editor-sessions.d.ts +109 -0
- package/src/lib/plugin-manager/editor-sessions.js +137 -0
- package/src/lib/plugin-manager/editor-sessions.js.map +1 -0
- package/src/lib/plugin-manager/enabled-plugins.d.ts +438 -0
- package/src/lib/plugin-manager/enabled-plugins.js +403 -0
- package/src/lib/plugin-manager/enabled-plugins.js.map +1 -0
- package/src/lib/plugin-manager/feature-plugins.d.ts +1314 -0
- package/src/lib/plugin-manager/feature-plugins.js +609 -0
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +11 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +149 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -0
- package/src/lib/plugin-manager/index.d.ts +42 -0
- package/src/lib/plugin-manager/index.js +46 -0
- package/src/lib/plugin-manager/index.js.map +1 -0
- package/src/lib/plugin-manager/install-presets.d.ts +93 -0
- package/src/lib/plugin-manager/install-presets.js +86 -0
- package/src/lib/plugin-manager/install-presets.js.map +1 -0
- package/src/lib/plugin-manager/media-delivery-provider.d.ts +124 -0
- package/src/lib/plugin-manager/media-delivery-provider.js +53 -0
- package/src/lib/plugin-manager/media-delivery-provider.js.map +1 -0
- package/src/lib/plugin-manager/order-fulfilment.d.ts +142 -0
- package/src/lib/plugin-manager/order-fulfilment.js +104 -0
- package/src/lib/plugin-manager/order-fulfilment.js.map +1 -0
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +122 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +140 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-bridge.d.ts +98 -0
- package/src/lib/plugin-manager/plugin-bridge.js +154 -0
- package/src/lib/plugin-manager/plugin-bridge.js.map +1 -0
- package/src/lib/plugin-manager/plugin-config.d.ts +148 -0
- package/src/lib/plugin-manager/plugin-config.js +228 -0
- package/src/lib/plugin-manager/plugin-config.js.map +1 -0
- package/src/lib/plugin-manager/plugin-console-crons.d.ts +139 -0
- package/src/lib/plugin-manager/plugin-console-crons.js +177 -0
- package/src/lib/plugin-manager/plugin-console-crons.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contact-capture.d.ts +220 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js +89 -0
- package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contributions.d.ts +244 -0
- package/src/lib/plugin-manager/plugin-contributions.js +283 -0
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.d.ts +169 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.js +84 -0
- package/src/lib/plugin-manager/plugin-entitlement-keys.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlements.d.ts +181 -0
- package/src/lib/plugin-manager/plugin-entitlements.js +188 -0
- package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-events.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-events.js +79 -0
- package/src/lib/plugin-manager/plugin-events.js.map +1 -0
- package/src/lib/plugin-manager/plugin-figures.d.ts +251 -0
- package/src/lib/plugin-manager/plugin-figures.js +252 -0
- package/src/lib/plugin-manager/plugin-figures.js.map +1 -0
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +146 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +116 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-jobs.d.ts +130 -0
- package/src/lib/plugin-manager/plugin-jobs.js +182 -0
- package/src/lib/plugin-manager/plugin-jobs.js.map +1 -0
- package/src/lib/plugin-manager/plugin-loader.d.ts +86 -0
- package/src/lib/plugin-manager/plugin-loader.js +223 -0
- package/src/lib/plugin-manager/plugin-loader.js.map +1 -0
- package/src/lib/plugin-manager/plugin-manager.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-manager.js +343 -0
- package/src/lib/plugin-manager/plugin-manager.js.map +1 -0
- package/src/lib/plugin-manager/plugin-metered-lines.d.ts +97 -0
- package/src/lib/plugin-manager/plugin-metered-lines.js +123 -0
- package/src/lib/plugin-manager/plugin-metered-lines.js.map +1 -0
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +52 -0
- package/src/lib/plugin-manager/plugin-org-erasure.js +100 -0
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-permissions.d.ts +69 -0
- package/src/lib/plugin-manager/plugin-permissions.js +77 -0
- package/src/lib/plugin-manager/plugin-permissions.js.map +1 -0
- package/src/lib/plugin-manager/plugin-person-erasure.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-person-erasure.js +109 -0
- package/src/lib/plugin-manager/plugin-person-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-cards.d.ts +99 -0
- package/src/lib/plugin-manager/plugin-record-cards.js +59 -0
- package/src/lib/plugin-manager/plugin-record-cards.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-facts.d.ts +111 -0
- package/src/lib/plugin-manager/plugin-record-facts.js +51 -0
- package/src/lib/plugin-manager/plugin-record-facts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-routes.d.ts +129 -0
- package/src/lib/plugin-manager/plugin-record-routes.js +93 -0
- package/src/lib/plugin-manager/plugin-record-routes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-timeline.d.ts +147 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js +39 -0
- package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.d.ts +137 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.js +51 -0
- package/src/lib/plugin-manager/plugin-resource-drafts.js.map +1 -0
- package/src/lib/plugin-manager/plugin-services.d.ts +94 -0
- package/src/lib/plugin-manager/plugin-services.js +153 -0
- package/src/lib/plugin-manager/plugin-services.js.map +1 -0
- package/src/lib/plugin-manager/plugin-styles-ui.d.ts +71 -0
- package/src/lib/plugin-manager/plugin-styles-ui.js +80 -0
- package/src/lib/plugin-manager/plugin-styles-ui.js.map +1 -0
- package/src/lib/plugin-manager/plugin-styles.d.ts +176 -0
- package/src/lib/plugin-manager/plugin-styles.js +186 -0
- package/src/lib/plugin-manager/plugin-styles.js.map +1 -0
- package/src/lib/plugin-manager/plugin-subprocessors.d.ts +135 -0
- package/src/lib/plugin-manager/plugin-subprocessors.js +129 -0
- package/src/lib/plugin-manager/plugin-subprocessors.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +84 -0
- package/src/lib/plugin-manager/plugin-tax-profile.js +39 -0
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -0
- package/src/lib/plugin-manager/plugin-user-erasure.d.ts +53 -0
- package/src/lib/plugin-manager/plugin-user-erasure.js +84 -0
- package/src/lib/plugin-manager/plugin-user-erasure.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +121 -0
- package/src/lib/plugin-manager/plugin-zones.js +74 -0
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -0
- package/src/lib/plugin-manager/realm-plugins.d.ts +112 -0
- package/src/lib/plugin-manager/realm-plugins.js +196 -0
- package/src/lib/plugin-manager/realm-plugins.js.map +1 -0
- package/src/lib/plugin-manager/realm-server.d.ts +54 -0
- package/src/lib/plugin-manager/realm-server.js +88 -0
- package/src/lib/plugin-manager/realm-server.js.map +1 -0
- package/src/lib/plugin-manager/record-zone-props.d.ts +126 -0
- package/src/lib/plugin-manager/record-zone-props.js +31 -0
- package/src/lib/plugin-manager/record-zone-props.js.map +1 -0
- package/src/lib/plugin-manager/site-page-hooks.d.ts +102 -0
- package/src/lib/plugin-manager/site-page-hooks.js +114 -0
- package/src/lib/plugin-manager/site-page-hooks.js.map +1 -0
- package/src/lib/plugin-manager/site-runtime.d.ts +57 -0
- package/src/lib/plugin-manager/site-runtime.js +25 -0
- package/src/lib/plugin-manager/site-runtime.js.map +1 -0
- package/src/lib/plugin-manager/usage-alert-contributors.d.ts +115 -0
- package/src/lib/plugin-manager/usage-alert-contributors.js +106 -0
- package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -0
- package/src/lib/types/ast.d.ts +199 -0
- package/src/lib/types/ast.js +20 -0
- package/src/lib/types/ast.js.map +1 -0
- package/src/lib/types/index.d.ts +20 -0
- package/src/lib/types/index.js +21 -0
- package/src/lib/types/index.js.map +1 -0
- package/src/lib/types/nodes.d.ts +608 -0
- package/src/lib/types/nodes.js +28 -0
- package/src/lib/types/nodes.js.map +1 -0
- package/src/lib/types/routing.d.ts +17 -0
- package/src/lib/types/routing.js +18 -0
- package/src/lib/types/routing.js.map +1 -0
- package/src/lib/types/screen.d.ts +23 -0
- package/src/lib/types/screen.js +18 -0
- package/src/lib/types/screen.js.map +1 -0
- package/src/lib/utils.d.ts +25 -0
- package/src/lib/utils.js +42 -0
- package/src/lib/utils.js.map +1 -0
- package/src/server.d.ts +37 -0
- package/src/server.js +55 -0
- package/src/server.js.map +1 -0
|
@@ -0,0 +1,1055 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2026 Aglyn LLC
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/ /**
|
|
19
|
+
* Media references (AGL-1215).
|
|
20
|
+
*
|
|
21
|
+
* A node used to persist a media asset's URL. First the firebasestorage
|
|
22
|
+
* download URL, which names the object's CURRENT location — a folder move
|
|
23
|
+
* physically copies the object, rewrites `url` and DELETES the original, so
|
|
24
|
+
* every node holding the old one 404s forever. The first pass at this issue
|
|
25
|
+
* (`b27d96791`) switched the picker to the mediaId-keyed CDN path
|
|
26
|
+
* `/api/media/cdn/{scope}/{mediaId}`, which fixed that.
|
|
27
|
+
*
|
|
28
|
+
* It left a smaller version of the same bug. The persisted document is now
|
|
29
|
+
* coupled to a ROUTE SHAPE — a delivery detail that has already changed once
|
|
30
|
+
* (AGL-829 added the content-hashed third segment) and belongs to the app,
|
|
31
|
+
* not to the content. Change the route and every screen, layout, component
|
|
32
|
+
* and template document on every host has to be migrated in lockstep, in
|
|
33
|
+
* both storage forms, or the sites break. A document should record WHICH
|
|
34
|
+
* ASSET; how to fetch it is the renderer's business.
|
|
35
|
+
*
|
|
36
|
+
* So a node stores `media:{scope}/{mediaId}` and the URL is built at render
|
|
37
|
+
* time. {@link MEDIA_CDN_ROUTE} below is then the only place in the codebase
|
|
38
|
+
* that knows the route shape, and changing it is a deploy rather than a
|
|
39
|
+
* migration.
|
|
40
|
+
*
|
|
41
|
+
* ## Why a token in the existing string field, not `mediaId` + `mediaScope`
|
|
42
|
+
*
|
|
43
|
+
* 1. **"Browse media" is one callback that writes one string.** The besigner
|
|
44
|
+
* offers it for every media-bearing attribute it can spot — `src`,
|
|
45
|
+
* `poster`, `imageUrl` — and hands back a single value. A dedicated prop
|
|
46
|
+
* PAIR would fix `image.src` only, and would need the picker to learn
|
|
47
|
+
* which component pairs which props. A token flows through the plumbing
|
|
48
|
+
* that already exists and covers every one of those fields at once.
|
|
49
|
+
* 2. **Two fields are two fields that can disagree.** `src` has to survive
|
|
50
|
+
* regardless — an author-typed external URL (a hotlinked image) is a real
|
|
51
|
+
* and supported case — so a `mediaId` prop would need a precedence rule
|
|
52
|
+
* against `src` anyway, and a stale `src` sitting next to a fresh
|
|
53
|
+
* `mediaId` is invisible until someone clears the reference. One field
|
|
54
|
+
* holds one value, and what it is is decidable from the value itself.
|
|
55
|
+
* 3. **The field already carries non-URL values.** `{{var:id}}` binding
|
|
56
|
+
* tokens live in exactly this position and resolve at render. A media
|
|
57
|
+
* reference is the same kind of thing, and reads that way to an author.
|
|
58
|
+
*
|
|
59
|
+
* ## The content pin names bytes, and no URL is built from it (AGL-2798)
|
|
60
|
+
*
|
|
61
|
+
* A reference may carry the asset's content hash — `media:{scope}/{id}@{hash}`
|
|
62
|
+
* (AGL-2685). It parses, it round-trips and the where-used scan matches it,
|
|
63
|
+
* but {@link resolveMediaSrc} ignores it: a pinned reference resolves to the
|
|
64
|
+
* same stable URL as an unpinned one.
|
|
65
|
+
*
|
|
66
|
+
* The pin used to resolve to the CDN's content-hashed form,
|
|
67
|
+
* `/api/media/cdn/{scope}/{id}/{hash}`, which is served `immutable` for a
|
|
68
|
+
* year. The case for it was that a stale hash 302s to the stable URL, so a
|
|
69
|
+
* replace would cost one extra hop. That hop only happens when a request
|
|
70
|
+
* reaches the handler, and an immutable response is precisely the one nothing
|
|
71
|
+
* asks about again: Vercel's edge stores it and answers from its copy
|
|
72
|
+
* (measured on production, `MISS` then `HIT`), and every browser that fetched
|
|
73
|
+
* it keeps its own. A page naming that URL showed the replaced bytes for as
|
|
74
|
+
* long as either copy lived, and a replace has to reach every place the asset
|
|
75
|
+
* is used.
|
|
76
|
+
*
|
|
77
|
+
* The two ways to keep the year-long URL were weighed and refused:
|
|
78
|
+
*
|
|
79
|
+
* 1. **Purge the edge on replace.** A purge cannot reach a browser's copy,
|
|
80
|
+
* and it puts a credentialled call to a third-party API on the replace
|
|
81
|
+
* path that has to fail soft — the argument `media-takedown-reach.ts`
|
|
82
|
+
* makes about takedowns.
|
|
83
|
+
* 2. **Re-pin every stored reference on replace.** A write fan-out into
|
|
84
|
+
* published versions, found by a where-used scan that caps its own work,
|
|
85
|
+
* and it still leaves every copy of the old URL outside our documents — a
|
|
86
|
+
* sent email, a feed reader, a hotlink — on the year-long promise.
|
|
87
|
+
*
|
|
88
|
+
* The stable URL is revalidated rather than trusted: a 60-second browser
|
|
89
|
+
* window, an ETag answered with a 304, an hour at the edge. A replace reaches
|
|
90
|
+
* it on every surface within that bound with nothing to re-publish, which is
|
|
91
|
+
* how every reference written before pins existed has always behaved.
|
|
92
|
+
*
|
|
93
|
+
* References that already carry a pin keep it. Nothing strips one, and a hash
|
|
94
|
+
* recording which bytes an author placed stays available to anything that
|
|
95
|
+
* wants to check them; {@link mediaNodeSrc} simply mints no new ones.
|
|
96
|
+
*
|
|
97
|
+
* ## What is still NOT stored
|
|
98
|
+
*
|
|
99
|
+
* The entitlement decision — see {@link mediaNodeSrc}, which is why a
|
|
100
|
+
* free-tier org keeps getting a raw storage URL rather than a reference.
|
|
101
|
+
*/ /**
|
|
102
|
+
* The media delivery route. The ONE literal a route change has to touch —
|
|
103
|
+
* everything else derives from it. Kept in the framework package rather than
|
|
104
|
+
* next to the handler because the handler lives in a server-only lib that a
|
|
105
|
+
* plugin component cannot import.
|
|
106
|
+
*/ import { TENANT_APEX } from "./host-naming.js";
|
|
107
|
+
export const MEDIA_CDN_ROUTE = '/api/media/cdn';
|
|
108
|
+
/**
|
|
109
|
+
* The WebP variant widths generated at upload (AGL-175), and the widths a
|
|
110
|
+
* renderer may advertise in a `srcSet`.
|
|
111
|
+
*
|
|
112
|
+
* Here rather than beside the handler for the reason above: `serveMediaCdn`
|
|
113
|
+
* lives in a server-only lib that a plugin component cannot import, and the
|
|
114
|
+
* renderer needs the same list. It was duplicated as a bare `[320, 640, 1280]`
|
|
115
|
+
* literal in `libs/plugins/mui/.../image.tsx`, so a width added to the
|
|
116
|
+
* generator never reached the markup.
|
|
117
|
+
*
|
|
118
|
+
* ⚠️ 1920 EXISTS SO THE LARGEST CANDIDATE IS STILL A VARIANT (2026-08-26).
|
|
119
|
+
*
|
|
120
|
+
* The srcSet used to top out with the BARE url labelled `1920w` — the only
|
|
121
|
+
* candidate that is never WebP. With `sizes="100vw"` any retina desktop needs
|
|
122
|
+
* more effective pixels than 1280w offers, so that bare candidate is the one
|
|
123
|
+
* most desktop visitors actually download. Measured on aglyn.com's own
|
|
124
|
+
* assets: 335 KB / 305 KB / 164 KB PNG originals against 4 KB / 4 KB / 5 KB
|
|
125
|
+
* WebP at `?w=320` — and ~94% of a media serve is bandwidth (AGL-1442).
|
|
126
|
+
*
|
|
127
|
+
* `mediaVariantWidthsFor` names every width below the source, and for a JPEG
|
|
128
|
+
* or PNG the rest as WebP at the source's own width; `serveMediaCdn` serves
|
|
129
|
+
* the original for a width an asset does not have, so a missing variant
|
|
130
|
+
* degrades to exactly the bytes it served before.
|
|
131
|
+
*
|
|
132
|
+
* ⛔ EXISTING ASSETS KEEP THE VARIANTS THEY WERE UPLOADED WITH until a backfill
|
|
133
|
+
* runs — no regression, and no saving on them either. The backfill is a
|
|
134
|
+
* `sharp` pass over the corpus, a script and not a patch (AGL-1442 S7).
|
|
135
|
+
*/ export const MEDIA_CDN_VARIANT_WIDTHS = [
|
|
136
|
+
320,
|
|
137
|
+
640,
|
|
138
|
+
1280,
|
|
139
|
+
1920
|
|
140
|
+
];
|
|
141
|
+
/**
|
|
142
|
+
* The variant width a surface asks for when it can only ask for ONE.
|
|
143
|
+
*
|
|
144
|
+
* An `<img>` hands the browser {@link MEDIA_CDN_VARIANT_WIDTHS} and lets it
|
|
145
|
+
* choose. A `<video poster>` attribute and a `thumbnailUrl` in structured data
|
|
146
|
+
* each take a single url, so they have to name a width — and it has to be the
|
|
147
|
+
* SAME width, or a crawler fetching the thumbnail gets different bytes from
|
|
148
|
+
* the visitor looking at the poster. 1280 is the widest variant below a 1920
|
|
149
|
+
* original's own width.
|
|
150
|
+
*/ export const MEDIA_CDN_POSTER_WIDTH = 1280;
|
|
151
|
+
/**
|
|
152
|
+
* Scheme of a stored media reference. Chosen so `startsWith` is a decision:
|
|
153
|
+
* no URL, path, or `{{binding}}` an author can type begins with it, and it
|
|
154
|
+
* is not a registered URL scheme, so a browser handed one by mistake fails
|
|
155
|
+
* loudly rather than fetching something.
|
|
156
|
+
*/ export const MEDIA_REF_PREFIX = 'media:';
|
|
157
|
+
/**
|
|
158
|
+
* What separates the media id from the optional content pin (AGL-2685).
|
|
159
|
+
*
|
|
160
|
+
* `@` because it cannot occur in either half: {@link SEGMENT_SOURCE} is
|
|
161
|
+
* `[A-Za-z0-9_-]`, so the FIRST `@` after the media id is unambiguously the
|
|
162
|
+
* boundary, and a reference written before pins existed contains none.
|
|
163
|
+
*/ export const MEDIA_REF_HASH_SEPARATOR = '@';
|
|
164
|
+
const ORG_SCOPE_PREFIX = 'org:';
|
|
165
|
+
/**
|
|
166
|
+
* One path segment. Mirrors the `SEGMENT` grammar `serveMediaCdn` validates
|
|
167
|
+
* requests against — deliberately a copy, not an import: that one is the
|
|
168
|
+
* authority because it must distrust the network, and this one exists so we
|
|
169
|
+
* never MINT or emit a reference the CDN would reject. Divergence shows up
|
|
170
|
+
* as a 400 in a dev smoke, not as a security hole.
|
|
171
|
+
*/ const SEGMENT_SOURCE = '[A-Za-z0-9_-]{1,64}';
|
|
172
|
+
const SEGMENT = new RegExp(`^${SEGMENT_SOURCE}$`);
|
|
173
|
+
/** Whether a scope segment is one the CDN would accept. */ export function isMediaCdnScope(scope) {
|
|
174
|
+
if (!scope.startsWith(ORG_SCOPE_PREFIX)) return SEGMENT.test(scope);
|
|
175
|
+
const parts = scope.slice(ORG_SCOPE_PREFIX.length).split(':');
|
|
176
|
+
if (parts.length < 1 || parts.length > 2) return false;
|
|
177
|
+
return parts.every((part)=>SEGMENT.test(part));
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Mints the stored form. Returns undefined rather than emitting junk.
|
|
181
|
+
*
|
|
182
|
+
* A `contentHash` that does not fit the segment grammar is DROPPED rather
|
|
183
|
+
* than refused: the pin is an optimisation, and returning undefined for it
|
|
184
|
+
* would turn a bad hash into no reference at all — an image that stops
|
|
185
|
+
* rendering because a cache hint was malformed.
|
|
186
|
+
*/ export function formatMediaRef(scope, mediaId, contentHash) {
|
|
187
|
+
if (!scope || !mediaId) return undefined;
|
|
188
|
+
if (!isMediaCdnScope(scope) || !SEGMENT.test(mediaId)) return undefined;
|
|
189
|
+
const pin = contentHash && SEGMENT.test(contentHash) ? `${MEDIA_REF_HASH_SEPARATOR}${contentHash}` : '';
|
|
190
|
+
return `${MEDIA_REF_PREFIX}${scope}/${mediaId}${pin}`;
|
|
191
|
+
}
|
|
192
|
+
/** Whether a persisted value is a media reference rather than a URL. */ export function isMediaRef(value) {
|
|
193
|
+
return typeof value === 'string' && value.startsWith(MEDIA_REF_PREFIX);
|
|
194
|
+
}
|
|
195
|
+
/** Reads a stored reference apart; null when it isn't a well-formed one. */ export function parseMediaRef(value) {
|
|
196
|
+
if (!isMediaRef(value)) return null;
|
|
197
|
+
const rest = value.slice(MEDIA_REF_PREFIX.length);
|
|
198
|
+
// The scope segment may contain `:` but never `/`, so the FIRST slash is
|
|
199
|
+
// the boundary and the media id is everything after it.
|
|
200
|
+
const slash = rest.indexOf('/');
|
|
201
|
+
if (slash <= 0) return null;
|
|
202
|
+
const scope = rest.slice(0, slash);
|
|
203
|
+
// The media id may be followed by `@{contentHash}` (AGL-2685). Neither half
|
|
204
|
+
// can contain `@`, so the first one is the boundary.
|
|
205
|
+
const tail = rest.slice(slash + 1);
|
|
206
|
+
const at = tail.indexOf(MEDIA_REF_HASH_SEPARATOR);
|
|
207
|
+
const mediaId = at === -1 ? tail : tail.slice(0, at);
|
|
208
|
+
const contentHash = at === -1 ? undefined : tail.slice(at + 1);
|
|
209
|
+
if (!isMediaCdnScope(scope) || !SEGMENT.test(mediaId)) return null;
|
|
210
|
+
// A malformed pin loses the PIN, never the reference — the asset is still
|
|
211
|
+
// named, and the stable URL still serves it.
|
|
212
|
+
if (contentHash !== undefined && !SEGMENT.test(contentHash)) return {
|
|
213
|
+
scope,
|
|
214
|
+
mediaId
|
|
215
|
+
};
|
|
216
|
+
return contentHash === undefined ? {
|
|
217
|
+
scope,
|
|
218
|
+
mediaId
|
|
219
|
+
} : {
|
|
220
|
+
scope,
|
|
221
|
+
mediaId,
|
|
222
|
+
contentHash
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Whether a value is a media-library CDN **path** — exactly what the media
|
|
227
|
+
* picker writes (AGL-2286).
|
|
228
|
+
*
|
|
229
|
+
* `MediaUrlField`'s `onPick` hands back `media.cdnPath`, which is
|
|
230
|
+
* `/api/media/cdn/{scope}/{mediaId}` and is never absolute. Several save
|
|
231
|
+
* routes validated their URL field with a bare `^https://` test and so
|
|
232
|
+
* refused every asset their own Browse button could produce. AGL-2247 fixed
|
|
233
|
+
* that for the white-label branding profile with a private regex inside
|
|
234
|
+
* `apps/console/app/api/_lib/branding-url.ts`; this is that predicate
|
|
235
|
+
* promoted to the module that already owns the grammar, because the org
|
|
236
|
+
* profile logo and the member avatar had the same defect and live in a lib
|
|
237
|
+
* `apps/console` cannot be imported from.
|
|
238
|
+
*
|
|
239
|
+
* Deliberately NOT {@link isMediaCdnUrl}, which asks a different question
|
|
240
|
+
* with `includes()` and would answer yes to `https://evil.example/x/api/media/cdn/a/b`.
|
|
241
|
+
* A validator needs the strict form, so this mirrors {@link parseMediaRef}
|
|
242
|
+
* exactly — same first-slash boundary, same `isMediaCdnScope` and `SEGMENT`
|
|
243
|
+
* checks — rather than re-deriving a regex that could drift from the route
|
|
244
|
+
* the path is about to be served by.
|
|
245
|
+
*/ export function isMediaCdnPath(value) {
|
|
246
|
+
if (typeof value !== 'string') return false;
|
|
247
|
+
const prefix = `${MEDIA_CDN_ROUTE}/`;
|
|
248
|
+
if (!value.startsWith(prefix)) return false;
|
|
249
|
+
const rest = value.slice(prefix.length);
|
|
250
|
+
// The scope segment may contain `:` but never `/`, so the FIRST slash is
|
|
251
|
+
// the boundary and the media id is everything after it.
|
|
252
|
+
const slash = rest.indexOf('/');
|
|
253
|
+
if (slash <= 0) return false;
|
|
254
|
+
const scope = rest.slice(0, slash);
|
|
255
|
+
const mediaId = rest.slice(slash + 1);
|
|
256
|
+
return isMediaCdnScope(scope) && SEGMENT.test(mediaId);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Rewrites an org scope so it names the site doing the rendering — the
|
|
260
|
+
* scope-segment twin of `hostQualifiedCdnPath` (AGL-1043).
|
|
261
|
+
*
|
|
262
|
+
* `org:{orgId}` serves ORG-WIDE assets only; an asset restricted to
|
|
263
|
+
* particular sites has to be asked for through `org:{orgId}:{hostId}`,
|
|
264
|
+
* because the CDN is unauthenticated and the URL is the only thing it can
|
|
265
|
+
* decide from. The qualified form is a superset — it also serves org-wide
|
|
266
|
+
* assets, since `visibleToHost` is true for `['org']` — so qualifying
|
|
267
|
+
* whenever a host is known is always safe and never needs `visibleTo`.
|
|
268
|
+
*
|
|
269
|
+
* It REPLACES an existing qualification rather than refusing to touch one.
|
|
270
|
+
* A baked-in host is the picker's best guess made where no site context
|
|
271
|
+
* existed; the site actually rendering the node is the better answer, and
|
|
272
|
+
* this is what lets one reference work in a reusable component or layout
|
|
273
|
+
* shared across several sites — the case a single stored URL can never
|
|
274
|
+
* cover.
|
|
275
|
+
*/ export function hostQualifiedScope(scope, hostId) {
|
|
276
|
+
if (!hostId || !SEGMENT.test(hostId)) return scope;
|
|
277
|
+
if (!scope.startsWith(ORG_SCOPE_PREFIX)) return scope;
|
|
278
|
+
const orgId = scope.slice(ORG_SCOPE_PREFIX.length).split(':')[0];
|
|
279
|
+
if (!orgId || !SEGMENT.test(orgId)) return scope;
|
|
280
|
+
return `${ORG_SCOPE_PREFIX}${orgId}:${hostId}`;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* The render-time resolver every surface shares. Precedence, in order:
|
|
284
|
+
*
|
|
285
|
+
* 1. a **media reference** → the CDN URL for it, host-qualified if we know
|
|
286
|
+
* which site is asking;
|
|
287
|
+
* 2. any other non-empty string → **itself, untouched**. That is the whole
|
|
288
|
+
* back-compat story and it needs no migration to be correct: nodes
|
|
289
|
+
* holding a raw `https://firebasestorage.googleapis.com/…` URL, nodes
|
|
290
|
+
* holding an `/api/media/cdn/…` path written by the first pass,
|
|
291
|
+
* and an author-typed external URL for a hotlinked image are all just
|
|
292
|
+
* passed through;
|
|
293
|
+
* 3. empty/absent → undefined, so the caller shows its placeholder.
|
|
294
|
+
*
|
|
295
|
+
* A value that opens with `media:` but does not parse resolves to undefined
|
|
296
|
+
* rather than reaching an `<img src>`. There is no correct URL to emit for
|
|
297
|
+
* it, and a placeholder in the editor is a report; `src="media:junk"` is a
|
|
298
|
+
* console error nobody reads.
|
|
299
|
+
*/ export function resolveMediaSrc(value, options) {
|
|
300
|
+
if (!value) return undefined;
|
|
301
|
+
if (!isMediaRef(value)) return value;
|
|
302
|
+
const ref = parseMediaRef(value);
|
|
303
|
+
if (!ref) return undefined;
|
|
304
|
+
const scope = hostQualifiedScope(ref.scope, options == null ? void 0 : options.hostId);
|
|
305
|
+
// The stable URL, pinned or not (AGL-2798). The content-hashed form is held
|
|
306
|
+
// for a year by the edge and by every browser that fetched it, where no
|
|
307
|
+
// replace can reach — see the module note.
|
|
308
|
+
return `${MEDIA_CDN_ROUTE}/${scope}/${ref.mediaId}`;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* The site-relative path of an ABSOLUTE first-party CDN URL, or undefined
|
|
312
|
+
* when the value is not one. Internal to {@link siteRelativeMediaSrc}.
|
|
313
|
+
*
|
|
314
|
+
* Gated on {@link isFirstPartyHost} rather than on the path alone, and that
|
|
315
|
+
* gate is the whole safety argument: an author-typed hotlink whose path
|
|
316
|
+
* happens to look like ours must keep its origin, or we would silently
|
|
317
|
+
* re-point someone else's image at our own CDN.
|
|
318
|
+
*
|
|
319
|
+
* `search` and `hash` are carried through. A private asset is served behind
|
|
320
|
+
* `exp` + `sig`, and `signMediaAccess` signs (scope, mediaId, exp) — never
|
|
321
|
+
* the host — so a signature survives the origin being dropped.
|
|
322
|
+
*/ function firstPartyCdnPathname(value) {
|
|
323
|
+
// Cheap reject before constructing a URL: only an absolute http(s) URL
|
|
324
|
+
// carries an origin to drop, and this runs on every rendered image.
|
|
325
|
+
if (!/^https?:\/\//i.test(value)) return undefined;
|
|
326
|
+
let url;
|
|
327
|
+
try {
|
|
328
|
+
url = new URL(value);
|
|
329
|
+
} catch (unused) {
|
|
330
|
+
return undefined;
|
|
331
|
+
}
|
|
332
|
+
if (!isFirstPartyHost(url.hostname)) return undefined;
|
|
333
|
+
if (!url.pathname.startsWith(`${MEDIA_CDN_ROUTE}/`)) return undefined;
|
|
334
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* {@link resolveMediaSrc}, with an absolute FIRST-PARTY CDN URL folded back
|
|
338
|
+
* to the site-relative path that names the same bytes (AGL-1726).
|
|
339
|
+
*
|
|
340
|
+
* The resolver's pass-through branch is right for what it was written for —
|
|
341
|
+
* a raw storage URL and an author's hotlink are values we must not touch.
|
|
342
|
+
* But a stored `https://{subdomain}.aglyn.app/api/media/cdn/…` is neither.
|
|
343
|
+
* It is OUR route, addressed the long way round, and on a white-label
|
|
344
|
+
* storefront served from the customer's own domain it is:
|
|
345
|
+
*
|
|
346
|
+
* 1. a **brand leak** — the platform subdomain appears in page source and in
|
|
347
|
+
* every visitor's request, on a site whose owner pays not to see it;
|
|
348
|
+
* 2. **cross-origin**, so `img-src 'self'` would blank it (this is the
|
|
349
|
+
* AGL-1726 measurement, and fixing it unblocks that flip);
|
|
350
|
+
* 3. a dependency on `aglyn.app` resolving, on a page that otherwise has no
|
|
351
|
+
* reason to need it.
|
|
352
|
+
*
|
|
353
|
+
* Dropping the origin is safe because `serveMediaCdn` decides from the URL
|
|
354
|
+
* and the document, never from the `Host` header — "the cache key IS the
|
|
355
|
+
* URL, one host's answer can never reach another" — and BOTH apps mount the
|
|
356
|
+
* route, so the console canvas and the tenant page each serve their own.
|
|
357
|
+
*
|
|
358
|
+
* ## Why this is a separate function and not a change to `resolveMediaSrc`
|
|
359
|
+
*
|
|
360
|
+
* Two consumers need the absolute form and would be harmed by folding this
|
|
361
|
+
* into the shared resolver:
|
|
362
|
+
*
|
|
363
|
+
* - {@link absoluteMediaSrc}'s out-of-band readers (`og:image`, the PWA
|
|
364
|
+
* manifest, JSON-LD, an inbox). They re-absolutize against a stated
|
|
365
|
+
* origin, so a value that no longer carries one returns undefined
|
|
366
|
+
* wherever that origin is unknown.
|
|
367
|
+
* - `resolveEmailMediaSrc` in `shared-util-email`, a deliberate COPY of
|
|
368
|
+
* `resolveMediaSrc` pinned by `apps/console/specs/email-media-src-drift.spec.ts`.
|
|
369
|
+
* It cannot import this module (`scope:shared` is a leaf), so any change
|
|
370
|
+
* to the authority has to be mirrored by hand — and a mirror of
|
|
371
|
+
* {@link isFirstPartyHost}, which reads two environment variables, is the
|
|
372
|
+
* AGL-2195 trap re-armed.
|
|
373
|
+
*
|
|
374
|
+
* So: the render-time resolver keeps its contract, and a surface that puts
|
|
375
|
+
* the result straight into an `<img src>` on a page asks for this instead.
|
|
376
|
+
*/ export function siteRelativeMediaSrc(value, options) {
|
|
377
|
+
var _firstPartyCdnPathname;
|
|
378
|
+
const resolved = resolveMediaSrc(value, options);
|
|
379
|
+
// Absent, empty, and an unparseable reference all arrive here as
|
|
380
|
+
// undefined and must LEAVE as undefined — the caller's placeholder is the
|
|
381
|
+
// correct render, and `strictNullChecks` being off repo-wide means a
|
|
382
|
+
// missing field folds to falsy rather than announcing itself.
|
|
383
|
+
if (!resolved) return undefined;
|
|
384
|
+
return (_firstPartyCdnPathname = firstPartyCdnPathname(resolved)) != null ? _firstPartyCdnPathname : resolved;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* {@link resolveMediaSrc}, then made ABSOLUTE against a stated origin.
|
|
388
|
+
*
|
|
389
|
+
* Two of the three stored generations — a `media:` reference and the AGL-175
|
|
390
|
+
* relative CDN path — resolve site-RELATIVE, which is right for an `<img>` on
|
|
391
|
+
* a page and wrong for every consumer that reads the URL out of band: a
|
|
392
|
+
* crawler fetching `og:image` (AGL-1337), an inbox rendering a campaign
|
|
393
|
+
* (AGL-1224), an installer fetching a PWA manifest icon (AGL-1407). None of
|
|
394
|
+
* them has a page to resolve against, and the tenant app declares no
|
|
395
|
+
* `metadataBase`, so Next resolves nothing for us either.
|
|
396
|
+
*
|
|
397
|
+
* With no origin a relative value returns **undefined** rather than a
|
|
398
|
+
* relative URL — the rule the canonical and the RSS feed already follow
|
|
399
|
+
* (AGL-1160/AGL-1272): never interpolate an unknown origin, and never emit a
|
|
400
|
+
* URL that is well-formed but wrong. An absolute value is unaffected, so the
|
|
401
|
+
* author-typed external URL and the raw storage URL never depend on knowing
|
|
402
|
+
* the origin at all.
|
|
403
|
+
*
|
|
404
|
+
* A protocol-relative `//host/x.png` only lacks a scheme; it is given `https:`
|
|
405
|
+
* rather than an origin, which would corrupt it.
|
|
406
|
+
*/ export function absoluteMediaSrc(value, options) {
|
|
407
|
+
const resolved = resolveMediaSrc(value, options);
|
|
408
|
+
if (!resolved) return undefined;
|
|
409
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(resolved)) return resolved;
|
|
410
|
+
if (resolved.startsWith('//')) return `https:${resolved}`;
|
|
411
|
+
const origin = options == null ? void 0 : options.origin;
|
|
412
|
+
if (!origin) return undefined;
|
|
413
|
+
return resolved.startsWith('/') ? `${origin}${resolved}` : `${origin}/${resolved}`;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Whether a resolved URL is served by our CDN, and therefore carries the
|
|
417
|
+
* generated WebP variants selected by `?w=`. Widths without a variant fall
|
|
418
|
+
* back to the original server-side, so a static srcSet is safe for any
|
|
419
|
+
* CDN-form URL — including the legacy stored paths, which is why this asks
|
|
420
|
+
* about the RESOLVED url rather than about the stored value.
|
|
421
|
+
*/ export function isMediaCdnUrl(url) {
|
|
422
|
+
return Boolean(url && url.includes(`${MEDIA_CDN_ROUTE}/`));
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* One resolved URL at a chosen variant width (AGL-2741).
|
|
426
|
+
*
|
|
427
|
+
* `image.tsx` hands the browser the whole candidate list and lets it choose,
|
|
428
|
+
* which is right for an `<img>` and impossible everywhere else: a
|
|
429
|
+
* `<video poster>` attribute takes ONE url and no `srcset`, and so does a
|
|
430
|
+
* `thumbnailUrl` in structured data. Those callers still want the WebP variant
|
|
431
|
+
* rather than the 335 KB PNG original, and they have to name the width
|
|
432
|
+
* themselves.
|
|
433
|
+
*
|
|
434
|
+
* The width is only appended when the resolved url is a CDN one. A hotlinked
|
|
435
|
+
* image has no variants and no handler behind it, so a `?w=` there would be a
|
|
436
|
+
* query string on somebody else's server; a width the asset has no variant for
|
|
437
|
+
* falls back to the original server-side, so this is safe on any CDN-form url
|
|
438
|
+
* and on an asset whose variants were never generated.
|
|
439
|
+
*
|
|
440
|
+
* Shared rather than restated at each call site because a poster attribute and
|
|
441
|
+
* the `thumbnailUrl` describing it must name the SAME bytes — two spellings of
|
|
442
|
+
* "resolve the poster" is how those drift apart.
|
|
443
|
+
*
|
|
444
|
+
* The width MERGES into a query the url already carries (AGL-2958). A film's
|
|
445
|
+
* captured frame is `?poster=1` on the film's own url and a signed private
|
|
446
|
+
* asset carries `exp`/`sig`, and both are values an image or poster field can
|
|
447
|
+
* hold. A bare `?w=` append turns the first into `?poster=1?w=640`, which the
|
|
448
|
+
* CDN reads as a `poster` of `1?w=640` — not a request for the still, and no
|
|
449
|
+
* width either — so it answers with the master film. `image.tsx` builds every
|
|
450
|
+
* `srcSet` candidate through here for the same reason.
|
|
451
|
+
*/ export function mediaVariantSrc(value, options) {
|
|
452
|
+
const resolved = resolveMediaSrc(typeof value === 'string' ? value : undefined, options);
|
|
453
|
+
if (!resolved) return undefined;
|
|
454
|
+
return isMediaCdnUrl(resolved) ? withMediaCdnQuery(resolved, [
|
|
455
|
+
[
|
|
456
|
+
'w',
|
|
457
|
+
String(options.width)
|
|
458
|
+
]
|
|
459
|
+
]) : resolved;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* The whole candidate list for an `<img>`: every width in
|
|
463
|
+
* {@link MEDIA_CDN_VARIANT_WIDTHS} as a `?w=` url, or `undefined` for a url
|
|
464
|
+
* that is not ours and therefore has no variants to offer.
|
|
465
|
+
*
|
|
466
|
+
* Takes the RESOLVED url, like {@link isMediaCdnUrl} and for the same reason:
|
|
467
|
+
* a `media:` reference and a legacy stored path both keep their WebP variants,
|
|
468
|
+
* while a hotlinked image gets nothing rather than a `?w=` on somebody else's
|
|
469
|
+
* server. Each candidate goes through {@link mediaVariantSrc} so the width
|
|
470
|
+
* MERGES into a query the url already carries (AGL-2958) instead of being
|
|
471
|
+
* appended after one.
|
|
472
|
+
*
|
|
473
|
+
* Shared rather than restated because three surfaces render a library image —
|
|
474
|
+
* the Image element, a Markdown body and a collection entry's body — and the
|
|
475
|
+
* two body renderers shipped with no `srcSet` at all for exactly as long as
|
|
476
|
+
* this list lived inside `image.tsx` (AGL-3149). A fourth copy is how the
|
|
477
|
+
* next one drifts.
|
|
478
|
+
*
|
|
479
|
+
* ⚠️ `srcSet` alone is not a delivery-only change. With `w` descriptors the
|
|
480
|
+
* browser derives the image's density-corrected intrinsic size from `sizes`,
|
|
481
|
+
* so an `<img>` carrying this list and no intrinsic `width`/`height` pair
|
|
482
|
+
* renders at `sizes` rather than at its own size — measured, a 320px asset in
|
|
483
|
+
* a 712px column jumped to 668px. Hand it the pair, or hand it an explicit CSS
|
|
484
|
+
* width, but do not hand it this list alone.
|
|
485
|
+
*/ export function mediaCdnSrcSet(src) {
|
|
486
|
+
if (!isMediaCdnUrl(src)) return undefined;
|
|
487
|
+
return MEDIA_CDN_VARIANT_WIDTHS.map((width)=>`${mediaVariantSrc(src, {
|
|
488
|
+
width
|
|
489
|
+
})} ${width}w`).join(', ');
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Every sizing attribute an image inside authored PROSE should carry, given
|
|
493
|
+
* what the composition could learn about the asset (AGL-3149).
|
|
494
|
+
*
|
|
495
|
+
* A body image differs from an Image element in the one way that matters here:
|
|
496
|
+
* nobody sets its CSS width. It is laid out by `max-width: 100%` and its own
|
|
497
|
+
* intrinsic size, so the attributes below are what decide both its box and its
|
|
498
|
+
* bytes, and they only work as a set:
|
|
499
|
+
*
|
|
500
|
+
* - `width`/`height` map to presentational-hint CSS `width`, which
|
|
501
|
+
* `max-width: 100%` then caps — so the rendered width is
|
|
502
|
+
* `min(natural, column)`. That is the growth the issue asked for, and it is
|
|
503
|
+
* also what stops `sizes` deciding the size (see {@link mediaCdnSrcSet}).
|
|
504
|
+
* The renderer MUST pair them with `height: auto`, or the height hint
|
|
505
|
+
* survives the width cap and the picture is squashed.
|
|
506
|
+
* - `sizes` is then only a delivery hint, and it is derived from the pair
|
|
507
|
+
* rather than from the column: an image narrower than the column renders at
|
|
508
|
+
* its own width, so describing the column would fetch a candidate several
|
|
509
|
+
* times larger than the slot. Measured, a 320px asset under a fixed
|
|
510
|
+
* `sizes="712px"` fetched `?w=1280`; under its own width it fetches `?w=320`.
|
|
511
|
+
*
|
|
512
|
+
* WITHOUT a pair this returns the resolved `src` and NOTHING else — today's
|
|
513
|
+
* markup exactly. That is deliberate: `srcSet` without the pair would upscale
|
|
514
|
+
* every image narrower than the column, so an asset the facts read cannot
|
|
515
|
+
* answer for (a hotlink, an SVG the upload could not measure, one past the
|
|
516
|
+
* composition's cap) must come out unchanged rather than half-improved.
|
|
517
|
+
*/ export function mediaBodyImageAttributes(options) {
|
|
518
|
+
const src = resolveMediaSrc(typeof options.src === 'string' ? options.src : undefined, {
|
|
519
|
+
hostId: options.hostId
|
|
520
|
+
});
|
|
521
|
+
const { size } = options;
|
|
522
|
+
if (!size) return {
|
|
523
|
+
src
|
|
524
|
+
};
|
|
525
|
+
const srcSet = mediaCdnSrcSet(src);
|
|
526
|
+
return _extends({
|
|
527
|
+
src,
|
|
528
|
+
width: size.width,
|
|
529
|
+
height: size.height
|
|
530
|
+
}, srcSet ? {
|
|
531
|
+
srcSet,
|
|
532
|
+
sizes: `(max-width: ${size.width}px) 100vw, ${size.width}px`
|
|
533
|
+
} : {});
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Hosts that serve OUR OWN media, for {@link isFirstPartyMediaSrc}.
|
|
537
|
+
*
|
|
538
|
+
* `firebasestorage.googleapis.com` is here because it is where the DAM
|
|
539
|
+
* actually stores bytes: `mediaSrc` falls back to the raw download URL for a
|
|
540
|
+
* free-tier org, which has no `mediaCdn` entitlement and therefore no
|
|
541
|
+
* `cdnPath`. Excluding it would mean "upload it to the library" was advice a
|
|
542
|
+
* free-tier publisher could not follow.
|
|
543
|
+
*
|
|
544
|
+
* `storage.googleapis.com` is deliberately NOT here — see AGL-1702 #3. Its
|
|
545
|
+
* only producer in source is a signed WRITE url, and allowlisting it
|
|
546
|
+
* pre-emptively is how a host nobody has proved we need becomes permanent.
|
|
547
|
+
*/ const FIRST_PARTY_MEDIA_HOSTS = [
|
|
548
|
+
'firebasestorage.googleapis.com'
|
|
549
|
+
];
|
|
550
|
+
/**
|
|
551
|
+
* Apexes whose subdomains are ours. `localhost` covers dev and e2e.
|
|
552
|
+
*
|
|
553
|
+
* `aglyn.com` and `aglyn.io` are both in `security-origins.js`'s
|
|
554
|
+
* `PRODUCTION_DOMAINS`; `aglyn.app` is `TENANT_APEX`; `aglyn.dev` is carried
|
|
555
|
+
* because `tools/lint-rules/no-remote-image-service.mjs` already treats it as
|
|
556
|
+
* first-party and a disagreement between the two lists is the kind of thing
|
|
557
|
+
* that gets discovered as a broken image.
|
|
558
|
+
*/ const FIRST_PARTY_APEXES = [
|
|
559
|
+
'aglyn.com',
|
|
560
|
+
'aglyn.app',
|
|
561
|
+
'aglyn.io',
|
|
562
|
+
'aglyn.dev',
|
|
563
|
+
'localhost',
|
|
564
|
+
// The operator's own names on a self-host install (AGL-2172). Pinned to our
|
|
565
|
+
// five, this said a self-hoster's OWN media and CDN hostnames were
|
|
566
|
+
// third-party — so their authors got off-site warnings about their own
|
|
567
|
+
// assets, and the Styles panel's url() hint fired on every image they
|
|
568
|
+
// uploaded. Derived from the same variables the rest of the runtime reads,
|
|
569
|
+
// never a sixth list: `TENANT_APEX` is imported rather than restated, and a
|
|
570
|
+
// console URL arrives as an origin so it is reduced to a hostname here.
|
|
571
|
+
...operatorFirstPartyApexes()
|
|
572
|
+
];
|
|
573
|
+
/**
|
|
574
|
+
* The apexes this DEPLOYMENT serves, beyond Aglyn's own.
|
|
575
|
+
*
|
|
576
|
+
* Empty on Aglyn's cloud, where the five above are the whole answer. A
|
|
577
|
+
* function rather than a spread of constants so an unset or malformed value
|
|
578
|
+
* contributes nothing instead of an empty string — `''` in this list would
|
|
579
|
+
* make `endsWith('.')` true for every hostname on earth.
|
|
580
|
+
*/ function operatorFirstPartyApexes() {
|
|
581
|
+
var _process_env_NEXT_PUBLIC_WORKSPACE_DOMAIN;
|
|
582
|
+
const consoleHost = (()=>{
|
|
583
|
+
var _process_env_NEXT_PUBLIC_CONSOLE_URL;
|
|
584
|
+
const raw = (_process_env_NEXT_PUBLIC_CONSOLE_URL = process.env.NEXT_PUBLIC_CONSOLE_URL) == null ? void 0 : _process_env_NEXT_PUBLIC_CONSOLE_URL.trim();
|
|
585
|
+
if (!raw) return undefined;
|
|
586
|
+
try {
|
|
587
|
+
return new URL(raw).hostname.toLowerCase();
|
|
588
|
+
} catch (unused) {
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
})();
|
|
592
|
+
return [
|
|
593
|
+
TENANT_APEX,
|
|
594
|
+
consoleHost,
|
|
595
|
+
(_process_env_NEXT_PUBLIC_WORKSPACE_DOMAIN = process.env.NEXT_PUBLIC_WORKSPACE_DOMAIN) == null ? void 0 : _process_env_NEXT_PUBLIC_WORKSPACE_DOMAIN.trim().toLowerCase()
|
|
596
|
+
].filter((name)=>Boolean(name && name.includes('.')));
|
|
597
|
+
}
|
|
598
|
+
// The parameter is `hostname`, not `host`, on purpose (AGL-1718/AGL-1719). In
|
|
599
|
+
// this repo `host` names the `hosts/{hostId}` SITE DOCUMENT, and the AGL-1361
|
|
600
|
+
// write-deny guard scans this whole directory textually for `host.<field>` to
|
|
601
|
+
// build that document's field universe. A string local called `host` therefore
|
|
602
|
+
// reads as a site field: `host.toLowerCase()` was collected as a host field
|
|
603
|
+
// named `toLowerCase` and turned the guard red. `url.hostname` is what the one
|
|
604
|
+
// caller passes, so this is also the more accurate name.
|
|
605
|
+
//
|
|
606
|
+
// Exported for `author-css.ts` (AGL-1737): the Styles panel's passive
|
|
607
|
+
// off-site-url() hint needs the SAME first-party set this file already keeps
|
|
608
|
+
// in sync with `security-origins.js`, rather than a third copy of the list.
|
|
609
|
+
export function isFirstPartyHost(hostname) {
|
|
610
|
+
const lower = hostname.toLowerCase();
|
|
611
|
+
if (FIRST_PARTY_MEDIA_HOSTS.includes(lower)) return true;
|
|
612
|
+
return FIRST_PARTY_APEXES.some((apex)=>lower === apex || lower.endsWith(`.${apex}`));
|
|
613
|
+
}
|
|
614
|
+
/**
|
|
615
|
+
* Whether a stored image `src` names media WE serve (AGL-1701).
|
|
616
|
+
*
|
|
617
|
+
* The predicate an authoring surface validates against when the person
|
|
618
|
+
* supplying the value is not the person who will render it. A marketplace
|
|
619
|
+
* publisher types a listing logo; every OTHER org's users load it. An `<img>`
|
|
620
|
+
* on a host the publisher controls is a beacon — it discloses each viewer's
|
|
621
|
+
* IP, user-agent and a `Referer` naming the console and the org, on every
|
|
622
|
+
* render, to a recipient who appears on no subprocessor register. That is a
|
|
623
|
+
* disclosure question, and the answer is not to name the host in a policy;
|
|
624
|
+
* it is to stop accepting the host.
|
|
625
|
+
*
|
|
626
|
+
* Three accepted forms, in descending order of how much we like them:
|
|
627
|
+
*
|
|
628
|
+
* 1. a `media:` reference — names the asset, survives a move or a replace;
|
|
629
|
+
* 2. a root-relative path under {@link MEDIA_CDN_ROUTE} — same-origin, so
|
|
630
|
+
* `img-src 'self'` covers it with no allowlist entry at all;
|
|
631
|
+
* 3. an absolute `https:` URL on a first-party host. Two sub-cases, and both
|
|
632
|
+
* are what the DAM picker actually emits today: `mediaSrc` prefixes
|
|
633
|
+
* `window.location.origin` onto `cdnPath` because a listing renders
|
|
634
|
+
* somewhere other than the console, and it falls back to the raw storage
|
|
635
|
+
* download URL when the org has no CDN entitlement.
|
|
636
|
+
*
|
|
637
|
+
* `http:` is refused in every form, and so is protocol-relative `//host` —
|
|
638
|
+
* which `new URL` would resolve against a base we do not have here, and which
|
|
639
|
+
* on a page is simply the same egress with the scheme borrowed.
|
|
640
|
+
*
|
|
641
|
+
* KNOWN GAP, stated rather than papered over: an org with a white-label
|
|
642
|
+
* `customConsoleDomain` would have `mediaSrc` emit that domain, which this
|
|
643
|
+
* refuses. Inert today — AGL-743 leaves the claim `pending` and nothing
|
|
644
|
+
* routes on it — and the fix when it does route is to resolve the claim here,
|
|
645
|
+
* not to widen the apex list.
|
|
646
|
+
*/ export function isFirstPartyMediaSrc(value) {
|
|
647
|
+
if (typeof value !== 'string') return false;
|
|
648
|
+
const trimmed = value.trim();
|
|
649
|
+
if (!trimmed) return false;
|
|
650
|
+
// `startsWith` rather than `isMediaRef`: that one is a `value is string`
|
|
651
|
+
// predicate, so narrowing a value ALREADY known to be a string leaves the
|
|
652
|
+
// else branch as `never` and every later `.startsWith` fails to compile
|
|
653
|
+
// under the console's stricter config (and, silently, not under this
|
|
654
|
+
// library's — which is how it would have shipped).
|
|
655
|
+
if (trimmed.startsWith(MEDIA_REF_PREFIX)) {
|
|
656
|
+
return parseMediaRef(trimmed) !== null;
|
|
657
|
+
}
|
|
658
|
+
// Root-relative only. `//host/…` is protocol-relative, not a path.
|
|
659
|
+
if (trimmed.startsWith('/')) {
|
|
660
|
+
if (trimmed.startsWith('//')) return false;
|
|
661
|
+
return trimmed.startsWith(`${MEDIA_CDN_ROUTE}/`);
|
|
662
|
+
}
|
|
663
|
+
try {
|
|
664
|
+
const url = new URL(trimmed);
|
|
665
|
+
if (url.protocol !== 'https:') return false;
|
|
666
|
+
return isFirstPartyHost(url.hostname);
|
|
667
|
+
} catch (unused) {
|
|
668
|
+
return false;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Reads a reference back out of a CDN path — how the picker mints one from
|
|
673
|
+
* the `cdnPath` the server already wrote on the media doc, so nothing new
|
|
674
|
+
* has to be plumbed through the media APIs.
|
|
675
|
+
*
|
|
676
|
+
* A content-hashed path (`…/{mediaId}/{hash}`) yields the reference for the
|
|
677
|
+
* asset it names, and the hash is discarded: a reference names the ASSET, so
|
|
678
|
+
* that a replace reaches it (AGL-2798).
|
|
679
|
+
*/ export function mediaRefFromCdnPath(cdnPath) {
|
|
680
|
+
if (!cdnPath) return undefined;
|
|
681
|
+
const marker = `${MEDIA_CDN_ROUTE}/`;
|
|
682
|
+
const at = cdnPath.indexOf(marker);
|
|
683
|
+
if (at === -1) return undefined;
|
|
684
|
+
const [scope, mediaId] = cdnPath.slice(at + marker.length).split('/');
|
|
685
|
+
return formatMediaRef(scope, mediaId);
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Matches every stored reference to ONE asset, whatever scope form it
|
|
689
|
+
* carries — host library, bare org, or host-qualified org.
|
|
690
|
+
*
|
|
691
|
+
* The where-used scan (AGL-833/AGL-1045) answers "what breaks if I move,
|
|
692
|
+
* restrict or delete this?" by looking for the asset's URL inside serialized
|
|
693
|
+
* documents. A reference contains neither the storage URL nor the CDN path,
|
|
694
|
+
* so without this it would report an asset as used nowhere — and the scope
|
|
695
|
+
* confirmation that quotes those results would tell an author it is safe to
|
|
696
|
+
* restrict an asset that is on a live page. Enumerating the org's hosts to
|
|
697
|
+
* build one needle per site would work and would silently under-report the
|
|
698
|
+
* moment a scan skipped a host; one pattern cannot.
|
|
699
|
+
*
|
|
700
|
+
* Deliberately not anchored to a quote: it must find a reference wherever it
|
|
701
|
+
* was serialized. The trailing guard stops `med1` matching `med12`.
|
|
702
|
+
*
|
|
703
|
+
* It matches a PINNED reference too (AGL-2685) and must keep doing so: `@` is
|
|
704
|
+
* outside `[A-Za-z0-9_-]`, so `media:h/med1@abc` satisfies the trailing guard
|
|
705
|
+
* on its own. Had it not, the where-used scan would have started reporting
|
|
706
|
+
* live assets as used nowhere the day pins shipped — a scan whose every error
|
|
707
|
+
* already points at "safe to delete".
|
|
708
|
+
*
|
|
709
|
+
* It matches the same asset spelled as a CDN PATH as well (AGL-2969), in the
|
|
710
|
+
* same scope forms. The scan's needles include the document's own `cdnPath`,
|
|
711
|
+
* but that is the bare org form, and two writers store the path with the site
|
|
712
|
+
* in its scope: a plugin page's picker, for an asset shared with one site
|
|
713
|
+
* (`hostQualifiedCdnPath`), and an entry cover filled from a film's frame
|
|
714
|
+
* (`mediaPosterSrc`, qualified for every org film). A query, a content-hash
|
|
715
|
+
* segment and an origin in front all leave the match intact, and the same
|
|
716
|
+
* trailing guard applies.
|
|
717
|
+
*/ export function mediaRefPattern(mediaId) {
|
|
718
|
+
const id = mediaId.replace(/[^A-Za-z0-9_-]/g, '');
|
|
719
|
+
// An id that sanitizes to nothing must match NOTHING — never everything.
|
|
720
|
+
if (!id) return /(?!)/;
|
|
721
|
+
return new RegExp(`(?:${MEDIA_REF_PREFIX}|${MEDIA_CDN_ROUTE}/)` + `(?:org:${SEGMENT_SOURCE}(?::${SEGMENT_SOURCE})?` + `|${SEGMENT_SOURCE})/${id}(?![A-Za-z0-9_-])`);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* What the media picker writes into a node prop.
|
|
725
|
+
*
|
|
726
|
+
* The reference is derived from `cdnPath`, and that is load-bearing rather
|
|
727
|
+
* than convenient: `cdnPath` is only minted for orgs entitled to `mediaCdn`
|
|
728
|
+
* and is deleted for private assets (`mediaCdnPathUpdate`). Since the CDN
|
|
729
|
+
* handler itself checks neither, minting a reference from an id we happen to
|
|
730
|
+
* know would hand every free-tier org paid delivery. Deriving it means the
|
|
731
|
+
* entitlement gate keeps working with no second copy of the rule — and a
|
|
732
|
+
* free-tier org degrades to the raw storage URL, which is exactly what it
|
|
733
|
+
* got before the CDN-path pass.
|
|
734
|
+
*
|
|
735
|
+
* `media.cdnPath` is expected to be already host-qualified by the picker
|
|
736
|
+
* dialog (AGL-1043). That qualification is preserved in the stored scope so
|
|
737
|
+
* the besigner canvas, which has no site context, can still fetch a
|
|
738
|
+
* restricted asset; {@link resolveMediaSrc} overrides it wherever the real
|
|
739
|
+
* rendering host IS known.
|
|
740
|
+
*
|
|
741
|
+
* No content pin is written, even when `media.contentHash` is present
|
|
742
|
+
* (AGL-2798). A pin changes no URL a reference renders, so writing one would
|
|
743
|
+
* put a value into the document that nothing reads, and hand the next reader
|
|
744
|
+
* a reason to turn it back into the year-long URL no replace can reach. The
|
|
745
|
+
* field stays in the accepted shape because callers hand over the whole media
|
|
746
|
+
* document.
|
|
747
|
+
*/ export function mediaNodeSrc(media) {
|
|
748
|
+
var _ref, _mediaRefFromCdnPath;
|
|
749
|
+
return (_ref = (_mediaRefFromCdnPath = mediaRefFromCdnPath(media.cdnPath)) != null ? _mediaRefFromCdnPath : media.url) != null ? _ref : undefined;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* The derived objects a VIDEO asset carries, and how a caller asks for one
|
|
753
|
+
* (AGL-2742 / AGL-2743).
|
|
754
|
+
*
|
|
755
|
+
* ## Why these are query parameters on the asset's own URL
|
|
756
|
+
*
|
|
757
|
+
* The alternative was a second media document — a poster with its own id,
|
|
758
|
+
* pointed at from the video's. It was refused for the reason the whole
|
|
759
|
+
* `media:` scheme exists: a reference names an ASSET so that replacing its
|
|
760
|
+
* bytes propagates everywhere without re-linking. Two documents are two
|
|
761
|
+
* lifecycles that can diverge, and the first replace of a video would leave
|
|
762
|
+
* the old poster live under an id no reader knows is stale. One id, one
|
|
763
|
+
* delete, one replace — and a DAM grid that shows the film rather than the
|
|
764
|
+
* film plus a mystery still.
|
|
765
|
+
*
|
|
766
|
+
* The parameters mirror `?w=`, which has selected a derived object since
|
|
767
|
+
* AGL-175. Nothing about the reference itself changes: the same stored
|
|
768
|
+
* `media:{scope}/{id}` yields the master, the poster and every rendition,
|
|
769
|
+
* because which representation you want is a rendering decision and the
|
|
770
|
+
* document records only which asset.
|
|
771
|
+
*/ export const MEDIA_CDN_POSTER_PARAM = 'poster';
|
|
772
|
+
/** Selects a video rendition by key. See {@link isMediaRenditionKey}. */ export const MEDIA_CDN_RENDITION_PARAM = 'r';
|
|
773
|
+
/**
|
|
774
|
+
* The `?r=` value meaning "the best delivery copy you have" (AGL-2753).
|
|
775
|
+
*
|
|
776
|
+
* A key names ONE encoding, which a caller can only ask for if it knows the
|
|
777
|
+
* asset has it. Nothing that renders a page knows that: renditions are
|
|
778
|
+
* produced out of band by `tools/scripts/generate-video-renditions.mjs`,
|
|
779
|
+
* minutes or days after the upload, and a published page is cached HTML that
|
|
780
|
+
* neither regenerates when an encoding lands nor varies on a visitor's
|
|
781
|
+
* `Accept`. So a placement made today can never name a rendition made
|
|
782
|
+
* tomorrow, and the encodings would be produced and never served.
|
|
783
|
+
*
|
|
784
|
+
* This sentinel moves the choice to the one place that already holds the
|
|
785
|
+
* document: `serveMediaCdn` reads it on every asset request anyway. The page
|
|
786
|
+
* emits one URL that says what it WANTS rather than what exists, and an asset
|
|
787
|
+
* with no renditions answers it with the master — the same degradation an
|
|
788
|
+
* unknown `?r=` has always had, reached deliberately instead of by accident.
|
|
789
|
+
*
|
|
790
|
+
* ⚠️ Sentinel and key share a namespace, so {@link parseMediaRendition}
|
|
791
|
+
* refuses a stored entry keyed `auto`. Without that refusal a producer could
|
|
792
|
+
* mint one and make the sentinel unreachable — the negotiated form silently
|
|
793
|
+
* pinned to whichever encoding happened to claim the name.
|
|
794
|
+
*/ export const MEDIA_CDN_RENDITION_AUTO = 'auto';
|
|
795
|
+
/**
|
|
796
|
+
* Object-path suffix for a video's poster still. The width variants sit
|
|
797
|
+
* under it as `{objectPath}__poster__w{n}.webp`, which is exactly what
|
|
798
|
+
* `generateMediaVariants` produces when handed `{objectPath}__poster` — the
|
|
799
|
+
* poster reuses the image variant generator whole rather than teaching it
|
|
800
|
+
* about video.
|
|
801
|
+
*/ export const MEDIA_POSTER_OBJECT_SUFFIX = '__poster';
|
|
802
|
+
/** Object-path prefix for a rendition: `{objectPath}__r{key}.{ext}`. */ export const MEDIA_RENDITION_OBJECT_PREFIX = '__r';
|
|
803
|
+
/**
|
|
804
|
+
* The grammar a rendition key must fit.
|
|
805
|
+
*
|
|
806
|
+
* Deliberately narrower than the segment grammar above: a key becomes part
|
|
807
|
+
* of a Storage object path, and the two characters `SEGMENT` allows that
|
|
808
|
+
* this does not — `_` and a leading `-` — are the two that would let a
|
|
809
|
+
* crafted key collide with the `__w{n}` and `__poster` suffixes. `720p` and
|
|
810
|
+
* `720p-av1` fit; `_poster` and `_w320` cannot.
|
|
811
|
+
*/ const RENDITION_KEY = /^[a-z0-9][a-z0-9-]{0,23}$/;
|
|
812
|
+
/** Whether a value may be used as a rendition key, minted or received. */ export function isMediaRenditionKey(value) {
|
|
813
|
+
return typeof value === 'string' && RENDITION_KEY.test(value);
|
|
814
|
+
}
|
|
815
|
+
/** Container extension grammar. Same argument as {@link RENDITION_KEY}. */ const RENDITION_EXT = /^[a-z0-9]{1,8}$/;
|
|
816
|
+
/**
|
|
817
|
+
* Read one stored rendition entry, or null.
|
|
818
|
+
*
|
|
819
|
+
* ⚠️ This is a SECURITY gate, not a convenience. `key` and `ext` are
|
|
820
|
+
* interpolated into a Cloud Storage object path by
|
|
821
|
+
* {@link mediaRenditionObjectPath}, and the media document they come from is
|
|
822
|
+
* writable by anyone with editor rights on the scope. An entry carrying
|
|
823
|
+
* `key: '../../../adminAudit-archive/x'` would otherwise walk straight out of
|
|
824
|
+
* the asset's prefix on an admin-SDK bucket read — the same class of hole
|
|
825
|
+
* `mediaStoragePathInScope` closes for `storagePath` (AGL-1881), reached by a
|
|
826
|
+
* different field.
|
|
827
|
+
*
|
|
828
|
+
* The two grammars admit no `/`, no `.` and no `..`, so a validated entry
|
|
829
|
+
* cannot leave the object it belongs to whatever the document says.
|
|
830
|
+
*/ export function parseMediaRendition(value) {
|
|
831
|
+
if (!value || typeof value !== 'object') return null;
|
|
832
|
+
const entry = value;
|
|
833
|
+
const key = entry['key'];
|
|
834
|
+
const ext = entry['ext'];
|
|
835
|
+
const contentType = entry['contentType'];
|
|
836
|
+
if (!isMediaRenditionKey(key)) return null;
|
|
837
|
+
// The negotiation sentinel is not a name an encoding may take: it is
|
|
838
|
+
// resolved before the by-key lookup, so an entry claiming it would be
|
|
839
|
+
// unreachable AND would shadow the request every page makes (AGL-2753).
|
|
840
|
+
if (key === MEDIA_CDN_RENDITION_AUTO) return null;
|
|
841
|
+
if (typeof ext !== 'string' || !RENDITION_EXT.test(ext)) return null;
|
|
842
|
+
if (typeof contentType !== 'string' || !/^video\/[\w.+-]{1,64}$/.test(contentType)) {
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
const width = Math.round(Number(entry['width']));
|
|
846
|
+
const height = Math.round(Number(entry['height']));
|
|
847
|
+
const sizeBytes = Math.round(Number(entry['sizeBytes']));
|
|
848
|
+
if (!Number.isFinite(width) || width <= 0) return null;
|
|
849
|
+
if (!Number.isFinite(height) || height <= 0) return null;
|
|
850
|
+
return {
|
|
851
|
+
key,
|
|
852
|
+
ext,
|
|
853
|
+
contentType,
|
|
854
|
+
width,
|
|
855
|
+
height,
|
|
856
|
+
sizeBytes: Number.isFinite(sizeBytes) && sizeBytes > 0 ? sizeBytes : 0
|
|
857
|
+
};
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Every VALID rendition on a document, in stored order.
|
|
861
|
+
*
|
|
862
|
+
* Order is the document's, and it is meaningful: a renderer emits one
|
|
863
|
+
* `<source>` per entry and a browser takes the FIRST it can decode, so the
|
|
864
|
+
* producer writes the most efficient codec first. Dropping an invalid entry
|
|
865
|
+
* rather than refusing the list keeps one malformed row from costing an asset
|
|
866
|
+
* every rendition it has.
|
|
867
|
+
*/ export function parseMediaRenditions(value) {
|
|
868
|
+
if (!Array.isArray(value)) return [];
|
|
869
|
+
const parsed = [];
|
|
870
|
+
for (const entry of value){
|
|
871
|
+
const rendition = parseMediaRendition(entry);
|
|
872
|
+
if (rendition) parsed.push(rendition);
|
|
873
|
+
}
|
|
874
|
+
return parsed;
|
|
875
|
+
}
|
|
876
|
+
/** Storage object path of an asset's poster still. */ export function mediaPosterObjectPath(objectPath) {
|
|
877
|
+
return `${objectPath}${MEDIA_POSTER_OBJECT_SUFFIX}.webp`;
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Storage object path of one rendition. The `.` before the extension is the
|
|
881
|
+
* only one in the suffix, so a path is unambiguous even when a key contains
|
|
882
|
+
* digits that look like a width.
|
|
883
|
+
*/ export function mediaRenditionObjectPath(objectPath, rendition) {
|
|
884
|
+
return `${objectPath}${MEDIA_RENDITION_OBJECT_PREFIX}${rendition.key}.${rendition.ext}`;
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Append CDN query parameters to a resolved media URL.
|
|
888
|
+
*
|
|
889
|
+
* Private assets already carry `exp`/`sig`, and the pinned form already
|
|
890
|
+
* carries a hash segment, so this has to merge rather than assign — hence
|
|
891
|
+
* the `?`/`&` test instead of a template literal. Kept private: every public
|
|
892
|
+
* entry point below decides for itself whether a value is even eligible.
|
|
893
|
+
*/ function withMediaCdnQuery(src, params) {
|
|
894
|
+
const query = params.map(([key, value])=>`${key}=${value}`).join('&');
|
|
895
|
+
return `${src}${src.includes('?') ? '&' : '?'}${query}`;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Whether a resolved value is one THIS platform serves, and so one that can
|
|
899
|
+
* be asked for a poster or a rendition.
|
|
900
|
+
*
|
|
901
|
+
* An author-typed hotlink and a raw `firebasestorage.googleapis.com` URL both
|
|
902
|
+
* pass through {@link resolveMediaSrc} untouched, and neither has a poster.
|
|
903
|
+
* Appending `?poster=1` to them would produce a URL that either 404s or —
|
|
904
|
+
* worse, on a permissive third-party host — serves the whole video under a
|
|
905
|
+
* name that promises 40 KB.
|
|
906
|
+
*
|
|
907
|
+
* ⚠️ Deliberately the PREFIX test and not {@link isMediaCdnPath}, which is
|
|
908
|
+
* the strict validator two functions above. The strict form refuses the
|
|
909
|
+
* content-hashed shape — `/api/media/cdn/{scope}/{id}/{hash}` — because its
|
|
910
|
+
* media-id segment then contains a `/`. No reference resolves to that shape
|
|
911
|
+
* (AGL-2798), but a stored PATH can still hold one: it passes through
|
|
912
|
+
* {@link resolveMediaSrc} untouched and the CDN still answers it, so refusing
|
|
913
|
+
* it here would drop the poster and renditions of an asset that serves.
|
|
914
|
+
*
|
|
915
|
+
* Nothing is lost by being looser: the strict grammar is a SUBSET of this
|
|
916
|
+
* prefix, and everything the prefix additionally admits is a same-origin
|
|
917
|
+
* path into this platform's own route — which is the only question this
|
|
918
|
+
* predicate asks.
|
|
919
|
+
*/ function derivedObjectEligible(src) {
|
|
920
|
+
if (!src) return false;
|
|
921
|
+
return src.startsWith(`${MEDIA_CDN_ROUTE}/`);
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* The poster URL for a stored media reference, or undefined when the value
|
|
925
|
+
* cannot have one.
|
|
926
|
+
*
|
|
927
|
+
* `width` narrows to a generated poster variant. An asset with no variant at
|
|
928
|
+
* that width still answers — `serveMediaCdn` falls back to the full poster,
|
|
929
|
+
* the same degradation `?w=` has always had — so a renderer may advertise
|
|
930
|
+
* the standard {@link MEDIA_CDN_VARIANT_WIDTHS} in a `srcSet` without
|
|
931
|
+
* consulting the document.
|
|
932
|
+
*
|
|
933
|
+
* ⚠️ Returning a URL is NOT a promise that a poster exists. Nothing here can
|
|
934
|
+
* read a media document, and a video uploaded before AGL-2742 — or by a
|
|
935
|
+
* browser that could not decode it — has none.
|
|
936
|
+
*
|
|
937
|
+
* That case answers **404**, deliberately and not as a gap: `serveMediaCdn`
|
|
938
|
+
* refuses a poster it does not have rather than falling back to the master,
|
|
939
|
+
* because answering a request for a 40 KB still with 60 MB of `video/mp4` is
|
|
940
|
+
* the exact cost this exists to remove. So a `<video poster>` built from this
|
|
941
|
+
* degrades to a `<video>` with no poster, which is what every video on the
|
|
942
|
+
* platform did before AGL-2742 — which is why this is allowed to answer
|
|
943
|
+
* without knowing. A caller putting the URL somewhere a 404 is NOT free (an
|
|
944
|
+
* `<img>`, an `og:image`) must read `poster` off the document first.
|
|
945
|
+
*/ export function mediaPosterSrc(value, options) {
|
|
946
|
+
const src = resolveMediaSrc(value, options);
|
|
947
|
+
if (!derivedObjectEligible(src)) return undefined;
|
|
948
|
+
const width = Number(options == null ? void 0 : options.width);
|
|
949
|
+
const params = [
|
|
950
|
+
[
|
|
951
|
+
MEDIA_CDN_POSTER_PARAM,
|
|
952
|
+
'1'
|
|
953
|
+
]
|
|
954
|
+
];
|
|
955
|
+
if (Number.isFinite(width) && width > 0) {
|
|
956
|
+
params.push([
|
|
957
|
+
'w',
|
|
958
|
+
String(Math.round(width))
|
|
959
|
+
]);
|
|
960
|
+
}
|
|
961
|
+
return withMediaCdnQuery(src, params);
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* The URL of one rendition. Undefined for a key that does not fit the
|
|
965
|
+
* grammar, so a malformed key never reaches a `<source src>` — an empty
|
|
966
|
+
* `src` makes a browser re-request the PAGE, which is a far more expensive
|
|
967
|
+
* mistake than a missing source element.
|
|
968
|
+
*/ export function mediaRenditionSrc(value, key, options) {
|
|
969
|
+
if (!isMediaRenditionKey(key)) return undefined;
|
|
970
|
+
const src = resolveMediaSrc(value, options);
|
|
971
|
+
if (!derivedObjectEligible(src)) return undefined;
|
|
972
|
+
return withMediaCdnQuery(src, [
|
|
973
|
+
[
|
|
974
|
+
MEDIA_CDN_RENDITION_PARAM,
|
|
975
|
+
key
|
|
976
|
+
]
|
|
977
|
+
]);
|
|
978
|
+
}
|
|
979
|
+
/**
|
|
980
|
+
* The URL a player should actually load for a video (AGL-2753).
|
|
981
|
+
*
|
|
982
|
+
* This is {@link resolveMediaSrc} plus one query parameter, and the parameter
|
|
983
|
+
* is the entire feature: it asks the CDN for the best delivery copy it has
|
|
984
|
+
* rather than naming one, so a rendition encoded LONG after the video was
|
|
985
|
+
* placed on a page reaches that page with no re-pick, no node backfill and no
|
|
986
|
+
* document read on the render path. See {@link MEDIA_CDN_RENDITION_AUTO} for
|
|
987
|
+
* why the choice has to live at the CDN.
|
|
988
|
+
*
|
|
989
|
+
* ⚠️ Unlike {@link mediaPosterSrc} this NEVER returns undefined for a value
|
|
990
|
+
* that resolved. A poster may legitimately have no URL — the element simply
|
|
991
|
+
* renders without one — but a video with no URL is a dead player, so anything
|
|
992
|
+
* this cannot improve is passed through exactly as `resolveMediaSrc` left it.
|
|
993
|
+
* An author-typed hotlink and a raw Storage URL therefore come back untouched:
|
|
994
|
+
* they are not this platform's objects and have no renditions to ask for.
|
|
995
|
+
*
|
|
996
|
+
* Safe on an asset that has none. `?r=` degrades to the master by design —
|
|
997
|
+
* "the same video in more bytes" — which is precisely what every video served
|
|
998
|
+
* before this existed, so a page that adopts this URL cannot regress.
|
|
999
|
+
*/ export function videoDeliverySrc(value, options) {
|
|
1000
|
+
const src = resolveMediaSrc(value, options);
|
|
1001
|
+
if (!derivedObjectEligible(src)) return src;
|
|
1002
|
+
return withMediaCdnQuery(src, [
|
|
1003
|
+
[
|
|
1004
|
+
MEDIA_CDN_RENDITION_PARAM,
|
|
1005
|
+
MEDIA_CDN_RENDITION_AUTO
|
|
1006
|
+
]
|
|
1007
|
+
]);
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* The still a Video element should show, from the two places one can come
|
|
1011
|
+
* from (AGL-2749).
|
|
1012
|
+
*
|
|
1013
|
+
* A video placement has two candidate posters and they are not equal:
|
|
1014
|
+
*
|
|
1015
|
+
* 1. **The author's own**, a media reference or a URL in the element's
|
|
1016
|
+
* `poster` field. It wins outright wherever it is set — an author who went
|
|
1017
|
+
* and chose a frame meant that frame, and a generated one silently
|
|
1018
|
+
* replacing it would make re-picking the SOURCE a destructive edit.
|
|
1019
|
+
* 2. **The one the DAM generated at upload** ({@link mediaPosterSrc}), which
|
|
1020
|
+
* is not a separate asset at all: it is `?poster=1` on the video's own
|
|
1021
|
+
* reference.
|
|
1022
|
+
*
|
|
1023
|
+
* ⚠️ `generated` is REQUIRED for the second, and it is the whole reason this
|
|
1024
|
+
* function exists rather than a `??` at each call site. `mediaPosterSrc`
|
|
1025
|
+
* answers for any CDN-form reference and its own documentation says plainly
|
|
1026
|
+
* that a URL is **not a promise a poster exists** — a video uploaded before
|
|
1027
|
+
* AGL-2742, or one the uploader's browser could not decode, answers 404. That
|
|
1028
|
+
* degrades harmlessly behind `<video poster>` and NOT harmlessly in an
|
|
1029
|
+
* `<img>` (a broken image) or in a `thumbnailUrl` (a rich result pointing at
|
|
1030
|
+
* nothing). So the caller has to have read `poster` off the media document —
|
|
1031
|
+
* which the pick does, once, and carries on the node.
|
|
1032
|
+
*
|
|
1033
|
+
* `width` narrows both candidates to a variant, for the surfaces that take one
|
|
1034
|
+
* url and no `srcset`. Omit it to get the full-size still, which is what an
|
|
1035
|
+
* `<img>` wants as its `src` beside a `srcSet` of widths.
|
|
1036
|
+
*/ export function videoPosterSrc(options) {
|
|
1037
|
+
const _ref = options != null ? options : {}, { poster, src, generated, width } = _ref, resolve = _object_without_properties_loose(_ref, [
|
|
1038
|
+
"poster",
|
|
1039
|
+
"src",
|
|
1040
|
+
"generated",
|
|
1041
|
+
"width"
|
|
1042
|
+
]);
|
|
1043
|
+
const authored = typeof poster === 'string' ? poster.trim() : '';
|
|
1044
|
+
if (authored) {
|
|
1045
|
+
return width ? mediaVariantSrc(authored, _extends({}, resolve, {
|
|
1046
|
+
width
|
|
1047
|
+
})) : resolveMediaSrc(authored, resolve);
|
|
1048
|
+
}
|
|
1049
|
+
if (!generated) return undefined;
|
|
1050
|
+
return mediaPosterSrc(typeof src === 'string' ? src : undefined, _extends({}, resolve, {
|
|
1051
|
+
width
|
|
1052
|
+
}));
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
//# sourceMappingURL=media-ref.js.map
|