emdash 0.37.0 → 0.39.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/dist/action-token-On1sot_c.mjs +26 -0
- package/dist/action-token-On1sot_c.mjs.map +1 -0
- package/dist/activation-CaMfdBt1.mjs +382 -0
- package/dist/activation-CaMfdBt1.mjs.map +1 -0
- package/dist/adapters-Cq10K4_c.d.mts +171 -0
- package/dist/adapters-Cq10K4_c.d.mts.map +1 -0
- package/dist/after-PcEvMY_6.mjs +96 -0
- package/dist/after-PcEvMY_6.mjs.map +1 -0
- package/dist/allowed-origins-1Sa-2wZK.mjs +116 -0
- package/dist/allowed-origins-1Sa-2wZK.mjs.map +1 -0
- package/dist/api/route-utils.d.mts +4 -3
- package/dist/api/route-utils.d.mts.map +1 -1
- package/dist/api/route-utils.mjs +45 -29
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +7 -6
- package/dist/api-DmjKxPCY.mjs +4831 -0
- package/dist/api-DmjKxPCY.mjs.map +1 -0
- package/dist/api-tokens-BIXItFKV.mjs +163 -0
- package/dist/api-tokens-BIXItFKV.mjs.map +1 -0
- package/dist/apply-drpfmqrR.mjs +1005 -0
- package/dist/apply-drpfmqrR.mjs.map +1 -0
- package/dist/artifact-fetch-COiMhVgk.mjs +813 -0
- package/dist/artifact-fetch-COiMhVgk.mjs.map +1 -0
- package/dist/astro/index.d.mts +14 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +123 -13
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +12 -10
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +20 -11
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/media-usage-write-fence.mjs +5 -5
- package/dist/astro/middleware/redirect.mjs +11 -9
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.d.mts +1 -1
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +154 -28
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +13 -10
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +122 -3041
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +10 -9
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +10 -9
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +13 -12
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +13 -12
- package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +13 -12
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +22 -21
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +22 -21
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +22 -21
- package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_/status.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +21 -54
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/bulk.mjs +15 -14
- package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/counts.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/index.mjs +15 -14
- package/dist/astro/routes/api/admin/comments/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +5 -5
- package/dist/astro/routes/api/admin/media-usage/activation.mjs +17 -16
- package/dist/astro/routes/api/admin/media-usage/activation.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs +19 -18
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs +19 -18
- package/dist/astro/routes/api/admin/media-usage/collection-deletions/retry.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/progress.mjs +17 -17
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +21 -20
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs +19 -18
- package/dist/astro/routes/api/admin/media-usage/work/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs +19 -18
- package/dist/astro/routes/api/admin/media-usage/work/retry.mjs.map +1 -1
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +5 -5
- package/dist/astro/routes/api/admin/plugins/_id_/disable.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +9 -66
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +9 -69
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +66 -59
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +6 -6
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +65 -59
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +70 -61
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +87 -63
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +66 -59
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +65 -59
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +85 -63
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +65 -59
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +70 -61
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +90 -66
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +9 -7
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +77 -63
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/verify.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs +67 -61
- package/dist/astro/routes/api/admin/plugins/registry/verify.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +66 -60
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.d.mts +8 -0
- package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs +27 -0
- package/dist/astro/routes/api/admin/scheduled-policy-rejections/_collection_/_id_.mjs.map +1 -0
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +65 -59
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +4 -4
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +65 -59
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +11 -10
- package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
- package/dist/astro/routes/api/admin/users/index.mjs +10 -9
- package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
- package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/complete.mjs +15 -14
- package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/index.mjs +12 -11
- package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +14 -13
- package/dist/astro/routes/api/auth/invite/register-options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/logout.mjs +4 -4
- package/dist/astro/routes/api/auth/magic-link/send.mjs +14 -13
- package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/me.mjs +11 -10
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +10 -9
- package/dist/astro/routes/api/auth/passkey/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/index.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/options.mjs +16 -15
- package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +14 -13
- package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +15 -14
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/verify.mjs +15 -14
- package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/complete.mjs +15 -14
- package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/request.mjs +14 -13
- package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +15 -211
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +18 -17
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +17 -11
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts +10 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs +67 -0
- package/dist/astro/routes/api/content/_collection_/_id_/lock.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.d.mts +8 -0
- package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs +35 -0
- package/dist/astro/routes/api/content/_collection_/_id_/plugin-extensions/_pluginId_/_kind_/_extensionId_.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +16 -15
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts +9 -2
- package/dist/astro/routes/api/content/_collection_/_id_/publish.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +28 -16
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +27 -23
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +27 -23
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +27 -12
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +23 -20
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +25 -12
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +27 -14
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +18 -12
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +11 -10
- package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
- package/dist/astro/routes/api/dashboard.mjs +14 -12
- package/dist/astro/routes/api/dashboard.mjs.map +1 -1
- package/dist/astro/routes/api/dev/emails.mjs +4 -4
- package/dist/astro/routes/api/health.d.mts +8 -0
- package/dist/astro/routes/api/health.d.mts.map +1 -0
- package/dist/astro/routes/api/health.mjs +21 -0
- package/dist/astro/routes/api/health.mjs.map +1 -0
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +25 -23
- package/dist/astro/routes/api/import/probe.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +5 -5
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +13 -11
- package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.mjs +20 -19
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts +12 -10
- package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +15 -14
- package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +14 -13
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +13 -11
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +18 -17
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +25 -23
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +13 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +36 -33
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +17 -9
- package/dist/astro/routes/api/manifest.mjs.map +1 -1
- package/dist/astro/routes/api/mcp.d.mts.map +1 -1
- package/dist/astro/routes/api/mcp.mjs +192 -110
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +15 -14
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/replace.mjs +12 -11
- package/dist/astro/routes/api/media/_id_/replace.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/upload.mjs +8 -8
- package/dist/astro/routes/api/media/_id_/usage.mjs +23 -22
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +22 -21
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/asset/_id_/_filename_.d.mts +8 -0
- package/dist/astro/routes/api/media/asset/_id_/_filename_.d.mts.map +1 -0
- package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs +52 -0
- package/dist/astro/routes/api/media/asset/_id_/_filename_.mjs.map +1 -0
- package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
- package/dist/astro/routes/api/media/folders/_id_.mjs +12 -11
- package/dist/astro/routes/api/media/folders/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/folders/index.mjs +12 -11
- package/dist/astro/routes/api/media/folders/index.mjs.map +1 -1
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +4 -4
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +4 -4
- package/dist/astro/routes/api/media/providers/index.mjs +4 -4
- package/dist/astro/routes/api/media/upload-url.mjs +14 -13
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.mjs +26 -25
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +15 -14
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +15 -14
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +15 -14
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +15 -14
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +15 -14
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +15 -14
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
- package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
- package/dist/astro/routes/api/oauth/register.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
- package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
- package/dist/astro/routes/api/oauth/token.mjs +7 -7
- package/dist/astro/routes/api/openapi.json.mjs +95 -24
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts +2 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +22 -40
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/index.mjs +18 -14
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +18 -14
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +20 -22
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.d.mts.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +19 -19
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.mjs +27 -23
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/translations.mjs +21 -18
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/relations/index.mjs +27 -23
- package/dist/astro/routes/api/relations/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -5
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +65 -59
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +65 -59
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +65 -59
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +65 -59
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +65 -59
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/reorder.mjs +65 -59
- package/dist/astro/routes/api/schema/collections/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +16 -14
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +65 -59
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +65 -59
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +16 -14
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +17 -14
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +16 -14
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +10 -9
- package/dist/astro/routes/api/search/stats.mjs.map +1 -1
- package/dist/astro/routes/api/search/suggest.mjs +15 -13
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +15 -13
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +15 -13
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +9 -8
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +8 -7
- package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/export.mjs +9 -8
- package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/index.mjs +10 -9
- package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +22 -20
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +16 -15
- package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin.mjs +15 -14
- package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +42 -38
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +43 -38
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +5 -5
- package/dist/astro/routes/api/snapshot.mjs +11 -10
- package/dist/astro/routes/api/snapshot.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs +23 -21
- package/dist/astro/routes/api/taxonomies/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +23 -21
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +23 -21
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +23 -21
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs +22 -20
- package/dist/astro/routes/api/taxonomies/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_.mjs +23 -21
- package/dist/astro/routes/api/taxonomies/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +23 -21
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +8 -8
- package/dist/astro/routes/api/typegen.mjs +6 -6
- package/dist/astro/routes/api/visual-editing/action-token.d.mts +8 -0
- package/dist/astro/routes/api/visual-editing/action-token.d.mts.map +1 -0
- package/dist/astro/routes/api/visual-editing/action-token.mjs +25 -0
- package/dist/astro/routes/api/visual-editing/action-token.mjs.map +1 -0
- package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.d.mts +8 -0
- package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.d.mts.map +1 -0
- package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs +37 -0
- package/dist/astro/routes/api/visual-editing/content/_collection_/_id_/publish.mjs.map +1 -0
- package/dist/astro/routes/api/visual-editing/toolbar-labels.d.mts +8 -0
- package/dist/astro/routes/api/visual-editing/toolbar-labels.d.mts.map +1 -0
- package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs +20 -0
- package/dist/astro/routes/api/visual-editing/toolbar-labels.mjs.map +1 -0
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +12 -11
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +16 -15
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +16 -15
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/index.mjs +16 -15
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +4 -4
- package/dist/astro/routes/robots.txt.mjs +13 -12
- package/dist/astro/routes/robots.txt.mjs.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.d.mts.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +24 -19
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +14 -13
- package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
- package/dist/astro/types.d.mts +79 -26
- package/dist/astro/types.d.mts.map +1 -1
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/authoritative-records-DbqshfKD.mjs +5172 -0
- package/dist/authoritative-records-DbqshfKD.mjs.map +1 -0
- package/dist/authorize-BXpfMpp0.mjs +40 -0
- package/dist/authorize-BXpfMpp0.mjs.map +1 -0
- package/dist/backup-BsPQdwnS.mjs +246 -0
- package/dist/backup-BsPQdwnS.mjs.map +1 -0
- package/dist/base64-DvnNgP7e.mjs +63 -0
- package/dist/base64-DvnNgP7e.mjs.map +1 -0
- package/dist/byline-Doh-wt99.mjs +906 -0
- package/dist/byline-Doh-wt99.mjs.map +1 -0
- package/dist/byline-fields-CsrdvaLV.mjs +123 -0
- package/dist/byline-fields-CsrdvaLV.mjs.map +1 -0
- package/dist/byline-registry-D6lWzXk6.mjs +406 -0
- package/dist/byline-registry-D6lWzXk6.mjs.map +1 -0
- package/dist/bylines-Cop0hkoy.mjs +214 -0
- package/dist/bylines-Cop0hkoy.mjs.map +1 -0
- package/dist/bylines-kpBzHPr8.mjs +232 -0
- package/dist/bylines-kpBzHPr8.mjs.map +1 -0
- package/dist/cache-B0pOlXdM.mjs +108 -0
- package/dist/cache-B0pOlXdM.mjs.map +1 -0
- package/dist/capture-triggers-gxQxnxrJ.mjs +362 -0
- package/dist/capture-triggers-gxQxnxrJ.mjs.map +1 -0
- package/dist/challenge-store-CkRdSdd8.mjs +51 -0
- package/dist/challenge-store-CkRdSdd8.mjs.map +1 -0
- package/dist/checksum-Bsi2D9M1.mjs +162 -0
- package/dist/checksum-Bsi2D9M1.mjs.map +1 -0
- package/dist/chrome-tags-D7LGB91U.mjs +24 -0
- package/dist/chrome-tags-D7LGB91U.mjs.map +1 -0
- package/dist/chunks-BmWyou79.mjs +25 -0
- package/dist/chunks-BmWyou79.mjs.map +1 -0
- package/dist/cli/index.mjs +921 -106
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +17 -7
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +17 -12
- package/dist/client/index.mjs.map +1 -1
- package/dist/collection-deletion-C3Xixmkx.mjs +436 -0
- package/dist/collection-deletion-C3Xixmkx.mjs.map +1 -0
- package/dist/collection-slugs-cache-D9auiKmI.mjs +85 -0
- package/dist/collection-slugs-cache-D9auiKmI.mjs.map +1 -0
- package/dist/comment-DcT8qdPK.mjs +313 -0
- package/dist/comment-DcT8qdPK.mjs.map +1 -0
- package/dist/comment-reaction-DY5-y8Y5.mjs +85 -0
- package/dist/comment-reaction-DY5-y8Y5.mjs.map +1 -0
- package/dist/comments-B67VRNGw.mjs +204 -0
- package/dist/comments-B67VRNGw.mjs.map +1 -0
- package/dist/comments-BVzzt6x5.mjs +99 -0
- package/dist/comments-BVzzt6x5.mjs.map +1 -0
- package/dist/components-DIl9Qzh6.mjs +108 -0
- package/dist/components-DIl9Qzh6.mjs.map +1 -0
- package/dist/config-B2acLeC5.mjs +242 -0
- package/dist/config-B2acLeC5.mjs.map +1 -0
- package/dist/config-CGVeT8Hc.mjs +73 -0
- package/dist/config-CGVeT8Hc.mjs.map +1 -0
- package/dist/config-D3HhLON3.d.mts +39 -0
- package/dist/config-D3HhLON3.d.mts.map +1 -0
- package/dist/config-DS7e4EZ9.d.mts +6387 -0
- package/dist/config-DS7e4EZ9.d.mts.map +1 -0
- package/dist/content-DZ3B5qtA.mjs +2216 -0
- package/dist/content-DZ3B5qtA.mjs.map +1 -0
- package/dist/content-list-query-CbPdzsna.d.mts +26 -0
- package/dist/content-list-query-CbPdzsna.d.mts.map +1 -0
- package/dist/content-policy-CM4skrNi.mjs +46 -0
- package/dist/content-policy-CM4skrNi.mjs.map +1 -0
- package/dist/content-refresh-BHLHJgyt.mjs +3599 -0
- package/dist/content-refresh-BHLHJgyt.mjs.map +1 -0
- package/dist/content-repair-BVll5WNl.mjs +440 -0
- package/dist/content-repair-BVll5WNl.mjs.map +1 -0
- package/dist/context-B195kjqZ.mjs +1835 -0
- package/dist/context-B195kjqZ.mjs.map +1 -0
- package/dist/cron-BcR3RN4K.mjs +282 -0
- package/dist/cron-BcR3RN4K.mjs.map +1 -0
- package/dist/dashboard-CZD4G7k_.mjs +151 -0
- package/dist/dashboard-CZD4G7k_.mjs.map +1 -0
- package/dist/database/migration-lock.d.mts +37 -0
- package/dist/database/migration-lock.d.mts.map +1 -0
- package/dist/database/migration-lock.mjs +76 -0
- package/dist/database/migration-lock.mjs.map +1 -0
- package/dist/database/pg-migration-lock.d.mts +1 -1
- package/dist/database/pg-migration-lock.mjs +1 -1
- package/dist/database/pg-migration-lock.mjs.map +1 -1
- package/dist/datetime-normalization-PeiEdcRY.mjs +187 -0
- package/dist/datetime-normalization-PeiEdcRY.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +4 -3
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql-migrations.d.mts +1 -1
- package/dist/db/libsql-migrations.mjs +7 -6
- package/dist/db/libsql-migrations.mjs.map +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres-migrations.d.mts +1 -1
- package/dist/db/postgres-migrations.mjs +7 -6
- package/dist/db/postgres-migrations.mjs.map +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite-migrations.d.mts +1 -1
- package/dist/db/sqlite-migrations.mjs +7 -6
- package/dist/db/sqlite-migrations.mjs.map +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/db/sqlite.mjs +1 -1
- package/dist/db-errors-CBD5yMro.mjs +55 -0
- package/dist/db-errors-CBD5yMro.mjs.map +1 -0
- package/dist/default-BtlxWgh9.mjs +81 -0
- package/dist/default-BtlxWgh9.mjs.map +1 -0
- package/dist/deferred-tasks-Ba9fphlE.d.mts +9 -0
- package/dist/deferred-tasks-Ba9fphlE.d.mts.map +1 -0
- package/dist/dev-typegen-CZaPLl3V.mjs +29 -0
- package/dist/dev-typegen-CZaPLl3V.mjs.map +1 -0
- package/dist/device-flow-3E5l0fpH.mjs +466 -0
- package/dist/device-flow-3E5l0fpH.mjs.map +1 -0
- package/dist/dialect-helpers-CtYdsX4W.mjs +307 -0
- package/dist/dialect-helpers-CtYdsX4W.mjs.map +1 -0
- package/dist/direct-executor-ZI8E01Yt.mjs +104 -0
- package/dist/direct-executor-ZI8E01Yt.mjs.map +1 -0
- package/dist/dist-2hDLsLeq.mjs +810 -0
- package/dist/dist-2hDLsLeq.mjs.map +1 -0
- package/dist/email-console-gc-E3Eqj.mjs +50 -0
- package/dist/email-console-gc-E3Eqj.mjs.map +1 -0
- package/dist/emdash-runtime-DZGinqTL.mjs +4041 -0
- package/dist/emdash-runtime-DZGinqTL.mjs.map +1 -0
- package/dist/enrich-C2Mk0lwE.mjs +194 -0
- package/dist/enrich-C2Mk0lwE.mjs.map +1 -0
- package/dist/entry-lock-D3C99MXS.mjs +1520 -0
- package/dist/entry-lock-D3C99MXS.mjs.map +1 -0
- package/dist/entry-lock-D9rnj2Lu.mjs +163 -0
- package/dist/entry-lock-D9rnj2Lu.mjs.map +1 -0
- package/dist/entry-lock-DX7QkqEg.d.mts +3503 -0
- package/dist/entry-lock-DX7QkqEg.d.mts.map +1 -0
- package/dist/entry-locks-CO_KaoU5.mjs +167 -0
- package/dist/entry-locks-CO_KaoU5.mjs.map +1 -0
- package/dist/error-CCTCskie.mjs +90 -0
- package/dist/error-CCTCskie.mjs.map +1 -0
- package/dist/errors-W3PA8HqB.mjs +447 -0
- package/dist/errors-W3PA8HqB.mjs.map +1 -0
- package/dist/escape-DN4Qmjsl.mjs +9 -0
- package/dist/escape-DN4Qmjsl.mjs.map +1 -0
- package/dist/field-defs-cache-B337z8UJ.mjs +77 -0
- package/dist/field-defs-cache-B337z8UJ.mjs.map +1 -0
- package/dist/focal-point-Gr34o-4o.mjs +23 -0
- package/dist/focal-point-Gr34o-4o.mjs.map +1 -0
- package/dist/fts-manager-DMb0sbIQ.mjs +413 -0
- package/dist/fts-manager-DMb0sbIQ.mjs.map +1 -0
- package/dist/hash-CLVFzWvx.mjs +37 -0
- package/dist/hash-CLVFzWvx.mjs.map +1 -0
- package/dist/hook-result-KY1jq21o.d.mts +31 -0
- package/dist/hook-result-KY1jq21o.d.mts.map +1 -0
- package/dist/hreflang-BgS2FqhH.d.mts +50 -0
- package/dist/hreflang-BgS2FqhH.d.mts.map +1 -0
- package/dist/hreflang-CrJwqoeb.mjs +105 -0
- package/dist/hreflang-CrJwqoeb.mjs.map +1 -0
- package/dist/http-route-dispatch-DAKlanXb.mjs +339 -0
- package/dist/http-route-dispatch-DAKlanXb.mjs.map +1 -0
- package/dist/identity-DRGSHEEr.mjs +35 -0
- package/dist/identity-DRGSHEEr.mjs.map +1 -0
- package/dist/import-DFr5B_hC.mjs +2020 -0
- package/dist/import-DFr5B_hC.mjs.map +1 -0
- package/dist/index-CDwKDkTq.d.mts +623 -0
- package/dist/index-CDwKDkTq.d.mts.map +1 -0
- package/dist/index.d.mts +27 -22
- package/dist/index.mjs +101 -86
- package/dist/init-lock-4eRRB4Le.mjs +56 -0
- package/dist/init-lock-4eRRB4Le.mjs.map +1 -0
- package/dist/install-finalization-5Os-QZ-2.mjs +58 -0
- package/dist/install-finalization-5Os-QZ-2.mjs.map +1 -0
- package/dist/lifecycle-7e-Lt_kX.mjs +25 -0
- package/dist/lifecycle-7e-Lt_kX.mjs.map +1 -0
- package/dist/load-Cu5bvCZh.mjs +28 -0
- package/dist/load-Cu5bvCZh.mjs.map +1 -0
- package/dist/loader-t4TxaFiQ.mjs +1004 -0
- package/dist/loader-t4TxaFiQ.mjs.map +1 -0
- package/dist/manifest-builder-D31UoJCu.mjs +189 -0
- package/dist/manifest-builder-D31UoJCu.mjs.map +1 -0
- package/dist/manifest-schema-Bkh8SeHd.mjs +491 -0
- package/dist/manifest-schema-Bkh8SeHd.mjs.map +1 -0
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +4 -4
- package/dist/media/local-runtime.d.mts +14 -12
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +12 -11
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/media-TBlKCwo7.mjs +334 -0
- package/dist/media-TBlKCwo7.mjs.map +1 -0
- package/dist/media-allowlist-s60eAIf6.mjs +44 -0
- package/dist/media-allowlist-s60eAIf6.mjs.map +1 -0
- package/dist/media-folders-ClIRLUQv.mjs +210 -0
- package/dist/media-folders-ClIRLUQv.mjs.map +1 -0
- package/dist/media-url-DY_ijO3B.mjs +43 -0
- package/dist/media-url-DY_ijO3B.mjs.map +1 -0
- package/dist/media-usage-C4NolTpQ.mjs +1833 -0
- package/dist/media-usage-C4NolTpQ.mjs.map +1 -0
- package/dist/media-usage-activation-CAhmb14O.mjs +78 -0
- package/dist/media-usage-activation-CAhmb14O.mjs.map +1 -0
- package/dist/media-usage-work-Cu5DqewW.mjs +586 -0
- package/dist/media-usage-work-Cu5DqewW.mjs.map +1 -0
- package/dist/media-usage-work-DJr3rOEN.mjs +152 -0
- package/dist/media-usage-work-DJr3rOEN.mjs.map +1 -0
- package/dist/media-usage-write-fence-DW5oHT7q.mjs +42 -0
- package/dist/media-usage-write-fence-DW5oHT7q.mjs.map +1 -0
- package/dist/menus-DbgU9z5Q.mjs +3732 -0
- package/dist/menus-DbgU9z5Q.mjs.map +1 -0
- package/dist/menus-Wy8m5NcH.mjs +753 -0
- package/dist/menus-Wy8m5NcH.mjs.map +1 -0
- package/dist/migrations/index.d.mts +2 -2
- package/dist/migrations/index.d.mts.map +1 -1
- package/dist/migrations/index.mjs +6 -5
- package/dist/mime-CCYRC4r1.mjs +36 -0
- package/dist/mime-CCYRC4r1.mjs.map +1 -0
- package/dist/mode-CkmOhFqj.mjs +23 -0
- package/dist/mode-CkmOhFqj.mjs.map +1 -0
- package/dist/node-sqlite-compat-vpVaILnb.mjs +46 -0
- package/dist/node-sqlite-compat-vpVaILnb.mjs.map +1 -0
- package/dist/normalize-dChXQjwS.mjs +191 -0
- package/dist/normalize-dChXQjwS.mjs.map +1 -0
- package/dist/oauth-authorization-DZ-R-hmx.mjs +274 -0
- package/dist/oauth-authorization-DZ-R-hmx.mjs.map +1 -0
- package/dist/oauth-clients-BMPA8vjl.mjs +266 -0
- package/dist/oauth-clients-BMPA8vjl.mjs.map +1 -0
- package/dist/oauth-state-store-0gIdb48-.mjs +50 -0
- package/dist/oauth-state-store-0gIdb48-.mjs.map +1 -0
- package/dist/oauth-user-lookup-ChVW4UWu.mjs +26 -0
- package/dist/oauth-user-lookup-ChVW4UWu.mjs.map +1 -0
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/object-cache-DlSVbn5Y.mjs +534 -0
- package/dist/object-cache-DlSVbn5Y.mjs.map +1 -0
- package/dist/options-D5WcorD5.mjs +200 -0
- package/dist/options-D5WcorD5.mjs.map +1 -0
- package/dist/options-DAknChnw.d.mts +77 -0
- package/dist/options-DAknChnw.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.d.mts.map +1 -1
- package/dist/page/index.mjs +13 -0
- package/dist/page/index.mjs.map +1 -1
- package/dist/parse-Cr379Av9.mjs +81 -0
- package/dist/parse-Cr379Av9.mjs.map +1 -0
- package/dist/parse-tj9XLNO_.d.mts +165 -0
- package/dist/parse-tj9XLNO_.d.mts.map +1 -0
- package/dist/passkey-config-BD-wMaCf.mjs +46 -0
- package/dist/passkey-config-BD-wMaCf.mjs.map +1 -0
- package/dist/patterns-Do3iqi7N.mjs +145 -0
- package/dist/patterns-Do3iqi7N.mjs.map +1 -0
- package/dist/placeholder-CubPFn_L.d.mts +306 -0
- package/dist/placeholder-CubPFn_L.d.mts.map +1 -0
- package/dist/plugin-test-runtime.d.mts +97 -0
- package/dist/plugin-test-runtime.d.mts.map +1 -0
- package/dist/plugin-test-runtime.mjs +105 -0
- package/dist/plugin-types.d.mts +53 -15
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-types.mjs +18 -1
- package/dist/plugin-types.mjs.map +1 -0
- package/dist/plugin-utils.d.mts +12 -10
- package/dist/plugin-utils.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +12 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +18 -13
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/plugins/host.d.mts +7 -0
- package/dist/plugins/host.mjs +45 -0
- package/dist/plugins/http-wire.d.mts +25 -0
- package/dist/plugins/http-wire.d.mts.map +1 -0
- package/dist/plugins/http-wire.mjs +148 -0
- package/dist/plugins/http-wire.mjs.map +1 -0
- package/dist/plugins/secret-redactor.d.mts +9 -0
- package/dist/plugins/secret-redactor.d.mts.map +1 -0
- package/dist/plugins/secret-redactor.mjs +51 -0
- package/dist/plugins/secret-redactor.mjs.map +1 -0
- package/dist/plugins-DHurtdXQ.mjs +277 -0
- package/dist/plugins-DHurtdXQ.mjs.map +1 -0
- package/dist/policy-lyZnjpwz.mjs +45 -0
- package/dist/policy-lyZnjpwz.mjs.map +1 -0
- package/dist/portable-text-oAwodbPS.mjs +286 -0
- package/dist/portable-text-oAwodbPS.mjs.map +1 -0
- package/dist/preview-Cup2bj8c.mjs +107 -0
- package/dist/preview-Cup2bj8c.mjs.map +1 -0
- package/dist/protocol-C1CNiKX4.d.mts +61 -0
- package/dist/protocol-C1CNiKX4.d.mts.map +1 -0
- package/dist/public-submission-Cs-pFMQK.mjs +245 -0
- package/dist/public-submission-Cs-pFMQK.mjs.map +1 -0
- package/dist/public-url-BWVHsfQv.mjs +101 -0
- package/dist/public-url-BWVHsfQv.mjs.map +1 -0
- package/dist/query-D-lxiOgn.mjs +890 -0
- package/dist/query-D-lxiOgn.mjs.map +1 -0
- package/dist/query-D7kHKOws.mjs +41 -0
- package/dist/query-D7kHKOws.mjs.map +1 -0
- package/dist/rate-limit-CqJn-w4h.mjs +120 -0
- package/dist/rate-limit-CqJn-w4h.mjs.map +1 -0
- package/dist/redirect-BrChFPIu.mjs +17 -0
- package/dist/redirect-BrChFPIu.mjs.map +1 -0
- package/dist/redirect-D2Yo-b6S.mjs +415 -0
- package/dist/redirect-D2Yo-b6S.mjs.map +1 -0
- package/dist/redirects-BCiTaIQ-.mjs +146 -0
- package/dist/redirects-BCiTaIQ-.mjs.map +1 -0
- package/dist/redirects-ByItliuu.mjs +644 -0
- package/dist/redirects-ByItliuu.mjs.map +1 -0
- package/dist/registry/testing.d.mts +14 -0
- package/dist/registry/testing.d.mts.map +1 -0
- package/dist/registry/testing.mjs +255 -0
- package/dist/registry/testing.mjs.map +1 -0
- package/dist/registry-CkuPoZs7.mjs +1222 -0
- package/dist/registry-CkuPoZs7.mjs.map +1 -0
- package/dist/relation-XTAtOpJO.mjs +334 -0
- package/dist/relation-XTAtOpJO.mjs.map +1 -0
- package/dist/relations-B4w-G5U9.mjs +309 -0
- package/dist/relations-B4w-G5U9.mjs.map +1 -0
- package/dist/relations-O63JWBRj.mjs +403 -0
- package/dist/relations-O63JWBRj.mjs.map +1 -0
- package/dist/request-cache-DaMhSQdx.mjs +104 -0
- package/dist/request-cache-DaMhSQdx.mjs.map +1 -0
- package/dist/request-context.d.mts +1 -1
- package/dist/request-meta-C8yl_sIs.mjs +141 -0
- package/dist/request-meta-C8yl_sIs.mjs.map +1 -0
- package/dist/resolve-BJIS8wKr.mjs +199 -0
- package/dist/resolve-BJIS8wKr.mjs.map +1 -0
- package/dist/route-wire-D66L2oaZ.mjs +197 -0
- package/dist/route-wire-D66L2oaZ.mjs.map +1 -0
- package/dist/routes-DYsTe-oR.mjs +321 -0
- package/dist/routes-DYsTe-oR.mjs.map +1 -0
- package/dist/runner-3gfxRsJG.d.mts +68 -0
- package/dist/runner-3gfxRsJG.d.mts.map +1 -0
- package/dist/runner-ClrleR8A.mjs +5502 -0
- package/dist/runner-ClrleR8A.mjs.map +1 -0
- package/dist/runtime.d.mts +13 -11
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +6 -5
- package/dist/runtime.mjs.map +1 -1
- package/dist/schema-CPhPM9Do.mjs +420 -0
- package/dist/schema-CPhPM9Do.mjs.map +1 -0
- package/dist/schema-DEERRrKS.mjs +9 -0
- package/dist/schema-DEERRrKS.mjs.map +1 -0
- package/dist/scopes-Bn8_rCSt.mjs +27 -0
- package/dist/scopes-Bn8_rCSt.mjs.map +1 -0
- package/dist/search-lami_Ota.mjs +448 -0
- package/dist/search-lami_Ota.mjs.map +1 -0
- package/dist/secrets-DNgVgz_e.mjs +341 -0
- package/dist/secrets-DNgVgz_e.mjs.map +1 -0
- package/dist/sections-BIpd4Cxf.mjs +346 -0
- package/dist/sections-BIpd4Cxf.mjs.map +1 -0
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +35 -31
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +27 -26
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo-BtU70b7l.mjs +114 -0
- package/dist/seo-BtU70b7l.mjs.map +1 -0
- package/dist/seo-_4qmazxz.mjs +133 -0
- package/dist/seo-_4qmazxz.mjs.map +1 -0
- package/dist/service-Bpy5iTX0.mjs +150 -0
- package/dist/service-Bpy5iTX0.mjs.map +1 -0
- package/dist/session-user-BQeS2Mrb.mjs +51 -0
- package/dist/session-user-BQeS2Mrb.mjs.map +1 -0
- package/dist/settings-DmroR53o.mjs +420 -0
- package/dist/settings-DmroR53o.mjs.map +1 -0
- package/dist/settings-g2F2a3Ub.mjs +51 -0
- package/dist/settings-g2F2a3Ub.mjs.map +1 -0
- package/dist/setup-complete-BrZaXpVV.mjs +26 -0
- package/dist/setup-complete-BrZaXpVV.mjs.map +1 -0
- package/dist/setup-nonce-Cb9-884O.mjs +25 -0
- package/dist/setup-nonce-Cb9-884O.mjs.map +1 -0
- package/dist/single-flight-cache-B5O2qhO1.mjs +104 -0
- package/dist/single-flight-cache-B5O2qhO1.mjs.map +1 -0
- package/dist/site-url-DjhYCaep.mjs +16 -0
- package/dist/site-url-DjhYCaep.mjs.map +1 -0
- package/dist/slugify-T5GHH42D.mjs +17 -0
- package/dist/slugify-T5GHH42D.mjs.map +1 -0
- package/dist/snapshot-C32Xuv3o.mjs +233 -0
- package/dist/snapshot-C32Xuv3o.mjs.map +1 -0
- package/dist/ssrf-Co1GGFZz.mjs +406 -0
- package/dist/ssrf-Co1GGFZz.mjs.map +1 -0
- package/dist/state-C7gCoiHr.mjs +153 -0
- package/dist/state-C7gCoiHr.mjs.map +1 -0
- package/dist/status-DLoBmcDz.mjs +30 -0
- package/dist/status-DLoBmcDz.mjs.map +1 -0
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/storage-query-CPctdMKX.d.mts +1519 -0
- package/dist/storage-query-CPctdMKX.d.mts.map +1 -0
- package/dist/target-CUKlGrXb.mjs +27 -0
- package/dist/target-CUKlGrXb.mjs.map +1 -0
- package/dist/taxonomies-BpqpXJUE.mjs +707 -0
- package/dist/taxonomies-BpqpXJUE.mjs.map +1 -0
- package/dist/taxonomies-ClCo4IGO.mjs +899 -0
- package/dist/taxonomies-ClCo4IGO.mjs.map +1 -0
- package/dist/taxonomy-Dj1vpw5E.mjs +508 -0
- package/dist/taxonomy-Dj1vpw5E.mjs.map +1 -0
- package/dist/tokens-Ns02GAma.mjs +171 -0
- package/dist/tokens-Ns02GAma.mjs.map +1 -0
- package/dist/transaction-BcJO4Tmc.mjs +29 -0
- package/dist/transaction-BcJO4Tmc.mjs.map +1 -0
- package/dist/transport-B8P1xsqk.mjs +136 -0
- package/dist/transport-B8P1xsqk.mjs.map +1 -0
- package/dist/transport-BLHZZcD_.d.mts +42 -0
- package/dist/transport-BLHZZcD_.d.mts.map +1 -0
- package/dist/trusted-proxy-Cg7SuD15.mjs +51 -0
- package/dist/trusted-proxy-Cg7SuD15.mjs.map +1 -0
- package/dist/turnstile-DWCSh_Qc.mjs +53 -0
- package/dist/turnstile-DWCSh_Qc.mjs.map +1 -0
- package/dist/types-B3RkqvDW.mjs +156 -0
- package/dist/types-B3RkqvDW.mjs.map +1 -0
- package/dist/types-BkUg2yHx.mjs +92 -0
- package/dist/types-BkUg2yHx.mjs.map +1 -0
- package/dist/types-BtuppOTV.mjs +16 -0
- package/dist/types-BtuppOTV.mjs.map +1 -0
- package/dist/types-CCR3ivXE.d.mts +363 -0
- package/dist/types-CCR3ivXE.d.mts.map +1 -0
- package/dist/types-CSHgU_-_.mjs +18 -0
- package/dist/types-CSHgU_-_.mjs.map +1 -0
- package/dist/types-CbwqGOXm.d.mts +766 -0
- package/dist/types-CbwqGOXm.d.mts.map +1 -0
- package/dist/types-D4RGIc2I.d.mts +198 -0
- package/dist/types-D4RGIc2I.d.mts.map +1 -0
- package/dist/types-DEHidMEk.d.mts +1637 -0
- package/dist/types-DEHidMEk.d.mts.map +1 -0
- package/dist/types-DQeU2SR7.d.mts +279 -0
- package/dist/types-DQeU2SR7.d.mts.map +1 -0
- package/dist/types-DxQWoQLA.d.mts +264 -0
- package/dist/types-DxQWoQLA.d.mts.map +1 -0
- package/dist/types-FBBnGZ2Y.d.mts +198 -0
- package/dist/types-FBBnGZ2Y.d.mts.map +1 -0
- package/dist/types-ZCnlropY.mjs +69 -0
- package/dist/types-ZCnlropY.mjs.map +1 -0
- package/dist/types-_Qtyawiy.d.mts +124 -0
- package/dist/types-_Qtyawiy.d.mts.map +1 -0
- package/dist/types-gC6FAoa_.d.mts +75 -0
- package/dist/types-gC6FAoa_.d.mts.map +1 -0
- package/dist/types-k--LneIF.mjs +22 -0
- package/dist/types-k--LneIF.mjs.map +1 -0
- package/dist/upload-attempts-2xdnoKGe.mjs +27 -0
- package/dist/upload-attempts-2xdnoKGe.mjs.map +1 -0
- package/dist/url-pattern-3m3reMzr.mjs +33 -0
- package/dist/url-pattern-3m3reMzr.mjs.map +1 -0
- package/dist/user-DroRntkx.mjs +171 -0
- package/dist/user-DroRntkx.mjs.map +1 -0
- package/dist/utils-CC2oNGV8.mjs +435 -0
- package/dist/utils-CC2oNGV8.mjs.map +1 -0
- package/dist/validate-BCP9HNDn.mjs +384 -0
- package/dist/validate-BCP9HNDn.mjs.map +1 -0
- package/dist/validate-CyQ7I3xF.d.mts +410 -0
- package/dist/validate-CyQ7I3xF.d.mts.map +1 -0
- package/dist/validate-DANX1-Qi.mjs +120 -0
- package/dist/validate-DANX1-Qi.mjs.map +1 -0
- package/dist/validation-DBy6WF94.mjs +216 -0
- package/dist/validation-DBy6WF94.mjs.map +1 -0
- package/dist/version-B57E4Uo7.mjs +7 -0
- package/dist/version-B57E4Uo7.mjs.map +1 -0
- package/dist/widgets-wQ7Xcgq8.mjs +126 -0
- package/dist/widgets-wQ7Xcgq8.mjs.map +1 -0
- package/dist/wxr-taxonomies-DIHfvEDt.mjs +406 -0
- package/dist/wxr-taxonomies-DIHfvEDt.mjs.map +1 -0
- package/dist/wxr-taxonomies-DU2ZSiGc.d.mts +34 -0
- package/dist/wxr-taxonomies-DU2ZSiGc.d.mts.map +1 -0
- package/dist/zod-generator-D_yHIWfs.mjs +329 -0
- package/dist/zod-generator-D_yHIWfs.mjs.map +1 -0
- package/package.json +39 -12
- package/src/api/errors.ts +23 -0
- package/src/api/handlers/backup.ts +11 -5
- package/src/api/handlers/content.ts +226 -85
- package/src/api/handlers/dashboard.ts +31 -1
- package/src/api/handlers/entry-lock.ts +206 -0
- package/src/api/handlers/index.ts +3 -0
- package/src/api/handlers/manifest.ts +5 -6
- package/src/api/handlers/marketplace.ts +126 -34
- package/src/api/handlers/media-upload.ts +31 -4
- package/src/api/handlers/menus.ts +9 -0
- package/src/api/handlers/plugin-settings.ts +35 -3
- package/src/api/handlers/redirects.ts +221 -138
- package/src/api/handlers/registry.ts +75 -29
- package/src/api/handlers/revision.ts +16 -27
- package/src/api/handlers/seo.ts +10 -1
- package/src/api/handlers/snapshot.ts +87 -72
- package/src/api/handlers/taxonomies.ts +79 -5
- package/src/api/handlers/validation.ts +120 -19
- package/src/api/openapi/document.ts +133 -11
- package/src/api/schemas/content.ts +32 -12
- package/src/api/schemas/entry-lock.ts +57 -0
- package/src/api/schemas/index.ts +1 -0
- package/src/api/schemas/schema.ts +10 -1
- package/src/api/schemas/search.ts +4 -0
- package/src/api/types.ts +4 -0
- package/src/astro/integration/index.ts +22 -6
- package/src/astro/integration/routes.ts +89 -0
- package/src/astro/integration/runtime.ts +40 -24
- package/src/astro/integration/virtual-modules.ts +4 -0
- package/src/astro/integration/vite-config.ts +31 -0
- package/src/astro/middleware/auth.ts +25 -4
- package/src/astro/middleware/request-context.ts +28 -10
- package/src/astro/middleware.ts +33 -1
- package/src/astro/prefetch.ts +2 -2
- package/src/astro/routes/api/admin/comments/[id]/status.ts +22 -58
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +2 -15
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +2 -25
- package/src/astro/routes/api/admin/plugins/[id]/uninstall.ts +1 -0
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +23 -4
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +12 -2
- package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +1 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +29 -10
- package/src/astro/routes/api/admin/plugins/registry/artifact.ts +8 -2
- package/src/astro/routes/api/admin/plugins/registry/install.ts +15 -4
- package/src/astro/routes/api/admin/plugins/registry/verify.ts +2 -1
- package/src/astro/routes/api/admin/plugins/updates.ts +6 -1
- package/src/astro/routes/api/admin/scheduled-policy-rejections/[collection]/[id].ts +34 -0
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +4 -259
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +10 -0
- package/src/astro/routes/api/content/[collection]/[id]/lock.ts +133 -0
- package/src/astro/routes/api/content/[collection]/[id]/plugin-extensions/[pluginId]/[kind]/[extensionId].ts +29 -0
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +21 -4
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +30 -1
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +15 -1
- package/src/astro/routes/api/content/[collection]/[id].ts +27 -2
- package/src/astro/routes/api/content/[collection]/index.ts +3 -0
- package/src/astro/routes/api/health.ts +23 -0
- package/src/astro/routes/api/manifest.ts +14 -4
- package/src/astro/routes/api/mcp.ts +2 -1
- package/src/astro/routes/api/media/asset/[id]/[filename].ts +50 -0
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +13 -81
- package/src/astro/routes/api/redirects/[id].ts +0 -3
- package/src/astro/routes/api/redirects/index.ts +0 -2
- package/src/astro/routes/api/search/index.ts +1 -0
- package/src/astro/routes/api/visual-editing/action-token.ts +36 -0
- package/src/astro/routes/api/visual-editing/content/[collection]/[id]/publish.ts +32 -0
- package/src/astro/routes/api/visual-editing/toolbar-labels.ts +16 -0
- package/src/astro/routes/sitemap-[collection].xml.ts +11 -4
- package/src/astro/types.ts +83 -12
- package/src/cli/commands/bundle-utils.ts +19 -19
- package/src/cli/commands/bundle.ts +9 -6
- package/src/cli/commands/content.ts +32 -6
- package/src/cli/commands/doctor.ts +25 -0
- package/src/cli/commands/export-seed.ts +195 -56
- package/src/cli/commands/migrate.ts +71 -23
- package/src/cli/commands/publish.ts +2 -2
- package/src/client/index.ts +34 -7
- package/src/comments/public-submission.ts +246 -0
- package/src/comments/service.ts +59 -12
- package/src/components/EmDashBodyEnd.astro +4 -1
- package/src/components/EmDashBodyStart.astro +4 -1
- package/src/components/EmDashHead.astro +36 -16
- package/src/components/Gallery.astro +18 -4
- package/src/components/InlineEditor.astro +3 -1
- package/src/components/InlinePortableTextEditor.tsx +106 -11
- package/src/components/PortableText.astro +4 -0
- package/src/components/Table.astro +147 -62
- package/src/components/widgets/Archives.astro +6 -5
- package/src/config/errors.ts +13 -0
- package/src/config/secrets.ts +25 -11
- package/src/content/converters/portable-text-to-prosemirror.ts +26 -2
- package/src/content/converters/prosemirror-to-portable-text.ts +35 -6
- package/src/content/converters/types.ts +10 -0
- package/src/content/known-fields.ts +44 -0
- package/src/database/connection.ts +5 -1
- package/src/database/content-datetime.ts +123 -0
- package/src/database/datetime-storage.ts +452 -0
- package/src/database/dialect-helpers.ts +161 -1
- package/src/database/migration-lock.ts +140 -0
- package/src/database/migrations/075_entry_edit_locks.ts +44 -0
- package/src/database/migrations/076_collection_nav_group.ts +22 -0
- package/src/database/migrations/077_plugin_storage_revisions.ts +89 -0
- package/src/database/migrations/078_menu_item_translation_groups.ts +15 -0
- package/src/database/migrations/079_datetime_normalization.ts +13 -0
- package/src/database/migrations/080_content_translation_locale_unique.ts +88 -0
- package/src/database/migrations/081_redirect_write_guards.ts +257 -0
- package/src/database/migrations/082_taxonomy_translation_locale_unique.ts +49 -0
- package/src/database/migrations/runner.ts +63 -15
- package/src/database/pg-migration-lock.ts +2 -2
- package/src/database/repositories/byline.ts +9 -0
- package/src/database/repositories/comment.ts +86 -0
- package/src/database/repositories/content.ts +560 -69
- package/src/database/repositories/entry-locks.ts +257 -0
- package/src/database/repositories/media.ts +35 -4
- package/src/database/repositories/menu.ts +1 -0
- package/src/database/repositories/options.ts +113 -7
- package/src/database/repositories/plugin-storage.ts +159 -0
- package/src/database/repositories/redirect.ts +262 -56
- package/src/database/repositories/revision.ts +116 -17
- package/src/database/repositories/taxonomy.ts +42 -0
- package/src/database/repositories/types.ts +5 -0
- package/src/database/types.ts +26 -1
- package/src/datetime-normalization.ts +311 -0
- package/src/db/node-sqlite-compat.ts +3 -2
- package/src/emdash-runtime.ts +1994 -424
- package/src/fields/image.ts +2 -0
- package/src/i18n/config.ts +6 -6
- package/src/i18n/resolve.ts +98 -15
- package/src/index.ts +101 -0
- package/src/loader.ts +49 -4
- package/src/mcp/server.ts +216 -68
- package/src/media/responsive.ts +23 -0
- package/src/media/usage/content-refresh.ts +2 -1
- package/src/media/usage/extractor.ts +50 -15
- package/src/media/usage/types.ts +1 -1
- package/src/menus/index.ts +64 -35
- package/src/migrations/direct-executor.ts +40 -2
- package/src/migrations/index.ts +1 -0
- package/src/migrations/protocol.ts +11 -1
- package/src/page/seo-contributions.ts +78 -1
- package/src/page/seo-panel.ts +47 -0
- package/src/plugin-test-runtime.ts +17 -0
- package/src/plugin-types.ts +128 -21
- package/src/plugins/adapt-sandbox-entry.ts +34 -27
- package/src/plugins/conditional-storage.ts +30 -0
- package/src/plugins/content-access.ts +170 -0
- package/src/plugins/content-policy.ts +74 -0
- package/src/plugins/context.ts +790 -166
- package/src/plugins/cron.ts +18 -10
- package/src/plugins/define-plugin.ts +55 -54
- package/src/plugins/editor-draft.ts +257 -0
- package/src/plugins/hooks.ts +136 -3
- package/src/plugins/host.ts +29 -0
- package/src/plugins/http-route-dispatch.ts +389 -0
- package/src/plugins/http-wire.ts +180 -0
- package/src/plugins/index.ts +97 -3
- package/src/plugins/install-finalization.ts +77 -0
- package/src/plugins/lifecycle.ts +47 -0
- package/src/plugins/manager.ts +5 -2
- package/src/plugins/manifest-schema.ts +314 -58
- package/src/plugins/media.ts +166 -0
- package/src/plugins/request-meta.ts +12 -2
- package/src/plugins/route-wire.ts +304 -0
- package/src/plugins/routes.ts +38 -5
- package/src/plugins/sandbox/index.ts +4 -0
- package/src/plugins/sandbox/proxy.ts +129 -0
- package/src/plugins/sandbox/types.ts +83 -7
- package/src/plugins/secret-redactor.ts +65 -0
- package/src/plugins/settings.ts +303 -0
- package/src/plugins/state.ts +26 -0
- package/src/plugins/storage-query.ts +45 -0
- package/src/plugins/storage-update.ts +96 -0
- package/src/plugins/types.ts +602 -15
- package/src/query.ts +84 -4
- package/src/registry/authoritative-records.ts +26 -0
- package/src/registry/config.ts +182 -31
- package/src/registry/testing.ts +100 -0
- package/src/registry/types.ts +12 -70
- package/src/scheduled-publish.ts +70 -3
- package/src/schema/collection-slugs-cache.ts +157 -0
- package/src/schema/index.ts +1 -0
- package/src/schema/registry.ts +64 -1
- package/src/schema/types.ts +32 -6
- package/src/schema/zod-generator.ts +5 -13
- package/src/search/fts-manager.ts +3 -3
- package/src/search/query.ts +32 -5
- package/src/search/types.ts +8 -0
- package/src/security/ssrf.ts +167 -141
- package/src/seed/apply.ts +41 -3
- package/src/seed/types.ts +13 -3
- package/src/seed/validate.ts +18 -1
- package/src/seo/hreflang.ts +10 -6
- package/src/seo/index.ts +5 -10
- package/src/seo/media-url.ts +26 -0
- package/src/settings/index.ts +53 -11
- package/src/taxonomies/term-counts.ts +22 -5
- package/src/visual-editing/action-token.ts +31 -0
- package/src/visual-editing/toolbar-bootstrap.ts +31 -6
- package/src/visual-editing/toolbar.ts +103 -12
- package/src/widgets/archives.ts +10 -9
- package/src/widgets/index.ts +11 -1
- package/dist/activation-K0kGBWuJ.mjs +0 -382
- package/dist/activation-K0kGBWuJ.mjs.map +0 -1
- package/dist/adapters-BDQwg236.d.mts +0 -171
- package/dist/adapters-BDQwg236.d.mts.map +0 -1
- package/dist/after-CBU2vkoO.mjs +0 -96
- package/dist/after-CBU2vkoO.mjs.map +0 -1
- package/dist/allowed-origins-BGglilcs.mjs +0 -116
- package/dist/allowed-origins-BGglilcs.mjs.map +0 -1
- package/dist/api-Dz6rgoa3.mjs +0 -10040
- package/dist/api-Dz6rgoa3.mjs.map +0 -1
- package/dist/api-tokens-BSsQACNe.mjs +0 -163
- package/dist/api-tokens-BSsQACNe.mjs.map +0 -1
- package/dist/apply-B4SIOxR1.mjs +0 -980
- package/dist/apply-B4SIOxR1.mjs.map +0 -1
- package/dist/authorize-Bkf_UHhD.mjs +0 -40
- package/dist/authorize-Bkf_UHhD.mjs.map +0 -1
- package/dist/backup-rwVAl9NI.mjs +0 -241
- package/dist/backup-rwVAl9NI.mjs.map +0 -1
- package/dist/base64-CvLhUKQv.mjs +0 -63
- package/dist/base64-CvLhUKQv.mjs.map +0 -1
- package/dist/bundle-C8S2Zl6U.mjs +0 -663
- package/dist/bundle-C8S2Zl6U.mjs.map +0 -1
- package/dist/byline-DuhF7NWl.mjs +0 -902
- package/dist/byline-DuhF7NWl.mjs.map +0 -1
- package/dist/byline-fields-BovY4KYM.mjs +0 -123
- package/dist/byline-fields-BovY4KYM.mjs.map +0 -1
- package/dist/byline-registry-Bpu9-MVs.mjs +0 -406
- package/dist/byline-registry-Bpu9-MVs.mjs.map +0 -1
- package/dist/bylines-CJ5nd6Lw.mjs +0 -232
- package/dist/bylines-CJ5nd6Lw.mjs.map +0 -1
- package/dist/bylines-RwBAeOF1.mjs +0 -214
- package/dist/bylines-RwBAeOF1.mjs.map +0 -1
- package/dist/cache-BF5Kvn59.mjs +0 -108
- package/dist/cache-BF5Kvn59.mjs.map +0 -1
- package/dist/capture-triggers-CNW1q3HK.mjs +0 -362
- package/dist/capture-triggers-CNW1q3HK.mjs.map +0 -1
- package/dist/challenge-store-DQN_Yrck.mjs +0 -51
- package/dist/challenge-store-DQN_Yrck.mjs.map +0 -1
- package/dist/chrome-tags-D8fiZG94.mjs +0 -24
- package/dist/chrome-tags-D8fiZG94.mjs.map +0 -1
- package/dist/chunks-C4szrD8o.mjs +0 -25
- package/dist/chunks-C4szrD8o.mjs.map +0 -1
- package/dist/collection-deletion-Bj07NHbj.mjs +0 -436
- package/dist/collection-deletion-Bj07NHbj.mjs.map +0 -1
- package/dist/comment-reaction-BhrvSHml.mjs +0 -85
- package/dist/comment-reaction-BhrvSHml.mjs.map +0 -1
- package/dist/comment-vxOzWbZN.mjs +0 -255
- package/dist/comment-vxOzWbZN.mjs.map +0 -1
- package/dist/comments-Ct4ensnf.mjs +0 -204
- package/dist/comments-Ct4ensnf.mjs.map +0 -1
- package/dist/components-DJbo1z0S.mjs +0 -108
- package/dist/components-DJbo1z0S.mjs.map +0 -1
- package/dist/config-B9eZ340f.d.mts +0 -34
- package/dist/config-B9eZ340f.d.mts.map +0 -1
- package/dist/config-C3EBstHi.mjs +0 -72
- package/dist/config-C3EBstHi.mjs.map +0 -1
- package/dist/config-it29yDLA.mjs +0 -1163
- package/dist/config-it29yDLA.mjs.map +0 -1
- package/dist/content-DjvM0T92.mjs +0 -1725
- package/dist/content-DjvM0T92.mjs.map +0 -1
- package/dist/content-list-query-Btqd4uV2.d.mts +0 -26
- package/dist/content-list-query-Btqd4uV2.d.mts.map +0 -1
- package/dist/content-refresh-Bwp-8yGy.mjs +0 -3588
- package/dist/content-refresh-Bwp-8yGy.mjs.map +0 -1
- package/dist/content-repair-Czdp7jz5.mjs +0 -440
- package/dist/content-repair-Czdp7jz5.mjs.map +0 -1
- package/dist/context-CX6gxOLW.mjs +0 -1068
- package/dist/context-CX6gxOLW.mjs.map +0 -1
- package/dist/cron-C6o7VppJ.mjs +0 -277
- package/dist/cron-C6o7VppJ.mjs.map +0 -1
- package/dist/dashboard-C2kTeeRI.mjs +0 -140
- package/dist/dashboard-C2kTeeRI.mjs.map +0 -1
- package/dist/db-errors-Cl-sKYTm.mjs +0 -55
- package/dist/db-errors-Cl-sKYTm.mjs.map +0 -1
- package/dist/default-Clra32mw.mjs +0 -81
- package/dist/default-Clra32mw.mjs.map +0 -1
- package/dist/deferred-tasks-CvDETTJO.d.mts +0 -9
- package/dist/deferred-tasks-CvDETTJO.d.mts.map +0 -1
- package/dist/dev-typegen-DzOPfsNj.mjs +0 -29
- package/dist/dev-typegen-DzOPfsNj.mjs.map +0 -1
- package/dist/device-flow-D2oCWvLJ.mjs +0 -466
- package/dist/device-flow-D2oCWvLJ.mjs.map +0 -1
- package/dist/dialect-helpers-BSbfaO3F.mjs +0 -202
- package/dist/dialect-helpers-BSbfaO3F.mjs.map +0 -1
- package/dist/direct-executor-Bfa5_ToE.mjs +0 -85
- package/dist/direct-executor-Bfa5_ToE.mjs.map +0 -1
- package/dist/dist-89xCrGqi.mjs +0 -810
- package/dist/dist-89xCrGqi.mjs.map +0 -1
- package/dist/email-console-Dzb6uGYa.mjs +0 -50
- package/dist/email-console-Dzb6uGYa.mjs.map +0 -1
- package/dist/enrich-BX0IDp4z.mjs +0 -194
- package/dist/enrich-BX0IDp4z.mjs.map +0 -1
- package/dist/error-DFrQjppn.mjs +0 -90
- package/dist/error-DFrQjppn.mjs.map +0 -1
- package/dist/errors-DsVoDUjJ.mjs +0 -427
- package/dist/errors-DsVoDUjJ.mjs.map +0 -1
- package/dist/escape-HmHTC1Is.mjs +0 -9
- package/dist/escape-HmHTC1Is.mjs.map +0 -1
- package/dist/field-defs-cache-BM4SIRqH.mjs +0 -77
- package/dist/field-defs-cache-BM4SIRqH.mjs.map +0 -1
- package/dist/focal-point-BeWFo6Xx.mjs +0 -23
- package/dist/focal-point-BeWFo6Xx.mjs.map +0 -1
- package/dist/fts-manager-Do1BlW2r.mjs +0 -413
- package/dist/fts-manager-Do1BlW2r.mjs.map +0 -1
- package/dist/hash-3JJPlHF2.mjs +0 -37
- package/dist/hash-3JJPlHF2.mjs.map +0 -1
- package/dist/hook-result-DCh2WUpe.d.mts +0 -31
- package/dist/hook-result-DCh2WUpe.d.mts.map +0 -1
- package/dist/hreflang-B6hbAuuO.d.mts +0 -48
- package/dist/hreflang-B6hbAuuO.d.mts.map +0 -1
- package/dist/hreflang-DQbPZliA.mjs +0 -102
- package/dist/hreflang-DQbPZliA.mjs.map +0 -1
- package/dist/identity-DksvEazf.mjs +0 -35
- package/dist/identity-DksvEazf.mjs.map +0 -1
- package/dist/import-CJpaBBBT.mjs +0 -2020
- package/dist/import-CJpaBBBT.mjs.map +0 -1
- package/dist/index-BJNMCWmu.d.mts +0 -6562
- package/dist/index-BJNMCWmu.d.mts.map +0 -1
- package/dist/index-Du8K7bWa.d.mts +0 -278
- package/dist/index-Du8K7bWa.d.mts.map +0 -1
- package/dist/init-lock-DJkX6Hto.mjs +0 -56
- package/dist/init-lock-DJkX6Hto.mjs.map +0 -1
- package/dist/load-CawHjTOH.mjs +0 -28
- package/dist/load-CawHjTOH.mjs.map +0 -1
- package/dist/loader-Z8vl7zTq.mjs +0 -966
- package/dist/loader-Z8vl7zTq.mjs.map +0 -1
- package/dist/manifest-builder-COtzuca2.mjs +0 -189
- package/dist/manifest-builder-COtzuca2.mjs.map +0 -1
- package/dist/manifest-schema-BNWwR8Vd.mjs +0 -301
- package/dist/manifest-schema-BNWwR8Vd.mjs.map +0 -1
- package/dist/media-BBm8Wg3f.mjs +0 -318
- package/dist/media-BBm8Wg3f.mjs.map +0 -1
- package/dist/media-BHjus86Y.mjs +0 -464
- package/dist/media-BHjus86Y.mjs.map +0 -1
- package/dist/media-allowlist-CoTBWoDp.mjs +0 -44
- package/dist/media-allowlist-CoTBWoDp.mjs.map +0 -1
- package/dist/media-folders-BGkATs8n.mjs +0 -210
- package/dist/media-folders-BGkATs8n.mjs.map +0 -1
- package/dist/media-upload-BCidR-EY.mjs +0 -147
- package/dist/media-upload-BCidR-EY.mjs.map +0 -1
- package/dist/media-url-DHoPr0hq.mjs +0 -26
- package/dist/media-url-DHoPr0hq.mjs.map +0 -1
- package/dist/media-usage-CdY5jhSR.mjs +0 -1833
- package/dist/media-usage-CdY5jhSR.mjs.map +0 -1
- package/dist/media-usage-activation-BgeMtK5C.mjs +0 -78
- package/dist/media-usage-activation-BgeMtK5C.mjs.map +0 -1
- package/dist/media-usage-work-CnGCdHxx.mjs +0 -152
- package/dist/media-usage-work-CnGCdHxx.mjs.map +0 -1
- package/dist/media-usage-work-D6D9sMCA.mjs +0 -586
- package/dist/media-usage-work-D6D9sMCA.mjs.map +0 -1
- package/dist/media-usage-write-fence-hjeD4u7s.mjs +0 -42
- package/dist/media-usage-write-fence-hjeD4u7s.mjs.map +0 -1
- package/dist/menus-6qSwTNxG.mjs +0 -4010
- package/dist/menus-6qSwTNxG.mjs.map +0 -1
- package/dist/menus-uvPLXMZf.mjs +0 -744
- package/dist/menus-uvPLXMZf.mjs.map +0 -1
- package/dist/mime-CUIG6x84.mjs +0 -36
- package/dist/mime-CUIG6x84.mjs.map +0 -1
- package/dist/mode-DN_WneRx.mjs +0 -23
- package/dist/mode-DN_WneRx.mjs.map +0 -1
- package/dist/node-sqlite-compat-BuJXIeMz.mjs +0 -46
- package/dist/node-sqlite-compat-BuJXIeMz.mjs.map +0 -1
- package/dist/normalize-C2xNjTSG.mjs +0 -191
- package/dist/normalize-C2xNjTSG.mjs.map +0 -1
- package/dist/oauth-authorization-Dj6Kwc21.mjs +0 -274
- package/dist/oauth-authorization-Dj6Kwc21.mjs.map +0 -1
- package/dist/oauth-clients-FD7I0J8m.mjs +0 -266
- package/dist/oauth-clients-FD7I0J8m.mjs.map +0 -1
- package/dist/oauth-state-store-DkmDOmHs.mjs +0 -50
- package/dist/oauth-state-store-DkmDOmHs.mjs.map +0 -1
- package/dist/oauth-user-lookup-CvIwGpYd.mjs +0 -26
- package/dist/oauth-user-lookup-CvIwGpYd.mjs.map +0 -1
- package/dist/object-cache-DVKnyOfy.mjs +0 -534
- package/dist/object-cache-DVKnyOfy.mjs.map +0 -1
- package/dist/options-BHPeIbBd.mjs +0 -117
- package/dist/options-BHPeIbBd.mjs.map +0 -1
- package/dist/options-CYb4y7hM.d.mts +0 -221
- package/dist/options-CYb4y7hM.d.mts.map +0 -1
- package/dist/parse-Ckpg-Qfp.mjs +0 -81
- package/dist/parse-Ckpg-Qfp.mjs.map +0 -1
- package/dist/passkey-config-O_lj3y0k.mjs +0 -46
- package/dist/passkey-config-O_lj3y0k.mjs.map +0 -1
- package/dist/patterns-D9iDO3j8.mjs +0 -145
- package/dist/patterns-D9iDO3j8.mjs.map +0 -1
- package/dist/placeholder-4X9BrRrp.d.mts +0 -306
- package/dist/placeholder-4X9BrRrp.d.mts.map +0 -1
- package/dist/policy-Dhtwntrt.mjs +0 -45
- package/dist/policy-Dhtwntrt.mjs.map +0 -1
- package/dist/portable-text-U85hOafW.mjs +0 -286
- package/dist/portable-text-U85hOafW.mjs.map +0 -1
- package/dist/preview-B_vJLvf8.mjs +0 -107
- package/dist/preview-B_vJLvf8.mjs.map +0 -1
- package/dist/protocol-JdD2YhY9.d.mts +0 -52
- package/dist/protocol-JdD2YhY9.d.mts.map +0 -1
- package/dist/public-url-CarhZJgf.mjs +0 -101
- package/dist/public-url-CarhZJgf.mjs.map +0 -1
- package/dist/query-BZKZcG5b.mjs +0 -881
- package/dist/query-BZKZcG5b.mjs.map +0 -1
- package/dist/query-BndaFxxp.mjs +0 -41
- package/dist/query-BndaFxxp.mjs.map +0 -1
- package/dist/rate-limit-BZmATC6W.mjs +0 -120
- package/dist/rate-limit-BZmATC6W.mjs.map +0 -1
- package/dist/redirect-CZkbozu9.mjs +0 -313
- package/dist/redirect-CZkbozu9.mjs.map +0 -1
- package/dist/redirect-CzqnLxK-.mjs +0 -17
- package/dist/redirect-CzqnLxK-.mjs.map +0 -1
- package/dist/redirects-BLNOWQTn.mjs +0 -1238
- package/dist/redirects-BLNOWQTn.mjs.map +0 -1
- package/dist/redirects-CqzNM0KM.mjs +0 -579
- package/dist/redirects-CqzNM0KM.mjs.map +0 -1
- package/dist/registry-AZAsRsor.mjs +0 -1179
- package/dist/registry-AZAsRsor.mjs.map +0 -1
- package/dist/relation-04DfKRTO.mjs +0 -334
- package/dist/relation-04DfKRTO.mjs.map +0 -1
- package/dist/relations-C4htk5sb.mjs +0 -309
- package/dist/relations-C4htk5sb.mjs.map +0 -1
- package/dist/relations-CcFwDJdJ.mjs +0 -403
- package/dist/relations-CcFwDJdJ.mjs.map +0 -1
- package/dist/relations-DnRK4YIT.d.mts +0 -3354
- package/dist/relations-DnRK4YIT.d.mts.map +0 -1
- package/dist/request-cache-DH9zdCOD.mjs +0 -104
- package/dist/request-cache-DH9zdCOD.mjs.map +0 -1
- package/dist/request-meta-DYxLlnmz.mjs +0 -140
- package/dist/request-meta-DYxLlnmz.mjs.map +0 -1
- package/dist/resolve-prZ3mP7l.mjs +0 -143
- package/dist/resolve-prZ3mP7l.mjs.map +0 -1
- package/dist/runner-BLIDKpmA.mjs +0 -4676
- package/dist/runner-BLIDKpmA.mjs.map +0 -1
- package/dist/runner-YKfIMnaF.d.mts +0 -67
- package/dist/runner-YKfIMnaF.d.mts.map +0 -1
- package/dist/schema-CGnBeLiW.mjs +0 -9
- package/dist/schema-CGnBeLiW.mjs.map +0 -1
- package/dist/schema-DYr-Vd-L.mjs +0 -420
- package/dist/schema-DYr-Vd-L.mjs.map +0 -1
- package/dist/scopes-BhWvBavj.mjs +0 -27
- package/dist/scopes-BhWvBavj.mjs.map +0 -1
- package/dist/search-C-qDk4kx.mjs +0 -439
- package/dist/search-C-qDk4kx.mjs.map +0 -1
- package/dist/secrets-rEtHt-6z.mjs +0 -330
- package/dist/secrets-rEtHt-6z.mjs.map +0 -1
- package/dist/sections-B_nYvlwn.mjs +0 -346
- package/dist/sections-B_nYvlwn.mjs.map +0 -1
- package/dist/seo-926NRIgt.mjs +0 -133
- package/dist/seo-926NRIgt.mjs.map +0 -1
- package/dist/seo-CVWkdv6x.mjs +0 -113
- package/dist/seo-CVWkdv6x.mjs.map +0 -1
- package/dist/service-CJl3ZAYs.mjs +0 -195
- package/dist/service-CJl3ZAYs.mjs.map +0 -1
- package/dist/session-user-BlMgqCHS.mjs +0 -51
- package/dist/session-user-BlMgqCHS.mjs.map +0 -1
- package/dist/settings--wobrkkC.mjs +0 -258
- package/dist/settings--wobrkkC.mjs.map +0 -1
- package/dist/settings-Cwm6o2jY.mjs +0 -51
- package/dist/settings-Cwm6o2jY.mjs.map +0 -1
- package/dist/setup-complete-DQbClIN2.mjs +0 -26
- package/dist/setup-complete-DQbClIN2.mjs.map +0 -1
- package/dist/setup-nonce-DZCFS2sn.mjs +0 -25
- package/dist/setup-nonce-DZCFS2sn.mjs.map +0 -1
- package/dist/single-flight-cache-BPuGPdcN.mjs +0 -104
- package/dist/single-flight-cache-BPuGPdcN.mjs.map +0 -1
- package/dist/site-url-BrxA_E9H.mjs +0 -16
- package/dist/site-url-BrxA_E9H.mjs.map +0 -1
- package/dist/slugify-B994zkXC.mjs +0 -17
- package/dist/slugify-B994zkXC.mjs.map +0 -1
- package/dist/snapshot--OCDTqdb.mjs +0 -216
- package/dist/snapshot--OCDTqdb.mjs.map +0 -1
- package/dist/ssrf-5sIM5jzl.mjs +0 -349
- package/dist/ssrf-5sIM5jzl.mjs.map +0 -1
- package/dist/state-BpFVsJZB.mjs +0 -136
- package/dist/state-BpFVsJZB.mjs.map +0 -1
- package/dist/status-B777-dXz.mjs +0 -30
- package/dist/status-B777-dXz.mjs.map +0 -1
- package/dist/target-BmR0iTwz.mjs +0 -27
- package/dist/target-BmR0iTwz.mjs.map +0 -1
- package/dist/taxonomies-DkAkMupr.mjs +0 -837
- package/dist/taxonomies-DkAkMupr.mjs.map +0 -1
- package/dist/taxonomies-Wfy_Lg12.mjs +0 -698
- package/dist/taxonomies-Wfy_Lg12.mjs.map +0 -1
- package/dist/taxonomy-tJepplLL.mjs +0 -484
- package/dist/taxonomy-tJepplLL.mjs.map +0 -1
- package/dist/tokens-BCO1oruF.mjs +0 -171
- package/dist/tokens-BCO1oruF.mjs.map +0 -1
- package/dist/transaction-0KOpOyMu.mjs +0 -29
- package/dist/transaction-0KOpOyMu.mjs.map +0 -1
- package/dist/transport-Dr3qtwXC.mjs +0 -136
- package/dist/transport-Dr3qtwXC.mjs.map +0 -1
- package/dist/transport-xh6YKW2G.d.mts +0 -42
- package/dist/transport-xh6YKW2G.d.mts.map +0 -1
- package/dist/trusted-proxy-BR5F1Otp.mjs +0 -51
- package/dist/trusted-proxy-BR5F1Otp.mjs.map +0 -1
- package/dist/types-3qNFPlci.mjs +0 -16
- package/dist/types-3qNFPlci.mjs.map +0 -1
- package/dist/types-75KIqzL9.mjs +0 -142
- package/dist/types-75KIqzL9.mjs.map +0 -1
- package/dist/types-B6GrPic4.d.mts +0 -1335
- package/dist/types-B6GrPic4.d.mts.map +0 -1
- package/dist/types-BuHW4xDE.d.mts +0 -259
- package/dist/types-BuHW4xDE.d.mts.map +0 -1
- package/dist/types-C00oyCZp.d.mts +0 -198
- package/dist/types-C00oyCZp.d.mts.map +0 -1
- package/dist/types-CDtkNSFQ.d.mts +0 -75
- package/dist/types-CDtkNSFQ.d.mts.map +0 -1
- package/dist/types-CPeXo1wF.d.mts +0 -124
- package/dist/types-CPeXo1wF.d.mts.map +0 -1
- package/dist/types-CQPWhPxE.mjs +0 -92
- package/dist/types-CQPWhPxE.mjs.map +0 -1
- package/dist/types-CXFkwEGC.d.mts +0 -198
- package/dist/types-CXFkwEGC.d.mts.map +0 -1
- package/dist/types-DM3vioBY.mjs +0 -18
- package/dist/types-DM3vioBY.mjs.map +0 -1
- package/dist/types-DczELMop.d.mts +0 -363
- package/dist/types-DczELMop.d.mts.map +0 -1
- package/dist/types-DfuTR6dL.mjs +0 -3
- package/dist/types-FV23hEoW.d.mts +0 -743
- package/dist/types-FV23hEoW.d.mts.map +0 -1
- package/dist/types-xDMtUFnO.d.mts +0 -257
- package/dist/types-xDMtUFnO.d.mts.map +0 -1
- package/dist/upload-attempts-BsqoQ1fn.mjs +0 -27
- package/dist/upload-attempts-BsqoQ1fn.mjs.map +0 -1
- package/dist/url-pattern-D4c2czpJ.mjs +0 -33
- package/dist/url-pattern-D4c2czpJ.mjs.map +0 -1
- package/dist/user-BTZ40aq6.mjs +0 -171
- package/dist/user-BTZ40aq6.mjs.map +0 -1
- package/dist/utils-BKvNjjhY.mjs +0 -435
- package/dist/utils-BKvNjjhY.mjs.map +0 -1
- package/dist/validate-BpwoDOgt.mjs +0 -120
- package/dist/validate-BpwoDOgt.mjs.map +0 -1
- package/dist/validate-DE_LRwo9.mjs +0 -379
- package/dist/validate-DE_LRwo9.mjs.map +0 -1
- package/dist/validate-DUP27OYD.d.mts +0 -400
- package/dist/validate-DUP27OYD.d.mts.map +0 -1
- package/dist/validation-BMImFJ11.mjs +0 -153
- package/dist/validation-BMImFJ11.mjs.map +0 -1
- package/dist/version-Bii3suaO.mjs +0 -7
- package/dist/version-Bii3suaO.mjs.map +0 -1
- package/dist/widgets-D3gJ10xU.mjs +0 -122
- package/dist/widgets-D3gJ10xU.mjs.map +0 -1
- package/dist/wxr-taxonomies-B2Og_6rU.d.mts +0 -34
- package/dist/wxr-taxonomies-B2Og_6rU.d.mts.map +0 -1
- package/dist/wxr-taxonomies-Cxngsjwo.mjs +0 -406
- package/dist/wxr-taxonomies-Cxngsjwo.mjs.map +0 -1
- package/dist/zod-generator-BuYSQJB7.mjs +0 -331
- package/dist/zod-generator-BuYSQJB7.mjs.map +0 -1
- /package/dist/{api-tokens-BfYts-sq.mjs → api-tokens-DS1VzN7_.mjs} +0 -0
- /package/dist/{ssrf-Dg3cIT-b.mjs → ssrf-BRpTDMV6.mjs} +0 -0
package/src/plugins/context.ts
CHANGED
|
@@ -8,16 +8,31 @@
|
|
|
8
8
|
import type { Kysely } from "kysely";
|
|
9
9
|
import { ulid } from "ulidx";
|
|
10
10
|
|
|
11
|
+
import {
|
|
12
|
+
handleRedirectCreate,
|
|
13
|
+
handleRedirectDelete,
|
|
14
|
+
handleRedirectList,
|
|
15
|
+
handleRedirectUpdate,
|
|
16
|
+
} from "../api/handlers/redirects.js";
|
|
17
|
+
import { handleTermCreate } from "../api/handlers/taxonomies.js";
|
|
18
|
+
import { createRedirectBody, updateRedirectBody } from "../api/schemas/redirects.js";
|
|
19
|
+
import { CommentRepository, type Comment } from "../database/repositories/comment.js";
|
|
11
20
|
import { ContentRepository } from "../database/repositories/content.js";
|
|
21
|
+
import { EntryLockRepository } from "../database/repositories/entry-locks.js";
|
|
12
22
|
import { MediaRepository } from "../database/repositories/media.js";
|
|
13
23
|
import { OptionsRepository } from "../database/repositories/options.js";
|
|
14
24
|
import { PluginStorageRepository } from "../database/repositories/plugin-storage.js";
|
|
25
|
+
import {
|
|
26
|
+
RedirectRepository,
|
|
27
|
+
type Redirect,
|
|
28
|
+
type VersionedRedirectRecord,
|
|
29
|
+
} from "../database/repositories/redirect.js";
|
|
15
30
|
import { SeoRepository } from "../database/repositories/seo.js";
|
|
16
31
|
import { TaxonomyRepository, type Taxonomy } from "../database/repositories/taxonomy.js";
|
|
17
32
|
import { UserRepository } from "../database/repositories/user.js";
|
|
18
33
|
import { withTransaction } from "../database/transaction.js";
|
|
19
34
|
import type { Database } from "../database/types.js";
|
|
20
|
-
import { resolveContentCreateLocale } from "../i18n/config.js";
|
|
35
|
+
import { getI18nConfig, resolveContentCreateLocale } from "../i18n/config.js";
|
|
21
36
|
import {
|
|
22
37
|
resolveAndValidateExternalUrl,
|
|
23
38
|
SsrfError,
|
|
@@ -25,20 +40,38 @@ import {
|
|
|
25
40
|
} from "../import/ssrf.js";
|
|
26
41
|
import { enrichImageMetadata } from "../media/enrich.js";
|
|
27
42
|
import { markContentMediaUsageCollectionStaleSafely } from "../media/usage/content-refresh.js";
|
|
43
|
+
import { SchemaRegistry } from "../schema/registry.js";
|
|
28
44
|
import { invalidateSiteSettingsCache } from "../settings/index.js";
|
|
29
45
|
import type { Storage } from "../storage/types.js";
|
|
46
|
+
import { assertStorageKey } from "./conditional-storage.js";
|
|
47
|
+
import { createContentAccess } from "./content-access.js";
|
|
30
48
|
import { CronAccessImpl } from "./cron.js";
|
|
31
49
|
import type { EmailPipeline } from "./email.js";
|
|
50
|
+
import {
|
|
51
|
+
bufferPluginHttpRequest,
|
|
52
|
+
pluginHttpRedirectAction,
|
|
53
|
+
pluginHttpResponseFromWire,
|
|
54
|
+
pluginHttpResponseToWire,
|
|
55
|
+
rewritePluginHttpRedirect,
|
|
56
|
+
} from "./http-wire.js";
|
|
57
|
+
import { readPluginMediaBytes, toPluginMediaItem, updatePluginMediaMetadata } from "./media.js";
|
|
58
|
+
import {
|
|
59
|
+
createPluginSecretRedactor,
|
|
60
|
+
createSettingsAccess,
|
|
61
|
+
type PluginSecretRedactor,
|
|
62
|
+
} from "./settings.js";
|
|
32
63
|
import type {
|
|
33
64
|
ResolvedPlugin,
|
|
34
65
|
PluginContext,
|
|
35
66
|
PluginStorageConfig,
|
|
36
67
|
StorageCollection,
|
|
37
68
|
KVAccess,
|
|
69
|
+
SettingsAccess,
|
|
38
70
|
CronAccess,
|
|
39
71
|
EmailAccess,
|
|
40
72
|
ContentAccess,
|
|
41
73
|
ContentAccessWithWrite,
|
|
74
|
+
VersionedContentItem,
|
|
42
75
|
MediaAccess,
|
|
43
76
|
MediaAccessWithWrite,
|
|
44
77
|
HttpAccess,
|
|
@@ -53,14 +86,32 @@ import type {
|
|
|
53
86
|
MediaItem,
|
|
54
87
|
PaginatedResult,
|
|
55
88
|
QueryOptions,
|
|
56
|
-
ContentListOptions,
|
|
57
89
|
MediaListOptions,
|
|
58
90
|
TaxonomyAccess,
|
|
91
|
+
TaxonomyAccessWithWrite,
|
|
59
92
|
TaxonomyDefInfo,
|
|
60
93
|
TaxonomyTermInfo,
|
|
94
|
+
TaxonomyTermCreateInput,
|
|
61
95
|
TaxonomyReadOptions,
|
|
96
|
+
CommentAccess,
|
|
97
|
+
CommentListOptions,
|
|
98
|
+
PluginComment,
|
|
99
|
+
PluginCommentStatus,
|
|
100
|
+
RedirectAccess,
|
|
101
|
+
RedirectAccessWithWrite,
|
|
102
|
+
RedirectCreateInput,
|
|
103
|
+
RedirectInfo,
|
|
104
|
+
RedirectListOptions,
|
|
105
|
+
RedirectStatus,
|
|
106
|
+
RedirectUpdateInput,
|
|
107
|
+
VersionedRedirect,
|
|
108
|
+
SchemaAccess,
|
|
109
|
+
CollectionSchemaInfo,
|
|
110
|
+
PluginContentCreateCallback,
|
|
62
111
|
} from "./types.js";
|
|
63
112
|
|
|
113
|
+
export { createContentAccess } from "./content-access.js";
|
|
114
|
+
|
|
64
115
|
// =============================================================================
|
|
65
116
|
// KV Access
|
|
66
117
|
// =============================================================================
|
|
@@ -69,32 +120,76 @@ import type {
|
|
|
69
120
|
* Create KV accessor for a plugin
|
|
70
121
|
* All keys are automatically prefixed with the plugin ID
|
|
71
122
|
*/
|
|
72
|
-
export function createKVAccess(
|
|
123
|
+
export function createKVAccess(
|
|
124
|
+
optionsRepo: OptionsRepository,
|
|
125
|
+
pluginId: string,
|
|
126
|
+
settings: SettingsAccess = createSettingsAccess(optionsRepo, pluginId),
|
|
127
|
+
): KVAccess {
|
|
73
128
|
const prefix = `plugin:${pluginId}:`;
|
|
74
129
|
|
|
75
130
|
return {
|
|
76
131
|
async get<T>(key: string): Promise<T | null> {
|
|
132
|
+
if (key.startsWith("settings:")) return settings.get<T>(key.slice("settings:".length));
|
|
77
133
|
return optionsRepo.get<T>(`${prefix}${key}`);
|
|
78
134
|
},
|
|
135
|
+
async getVersioned<T>(key: string) {
|
|
136
|
+
assertStorageKey(key);
|
|
137
|
+
if (key.startsWith("settings:")) {
|
|
138
|
+
return settings.getVersioned<T>(key.slice("settings:".length));
|
|
139
|
+
}
|
|
140
|
+
return optionsRepo.getVersioned<T>(`${prefix}${key}`);
|
|
141
|
+
},
|
|
142
|
+
async compareAndSet(key, expectedRevision, value) {
|
|
143
|
+
assertStorageKey(key);
|
|
144
|
+
if (key.startsWith("settings:")) {
|
|
145
|
+
return settings.compareAndSet(key.slice("settings:".length), expectedRevision, value);
|
|
146
|
+
}
|
|
147
|
+
return optionsRepo.compareAndSet(`${prefix}${key}`, expectedRevision, value);
|
|
148
|
+
},
|
|
149
|
+
async compareAndDelete(key, expectedRevision) {
|
|
150
|
+
assertStorageKey(key);
|
|
151
|
+
if (key.startsWith("settings:")) {
|
|
152
|
+
return settings.compareAndDelete(key.slice("settings:".length), expectedRevision);
|
|
153
|
+
}
|
|
154
|
+
return optionsRepo.compareAndDelete(`${prefix}${key}`, expectedRevision);
|
|
155
|
+
},
|
|
79
156
|
|
|
80
157
|
async set(key: string, value: unknown): Promise<void> {
|
|
158
|
+
if (key.startsWith("settings:")) {
|
|
159
|
+
await settings.set(key.slice("settings:".length), value);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
81
162
|
await optionsRepo.set(`${prefix}${key}`, value);
|
|
82
163
|
},
|
|
83
164
|
|
|
84
165
|
async delete(key: string): Promise<boolean> {
|
|
166
|
+
if (key.startsWith("settings:")) return settings.delete(key.slice("settings:".length));
|
|
85
167
|
return optionsRepo.delete(`${prefix}${key}`);
|
|
86
168
|
},
|
|
87
169
|
|
|
88
170
|
async list(keyPrefix?: string): Promise<Array<{ key: string; value: unknown }>> {
|
|
89
|
-
const
|
|
171
|
+
const requestedPrefix = keyPrefix ?? "";
|
|
172
|
+
const includesSettings =
|
|
173
|
+
"settings:".startsWith(requestedPrefix) || requestedPrefix.startsWith("settings:");
|
|
174
|
+
const fullPrefix = `${prefix}${requestedPrefix}`;
|
|
90
175
|
const entriesMap = await optionsRepo.getByPrefix(fullPrefix);
|
|
91
176
|
const result: Array<{ key: string; value: unknown }> = [];
|
|
92
177
|
for (const [fullKey, value] of entriesMap) {
|
|
178
|
+
if (includesSettings && fullKey.startsWith(`${prefix}settings:`)) continue;
|
|
93
179
|
result.push({
|
|
94
180
|
key: fullKey.slice(prefix.length),
|
|
95
181
|
value,
|
|
96
182
|
});
|
|
97
183
|
}
|
|
184
|
+
if (includesSettings) {
|
|
185
|
+
const settingPrefix = requestedPrefix.startsWith("settings:")
|
|
186
|
+
? requestedPrefix.slice("settings:".length)
|
|
187
|
+
: "";
|
|
188
|
+
for (const entry of await settings.list(settingPrefix)) {
|
|
189
|
+
const key = `settings:${entry.key}`;
|
|
190
|
+
if (key.startsWith(requestedPrefix)) result.push({ key, value: entry.value });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
98
193
|
return result;
|
|
99
194
|
},
|
|
100
195
|
};
|
|
@@ -118,6 +213,9 @@ function createStorageCollection<T>(
|
|
|
118
213
|
|
|
119
214
|
return {
|
|
120
215
|
get: (id) => repo.get(id),
|
|
216
|
+
getVersioned: (id) => repo.getVersioned(id),
|
|
217
|
+
compareAndSet: (id, expectedRevision, data) => repo.compareAndSet(id, expectedRevision, data),
|
|
218
|
+
compareAndDelete: (id, expectedRevision) => repo.compareAndDelete(id, expectedRevision),
|
|
121
219
|
put: (id, data) => repo.put(id, data),
|
|
122
220
|
delete: (id) => repo.delete(id),
|
|
123
221
|
exists: (id) => repo.exists(id),
|
|
@@ -125,6 +223,7 @@ function createStorageCollection<T>(
|
|
|
125
223
|
putMany: (items) => repo.putMany(items),
|
|
126
224
|
deleteMany: (ids) => repo.deleteMany(ids),
|
|
127
225
|
count: (where) => repo.count(where),
|
|
226
|
+
updateIf: (id, updateArgs) => repo.updateIf(id, updateArgs),
|
|
128
227
|
|
|
129
228
|
// Query returns PaginatedResult instead of the old format
|
|
130
229
|
async query(options?: QueryOptions): Promise<PaginatedResult<{ id: string; data: T }>> {
|
|
@@ -232,88 +331,53 @@ function taxonomyToTermInfo(term: Taxonomy): TaxonomyTermInfo {
|
|
|
232
331
|
};
|
|
233
332
|
}
|
|
234
333
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const contentRepo = new ContentRepository(db);
|
|
240
|
-
const seoRepo = new SeoRepository(db);
|
|
241
|
-
|
|
334
|
+
function collectionToSchemaInfo(
|
|
335
|
+
collection: Awaited<ReturnType<SchemaRegistry["getCollectionWithFields"]>>,
|
|
336
|
+
): CollectionSchemaInfo | null {
|
|
337
|
+
if (!collection) return null;
|
|
242
338
|
return {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
339
|
+
slug: collection.slug,
|
|
340
|
+
label: collection.label,
|
|
341
|
+
labelSingular: collection.labelSingular ?? null,
|
|
342
|
+
description: collection.description ?? null,
|
|
343
|
+
supports: collection.supports,
|
|
344
|
+
hasSeo: collection.hasSeo,
|
|
345
|
+
titleField: collection.titleField ?? null,
|
|
346
|
+
dateField: collection.dateField ?? null,
|
|
347
|
+
urlPattern: collection.urlPattern ?? null,
|
|
348
|
+
routable: collection.routable !== false,
|
|
349
|
+
hidden: collection.hidden,
|
|
350
|
+
fields: collection.fields.map((field) => ({
|
|
351
|
+
slug: field.slug,
|
|
352
|
+
label: field.label,
|
|
353
|
+
type: field.type,
|
|
354
|
+
required: field.required,
|
|
355
|
+
unique: field.unique,
|
|
356
|
+
...(field.defaultValue === undefined ? {} : { default: field.defaultValue }),
|
|
357
|
+
...(field.validation === undefined ? {} : { validation: field.validation }),
|
|
358
|
+
...(field.widget === undefined ? {} : { widget: field.widget }),
|
|
359
|
+
...(field.options === undefined ? {} : { options: field.options }),
|
|
360
|
+
searchable: field.searchable,
|
|
361
|
+
indexed: field.indexed,
|
|
362
|
+
translatable: field.translatable,
|
|
363
|
+
sortOrder: field.sortOrder,
|
|
364
|
+
})),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
259
367
|
|
|
260
|
-
|
|
261
|
-
|
|
368
|
+
export function createSchemaAccess(db: Kysely<Database>): SchemaAccess {
|
|
369
|
+
const registry = new SchemaRegistry(db);
|
|
370
|
+
return {
|
|
371
|
+
async listCollections() {
|
|
372
|
+
const collections: CollectionSchemaInfo[] = [];
|
|
373
|
+
for (const collection of await registry.listCollectionsWithFields()) {
|
|
374
|
+
const info = collectionToSchemaInfo(collection);
|
|
375
|
+
if (info) collections.push(info);
|
|
262
376
|
}
|
|
263
|
-
|
|
264
|
-
return result;
|
|
377
|
+
return collections;
|
|
265
378
|
},
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
collection: string,
|
|
269
|
-
options?: ContentListOptions,
|
|
270
|
-
): Promise<PaginatedResult<ContentItem>> {
|
|
271
|
-
// Convert orderBy format if provided
|
|
272
|
-
let orderBy: { field: string; direction: "asc" | "desc" } | undefined;
|
|
273
|
-
if (options?.orderBy) {
|
|
274
|
-
const entries = Object.entries(options.orderBy);
|
|
275
|
-
const first = entries[0];
|
|
276
|
-
if (first) {
|
|
277
|
-
orderBy = { field: first[0], direction: first[1] };
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const result = await contentRepo.findMany(collection, {
|
|
282
|
-
limit: options?.limit ?? 50,
|
|
283
|
-
cursor: options?.cursor,
|
|
284
|
-
orderBy,
|
|
285
|
-
where: options?.where,
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
const items: ContentItem[] = result.items.map((item) => ({
|
|
289
|
-
id: item.id,
|
|
290
|
-
type: item.type,
|
|
291
|
-
slug: item.slug,
|
|
292
|
-
status: item.status,
|
|
293
|
-
data: item.data,
|
|
294
|
-
createdAt: item.createdAt,
|
|
295
|
-
updatedAt: item.updatedAt,
|
|
296
|
-
locale: item.locale,
|
|
297
|
-
publishedAt: item.publishedAt,
|
|
298
|
-
scheduledAt: item.scheduledAt,
|
|
299
|
-
}));
|
|
300
|
-
|
|
301
|
-
if (items.length > 0 && (await seoRepo.isEnabled(collection))) {
|
|
302
|
-
const seoMap = await seoRepo.getMany(
|
|
303
|
-
collection,
|
|
304
|
-
items.map((i) => i.id),
|
|
305
|
-
);
|
|
306
|
-
for (const item of items) {
|
|
307
|
-
const seo = seoMap.get(item.id);
|
|
308
|
-
if (seo) item.seo = seo;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
return {
|
|
313
|
-
items,
|
|
314
|
-
cursor: result.nextCursor,
|
|
315
|
-
hasMore: !!result.nextCursor,
|
|
316
|
-
};
|
|
379
|
+
async getCollection(slug) {
|
|
380
|
+
return collectionToSchemaInfo(await registry.getCollectionWithFields(slug));
|
|
317
381
|
},
|
|
318
382
|
};
|
|
319
383
|
}
|
|
@@ -360,6 +424,327 @@ export function createTaxonomyAccess(db: Kysely<Database>): TaxonomyAccess {
|
|
|
360
424
|
};
|
|
361
425
|
}
|
|
362
426
|
|
|
427
|
+
function toPluginComment(comment: Comment): PluginComment {
|
|
428
|
+
if (comment.status === "trash") throw new Error("Trashed comments are not plugin-readable");
|
|
429
|
+
return {
|
|
430
|
+
id: comment.id,
|
|
431
|
+
collection: comment.collection,
|
|
432
|
+
contentId: comment.contentId,
|
|
433
|
+
parentId: comment.parentId,
|
|
434
|
+
authorName: comment.authorName,
|
|
435
|
+
authorEmail: comment.authorEmail,
|
|
436
|
+
body: comment.body,
|
|
437
|
+
status: comment.status,
|
|
438
|
+
ipHash: comment.ipHash,
|
|
439
|
+
userAgent: comment.userAgent,
|
|
440
|
+
moderationMetadata: comment.moderationMetadata,
|
|
441
|
+
createdAt: comment.createdAt,
|
|
442
|
+
updatedAt: comment.updatedAt,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
export function createCommentAccess(
|
|
447
|
+
db: Kysely<Database>,
|
|
448
|
+
moderate?: (
|
|
449
|
+
id: string,
|
|
450
|
+
status: PluginCommentStatus,
|
|
451
|
+
expectedStatus: PluginCommentStatus,
|
|
452
|
+
) => Promise<PluginComment>,
|
|
453
|
+
): CommentAccess {
|
|
454
|
+
const repo = new CommentRepository(db);
|
|
455
|
+
return {
|
|
456
|
+
async get(id) {
|
|
457
|
+
const comment = await repo.findById(id);
|
|
458
|
+
return !comment || comment.status === "trash" ? null : toPluginComment(comment);
|
|
459
|
+
},
|
|
460
|
+
async list(options: CommentListOptions = {}) {
|
|
461
|
+
const result = await repo.findForPlugin(options);
|
|
462
|
+
return {
|
|
463
|
+
items: result.items.map(toPluginComment),
|
|
464
|
+
cursor: result.nextCursor,
|
|
465
|
+
hasMore: result.nextCursor !== undefined,
|
|
466
|
+
};
|
|
467
|
+
},
|
|
468
|
+
count: (options) => repo.countForPlugin(options),
|
|
469
|
+
...(moderate
|
|
470
|
+
? {
|
|
471
|
+
setStatus: (id, status, options) => moderate(id, status, options.expectedStatus),
|
|
472
|
+
}
|
|
473
|
+
: {}),
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export class RedirectAccessError extends Error {
|
|
478
|
+
override readonly name = "RedirectAccessError";
|
|
479
|
+
|
|
480
|
+
constructor(
|
|
481
|
+
readonly code: string,
|
|
482
|
+
message: string,
|
|
483
|
+
) {
|
|
484
|
+
super(message);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
const REDIRECT_REVISION_PREFIX = "r1.";
|
|
489
|
+
const BASE64_PADDING_RE = /=+$/;
|
|
490
|
+
|
|
491
|
+
function encodeRedirectRevision(id: string, revision: string): string {
|
|
492
|
+
const payload = `${id}\0${revision}`;
|
|
493
|
+
return `${REDIRECT_REVISION_PREFIX}${btoa(payload)
|
|
494
|
+
.replaceAll("+", "-")
|
|
495
|
+
.replaceAll("/", "_")
|
|
496
|
+
.replace(BASE64_PADDING_RE, "")}`;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function decodeRedirectRevision(id: string, revision: string): string {
|
|
500
|
+
if (typeof revision !== "string" || !revision.startsWith(REDIRECT_REVISION_PREFIX)) {
|
|
501
|
+
throw new RedirectAccessError("INVALID_PRECONDITION", "Invalid redirect revision");
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
const encoded = revision
|
|
505
|
+
.slice(REDIRECT_REVISION_PREFIX.length)
|
|
506
|
+
.replaceAll("-", "+")
|
|
507
|
+
.replaceAll("_", "/");
|
|
508
|
+
const padded = encoded.padEnd(Math.ceil(encoded.length / 4) * 4, "=");
|
|
509
|
+
const [revisionId, updatedAt, extra] = atob(padded).split("\0");
|
|
510
|
+
if (revisionId !== id || !updatedAt || extra !== undefined) throw new Error("invalid");
|
|
511
|
+
return updatedAt;
|
|
512
|
+
} catch (error) {
|
|
513
|
+
if (error instanceof RedirectAccessError) throw error;
|
|
514
|
+
throw new RedirectAccessError("INVALID_PRECONDITION", "Invalid redirect revision");
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function toRedirectInfo(redirect: Redirect): RedirectInfo {
|
|
519
|
+
return {
|
|
520
|
+
...redirect,
|
|
521
|
+
type: redirect.type as RedirectStatus,
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function toVersionedRedirect(record: VersionedRedirectRecord): VersionedRedirect {
|
|
526
|
+
return {
|
|
527
|
+
redirect: toRedirectInfo(record.redirect),
|
|
528
|
+
_rev: encodeRedirectRevision(record.redirect.id, record.configRevision),
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
async function readVersionedRedirect(
|
|
533
|
+
repo: RedirectRepository,
|
|
534
|
+
id: string,
|
|
535
|
+
): Promise<VersionedRedirect | null> {
|
|
536
|
+
const record = await repo.findVersionedById(id);
|
|
537
|
+
return record ? toVersionedRedirect(record) : null;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function throwRedirectResult(error: { code: string; message: string }): never {
|
|
541
|
+
throw new RedirectAccessError(error.code, error.message);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function assertNoAutomaticRedirectMarker(input: object): void {
|
|
545
|
+
if (typeof input !== "object" || input === null || Array.isArray(input)) {
|
|
546
|
+
throw new RedirectAccessError("VALIDATION_ERROR", "Redirect input must be an object");
|
|
547
|
+
}
|
|
548
|
+
if (Object.hasOwn(input, "auto")) {
|
|
549
|
+
throw new RedirectAccessError(
|
|
550
|
+
"VALIDATION_ERROR",
|
|
551
|
+
"The automatic redirect marker is managed by EmDash",
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function createRedirectAccess(db: Kysely<Database>): RedirectAccess;
|
|
557
|
+
export function createRedirectAccess(db: Kysely<Database>, writable: true): RedirectAccessWithWrite;
|
|
558
|
+
export function createRedirectAccess(
|
|
559
|
+
db: Kysely<Database>,
|
|
560
|
+
writable = false,
|
|
561
|
+
): RedirectAccess | RedirectAccessWithWrite {
|
|
562
|
+
const repo = new RedirectRepository(db);
|
|
563
|
+
const readAccess: RedirectAccess = {
|
|
564
|
+
async list(options: RedirectListOptions = {}) {
|
|
565
|
+
const result = await handleRedirectList(db, options);
|
|
566
|
+
if (!result.success) return throwRedirectResult(result.error);
|
|
567
|
+
return {
|
|
568
|
+
items: result.data.items.map(toRedirectInfo),
|
|
569
|
+
cursor: result.data.nextCursor,
|
|
570
|
+
hasMore: result.data.nextCursor !== undefined,
|
|
571
|
+
};
|
|
572
|
+
},
|
|
573
|
+
get: (id: string) => readVersionedRedirect(repo, id),
|
|
574
|
+
};
|
|
575
|
+
if (!writable) return readAccess;
|
|
576
|
+
|
|
577
|
+
return {
|
|
578
|
+
...readAccess,
|
|
579
|
+
async create(input: RedirectCreateInput) {
|
|
580
|
+
assertNoAutomaticRedirectMarker(input);
|
|
581
|
+
const parsed = createRedirectBody.safeParse(input);
|
|
582
|
+
if (!parsed.success) {
|
|
583
|
+
throw new RedirectAccessError(
|
|
584
|
+
"VALIDATION_ERROR",
|
|
585
|
+
parsed.error.issues[0]?.message ?? "Invalid redirect",
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
const result = await handleRedirectCreate(db, parsed.data);
|
|
589
|
+
if (!result.success) return throwRedirectResult(result.error);
|
|
590
|
+
const current = await readVersionedRedirect(repo, result.data.id);
|
|
591
|
+
if (!current) throw new RedirectAccessError("NOT_FOUND", "Created redirect not found");
|
|
592
|
+
return current;
|
|
593
|
+
},
|
|
594
|
+
async update(id: string, input: RedirectUpdateInput & { _rev: string }) {
|
|
595
|
+
assertNoAutomaticRedirectMarker(input);
|
|
596
|
+
const { _rev, ...patch } = input;
|
|
597
|
+
const expectedRevision = decodeRedirectRevision(id, _rev);
|
|
598
|
+
const parsed = updateRedirectBody.safeParse(patch);
|
|
599
|
+
if (!parsed.success) {
|
|
600
|
+
throw new RedirectAccessError(
|
|
601
|
+
"VALIDATION_ERROR",
|
|
602
|
+
parsed.error.issues[0]?.message ?? "Invalid redirect",
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
const result = await handleRedirectUpdate(db, id, parsed.data, { expectedRevision });
|
|
606
|
+
if (!result.success) return throwRedirectResult(result.error);
|
|
607
|
+
const current = await readVersionedRedirect(repo, result.data.id);
|
|
608
|
+
if (!current) throw new RedirectAccessError("NOT_FOUND", "Updated redirect not found");
|
|
609
|
+
return current;
|
|
610
|
+
},
|
|
611
|
+
async delete(id: string, options: { _rev: string }) {
|
|
612
|
+
if (typeof options !== "object" || options === null) {
|
|
613
|
+
throw new RedirectAccessError("INVALID_PRECONDITION", "Invalid redirect revision");
|
|
614
|
+
}
|
|
615
|
+
const expectedRevision = decodeRedirectRevision(id, options._rev);
|
|
616
|
+
const result = await handleRedirectDelete(db, id, { expectedRevision });
|
|
617
|
+
if (!result.success) return throwRedirectResult(result.error);
|
|
618
|
+
return result.data.deleted;
|
|
619
|
+
},
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
const MAX_TAXONOMY_DELTA_TERMS = 64;
|
|
624
|
+
|
|
625
|
+
function taxonomyAccessError(code: string, message: string): Error {
|
|
626
|
+
return Object.assign(new Error(message), { code });
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async function resolveTaxonomyDelta(
|
|
630
|
+
db: Kysely<Database>,
|
|
631
|
+
collection: string,
|
|
632
|
+
entryId: string,
|
|
633
|
+
taxonomy: string,
|
|
634
|
+
termIds: string[],
|
|
635
|
+
): Promise<{ repo: TaxonomyRepository; groups: string[]; locale: string }> {
|
|
636
|
+
if (termIds.length > MAX_TAXONOMY_DELTA_TERMS) {
|
|
637
|
+
throw taxonomyAccessError(
|
|
638
|
+
"VALIDATION_ERROR",
|
|
639
|
+
`A taxonomy assignment delta can contain at most ${MAX_TAXONOMY_DELTA_TERMS} term IDs`,
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
if (termIds.some((id) => typeof id !== "string" || id.length === 0)) {
|
|
643
|
+
throw taxonomyAccessError("VALIDATION_ERROR", "Taxonomy term IDs must be non-empty strings");
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
const defs = await db
|
|
647
|
+
.selectFrom("_emdash_taxonomy_defs")
|
|
648
|
+
.select(["collections"])
|
|
649
|
+
.where("name", "=", taxonomy)
|
|
650
|
+
.execute();
|
|
651
|
+
if (defs.length === 0) {
|
|
652
|
+
throw taxonomyAccessError("NOT_FOUND", `Taxonomy '${taxonomy}' not found`);
|
|
653
|
+
}
|
|
654
|
+
const attached = defs.some((def) => parseCollectionsColumn(def.collections).includes(collection));
|
|
655
|
+
if (!attached) {
|
|
656
|
+
throw taxonomyAccessError(
|
|
657
|
+
"VALIDATION_ERROR",
|
|
658
|
+
`Taxonomy '${taxonomy}' is not attached to collection '${collection}'`,
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const entry = await new ContentRepository(db).findById(collection, entryId);
|
|
663
|
+
if (!entry) {
|
|
664
|
+
throw taxonomyAccessError(
|
|
665
|
+
"NOT_FOUND",
|
|
666
|
+
`Content entry '${entryId}' not found in '${collection}'`,
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
const repo = new TaxonomyRepository(db);
|
|
671
|
+
const groups: string[] = [];
|
|
672
|
+
for (const id of new Set(termIds)) {
|
|
673
|
+
const term = await repo.findByIdOrTranslationGroup(id);
|
|
674
|
+
if (!term) throw taxonomyAccessError("NOT_FOUND", `Taxonomy term '${id}' not found`);
|
|
675
|
+
if (term.name !== taxonomy) {
|
|
676
|
+
throw taxonomyAccessError(
|
|
677
|
+
"VALIDATION_ERROR",
|
|
678
|
+
`Taxonomy term '${id}' belongs to '${term.name}', not '${taxonomy}'`,
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
groups.push(term.translationGroup ?? term.id);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
return { repo, groups, locale: entry.locale ?? getI18nConfig()?.defaultLocale ?? "en" };
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
async function readResolvedEntryTerms(
|
|
688
|
+
repo: TaxonomyRepository,
|
|
689
|
+
collection: string,
|
|
690
|
+
entryId: string,
|
|
691
|
+
taxonomy: string,
|
|
692
|
+
locale: string,
|
|
693
|
+
): Promise<TaxonomyTermInfo[]> {
|
|
694
|
+
const defaultLocale = getI18nConfig()?.defaultLocale ?? locale;
|
|
695
|
+
const assignments = await repo.getTermAssignmentsForEntry(
|
|
696
|
+
collection,
|
|
697
|
+
entryId,
|
|
698
|
+
taxonomy,
|
|
699
|
+
locale,
|
|
700
|
+
defaultLocale,
|
|
701
|
+
);
|
|
702
|
+
return assignments.flatMap(({ term }) => (term ? [taxonomyToTermInfo(term)] : []));
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
export function createTaxonomyAccessWithWrite(db: Kysely<Database>): TaxonomyAccessWithWrite {
|
|
706
|
+
return {
|
|
707
|
+
...createTaxonomyAccess(db),
|
|
708
|
+
async createTerm(taxonomy: string, input: TaxonomyTermCreateInput) {
|
|
709
|
+
const result = await handleTermCreate(db, taxonomy, input);
|
|
710
|
+
if (!result.success) throw taxonomyAccessError(result.error.code, result.error.message);
|
|
711
|
+
const { term } = result.data;
|
|
712
|
+
return {
|
|
713
|
+
id: term.id,
|
|
714
|
+
taxonomy: term.name,
|
|
715
|
+
slug: term.slug,
|
|
716
|
+
label: term.label,
|
|
717
|
+
parentId: term.parentId,
|
|
718
|
+
data: term.description ? { description: term.description } : null,
|
|
719
|
+
locale: term.locale,
|
|
720
|
+
translationGroup: term.translationGroup,
|
|
721
|
+
};
|
|
722
|
+
},
|
|
723
|
+
async addEntryTerms(collection, entryId, taxonomy, termIds) {
|
|
724
|
+
const { repo, groups, locale } = await resolveTaxonomyDelta(
|
|
725
|
+
db,
|
|
726
|
+
collection,
|
|
727
|
+
entryId,
|
|
728
|
+
taxonomy,
|
|
729
|
+
termIds,
|
|
730
|
+
);
|
|
731
|
+
await repo.attachGroupsToEntry(collection, entryId, groups);
|
|
732
|
+
return readResolvedEntryTerms(repo, collection, entryId, taxonomy, locale);
|
|
733
|
+
},
|
|
734
|
+
async removeEntryTerms(collection, entryId, taxonomy, termIds) {
|
|
735
|
+
const { repo, groups, locale } = await resolveTaxonomyDelta(
|
|
736
|
+
db,
|
|
737
|
+
collection,
|
|
738
|
+
entryId,
|
|
739
|
+
taxonomy,
|
|
740
|
+
termIds,
|
|
741
|
+
);
|
|
742
|
+
await repo.detachGroupsFromEntry(collection, entryId, groups);
|
|
743
|
+
return readResolvedEntryTerms(repo, collection, entryId, taxonomy, locale);
|
|
744
|
+
},
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
|
|
363
748
|
/**
|
|
364
749
|
* Create full content access with write operations.
|
|
365
750
|
*
|
|
@@ -372,8 +757,14 @@ export function createTaxonomyAccess(db: Kysely<Database>): TaxonomyAccess {
|
|
|
372
757
|
export function createContentAccessWithWrite(
|
|
373
758
|
db: Kysely<Database>,
|
|
374
759
|
beforeContentWrite?: () => Promise<void>,
|
|
760
|
+
accessOptions?: { site?: SiteInfo; revisions?: boolean },
|
|
761
|
+
contentCreate?: (data: {
|
|
762
|
+
collection: string;
|
|
763
|
+
input: ContentWriteInput;
|
|
764
|
+
options?: ContentCreateOptions;
|
|
765
|
+
}) => Promise<ContentItem>,
|
|
375
766
|
): ContentAccessWithWrite {
|
|
376
|
-
const readAccess = createContentAccess(db);
|
|
767
|
+
const readAccess = createContentAccess(db, accessOptions);
|
|
377
768
|
|
|
378
769
|
return {
|
|
379
770
|
...readAccess,
|
|
@@ -385,6 +776,13 @@ export function createContentAccessWithWrite(
|
|
|
385
776
|
): Promise<ContentItem> {
|
|
386
777
|
const locale = resolveContentCreateLocale(options?.locale);
|
|
387
778
|
await beforeContentWrite?.();
|
|
779
|
+
if (contentCreate) {
|
|
780
|
+
return contentCreate({
|
|
781
|
+
collection,
|
|
782
|
+
input: data,
|
|
783
|
+
options: { ...options, locale },
|
|
784
|
+
});
|
|
785
|
+
}
|
|
388
786
|
const { fields, seo } = splitSeoFromInput(data);
|
|
389
787
|
let contentMutated = false;
|
|
390
788
|
|
|
@@ -399,6 +797,7 @@ export function createContentAccessWithWrite(
|
|
|
399
797
|
type: collection,
|
|
400
798
|
data: fields,
|
|
401
799
|
locale,
|
|
800
|
+
translationOf: options?.translationOf,
|
|
402
801
|
});
|
|
403
802
|
contentMutated = true;
|
|
404
803
|
|
|
@@ -500,6 +899,9 @@ export function createContentAccessWithWrite(
|
|
|
500
899
|
const contentRepo = new ContentRepository(db);
|
|
501
900
|
const deleted = await contentRepo.delete(collection, id);
|
|
502
901
|
if (deleted) {
|
|
902
|
+
// A trashed entry can no longer be opened, so its holder can never
|
|
903
|
+
// release the lease itself. Mirrors handleContentDelete.
|
|
904
|
+
await new EntryLockRepository(db).releaseEntry(collection, id);
|
|
503
905
|
await markContentMediaUsageCollectionStaleSafely(db, collection, "CONTENT_USAGE_STALE");
|
|
504
906
|
}
|
|
505
907
|
return deleted;
|
|
@@ -520,17 +922,7 @@ export function createMediaAccess(db: Kysely<Database>): MediaAccess {
|
|
|
520
922
|
return {
|
|
521
923
|
async get(id: string): Promise<MediaItem | null> {
|
|
522
924
|
const item = await mediaRepo.findById(id);
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
return {
|
|
526
|
-
id: item.id,
|
|
527
|
-
filename: item.filename,
|
|
528
|
-
mimeType: item.mimeType,
|
|
529
|
-
size: item.size,
|
|
530
|
-
// Construct URL from storage key (or use a sensible default path)
|
|
531
|
-
url: `/media/${item.id}/${item.filename}`,
|
|
532
|
-
createdAt: item.createdAt,
|
|
533
|
-
};
|
|
925
|
+
return item?.status === "ready" ? toPluginMediaItem(item) : null;
|
|
534
926
|
},
|
|
535
927
|
|
|
536
928
|
async list(options?: MediaListOptions): Promise<PaginatedResult<MediaItem>> {
|
|
@@ -541,14 +933,7 @@ export function createMediaAccess(db: Kysely<Database>): MediaAccess {
|
|
|
541
933
|
});
|
|
542
934
|
|
|
543
935
|
return {
|
|
544
|
-
items: result.items.map(
|
|
545
|
-
id: item.id,
|
|
546
|
-
filename: item.filename,
|
|
547
|
-
mimeType: item.mimeType,
|
|
548
|
-
size: item.size,
|
|
549
|
-
url: `/media/${item.id}/${item.filename}`,
|
|
550
|
-
createdAt: item.createdAt,
|
|
551
|
-
})),
|
|
936
|
+
items: result.items.map(toPluginMediaItem),
|
|
552
937
|
cursor: result.nextCursor,
|
|
553
938
|
hasMore: !!result.nextCursor,
|
|
554
939
|
};
|
|
@@ -556,6 +941,17 @@ export function createMediaAccess(db: Kysely<Database>): MediaAccess {
|
|
|
556
941
|
};
|
|
557
942
|
}
|
|
558
943
|
|
|
944
|
+
function mediaReadDenied(): never {
|
|
945
|
+
throw new Error("Missing capability: media:read");
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function createBlockedMediaReadAccess(): MediaAccess {
|
|
949
|
+
return {
|
|
950
|
+
get: async () => mediaReadDenied(),
|
|
951
|
+
list: async () => mediaReadDenied(),
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
|
|
559
955
|
/**
|
|
560
956
|
* Create full media access with write operations.
|
|
561
957
|
*
|
|
@@ -689,30 +1085,62 @@ export function createMediaAccessWithWrite(
|
|
|
689
1085
|
/** Maximum number of redirects to follow in plugin HTTP access */
|
|
690
1086
|
const MAX_PLUGIN_REDIRECTS = 5;
|
|
691
1087
|
|
|
1088
|
+
function stripTrailingDots(value: string): string {
|
|
1089
|
+
let end = value.length;
|
|
1090
|
+
while (end > 0 && value.charCodeAt(end - 1) === 46) end--;
|
|
1091
|
+
return end === value.length ? value : value.slice(0, end);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
692
1094
|
/**
|
|
693
1095
|
* Check if a hostname matches any pattern in the allowed list.
|
|
694
1096
|
* Patterns: "*" matches all, "*.example.com" matches subdomains AND bare "example.com",
|
|
695
1097
|
* "api.example.com" matches exactly.
|
|
696
1098
|
*/
|
|
697
1099
|
function isHostAllowed(host: string, allowedHosts: string[]): boolean {
|
|
1100
|
+
const normalizedHost = stripTrailingDots(host.toLowerCase());
|
|
698
1101
|
return allowedHosts.some((pattern) => {
|
|
699
|
-
|
|
700
|
-
if (
|
|
701
|
-
|
|
1102
|
+
const normalizedPattern = stripTrailingDots(pattern.toLowerCase());
|
|
1103
|
+
if (normalizedPattern === "*") return true;
|
|
1104
|
+
if (normalizedPattern.startsWith("*.")) {
|
|
1105
|
+
const suffix = normalizedPattern.slice(1); // ".example.com"
|
|
702
1106
|
// Match subdomains (foo.example.com) and bare domain (example.com)
|
|
703
|
-
return
|
|
1107
|
+
return normalizedHost.endsWith(suffix) || normalizedHost === normalizedPattern.slice(2);
|
|
704
1108
|
}
|
|
705
|
-
return
|
|
1109
|
+
return normalizedHost === normalizedPattern;
|
|
706
1110
|
});
|
|
707
1111
|
}
|
|
708
1112
|
|
|
1113
|
+
function tryParsePluginHttpTarget(url: string): URL | null {
|
|
1114
|
+
try {
|
|
1115
|
+
return new URL(url);
|
|
1116
|
+
} catch {
|
|
1117
|
+
return null;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
async function validatePluginHttpTarget(pluginId: string, url: string): Promise<URL> {
|
|
1122
|
+
try {
|
|
1123
|
+
return await resolveAndValidateExternalUrl(url);
|
|
1124
|
+
} catch (error) {
|
|
1125
|
+
const message = error instanceof SsrfError ? error.message : "SSRF validation failed";
|
|
1126
|
+
const target = tryParsePluginHttpTarget(url);
|
|
1127
|
+
throw new Error(
|
|
1128
|
+
`Plugin "${pluginId}": blocked fetch to "${target ? target.hostname : "invalid URL"}": ${message}`,
|
|
1129
|
+
{ cause: error },
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
|
|
709
1134
|
/**
|
|
710
|
-
* Create HTTP access with host validation.
|
|
1135
|
+
* Create HTTP access with host validation and SSRF protection.
|
|
711
1136
|
*
|
|
712
|
-
* Uses redirect: "manual" to re-validate each redirect target
|
|
713
|
-
* the allowedHosts list, preventing redirects to unauthorized hosts.
|
|
1137
|
+
* Uses redirect: "manual" to re-validate each redirect target before dispatch.
|
|
714
1138
|
*/
|
|
715
|
-
export function createHttpAccess(
|
|
1139
|
+
export function createHttpAccess(
|
|
1140
|
+
pluginId: string,
|
|
1141
|
+
allowedHosts: string[],
|
|
1142
|
+
fetchImpl: typeof fetch = globalThis.fetch,
|
|
1143
|
+
): HttpAccess {
|
|
716
1144
|
return {
|
|
717
1145
|
async fetch(url: string, init?: RequestInit): Promise<Response> {
|
|
718
1146
|
// Deny by default — plugins must declare allowed hosts
|
|
@@ -725,36 +1153,51 @@ export function createHttpAccess(pluginId: string, allowedHosts: string[]): Http
|
|
|
725
1153
|
|
|
726
1154
|
let currentUrl = url;
|
|
727
1155
|
let currentInit = init;
|
|
1156
|
+
let requestBuffered = false;
|
|
1157
|
+
let redirected = false;
|
|
728
1158
|
|
|
729
1159
|
for (let i = 0; i <= MAX_PLUGIN_REDIRECTS; i++) {
|
|
730
|
-
const
|
|
731
|
-
if (!isHostAllowed(hostname, allowedHosts)) {
|
|
1160
|
+
const target = tryParsePluginHttpTarget(currentUrl);
|
|
1161
|
+
if (target && !isHostAllowed(target.hostname, allowedHosts)) {
|
|
732
1162
|
throw new Error(
|
|
733
|
-
`Plugin "${pluginId}" is not allowed to fetch from host "${hostname}". ` +
|
|
1163
|
+
`Plugin "${pluginId}" is not allowed to fetch from host "${target.hostname}". ` +
|
|
734
1164
|
`Allowed hosts: ${allowedHosts.join(", ")}`,
|
|
735
1165
|
);
|
|
736
1166
|
}
|
|
1167
|
+
await validatePluginHttpTarget(pluginId, currentUrl);
|
|
1168
|
+
if (!requestBuffered) {
|
|
1169
|
+
currentInit = await bufferPluginHttpRequest(currentInit);
|
|
1170
|
+
requestBuffered = true;
|
|
1171
|
+
}
|
|
737
1172
|
|
|
738
|
-
const response = await
|
|
1173
|
+
const response = await fetchImpl(currentUrl, {
|
|
739
1174
|
...currentInit,
|
|
740
1175
|
redirect: "manual",
|
|
741
1176
|
});
|
|
742
1177
|
|
|
743
|
-
// Not a redirect -- return directly
|
|
744
|
-
if (response.status < 300 || response.status >= 400) {
|
|
745
|
-
return response;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
// Extract redirect target
|
|
749
1178
|
const location = response.headers.get("Location");
|
|
750
|
-
if (
|
|
751
|
-
return
|
|
1179
|
+
if (location === null) {
|
|
1180
|
+
return pluginHttpResponseFromWire(
|
|
1181
|
+
await pluginHttpResponseToWire(response, currentUrl, redirected),
|
|
1182
|
+
);
|
|
1183
|
+
}
|
|
1184
|
+
const redirectAction = pluginHttpRedirectAction(response.status, true, currentInit);
|
|
1185
|
+
if (redirectAction === "return") {
|
|
1186
|
+
return pluginHttpResponseFromWire(
|
|
1187
|
+
await pluginHttpResponseToWire(response, currentUrl, redirected),
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1190
|
+
await response.body?.cancel();
|
|
1191
|
+
if (redirectAction === "error") {
|
|
1192
|
+
throw new Error(`Plugin "${pluginId}": redirect mode is "error"`);
|
|
752
1193
|
}
|
|
753
1194
|
|
|
754
1195
|
// Resolve relative redirects; strip credentials on cross-origin hops
|
|
755
1196
|
const previousOrigin = new URL(currentUrl).origin;
|
|
756
1197
|
currentUrl = new URL(location, currentUrl).href;
|
|
1198
|
+
redirected = true;
|
|
757
1199
|
const nextOrigin = new URL(currentUrl).origin;
|
|
1200
|
+
currentInit = rewritePluginHttpRedirect(response.status, currentInit);
|
|
758
1201
|
|
|
759
1202
|
if (previousOrigin !== nextOrigin && currentInit) {
|
|
760
1203
|
currentInit = stripCredentialHeaders(currentInit);
|
|
@@ -767,49 +1210,56 @@ export function createHttpAccess(pluginId: string, allowedHosts: string[]): Http
|
|
|
767
1210
|
}
|
|
768
1211
|
|
|
769
1212
|
/**
|
|
770
|
-
* Create unrestricted HTTP access (for plugins with network:
|
|
1213
|
+
* Create unrestricted HTTP access (for plugins with network:request:unrestricted capability).
|
|
771
1214
|
* No host validation, but applies SSRF protection on redirect targets to
|
|
772
1215
|
* prevent plugins from being tricked into reaching internal services.
|
|
773
1216
|
*/
|
|
774
|
-
export function createUnrestrictedHttpAccess(
|
|
1217
|
+
export function createUnrestrictedHttpAccess(
|
|
1218
|
+
pluginId: string,
|
|
1219
|
+
fetchImpl: typeof fetch = globalThis.fetch,
|
|
1220
|
+
): HttpAccess {
|
|
775
1221
|
return {
|
|
776
1222
|
async fetch(url: string, init?: RequestInit): Promise<Response> {
|
|
777
1223
|
let currentUrl = url;
|
|
778
1224
|
let currentInit = init;
|
|
1225
|
+
let requestBuffered = false;
|
|
1226
|
+
let redirected = false;
|
|
779
1227
|
|
|
780
1228
|
for (let i = 0; i <= MAX_PLUGIN_REDIRECTS; i++) {
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
} catch (e) {
|
|
786
|
-
const msg = e instanceof SsrfError ? e.message : "SSRF validation failed";
|
|
787
|
-
throw new Error(
|
|
788
|
-
`Plugin "${pluginId}": blocked fetch to "${new URL(currentUrl).hostname}": ${msg}`,
|
|
789
|
-
{ cause: e },
|
|
790
|
-
);
|
|
1229
|
+
await validatePluginHttpTarget(pluginId, currentUrl);
|
|
1230
|
+
if (!requestBuffered) {
|
|
1231
|
+
currentInit = await bufferPluginHttpRequest(currentInit);
|
|
1232
|
+
requestBuffered = true;
|
|
791
1233
|
}
|
|
792
1234
|
|
|
793
|
-
const response = await
|
|
1235
|
+
const response = await fetchImpl(currentUrl, {
|
|
794
1236
|
...currentInit,
|
|
795
1237
|
redirect: "manual",
|
|
796
1238
|
});
|
|
797
1239
|
|
|
798
|
-
// Not a redirect -- return directly
|
|
799
|
-
if (response.status < 300 || response.status >= 400) {
|
|
800
|
-
return response;
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
// Extract redirect target
|
|
804
1240
|
const location = response.headers.get("Location");
|
|
805
|
-
if (
|
|
806
|
-
return
|
|
1241
|
+
if (location === null) {
|
|
1242
|
+
return pluginHttpResponseFromWire(
|
|
1243
|
+
await pluginHttpResponseToWire(response, currentUrl, redirected),
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
const redirectAction = pluginHttpRedirectAction(response.status, true, currentInit);
|
|
1247
|
+
if (redirectAction === "return") {
|
|
1248
|
+
return pluginHttpResponseFromWire(
|
|
1249
|
+
await pluginHttpResponseToWire(response, currentUrl, redirected),
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
await response.body?.cancel();
|
|
1253
|
+
if (redirectAction === "error") {
|
|
1254
|
+
throw new Error(`Plugin "${pluginId}": redirect mode is "error"`);
|
|
807
1255
|
}
|
|
808
1256
|
|
|
809
1257
|
// Resolve relative redirects; strip credentials on cross-origin hops
|
|
810
1258
|
const previousOrigin = new URL(currentUrl).origin;
|
|
811
1259
|
currentUrl = new URL(location, currentUrl).href;
|
|
1260
|
+
redirected = true;
|
|
812
1261
|
const nextOrigin = new URL(currentUrl).origin;
|
|
1262
|
+
currentInit = rewritePluginHttpRedirect(response.status, currentInit);
|
|
813
1263
|
|
|
814
1264
|
if (previousOrigin !== nextOrigin && currentInit) {
|
|
815
1265
|
currentInit = stripCredentialHeaders(currentInit);
|
|
@@ -842,39 +1292,40 @@ export function createBlockedHttpAccess(pluginId: string): HttpAccess {
|
|
|
842
1292
|
/**
|
|
843
1293
|
* Create logger for a plugin
|
|
844
1294
|
*/
|
|
845
|
-
export function createLogAccess(pluginId: string): LogAccess {
|
|
1295
|
+
export function createLogAccess(pluginId: string, redactor?: PluginSecretRedactor): LogAccess {
|
|
846
1296
|
const prefix = `[plugin:${pluginId}]`;
|
|
1297
|
+
const redact = <T>(value: T): T => redactor?.redact(value) ?? value;
|
|
847
1298
|
|
|
848
1299
|
return {
|
|
849
1300
|
debug(message: string, data?: unknown): void {
|
|
850
1301
|
if (data !== undefined) {
|
|
851
|
-
console.debug(prefix, message, data);
|
|
1302
|
+
console.debug(prefix, redact(message), redact(data));
|
|
852
1303
|
} else {
|
|
853
|
-
console.debug(prefix, message);
|
|
1304
|
+
console.debug(prefix, redact(message));
|
|
854
1305
|
}
|
|
855
1306
|
},
|
|
856
1307
|
|
|
857
1308
|
info(message: string, data?: unknown): void {
|
|
858
1309
|
if (data !== undefined) {
|
|
859
|
-
console.info(prefix, message, data);
|
|
1310
|
+
console.info(prefix, redact(message), redact(data));
|
|
860
1311
|
} else {
|
|
861
|
-
console.info(prefix, message);
|
|
1312
|
+
console.info(prefix, redact(message));
|
|
862
1313
|
}
|
|
863
1314
|
},
|
|
864
1315
|
|
|
865
1316
|
warn(message: string, data?: unknown): void {
|
|
866
1317
|
if (data !== undefined) {
|
|
867
|
-
console.warn(prefix, message, data);
|
|
1318
|
+
console.warn(prefix, redact(message), redact(data));
|
|
868
1319
|
} else {
|
|
869
|
-
console.warn(prefix, message);
|
|
1320
|
+
console.warn(prefix, redact(message));
|
|
870
1321
|
}
|
|
871
1322
|
},
|
|
872
1323
|
|
|
873
1324
|
error(message: string, data?: unknown): void {
|
|
874
1325
|
if (data !== undefined) {
|
|
875
|
-
console.error(prefix, message, data);
|
|
1326
|
+
console.error(prefix, redact(message), redact(data));
|
|
876
1327
|
} else {
|
|
877
|
-
console.error(prefix, message);
|
|
1328
|
+
console.error(prefix, redact(message));
|
|
878
1329
|
}
|
|
879
1330
|
},
|
|
880
1331
|
};
|
|
@@ -1005,6 +1456,8 @@ export function createUserAccess(db: Kysely<Database>): UserAccess {
|
|
|
1005
1456
|
export interface PluginContextFactoryOptions {
|
|
1006
1457
|
db: Kysely<Database>;
|
|
1007
1458
|
beforeContentWrite?: () => Promise<void>;
|
|
1459
|
+
contentCreate?: PluginContentCreateCallback;
|
|
1460
|
+
contentActions?: ContentActionCallbacks;
|
|
1008
1461
|
/**
|
|
1009
1462
|
* Resolver for the database connection, preferred over `db` when present.
|
|
1010
1463
|
* Called per `createContext()` so connection-backed adapters (e.g. Postgres
|
|
@@ -1040,6 +1493,8 @@ export interface PluginContextFactoryOptions {
|
|
|
1040
1493
|
* If not provided, ctx.cron will not be available.
|
|
1041
1494
|
*/
|
|
1042
1495
|
cronReschedule?: () => void;
|
|
1496
|
+
/** Clock used to calculate the first run of recurring plugin tasks. */
|
|
1497
|
+
now?: () => Date;
|
|
1043
1498
|
/**
|
|
1044
1499
|
* Email pipeline instance for ctx.email.
|
|
1045
1500
|
* If not provided (or no provider configured), ctx.email will be undefined.
|
|
@@ -1052,6 +1507,73 @@ export interface PluginContextFactoryOptions {
|
|
|
1052
1507
|
* client IP the core auth path does.
|
|
1053
1508
|
*/
|
|
1054
1509
|
trustedProxyHeaders?: string[];
|
|
1510
|
+
commentModerate?: (
|
|
1511
|
+
pluginId: string,
|
|
1512
|
+
id: string,
|
|
1513
|
+
status: PluginCommentStatus,
|
|
1514
|
+
expectedStatus: PluginCommentStatus,
|
|
1515
|
+
) => Promise<PluginComment>;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
export interface ContentActionCallbacks {
|
|
1519
|
+
/** Register a sandbox invocation before it can call a content action. */
|
|
1520
|
+
begin?(
|
|
1521
|
+
pluginId: string,
|
|
1522
|
+
invocationId: string,
|
|
1523
|
+
invalidateContentCache?: (tags: string[]) => Promise<void>,
|
|
1524
|
+
): void;
|
|
1525
|
+
/** Release queued after-hooks; `final: false` keeps late actions self-scheduling after timeout. */
|
|
1526
|
+
flush(pluginId: string, invocationId?: string, final?: boolean): Promise<void>;
|
|
1527
|
+
getVersioned(
|
|
1528
|
+
pluginId: string,
|
|
1529
|
+
collection: string,
|
|
1530
|
+
id: string,
|
|
1531
|
+
): Promise<VersionedContentItem | null>;
|
|
1532
|
+
publish(
|
|
1533
|
+
pluginId: string,
|
|
1534
|
+
collection: string,
|
|
1535
|
+
id: string,
|
|
1536
|
+
options: { _rev: string },
|
|
1537
|
+
invocationId?: string,
|
|
1538
|
+
invalidateContentCache?: (tags: string[]) => Promise<void>,
|
|
1539
|
+
): Promise<VersionedContentItem>;
|
|
1540
|
+
unpublish(
|
|
1541
|
+
pluginId: string,
|
|
1542
|
+
collection: string,
|
|
1543
|
+
id: string,
|
|
1544
|
+
options: { _rev: string },
|
|
1545
|
+
invocationId?: string,
|
|
1546
|
+
invalidateContentCache?: (tags: string[]) => Promise<void>,
|
|
1547
|
+
): Promise<VersionedContentItem>;
|
|
1548
|
+
schedule(
|
|
1549
|
+
pluginId: string,
|
|
1550
|
+
collection: string,
|
|
1551
|
+
id: string,
|
|
1552
|
+
options: { scheduledAt: string; _rev: string },
|
|
1553
|
+
invocationId?: string,
|
|
1554
|
+
invalidateContentCache?: (tags: string[]) => Promise<void>,
|
|
1555
|
+
): Promise<VersionedContentItem>;
|
|
1556
|
+
unschedule(
|
|
1557
|
+
pluginId: string,
|
|
1558
|
+
collection: string,
|
|
1559
|
+
id: string,
|
|
1560
|
+
options: { _rev: string },
|
|
1561
|
+
invocationId?: string,
|
|
1562
|
+
invalidateContentCache?: (tags: string[]) => Promise<void>,
|
|
1563
|
+
): Promise<VersionedContentItem>;
|
|
1564
|
+
getTrashedVersioned(
|
|
1565
|
+
pluginId: string,
|
|
1566
|
+
collection: string,
|
|
1567
|
+
id: string,
|
|
1568
|
+
): Promise<VersionedContentItem | null>;
|
|
1569
|
+
restore(
|
|
1570
|
+
pluginId: string,
|
|
1571
|
+
collection: string,
|
|
1572
|
+
id: string,
|
|
1573
|
+
options: { _rev: string },
|
|
1574
|
+
invocationId?: string,
|
|
1575
|
+
invalidateContentCache?: (tags: string[]) => Promise<void>,
|
|
1576
|
+
): Promise<VersionedContentItem>;
|
|
1055
1577
|
}
|
|
1056
1578
|
|
|
1057
1579
|
/**
|
|
@@ -1060,6 +1582,8 @@ export interface PluginContextFactoryOptions {
|
|
|
1060
1582
|
export class PluginContextFactory {
|
|
1061
1583
|
private resolveDb: () => Kysely<Database>;
|
|
1062
1584
|
private beforeContentWrite?: () => Promise<void>;
|
|
1585
|
+
private contentCreate?: PluginContentCreateCallback;
|
|
1586
|
+
private contentActions?: ContentActionCallbacks;
|
|
1063
1587
|
private storage?: Storage;
|
|
1064
1588
|
private getUploadUrl?: (
|
|
1065
1589
|
filename: string,
|
|
@@ -1068,7 +1592,9 @@ export class PluginContextFactory {
|
|
|
1068
1592
|
private site: SiteInfo;
|
|
1069
1593
|
private urlHelper: (path: string) => string;
|
|
1070
1594
|
private cronReschedule?: () => void;
|
|
1595
|
+
private now: () => Date;
|
|
1071
1596
|
private emailPipeline?: EmailPipeline;
|
|
1597
|
+
private commentModerate?: PluginContextFactoryOptions["commentModerate"];
|
|
1072
1598
|
/**
|
|
1073
1599
|
* Plugin IDs already warned about a missing media-write backend, so the
|
|
1074
1600
|
* warning fires once per factory instead of on every hook/route context
|
|
@@ -1080,12 +1606,16 @@ export class PluginContextFactory {
|
|
|
1080
1606
|
const fixedDb = options.db;
|
|
1081
1607
|
this.resolveDb = options.getDb ?? (() => fixedDb);
|
|
1082
1608
|
this.beforeContentWrite = options.beforeContentWrite;
|
|
1609
|
+
this.contentCreate = options.contentCreate;
|
|
1610
|
+
this.contentActions = options.contentActions;
|
|
1083
1611
|
this.storage = options.storage;
|
|
1084
1612
|
this.getUploadUrl = options.getUploadUrl;
|
|
1085
1613
|
this.site = createSiteInfo(options.siteInfo ?? {});
|
|
1086
1614
|
this.urlHelper = createUrlHelper(this.site.url);
|
|
1087
1615
|
this.cronReschedule = options.cronReschedule;
|
|
1616
|
+
this.now = options.now ?? (() => new Date());
|
|
1088
1617
|
this.emailPipeline = options.emailPipeline;
|
|
1618
|
+
this.commentModerate = options.commentModerate;
|
|
1089
1619
|
}
|
|
1090
1620
|
|
|
1091
1621
|
/**
|
|
@@ -1102,8 +1632,16 @@ export class PluginContextFactory {
|
|
|
1102
1632
|
const optionsRepo = new OptionsRepository(db);
|
|
1103
1633
|
|
|
1104
1634
|
// Always available
|
|
1105
|
-
const
|
|
1106
|
-
const
|
|
1635
|
+
const secretRedactor = createPluginSecretRedactor();
|
|
1636
|
+
const settings = createSettingsAccess(
|
|
1637
|
+
optionsRepo,
|
|
1638
|
+
plugin.id,
|
|
1639
|
+
plugin.admin.settingsSchema ?? {},
|
|
1640
|
+
undefined,
|
|
1641
|
+
secretRedactor.add,
|
|
1642
|
+
);
|
|
1643
|
+
const kv = createKVAccess(optionsRepo, plugin.id, settings);
|
|
1644
|
+
const log = createLogAccess(plugin.id, secretRedactor);
|
|
1107
1645
|
const storage = createStorageAccess(db, plugin.id, plugin.storage);
|
|
1108
1646
|
|
|
1109
1647
|
// Capability-gated: content
|
|
@@ -1112,23 +1650,93 @@ export class PluginContextFactory {
|
|
|
1112
1650
|
// names ("read:content", "write:content") never appear here.
|
|
1113
1651
|
let content: ContentAccess | ContentAccessWithWrite | undefined;
|
|
1114
1652
|
if (capabilities.has("content:write")) {
|
|
1115
|
-
content = createContentAccessWithWrite(
|
|
1653
|
+
content = createContentAccessWithWrite(
|
|
1654
|
+
db,
|
|
1655
|
+
this.beforeContentWrite,
|
|
1656
|
+
{
|
|
1657
|
+
site: this.site,
|
|
1658
|
+
revisions: capabilities.has("content:revisions:read"),
|
|
1659
|
+
},
|
|
1660
|
+
this.contentCreate
|
|
1661
|
+
? (input) => this.contentCreate!(plugin.id, input.collection, input.input, input.options)
|
|
1662
|
+
: undefined,
|
|
1663
|
+
);
|
|
1116
1664
|
} else if (capabilities.has("content:read")) {
|
|
1117
|
-
content = createContentAccess(db
|
|
1665
|
+
content = createContentAccess(db, {
|
|
1666
|
+
site: this.site,
|
|
1667
|
+
revisions: capabilities.has("content:revisions:read"),
|
|
1668
|
+
});
|
|
1669
|
+
}
|
|
1670
|
+
if (capabilities.has("content:publish") && this.contentActions) {
|
|
1671
|
+
content = Object.assign(content ?? createContentAccess(db), {
|
|
1672
|
+
getVersioned: (collection: string, id: string) =>
|
|
1673
|
+
this.contentActions!.getVersioned(plugin.id, collection, id),
|
|
1674
|
+
publish: (collection: string, id: string, options: { _rev: string }) =>
|
|
1675
|
+
this.contentActions!.publish(plugin.id, collection, id, options),
|
|
1676
|
+
unpublish: (collection: string, id: string, options: { _rev: string }) =>
|
|
1677
|
+
this.contentActions!.unpublish(plugin.id, collection, id, options),
|
|
1678
|
+
schedule: (
|
|
1679
|
+
collection: string,
|
|
1680
|
+
id: string,
|
|
1681
|
+
options: { scheduledAt: string; _rev: string },
|
|
1682
|
+
) => this.contentActions!.schedule(plugin.id, collection, id, options),
|
|
1683
|
+
unschedule: (collection: string, id: string, options: { _rev: string }) =>
|
|
1684
|
+
this.contentActions!.unschedule(plugin.id, collection, id, options),
|
|
1685
|
+
});
|
|
1686
|
+
}
|
|
1687
|
+
if (capabilities.has("content:restore") && this.contentActions) {
|
|
1688
|
+
content = Object.assign(
|
|
1689
|
+
content ?? {
|
|
1690
|
+
get: async () => {
|
|
1691
|
+
throw new Error("Missing capability: content:read");
|
|
1692
|
+
},
|
|
1693
|
+
list: async () => {
|
|
1694
|
+
throw new Error("Missing capability: content:read");
|
|
1695
|
+
},
|
|
1696
|
+
},
|
|
1697
|
+
{
|
|
1698
|
+
getTrashedVersioned: (collection: string, id: string) =>
|
|
1699
|
+
this.contentActions!.getTrashedVersioned(plugin.id, collection, id),
|
|
1700
|
+
restore: (collection: string, id: string, options: { _rev: string }) =>
|
|
1701
|
+
this.contentActions!.restore(plugin.id, collection, id, options),
|
|
1702
|
+
},
|
|
1703
|
+
);
|
|
1118
1704
|
}
|
|
1119
1705
|
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1706
|
+
const schema = capabilities.has("schema:read") ? createSchemaAccess(db) : undefined;
|
|
1707
|
+
|
|
1708
|
+
// Capability-gated: taxonomies
|
|
1709
|
+
let taxonomies: TaxonomyAccess | TaxonomyAccessWithWrite | undefined;
|
|
1710
|
+
if (capabilities.has("taxonomies:write")) {
|
|
1711
|
+
taxonomies = createTaxonomyAccessWithWrite(db);
|
|
1712
|
+
} else if (capabilities.has("taxonomies:read")) {
|
|
1123
1713
|
taxonomies = createTaxonomyAccess(db);
|
|
1124
1714
|
}
|
|
1125
1715
|
|
|
1716
|
+
let redirects: RedirectAccess | RedirectAccessWithWrite | undefined;
|
|
1717
|
+
if (capabilities.has("redirects:write")) {
|
|
1718
|
+
redirects = createRedirectAccess(db, true);
|
|
1719
|
+
} else if (capabilities.has("redirects:read")) {
|
|
1720
|
+
redirects = createRedirectAccess(db);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1126
1723
|
// Capability-gated: media
|
|
1127
1724
|
// `upload()` only needs `storage`; `getUploadUrl()` is derived from
|
|
1128
1725
|
// storage when no explicit provider is wired. Granting write access on
|
|
1129
1726
|
// either avoids silently degrading media:write to read-only — the bug
|
|
1130
1727
|
// where the runtime threads `storage` but not `getUploadUrl`.
|
|
1131
1728
|
let media: MediaAccess | MediaAccessWithWrite | undefined;
|
|
1729
|
+
const hasMediaAccess =
|
|
1730
|
+
capabilities.has("media:read") ||
|
|
1731
|
+
capabilities.has("media:write") ||
|
|
1732
|
+
capabilities.has("media:bytes:read") ||
|
|
1733
|
+
capabilities.has("media:metadata:write");
|
|
1734
|
+
if (hasMediaAccess) {
|
|
1735
|
+
media =
|
|
1736
|
+
capabilities.has("media:read") || capabilities.has("media:write")
|
|
1737
|
+
? createMediaAccess(db)
|
|
1738
|
+
: createBlockedMediaReadAccess();
|
|
1739
|
+
}
|
|
1132
1740
|
if (capabilities.has("media:write")) {
|
|
1133
1741
|
if (this.getUploadUrl || this.storage) {
|
|
1134
1742
|
media = createMediaAccessWithWrite(db, this.getUploadUrl, this.storage);
|
|
@@ -1139,12 +1747,14 @@ export class PluginContextFactory {
|
|
|
1139
1747
|
"declares the media:write capability but no storage backend is configured; upload() is unavailable.",
|
|
1140
1748
|
);
|
|
1141
1749
|
}
|
|
1142
|
-
|
|
1143
|
-
media = createMediaAccess(db);
|
|
1144
|
-
}
|
|
1750
|
+
media ??= createMediaAccess(db);
|
|
1145
1751
|
}
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1752
|
+
}
|
|
1753
|
+
if (capabilities.has("media:bytes:read") && media) {
|
|
1754
|
+
media.readBytes = (id, options) => readPluginMediaBytes(db, this.storage, id, options);
|
|
1755
|
+
}
|
|
1756
|
+
if (capabilities.has("media:metadata:write") && media) {
|
|
1757
|
+
media.updateMetadata = (id, patch) => updatePluginMediaMetadata(db, id, patch);
|
|
1148
1758
|
}
|
|
1149
1759
|
|
|
1150
1760
|
// Capability-gated: http
|
|
@@ -1161,11 +1771,21 @@ export class PluginContextFactory {
|
|
|
1161
1771
|
users = createUserAccess(db);
|
|
1162
1772
|
}
|
|
1163
1773
|
|
|
1774
|
+
let comments: CommentAccess | undefined;
|
|
1775
|
+
if (capabilities.has("comments:moderate")) {
|
|
1776
|
+
comments = createCommentAccess(db, (id, status, expectedStatus) => {
|
|
1777
|
+
if (!this.commentModerate) throw new Error("Comment moderation is unavailable");
|
|
1778
|
+
return this.commentModerate(plugin.id, id, status, expectedStatus);
|
|
1779
|
+
});
|
|
1780
|
+
} else if (capabilities.has("comments:read")) {
|
|
1781
|
+
comments = createCommentAccess(db);
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1164
1784
|
// Cron access — always available (scoped to plugin), but only if
|
|
1165
1785
|
// the runtime provided a reschedule callback (i.e. cron is wired up).
|
|
1166
1786
|
let cron: CronAccess | undefined;
|
|
1167
1787
|
if (this.cronReschedule) {
|
|
1168
|
-
cron = new CronAccessImpl(db, plugin.id, this.cronReschedule);
|
|
1788
|
+
cron = new CronAccessImpl(db, plugin.id, this.cronReschedule, this.now);
|
|
1169
1789
|
}
|
|
1170
1790
|
|
|
1171
1791
|
// Email access — requires email:send capability AND a configured provider
|
|
@@ -1185,14 +1805,18 @@ export class PluginContextFactory {
|
|
|
1185
1805
|
},
|
|
1186
1806
|
storage,
|
|
1187
1807
|
kv,
|
|
1808
|
+
settings,
|
|
1188
1809
|
content,
|
|
1810
|
+
schema,
|
|
1189
1811
|
taxonomies,
|
|
1812
|
+
redirects,
|
|
1190
1813
|
media,
|
|
1191
1814
|
http,
|
|
1192
1815
|
log,
|
|
1193
1816
|
site: this.site,
|
|
1194
1817
|
url: this.urlHelper,
|
|
1195
1818
|
users,
|
|
1819
|
+
comments,
|
|
1196
1820
|
cron,
|
|
1197
1821
|
email,
|
|
1198
1822
|
};
|