@aglyn/aglyn 1.0.0-beta.218 → 1.0.0-beta.220
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -12
- package/src/lib/app-utils/actions.d.ts +26 -433
- package/src/lib/app-utils/actions.js +108 -633
- package/src/lib/app-utils/actions.js.map +1 -1
- package/src/lib/app-utils/activity-presenter.d.ts +3 -3
- package/src/lib/app-utils/activity-presenter.js +36 -52
- package/src/lib/app-utils/activity-presenter.js.map +1 -1
- package/src/lib/app-utils/analytics-events.d.ts +1 -1
- package/src/lib/app-utils/analytics-events.js.map +1 -1
- package/src/lib/app-utils/analytics-provider.d.ts +182 -0
- package/src/lib/app-utils/analytics-provider.js +133 -0
- package/src/lib/app-utils/analytics-provider.js.map +1 -0
- package/src/lib/app-utils/api-plugins.d.ts +46 -0
- package/src/lib/app-utils/api-plugins.js +19 -0
- package/src/lib/app-utils/api-plugins.js.map +1 -1
- package/src/lib/app-utils/{marketplace-overrides.d.ts → artifact-overrides.d.ts} +9 -6
- package/src/lib/app-utils/{marketplace-overrides.js → artifact-overrides.js} +10 -7
- package/src/lib/app-utils/artifact-overrides.js.map +1 -0
- package/src/lib/app-utils/{marketplace-provenance.d.ts → artifact-provenance.d.ts} +12 -10
- package/src/lib/app-utils/{marketplace-provenance.js → artifact-provenance.js} +9 -7
- package/src/lib/app-utils/artifact-provenance.js.map +1 -0
- package/src/lib/app-utils/binding-token-catalog.d.ts +5 -13
- package/src/lib/app-utils/binding-token-catalog.js +17 -41
- package/src/lib/app-utils/binding-token-catalog.js.map +1 -1
- package/src/lib/app-utils/brand-support-line.d.ts +36 -0
- package/src/lib/app-utils/brand-support-line.js +38 -0
- package/src/lib/app-utils/brand-support-line.js.map +1 -0
- package/src/lib/app-utils/collection-entries.d.ts +2 -2
- package/src/lib/app-utils/collection-entries.js.map +1 -1
- package/src/lib/app-utils/consent-group-change.d.ts +4 -0
- package/src/lib/app-utils/consent-group-change.js.map +1 -1
- package/src/lib/app-utils/consent-groups.d.ts +1 -1
- package/src/lib/app-utils/consent-groups.js.map +1 -1
- package/src/lib/app-utils/console-routes.d.ts +15 -42
- package/src/lib/app-utils/console-routes.js +10 -39
- package/src/lib/app-utils/console-routes.js.map +1 -1
- package/src/lib/app-utils/contacts.d.ts +24 -2
- package/src/lib/app-utils/contacts.js +21 -5
- package/src/lib/app-utils/contacts.js.map +1 -1
- package/src/lib/app-utils/container-membership.d.ts +93 -0
- package/src/lib/app-utils/container-membership.js +165 -0
- package/src/lib/app-utils/container-membership.js.map +1 -0
- package/src/lib/app-utils/crm-task-reminders.d.ts +23 -6
- package/src/lib/app-utils/crm-task-reminders.js +32 -11
- package/src/lib/app-utils/crm-task-reminders.js.map +1 -1
- package/src/lib/app-utils/crm.d.ts +24 -4
- package/src/lib/app-utils/crm.js +23 -0
- package/src/lib/app-utils/crm.js.map +1 -1
- package/src/lib/app-utils/cross-pool-desync.d.ts +39 -0
- package/src/lib/app-utils/cross-pool-desync.js +47 -0
- package/src/lib/app-utils/cross-pool-desync.js.map +1 -0
- package/src/lib/app-utils/csv-upload.d.ts +29 -0
- package/src/lib/app-utils/csv-upload.js +29 -0
- package/src/lib/app-utils/csv-upload.js.map +1 -0
- package/src/lib/app-utils/{dataset-csv.d.ts → csv.d.ts} +10 -43
- package/src/lib/app-utils/{dataset-csv.js → csv.js} +10 -81
- package/src/lib/app-utils/csv.js.map +1 -0
- package/src/lib/app-utils/dataset-models.d.ts +5 -5
- package/src/lib/app-utils/dataset-models.js +19 -2
- package/src/lib/app-utils/dataset-models.js.map +1 -1
- package/src/lib/app-utils/datasets.d.ts +65 -30
- package/src/lib/app-utils/datasets.js +74 -24
- package/src/lib/app-utils/datasets.js.map +1 -1
- package/src/lib/app-utils/docs-deflection.d.ts +6 -6
- package/src/lib/app-utils/docs-deflection.js.map +1 -1
- package/src/lib/app-utils/docs-help.generated.d.ts +14 -8
- package/src/lib/app-utils/docs-help.generated.js +23 -6
- package/src/lib/app-utils/docs-help.generated.js.map +1 -1
- package/src/lib/app-utils/docs-index.generated.d.ts +2 -2
- package/src/lib/app-utils/docs-index.generated.js +570 -346
- package/src/lib/app-utils/docs-index.generated.js.map +1 -1
- package/src/lib/app-utils/docs-retrieval.d.ts +3 -3
- package/src/lib/app-utils/docs-retrieval.js +14 -10
- package/src/lib/app-utils/docs-retrieval.js.map +1 -1
- package/src/lib/app-utils/duplicate-resource.d.ts +4 -1
- package/src/lib/app-utils/duplicate-resource.js +7 -4
- package/src/lib/app-utils/duplicate-resource.js.map +1 -1
- package/src/lib/app-utils/dynamic-list-rule.d.ts +1 -1
- package/src/lib/app-utils/dynamic-list-rule.js +3 -3
- package/src/lib/app-utils/dynamic-list-rule.js.map +1 -1
- package/src/lib/app-utils/element-ui.d.ts +1 -1
- package/src/lib/app-utils/element-ui.js +1 -1
- package/src/lib/app-utils/element-ui.js.map +1 -1
- package/src/lib/app-utils/email-starter-policy.js +3 -3
- package/src/lib/app-utils/email-starter-policy.js.map +1 -1
- package/src/lib/app-utils/email-text.d.ts +80 -0
- package/src/lib/app-utils/email-text.js +189 -0
- package/src/lib/app-utils/email-text.js.map +1 -0
- package/src/lib/app-utils/{list-assignment-policy.d.ts → enrollment-basis.d.ts} +4 -0
- package/src/lib/app-utils/{list-assignment-policy.js → enrollment-basis.js} +5 -1
- package/src/lib/app-utils/enrollment-basis.js.map +1 -0
- package/src/lib/app-utils/entity-picker-context.d.ts +10 -5
- package/src/lib/app-utils/entity-picker-context.js.map +1 -1
- package/src/lib/app-utils/error-beacon.d.ts +75 -6
- package/src/lib/app-utils/error-beacon.js +160 -21
- package/src/lib/app-utils/error-beacon.js.map +1 -1
- package/src/lib/app-utils/expand-repeatables.d.ts +10 -10
- package/src/lib/app-utils/expand-repeatables.js +14 -14
- package/src/lib/app-utils/expand-repeatables.js.map +1 -1
- package/src/lib/app-utils/forms.js +2 -2
- package/src/lib/app-utils/forms.js.map +1 -1
- package/src/lib/app-utils/health-report.d.ts +2 -3
- package/src/lib/app-utils/health-report.js +8 -6
- package/src/lib/app-utils/health-report.js.map +1 -1
- package/src/lib/app-utils/host-events.d.ts +82 -0
- package/src/lib/app-utils/host-events.js +62 -0
- package/src/lib/app-utils/host-events.js.map +1 -0
- package/src/lib/app-utils/inbound-mail-domain.d.ts +27 -0
- package/src/lib/app-utils/inbound-mail-domain.js +31 -0
- package/src/lib/app-utils/inbound-mail-domain.js.map +1 -0
- package/src/lib/app-utils/lockdown.d.ts +11 -0
- package/src/lib/app-utils/lockdown.js +33 -3
- package/src/lib/app-utils/lockdown.js.map +1 -1
- package/src/lib/app-utils/margin-utilization.d.ts +4 -69
- package/src/lib/app-utils/margin-utilization.js +82 -69
- package/src/lib/app-utils/margin-utilization.js.map +1 -1
- package/src/lib/app-utils/member-email-aliases.d.ts +25 -0
- package/src/lib/app-utils/member-email-aliases.js +29 -0
- package/src/lib/app-utils/member-email-aliases.js.map +1 -1
- package/src/lib/app-utils/node-definition-sanitizer.d.ts +16 -16
- package/src/lib/app-utils/node-definition-sanitizer.js +24 -20
- package/src/lib/app-utils/node-definition-sanitizer.js.map +1 -1
- package/src/lib/app-utils/node-interactions.d.ts +7 -7
- package/src/lib/app-utils/node-interactions.js.map +1 -1
- package/src/lib/app-utils/notifications.d.ts +147 -47
- package/src/lib/app-utils/notifications.js +182 -44
- package/src/lib/app-utils/notifications.js.map +1 -1
- package/src/lib/app-utils/operator-alerts.d.ts +15 -1
- package/src/lib/app-utils/operator-alerts.js +47 -10
- package/src/lib/app-utils/operator-alerts.js.map +1 -1
- package/src/lib/app-utils/payments-configured.d.ts +8 -21
- package/src/lib/app-utils/payments-configured.js +8 -23
- package/src/lib/app-utils/payments-configured.js.map +1 -1
- package/src/lib/app-utils/plan-entitlements.d.ts +207 -306
- package/src/lib/app-utils/plan-entitlements.js +345 -528
- package/src/lib/app-utils/plan-entitlements.js.map +1 -1
- package/src/lib/app-utils/platform-brand.d.ts +10 -0
- package/src/lib/app-utils/platform-brand.js +14 -3
- package/src/lib/app-utils/platform-brand.js.map +1 -1
- package/src/lib/app-utils/platform-marketing-consent.d.ts +56 -2
- package/src/lib/app-utils/platform-marketing-consent.js +6 -5
- package/src/lib/app-utils/platform-marketing-consent.js.map +1 -1
- package/src/lib/app-utils/plugin-api-rate-limit.d.ts +7 -1
- package/src/lib/app-utils/plugin-api-rate-limit.js +11 -3
- package/src/lib/app-utils/plugin-api-rate-limit.js.map +1 -1
- package/src/lib/app-utils/plugin-bundle-checks.js +2 -2
- package/src/lib/app-utils/plugin-bundle-checks.js.map +1 -1
- package/src/lib/app-utils/plugin-host-events.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-host-events.generated.js +169 -0
- package/src/lib/app-utils/plugin-host-events.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-release-flags.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js +106 -0
- package/src/lib/app-utils/plugin-release-flags.generated.js.map +1 -0
- package/src/lib/app-utils/plugin-starter-templates.generated.d.ts +12 -0
- package/src/lib/app-utils/plugin-starter-templates.generated.js +711 -0
- package/src/lib/app-utils/plugin-starter-templates.generated.js.map +1 -0
- package/src/lib/app-utils/realm-host-surface.generated.js +2 -0
- package/src/lib/app-utils/realm-host-surface.generated.js.map +1 -1
- package/src/lib/app-utils/release-flags.d.ts +14 -5
- package/src/lib/app-utils/release-flags.js +21 -125
- package/src/lib/app-utils/release-flags.js.map +1 -1
- package/src/lib/app-utils/repeat-query.d.ts +56 -0
- package/src/lib/app-utils/{dataset-query.js → repeat-query.js} +16 -16
- package/src/lib/app-utils/repeat-query.js.map +1 -0
- package/src/lib/app-utils/repeat-sources.d.ts +9 -0
- package/src/lib/app-utils/repeat-sources.js.map +1 -1
- package/src/lib/app-utils/retained-refusals.d.ts +73 -0
- package/src/lib/app-utils/retained-refusals.js +186 -0
- package/src/lib/app-utils/retained-refusals.js.map +1 -0
- package/src/lib/app-utils/scope-tokens.d.ts +27 -0
- package/src/lib/app-utils/scope-tokens.js +61 -0
- package/src/lib/app-utils/scope-tokens.js.map +1 -1
- package/src/lib/app-utils/screen-link-context.js +3 -3
- package/src/lib/app-utils/screen-link-context.js.map +1 -1
- package/src/lib/app-utils/screen-route.js +1 -1
- package/src/lib/app-utils/screen-route.js.map +1 -1
- package/src/lib/app-utils/seo-audit.d.ts +132 -0
- package/src/lib/app-utils/seo-audit.js +246 -0
- package/src/lib/app-utils/seo-audit.js.map +1 -0
- package/src/lib/app-utils/seo-keywords.d.ts +48 -0
- package/src/lib/app-utils/seo-keywords.js +60 -0
- package/src/lib/app-utils/seo-keywords.js.map +1 -0
- package/src/lib/app-utils/seo-page-facts.d.ts +66 -0
- package/src/lib/app-utils/seo-page-facts.js +155 -0
- package/src/lib/app-utils/seo-page-facts.js.map +1 -0
- package/src/lib/app-utils/seo-site-scan.d.ts +126 -0
- package/src/lib/app-utils/seo-site-scan.js +162 -0
- package/src/lib/app-utils/seo-site-scan.js.map +1 -0
- package/src/lib/app-utils/seo-title-variables.js +1 -1
- package/src/lib/app-utils/seo-title-variables.js.map +1 -1
- package/src/lib/app-utils/server.d.ts +13 -18
- package/src/lib/app-utils/server.js +33 -51
- package/src/lib/app-utils/server.js.map +1 -1
- package/src/lib/app-utils/site-interactions.d.ts +501 -0
- package/src/lib/app-utils/site-interactions.js +554 -0
- package/src/lib/app-utils/site-interactions.js.map +1 -0
- package/src/lib/app-utils/{marketplace-theme.d.ts → site-theme.d.ts} +13 -2
- package/src/lib/app-utils/{marketplace-theme.js → site-theme.js} +2 -2
- package/src/lib/app-utils/site-theme.js.map +1 -0
- package/src/lib/app-utils/sitemap.d.ts +4 -3
- package/src/lib/app-utils/sitemap.js +9 -7
- package/src/lib/app-utils/sitemap.js.map +1 -1
- package/src/lib/app-utils/stale-build-error.d.ts +51 -0
- package/src/lib/app-utils/stale-build-error.js +100 -1
- package/src/lib/app-utils/stale-build-error.js.map +1 -1
- package/src/lib/app-utils/starter-template-nodes.d.ts +137 -0
- package/src/lib/app-utils/starter-template-nodes.js +129 -0
- package/src/lib/app-utils/starter-template-nodes.js.map +1 -0
- package/src/lib/app-utils/starter-templates.d.ts +11 -34
- package/src/lib/app-utils/starter-templates.js +19 -230
- package/src/lib/app-utils/starter-templates.js.map +1 -1
- package/src/lib/app-utils/{email-topics.d.ts → subscription-topics.d.ts} +64 -48
- package/src/lib/app-utils/{email-topics.js → subscription-topics.js} +39 -109
- package/src/lib/app-utils/subscription-topics.js.map +1 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.d.ts +118 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js +123 -0
- package/src/lib/app-utils/tax-jurisdiction-figures.js.map +1 -0
- package/src/lib/app-utils/theme-library.d.ts +10 -3
- package/src/lib/app-utils/theme-library.js +13 -4
- package/src/lib/app-utils/theme-library.js.map +1 -1
- package/src/lib/app-utils/usage-budget.d.ts +73 -188
- package/src/lib/app-utils/usage-budget.js +58 -194
- package/src/lib/app-utils/usage-budget.js.map +1 -1
- package/src/lib/app-utils/{campaign-attribution.d.ts → utm-attribution.d.ts} +11 -6
- package/src/lib/app-utils/{campaign-attribution.js → utm-attribution.js} +13 -8
- package/src/lib/app-utils/utm-attribution.js.map +1 -0
- package/src/lib/app-utils/{campaign-forwarding.d.ts → utm-forwarding.d.ts} +14 -14
- package/src/lib/app-utils/{campaign-forwarding.js → utm-forwarding.js} +26 -26
- package/src/lib/app-utils/utm-forwarding.js.map +1 -0
- package/src/lib/app-utils/{campaign-touch.d.ts → utm-touch.d.ts} +25 -17
- package/src/lib/app-utils/{campaign-touch.js → utm-touch.js} +38 -30
- package/src/lib/app-utils/utm-touch.js.map +1 -0
- package/src/lib/app-utils/variables.d.ts +9 -9
- package/src/lib/app-utils/variables.js.map +1 -1
- package/src/lib/app-utils/video-object.js +6 -5
- package/src/lib/app-utils/video-object.js.map +1 -1
- package/src/lib/app-utils/visitor-consent.d.ts +41 -164
- package/src/lib/app-utils/visitor-consent.js +66 -277
- package/src/lib/app-utils/visitor-consent.js.map +1 -1
- package/src/lib/app-utils/visitor-record-ceiling.d.ts +32 -0
- package/src/lib/app-utils/visitor-record-ceiling.js +39 -0
- package/src/lib/app-utils/visitor-record-ceiling.js.map +1 -1
- package/src/lib/app-utils/web-vitals-rum.d.ts +7 -7
- package/src/lib/app-utils/web-vitals-rum.js +31 -63
- package/src/lib/app-utils/web-vitals-rum.js.map +1 -1
- package/src/lib/app-utils/where-used.d.ts +11 -6
- package/src/lib/app-utils/where-used.js +3 -8
- package/src/lib/app-utils/where-used.js.map +1 -1
- package/src/lib/foundation/definitions/components.types.d.ts +1 -1
- package/src/lib/foundation/definitions/components.types.js +1 -1
- package/src/lib/foundation/definitions/components.types.js.map +1 -1
- package/src/lib/foundation/definitions/org-billing.types.d.ts +11 -137
- package/src/lib/foundation/definitions/org-billing.types.js.map +1 -1
- package/src/lib/foundation/definitions/organization.types.d.ts +1 -3
- package/src/lib/foundation/definitions/organization.types.js.map +1 -1
- package/src/lib/foundation/definitions/platform.types.d.ts +11 -5
- package/src/lib/foundation/definitions/platform.types.js.map +1 -1
- package/src/lib/foundation/definitions/write-deny-coverage.util.d.ts +16 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js +20 -0
- package/src/lib/foundation/definitions/write-deny-coverage.util.js.map +1 -1
- package/src/lib/foundation/index.d.ts +1 -1
- package/src/lib/foundation/index.js.map +1 -1
- package/src/lib/plugin-manager/besigner-documents.d.ts +96 -0
- package/src/lib/plugin-manager/besigner-documents.js +61 -0
- package/src/lib/plugin-manager/besigner-documents.js.map +1 -0
- package/src/lib/plugin-manager/computed-variables.d.ts +71 -0
- package/src/lib/plugin-manager/computed-variables.js +74 -0
- package/src/lib/plugin-manager/computed-variables.js.map +1 -0
- package/src/lib/plugin-manager/custom-fields.d.ts +29 -2
- package/src/lib/plugin-manager/custom-fields.js +47 -1
- package/src/lib/plugin-manager/custom-fields.js.map +1 -1
- package/src/lib/plugin-manager/feature-plugins.d.ts +372 -99
- package/src/lib/plugin-manager/feature-plugins.js +126 -51
- package/src/lib/plugin-manager/feature-plugins.js.map +1 -1
- package/src/lib/plugin-manager/first-party-plugins.generated.d.ts +134 -0
- package/src/lib/plugin-manager/first-party-plugins.generated.js +840 -10
- package/src/lib/plugin-manager/first-party-plugins.generated.js.map +1 -1
- package/src/lib/plugin-manager/index.d.ts +0 -1
- package/src/lib/plugin-manager/index.js +0 -1
- package/src/lib/plugin-manager/index.js.map +1 -1
- package/src/lib/plugin-manager/plugin-activity-actions.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js +25 -0
- package/src/lib/plugin-manager/plugin-activity-actions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-contact-capture.d.ts +9 -4
- package/src/lib/plugin-manager/plugin-contact-capture.js.map +1 -1
- package/src/lib/plugin-manager/plugin-containers.d.ts +68 -0
- package/src/lib/plugin-manager/plugin-containers.generated.d.ts +10 -0
- package/src/lib/plugin-manager/plugin-containers.generated.js +20 -0
- package/src/lib/plugin-manager/plugin-containers.generated.js.map +1 -0
- package/src/lib/plugin-manager/plugin-containers.js +27 -0
- package/src/lib/plugin-manager/plugin-containers.js.map +1 -0
- package/src/lib/plugin-manager/plugin-contributions.d.ts +1 -1
- package/src/lib/plugin-manager/plugin-contributions.js.map +1 -1
- package/src/lib/plugin-manager/plugin-declarations-repair.d.ts +36 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js +64 -0
- package/src/lib/plugin-manager/plugin-declarations-repair.js.map +1 -0
- package/src/lib/plugin-manager/plugin-dependents.d.ts +101 -0
- package/src/lib/plugin-manager/plugin-dependents.js +75 -0
- package/src/lib/plugin-manager/plugin-dependents.js.map +1 -0
- package/src/lib/plugin-manager/plugin-distribution.d.ts +55 -0
- package/src/lib/plugin-manager/plugin-distribution.js +45 -0
- package/src/lib/plugin-manager/plugin-distribution.js.map +1 -0
- package/src/lib/plugin-manager/plugin-entitlements.d.ts +8 -0
- package/src/lib/plugin-manager/plugin-entitlements.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-collections.d.ts +17 -0
- package/src/lib/plugin-manager/plugin-host-collections.js +6 -0
- package/src/lib/plugin-manager/plugin-host-collections.js.map +1 -1
- package/src/lib/plugin-manager/plugin-host-resources.d.ts +133 -0
- package/src/lib/plugin-manager/plugin-host-resources.js +52 -0
- package/src/lib/plugin-manager/plugin-host-resources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-membership-detach.js +1 -1
- package/src/lib/plugin-manager/plugin-membership-detach.js.map +1 -1
- package/src/lib/plugin-manager/plugin-org-erasure.d.ts +28 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js +61 -2
- package/src/lib/plugin-manager/plugin-org-erasure.js.map +1 -1
- package/src/lib/plugin-manager/plugin-plan-entitlements.d.ts +123 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js +101 -0
- package/src/lib/plugin-manager/plugin-plan-entitlements.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-email-state.d.ts +69 -0
- package/src/lib/plugin-manager/plugin-record-email-state.js +32 -0
- package/src/lib/plugin-manager/plugin-record-email-state.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-index.d.ts +95 -0
- package/src/lib/plugin-manager/plugin-record-index.js +51 -0
- package/src/lib/plugin-manager/plugin-record-index.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-lists.d.ts +115 -0
- package/src/lib/plugin-manager/plugin-record-lists.js +75 -0
- package/src/lib/plugin-manager/plugin-record-lists.js.map +1 -0
- package/src/lib/plugin-manager/plugin-record-timeline.d.ts +42 -8
- package/src/lib/plugin-manager/plugin-record-timeline.js.map +1 -1
- package/src/lib/plugin-manager/plugin-record-written.d.ts +58 -0
- package/src/lib/plugin-manager/plugin-record-written.js +42 -0
- package/src/lib/plugin-manager/plugin-record-written.js.map +1 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.d.ts +213 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js +194 -0
- package/src/lib/plugin-manager/plugin-revenue-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-beacons.d.ts +71 -0
- package/src/lib/plugin-manager/plugin-site-beacons.js +54 -0
- package/src/lib/plugin-manager/plugin-site-beacons.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-bundle.d.ts +145 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js +78 -0
- package/src/lib/plugin-manager/plugin-site-bundle.js.map +1 -0
- package/src/lib/plugin-manager/plugin-site-cache.d.ts +12 -0
- package/src/lib/plugin-manager/plugin-site-cache.js.map +1 -1
- package/src/lib/plugin-manager/plugin-site-export.d.ts +81 -0
- package/src/lib/plugin-manager/plugin-site-export.js +40 -0
- package/src/lib/plugin-manager/plugin-site-export.js.map +1 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.d.ts +88 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js +29 -0
- package/src/lib/plugin-manager/plugin-sitemap-sections.js.map +1 -0
- package/src/lib/plugin-manager/plugin-subscription-topics.generated.d.ts +11 -0
- package/src/lib/plugin-manager/plugin-subscription-topics.generated.js +41 -0
- package/src/lib/plugin-manager/plugin-subscription-topics.generated.js.map +1 -0
- package/src/lib/plugin-manager/plugin-tax-profile.d.ts +20 -4
- package/src/lib/plugin-manager/plugin-tax-profile.js.map +1 -1
- package/src/lib/plugin-manager/plugin-tax-return-sources.d.ts +255 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js +191 -0
- package/src/lib/plugin-manager/plugin-tax-return-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-template-sources.d.ts +75 -0
- package/src/lib/plugin-manager/plugin-template-sources.js +37 -0
- package/src/lib/plugin-manager/plugin-template-sources.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-axes.d.ts +319 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js +186 -0
- package/src/lib/plugin-manager/plugin-usage-axes.js.map +1 -0
- package/src/lib/plugin-manager/plugin-usage-meters.d.ts +108 -0
- package/src/lib/plugin-manager/plugin-usage-meters.js +105 -0
- package/src/lib/plugin-manager/plugin-usage-meters.js.map +1 -0
- package/src/lib/plugin-manager/plugin-zones.d.ts +4 -5
- package/src/lib/plugin-manager/plugin-zones.js.map +1 -1
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js +2 -0
- package/src/lib/plugin-manager/realm-host-aglyn.generated.js.map +1 -1
- package/src/lib/plugin-manager/record-captured-contact.d.ts +1 -14
- package/src/lib/plugin-manager/record-captured-contact.js +10 -32
- package/src/lib/plugin-manager/record-captured-contact.js.map +1 -1
- package/src/lib/plugin-manager/repeat-rows.d.ts +124 -0
- package/src/lib/plugin-manager/repeat-rows.js +108 -0
- package/src/lib/plugin-manager/repeat-rows.js.map +1 -0
- package/src/lib/plugin-manager/submission-record-target.d.ts +144 -0
- package/src/lib/plugin-manager/submission-record-target.js +125 -0
- package/src/lib/plugin-manager/submission-record-target.js.map +1 -0
- package/src/lib/plugin-manager/usage-alert-contributors.d.ts +76 -6
- package/src/lib/plugin-manager/usage-alert-contributors.js +23 -10
- package/src/lib/plugin-manager/usage-alert-contributors.js.map +1 -1
- package/src/lib/plugin-manager/video-embed-provider.d.ts +108 -0
- package/src/lib/plugin-manager/video-embed-provider.js +165 -0
- package/src/lib/plugin-manager/video-embed-provider.js.map +1 -0
- package/src/lib/types/nodes.d.ts +2 -2
- package/src/lib/types/nodes.js.map +1 -1
- package/src/lib/app-utils/assist-credits.d.ts +0 -482
- package/src/lib/app-utils/assist-credits.js +0 -509
- package/src/lib/app-utils/assist-credits.js.map +0 -1
- package/src/lib/app-utils/campaign-attribution.js.map +0 -1
- package/src/lib/app-utils/campaign-forwarding.js.map +0 -1
- package/src/lib/app-utils/campaign-membership.d.ts +0 -121
- package/src/lib/app-utils/campaign-membership.js +0 -189
- package/src/lib/app-utils/campaign-membership.js.map +0 -1
- package/src/lib/app-utils/campaign-touch.js.map +0 -1
- package/src/lib/app-utils/console-record-links.d.ts +0 -163
- package/src/lib/app-utils/console-record-links.js +0 -180
- package/src/lib/app-utils/console-record-links.js.map +0 -1
- package/src/lib/app-utils/contact-holder.d.ts +0 -68
- package/src/lib/app-utils/contact-holder.js +0 -129
- package/src/lib/app-utils/contact-holder.js.map +0 -1
- package/src/lib/app-utils/contact-merge.d.ts +0 -136
- package/src/lib/app-utils/contact-merge.js +0 -412
- package/src/lib/app-utils/contact-merge.js.map +0 -1
- package/src/lib/app-utils/crm-booking.d.ts +0 -75
- package/src/lib/app-utils/crm-booking.js +0 -133
- package/src/lib/app-utils/crm-booking.js.map +0 -1
- package/src/lib/app-utils/crm-csv.d.ts +0 -239
- package/src/lib/app-utils/crm-csv.js +0 -467
- package/src/lib/app-utils/crm-csv.js.map +0 -1
- package/src/lib/app-utils/crm-digest.d.ts +0 -185
- package/src/lib/app-utils/crm-digest.js +0 -272
- package/src/lib/app-utils/crm-digest.js.map +0 -1
- package/src/lib/app-utils/crm-inbound.d.ts +0 -245
- package/src/lib/app-utils/crm-inbound.js +0 -407
- package/src/lib/app-utils/crm-inbound.js.map +0 -1
- package/src/lib/app-utils/crm-reports.d.ts +0 -479
- package/src/lib/app-utils/crm-reports.js +0 -680
- package/src/lib/app-utils/crm-reports.js.map +0 -1
- package/src/lib/app-utils/dataset-csv.js.map +0 -1
- package/src/lib/app-utils/dataset-query.d.ts +0 -57
- package/src/lib/app-utils/dataset-query.js.map +0 -1
- package/src/lib/app-utils/email-topics.js.map +0 -1
- package/src/lib/app-utils/form-dataset-binding.d.ts +0 -50
- package/src/lib/app-utils/form-dataset-binding.js +0 -74
- package/src/lib/app-utils/form-dataset-binding.js.map +0 -1
- package/src/lib/app-utils/list-assignment-policy.js.map +0 -1
- package/src/lib/app-utils/list-import.d.ts +0 -158
- package/src/lib/app-utils/list-import.js +0 -332
- package/src/lib/app-utils/list-import.js.map +0 -1
- package/src/lib/app-utils/marketplace-listing-visibility.d.ts +0 -122
- package/src/lib/app-utils/marketplace-listing-visibility.js +0 -147
- package/src/lib/app-utils/marketplace-listing-visibility.js.map +0 -1
- package/src/lib/app-utils/marketplace-overrides.js.map +0 -1
- package/src/lib/app-utils/marketplace-provenance.js.map +0 -1
- package/src/lib/app-utils/marketplace-theme.js.map +0 -1
- package/src/lib/app-utils/marketplace-update-state.d.ts +0 -119
- package/src/lib/app-utils/marketplace-update-state.js +0 -132
- package/src/lib/app-utils/marketplace-update-state.js.map +0 -1
- package/src/lib/app-utils/publisher-agreement.d.ts +0 -289
- package/src/lib/app-utils/publisher-agreement.js +0 -321
- package/src/lib/app-utils/publisher-agreement.js.map +0 -1
- package/src/lib/app-utils/wistia-embed.d.ts +0 -104
- package/src/lib/app-utils/wistia-embed.js +0 -138
- package/src/lib/app-utils/wistia-embed.js.map +0 -1
- package/src/lib/app-utils/workflows.d.ts +0 -136
- package/src/lib/app-utils/workflows.js +0 -346
- package/src/lib/app-utils/workflows.js.map +0 -1
- package/src/lib/plugin-manager/commerce-zone-props.d.ts +0 -172
- package/src/lib/plugin-manager/commerce-zone-props.js +0 -31
- package/src/lib/plugin-manager/commerce-zone-props.js.map +0 -1
- package/src/lib/plugin-manager/plugin-metered-lines.d.ts +0 -97
- package/src/lib/plugin-manager/plugin-metered-lines.js +0 -123
- package/src/lib/plugin-manager/plugin-metered-lines.js.map +0 -1
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import type { RepeatableDataset } from '../app-utils/expand-repeatables';
|
|
18
|
+
/**
|
|
19
|
+
* WHERE A PUBLISHED PAGE'S REPEATED ROWS COME FROM (AGL-3080).
|
|
20
|
+
*
|
|
21
|
+
* Any element can repeat, and the platform decides what a repeat MEANS — the
|
|
22
|
+
* scope, the copies, the filter, the bound (`expand-repeatables.ts`). What it
|
|
23
|
+
* does not decide is where the rows live. That is the plugin's that keeps
|
|
24
|
+
* them, and the composition that renders a published page asks it here, with
|
|
25
|
+
* the keys the page's tree repeats over, and never reads a collection itself.
|
|
26
|
+
*
|
|
27
|
+
* `repeat-sources.ts` is the editor's side of the same line: a hook the
|
|
28
|
+
* besigner's canvas mounts to preview the rows. This is the server's side,
|
|
29
|
+
* read once per compose, and it is a different registry because its readers
|
|
30
|
+
* are different processes with different failure costs.
|
|
31
|
+
*
|
|
32
|
+
* ## Declared, then registered — and an absent reader is refused
|
|
33
|
+
*
|
|
34
|
+
* The reader is registered from the owning plugin's `serverDeclarations`
|
|
35
|
+
* entry, which every app runs at boot, so every process that composes a page
|
|
36
|
+
* has it before the first request. But a registry is only safe where an empty
|
|
37
|
+
* one cannot be mistaken for an answer, and here it can: a page whose repeat
|
|
38
|
+
* found no reader would render the template once where the author put a list,
|
|
39
|
+
* and nothing anywhere would be red. That is the AGL-3025 shape on the most
|
|
40
|
+
* public surface the product has.
|
|
41
|
+
*
|
|
42
|
+
* So the plugin that answers also DECLARES that it does, in
|
|
43
|
+
* `plugins.config.json` (`repeatSource`), and the generator compiles that into
|
|
44
|
+
* core. The two together tell the one case that is a real answer from the one
|
|
45
|
+
* that is a broken boot:
|
|
46
|
+
*
|
|
47
|
+
* - nothing declared — this deployment ships no plugin that keeps rows, and a
|
|
48
|
+
* repeat renders its element once, as written, exactly as a key naming
|
|
49
|
+
* nothing does;
|
|
50
|
+
* - declared and registered — the reader answers;
|
|
51
|
+
* - declared and NOT registered — the boot failed. The app's declarations
|
|
52
|
+
* step is run again ({@link runPluginDeclarationsRepair}); if the reader is
|
|
53
|
+
* still missing, {@link readRepeatRows} THROWS. A render that throws keeps
|
|
54
|
+
* the page it last rendered in the cache and is loud in the logs, which is
|
|
55
|
+
* the right way round for a page that would otherwise go out wrong.
|
|
56
|
+
*
|
|
57
|
+
* Per-key failures are the reader's to absorb, as they always were: a deleted
|
|
58
|
+
* or unreadable entry leaves its element rendering once and costs the page
|
|
59
|
+
* nothing else.
|
|
60
|
+
*
|
|
61
|
+
* Reached by path, never through a barrel: only the server composition asks.
|
|
62
|
+
*/
|
|
63
|
+
/** One composition's question: the keys a page's tree repeats over. */
|
|
64
|
+
export interface RepeatRowsRequest {
|
|
65
|
+
/** The site being rendered. A reader answers only what that site may see. */
|
|
66
|
+
hostId: string;
|
|
67
|
+
/**
|
|
68
|
+
* The keys exactly as the nodes store them (`repeatKeys`), trimmed,
|
|
69
|
+
* sorted and without repeats.
|
|
70
|
+
*/
|
|
71
|
+
keys: readonly string[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The rows for a request, under every key the expansion looks them up by: the
|
|
75
|
+
* key as the node stores it, the entry's own id, and each entry a one-hop
|
|
76
|
+
* reference in the rows reads. A key with nothing to render is absent.
|
|
77
|
+
*/
|
|
78
|
+
export type RepeatRowsAnswer = Record<string, RepeatableDataset>;
|
|
79
|
+
/** Answers one composition's request. Never rejects for a single bad key. */
|
|
80
|
+
export type RepeatRowReader = (request: RepeatRowsRequest) => Promise<RepeatRowsAnswer>;
|
|
81
|
+
/** The compiled declaration: which plugin answers, under which source id. */
|
|
82
|
+
export interface RepeatSourceDeclaration {
|
|
83
|
+
pluginId: string;
|
|
84
|
+
/** The same id the plugin's editor source (`repeat-sources.ts`) uses. */
|
|
85
|
+
id: string;
|
|
86
|
+
}
|
|
87
|
+
/** The plugin declared to answer repeats, or `null` when none is. */
|
|
88
|
+
export declare function declaredRepeatSource(): RepeatSourceDeclaration | null;
|
|
89
|
+
interface RegisteredReader {
|
|
90
|
+
pluginId: string;
|
|
91
|
+
reader: RepeatRowReader;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Registers the reader for a source. Returns the unregister, which removes it
|
|
95
|
+
* only while it is still the one registered.
|
|
96
|
+
*
|
|
97
|
+
* The owner is the plugin whose register fn is running, or the `pluginId`
|
|
98
|
+
* passed for a boot declaration, where the loader's marker is not set. A
|
|
99
|
+
* registration with neither is refused, and so is one from a plugin other
|
|
100
|
+
* than the one the declaration names — two readers for one source would each
|
|
101
|
+
* answer for the other's rows. The same plugin registering again replaces its
|
|
102
|
+
* reader (a second surface, a repeated boot).
|
|
103
|
+
*/
|
|
104
|
+
export declare function registerRepeatRowReader(sourceId: string, reader: RepeatRowReader, options?: {
|
|
105
|
+
pluginId?: string;
|
|
106
|
+
}): () => void;
|
|
107
|
+
/** The reader registered for a source, with its owner, or `null`. */
|
|
108
|
+
export declare function repeatRowReader(sourceId: string): RegisteredReader | null;
|
|
109
|
+
/** Only for specs: forgets every registered reader. */
|
|
110
|
+
export declare function resetRepeatRowReadersForTests(): void;
|
|
111
|
+
/**
|
|
112
|
+
* The declared source's reader was not registered, even after the app's
|
|
113
|
+
* declarations step ran again. Thrown, never answered: see the module note.
|
|
114
|
+
*/
|
|
115
|
+
export declare class RepeatRowsUnavailableError extends Error {
|
|
116
|
+
readonly source: RepeatSourceDeclaration;
|
|
117
|
+
constructor(source: RepeatSourceDeclaration);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* The rows a composition's repeats render. See the module note for what each
|
|
121
|
+
* of the three cases answers; with no keys it answers `{}` and asks nobody.
|
|
122
|
+
*/
|
|
123
|
+
export declare function readRepeatRows(request: RepeatRowsRequest): Promise<RepeatRowsAnswer>;
|
|
124
|
+
export {};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ var _globalScope_READERS_KEY;
|
|
17
|
+
import { getRegisteringPluginId } from "../app-utils/registering-plugin.js";
|
|
18
|
+
import { PLUGIN_REPEAT_SOURCE_DECLARED } from "./first-party-plugins.generated.js";
|
|
19
|
+
import { runPluginDeclarationsRepair } from "./plugin-declarations-repair.js";
|
|
20
|
+
/** The plugin declared to answer repeats, or `null` when none is. */ export function declaredRepeatSource() {
|
|
21
|
+
return PLUGIN_REPEAT_SOURCE_DECLARED;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One table per process, on `globalThis` (AGL-3412): the app registers from
|
|
25
|
+
* `instrumentation.ts`, which Next compiles apart from the routes that read,
|
|
26
|
+
* and a module-scoped map would be filled in one copy and read empty in the
|
|
27
|
+
* other — the exact failure this module exists to refuse.
|
|
28
|
+
*/ const READERS_KEY = Symbol.for('@aglyn/aglyn:repeat-row-readers');
|
|
29
|
+
const globalScope = globalThis;
|
|
30
|
+
const readers = (_globalScope_READERS_KEY = globalScope[READERS_KEY]) != null ? _globalScope_READERS_KEY : globalScope[READERS_KEY] = new Map();
|
|
31
|
+
/**
|
|
32
|
+
* Registers the reader for a source. Returns the unregister, which removes it
|
|
33
|
+
* only while it is still the one registered.
|
|
34
|
+
*
|
|
35
|
+
* The owner is the plugin whose register fn is running, or the `pluginId`
|
|
36
|
+
* passed for a boot declaration, where the loader's marker is not set. A
|
|
37
|
+
* registration with neither is refused, and so is one from a plugin other
|
|
38
|
+
* than the one the declaration names — two readers for one source would each
|
|
39
|
+
* answer for the other's rows. The same plugin registering again replaces its
|
|
40
|
+
* reader (a second surface, a repeated boot).
|
|
41
|
+
*/ export function registerRepeatRowReader(sourceId, reader, options) {
|
|
42
|
+
var _ref, _getRegisteringPluginId;
|
|
43
|
+
const id = sourceId.trim();
|
|
44
|
+
const pluginId = ((_ref = (_getRegisteringPluginId = getRegisteringPluginId()) != null ? _getRegisteringPluginId : options == null ? void 0 : options.pluginId) != null ? _ref : '').trim();
|
|
45
|
+
if (!id) throw new Error('a repeat row reader needs a source id');
|
|
46
|
+
if (!pluginId) {
|
|
47
|
+
throw new Error(`repeat row reader "${id}" registered with no owner: pass { pluginId } ` + 'when registering outside a plugin register fn');
|
|
48
|
+
}
|
|
49
|
+
const declared = declaredRepeatSource();
|
|
50
|
+
if ((declared == null ? void 0 : declared.id) === id && declared.pluginId !== pluginId) {
|
|
51
|
+
throw new Error(`repeat source "${id}" is declared by "${declared.pluginId}"; ` + `refused a reader from "${pluginId}"`);
|
|
52
|
+
}
|
|
53
|
+
const held = readers.get(id);
|
|
54
|
+
if (held && held.pluginId !== pluginId) {
|
|
55
|
+
throw new Error(`repeat source "${id}" already has a reader from "${held.pluginId}"; ` + `refused "${pluginId}"`);
|
|
56
|
+
}
|
|
57
|
+
const entry = {
|
|
58
|
+
pluginId,
|
|
59
|
+
reader
|
|
60
|
+
};
|
|
61
|
+
readers.set(id, entry);
|
|
62
|
+
return ()=>{
|
|
63
|
+
if (readers.get(id) === entry) readers.delete(id);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** The reader registered for a source, with its owner, or `null`. */ export function repeatRowReader(sourceId) {
|
|
67
|
+
var _readers_get;
|
|
68
|
+
return (_readers_get = readers.get(sourceId)) != null ? _readers_get : null;
|
|
69
|
+
}
|
|
70
|
+
/** Only for specs: forgets every registered reader. */ export function resetRepeatRowReadersForTests() {
|
|
71
|
+
readers.clear();
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The declared source's reader was not registered, even after the app's
|
|
75
|
+
* declarations step ran again. Thrown, never answered: see the module note.
|
|
76
|
+
*/ export class RepeatRowsUnavailableError extends Error {
|
|
77
|
+
constructor(source){
|
|
78
|
+
super(`repeat source "${source.id}" is declared by "${source.pluginId}" but ` + 'no reader is registered in this process — its server declarations ' + 'did not run. Refusing to render repeats as if they had no rows.'), this.source = source;
|
|
79
|
+
this.name = 'RepeatRowsUnavailableError';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The rows a composition's repeats render. See the module note for what each
|
|
84
|
+
* of the three cases answers; with no keys it answers `{}` and asks nobody.
|
|
85
|
+
*/ export async function readRepeatRows(request) {
|
|
86
|
+
const keys = [
|
|
87
|
+
...new Set(request.keys.map((key)=>key.trim()).filter(Boolean))
|
|
88
|
+
].sort();
|
|
89
|
+
if (!keys.length) return {};
|
|
90
|
+
const declared = declaredRepeatSource();
|
|
91
|
+
if (!declared) return {};
|
|
92
|
+
let registered = readers.get(declared.id);
|
|
93
|
+
if (!registered) {
|
|
94
|
+
try {
|
|
95
|
+
await runPluginDeclarationsRepair();
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error('[repeat-rows] the declarations repair failed', error);
|
|
98
|
+
}
|
|
99
|
+
registered = readers.get(declared.id);
|
|
100
|
+
}
|
|
101
|
+
if (!registered) throw new RepeatRowsUnavailableError(declared);
|
|
102
|
+
return registered.reader({
|
|
103
|
+
hostId: request.hostId,
|
|
104
|
+
keys
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
//# sourceMappingURL=repeat-rows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/repeat-rows.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { RepeatableDataset } from '../app-utils/expand-repeatables'\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport { PLUGIN_REPEAT_SOURCE_DECLARED } from './first-party-plugins.generated'\nimport { runPluginDeclarationsRepair } from './plugin-declarations-repair'\n\n/**\n * WHERE A PUBLISHED PAGE'S REPEATED ROWS COME FROM (AGL-3080).\n *\n * Any element can repeat, and the platform decides what a repeat MEANS — the\n * scope, the copies, the filter, the bound (`expand-repeatables.ts`). What it\n * does not decide is where the rows live. That is the plugin's that keeps\n * them, and the composition that renders a published page asks it here, with\n * the keys the page's tree repeats over, and never reads a collection itself.\n *\n * `repeat-sources.ts` is the editor's side of the same line: a hook the\n * besigner's canvas mounts to preview the rows. This is the server's side,\n * read once per compose, and it is a different registry because its readers\n * are different processes with different failure costs.\n *\n * ## Declared, then registered — and an absent reader is refused\n *\n * The reader is registered from the owning plugin's `serverDeclarations`\n * entry, which every app runs at boot, so every process that composes a page\n * has it before the first request. But a registry is only safe where an empty\n * one cannot be mistaken for an answer, and here it can: a page whose repeat\n * found no reader would render the template once where the author put a list,\n * and nothing anywhere would be red. That is the AGL-3025 shape on the most\n * public surface the product has.\n *\n * So the plugin that answers also DECLARES that it does, in\n * `plugins.config.json` (`repeatSource`), and the generator compiles that into\n * core. The two together tell the one case that is a real answer from the one\n * that is a broken boot:\n *\n * - nothing declared — this deployment ships no plugin that keeps rows, and a\n * repeat renders its element once, as written, exactly as a key naming\n * nothing does;\n * - declared and registered — the reader answers;\n * - declared and NOT registered — the boot failed. The app's declarations\n * step is run again ({@link runPluginDeclarationsRepair}); if the reader is\n * still missing, {@link readRepeatRows} THROWS. A render that throws keeps\n * the page it last rendered in the cache and is loud in the logs, which is\n * the right way round for a page that would otherwise go out wrong.\n *\n * Per-key failures are the reader's to absorb, as they always were: a deleted\n * or unreadable entry leaves its element rendering once and costs the page\n * nothing else.\n *\n * Reached by path, never through a barrel: only the server composition asks.\n */\n\n/** One composition's question: the keys a page's tree repeats over. */\nexport interface RepeatRowsRequest {\n /** The site being rendered. A reader answers only what that site may see. */\n hostId: string\n /**\n * The keys exactly as the nodes store them (`repeatKeys`), trimmed,\n * sorted and without repeats.\n */\n keys: readonly string[]\n}\n\n/**\n * The rows for a request, under every key the expansion looks them up by: the\n * key as the node stores it, the entry's own id, and each entry a one-hop\n * reference in the rows reads. A key with nothing to render is absent.\n */\nexport type RepeatRowsAnswer = Record<string, RepeatableDataset>\n\n/** Answers one composition's request. Never rejects for a single bad key. */\nexport type RepeatRowReader = (\n request: RepeatRowsRequest,\n) => Promise<RepeatRowsAnswer>\n\n/** The compiled declaration: which plugin answers, under which source id. */\nexport interface RepeatSourceDeclaration {\n pluginId: string\n /** The same id the plugin's editor source (`repeat-sources.ts`) uses. */\n id: string\n}\n\n/** The plugin declared to answer repeats, or `null` when none is. */\nexport function declaredRepeatSource(): RepeatSourceDeclaration | null {\n return PLUGIN_REPEAT_SOURCE_DECLARED\n}\n\ninterface RegisteredReader {\n pluginId: string\n reader: RepeatRowReader\n}\n\n/**\n * One table per process, on `globalThis` (AGL-3412): the app registers from\n * `instrumentation.ts`, which Next compiles apart from the routes that read,\n * and a module-scoped map would be filled in one copy and read empty in the\n * other — the exact failure this module exists to refuse.\n */\nconst READERS_KEY = Symbol.for('@aglyn/aglyn:repeat-row-readers')\n\nconst globalScope = globalThis as typeof globalThis & {\n [READERS_KEY]?: Map<string, RegisteredReader>\n}\n\nconst readers: Map<string, RegisteredReader> =\n globalScope[READERS_KEY] ?? (globalScope[READERS_KEY] = new Map())\n\n/**\n * Registers the reader for a source. Returns the unregister, which removes it\n * only while it is still the one registered.\n *\n * The owner is the plugin whose register fn is running, or the `pluginId`\n * passed for a boot declaration, where the loader's marker is not set. A\n * registration with neither is refused, and so is one from a plugin other\n * than the one the declaration names — two readers for one source would each\n * answer for the other's rows. The same plugin registering again replaces its\n * reader (a second surface, a repeated boot).\n */\nexport function registerRepeatRowReader(\n sourceId: string,\n reader: RepeatRowReader,\n options?: { pluginId?: string },\n): () => void {\n const id = sourceId.trim()\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n if (!id) throw new Error('a repeat row reader needs a source id')\n if (!pluginId) {\n throw new Error(\n `repeat row reader \"${id}\" registered with no owner: pass { pluginId } ` +\n 'when registering outside a plugin register fn',\n )\n }\n const declared = declaredRepeatSource()\n if (declared?.id === id && declared.pluginId !== pluginId) {\n throw new Error(\n `repeat source \"${id}\" is declared by \"${declared.pluginId}\"; ` +\n `refused a reader from \"${pluginId}\"`,\n )\n }\n const held = readers.get(id)\n if (held && held.pluginId !== pluginId) {\n throw new Error(\n `repeat source \"${id}\" already has a reader from \"${held.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n const entry: RegisteredReader = { pluginId, reader }\n readers.set(id, entry)\n return () => {\n if (readers.get(id) === entry) readers.delete(id)\n }\n}\n\n/** The reader registered for a source, with its owner, or `null`. */\nexport function repeatRowReader(sourceId: string): RegisteredReader | null {\n return readers.get(sourceId) ?? null\n}\n\n/** Only for specs: forgets every registered reader. */\nexport function resetRepeatRowReadersForTests(): void {\n readers.clear()\n}\n\n/**\n * The declared source's reader was not registered, even after the app's\n * declarations step ran again. Thrown, never answered: see the module note.\n */\nexport class RepeatRowsUnavailableError extends Error {\n constructor(readonly source: RepeatSourceDeclaration) {\n super(\n `repeat source \"${source.id}\" is declared by \"${source.pluginId}\" but ` +\n 'no reader is registered in this process — its server declarations ' +\n 'did not run. Refusing to render repeats as if they had no rows.',\n )\n this.name = 'RepeatRowsUnavailableError'\n }\n}\n\n/**\n * The rows a composition's repeats render. See the module note for what each\n * of the three cases answers; with no keys it answers `{}` and asks nobody.\n */\nexport async function readRepeatRows(\n request: RepeatRowsRequest,\n): Promise<RepeatRowsAnswer> {\n const keys = [\n ...new Set(request.keys.map((key) => key.trim()).filter(Boolean)),\n ].sort()\n if (!keys.length) return {}\n const declared = declaredRepeatSource()\n if (!declared) return {}\n let registered = readers.get(declared.id)\n if (!registered) {\n try {\n await runPluginDeclarationsRepair()\n } catch (error) {\n console.error('[repeat-rows] the declarations repair failed', error)\n }\n registered = readers.get(declared.id)\n }\n if (!registered) throw new RepeatRowsUnavailableError(declared)\n return registered.reader({ hostId: request.hostId, keys })\n}\n"],"names":["globalScope","getRegisteringPluginId","PLUGIN_REPEAT_SOURCE_DECLARED","runPluginDeclarationsRepair","declaredRepeatSource","READERS_KEY","Symbol","for","globalThis","readers","Map","registerRepeatRowReader","sourceId","reader","options","id","trim","pluginId","Error","declared","held","get","entry","set","delete","repeatRowReader","resetRepeatRowReadersForTests","clear","RepeatRowsUnavailableError","source","name","readRepeatRows","request","keys","Set","map","key","filter","Boolean","sort","length","registered","error","console","hostId"],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* WHERE A FORM'S SUBMISSION IS ALSO SAVED AS A RECORD (AGL-3080).
|
|
19
|
+
*
|
|
20
|
+
* A form on a published page can file every submission as a record another
|
|
21
|
+
* plugin keeps — a row in a dataset, today. The form is one plugin's element
|
|
22
|
+
* and the record is another plugin's storage, so neither may know the other:
|
|
23
|
+
* this is the contract between them, and core names neither the target nor
|
|
24
|
+
* where it keeps anything.
|
|
25
|
+
*
|
|
26
|
+
* It has two halves, because the decision of where a record lands must be
|
|
27
|
+
* made where the visitor cannot reach it:
|
|
28
|
+
*
|
|
29
|
+
* 1. {@link stampFormRecordTargets} — the page's composition hands the target
|
|
30
|
+
* the tree it is about to ship, and the target stamps each form it will
|
|
31
|
+
* write for with whatever it needs to trust at submit time (a signed
|
|
32
|
+
* binding). The submit route is public and unauthenticated, so nothing
|
|
33
|
+
* the body says on its own may choose a destination.
|
|
34
|
+
* 2. {@link writeFormRecordTarget} — the submit route hands the target the
|
|
35
|
+
* submission as posted, after the submission itself is stored. The target
|
|
36
|
+
* reads back what it stamped, writes the record or refuses it, and answers
|
|
37
|
+
* what to note on the submission (`routing`) so the Inbox can say where it
|
|
38
|
+
* went or why it did not.
|
|
39
|
+
*
|
|
40
|
+
* ## Declared, then registered — and an absent target is loud
|
|
41
|
+
*
|
|
42
|
+
* The target registers from its plugin's `serverDeclarations` entry, which
|
|
43
|
+
* every app runs at boot, and also DECLARES itself in `plugins.config.json`
|
|
44
|
+
* (`formRecordTarget`), compiled into core. A registry alone would read a
|
|
45
|
+
* failed boot as "no form writes anywhere", and every bound form would keep
|
|
46
|
+
* accepting submissions while its records quietly stopped — the AGL-3025
|
|
47
|
+
* shape. With the declaration the three cases are distinct:
|
|
48
|
+
*
|
|
49
|
+
* - nothing declared — this deployment ships no plugin that keeps records; no
|
|
50
|
+
* form is stamped and no submission writes one, which is a real answer;
|
|
51
|
+
* - declared and registered — the target answers;
|
|
52
|
+
* - declared and NOT registered — the app's declarations step runs again. If
|
|
53
|
+
* the target is still missing, a page carrying a form THROWS at render (the
|
|
54
|
+
* cache keeps the last good page, and the logs are red), and a submission
|
|
55
|
+
* is kept — the Inbox copy is written before this is asked — with the
|
|
56
|
+
* failure logged and noted on it under `routing.recordTargetUnavailable`.
|
|
57
|
+
*
|
|
58
|
+
* Server-only, and reached by path, never through a barrel.
|
|
59
|
+
*/
|
|
60
|
+
/** One submission, as the route stored it. */
|
|
61
|
+
export interface FormRecordWriteRequest {
|
|
62
|
+
/** The site the form was submitted on. */
|
|
63
|
+
hostId: string;
|
|
64
|
+
/** The organization that owns the site, when it has one. */
|
|
65
|
+
orgId: string | null;
|
|
66
|
+
/** The organization's billing document — the entitlements a write is held to. */
|
|
67
|
+
orgBilling: unknown;
|
|
68
|
+
/**
|
|
69
|
+
* The request body as posted. The target reads back only what it stamped
|
|
70
|
+
* onto the form, and must trust nothing else in it.
|
|
71
|
+
*/
|
|
72
|
+
body: Readonly<Record<string, unknown>>;
|
|
73
|
+
/** The submitted values, sanitized, keyed by the name each field submits under. */
|
|
74
|
+
fields: Readonly<Record<string, string>>;
|
|
75
|
+
}
|
|
76
|
+
/** What a target answers for one submission. */
|
|
77
|
+
export interface FormRecordWriteOutcome {
|
|
78
|
+
/**
|
|
79
|
+
* Written as the stored submission's `routing` when present: where the
|
|
80
|
+
* record went, or why it was refused. Absent when the form writes nowhere.
|
|
81
|
+
*/
|
|
82
|
+
routing?: Record<string, unknown>;
|
|
83
|
+
}
|
|
84
|
+
/** A plugin that keeps the records forms may file into. */
|
|
85
|
+
export interface FormRecordTarget {
|
|
86
|
+
/**
|
|
87
|
+
* Stamps each form in a composed tree this target will write for. Never
|
|
88
|
+
* mutates `nodes`, and answers the same object when it stamps nothing.
|
|
89
|
+
*/
|
|
90
|
+
stamp<N extends Record<string, unknown>>(nodes: N, hostId: string): Promise<N>;
|
|
91
|
+
/**
|
|
92
|
+
* Writes one submission's record, or refuses it. Never rejects: a record
|
|
93
|
+
* that cannot be written is no reason to fail a submission already stored.
|
|
94
|
+
*/
|
|
95
|
+
write(request: FormRecordWriteRequest): Promise<FormRecordWriteOutcome>;
|
|
96
|
+
}
|
|
97
|
+
/** The compiled declaration: which plugin keeps the records forms file into. */
|
|
98
|
+
export interface FormRecordTargetDeclaration {
|
|
99
|
+
pluginId: string;
|
|
100
|
+
id: string;
|
|
101
|
+
}
|
|
102
|
+
/** The plugin declared as the forms' record target, or `null` when none is. */
|
|
103
|
+
export declare function declaredFormRecordTarget(): FormRecordTargetDeclaration | null;
|
|
104
|
+
interface RegisteredTarget {
|
|
105
|
+
pluginId: string;
|
|
106
|
+
target: FormRecordTarget;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Registers the target. The owner is the plugin whose register fn is running,
|
|
110
|
+
* or the `pluginId` passed for a boot declaration; with neither, or from a
|
|
111
|
+
* plugin other than the one declared, it throws. The same plugin registering
|
|
112
|
+
* again replaces its target. Returns the unregister.
|
|
113
|
+
*/
|
|
114
|
+
export declare function registerFormRecordTarget(target: FormRecordTarget, options?: {
|
|
115
|
+
pluginId?: string;
|
|
116
|
+
}): () => void;
|
|
117
|
+
/** The registered target with its owner, or `null`. */
|
|
118
|
+
export declare function formRecordTarget(): RegisteredTarget | null;
|
|
119
|
+
/** Only for specs: forgets the registered target. */
|
|
120
|
+
export declare function resetFormRecordTargetForTests(): void;
|
|
121
|
+
/**
|
|
122
|
+
* The declared target's registration was not found, even after the app's
|
|
123
|
+
* declarations step ran again.
|
|
124
|
+
*/
|
|
125
|
+
export declare class FormRecordTargetUnavailableError extends Error {
|
|
126
|
+
readonly declared: FormRecordTargetDeclaration;
|
|
127
|
+
constructor(declared: FormRecordTargetDeclaration);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The tree a page ships, with each form the target writes for stamped.
|
|
131
|
+
*
|
|
132
|
+
* A tree with no form asks nobody and comes back as the same object. A tree
|
|
133
|
+
* with one THROWS when the declared target is missing — see the module note.
|
|
134
|
+
*/
|
|
135
|
+
export declare function stampFormRecordTargets<N extends Record<string, unknown>>(nodes: N, hostId: string): Promise<N>;
|
|
136
|
+
/**
|
|
137
|
+
* Files one stored submission as a record where the page's form said to.
|
|
138
|
+
*
|
|
139
|
+
* Never rejects. With no target declared it answers nothing; with the declared
|
|
140
|
+
* target missing it logs the failure and answers a `routing` note saying so,
|
|
141
|
+
* because the submission is already kept and losing it now would be worse.
|
|
142
|
+
*/
|
|
143
|
+
export declare function writeFormRecordTarget(request: FormRecordWriteRequest): Promise<FormRecordWriteOutcome>;
|
|
144
|
+
export {};
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ import { getRegisteringPluginId } from "../app-utils/registering-plugin.js";
|
|
17
|
+
import { FORM_COMPONENT_ID } from "../app-utils/forms.js";
|
|
18
|
+
import { PLUGIN_FORM_RECORD_TARGET_DECLARED } from "./first-party-plugins.generated.js";
|
|
19
|
+
import { runPluginDeclarationsRepair } from "./plugin-declarations-repair.js";
|
|
20
|
+
/** The plugin declared as the forms' record target, or `null` when none is. */ export function declaredFormRecordTarget() {
|
|
21
|
+
return PLUGIN_FORM_RECORD_TARGET_DECLARED;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One slot per process, on `globalThis` (AGL-3412): the app registers from
|
|
25
|
+
* `instrumentation.ts`, which Next compiles apart from the routes that read.
|
|
26
|
+
*/ const TARGET_KEY = Symbol.for('@aglyn/aglyn:submission-record-target');
|
|
27
|
+
const globalScope = globalThis;
|
|
28
|
+
/**
|
|
29
|
+
* Registers the target. The owner is the plugin whose register fn is running,
|
|
30
|
+
* or the `pluginId` passed for a boot declaration; with neither, or from a
|
|
31
|
+
* plugin other than the one declared, it throws. The same plugin registering
|
|
32
|
+
* again replaces its target. Returns the unregister.
|
|
33
|
+
*/ export function registerFormRecordTarget(target, options) {
|
|
34
|
+
var _ref, _getRegisteringPluginId;
|
|
35
|
+
const pluginId = ((_ref = (_getRegisteringPluginId = getRegisteringPluginId()) != null ? _getRegisteringPluginId : options == null ? void 0 : options.pluginId) != null ? _ref : '').trim();
|
|
36
|
+
if (!pluginId) {
|
|
37
|
+
throw new Error('the form record target was registered with no owner: pass ' + '{ pluginId } when registering outside a plugin register fn');
|
|
38
|
+
}
|
|
39
|
+
const declared = declaredFormRecordTarget();
|
|
40
|
+
if (declared && declared.pluginId !== pluginId) {
|
|
41
|
+
throw new Error(`the form record target is declared by "${declared.pluginId}"; ` + `refused "${pluginId}"`);
|
|
42
|
+
}
|
|
43
|
+
const held = globalScope[TARGET_KEY];
|
|
44
|
+
if (held && held.pluginId !== pluginId) {
|
|
45
|
+
throw new Error(`the form record target is already registered by "${held.pluginId}"; ` + `refused "${pluginId}"`);
|
|
46
|
+
}
|
|
47
|
+
const entry = {
|
|
48
|
+
pluginId,
|
|
49
|
+
target
|
|
50
|
+
};
|
|
51
|
+
globalScope[TARGET_KEY] = entry;
|
|
52
|
+
return ()=>{
|
|
53
|
+
if (globalScope[TARGET_KEY] === entry) globalScope[TARGET_KEY] = null;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/** The registered target with its owner, or `null`. */ export function formRecordTarget() {
|
|
57
|
+
var _globalScope_TARGET_KEY;
|
|
58
|
+
return (_globalScope_TARGET_KEY = globalScope[TARGET_KEY]) != null ? _globalScope_TARGET_KEY : null;
|
|
59
|
+
}
|
|
60
|
+
/** Only for specs: forgets the registered target. */ export function resetFormRecordTargetForTests() {
|
|
61
|
+
globalScope[TARGET_KEY] = null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The declared target's registration was not found, even after the app's
|
|
65
|
+
* declarations step ran again.
|
|
66
|
+
*/ export class FormRecordTargetUnavailableError extends Error {
|
|
67
|
+
constructor(declared){
|
|
68
|
+
super(`the form record target is declared by "${declared.pluginId}" but none ` + 'is registered in this process — its server declarations did not run. ' + 'Refusing to treat bound forms as writing nowhere.'), this.declared = declared;
|
|
69
|
+
this.name = 'FormRecordTargetUnavailableError';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** The declared target, repaired once if missing; `null` when none is declared. */ async function requireDeclaredTarget() {
|
|
73
|
+
const declared = declaredFormRecordTarget();
|
|
74
|
+
if (!declared) return null;
|
|
75
|
+
let registered = formRecordTarget();
|
|
76
|
+
if (!registered) {
|
|
77
|
+
try {
|
|
78
|
+
await runPluginDeclarationsRepair();
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('[submission-record-target] the declarations repair failed', error);
|
|
81
|
+
}
|
|
82
|
+
registered = formRecordTarget();
|
|
83
|
+
}
|
|
84
|
+
if (!registered) throw new FormRecordTargetUnavailableError(declared);
|
|
85
|
+
return registered.target;
|
|
86
|
+
}
|
|
87
|
+
const placesAForm = (nodes)=>Object.values(nodes).some((node)=>(node == null ? void 0 : node.componentId) === FORM_COMPONENT_ID);
|
|
88
|
+
/**
|
|
89
|
+
* The tree a page ships, with each form the target writes for stamped.
|
|
90
|
+
*
|
|
91
|
+
* A tree with no form asks nobody and comes back as the same object. A tree
|
|
92
|
+
* with one THROWS when the declared target is missing — see the module note.
|
|
93
|
+
*/ export async function stampFormRecordTargets(nodes, hostId) {
|
|
94
|
+
if (!placesAForm(nodes)) return nodes;
|
|
95
|
+
const target = await requireDeclaredTarget();
|
|
96
|
+
return target ? target.stamp(nodes, hostId) : nodes;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Files one stored submission as a record where the page's form said to.
|
|
100
|
+
*
|
|
101
|
+
* Never rejects. With no target declared it answers nothing; with the declared
|
|
102
|
+
* target missing it logs the failure and answers a `routing` note saying so,
|
|
103
|
+
* because the submission is already kept and losing it now would be worse.
|
|
104
|
+
*/ export async function writeFormRecordTarget(request) {
|
|
105
|
+
let target;
|
|
106
|
+
try {
|
|
107
|
+
target = await requireDeclaredTarget();
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('[submission-record-target] a submission could not be filed', error);
|
|
110
|
+
return {
|
|
111
|
+
routing: {
|
|
112
|
+
recordTargetUnavailable: true
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (!target) return {};
|
|
117
|
+
try {
|
|
118
|
+
return await target.write(request);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('[submission-record-target] the target failed a write', error);
|
|
121
|
+
return {};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=submission-record-target.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/aglyn/src/lib/plugin-manager/submission-record-target.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getRegisteringPluginId } from '../app-utils/registering-plugin'\nimport { FORM_COMPONENT_ID } from '../app-utils/forms'\nimport { PLUGIN_FORM_RECORD_TARGET_DECLARED } from './first-party-plugins.generated'\nimport { runPluginDeclarationsRepair } from './plugin-declarations-repair'\n\n/**\n * WHERE A FORM'S SUBMISSION IS ALSO SAVED AS A RECORD (AGL-3080).\n *\n * A form on a published page can file every submission as a record another\n * plugin keeps — a row in a dataset, today. The form is one plugin's element\n * and the record is another plugin's storage, so neither may know the other:\n * this is the contract between them, and core names neither the target nor\n * where it keeps anything.\n *\n * It has two halves, because the decision of where a record lands must be\n * made where the visitor cannot reach it:\n *\n * 1. {@link stampFormRecordTargets} — the page's composition hands the target\n * the tree it is about to ship, and the target stamps each form it will\n * write for with whatever it needs to trust at submit time (a signed\n * binding). The submit route is public and unauthenticated, so nothing\n * the body says on its own may choose a destination.\n * 2. {@link writeFormRecordTarget} — the submit route hands the target the\n * submission as posted, after the submission itself is stored. The target\n * reads back what it stamped, writes the record or refuses it, and answers\n * what to note on the submission (`routing`) so the Inbox can say where it\n * went or why it did not.\n *\n * ## Declared, then registered — and an absent target is loud\n *\n * The target registers from its plugin's `serverDeclarations` entry, which\n * every app runs at boot, and also DECLARES itself in `plugins.config.json`\n * (`formRecordTarget`), compiled into core. A registry alone would read a\n * failed boot as \"no form writes anywhere\", and every bound form would keep\n * accepting submissions while its records quietly stopped — the AGL-3025\n * shape. With the declaration the three cases are distinct:\n *\n * - nothing declared — this deployment ships no plugin that keeps records; no\n * form is stamped and no submission writes one, which is a real answer;\n * - declared and registered — the target answers;\n * - declared and NOT registered — the app's declarations step runs again. If\n * the target is still missing, a page carrying a form THROWS at render (the\n * cache keeps the last good page, and the logs are red), and a submission\n * is kept — the Inbox copy is written before this is asked — with the\n * failure logged and noted on it under `routing.recordTargetUnavailable`.\n *\n * Server-only, and reached by path, never through a barrel.\n */\n\n/** One submission, as the route stored it. */\nexport interface FormRecordWriteRequest {\n /** The site the form was submitted on. */\n hostId: string\n /** The organization that owns the site, when it has one. */\n orgId: string | null\n /** The organization's billing document — the entitlements a write is held to. */\n orgBilling: unknown\n /**\n * The request body as posted. The target reads back only what it stamped\n * onto the form, and must trust nothing else in it.\n */\n body: Readonly<Record<string, unknown>>\n /** The submitted values, sanitized, keyed by the name each field submits under. */\n fields: Readonly<Record<string, string>>\n}\n\n/** What a target answers for one submission. */\nexport interface FormRecordWriteOutcome {\n /**\n * Written as the stored submission's `routing` when present: where the\n * record went, or why it was refused. Absent when the form writes nowhere.\n */\n routing?: Record<string, unknown>\n}\n\n/** A plugin that keeps the records forms may file into. */\nexport interface FormRecordTarget {\n /**\n * Stamps each form in a composed tree this target will write for. Never\n * mutates `nodes`, and answers the same object when it stamps nothing.\n */\n stamp<N extends Record<string, unknown>>(nodes: N, hostId: string): Promise<N>\n /**\n * Writes one submission's record, or refuses it. Never rejects: a record\n * that cannot be written is no reason to fail a submission already stored.\n */\n write(request: FormRecordWriteRequest): Promise<FormRecordWriteOutcome>\n}\n\n/** The compiled declaration: which plugin keeps the records forms file into. */\nexport interface FormRecordTargetDeclaration {\n pluginId: string\n id: string\n}\n\n/** The plugin declared as the forms' record target, or `null` when none is. */\nexport function declaredFormRecordTarget(): FormRecordTargetDeclaration | null {\n return PLUGIN_FORM_RECORD_TARGET_DECLARED\n}\n\ninterface RegisteredTarget {\n pluginId: string\n target: FormRecordTarget\n}\n\n/**\n * One slot per process, on `globalThis` (AGL-3412): the app registers from\n * `instrumentation.ts`, which Next compiles apart from the routes that read.\n */\nconst TARGET_KEY = Symbol.for('@aglyn/aglyn:submission-record-target')\n\nconst globalScope = globalThis as typeof globalThis & {\n [TARGET_KEY]?: RegisteredTarget | null\n}\n\n/**\n * Registers the target. The owner is the plugin whose register fn is running,\n * or the `pluginId` passed for a boot declaration; with neither, or from a\n * plugin other than the one declared, it throws. The same plugin registering\n * again replaces its target. Returns the unregister.\n */\nexport function registerFormRecordTarget(\n target: FormRecordTarget,\n options?: { pluginId?: string },\n): () => void {\n const pluginId = (getRegisteringPluginId() ?? options?.pluginId ?? '').trim()\n if (!pluginId) {\n throw new Error(\n 'the form record target was registered with no owner: pass ' +\n '{ pluginId } when registering outside a plugin register fn',\n )\n }\n const declared = declaredFormRecordTarget()\n if (declared && declared.pluginId !== pluginId) {\n throw new Error(\n `the form record target is declared by \"${declared.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n const held = globalScope[TARGET_KEY]\n if (held && held.pluginId !== pluginId) {\n throw new Error(\n `the form record target is already registered by \"${held.pluginId}\"; ` +\n `refused \"${pluginId}\"`,\n )\n }\n const entry: RegisteredTarget = { pluginId, target }\n globalScope[TARGET_KEY] = entry\n return () => {\n if (globalScope[TARGET_KEY] === entry) globalScope[TARGET_KEY] = null\n }\n}\n\n/** The registered target with its owner, or `null`. */\nexport function formRecordTarget(): RegisteredTarget | null {\n return globalScope[TARGET_KEY] ?? null\n}\n\n/** Only for specs: forgets the registered target. */\nexport function resetFormRecordTargetForTests(): void {\n globalScope[TARGET_KEY] = null\n}\n\n/**\n * The declared target's registration was not found, even after the app's\n * declarations step ran again.\n */\nexport class FormRecordTargetUnavailableError extends Error {\n constructor(readonly declared: FormRecordTargetDeclaration) {\n super(\n `the form record target is declared by \"${declared.pluginId}\" but none ` +\n 'is registered in this process — its server declarations did not run. ' +\n 'Refusing to treat bound forms as writing nowhere.',\n )\n this.name = 'FormRecordTargetUnavailableError'\n }\n}\n\n/** The declared target, repaired once if missing; `null` when none is declared. */\nasync function requireDeclaredTarget(): Promise<FormRecordTarget | null> {\n const declared = declaredFormRecordTarget()\n if (!declared) return null\n let registered = formRecordTarget()\n if (!registered) {\n try {\n await runPluginDeclarationsRepair()\n } catch (error) {\n console.error('[submission-record-target] the declarations repair failed', error)\n }\n registered = formRecordTarget()\n }\n if (!registered) throw new FormRecordTargetUnavailableError(declared)\n return registered.target\n}\n\nconst placesAForm = (nodes: Record<string, unknown>): boolean =>\n Object.values(nodes).some(\n (node) =>\n (node as { componentId?: unknown } | null)?.componentId === FORM_COMPONENT_ID,\n )\n\n/**\n * The tree a page ships, with each form the target writes for stamped.\n *\n * A tree with no form asks nobody and comes back as the same object. A tree\n * with one THROWS when the declared target is missing — see the module note.\n */\nexport async function stampFormRecordTargets<N extends Record<string, unknown>>(\n nodes: N,\n hostId: string,\n): Promise<N> {\n if (!placesAForm(nodes)) return nodes\n const target = await requireDeclaredTarget()\n return target ? target.stamp(nodes, hostId) : nodes\n}\n\n/**\n * Files one stored submission as a record where the page's form said to.\n *\n * Never rejects. With no target declared it answers nothing; with the declared\n * target missing it logs the failure and answers a `routing` note saying so,\n * because the submission is already kept and losing it now would be worse.\n */\nexport async function writeFormRecordTarget(\n request: FormRecordWriteRequest,\n): Promise<FormRecordWriteOutcome> {\n let target: FormRecordTarget | null\n try {\n target = await requireDeclaredTarget()\n } catch (error) {\n console.error('[submission-record-target] a submission could not be filed', error)\n return { routing: { recordTargetUnavailable: true } }\n }\n if (!target) return {}\n try {\n return await target.write(request)\n } catch (error) {\n console.error('[submission-record-target] the target failed a write', error)\n return {}\n }\n}\n"],"names":["getRegisteringPluginId","FORM_COMPONENT_ID","PLUGIN_FORM_RECORD_TARGET_DECLARED","runPluginDeclarationsRepair","declaredFormRecordTarget","TARGET_KEY","Symbol","for","globalScope","globalThis","registerFormRecordTarget","target","options","pluginId","trim","Error","declared","held","entry","formRecordTarget","resetFormRecordTargetForTests","FormRecordTargetUnavailableError","name","requireDeclaredTarget","registered","error","console","placesAForm","nodes","Object","values","some","node","componentId","stampFormRecordTargets","hostId","stamp","writeFormRecordTarget","request","routing","recordTargetUnavailable","write"],"mappings":"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"}
|