@growth-labs/cms 0.1.0
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/README.md +165 -0
- package/dist/engine/activity-log.d.ts +17 -0
- package/dist/engine/activity-log.d.ts.map +1 -0
- package/dist/engine/activity-log.js +17 -0
- package/dist/engine/activity-log.js.map +1 -0
- package/dist/engine/ai-prompts.d.ts +57 -0
- package/dist/engine/ai-prompts.d.ts.map +1 -0
- package/dist/engine/ai-prompts.js +90 -0
- package/dist/engine/ai-prompts.js.map +1 -0
- package/dist/engine/ai-writeback.d.ts +36 -0
- package/dist/engine/ai-writeback.d.ts.map +1 -0
- package/dist/engine/ai-writeback.js +45 -0
- package/dist/engine/ai-writeback.js.map +1 -0
- package/dist/engine/api-keys.d.ts +76 -0
- package/dist/engine/api-keys.d.ts.map +1 -0
- package/dist/engine/api-keys.js +165 -0
- package/dist/engine/api-keys.js.map +1 -0
- package/dist/engine/content-insights.d.ts +36 -0
- package/dist/engine/content-insights.d.ts.map +1 -0
- package/dist/engine/content-insights.js +114 -0
- package/dist/engine/content-insights.js.map +1 -0
- package/dist/engine/contributors.d.ts +25 -0
- package/dist/engine/contributors.d.ts.map +1 -0
- package/dist/engine/contributors.js +59 -0
- package/dist/engine/contributors.js.map +1 -0
- package/dist/engine/cron.d.ts +15 -0
- package/dist/engine/cron.d.ts.map +1 -0
- package/dist/engine/cron.js +33 -0
- package/dist/engine/cron.js.map +1 -0
- package/dist/engine/d1.d.ts +16 -0
- package/dist/engine/d1.d.ts.map +1 -0
- package/dist/engine/d1.js +13 -0
- package/dist/engine/d1.js.map +1 -0
- package/dist/engine/foundry-dispatch.d.ts +52 -0
- package/dist/engine/foundry-dispatch.d.ts.map +1 -0
- package/dist/engine/foundry-dispatch.js +290 -0
- package/dist/engine/foundry-dispatch.js.map +1 -0
- package/dist/engine/import-parsers.d.ts +11 -0
- package/dist/engine/import-parsers.d.ts.map +1 -0
- package/dist/engine/import-parsers.js +373 -0
- package/dist/engine/import-parsers.js.map +1 -0
- package/dist/engine/index.d.ts +28 -0
- package/dist/engine/index.d.ts.map +1 -0
- package/dist/engine/index.js +57 -0
- package/dist/engine/index.js.map +1 -0
- package/dist/engine/invites.d.ts +78 -0
- package/dist/engine/invites.d.ts.map +1 -0
- package/dist/engine/invites.js +158 -0
- package/dist/engine/invites.js.map +1 -0
- package/dist/engine/members.d.ts +59 -0
- package/dist/engine/members.d.ts.map +1 -0
- package/dist/engine/members.js +124 -0
- package/dist/engine/members.js.map +1 -0
- package/dist/engine/membership-rules.d.ts +25 -0
- package/dist/engine/membership-rules.d.ts.map +1 -0
- package/dist/engine/membership-rules.js +44 -0
- package/dist/engine/membership-rules.js.map +1 -0
- package/dist/engine/og-render.d.ts +40 -0
- package/dist/engine/og-render.d.ts.map +1 -0
- package/dist/engine/og-render.js +26 -0
- package/dist/engine/og-render.js.map +1 -0
- package/dist/engine/publish-guard.d.ts +58 -0
- package/dist/engine/publish-guard.d.ts.map +1 -0
- package/dist/engine/publish-guard.js +80 -0
- package/dist/engine/publish-guard.js.map +1 -0
- package/dist/engine/publisher.d.ts +171 -0
- package/dist/engine/publisher.d.ts.map +1 -0
- package/dist/engine/publisher.js +597 -0
- package/dist/engine/publisher.js.map +1 -0
- package/dist/engine/revisions.d.ts +39 -0
- package/dist/engine/revisions.d.ts.map +1 -0
- package/dist/engine/revisions.js +203 -0
- package/dist/engine/revisions.js.map +1 -0
- package/dist/engine/sanitize.d.ts +52 -0
- package/dist/engine/sanitize.d.ts.map +1 -0
- package/dist/engine/sanitize.js +155 -0
- package/dist/engine/sanitize.js.map +1 -0
- package/dist/engine/seed-membership.d.ts +29 -0
- package/dist/engine/seed-membership.d.ts.map +1 -0
- package/dist/engine/seed-membership.js +65 -0
- package/dist/engine/seed-membership.js.map +1 -0
- package/dist/engine/seo.d.ts +20 -0
- package/dist/engine/seo.d.ts.map +1 -0
- package/dist/engine/seo.js +50 -0
- package/dist/engine/seo.js.map +1 -0
- package/dist/engine/slug-redirects.d.ts +8 -0
- package/dist/engine/slug-redirects.d.ts.map +1 -0
- package/dist/engine/slug-redirects.js +26 -0
- package/dist/engine/slug-redirects.js.map +1 -0
- package/dist/engine/slug.d.ts +6 -0
- package/dist/engine/slug.d.ts.map +1 -0
- package/dist/engine/slug.js +28 -0
- package/dist/engine/slug.js.map +1 -0
- package/dist/engine/soft-delete.d.ts +8 -0
- package/dist/engine/soft-delete.d.ts.map +1 -0
- package/dist/engine/soft-delete.js +28 -0
- package/dist/engine/soft-delete.js.map +1 -0
- package/dist/engine/tags.d.ts +14 -0
- package/dist/engine/tags.d.ts.map +1 -0
- package/dist/engine/tags.js +79 -0
- package/dist/engine/tags.js.map +1 -0
- package/dist/engine/topics.d.ts +10 -0
- package/dist/engine/topics.d.ts.map +1 -0
- package/dist/engine/topics.js +140 -0
- package/dist/engine/topics.js.map +1 -0
- package/dist/engine/url-guard.d.ts +12 -0
- package/dist/engine/url-guard.d.ts.map +1 -0
- package/dist/engine/url-guard.js +129 -0
- package/dist/engine/url-guard.js.map +1 -0
- package/dist/engine/validator/checks/bare-url-not-autolinked.d.ts +20 -0
- package/dist/engine/validator/checks/bare-url-not-autolinked.d.ts.map +1 -0
- package/dist/engine/validator/checks/bare-url-not-autolinked.js +54 -0
- package/dist/engine/validator/checks/bare-url-not-autolinked.js.map +1 -0
- package/dist/engine/validator/checks/broken-footnote-label.d.ts +16 -0
- package/dist/engine/validator/checks/broken-footnote-label.d.ts.map +1 -0
- package/dist/engine/validator/checks/broken-footnote-label.js +17 -0
- package/dist/engine/validator/checks/broken-footnote-label.js.map +1 -0
- package/dist/engine/validator/checks/double-encoded-entities.d.ts +18 -0
- package/dist/engine/validator/checks/double-encoded-entities.d.ts.map +1 -0
- package/dist/engine/validator/checks/double-encoded-entities.js +23 -0
- package/dist/engine/validator/checks/double-encoded-entities.js.map +1 -0
- package/dist/engine/validator/checks/empty-alt-text.d.ts +14 -0
- package/dist/engine/validator/checks/empty-alt-text.d.ts.map +1 -0
- package/dist/engine/validator/checks/empty-alt-text.js +23 -0
- package/dist/engine/validator/checks/empty-alt-text.js.map +1 -0
- package/dist/engine/validator/checks/heading-hierarchy-skip.d.ts +11 -0
- package/dist/engine/validator/checks/heading-hierarchy-skip.d.ts.map +1 -0
- package/dist/engine/validator/checks/heading-hierarchy-skip.js +20 -0
- package/dist/engine/validator/checks/heading-hierarchy-skip.js.map +1 -0
- package/dist/engine/validator/checks/html-comment-leak.d.ts +20 -0
- package/dist/engine/validator/checks/html-comment-leak.d.ts.map +1 -0
- package/dist/engine/validator/checks/html-comment-leak.js +30 -0
- package/dist/engine/validator/checks/html-comment-leak.js.map +1 -0
- package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.d.ts +12 -0
- package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.d.ts.map +1 -0
- package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.js +17 -0
- package/dist/engine/validator/checks/iframe-missing-dims-and-wrapper.js.map +1 -0
- package/dist/engine/validator/checks/invisible-control-chars.d.ts +24 -0
- package/dist/engine/validator/checks/invisible-control-chars.d.ts.map +1 -0
- package/dist/engine/validator/checks/invisible-control-chars.js +30 -0
- package/dist/engine/validator/checks/invisible-control-chars.js.map +1 -0
- package/dist/engine/validator/checks/paywall-marker-leak.d.ts +17 -0
- package/dist/engine/validator/checks/paywall-marker-leak.d.ts.map +1 -0
- package/dist/engine/validator/checks/paywall-marker-leak.js +22 -0
- package/dist/engine/validator/checks/paywall-marker-leak.js.map +1 -0
- package/dist/engine/validator/checks/raw-block-html.d.ts +28 -0
- package/dist/engine/validator/checks/raw-block-html.d.ts.map +1 -0
- package/dist/engine/validator/checks/raw-block-html.js +38 -0
- package/dist/engine/validator/checks/raw-block-html.js.map +1 -0
- package/dist/engine/validator/checks/stale-body-html.d.ts +28 -0
- package/dist/engine/validator/checks/stale-body-html.d.ts.map +1 -0
- package/dist/engine/validator/checks/stale-body-html.js +15 -0
- package/dist/engine/validator/checks/stale-body-html.js.map +1 -0
- package/dist/engine/validator/checks/unresolved-footnote-anchor.d.ts +11 -0
- package/dist/engine/validator/checks/unresolved-footnote-anchor.d.ts.map +1 -0
- package/dist/engine/validator/checks/unresolved-footnote-anchor.js +48 -0
- package/dist/engine/validator/checks/unresolved-footnote-anchor.js.map +1 -0
- package/dist/engine/validator/checks/word-gdocs-paste-artifacts.d.ts +23 -0
- package/dist/engine/validator/checks/word-gdocs-paste-artifacts.d.ts.map +1 -0
- package/dist/engine/validator/checks/word-gdocs-paste-artifacts.js +47 -0
- package/dist/engine/validator/checks/word-gdocs-paste-artifacts.js.map +1 -0
- package/dist/engine/validator/index.d.ts +75 -0
- package/dist/engine/validator/index.d.ts.map +1 -0
- package/dist/engine/validator/index.js +313 -0
- package/dist/engine/validator/index.js.map +1 -0
- package/dist/engine/validator/scan.d.ts +28 -0
- package/dist/engine/validator/scan.d.ts.map +1 -0
- package/dist/engine/validator/scan.js +97 -0
- package/dist/engine/validator/scan.js.map +1 -0
- package/dist/engine/validator/types.d.ts +50 -0
- package/dist/engine/validator/types.d.ts.map +1 -0
- package/dist/engine/validator/types.js +51 -0
- package/dist/engine/validator/types.js.map +1 -0
- package/dist/engine/webhook-signer.d.ts +39 -0
- package/dist/engine/webhook-signer.d.ts.map +1 -0
- package/dist/engine/webhook-signer.js +117 -0
- package/dist/engine/webhook-signer.js.map +1 -0
- package/dist/engine/webhooks.d.ts +75 -0
- package/dist/engine/webhooks.d.ts.map +1 -0
- package/dist/engine/webhooks.js +139 -0
- package/dist/engine/webhooks.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/integration/index.d.ts +6 -0
- package/dist/integration/index.d.ts.map +1 -0
- package/dist/integration/index.js +294 -0
- package/dist/integration/index.js.map +1 -0
- package/dist/integration/options.d.ts +105 -0
- package/dist/integration/options.d.ts.map +1 -0
- package/dist/integration/options.js +25 -0
- package/dist/integration/options.js.map +1 -0
- package/dist/integration/vite-plugin.d.ts +4 -0
- package/dist/integration/vite-plugin.d.ts.map +1 -0
- package/dist/integration/vite-plugin.js +37 -0
- package/dist/integration/vite-plugin.js.map +1 -0
- package/dist/providers/index.d.ts +3 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +3 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/null.d.ts +9 -0
- package/dist/providers/null.d.ts.map +1 -0
- package/dist/providers/null.js +144 -0
- package/dist/providers/null.js.map +1 -0
- package/dist/providers/types.d.ts +277 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/routes/ai.d.ts +25 -0
- package/dist/routes/ai.d.ts.map +1 -0
- package/dist/routes/ai.js +381 -0
- package/dist/routes/ai.js.map +1 -0
- package/dist/routes/analytics.d.ts +15 -0
- package/dist/routes/analytics.d.ts.map +1 -0
- package/dist/routes/analytics.js +61 -0
- package/dist/routes/analytics.js.map +1 -0
- package/dist/routes/api-keys.d.ts +13 -0
- package/dist/routes/api-keys.d.ts.map +1 -0
- package/dist/routes/api-keys.js +109 -0
- package/dist/routes/api-keys.js.map +1 -0
- package/dist/routes/authors.d.ts +19 -0
- package/dist/routes/authors.d.ts.map +1 -0
- package/dist/routes/authors.js +202 -0
- package/dist/routes/authors.js.map +1 -0
- package/dist/routes/authz-matrix.d.ts +78 -0
- package/dist/routes/authz-matrix.d.ts.map +1 -0
- package/dist/routes/authz-matrix.js +170 -0
- package/dist/routes/authz-matrix.js.map +1 -0
- package/dist/routes/calendar.d.ts +19 -0
- package/dist/routes/calendar.d.ts.map +1 -0
- package/dist/routes/calendar.js +89 -0
- package/dist/routes/calendar.js.map +1 -0
- package/dist/routes/config.d.ts +70 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +23 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/content-insights.d.ts +18 -0
- package/dist/routes/content-insights.d.ts.map +1 -0
- package/dist/routes/content-insights.js +137 -0
- package/dist/routes/content-insights.js.map +1 -0
- package/dist/routes/content.d.ts +145 -0
- package/dist/routes/content.d.ts.map +1 -0
- package/dist/routes/content.js +1374 -0
- package/dist/routes/content.js.map +1 -0
- package/dist/routes/context.d.ts +104 -0
- package/dist/routes/context.d.ts.map +1 -0
- package/dist/routes/context.js +26 -0
- package/dist/routes/context.js.map +1 -0
- package/dist/routes/cron.d.ts +8 -0
- package/dist/routes/cron.d.ts.map +1 -0
- package/dist/routes/cron.js +20 -0
- package/dist/routes/cron.js.map +1 -0
- package/dist/routes/dashboard.d.ts +12 -0
- package/dist/routes/dashboard.d.ts.map +1 -0
- package/dist/routes/dashboard.js +113 -0
- package/dist/routes/dashboard.js.map +1 -0
- package/dist/routes/imports.d.ts +10 -0
- package/dist/routes/imports.d.ts.map +1 -0
- package/dist/routes/imports.js +149 -0
- package/dist/routes/imports.js.map +1 -0
- package/dist/routes/index.d.ts +75 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +141 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/media-lib.d.ts +75 -0
- package/dist/routes/media-lib.d.ts.map +1 -0
- package/dist/routes/media-lib.js +305 -0
- package/dist/routes/media-lib.js.map +1 -0
- package/dist/routes/media.d.ts +32 -0
- package/dist/routes/media.d.ts.map +1 -0
- package/dist/routes/media.js +756 -0
- package/dist/routes/media.js.map +1 -0
- package/dist/routes/preview.d.ts +19 -0
- package/dist/routes/preview.d.ts.map +1 -0
- package/dist/routes/preview.js +150 -0
- package/dist/routes/preview.js.map +1 -0
- package/dist/routes/rbac-invites.d.ts +31 -0
- package/dist/routes/rbac-invites.d.ts.map +1 -0
- package/dist/routes/rbac-invites.js +174 -0
- package/dist/routes/rbac-invites.js.map +1 -0
- package/dist/routes/rbac.d.ts +12 -0
- package/dist/routes/rbac.d.ts.map +1 -0
- package/dist/routes/rbac.js +126 -0
- package/dist/routes/rbac.js.map +1 -0
- package/dist/routes/shell.d.ts +22 -0
- package/dist/routes/shell.d.ts.map +1 -0
- package/dist/routes/shell.js +123 -0
- package/dist/routes/shell.js.map +1 -0
- package/dist/routes/subscriptions.d.ts +21 -0
- package/dist/routes/subscriptions.d.ts.map +1 -0
- package/dist/routes/subscriptions.js +127 -0
- package/dist/routes/subscriptions.js.map +1 -0
- package/dist/routes/tags.d.ts +23 -0
- package/dist/routes/tags.d.ts.map +1 -0
- package/dist/routes/tags.js +68 -0
- package/dist/routes/tags.js.map +1 -0
- package/dist/routes/topics.d.ts +12 -0
- package/dist/routes/topics.d.ts.map +1 -0
- package/dist/routes/topics.js +49 -0
- package/dist/routes/topics.js.map +1 -0
- package/dist/routes/webhooks.d.ts +31 -0
- package/dist/routes/webhooks.d.ts.map +1 -0
- package/dist/routes/webhooks.js +173 -0
- package/dist/routes/webhooks.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +6 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/insights-ingest.d.ts +959 -0
- package/dist/schema/insights-ingest.d.ts.map +1 -0
- package/dist/schema/insights-ingest.js +112 -0
- package/dist/schema/insights-ingest.js.map +1 -0
- package/dist/schema/migrations.d.ts +63 -0
- package/dist/schema/migrations.d.ts.map +1 -0
- package/dist/schema/migrations.js +589 -0
- package/dist/schema/migrations.js.map +1 -0
- package/dist/schema/tables.d.ts +11 -0
- package/dist/schema/tables.d.ts.map +1 -0
- package/dist/schema/tables.js +56 -0
- package/dist/schema/tables.js.map +1 -0
- package/dist/schema/types.d.ts +476 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +37 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/ui/api/_authz.d.ts +6 -0
- package/dist/ui/api/_authz.d.ts.map +1 -0
- package/dist/ui/api/_authz.js +74 -0
- package/dist/ui/api/_authz.js.map +1 -0
- package/dist/ui/api/_content-config.d.ts +22 -0
- package/dist/ui/api/_content-config.d.ts.map +1 -0
- package/dist/ui/api/_content-config.js +50 -0
- package/dist/ui/api/_content-config.js.map +1 -0
- package/dist/ui/api/activity.d.ts +3 -0
- package/dist/ui/api/activity.d.ts.map +1 -0
- package/dist/ui/api/activity.js +28 -0
- package/dist/ui/api/activity.js.map +1 -0
- package/dist/ui/api/analytics.d.ts +3 -0
- package/dist/ui/api/analytics.d.ts.map +1 -0
- package/dist/ui/api/analytics.js +36 -0
- package/dist/ui/api/analytics.js.map +1 -0
- package/dist/ui/api/authors/[id].d.ts +4 -0
- package/dist/ui/api/authors/[id].d.ts.map +1 -0
- package/dist/ui/api/authors/[id].js +17 -0
- package/dist/ui/api/authors/[id].js.map +1 -0
- package/dist/ui/api/authors.d.ts +4 -0
- package/dist/ui/api/authors.d.ts.map +1 -0
- package/dist/ui/api/authors.js +12 -0
- package/dist/ui/api/authors.js.map +1 -0
- package/dist/ui/api/calendar.d.ts +3 -0
- package/dist/ui/api/calendar.d.ts.map +1 -0
- package/dist/ui/api/calendar.js +16 -0
- package/dist/ui/api/calendar.js.map +1 -0
- package/dist/ui/api/content/[id]/ai/headlines.d.ts +3 -0
- package/dist/ui/api/content/[id]/ai/headlines.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/ai/headlines.js +7 -0
- package/dist/ui/api/content/[id]/ai/headlines.js.map +1 -0
- package/dist/ui/api/content/[id]/ai/meta-description.d.ts +3 -0
- package/dist/ui/api/content/[id]/ai/meta-description.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/ai/meta-description.js +6 -0
- package/dist/ui/api/content/[id]/ai/meta-description.js.map +1 -0
- package/dist/ui/api/content/[id]/ai/og-image.d.ts +3 -0
- package/dist/ui/api/content/[id]/ai/og-image.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/ai/og-image.js +7 -0
- package/dist/ui/api/content/[id]/ai/og-image.js.map +1 -0
- package/dist/ui/api/content/[id]/ai/proofread.d.ts +3 -0
- package/dist/ui/api/content/[id]/ai/proofread.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/ai/proofread.js +7 -0
- package/dist/ui/api/content/[id]/ai/proofread.js.map +1 -0
- package/dist/ui/api/content/[id]/ai/takeaways.d.ts +3 -0
- package/dist/ui/api/content/[id]/ai/takeaways.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/ai/takeaways.js +6 -0
- package/dist/ui/api/content/[id]/ai/takeaways.js.map +1 -0
- package/dist/ui/api/content/[id]/contributors.d.ts +4 -0
- package/dist/ui/api/content/[id]/contributors.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/contributors.js +8 -0
- package/dist/ui/api/content/[id]/contributors.js.map +1 -0
- package/dist/ui/api/content/[id]/preview-token.d.ts +3 -0
- package/dist/ui/api/content/[id]/preview-token.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/preview-token.js +16 -0
- package/dist/ui/api/content/[id]/preview-token.js.map +1 -0
- package/dist/ui/api/content/[id]/revisions/[rev]/restore.d.ts +3 -0
- package/dist/ui/api/content/[id]/revisions/[rev]/restore.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/revisions/[rev]/restore.js +7 -0
- package/dist/ui/api/content/[id]/revisions/[rev]/restore.js.map +1 -0
- package/dist/ui/api/content/[id]/revisions/[rev].d.ts +3 -0
- package/dist/ui/api/content/[id]/revisions/[rev].d.ts.map +1 -0
- package/dist/ui/api/content/[id]/revisions/[rev].js +6 -0
- package/dist/ui/api/content/[id]/revisions/[rev].js.map +1 -0
- package/dist/ui/api/content/[id]/revisions.d.ts +3 -0
- package/dist/ui/api/content/[id]/revisions.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/revisions.js +6 -0
- package/dist/ui/api/content/[id]/revisions.js.map +1 -0
- package/dist/ui/api/content/[id]/seo-score.d.ts +3 -0
- package/dist/ui/api/content/[id]/seo-score.d.ts.map +1 -0
- package/dist/ui/api/content/[id]/seo-score.js +7 -0
- package/dist/ui/api/content/[id]/seo-score.js.map +1 -0
- package/dist/ui/api/content/[id].d.ts +5 -0
- package/dist/ui/api/content/[id].d.ts.map +1 -0
- package/dist/ui/api/content/[id].js +17 -0
- package/dist/ui/api/content/[id].js.map +1 -0
- package/dist/ui/api/content/bulk.d.ts +3 -0
- package/dist/ui/api/content/bulk.d.ts.map +1 -0
- package/dist/ui/api/content/bulk.js +7 -0
- package/dist/ui/api/content/bulk.js.map +1 -0
- package/dist/ui/api/content/counts.d.ts +3 -0
- package/dist/ui/api/content/counts.d.ts.map +1 -0
- package/dist/ui/api/content/counts.js +8 -0
- package/dist/ui/api/content/counts.js.map +1 -0
- package/dist/ui/api/content/foundry-callback.d.ts +3 -0
- package/dist/ui/api/content/foundry-callback.d.ts.map +1 -0
- package/dist/ui/api/content/foundry-callback.js +8 -0
- package/dist/ui/api/content/foundry-callback.js.map +1 -0
- package/dist/ui/api/content/import/confirm.d.ts +3 -0
- package/dist/ui/api/content/import/confirm.d.ts.map +1 -0
- package/dist/ui/api/content/import/confirm.js +11 -0
- package/dist/ui/api/content/import/confirm.js.map +1 -0
- package/dist/ui/api/content/import/parse.d.ts +3 -0
- package/dist/ui/api/content/import/parse.d.ts.map +1 -0
- package/dist/ui/api/content/import/parse.js +11 -0
- package/dist/ui/api/content/import/parse.js.map +1 -0
- package/dist/ui/api/content/insights-ingest.d.ts +3 -0
- package/dist/ui/api/content/insights-ingest.d.ts.map +1 -0
- package/dist/ui/api/content/insights-ingest.js +15 -0
- package/dist/ui/api/content/insights-ingest.js.map +1 -0
- package/dist/ui/api/content-insights/dismiss.d.ts +3 -0
- package/dist/ui/api/content-insights/dismiss.d.ts.map +1 -0
- package/dist/ui/api/content-insights/dismiss.js +16 -0
- package/dist/ui/api/content-insights/dismiss.js.map +1 -0
- package/dist/ui/api/content-insights/index.d.ts +3 -0
- package/dist/ui/api/content-insights/index.d.ts.map +1 -0
- package/dist/ui/api/content-insights/index.js +12 -0
- package/dist/ui/api/content-insights/index.js.map +1 -0
- package/dist/ui/api/content-insights/undismiss.d.ts +3 -0
- package/dist/ui/api/content-insights/undismiss.d.ts.map +1 -0
- package/dist/ui/api/content-insights/undismiss.js +16 -0
- package/dist/ui/api/content-insights/undismiss.js.map +1 -0
- package/dist/ui/api/content.d.ts +4 -0
- package/dist/ui/api/content.d.ts.map +1 -0
- package/dist/ui/api/content.js +16 -0
- package/dist/ui/api/content.js.map +1 -0
- package/dist/ui/api/dashboard.d.ts +3 -0
- package/dist/ui/api/dashboard.d.ts.map +1 -0
- package/dist/ui/api/dashboard.js +22 -0
- package/dist/ui/api/dashboard.js.map +1 -0
- package/dist/ui/api/me.d.ts +3 -0
- package/dist/ui/api/me.d.ts.map +1 -0
- package/dist/ui/api/me.js +18 -0
- package/dist/ui/api/me.js.map +1 -0
- package/dist/ui/api/media/[id].d.ts +3 -0
- package/dist/ui/api/media/[id].d.ts.map +1 -0
- package/dist/ui/api/media/[id].js +17 -0
- package/dist/ui/api/media/[id].js.map +1 -0
- package/dist/ui/api/media/images.d.ts +3 -0
- package/dist/ui/api/media/images.d.ts.map +1 -0
- package/dist/ui/api/media/images.js +6 -0
- package/dist/ui/api/media/images.js.map +1 -0
- package/dist/ui/api/media/library/[id].d.ts +3 -0
- package/dist/ui/api/media/library/[id].d.ts.map +1 -0
- package/dist/ui/api/media/library/[id].js +6 -0
- package/dist/ui/api/media/library/[id].js.map +1 -0
- package/dist/ui/api/media/library.d.ts +3 -0
- package/dist/ui/api/media/library.d.ts.map +1 -0
- package/dist/ui/api/media/library.js +17 -0
- package/dist/ui/api/media/library.js.map +1 -0
- package/dist/ui/api/media/podcast/abort.d.ts +3 -0
- package/dist/ui/api/media/podcast/abort.d.ts.map +1 -0
- package/dist/ui/api/media/podcast/abort.js +4 -0
- package/dist/ui/api/media/podcast/abort.js.map +1 -0
- package/dist/ui/api/media/podcast/complete.d.ts +3 -0
- package/dist/ui/api/media/podcast/complete.d.ts.map +1 -0
- package/dist/ui/api/media/podcast/complete.js +4 -0
- package/dist/ui/api/media/podcast/complete.js.map +1 -0
- package/dist/ui/api/media/podcast/init.d.ts +3 -0
- package/dist/ui/api/media/podcast/init.d.ts.map +1 -0
- package/dist/ui/api/media/podcast/init.js +4 -0
- package/dist/ui/api/media/podcast/init.js.map +1 -0
- package/dist/ui/api/media/podcast/part.d.ts +3 -0
- package/dist/ui/api/media/podcast/part.d.ts.map +1 -0
- package/dist/ui/api/media/podcast/part.js +4 -0
- package/dist/ui/api/media/podcast/part.js.map +1 -0
- package/dist/ui/api/media/podcast.d.ts +3 -0
- package/dist/ui/api/media/podcast.d.ts.map +1 -0
- package/dist/ui/api/media/podcast.js +6 -0
- package/dist/ui/api/media/podcast.js.map +1 -0
- package/dist/ui/api/media/videos/abort.d.ts +3 -0
- package/dist/ui/api/media/videos/abort.d.ts.map +1 -0
- package/dist/ui/api/media/videos/abort.js +6 -0
- package/dist/ui/api/media/videos/abort.js.map +1 -0
- package/dist/ui/api/media/videos/complete.d.ts +3 -0
- package/dist/ui/api/media/videos/complete.d.ts.map +1 -0
- package/dist/ui/api/media/videos/complete.js +6 -0
- package/dist/ui/api/media/videos/complete.js.map +1 -0
- package/dist/ui/api/media/videos/init.d.ts +3 -0
- package/dist/ui/api/media/videos/init.d.ts.map +1 -0
- package/dist/ui/api/media/videos/init.js +6 -0
- package/dist/ui/api/media/videos/init.js.map +1 -0
- package/dist/ui/api/media/videos/part.d.ts +3 -0
- package/dist/ui/api/media/videos/part.d.ts.map +1 -0
- package/dist/ui/api/media/videos/part.js +6 -0
- package/dist/ui/api/media/videos/part.js.map +1 -0
- package/dist/ui/api/notifications.d.ts +4 -0
- package/dist/ui/api/notifications.d.ts.map +1 -0
- package/dist/ui/api/notifications.js +20 -0
- package/dist/ui/api/notifications.js.map +1 -0
- package/dist/ui/api/search.d.ts +3 -0
- package/dist/ui/api/search.d.ts.map +1 -0
- package/dist/ui/api/search.js +18 -0
- package/dist/ui/api/search.js.map +1 -0
- package/dist/ui/api/settings/api-keys/[id].d.ts +3 -0
- package/dist/ui/api/settings/api-keys/[id].d.ts.map +1 -0
- package/dist/ui/api/settings/api-keys/[id].js +22 -0
- package/dist/ui/api/settings/api-keys/[id].js.map +1 -0
- package/dist/ui/api/settings/api-keys.d.ts +4 -0
- package/dist/ui/api/settings/api-keys.d.ts.map +1 -0
- package/dist/ui/api/settings/api-keys.js +19 -0
- package/dist/ui/api/settings/api-keys.js.map +1 -0
- package/dist/ui/api/settings/domains.d.ts +3 -0
- package/dist/ui/api/settings/domains.d.ts.map +1 -0
- package/dist/ui/api/settings/domains.js +32 -0
- package/dist/ui/api/settings/domains.js.map +1 -0
- package/dist/ui/api/settings/integrations.d.ts +3 -0
- package/dist/ui/api/settings/integrations.d.ts.map +1 -0
- package/dist/ui/api/settings/integrations.js +32 -0
- package/dist/ui/api/settings/integrations.js.map +1 -0
- package/dist/ui/api/settings/members/[userId].d.ts +4 -0
- package/dist/ui/api/settings/members/[userId].d.ts.map +1 -0
- package/dist/ui/api/settings/members/[userId].js +26 -0
- package/dist/ui/api/settings/members/[userId].js.map +1 -0
- package/dist/ui/api/settings/members/invite.d.ts +3 -0
- package/dist/ui/api/settings/members/invite.d.ts.map +1 -0
- package/dist/ui/api/settings/members/invite.js +21 -0
- package/dist/ui/api/settings/members/invite.js.map +1 -0
- package/dist/ui/api/settings/members.d.ts +3 -0
- package/dist/ui/api/settings/members.d.ts.map +1 -0
- package/dist/ui/api/settings/members.js +17 -0
- package/dist/ui/api/settings/members.js.map +1 -0
- package/dist/ui/api/settings/webhooks/[id]/test.d.ts +3 -0
- package/dist/ui/api/settings/webhooks/[id]/test.d.ts.map +1 -0
- package/dist/ui/api/settings/webhooks/[id]/test.js +24 -0
- package/dist/ui/api/settings/webhooks/[id]/test.js.map +1 -0
- package/dist/ui/api/settings/webhooks/[id].d.ts +3 -0
- package/dist/ui/api/settings/webhooks/[id].d.ts.map +1 -0
- package/dist/ui/api/settings/webhooks/[id].js +23 -0
- package/dist/ui/api/settings/webhooks/[id].js.map +1 -0
- package/dist/ui/api/settings/webhooks.d.ts +4 -0
- package/dist/ui/api/settings/webhooks.d.ts.map +1 -0
- package/dist/ui/api/settings/webhooks.js +21 -0
- package/dist/ui/api/settings/webhooks.js.map +1 -0
- package/dist/ui/api/subscriptions.d.ts +4 -0
- package/dist/ui/api/subscriptions.d.ts.map +1 -0
- package/dist/ui/api/subscriptions.js +47 -0
- package/dist/ui/api/subscriptions.js.map +1 -0
- package/dist/ui/api/tags/[id].d.ts +4 -0
- package/dist/ui/api/tags/[id].d.ts.map +1 -0
- package/dist/ui/api/tags/[id].js +18 -0
- package/dist/ui/api/tags/[id].js.map +1 -0
- package/dist/ui/api/tags/index.d.ts +4 -0
- package/dist/ui/api/tags/index.d.ts.map +1 -0
- package/dist/ui/api/tags/index.js +13 -0
- package/dist/ui/api/tags/index.js.map +1 -0
- package/dist/ui/api/topics/[id].d.ts +3 -0
- package/dist/ui/api/topics/[id].d.ts.map +1 -0
- package/dist/ui/api/topics/[id].js +15 -0
- package/dist/ui/api/topics/[id].js.map +1 -0
- package/dist/ui/api/topics/index.d.ts +4 -0
- package/dist/ui/api/topics/index.d.ts.map +1 -0
- package/dist/ui/api/topics/index.js +12 -0
- package/dist/ui/api/topics/index.js.map +1 -0
- package/dist/ui/api/workspace-settings.d.ts +4 -0
- package/dist/ui/api/workspace-settings.d.ts.map +1 -0
- package/dist/ui/api/workspace-settings.js +20 -0
- package/dist/ui/api/workspace-settings.js.map +1 -0
- package/dist/ui/client/boot-state.d.ts +15 -0
- package/dist/ui/client/boot-state.d.ts.map +1 -0
- package/dist/ui/client/boot-state.js +36 -0
- package/dist/ui/client/boot-state.js.map +1 -0
- package/dist/ui/client/mount.d.ts +3 -0
- package/dist/ui/client/mount.d.ts.map +1 -0
- package/dist/ui/client/mount.js +37 -0
- package/dist/ui/client/mount.js.map +1 -0
- package/dist/ui/commands.d.ts +23 -0
- package/dist/ui/commands.d.ts.map +1 -0
- package/dist/ui/commands.js +48 -0
- package/dist/ui/commands.js.map +1 -0
- package/dist/ui/components/CmsApp.d.ts +16 -0
- package/dist/ui/components/CmsApp.d.ts.map +1 -0
- package/dist/ui/components/CmsApp.js +74 -0
- package/dist/ui/components/CmsApp.js.map +1 -0
- package/dist/ui/components/CommandPalette.d.ts +7 -0
- package/dist/ui/components/CommandPalette.d.ts.map +1 -0
- package/dist/ui/components/CommandPalette.js +61 -0
- package/dist/ui/components/CommandPalette.js.map +1 -0
- package/dist/ui/components/NoAccessScreen.d.ts +2 -0
- package/dist/ui/components/NoAccessScreen.d.ts.map +1 -0
- package/dist/ui/components/NoAccessScreen.js +42 -0
- package/dist/ui/components/NoAccessScreen.js.map +1 -0
- package/dist/ui/components/ShareModal.d.ts +27 -0
- package/dist/ui/components/ShareModal.d.ts.map +1 -0
- package/dist/ui/components/ShareModal.js +208 -0
- package/dist/ui/components/ShareModal.js.map +1 -0
- package/dist/ui/components/SharePickers.d.ts +39 -0
- package/dist/ui/components/SharePickers.d.ts.map +1 -0
- package/dist/ui/components/SharePickers.js +352 -0
- package/dist/ui/components/SharePickers.js.map +1 -0
- package/dist/ui/components/ShareStatsPanel.d.ts +22 -0
- package/dist/ui/components/ShareStatsPanel.d.ts.map +1 -0
- package/dist/ui/components/ShareStatsPanel.js +317 -0
- package/dist/ui/components/ShareStatsPanel.js.map +1 -0
- package/dist/ui/components/Sidebar.d.ts +7 -0
- package/dist/ui/components/Sidebar.d.ts.map +1 -0
- package/dist/ui/components/Sidebar.js +20 -0
- package/dist/ui/components/Sidebar.js.map +1 -0
- package/dist/ui/components/SiteSwitcher.d.ts +4 -0
- package/dist/ui/components/SiteSwitcher.d.ts.map +1 -0
- package/dist/ui/components/SiteSwitcher.js +35 -0
- package/dist/ui/components/SiteSwitcher.js.map +1 -0
- package/dist/ui/components/Topbar.d.ts +9 -0
- package/dist/ui/components/Topbar.d.ts.map +1 -0
- package/dist/ui/components/Topbar.js +20 -0
- package/dist/ui/components/Topbar.js.map +1 -0
- package/dist/ui/editor/AiAssistPanel.d.ts +8 -0
- package/dist/ui/editor/AiAssistPanel.d.ts.map +1 -0
- package/dist/ui/editor/AiAssistPanel.js +221 -0
- package/dist/ui/editor/AiAssistPanel.js.map +1 -0
- package/dist/ui/editor/ContentForm.d.ts +46 -0
- package/dist/ui/editor/ContentForm.d.ts.map +1 -0
- package/dist/ui/editor/ContentForm.js +821 -0
- package/dist/ui/editor/ContentForm.js.map +1 -0
- package/dist/ui/editor/Rte.d.ts +16 -0
- package/dist/ui/editor/Rte.d.ts.map +1 -0
- package/dist/ui/editor/Rte.js +272 -0
- package/dist/ui/editor/Rte.js.map +1 -0
- package/dist/ui/editor/ai-assist.d.ts +43 -0
- package/dist/ui/editor/ai-assist.d.ts.map +1 -0
- package/dist/ui/editor/ai-assist.js +114 -0
- package/dist/ui/editor/ai-assist.js.map +1 -0
- package/dist/ui/editor/autosave.d.ts +18 -0
- package/dist/ui/editor/autosave.d.ts.map +1 -0
- package/dist/ui/editor/autosave.js +23 -0
- package/dist/ui/editor/autosave.js.map +1 -0
- package/dist/ui/editor/content-payload.d.ts +19 -0
- package/dist/ui/editor/content-payload.d.ts.map +1 -0
- package/dist/ui/editor/content-payload.js +97 -0
- package/dist/ui/editor/content-payload.js.map +1 -0
- package/dist/ui/editor/editor-media-upload.d.ts +6 -0
- package/dist/ui/editor/editor-media-upload.d.ts.map +1 -0
- package/dist/ui/editor/editor-media-upload.js +20 -0
- package/dist/ui/editor/editor-media-upload.js.map +1 -0
- package/dist/ui/editor/serialize.d.ts +6 -0
- package/dist/ui/editor/serialize.d.ts.map +1 -0
- package/dist/ui/editor/serialize.js +479 -0
- package/dist/ui/editor/serialize.js.map +1 -0
- package/dist/ui/editor/tweet-embed.d.ts +4 -0
- package/dist/ui/editor/tweet-embed.d.ts.map +1 -0
- package/dist/ui/editor/tweet-embed.js +49 -0
- package/dist/ui/editor/tweet-embed.js.map +1 -0
- package/dist/ui/hash-router.d.ts +5 -0
- package/dist/ui/hash-router.d.ts.map +1 -0
- package/dist/ui/hash-router.js +25 -0
- package/dist/ui/hash-router.js.map +1 -0
- package/dist/ui/icons.d.ts +32 -0
- package/dist/ui/icons.d.ts.map +1 -0
- package/dist/ui/icons.js +86 -0
- package/dist/ui/icons.js.map +1 -0
- package/dist/ui/inspector/Field.d.ts +12 -0
- package/dist/ui/inspector/Field.d.ts.map +1 -0
- package/dist/ui/inspector/Field.js +8 -0
- package/dist/ui/inspector/Field.js.map +1 -0
- package/dist/ui/inspector/FoundryTab.d.ts +9 -0
- package/dist/ui/inspector/FoundryTab.d.ts.map +1 -0
- package/dist/ui/inspector/FoundryTab.js +362 -0
- package/dist/ui/inspector/FoundryTab.js.map +1 -0
- package/dist/ui/inspector/HistoryTab.d.ts +7 -0
- package/dist/ui/inspector/HistoryTab.d.ts.map +1 -0
- package/dist/ui/inspector/HistoryTab.js +289 -0
- package/dist/ui/inspector/HistoryTab.js.map +1 -0
- package/dist/ui/inspector/Inspector.d.ts +13 -0
- package/dist/ui/inspector/Inspector.d.ts.map +1 -0
- package/dist/ui/inspector/Inspector.js +163 -0
- package/dist/ui/inspector/Inspector.js.map +1 -0
- package/dist/ui/inspector/OrganizeTab.d.ts +15 -0
- package/dist/ui/inspector/OrganizeTab.d.ts.map +1 -0
- package/dist/ui/inspector/OrganizeTab.js +319 -0
- package/dist/ui/inspector/OrganizeTab.js.map +1 -0
- package/dist/ui/inspector/PublishTab.d.ts +18 -0
- package/dist/ui/inspector/PublishTab.d.ts.map +1 -0
- package/dist/ui/inspector/PublishTab.js +339 -0
- package/dist/ui/inspector/PublishTab.js.map +1 -0
- package/dist/ui/inspector/Section.d.ts +10 -0
- package/dist/ui/inspector/Section.d.ts.map +1 -0
- package/dist/ui/inspector/Section.js +40 -0
- package/dist/ui/inspector/Section.js.map +1 -0
- package/dist/ui/inspector/SeoTab.d.ts +19 -0
- package/dist/ui/inspector/SeoTab.d.ts.map +1 -0
- package/dist/ui/inspector/SeoTab.js +328 -0
- package/dist/ui/inspector/SeoTab.js.map +1 -0
- package/dist/ui/inspector/foundry-stages.d.ts +36 -0
- package/dist/ui/inspector/foundry-stages.d.ts.map +1 -0
- package/dist/ui/inspector/foundry-stages.js +101 -0
- package/dist/ui/inspector/foundry-stages.js.map +1 -0
- package/dist/ui/inspector/inspector-data.d.ts +80 -0
- package/dist/ui/inspector/inspector-data.d.ts.map +1 -0
- package/dist/ui/inspector/inspector-data.js +172 -0
- package/dist/ui/inspector/inspector-data.js.map +1 -0
- package/dist/ui/inspector/organize-data.d.ts +23 -0
- package/dist/ui/inspector/organize-data.d.ts.map +1 -0
- package/dist/ui/inspector/organize-data.js +28 -0
- package/dist/ui/inspector/organize-data.js.map +1 -0
- package/dist/ui/inspector/revision-diff.d.ts +49 -0
- package/dist/ui/inspector/revision-diff.d.ts.map +1 -0
- package/dist/ui/inspector/revision-diff.js +166 -0
- package/dist/ui/inspector/revision-diff.js.map +1 -0
- package/dist/ui/inspector/seo-helpers.d.ts +37 -0
- package/dist/ui/inspector/seo-helpers.d.ts.map +1 -0
- package/dist/ui/inspector/seo-helpers.js +37 -0
- package/dist/ui/inspector/seo-helpers.js.map +1 -0
- package/dist/ui/inspector/tab-visibility.d.ts +14 -0
- package/dist/ui/inspector/tab-visibility.d.ts.map +1 -0
- package/dist/ui/inspector/tab-visibility.js +28 -0
- package/dist/ui/inspector/tab-visibility.js.map +1 -0
- package/dist/ui/nav.d.ts +16 -0
- package/dist/ui/nav.d.ts.map +1 -0
- package/dist/ui/nav.js +33 -0
- package/dist/ui/nav.js.map +1 -0
- package/dist/ui/pages/admin.astro +32 -0
- package/dist/ui/preview/draft-page.d.ts +37 -0
- package/dist/ui/preview/draft-page.d.ts.map +1 -0
- package/dist/ui/preview/draft-page.js +212 -0
- package/dist/ui/preview/draft-page.js.map +1 -0
- package/dist/ui/preview/preview-layout.d.ts +23 -0
- package/dist/ui/preview/preview-layout.d.ts.map +1 -0
- package/dist/ui/preview/preview-layout.js +30 -0
- package/dist/ui/preview/preview-layout.js.map +1 -0
- package/dist/ui/screens/AnalyticsScreen.d.ts +2 -0
- package/dist/ui/screens/AnalyticsScreen.d.ts.map +1 -0
- package/dist/ui/screens/AnalyticsScreen.js +408 -0
- package/dist/ui/screens/AnalyticsScreen.js.map +1 -0
- package/dist/ui/screens/AuthorsScreen.d.ts +2 -0
- package/dist/ui/screens/AuthorsScreen.d.ts.map +1 -0
- package/dist/ui/screens/AuthorsScreen.js +225 -0
- package/dist/ui/screens/AuthorsScreen.js.map +1 -0
- package/dist/ui/screens/CalendarScreen.d.ts +6 -0
- package/dist/ui/screens/CalendarScreen.d.ts.map +1 -0
- package/dist/ui/screens/CalendarScreen.js +327 -0
- package/dist/ui/screens/CalendarScreen.js.map +1 -0
- package/dist/ui/screens/ContentInsightsScreen.d.ts +2 -0
- package/dist/ui/screens/ContentInsightsScreen.d.ts.map +1 -0
- package/dist/ui/screens/ContentInsightsScreen.js +129 -0
- package/dist/ui/screens/ContentInsightsScreen.js.map +1 -0
- package/dist/ui/screens/ContentRoute.d.ts +2 -0
- package/dist/ui/screens/ContentRoute.d.ts.map +1 -0
- package/dist/ui/screens/ContentRoute.js +32 -0
- package/dist/ui/screens/ContentRoute.js.map +1 -0
- package/dist/ui/screens/DashboardScreen.d.ts +6 -0
- package/dist/ui/screens/DashboardScreen.d.ts.map +1 -0
- package/dist/ui/screens/DashboardScreen.js +273 -0
- package/dist/ui/screens/DashboardScreen.js.map +1 -0
- package/dist/ui/screens/EditorScreen.d.ts +7 -0
- package/dist/ui/screens/EditorScreen.d.ts.map +1 -0
- package/dist/ui/screens/EditorScreen.js +426 -0
- package/dist/ui/screens/EditorScreen.js.map +1 -0
- package/dist/ui/screens/LibraryScreen.d.ts +6 -0
- package/dist/ui/screens/LibraryScreen.d.ts.map +1 -0
- package/dist/ui/screens/LibraryScreen.js +580 -0
- package/dist/ui/screens/LibraryScreen.js.map +1 -0
- package/dist/ui/screens/MediaScreen.d.ts +2 -0
- package/dist/ui/screens/MediaScreen.d.ts.map +1 -0
- package/dist/ui/screens/MediaScreen.js +173 -0
- package/dist/ui/screens/MediaScreen.js.map +1 -0
- package/dist/ui/screens/SettingsScreen.d.ts +4 -0
- package/dist/ui/screens/SettingsScreen.d.ts.map +1 -0
- package/dist/ui/screens/SettingsScreen.js +751 -0
- package/dist/ui/screens/SettingsScreen.js.map +1 -0
- package/dist/ui/screens/SocialShareScreen.d.ts +2 -0
- package/dist/ui/screens/SocialShareScreen.d.ts.map +1 -0
- package/dist/ui/screens/SocialShareScreen.js +224 -0
- package/dist/ui/screens/SocialShareScreen.js.map +1 -0
- package/dist/ui/screens/SubscriptionsScreen.d.ts +2 -0
- package/dist/ui/screens/SubscriptionsScreen.d.ts.map +1 -0
- package/dist/ui/screens/SubscriptionsScreen.js +441 -0
- package/dist/ui/screens/SubscriptionsScreen.js.map +1 -0
- package/dist/ui/screens/TopicsScreen.d.ts +2 -0
- package/dist/ui/screens/TopicsScreen.d.ts.map +1 -0
- package/dist/ui/screens/TopicsScreen.js +360 -0
- package/dist/ui/screens/TopicsScreen.js.map +1 -0
- package/dist/ui/screens/analytics-data.d.ts +19 -0
- package/dist/ui/screens/analytics-data.d.ts.map +1 -0
- package/dist/ui/screens/analytics-data.js +42 -0
- package/dist/ui/screens/analytics-data.js.map +1 -0
- package/dist/ui/screens/calendar-data.d.ts +45 -0
- package/dist/ui/screens/calendar-data.d.ts.map +1 -0
- package/dist/ui/screens/calendar-data.js +70 -0
- package/dist/ui/screens/calendar-data.js.map +1 -0
- package/dist/ui/screens/content-insights-data.d.ts +54 -0
- package/dist/ui/screens/content-insights-data.d.ts.map +1 -0
- package/dist/ui/screens/content-insights-data.js +82 -0
- package/dist/ui/screens/content-insights-data.js.map +1 -0
- package/dist/ui/screens/content-view.d.ts +21 -0
- package/dist/ui/screens/content-view.d.ts.map +1 -0
- package/dist/ui/screens/content-view.js +17 -0
- package/dist/ui/screens/content-view.js.map +1 -0
- package/dist/ui/screens/library-data.d.ts +76 -0
- package/dist/ui/screens/library-data.d.ts.map +1 -0
- package/dist/ui/screens/library-data.js +116 -0
- package/dist/ui/screens/library-data.js.map +1 -0
- package/dist/ui/screens/media-upload.d.ts +19 -0
- package/dist/ui/screens/media-upload.d.ts.map +1 -0
- package/dist/ui/screens/media-upload.js +187 -0
- package/dist/ui/screens/media-upload.js.map +1 -0
- package/dist/ui/screens/public-url.d.ts +24 -0
- package/dist/ui/screens/public-url.d.ts.map +1 -0
- package/dist/ui/screens/public-url.js +74 -0
- package/dist/ui/screens/public-url.js.map +1 -0
- package/dist/ui/screens/registry.d.ts +3 -0
- package/dist/ui/screens/registry.d.ts.map +1 -0
- package/dist/ui/screens/registry.js +38 -0
- package/dist/ui/screens/registry.js.map +1 -0
- package/dist/ui/screens/render-state.d.ts +105 -0
- package/dist/ui/screens/render-state.d.ts.map +1 -0
- package/dist/ui/screens/render-state.js +127 -0
- package/dist/ui/screens/render-state.js.map +1 -0
- package/dist/ui/screens/settings-data.d.ts +55 -0
- package/dist/ui/screens/settings-data.d.ts.map +1 -0
- package/dist/ui/screens/settings-data.js +89 -0
- package/dist/ui/screens/settings-data.js.map +1 -0
- package/dist/ui/screens/settings-panels-data.d.ts +58 -0
- package/dist/ui/screens/settings-panels-data.d.ts.map +1 -0
- package/dist/ui/screens/settings-panels-data.js +88 -0
- package/dist/ui/screens/settings-panels-data.js.map +1 -0
- package/dist/ui/screens/social-share-data.d.ts +307 -0
- package/dist/ui/screens/social-share-data.d.ts.map +1 -0
- package/dist/ui/screens/social-share-data.js +447 -0
- package/dist/ui/screens/social-share-data.js.map +1 -0
- package/dist/ui/screens/topics-data.d.ts +38 -0
- package/dist/ui/screens/topics-data.d.ts.map +1 -0
- package/dist/ui/screens/topics-data.js +50 -0
- package/dist/ui/screens/topics-data.js.map +1 -0
- package/dist/ui/styles/broadsheet.css +394 -0
- package/dist/ui/theme.d.ts +23 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +87 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/ui/tweaks.d.ts +7 -0
- package/dist/ui/tweaks.d.ts.map +1 -0
- package/dist/ui/tweaks.js +31 -0
- package/dist/ui/tweaks.js.map +1 -0
- package/dist/ui/use-hash-router.d.ts +6 -0
- package/dist/ui/use-hash-router.d.ts.map +1 -0
- package/dist/ui/use-hash-router.js +15 -0
- package/dist/ui/use-hash-router.js.map +1 -0
- package/dist/ui/use-tweaks.d.ts +6 -0
- package/dist/ui/use-tweaks.d.ts.map +1 -0
- package/dist/ui/use-tweaks.js +24 -0
- package/dist/ui/use-tweaks.js.map +1 -0
- package/dist/ui/workspace-context.d.ts +34 -0
- package/dist/ui/workspace-context.d.ts.map +1 -0
- package/dist/ui/workspace-context.js +32 -0
- package/dist/ui/workspace-context.js.map +1 -0
- package/migrations/0001_create_cms_tables.sql +200 -0
- package/migrations/0002_review_softdelete_board.sql +112 -0
- package/migrations/0003_content_contributors.sql +16 -0
- package/migrations/0004_seo_faq_columns.sql +6 -0
- package/migrations/0005_revision_delta_columns.sql +5 -0
- package/migrations/0006_processing_trigger_token.sql +4 -0
- package/migrations/0007_content_slug_redirects.sql +9 -0
- package/migrations/0008_workspace_settings.sql +17 -0
- package/migrations/0009_workspace_memberships.sql +36 -0
- package/migrations/0010_api_keys_webhooks.sql +21 -0
- package/migrations/0011_notifications_activity.sql +22 -0
- package/migrations/0012_content_imports.sql +10 -0
- package/migrations/0013_media_normalization.sql +4 -0
- package/migrations/0014_api_key_prefix.sql +3 -0
- package/migrations/0015_cms_topics.sql +7 -0
- package/migrations/0016_content_insights.sql +53 -0
- package/package.json +82 -0
- package/src/engine/activity-log.ts +39 -0
- package/src/engine/ai-prompts.ts +124 -0
- package/src/engine/ai-writeback.ts +62 -0
- package/src/engine/api-keys.ts +239 -0
- package/src/engine/content-insights.ts +198 -0
- package/src/engine/contributors.ts +95 -0
- package/src/engine/cron.ts +62 -0
- package/src/engine/d1.ts +29 -0
- package/src/engine/foundry-dispatch.ts +417 -0
- package/src/engine/import-parsers.ts +478 -0
- package/src/engine/index.ts +230 -0
- package/src/engine/invites.ts +271 -0
- package/src/engine/members.ts +216 -0
- package/src/engine/membership-rules.ts +63 -0
- package/src/engine/og-render.ts +59 -0
- package/src/engine/publish-guard.ts +123 -0
- package/src/engine/publisher.ts +1032 -0
- package/src/engine/revisions.ts +292 -0
- package/src/engine/sanitize.ts +183 -0
- package/src/engine/seed-membership.ts +92 -0
- package/src/engine/seo.ts +72 -0
- package/src/engine/slug-redirects.ts +34 -0
- package/src/engine/slug.ts +33 -0
- package/src/engine/soft-delete.ts +42 -0
- package/src/engine/tags.ts +95 -0
- package/src/engine/topics.ts +158 -0
- package/src/engine/url-guard.ts +136 -0
- package/src/engine/validator/checks/bare-url-not-autolinked.ts +78 -0
- package/src/engine/validator/checks/broken-footnote-label.ts +33 -0
- package/src/engine/validator/checks/double-encoded-entities.ts +46 -0
- package/src/engine/validator/checks/empty-alt-text.ts +35 -0
- package/src/engine/validator/checks/heading-hierarchy-skip.ts +33 -0
- package/src/engine/validator/checks/html-comment-leak.ts +58 -0
- package/src/engine/validator/checks/iframe-missing-dims-and-wrapper.ts +34 -0
- package/src/engine/validator/checks/invisible-control-chars.ts +58 -0
- package/src/engine/validator/checks/paywall-marker-leak.ts +43 -0
- package/src/engine/validator/checks/raw-block-html.ts +65 -0
- package/src/engine/validator/checks/stale-body-html.ts +39 -0
- package/src/engine/validator/checks/unresolved-footnote-anchor.ts +61 -0
- package/src/engine/validator/checks/word-gdocs-paste-artifacts.ts +72 -0
- package/src/engine/validator/index.ts +385 -0
- package/src/engine/validator/scan.ts +103 -0
- package/src/engine/validator/types.ts +114 -0
- package/src/engine/webhook-signer.ts +139 -0
- package/src/engine/webhooks.ts +224 -0
- package/src/index.ts +79 -0
- package/src/integration/index.ts +298 -0
- package/src/integration/options.ts +30 -0
- package/src/integration/vite-plugin.ts +37 -0
- package/src/providers/index.ts +2 -0
- package/src/providers/null.ts +160 -0
- package/src/providers/types.ts +284 -0
- package/src/routes/ai.ts +461 -0
- package/src/routes/analytics.ts +78 -0
- package/src/routes/api-keys.ts +133 -0
- package/src/routes/authors.ts +282 -0
- package/src/routes/authz-matrix.ts +239 -0
- package/src/routes/calendar.ts +127 -0
- package/src/routes/config.ts +99 -0
- package/src/routes/content-insights.ts +159 -0
- package/src/routes/content.ts +1753 -0
- package/src/routes/context.ts +146 -0
- package/src/routes/cron.ts +27 -0
- package/src/routes/dashboard.ts +174 -0
- package/src/routes/imports.ts +190 -0
- package/src/routes/index.ts +295 -0
- package/src/routes/media-lib.ts +405 -0
- package/src/routes/media.ts +944 -0
- package/src/routes/preview.ts +182 -0
- package/src/routes/rbac-invites.ts +220 -0
- package/src/routes/rbac.ts +155 -0
- package/src/routes/shell.ts +163 -0
- package/src/routes/subscriptions.ts +167 -0
- package/src/routes/tags.ts +93 -0
- package/src/routes/topics.ts +58 -0
- package/src/routes/webhooks.ts +233 -0
- package/src/schema/index.ts +45 -0
- package/src/schema/insights-ingest.ts +126 -0
- package/src/schema/migrations.ts +599 -0
- package/src/schema/tables.ts +59 -0
- package/src/schema/types.ts +576 -0
- package/src/ui/api/_authz.ts +100 -0
- package/src/ui/api/_content-config.ts +75 -0
- package/src/ui/api/activity.ts +33 -0
- package/src/ui/api/analytics.ts +42 -0
- package/src/ui/api/authors/[id].ts +23 -0
- package/src/ui/api/authors.ts +19 -0
- package/src/ui/api/calendar.ts +21 -0
- package/src/ui/api/content/[id]/ai/headlines.ts +10 -0
- package/src/ui/api/content/[id]/ai/meta-description.ts +11 -0
- package/src/ui/api/content/[id]/ai/og-image.ts +10 -0
- package/src/ui/api/content/[id]/ai/proofread.ts +10 -0
- package/src/ui/api/content/[id]/ai/takeaways.ts +11 -0
- package/src/ui/api/content/[id]/contributors.ts +13 -0
- package/src/ui/api/content/[id]/preview-token.ts +21 -0
- package/src/ui/api/content/[id]/revisions/[rev]/restore.ts +12 -0
- package/src/ui/api/content/[id]/revisions/[rev].ts +11 -0
- package/src/ui/api/content/[id]/revisions.ts +9 -0
- package/src/ui/api/content/[id]/seo-score.ts +10 -0
- package/src/ui/api/content/[id].ts +23 -0
- package/src/ui/api/content/bulk.ts +10 -0
- package/src/ui/api/content/counts.ts +11 -0
- package/src/ui/api/content/foundry-callback.ts +11 -0
- package/src/ui/api/content/import/confirm.ts +16 -0
- package/src/ui/api/content/import/parse.ts +16 -0
- package/src/ui/api/content/insights-ingest.ts +24 -0
- package/src/ui/api/content-insights/dismiss.ts +23 -0
- package/src/ui/api/content-insights/index.ts +21 -0
- package/src/ui/api/content-insights/undismiss.ts +23 -0
- package/src/ui/api/content.ts +21 -0
- package/src/ui/api/dashboard.ts +28 -0
- package/src/ui/api/me.ts +23 -0
- package/src/ui/api/media/[id].ts +22 -0
- package/src/ui/api/media/images.ts +9 -0
- package/src/ui/api/media/library/[id].ts +9 -0
- package/src/ui/api/media/library.ts +22 -0
- package/src/ui/api/media/podcast/abort.ts +6 -0
- package/src/ui/api/media/podcast/complete.ts +6 -0
- package/src/ui/api/media/podcast/init.ts +6 -0
- package/src/ui/api/media/podcast/part.ts +6 -0
- package/src/ui/api/media/podcast.ts +9 -0
- package/src/ui/api/media/videos/abort.ts +9 -0
- package/src/ui/api/media/videos/complete.ts +9 -0
- package/src/ui/api/media/videos/init.ts +9 -0
- package/src/ui/api/media/videos/part.ts +9 -0
- package/src/ui/api/notifications.ts +26 -0
- package/src/ui/api/search.ts +23 -0
- package/src/ui/api/settings/api-keys/[id].ts +28 -0
- package/src/ui/api/settings/api-keys.ts +25 -0
- package/src/ui/api/settings/domains.ts +37 -0
- package/src/ui/api/settings/integrations.ts +40 -0
- package/src/ui/api/settings/members/[userId].ts +33 -0
- package/src/ui/api/settings/members/invite.ts +27 -0
- package/src/ui/api/settings/members.ts +23 -0
- package/src/ui/api/settings/webhooks/[id]/test.ts +30 -0
- package/src/ui/api/settings/webhooks/[id].ts +29 -0
- package/src/ui/api/settings/webhooks.ts +27 -0
- package/src/ui/api/subscriptions.ts +56 -0
- package/src/ui/api/tags/[id].ts +24 -0
- package/src/ui/api/tags/index.ts +18 -0
- package/src/ui/api/topics/[id].ts +20 -0
- package/src/ui/api/topics/index.ts +17 -0
- package/src/ui/api/workspace-settings.ts +26 -0
- package/src/ui/client/boot-state.ts +42 -0
- package/src/ui/client/mount.tsx +41 -0
- package/src/ui/commands.ts +62 -0
- package/src/ui/components/CmsApp.tsx +149 -0
- package/src/ui/components/CommandPalette.tsx +118 -0
- package/src/ui/components/NoAccessScreen.tsx +79 -0
- package/src/ui/components/ShareModal.tsx +650 -0
- package/src/ui/components/SharePickers.tsx +790 -0
- package/src/ui/components/ShareStatsPanel.tsx +721 -0
- package/src/ui/components/Sidebar.tsx +86 -0
- package/src/ui/components/SiteSwitcher.tsx +100 -0
- package/src/ui/components/Topbar.tsx +93 -0
- package/src/ui/editor/AiAssistPanel.tsx +407 -0
- package/src/ui/editor/ContentForm.tsx +1462 -0
- package/src/ui/editor/Rte.tsx +382 -0
- package/src/ui/editor/ai-assist.ts +139 -0
- package/src/ui/editor/autosave.ts +36 -0
- package/src/ui/editor/content-payload.ts +125 -0
- package/src/ui/editor/editor-media-upload.ts +26 -0
- package/src/ui/editor/serialize.ts +522 -0
- package/src/ui/editor/tweet-embed.ts +60 -0
- package/src/ui/hash-router.ts +30 -0
- package/src/ui/icons.tsx +208 -0
- package/src/ui/inspector/Field.tsx +30 -0
- package/src/ui/inspector/FoundryTab.tsx +613 -0
- package/src/ui/inspector/HistoryTab.tsx +482 -0
- package/src/ui/inspector/Inspector.tsx +328 -0
- package/src/ui/inspector/OrganizeTab.tsx +534 -0
- package/src/ui/inspector/PublishTab.tsx +626 -0
- package/src/ui/inspector/Section.tsx +81 -0
- package/src/ui/inspector/SeoTab.tsx +573 -0
- package/src/ui/inspector/foundry-stages.ts +140 -0
- package/src/ui/inspector/inspector-data.ts +232 -0
- package/src/ui/inspector/organize-data.ts +51 -0
- package/src/ui/inspector/revision-diff.ts +213 -0
- package/src/ui/inspector/seo-helpers.ts +71 -0
- package/src/ui/inspector/tab-visibility.ts +37 -0
- package/src/ui/nav.ts +48 -0
- package/src/ui/pages/admin.astro +32 -0
- package/src/ui/preview/draft-page.tsx +395 -0
- package/src/ui/preview/preview-layout.ts +49 -0
- package/src/ui/screens/AnalyticsScreen.tsx +938 -0
- package/src/ui/screens/AuthorsScreen.tsx +524 -0
- package/src/ui/screens/CalendarScreen.tsx +694 -0
- package/src/ui/screens/ContentInsightsScreen.tsx +417 -0
- package/src/ui/screens/ContentRoute.tsx +35 -0
- package/src/ui/screens/DashboardScreen.tsx +654 -0
- package/src/ui/screens/EditorScreen.tsx +673 -0
- package/src/ui/screens/LibraryScreen.tsx +1350 -0
- package/src/ui/screens/MediaScreen.tsx +357 -0
- package/src/ui/screens/SettingsScreen.tsx +1841 -0
- package/src/ui/screens/SocialShareScreen.tsx +670 -0
- package/src/ui/screens/SubscriptionsScreen.tsx +1240 -0
- package/src/ui/screens/TopicsScreen.tsx +912 -0
- package/src/ui/screens/analytics-data.ts +68 -0
- package/src/ui/screens/calendar-data.ts +126 -0
- package/src/ui/screens/content-insights-data.ts +127 -0
- package/src/ui/screens/content-view.ts +30 -0
- package/src/ui/screens/library-data.ts +177 -0
- package/src/ui/screens/media-upload.ts +283 -0
- package/src/ui/screens/public-url.ts +81 -0
- package/src/ui/screens/registry.tsx +53 -0
- package/src/ui/screens/render-state.ts +228 -0
- package/src/ui/screens/settings-data.ts +140 -0
- package/src/ui/screens/settings-panels-data.ts +142 -0
- package/src/ui/screens/social-share-data.ts +753 -0
- package/src/ui/screens/topics-data.ts +75 -0
- package/src/ui/styles/broadsheet.css +394 -0
- package/src/ui/theme.ts +104 -0
- package/src/ui/tweaks.ts +37 -0
- package/src/ui/use-hash-router.ts +17 -0
- package/src/ui/use-tweaks.ts +31 -0
- package/src/ui/workspace-context.tsx +62 -0
- package/src/virtual.d.ts +4 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// invites.ts — workspace_invites engine (P7 Task 5).
|
|
2
|
+
//
|
|
3
|
+
// Copies inbox-platform src/lib/invites/service.ts, re-keyed onto:
|
|
4
|
+
// workspace_invites / workspace_memberships / masthead_users
|
|
5
|
+
// Differences from inbox:
|
|
6
|
+
// - Uses Web Crypto (crypto.subtle.digest) NOT node:crypto — workerd-pure.
|
|
7
|
+
// - Timestamps are INTEGER unixepoch() (CMS convention, not inbox's TEXT datetime('now')).
|
|
8
|
+
// - acceptInvite takes the full user object; the identity call (mintOrAttachAccount)
|
|
9
|
+
// is the route layer's responsibility (routes/rbac-invites.ts), NOT the engine.
|
|
10
|
+
//
|
|
11
|
+
// SCOPE GUARDS (from spec §12):
|
|
12
|
+
// - Email must match the invite on accept (else invite_email_mismatch).
|
|
13
|
+
// - Membership is keyed on the REAL OpenAuth subject ('user:<uuid>') — NEVER a placeholder.
|
|
14
|
+
// - Email send is a Fronts-cutover concern; the engine only writes the row + returns the token.
|
|
15
|
+
import { upsertMastheadUser } from './members.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// hashInviteToken — Web Crypto SHA-256 hex (workerd-pure, no node:crypto)
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
export async function hashInviteToken(token) {
|
|
20
|
+
const enc = new TextEncoder();
|
|
21
|
+
const buf = await crypto.subtle.digest('SHA-256', enc.encode(token));
|
|
22
|
+
return Array.from(new Uint8Array(buf))
|
|
23
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
24
|
+
.join('');
|
|
25
|
+
}
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// createInvite — write the invite row, return the raw token (not stored)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Create a workspace invite. Generates a random token, stores only its
|
|
31
|
+
* SHA-256 hash in the DB (never the raw value), and returns the token + id.
|
|
32
|
+
*
|
|
33
|
+
* The invite-email send is a Fronts-cutover concern (injected hook in the route
|
|
34
|
+
* layer) — the engine only persists the row. Mirror inbox "failure-as-value".
|
|
35
|
+
*/
|
|
36
|
+
export async function createInvite(db, input) {
|
|
37
|
+
const id = crypto.randomUUID();
|
|
38
|
+
// Generate a raw token: 32 random bytes as hex
|
|
39
|
+
const raw = new Uint8Array(32);
|
|
40
|
+
crypto.getRandomValues(raw);
|
|
41
|
+
const token = Array.from(raw)
|
|
42
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
43
|
+
.join('');
|
|
44
|
+
const tokenHash = await hashInviteToken(token);
|
|
45
|
+
const expiresIn = input.expiresInSeconds ?? 7 * 24 * 60 * 60; // 7 days
|
|
46
|
+
const now = Math.floor(Date.now() / 1000);
|
|
47
|
+
const expiresAt = now + expiresIn;
|
|
48
|
+
await db
|
|
49
|
+
.prepare(`INSERT INTO workspace_invites (id, workspace_id, email, role, invited_by, token_hash, expires_at, accepted_at, created_at)
|
|
50
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, NULL, ?)`)
|
|
51
|
+
.bind(id, input.workspaceId, input.email, input.role, input.invitedBy, tokenHash, expiresAt, now)
|
|
52
|
+
.run();
|
|
53
|
+
return { inviteId: id, token };
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// loadInviteByToken — hash the token, look up, reject expired/accepted
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
/**
|
|
59
|
+
* Load a pending invite by its raw token. Returns null if:
|
|
60
|
+
* - token hash does not match any row
|
|
61
|
+
* - the invite is expired (expires_at <= now)
|
|
62
|
+
* - the invite is already accepted (accepted_at IS NOT NULL)
|
|
63
|
+
*
|
|
64
|
+
* Mirrors inbox `loadTenantInviteByToken`.
|
|
65
|
+
*/
|
|
66
|
+
export async function loadInviteByToken(db, token) {
|
|
67
|
+
const tokenHash = await hashInviteToken(token);
|
|
68
|
+
const now = Math.floor(Date.now() / 1000);
|
|
69
|
+
const row = await db
|
|
70
|
+
.prepare(`SELECT id, workspace_id, email, role, invited_by, token_hash, expires_at, accepted_at, created_at
|
|
71
|
+
FROM workspace_invites
|
|
72
|
+
WHERE token_hash = ? AND expires_at > ? AND accepted_at IS NULL`)
|
|
73
|
+
.bind(tokenHash, now)
|
|
74
|
+
.first();
|
|
75
|
+
if (!row)
|
|
76
|
+
return null;
|
|
77
|
+
return {
|
|
78
|
+
id: row.id,
|
|
79
|
+
workspaceId: row.workspace_id,
|
|
80
|
+
email: row.email,
|
|
81
|
+
role: row.role,
|
|
82
|
+
invitedBy: row.invited_by,
|
|
83
|
+
tokenHash: row.token_hash,
|
|
84
|
+
expiresAt: row.expires_at,
|
|
85
|
+
acceptedAt: row.accepted_at,
|
|
86
|
+
createdAt: row.created_at,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// upsertMembership — insert or update a workspace_memberships row
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
async function upsertMembership(db, { workspaceId, userId, role, invitedBy, acceptedAt, }) {
|
|
93
|
+
const now = Math.floor(Date.now() / 1000);
|
|
94
|
+
await db
|
|
95
|
+
.prepare(`INSERT INTO workspace_memberships (workspace_id, user_id, role, invited_by, accepted_at, created_at, updated_at)
|
|
96
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
97
|
+
ON CONFLICT(workspace_id, user_id) DO UPDATE SET
|
|
98
|
+
role = excluded.role,
|
|
99
|
+
accepted_at = excluded.accepted_at,
|
|
100
|
+
updated_at = excluded.updated_at`)
|
|
101
|
+
.bind(workspaceId, userId, role, invitedBy ?? null, acceptedAt, now, now)
|
|
102
|
+
.run();
|
|
103
|
+
}
|
|
104
|
+
// ---------------------------------------------------------------------------
|
|
105
|
+
// acceptInvite — validate email match, upsert user + membership, mark accepted
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
/**
|
|
108
|
+
* Accept a workspace invite.
|
|
109
|
+
*
|
|
110
|
+
* Validates:
|
|
111
|
+
* 1. The token resolves to a pending, non-expired invite.
|
|
112
|
+
* 2. The user's email matches the invite email (prevents invite-link hijacking).
|
|
113
|
+
*
|
|
114
|
+
* On success:
|
|
115
|
+
* - Upserts masthead_users (with the REAL OpenAuth subject as id).
|
|
116
|
+
* - Upserts workspace_memberships keyed on the real subject.
|
|
117
|
+
* - Marks the invite accepted.
|
|
118
|
+
*
|
|
119
|
+
* Throws:
|
|
120
|
+
* - 'invite_not_found' if the token is unknown/expired/accepted.
|
|
121
|
+
* - 'invite_email_mismatch' if the user email does not match.
|
|
122
|
+
*
|
|
123
|
+
* NOTE: The IdentityProvider.mintOrAttachAccount call is the ROUTE layer's
|
|
124
|
+
* responsibility — the engine only persists the data.
|
|
125
|
+
*/
|
|
126
|
+
export async function acceptInvite(db, input) {
|
|
127
|
+
const invite = await loadInviteByToken(db, input.token);
|
|
128
|
+
if (!invite) {
|
|
129
|
+
throw new Error('invite_not_found');
|
|
130
|
+
}
|
|
131
|
+
// Email must match (case-insensitive)
|
|
132
|
+
if (invite.email.toLowerCase() !== input.user.email.toLowerCase()) {
|
|
133
|
+
throw new Error('invite_email_mismatch');
|
|
134
|
+
}
|
|
135
|
+
const now = Math.floor(Date.now() / 1000);
|
|
136
|
+
// Upsert the user profile
|
|
137
|
+
await upsertMastheadUser(db, {
|
|
138
|
+
id: input.user.id,
|
|
139
|
+
email: input.user.email,
|
|
140
|
+
name: input.user.name,
|
|
141
|
+
image: input.user.image,
|
|
142
|
+
});
|
|
143
|
+
// Upsert the membership (accepted)
|
|
144
|
+
await upsertMembership(db, {
|
|
145
|
+
workspaceId: invite.workspaceId,
|
|
146
|
+
userId: input.user.id,
|
|
147
|
+
role: invite.role,
|
|
148
|
+
invitedBy: invite.invitedBy,
|
|
149
|
+
acceptedAt: now,
|
|
150
|
+
});
|
|
151
|
+
// Mark invite accepted
|
|
152
|
+
await db
|
|
153
|
+
.prepare(`UPDATE workspace_invites SET accepted_at = ? WHERE id = ?`)
|
|
154
|
+
.bind(now, invite.id)
|
|
155
|
+
.run();
|
|
156
|
+
return { workspaceId: invite.workspaceId, role: invite.role };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=invites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invites.js","sourceRoot":"","sources":["../../src/engine/invites.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { CmsRole } from '../schema/types.js';
|
|
2
|
+
import type { D1Database } from './d1.js';
|
|
3
|
+
/** A resolved membership record (workspace_memberships row, flat). */
|
|
4
|
+
export interface MembershipRecord {
|
|
5
|
+
workspaceId: string;
|
|
6
|
+
userId: string;
|
|
7
|
+
role: CmsRole;
|
|
8
|
+
invitedBy: string | null;
|
|
9
|
+
invitedAt: number | null;
|
|
10
|
+
acceptedAt: number | null;
|
|
11
|
+
createdAt: number;
|
|
12
|
+
updatedAt: number;
|
|
13
|
+
}
|
|
14
|
+
/** A membership record joined to masthead_users for the member-list view. */
|
|
15
|
+
export interface MemberListEntry extends MembershipRecord {
|
|
16
|
+
email: string;
|
|
17
|
+
name: string | null;
|
|
18
|
+
image: string | null;
|
|
19
|
+
}
|
|
20
|
+
export interface UpsertMastheadUserInput {
|
|
21
|
+
/** Real OpenAuth subject — MUST start with 'user:'. */
|
|
22
|
+
id: string;
|
|
23
|
+
email: string;
|
|
24
|
+
name: string | null;
|
|
25
|
+
image: string | null;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Upsert a masthead_users row. On conflict(id), updates email/name/image and
|
|
29
|
+
* bumps last_login_at + updated_at. Uses INTEGER unixepoch() timestamps
|
|
30
|
+
* (diverges from inbox's TEXT datetime('now') — match CMS convention).
|
|
31
|
+
*
|
|
32
|
+
* NEVER call with a locally-minted or placeholder id — id must be the real
|
|
33
|
+
* OpenAuth subject ('user:<uuid>'). A placeholder email on the UNIQUE column
|
|
34
|
+
* causes a 500 on the real person's first login (inbox-platform §16 risk 10).
|
|
35
|
+
*/
|
|
36
|
+
export declare function upsertMastheadUser(db: D1Database, input: UpsertMastheadUserInput): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Load a single workspace membership keyed on (workspaceId, userId).
|
|
39
|
+
* Returns null when absent — a caller receiving null must 403/401.
|
|
40
|
+
* The userId MUST be the real OpenAuth subject; a placeholder returns null.
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadMembership(db: D1Database, workspaceId: string, userId: string): Promise<MembershipRecord | null>;
|
|
43
|
+
/**
|
|
44
|
+
* List all accepted members for a workspace, joined to masthead_users for
|
|
45
|
+
* profile data. Ordered by membership created_at ASC (deterministic).
|
|
46
|
+
*/
|
|
47
|
+
export declare function listMembers(db: D1Database, workspaceId: string): Promise<MemberListEntry[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Update the role of an existing workspace member. Does not enforce the
|
|
50
|
+
* owner-invariant here — callers (route layer) must apply canChangeMemberRole
|
|
51
|
+
* from membership-rules.ts before calling this.
|
|
52
|
+
*/
|
|
53
|
+
export declare function setRole(db: D1Database, workspaceId: string, userId: string, role: CmsRole): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Remove a member from a workspace. Does not enforce the owner-invariant
|
|
56
|
+
* here — callers must apply canRemoveMember from membership-rules.ts first.
|
|
57
|
+
*/
|
|
58
|
+
export declare function removeMember(db: D1Database, workspaceId: string, userId: string): Promise<void>;
|
|
59
|
+
//# sourceMappingURL=members.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"members.d.ts","sourceRoot":"","sources":["../../src/engine/members.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAMzC,sEAAsE;AACtE,MAAM,WAAW,gBAAgB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;CACjB;AAED,6EAA6E;AAC7E,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACxD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAMD,MAAM,WAAW,uBAAuB;IACvC,uDAAuD;IACvD,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACvC,EAAE,EAAE,UAAU,EACd,KAAK,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAef;AAMD;;;;GAIG;AACH,wBAAsB,cAAc,CACnC,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA8BlC;AAMD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAyCjG;AAMD;;;;GAIG;AACH,wBAAsB,OAAO,CAC5B,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,GACX,OAAO,CAAC,IAAI,CAAC,CAUf;AAMD;;;GAGG;AACH,wBAAsB,YAAY,CACjC,EAAE,EAAE,UAAU,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAKf"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
// members.ts — Membership engine over workspace_memberships + masthead_users (P7 Task 1).
|
|
2
|
+
//
|
|
3
|
+
// Mirrors inbox-platform src/lib/data/members.ts (loadMembershipForUser /
|
|
4
|
+
// upsertInboxUser) re-keyed onto workspace_memberships / masthead_users.
|
|
5
|
+
// Differences from inbox:
|
|
6
|
+
// - Timestamps are INTEGER unixepoch() per CMS convention (inbox uses TEXT datetime('now')).
|
|
7
|
+
// - Subject format is the real OpenAuth subject 'user:<uuid>' (NEVER a locally-minted id).
|
|
8
|
+
// - listMembers does a LEFT JOIN to masthead_users for the profile view.
|
|
9
|
+
/**
|
|
10
|
+
* Upsert a masthead_users row. On conflict(id), updates email/name/image and
|
|
11
|
+
* bumps last_login_at + updated_at. Uses INTEGER unixepoch() timestamps
|
|
12
|
+
* (diverges from inbox's TEXT datetime('now') — match CMS convention).
|
|
13
|
+
*
|
|
14
|
+
* NEVER call with a locally-minted or placeholder id — id must be the real
|
|
15
|
+
* OpenAuth subject ('user:<uuid>'). A placeholder email on the UNIQUE column
|
|
16
|
+
* causes a 500 on the real person's first login (inbox-platform §16 risk 10).
|
|
17
|
+
*/
|
|
18
|
+
export async function upsertMastheadUser(db, input) {
|
|
19
|
+
const now = Math.floor(Date.now() / 1000);
|
|
20
|
+
await db
|
|
21
|
+
.prepare(`INSERT INTO masthead_users (id, email, name, image, last_login_at, created_at, updated_at)
|
|
22
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
23
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
24
|
+
email = excluded.email,
|
|
25
|
+
name = excluded.name,
|
|
26
|
+
image = excluded.image,
|
|
27
|
+
last_login_at = excluded.last_login_at,
|
|
28
|
+
updated_at = excluded.updated_at`)
|
|
29
|
+
.bind(input.id, input.email, input.name ?? null, input.image ?? null, now, now, now)
|
|
30
|
+
.run();
|
|
31
|
+
}
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// loadMembership (mirror loadMembershipForUser)
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/**
|
|
36
|
+
* Load a single workspace membership keyed on (workspaceId, userId).
|
|
37
|
+
* Returns null when absent — a caller receiving null must 403/401.
|
|
38
|
+
* The userId MUST be the real OpenAuth subject; a placeholder returns null.
|
|
39
|
+
*/
|
|
40
|
+
export async function loadMembership(db, workspaceId, userId) {
|
|
41
|
+
const row = await db
|
|
42
|
+
.prepare(`SELECT workspace_id, user_id, role, invited_by, invited_at, accepted_at, created_at, updated_at
|
|
43
|
+
FROM workspace_memberships
|
|
44
|
+
WHERE workspace_id = ? AND user_id = ?`)
|
|
45
|
+
.bind(workspaceId, userId)
|
|
46
|
+
.first();
|
|
47
|
+
if (!row)
|
|
48
|
+
return null;
|
|
49
|
+
return {
|
|
50
|
+
workspaceId: row.workspace_id,
|
|
51
|
+
userId: row.user_id,
|
|
52
|
+
role: row.role,
|
|
53
|
+
invitedBy: row.invited_by,
|
|
54
|
+
invitedAt: row.invited_at,
|
|
55
|
+
acceptedAt: row.accepted_at,
|
|
56
|
+
createdAt: row.created_at,
|
|
57
|
+
updatedAt: row.updated_at,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// listMembers — LEFT JOIN masthead_users for the member list view
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
/**
|
|
64
|
+
* List all accepted members for a workspace, joined to masthead_users for
|
|
65
|
+
* profile data. Ordered by membership created_at ASC (deterministic).
|
|
66
|
+
*/
|
|
67
|
+
export async function listMembers(db, workspaceId) {
|
|
68
|
+
const result = await db
|
|
69
|
+
.prepare(`SELECT
|
|
70
|
+
wm.workspace_id, wm.user_id, wm.role,
|
|
71
|
+
wm.invited_by, wm.invited_at, wm.accepted_at,
|
|
72
|
+
wm.created_at, wm.updated_at,
|
|
73
|
+
mu.email, mu.name, mu.image
|
|
74
|
+
FROM workspace_memberships wm
|
|
75
|
+
LEFT JOIN masthead_users mu ON mu.id = wm.user_id
|
|
76
|
+
WHERE wm.workspace_id = ?
|
|
77
|
+
ORDER BY wm.created_at ASC`)
|
|
78
|
+
.bind(workspaceId)
|
|
79
|
+
.all();
|
|
80
|
+
return (result.results ?? []).map((row) => ({
|
|
81
|
+
workspaceId: row.workspace_id,
|
|
82
|
+
userId: row.user_id,
|
|
83
|
+
role: row.role,
|
|
84
|
+
invitedBy: row.invited_by,
|
|
85
|
+
invitedAt: row.invited_at,
|
|
86
|
+
acceptedAt: row.accepted_at,
|
|
87
|
+
createdAt: row.created_at,
|
|
88
|
+
updatedAt: row.updated_at,
|
|
89
|
+
email: row.email,
|
|
90
|
+
name: row.name,
|
|
91
|
+
image: row.image,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// setRole — update a member's role
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
/**
|
|
98
|
+
* Update the role of an existing workspace member. Does not enforce the
|
|
99
|
+
* owner-invariant here — callers (route layer) must apply canChangeMemberRole
|
|
100
|
+
* from membership-rules.ts before calling this.
|
|
101
|
+
*/
|
|
102
|
+
export async function setRole(db, workspaceId, userId, role) {
|
|
103
|
+
const now = Math.floor(Date.now() / 1000);
|
|
104
|
+
await db
|
|
105
|
+
.prepare(`UPDATE workspace_memberships
|
|
106
|
+
SET role = ?, updated_at = ?
|
|
107
|
+
WHERE workspace_id = ? AND user_id = ?`)
|
|
108
|
+
.bind(role, now, workspaceId, userId)
|
|
109
|
+
.run();
|
|
110
|
+
}
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// removeMember — delete a membership row
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
/**
|
|
115
|
+
* Remove a member from a workspace. Does not enforce the owner-invariant
|
|
116
|
+
* here — callers must apply canRemoveMember from membership-rules.ts first.
|
|
117
|
+
*/
|
|
118
|
+
export async function removeMember(db, workspaceId, userId) {
|
|
119
|
+
await db
|
|
120
|
+
.prepare(`DELETE FROM workspace_memberships WHERE workspace_id = ? AND user_id = ?`)
|
|
121
|
+
.bind(workspaceId, userId)
|
|
122
|
+
.run();
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=members.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"members.js","sourceRoot":"","sources":["../../src/engine/members.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type MembershipSummary = {
|
|
2
|
+
userId: string;
|
|
3
|
+
role: string;
|
|
4
|
+
};
|
|
5
|
+
export type MemberActionDecision = {
|
|
6
|
+
allowed: true;
|
|
7
|
+
} | {
|
|
8
|
+
allowed: false;
|
|
9
|
+
reason: 'cannot-remove-self' | 'last-owner';
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Count the number of members with the 'owner' role.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ownerCount(members: MembershipSummary[]): number;
|
|
15
|
+
/**
|
|
16
|
+
* A member cannot remove themselves (avoids accidental lockout) and the sole
|
|
17
|
+
* owner cannot be removed (the workspace must always keep at least one owner).
|
|
18
|
+
*/
|
|
19
|
+
export declare function canRemoveMember(members: MembershipSummary[], actorUserId: string, targetUserId: string): MemberActionDecision;
|
|
20
|
+
/**
|
|
21
|
+
* The sole owner cannot be demoted to a non-owner role — that would leave the
|
|
22
|
+
* workspace with no owner. Any other role change is allowed.
|
|
23
|
+
*/
|
|
24
|
+
export declare function canChangeMemberRole(members: MembershipSummary[], targetUserId: string, newRole: string): MemberActionDecision;
|
|
25
|
+
//# sourceMappingURL=membership-rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"membership-rules.d.ts","sourceRoot":"","sources":["../../src/engine/membership-rules.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,iBAAiB,GAAG;IAC/B,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,MAAM,MAAM,oBAAoB,GAC7B;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GACjB;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,oBAAoB,GAAG,YAAY,CAAA;CAAE,CAAA;AAElE;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAE/D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,iBAAiB,EAAE,EAC5B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GAClB,oBAAoB,CAStB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,iBAAiB,EAAE,EAC5B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,GACb,oBAAoB,CAMtB"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// membership-rules.ts — Pure membership invariant guards (P7 Task 3).
|
|
2
|
+
//
|
|
3
|
+
// Copied from inbox-platform src/lib/permissions.ts — re-keyed onto the
|
|
4
|
+
// workspace_memberships model. The mailboxScope helpers are stripped; the
|
|
5
|
+
// owner-invariant logic (ownerCount / canRemoveMember / canChangeMemberRole)
|
|
6
|
+
// is preserved verbatim.
|
|
7
|
+
//
|
|
8
|
+
// These are PURE functions — no D1, no crypto, no async.
|
|
9
|
+
//
|
|
10
|
+
// The "always keep ≥1 owner" invariant is non-negotiable:
|
|
11
|
+
// - canRemoveMember: cannot remove self; cannot remove the sole owner.
|
|
12
|
+
// - canChangeMemberRole: cannot demote the sole owner to a non-owner role.
|
|
13
|
+
/**
|
|
14
|
+
* Count the number of members with the 'owner' role.
|
|
15
|
+
*/
|
|
16
|
+
export function ownerCount(members) {
|
|
17
|
+
return members.filter((member) => member.role === 'owner').length;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A member cannot remove themselves (avoids accidental lockout) and the sole
|
|
21
|
+
* owner cannot be removed (the workspace must always keep at least one owner).
|
|
22
|
+
*/
|
|
23
|
+
export function canRemoveMember(members, actorUserId, targetUserId) {
|
|
24
|
+
if (actorUserId === targetUserId) {
|
|
25
|
+
return { allowed: false, reason: 'cannot-remove-self' };
|
|
26
|
+
}
|
|
27
|
+
const target = members.find((member) => member.userId === targetUserId);
|
|
28
|
+
if (target?.role === 'owner' && ownerCount(members) <= 1) {
|
|
29
|
+
return { allowed: false, reason: 'last-owner' };
|
|
30
|
+
}
|
|
31
|
+
return { allowed: true };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The sole owner cannot be demoted to a non-owner role — that would leave the
|
|
35
|
+
* workspace with no owner. Any other role change is allowed.
|
|
36
|
+
*/
|
|
37
|
+
export function canChangeMemberRole(members, targetUserId, newRole) {
|
|
38
|
+
const target = members.find((member) => member.userId === targetUserId);
|
|
39
|
+
if (target?.role === 'owner' && newRole !== 'owner' && ownerCount(members) <= 1) {
|
|
40
|
+
return { allowed: false, reason: 'last-owner' };
|
|
41
|
+
}
|
|
42
|
+
return { allowed: true };
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=membership-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"membership-rules.js","sourceRoot":"","sources":["../../src/engine/membership-rules.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,6EAA6E;AAC7E,yBAAyB;AACzB,EAAE;AACF,yDAAyD;AACzD,EAAE;AACF,0DAA0D;AAC1D,yEAAyE;AACzE,6EAA6E;AAW7E;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAA4B;IACtD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,MAAM,CAAA;AAClE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC9B,OAA4B,EAC5B,WAAmB,EACnB,YAAoB;IAEpB,IAAI,WAAW,KAAK,YAAY,EAAE,CAAC;QAClC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAA;IACxD,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC,CAAA;IACvE,IAAI,MAAM,EAAE,IAAI,KAAK,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1D,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;IAChD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAClC,OAA4B,EAC5B,YAAoB,EACpB,OAAe;IAEf,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC,CAAA;IACvE,IAAI,MAAM,EAAE,IAAI,KAAK,OAAO,IAAI,OAAO,KAAK,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACjF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;IAChD,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** The deterministic spec the generateOgImage route hands to the renderer. */
|
|
2
|
+
export interface OgCardSpec {
|
|
3
|
+
/** The article headline / title. */
|
|
4
|
+
title: string;
|
|
5
|
+
/** Subtitle copy — typically the excerpt/dek. Empty string when absent. */
|
|
6
|
+
subtitle: string;
|
|
7
|
+
/** Publication brand label (displayed on the card). */
|
|
8
|
+
brand: string;
|
|
9
|
+
/** Optional hero-image URL to composite into the card background. */
|
|
10
|
+
heroUrl?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The renderer interface. The package defines the contract; the site (cutover
|
|
14
|
+
* P8) supplies a real implementation backed by a Browser Rendering binding or
|
|
15
|
+
* a Resvg/satori WASM path. Tests inject a stub that returns fixed bytes.
|
|
16
|
+
*/
|
|
17
|
+
export interface OgImageRenderer {
|
|
18
|
+
/** Render the card spec to PNG bytes. */
|
|
19
|
+
render(spec: OgCardSpec): Promise<Uint8Array>;
|
|
20
|
+
}
|
|
21
|
+
/** Options for buildOgCardSpec. */
|
|
22
|
+
export interface OgCardSpecOpts {
|
|
23
|
+
/** Override the publication brand label. Defaults to 'The Publication'. */
|
|
24
|
+
brand?: string;
|
|
25
|
+
/** Pre-resolved hero image URL. If absent, heroUrl is omitted from the spec. */
|
|
26
|
+
heroUrl?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build a deterministic OgCardSpec from a content row + options.
|
|
30
|
+
*
|
|
31
|
+
* - title: from the content item.
|
|
32
|
+
* - subtitle: from the item's excerpt; empty string when absent/null.
|
|
33
|
+
* - brand: from opts.brand or a sensible default label.
|
|
34
|
+
* - heroUrl: from opts.heroUrl when present; omitted otherwise.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildOgCardSpec(item: {
|
|
37
|
+
title: string;
|
|
38
|
+
excerpt?: string | null;
|
|
39
|
+
}, opts: OgCardSpecOpts): OgCardSpec;
|
|
40
|
+
//# sourceMappingURL=og-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"og-render.d.ts","sourceRoot":"","sources":["../../src/engine/og-render.ts"],"names":[],"mappings":"AAOA,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IAC1B,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,CAAA;IAChB,uDAAuD;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,yCAAyC;IACzC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;CAC7C;AAED,mCAAmC;AACnC,MAAM,WAAW,cAAc;IAC9B,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gFAAgF;IAChF,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC9B,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAChD,IAAI,EAAE,cAAc,GAClB,UAAU,CAUZ"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// OG-image renderer interface + pure card-spec builder (P4 Task 5).
|
|
2
|
+
//
|
|
3
|
+
// The package owns the OgImageRenderer *interface* and the OgCardSpec type.
|
|
4
|
+
// The mechanism that produces the PNG (Cloudflare Browser Rendering binding vs.
|
|
5
|
+
// Resvg/satori WASM) is INJECTED by the site and is NOT imported here — it is
|
|
6
|
+
// cutover glue (P8). Tests inject a stub renderer that returns fixed bytes.
|
|
7
|
+
/**
|
|
8
|
+
* Build a deterministic OgCardSpec from a content row + options.
|
|
9
|
+
*
|
|
10
|
+
* - title: from the content item.
|
|
11
|
+
* - subtitle: from the item's excerpt; empty string when absent/null.
|
|
12
|
+
* - brand: from opts.brand or a sensible default label.
|
|
13
|
+
* - heroUrl: from opts.heroUrl when present; omitted otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export function buildOgCardSpec(item, opts) {
|
|
16
|
+
const spec = {
|
|
17
|
+
title: item.title,
|
|
18
|
+
subtitle: item.excerpt ?? '',
|
|
19
|
+
brand: opts.brand ?? 'The Publication',
|
|
20
|
+
};
|
|
21
|
+
if (opts.heroUrl !== undefined) {
|
|
22
|
+
spec.heroUrl = opts.heroUrl;
|
|
23
|
+
}
|
|
24
|
+
return spec;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=og-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"og-render.js","sourceRoot":"","sources":["../../src/engine/og-render.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,8EAA8E;AAC9E,4EAA4E;AAgC5E;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC9B,IAAgD,EAChD,IAAoB;IAEpB,MAAM,IAAI,GAAe;QACxB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,OAAO,IAAI,EAAE;QAC5B,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,iBAAiB;KACtC,CAAA;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;IAC5B,CAAC;IACD,OAAO,IAAI,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* publish-guard.ts
|
|
3
|
+
*
|
|
4
|
+
* Wraps `validateArticleBody` for call sites that need a single
|
|
5
|
+
* pass/fail decision plus a response-shaped payload. The CMS PATCH
|
|
6
|
+
* route and Foundry callbacks each invoke this before writing the new
|
|
7
|
+
* body so broken content is rejected before it lands in
|
|
8
|
+
* `article_content`.
|
|
9
|
+
*
|
|
10
|
+
* Ported verbatim from fulcrum-labs/fronts
|
|
11
|
+
* src/lib/article-publish-guard.ts (inventory §1: extract). Only
|
|
12
|
+
* block-severity codes cause `ok = false`; warn-severity codes populate
|
|
13
|
+
* `warnings` so the CMS / Foundry callback can surface them to the
|
|
14
|
+
* editor but does NOT reject the write.
|
|
15
|
+
*
|
|
16
|
+
* Keep this layer thin — the heavy lifting lives in `./validator/`.
|
|
17
|
+
*/
|
|
18
|
+
import { type ArticleBodyInput, type RunOptions, type ValidationError } from './validator/index.js';
|
|
19
|
+
export interface PublishGuardOptions extends Partial<RunOptions> {
|
|
20
|
+
/**
|
|
21
|
+
* A short label included in the log line / response so logs can be
|
|
22
|
+
* traced back to the call site (e.g. "cms.patch", "foundry.faq").
|
|
23
|
+
*/
|
|
24
|
+
source: string;
|
|
25
|
+
/**
|
|
26
|
+
* Optional content_id for log correlation.
|
|
27
|
+
*/
|
|
28
|
+
contentId?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface PublishGuardOutcome {
|
|
31
|
+
/** `true` iff there are no block-severity violations. */
|
|
32
|
+
ok: boolean;
|
|
33
|
+
/** All violations (block + warn) in detection order. */
|
|
34
|
+
errors: ValidationError[];
|
|
35
|
+
/** Block-severity subset of {@link errors} — the rejection reason. */
|
|
36
|
+
blockErrors: ValidationError[];
|
|
37
|
+
/** Warn-severity subset of {@link errors} — for editor surfacing. */
|
|
38
|
+
warnings: ValidationError[];
|
|
39
|
+
/** Pre-formatted error string, ready for log lines / response body. */
|
|
40
|
+
summary: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Validate the body and produce a structured outcome. Callers decide
|
|
44
|
+
* whether to return a 422, log a warning, or proceed. `ok` is true
|
|
45
|
+
* iff there are no block-severity codes — warn-only violations still
|
|
46
|
+
* populate `warnings` for editor surfacing.
|
|
47
|
+
*/
|
|
48
|
+
export declare function evaluateArticleBody(input: ArticleBodyInput, options: PublishGuardOptions): PublishGuardOutcome;
|
|
49
|
+
/**
|
|
50
|
+
* Convenience helper for HTTP handlers: returns a 422 Response when
|
|
51
|
+
* the body has block-severity violations, or null when validation
|
|
52
|
+
* passes (so the handler can proceed). Warn-severity violations log
|
|
53
|
+
* but do NOT block the response — callers that want to surface them
|
|
54
|
+
* in their 200 payload should call {@link evaluateArticleBody}
|
|
55
|
+
* directly and read `outcome.warnings`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function publishGuardResponseOrNull(input: ArticleBodyInput, options: PublishGuardOptions): Response | null;
|
|
58
|
+
//# sourceMappingURL=publish-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish-guard.d.ts","sourceRoot":"","sources":["../../src/engine/publish-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACN,KAAK,gBAAgB,EAErB,KAAK,UAAU,EACf,KAAK,eAAe,EAIpB,MAAM,sBAAsB,CAAA;AAE7B,MAAM,WAAW,mBAAoB,SAAQ,OAAO,CAAC,UAAU,CAAC;IAC/D;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAA;IACd;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,mBAAmB;IACnC,yDAAyD;IACzD,EAAE,EAAE,OAAO,CAAA;IACX,wDAAwD;IACxD,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,sEAAsE;IACtE,WAAW,EAAE,eAAe,EAAE,CAAA;IAC9B,qEAAqE;IACrE,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAA;CACf;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAClC,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,mBAAmB,GAC1B,mBAAmB,CAqBrB;AAUD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACzC,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,mBAAmB,GAC1B,QAAQ,GAAG,IAAI,CAmBjB"}
|