emdash 0.28.1 → 0.30.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/{adapters-hUy8vOB-.d.mts → adapters-C0ONzkUP.d.mts} +10 -1
- package/dist/adapters-C0ONzkUP.d.mts.map +1 -0
- package/dist/{allowed-origins-CRsJ6BPM.mjs → allowed-origins-CCEi9bPI.mjs} +2 -2
- package/dist/{allowed-origins-CRsJ6BPM.mjs.map → allowed-origins-CCEi9bPI.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.d.mts.map +1 -1
- package/dist/api/route-utils.mjs +22 -21
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +5 -4
- package/dist/{api-DxFSorgk.mjs → api-b8WIiGU4.mjs} +306 -154
- package/dist/api-b8WIiGU4.mjs.map +1 -0
- package/dist/api-tokens-Cvmixds7.mjs +3 -0
- package/dist/{api-tokens-DvqeZmVq.mjs → api-tokens-uPt8UDpx.mjs} +2 -2
- package/dist/{api-tokens-DvqeZmVq.mjs.map → api-tokens-uPt8UDpx.mjs.map} +1 -1
- package/dist/{apply-CDJqIjPU.mjs → apply-CmIJK9j8.mjs} +35 -38
- package/dist/apply-CmIJK9j8.mjs.map +1 -0
- package/dist/astro/index.d.mts +12 -12
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +97 -13
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -10
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +56 -107
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.mjs +7 -7
- package/dist/astro/middleware/request-context.d.mts +3 -0
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +258 -31
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +47 -3
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +379 -117
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/PluginRegistry.d.mts +5 -1
- package/dist/astro/routes/PluginRegistry.d.mts.map +1 -1
- package/dist/astro/routes/PluginRegistry.mjs +2 -1
- package/dist/astro/routes/PluginRegistry.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +9 -8
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +9 -8
- 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 +7 -7
- package/dist/astro/routes/api/admin/api-tokens/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +11 -10
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +11 -10
- package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +11 -10
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +18 -17
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +19 -24
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +18 -17
- 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 +14 -13
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/bulk.mjs +11 -10
- package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/comments/index.mjs +11 -10
- 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/repair.d.mts +8 -0
- package/dist/astro/routes/api/admin/media-usage/repair.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs +30 -0
- package/dist/astro/routes/api/admin/media-usage/repair.mjs.map +1 -0
- 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.mjs +44 -41
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +44 -41
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +49 -41
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.d.mts +8 -0
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +39 -0
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs.map +1 -0
- package/dist/astro/routes/api/admin/plugins/_id_/settings.d.mts +9 -0
- package/dist/astro/routes/api/admin/plugins/_id_/settings.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +78 -0
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs.map +1 -0
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +43 -40
- 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 +46 -41
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +49 -41
- 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 +43 -40
- 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 +49 -42
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +43 -40
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +43 -40
- 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 +47 -42
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +43 -40
- 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 +48 -43
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +44 -41
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +43 -40
- 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 +43 -40
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +5 -5
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +10 -9
- package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +6 -6
- package/dist/astro/routes/api/admin/users/index.mjs +9 -8
- package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +7 -7
- package/dist/astro/routes/api/auth/invite/accept.mjs +4 -4
- package/dist/astro/routes/api/auth/invite/complete.mjs +14 -13
- package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/index.mjs +11 -10
- package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +13 -12
- 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 +13 -12
- package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +5 -5
- package/dist/astro/routes/api/auth/me.mjs +9 -8
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- package/dist/astro/routes/api/auth/mode.d.mts.map +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +6 -3
- package/dist/astro/routes/api/auth/mode.mjs.map +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +16 -6
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs.map +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_.d.mts.map +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +11 -5
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +8 -7
- 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 +14 -13
- package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +12 -11
- package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +13 -12
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/verify.mjs +13 -12
- package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/complete.mjs +14 -13
- package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/request.mjs +13 -12
- package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/verify.mjs +4 -4
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +70 -14
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +14 -13
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +5 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +6 -5
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +14 -13
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +10 -8
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts +9 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +72 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.d.mts +8 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +51 -0
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +5 -4
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +10 -8
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +20 -19
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +5 -4
- 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 +11 -9
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +5 -5
- package/dist/astro/routes/api/content/_collection_/authors.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/index.mjs +12 -10
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +10 -9
- package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
- package/dist/astro/routes/api/dashboard.mjs +8 -8
- package/dist/astro/routes/api/dev/emails.mjs +4 -4
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +19 -18
- 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 +11 -11
- package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -16
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/media.mjs +12 -11
- package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +12 -11
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +11 -16
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +12 -11
- 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 +19 -18
- 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 +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +29 -28
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +8 -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 +165 -52
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +10 -9
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/usage.d.mts +8 -0
- package/dist/astro/routes/api/media/_id_/usage.d.mts.map +1 -0
- package/dist/astro/routes/api/media/_id_/usage.mjs +37 -0
- package/dist/astro/routes/api/media/_id_/usage.mjs.map +1 -0
- package/dist/astro/routes/api/media/_id_.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +26 -10
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +4 -3
- package/dist/astro/routes/api/media/file/_...key_.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 +11 -10
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.d.mts.map +1 -1
- package/dist/astro/routes/api/media.mjs +34 -14
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +10 -9
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +10 -9
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +10 -9
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +10 -9
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +10 -9
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +10 -9
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.d.mts.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +7 -8
- package/dist/astro/routes/api/oauth/authorize.mjs.map +1 -1
- 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 +71 -24
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.d.mts.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +20 -32
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/index.mjs +13 -12
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +13 -12
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +14 -13
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +14 -13
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/relations/_id_/index.d.mts +10 -0
- package/dist/astro/routes/api/relations/_id_/index.d.mts.map +1 -0
- package/dist/astro/routes/api/relations/_id_/index.mjs +70 -0
- package/dist/astro/routes/api/relations/_id_/index.mjs.map +1 -0
- package/dist/astro/routes/api/relations/_id_/translations.d.mts +8 -0
- package/dist/astro/routes/api/relations/_id_/translations.d.mts.map +1 -0
- package/dist/astro/routes/api/relations/_id_/translations.mjs +34 -0
- package/dist/astro/routes/api/relations/_id_/translations.mjs.map +1 -0
- package/dist/astro/routes/api/relations/index.d.mts +9 -0
- package/dist/astro/routes/api/relations/index.d.mts.map +1 -0
- package/dist/astro/routes/api/relations/index.mjs +54 -0
- package/dist/astro/routes/api/relations/index.mjs.map +1 -0
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +5 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.d.mts.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +43 -40
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.d.mts.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +43 -40
- 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 +43 -40
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +43 -40
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +43 -40
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +9 -9
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +43 -40
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +43 -40
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +13 -12
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +14 -12
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +13 -12
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +8 -8
- package/dist/astro/routes/api/search/suggest.mjs +12 -11
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +12 -11
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +12 -11
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/backups/archives/_name_.d.mts +9 -0
- package/dist/astro/routes/api/settings/backups/archives/_name_.d.mts.map +1 -0
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +48 -0
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs.map +1 -0
- package/dist/astro/routes/api/settings/backups/archives/index.d.mts +8 -0
- package/dist/astro/routes/api/settings/backups/archives/index.d.mts.map +1 -0
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +23 -0
- package/dist/astro/routes/api/settings/backups/archives/index.mjs.map +1 -0
- package/dist/astro/routes/api/settings/backups/export.d.mts +8 -0
- package/dist/astro/routes/api/settings/backups/export.d.mts.map +1 -0
- package/dist/astro/routes/api/settings/backups/export.mjs +35 -0
- package/dist/astro/routes/api/settings/backups/export.mjs.map +1 -0
- package/dist/astro/routes/api/settings/backups/index.d.mts +9 -0
- package/dist/astro/routes/api/settings/backups/index.d.mts.map +1 -0
- package/dist/astro/routes/api/settings/backups/index.mjs +52 -0
- package/dist/astro/routes/api/settings/backups/index.mjs.map +1 -0
- package/dist/astro/routes/api/settings/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +16 -15
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +20 -16
- package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin.mjs +19 -15
- package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +29 -29
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +31 -30
- 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 +9 -216
- package/dist/astro/routes/api/snapshot.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +16 -15
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +7 -7
- package/dist/astro/routes/api/typegen.mjs +6 -6
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.d.mts.map +1 -1
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +4 -3
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs.map +1 -1
- package/dist/astro/routes/api/well-known/oauth-protected-resource.d.mts.map +1 -1
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +4 -3
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +9 -8
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +13 -12
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/index.mjs +13 -12
- 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 +9 -9
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +12 -12
- package/dist/astro/routes/sitemap.xml.mjs +10 -10
- package/dist/astro/types.d.mts +40 -16
- 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/{authorize-Dz88F_Fw.mjs → authorize-WxsiePzy.mjs} +7 -4
- package/dist/authorize-WxsiePzy.mjs.map +1 -0
- package/dist/backup-S8kFWtwD.mjs +241 -0
- package/dist/backup-S8kFWtwD.mjs.map +1 -0
- package/dist/{base64-CmWvODNW.mjs → base64-B-PsqheR.mjs} +8 -4
- package/dist/base64-B-PsqheR.mjs.map +1 -0
- package/dist/{byline-Bm8ZgUP9.mjs → byline-XEjchwzZ.mjs} +8 -8
- package/dist/{byline-Bm8ZgUP9.mjs.map → byline-XEjchwzZ.mjs.map} +1 -1
- package/dist/{byline-fields-CIx_GuN4.mjs → byline-fields-CdU_LTF1.mjs} +2 -2
- package/dist/{byline-fields-CIx_GuN4.mjs.map → byline-fields-CdU_LTF1.mjs.map} +1 -1
- package/dist/{byline-registry-BOjqDOim.mjs → byline-registry-BCuOp4UF.mjs} +3 -3
- package/dist/{byline-registry-BOjqDOim.mjs.map → byline-registry-BCuOp4UF.mjs.map} +1 -1
- package/dist/{bylines-6tm9mgQb.mjs → bylines-BJbT4gKS.mjs} +4 -4
- package/dist/{bylines-6tm9mgQb.mjs.map → bylines-BJbT4gKS.mjs.map} +1 -1
- package/dist/{bylines-CAZxGSrm.mjs → bylines-czseViYo.mjs} +8 -8
- package/dist/{bylines-CAZxGSrm.mjs.map → bylines-czseViYo.mjs.map} +1 -1
- package/dist/{cache-CEBAZjir.mjs → cache-CGCd6AVM.mjs} +3 -3
- package/dist/{cache-CEBAZjir.mjs.map → cache-CGCd6AVM.mjs.map} +1 -1
- package/dist/{challenge-store-anhwVER0.mjs → challenge-store-BFzgFRog.mjs} +1 -1
- package/dist/{challenge-store-anhwVER0.mjs.map → challenge-store-BFzgFRog.mjs.map} +1 -1
- package/dist/{chunks-B2isWQhr.mjs → chunks-BxXyunY-.mjs} +2 -2
- package/dist/{chunks-B2isWQhr.mjs.map → chunks-BxXyunY-.mjs.map} +1 -1
- package/dist/cli/index.mjs +142 -35
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +86 -3
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +20 -4
- package/dist/client/index.mjs.map +1 -1
- package/dist/{comment-CzeatwBV.mjs → comment-DPT0WKyd.mjs} +2 -2
- package/dist/{comment-CzeatwBV.mjs.map → comment-DPT0WKyd.mjs.map} +1 -1
- package/dist/{comment-reaction-Cj9QJY7I.mjs → comment-reaction-C65MldIB.mjs} +2 -2
- package/dist/{comment-reaction-Cj9QJY7I.mjs.map → comment-reaction-C65MldIB.mjs.map} +1 -1
- package/dist/{comments-BLE-jv5k.mjs → comments-Bz6sCbgD.mjs} +3 -3
- package/dist/{comments-BLE-jv5k.mjs.map → comments-Bz6sCbgD.mjs.map} +1 -1
- package/dist/{components-B_sATNUc.mjs → components-DZkL4Fx0.mjs} +1 -1
- package/dist/{components-B_sATNUc.mjs.map → components-DZkL4Fx0.mjs.map} +1 -1
- package/dist/{content-DhgEth4k.mjs → content-Ci04z2z-.mjs} +227 -34
- package/dist/content-Ci04z2z-.mjs.map +1 -0
- package/dist/{content-refresh-Br4gMzh8.mjs → content-refresh-D4khvC0R.mjs} +100 -8
- package/dist/content-refresh-D4khvC0R.mjs.map +1 -0
- package/dist/{context-BRIpHARC.mjs → context-B6hc7zJL.mjs} +156 -76
- package/dist/context-B6hc7zJL.mjs.map +1 -0
- package/dist/{cron-v4FTEFR_.mjs → cron-BlKIMD_e.mjs} +1 -1
- package/dist/{cron-v4FTEFR_.mjs.map → cron-BlKIMD_e.mjs.map} +1 -1
- package/dist/{dashboard-EvEKF5en.mjs → dashboard-C5NkXFbi.mjs} +6 -5
- package/dist/dashboard-C5NkXFbi.mjs.map +1 -0
- package/dist/database/pg-migration-lock.d.mts +21 -0
- package/dist/database/pg-migration-lock.d.mts.map +1 -0
- package/dist/database/pg-migration-lock.mjs +45 -0
- package/dist/database/pg-migration-lock.mjs.map +1 -0
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +2 -2
- package/dist/db/index.mjs.map +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/postgres.d.mts.map +1 -1
- package/dist/db/postgres.mjs +2 -8
- package/dist/db/postgres.mjs.map +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{db-errors-CK46D-ly.mjs → db-errors-CcWLaRiR.mjs} +4 -2
- package/dist/db-errors-CcWLaRiR.mjs.map +1 -0
- package/dist/{default-CM_D83Mg.mjs → default-C4v9KP56.mjs} +1 -1
- package/dist/{default-CM_D83Mg.mjs.map → default-C4v9KP56.mjs.map} +1 -1
- package/dist/{device-flow-CfGP18Uw.mjs → device-flow-BeA6lUS1.mjs} +6 -7
- package/dist/device-flow-BeA6lUS1.mjs.map +1 -0
- package/dist/dialect-helpers-HxEQGl_1.mjs +175 -0
- package/dist/dialect-helpers-HxEQGl_1.mjs.map +1 -0
- package/dist/{email-console-CIf4Lfvv.mjs → email-console-C-9Ng8DM.mjs} +1 -1
- package/dist/{email-console-CIf4Lfvv.mjs.map → email-console-C-9Ng8DM.mjs.map} +1 -1
- package/dist/{enrich-BQ0mxJRs.mjs → enrich-CFJJgxs_.mjs} +2 -2
- package/dist/{enrich-BQ0mxJRs.mjs.map → enrich-CFJJgxs_.mjs.map} +1 -1
- package/dist/error-CEGF6UZb.mjs +90 -0
- package/dist/error-CEGF6UZb.mjs.map +1 -0
- package/dist/{error-CkAseSqZ.mjs → errors-DtEXIQQV.mjs} +24 -84
- package/dist/errors-DtEXIQQV.mjs.map +1 -0
- package/dist/{escape-DqD0aCKu.mjs → escape-CFedIB1C.mjs} +1 -1
- package/dist/{escape-DqD0aCKu.mjs.map → escape-CFedIB1C.mjs.map} +1 -1
- package/dist/{field-defs-cache-WUI88LX5.mjs → field-defs-cache-DvmlgP-D.mjs} +5 -5
- package/dist/{field-defs-cache-WUI88LX5.mjs.map → field-defs-cache-DvmlgP-D.mjs.map} +1 -1
- package/dist/{fts-manager-BbFaF_V8.mjs → fts-manager-DzqIBrrW.mjs} +27 -3
- package/dist/{fts-manager-BbFaF_V8.mjs.map → fts-manager-DzqIBrrW.mjs.map} +1 -1
- package/dist/{hash-DrvzIXcz.mjs → hash-DFFrkivP.mjs} +1 -1
- package/dist/{hash-DrvzIXcz.mjs.map → hash-DFFrkivP.mjs.map} +1 -1
- package/dist/hreflang-CIxH_LKz.d.mts +48 -0
- package/dist/hreflang-CIxH_LKz.d.mts.map +1 -0
- package/dist/hreflang-db2Tpb2o.mjs +102 -0
- package/dist/hreflang-db2Tpb2o.mjs.map +1 -0
- package/dist/{import-fYLf14Co.mjs → import-Dmkm8S1W.mjs} +6 -6
- package/dist/{import-fYLf14Co.mjs.map → import-Dmkm8S1W.mjs.map} +1 -1
- package/dist/{index-Bm-Gy8Mh.d.mts → index-BEui-cRd.d.mts} +3 -3
- package/dist/{index-Bm-Gy8Mh.d.mts.map → index-BEui-cRd.d.mts.map} +1 -1
- package/dist/{index-B9sIxwe4.d.mts → index-wYnC6u4o.d.mts} +881 -22
- package/dist/index-wYnC6u4o.d.mts.map +1 -0
- package/dist/index.d.mts +19 -19
- package/dist/index.mjs +69 -64
- package/dist/{init-lock-6b309ZrF.mjs → init-lock-DJkX6Hto.mjs} +1 -1
- package/dist/{init-lock-6b309ZrF.mjs.map → init-lock-DJkX6Hto.mjs.map} +1 -1
- package/dist/{load-Djn3HWQS.mjs → load-Cx27ki1l.mjs} +2 -2
- package/dist/{load-Djn3HWQS.mjs.map → load-Cx27ki1l.mjs.map} +1 -1
- package/dist/{loader-CB6YHeul.mjs → loader-Be3ouI5L.mjs} +170 -21
- package/dist/loader-Be3ouI5L.mjs.map +1 -0
- package/dist/{manifest-schema-BHlgZM1W.mjs → manifest-schema-bCq54i7F.mjs} +18 -2
- package/dist/manifest-schema-bCq54i7F.mjs.map +1 -0
- package/dist/media/image-endpoint.d.mts +30 -2
- package/dist/media/image-endpoint.d.mts.map +1 -1
- package/dist/media/image-endpoint.mjs +30 -4
- package/dist/media/image-endpoint.mjs.map +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +12 -12
- package/dist/media/local-runtime.mjs +8 -8
- package/dist/{media-BrXIaMFN.mjs → media-BjhhENaJ.mjs} +2 -2
- package/dist/media-BjhhENaJ.mjs.map +1 -0
- package/dist/{media-allowlist-CRHEeJ_i.mjs → media-allowlist-jUppPWFy.mjs} +2 -2
- package/dist/{media-allowlist-CRHEeJ_i.mjs.map → media-allowlist-jUppPWFy.mjs.map} +1 -1
- package/dist/media-kIV1IxFf.mjs +243 -0
- package/dist/media-kIV1IxFf.mjs.map +1 -0
- package/dist/media-upload-D2wk3EIt.mjs +145 -0
- package/dist/media-upload-D2wk3EIt.mjs.map +1 -0
- package/dist/{media-url-CKi5XSw4.mjs → media-url-BCm5vBn6.mjs} +1 -1
- package/dist/{media-url-CKi5XSw4.mjs.map → media-url-BCm5vBn6.mjs.map} +1 -1
- package/dist/media-usage-CljdO1mc.mjs +554 -0
- package/dist/media-usage-CljdO1mc.mjs.map +1 -0
- package/dist/{menus-b2T4clbO.mjs → menus-BcyElFtI.mjs} +177 -15
- package/dist/menus-BcyElFtI.mjs.map +1 -0
- package/dist/{menus-Cfivc2Ad.mjs → menus-CZyG6rvx.mjs} +3 -3
- package/dist/{menus-Cfivc2Ad.mjs.map → menus-CZyG6rvx.mjs.map} +1 -1
- package/dist/{mime-CCEzze7W.mjs → mime-DfIVjNkr.mjs} +1 -1
- package/dist/{mime-CCEzze7W.mjs.map → mime-DfIVjNkr.mjs.map} +1 -1
- package/dist/{mode-BM9QgEmt.mjs → mode-fiXRMfeA.mjs} +1 -1
- package/dist/{mode-BM9QgEmt.mjs.map → mode-fiXRMfeA.mjs.map} +1 -1
- package/dist/{normalize-CeglrBT9.mjs → normalize-C-SHXmra.mjs} +1 -1
- package/dist/{normalize-CeglrBT9.mjs.map → normalize-C-SHXmra.mjs.map} +1 -1
- package/dist/{oauth-authorization-CXWkIGT4.mjs → oauth-authorization-oqfbBuMH.mjs} +6 -7
- package/dist/oauth-authorization-oqfbBuMH.mjs.map +1 -0
- package/dist/{oauth-clients-BmTI5rsl.mjs → oauth-clients-BlrUHAsf.mjs} +1 -1
- package/dist/{oauth-clients-BmTI5rsl.mjs.map → oauth-clients-BlrUHAsf.mjs.map} +1 -1
- package/dist/{oauth-state-store-YLFLcH5F.mjs → oauth-state-store-DnvjRMy6.mjs} +2 -1
- package/dist/{oauth-state-store-YLFLcH5F.mjs.map → oauth-state-store-DnvjRMy6.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-Bsc_GsX-.mjs → oauth-user-lookup-oUllxvAv.mjs} +1 -1
- package/dist/{oauth-user-lookup-Bsc_GsX-.mjs.map → oauth-user-lookup-oUllxvAv.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-DTTML-Tx.mjs → options-BlmBHTvX.mjs} +1 -1
- package/dist/{options-DTTML-Tx.mjs.map → options-BlmBHTvX.mjs.map} +1 -1
- package/dist/{options-iMpRRxIe.d.mts → options-BqMkWfYa.d.mts} +6 -6
- package/dist/{options-iMpRRxIe.d.mts.map → options-BqMkWfYa.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/page/index.d.mts.map +1 -1
- package/dist/page/index.mjs.map +1 -1
- package/dist/{parse-GmjecGct.mjs → parse-C_-6klII.mjs} +4 -12
- package/dist/{parse-GmjecGct.mjs.map → parse-C_-6klII.mjs.map} +1 -1
- package/dist/{passkey-config-De0ahnRg.mjs → passkey-config-C-SKpc0-.mjs} +1 -1
- package/dist/{passkey-config-De0ahnRg.mjs.map → passkey-config-C-SKpc0-.mjs.map} +1 -1
- package/dist/{patterns-BKmjvM7K.mjs → patterns-CiyXeDgr.mjs} +1 -1
- package/dist/{patterns-BKmjvM7K.mjs.map → patterns-CiyXeDgr.mjs.map} +1 -1
- package/dist/{placeholder-BSKwzRe4.d.mts → placeholder-Dop47JMM.d.mts} +1 -1
- package/dist/{placeholder-BSKwzRe4.d.mts.map → placeholder-Dop47JMM.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +21 -2
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +18 -16
- package/dist/plugin-utils.d.mts.map +1 -1
- package/dist/plugin-utils.mjs +8 -6
- package/dist/plugin-utils.mjs.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -10
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +15 -3
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/{portable-text-cCa0cGV6.mjs → portable-text-sDj92Kxv.mjs} +1 -1
- package/dist/{portable-text-cCa0cGV6.mjs.map → portable-text-sDj92Kxv.mjs.map} +1 -1
- package/dist/{preview-SSXNVPAC.mjs → preview-D4Jnbfx7.mjs} +2 -2
- package/dist/{preview-SSXNVPAC.mjs.map → preview-D4Jnbfx7.mjs.map} +1 -1
- package/dist/{public-url-Danv47cS.mjs → public-url-DSGTnJFw.mjs} +5 -3
- package/dist/public-url-DSGTnJFw.mjs.map +1 -0
- package/dist/{query-1Cp6U9oo.mjs → query-DR73ZNfm.mjs} +15 -15
- package/dist/query-DR73ZNfm.mjs.map +1 -0
- package/dist/{schema-CX9cfNkZ.mjs → query-Di7DOmPV.mjs} +5 -10
- package/dist/query-Di7DOmPV.mjs.map +1 -0
- package/dist/{rate-limit-C_Lf63Dd.mjs → rate-limit-CMj83JNW.mjs} +2 -2
- package/dist/{rate-limit-C_Lf63Dd.mjs.map → rate-limit-CMj83JNW.mjs.map} +1 -1
- package/dist/{redirect-CoW3G-0U.mjs → redirect-Botom7X6.mjs} +1 -1
- package/dist/{redirect-CoW3G-0U.mjs.map → redirect-Botom7X6.mjs.map} +1 -1
- package/dist/{redirect-IyfNirgS.mjs → redirect-CgLPYflR.mjs} +11 -5
- package/dist/redirect-CgLPYflR.mjs.map +1 -0
- package/dist/{redirects-Bs1g42Ri.mjs → redirects-B7t9bKsL.mjs} +6 -6
- package/dist/{redirects-Bs1g42Ri.mjs.map → redirects-B7t9bKsL.mjs.map} +1 -1
- package/dist/{redirects-DXEXBAII.mjs → redirects-BBq3n2Rj.mjs} +10 -143
- package/dist/redirects-BBq3n2Rj.mjs.map +1 -0
- package/dist/{registry-B57vp_X9.mjs → registry-FV15nLge.mjs} +99 -10
- package/dist/registry-FV15nLge.mjs.map +1 -0
- package/dist/relation-9M9j_UWo.mjs +334 -0
- package/dist/relation-9M9j_UWo.mjs.map +1 -0
- package/dist/{byline-fields-2Lp5Hbgf.mjs → relations-5_avdrN_.mjs} +60 -4
- package/dist/relations-5_avdrN_.mjs.map +1 -0
- package/dist/relations-BKvO39-9.mjs +397 -0
- package/dist/relations-BKvO39-9.mjs.map +1 -0
- package/dist/{byline-fields-CHE8UStY.d.mts → relations-Bh8jlFsU.d.mts} +486 -31
- package/dist/relations-Bh8jlFsU.d.mts.map +1 -0
- package/dist/{request-cache-KCNHp_RJ.mjs → request-cache-BSUptuJR.mjs} +1 -1
- package/dist/{request-cache-KCNHp_RJ.mjs.map → request-cache-BSUptuJR.mjs.map} +1 -1
- package/dist/{request-meta-DbvXaAvU.mjs → request-meta-DzXYYI-n.mjs} +2 -2
- package/dist/{request-meta-DbvXaAvU.mjs.map → request-meta-DzXYYI-n.mjs.map} +1 -1
- package/dist/{resolve-DR3wqMTy.mjs → resolve-Cd9dzclN.mjs} +1 -1
- package/dist/{resolve-DR3wqMTy.mjs.map → resolve-Cd9dzclN.mjs.map} +1 -1
- package/dist/{runner-DvFWoz8-.d.mts → runner-Dd8m8k9F.d.mts} +8 -2
- package/dist/runner-Dd8m8k9F.d.mts.map +1 -0
- package/dist/{runner-K8XK101B.mjs → runner-DfnZ5eUr.mjs} +355 -204
- package/dist/runner-DfnZ5eUr.mjs.map +1 -0
- package/dist/runtime.d.mts +11 -11
- package/dist/runtime.mjs +4 -4
- package/dist/schema-BXxlHeAf.mjs +9 -0
- package/dist/schema-BXxlHeAf.mjs.map +1 -0
- package/dist/scopes-Bl4IwHA-.mjs +27 -0
- package/dist/scopes-Bl4IwHA-.mjs.map +1 -0
- package/dist/{search-DZN2HZ-V.mjs → search-Bff-7jFt.mjs} +62 -12
- package/dist/search-Bff-7jFt.mjs.map +1 -0
- package/dist/{secrets-kp760LlD.mjs → secrets-CSwQIl4q.mjs} +4 -4
- package/dist/{secrets-kp760LlD.mjs.map → secrets-CSwQIl4q.mjs.map} +1 -1
- package/dist/{sections-CpF5SaGr.mjs → sections-CwW4s1al.mjs} +3 -3
- package/dist/{sections-CpF5SaGr.mjs.map → sections-CwW4s1al.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +23 -23
- package/dist/seo/index.d.mts +15 -2
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +22 -5
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-DXu2UQnC.mjs → seo-2cmFHZns.mjs} +2 -2
- package/dist/{seo-DXu2UQnC.mjs.map → seo-2cmFHZns.mjs.map} +1 -1
- package/dist/{seo-89-53DDs.mjs → seo-C3GDfT0V.mjs} +1 -1
- package/dist/{seo-89-53DDs.mjs.map → seo-C3GDfT0V.mjs.map} +1 -1
- package/dist/{service-DQmiBMzt.mjs → service-DkGTWGIi.mjs} +3 -3
- package/dist/{service-DQmiBMzt.mjs.map → service-DkGTWGIi.mjs.map} +1 -1
- package/dist/{session-user-Cascbax7.mjs → session-user-DbHqKDKe.mjs} +1 -1
- package/dist/{session-user-Cascbax7.mjs.map → session-user-DbHqKDKe.mjs.map} +1 -1
- package/dist/{settings-rZyHEcNT.mjs → settings-C4s8hFQm.mjs} +3 -3
- package/dist/{settings-rZyHEcNT.mjs.map → settings-C4s8hFQm.mjs.map} +1 -1
- package/dist/{settings-zhmdKyJQ.mjs → settings-CpA4lQFt.mjs} +6 -6
- package/dist/{settings-zhmdKyJQ.mjs.map → settings-CpA4lQFt.mjs.map} +1 -1
- package/dist/{setup-complete-Cb3LRyzy.mjs → setup-complete-CdIlqloh.mjs} +2 -2
- package/dist/{setup-complete-Cb3LRyzy.mjs.map → setup-complete-CdIlqloh.mjs.map} +1 -1
- package/dist/{setup-nonce-Z8x0tHf8.mjs → setup-nonce-DqiIPr-J.mjs} +1 -1
- package/dist/{setup-nonce-Z8x0tHf8.mjs.map → setup-nonce-DqiIPr-J.mjs.map} +1 -1
- package/dist/{single-flight-cache-BG3B_GhN.mjs → single-flight-cache-C2exrGAi.mjs} +2 -2
- package/dist/{single-flight-cache-BG3B_GhN.mjs.map → single-flight-cache-C2exrGAi.mjs.map} +1 -1
- package/dist/{site-url-BBfDTgZB.mjs → site-url-NGJT6NTU.mjs} +2 -2
- package/dist/{site-url-BBfDTgZB.mjs.map → site-url-NGJT6NTU.mjs.map} +1 -1
- package/dist/{slugify-Cce3dTdg.mjs → slugify-C_tqlU4G.mjs} +1 -1
- package/dist/{slugify-Cce3dTdg.mjs.map → slugify-C_tqlU4G.mjs.map} +1 -1
- package/dist/snapshot-BdpUJKD-.mjs +216 -0
- package/dist/snapshot-BdpUJKD-.mjs.map +1 -0
- package/dist/{ssrf-1g7usGBg.mjs → ssrf-CviKqWmq.mjs} +1 -1
- package/dist/{ssrf-1g7usGBg.mjs.map → ssrf-CviKqWmq.mjs.map} +1 -1
- package/dist/state-xxv6ZTMv.mjs +128 -0
- package/dist/state-xxv6ZTMv.mjs.map +1 -0
- package/dist/{status-CqJQX1QN.mjs → status-COfycGIU.mjs} +1 -1
- package/dist/{status-CqJQX1QN.mjs.map → status-COfycGIU.mjs.map} +1 -1
- 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/{taxonomies-Bs13SN-F.mjs → taxonomies-Ce49uIzY.mjs} +13 -9
- package/dist/taxonomies-Ce49uIzY.mjs.map +1 -0
- package/dist/{taxonomies-kH9ABDUF.mjs → taxonomies-DjSKBZpq.mjs} +115 -36
- package/dist/taxonomies-DjSKBZpq.mjs.map +1 -0
- package/dist/{taxonomy-BxGxZZdu.mjs → taxonomy-DfVooU4W.mjs} +60 -13
- package/dist/taxonomy-DfVooU4W.mjs.map +1 -0
- package/dist/{tokens-BGT0TUUo.mjs → tokens-DVltpO2D.mjs} +2 -2
- package/dist/{tokens-BGT0TUUo.mjs.map → tokens-DVltpO2D.mjs.map} +1 -1
- package/dist/{transaction-qfqpPVpu.mjs → transaction-D0FOsb3X.mjs} +1 -1
- package/dist/{transaction-qfqpPVpu.mjs.map → transaction-D0FOsb3X.mjs.map} +1 -1
- package/dist/{transport-DPefPMcz.mjs → transport-CKrlqSpD.mjs} +1 -1
- package/dist/{transport-DPefPMcz.mjs.map → transport-CKrlqSpD.mjs.map} +1 -1
- package/dist/{transport-BMDWHSgZ.d.mts → transport-Vd7VdqHv.d.mts} +1 -1
- package/dist/{transport-BMDWHSgZ.d.mts.map → transport-Vd7VdqHv.d.mts.map} +1 -1
- package/dist/{trusted-proxy-VTPRiX2s.mjs → trusted-proxy-CwjQj0YG.mjs} +1 -1
- package/dist/{trusted-proxy-VTPRiX2s.mjs.map → trusted-proxy-CwjQj0YG.mjs.map} +1 -1
- package/dist/{types-CgvhU-hF.d.mts → types-B4vm81VH.d.mts} +1 -1
- package/dist/{types-CgvhU-hF.d.mts.map → types-B4vm81VH.d.mts.map} +1 -1
- package/dist/{types-ea9sAPck.d.mts → types-B97jg3aW.d.mts} +6 -1
- package/dist/{types-ea9sAPck.d.mts.map → types-B97jg3aW.d.mts.map} +1 -1
- package/dist/{types-Jo3UYd6b.mjs → types-BD40g7zz.mjs} +1 -1
- package/dist/{types-Jo3UYd6b.mjs.map → types-BD40g7zz.mjs.map} +1 -1
- package/dist/{types-DmHk7vAt.d.mts → types-BNfPHfay.d.mts} +1 -1
- package/dist/{types-DmHk7vAt.d.mts.map → types-BNfPHfay.d.mts.map} +1 -1
- package/dist/{types-BcLUUbbR.d.mts → types-BfYUPJdP.d.mts} +11 -3
- package/dist/{types-BcLUUbbR.d.mts.map → types-BfYUPJdP.d.mts.map} +1 -1
- package/dist/{types-CGbYowGQ.d.mts → types-BvB7gDOD.d.mts} +90 -4
- package/dist/types-BvB7gDOD.d.mts.map +1 -0
- package/dist/{types-vgEWF18A.d.mts → types-C7U0HlEr.d.mts} +1 -1
- package/dist/{types-vgEWF18A.d.mts.map → types-C7U0HlEr.d.mts.map} +1 -1
- package/dist/{types-CuW0zWDA.mjs → types-D1iJ3DpO.mjs} +3 -3
- package/dist/{types-CuW0zWDA.mjs.map → types-D1iJ3DpO.mjs.map} +1 -1
- package/dist/{types-_HFLRzTn.d.mts → types-DPKhI5ib.d.mts} +9 -1
- package/dist/types-DPKhI5ib.d.mts.map +1 -0
- package/dist/{types-g_aFIdW0.d.mts → types-Kmaxdarz.d.mts} +1 -1
- package/dist/{types-g_aFIdW0.d.mts.map → types-Kmaxdarz.d.mts.map} +1 -1
- package/dist/{types-ClUkdbWb.d.mts → types-iVeZ5g6N.d.mts} +1 -1
- package/dist/{types-ClUkdbWb.d.mts.map → types-iVeZ5g6N.d.mts.map} +1 -1
- package/dist/{types-tM44hEcf.mjs → types-o7xo7VgH.mjs} +1 -1
- package/dist/{types-tM44hEcf.mjs.map → types-o7xo7VgH.mjs.map} +1 -1
- package/dist/{user-BjAOvU3Z.mjs → user-Bh-L1qo6.mjs} +3 -3
- package/dist/{user-BjAOvU3Z.mjs.map → user-Bh-L1qo6.mjs.map} +1 -1
- package/dist/{utils-BJXElxdw.mjs → utils-BbUgmeZG.mjs} +3 -3
- package/dist/{utils-BJXElxdw.mjs.map → utils-BbUgmeZG.mjs.map} +1 -1
- package/dist/{validate-Z1b86_3B.d.mts → validate-DULfgpJP.d.mts} +5 -5
- package/dist/{validate-Z1b86_3B.d.mts.map → validate-DULfgpJP.d.mts.map} +1 -1
- package/dist/{validate-CWSnKVIJ.mjs → validate-V9nCwq_-.mjs} +3 -3
- package/dist/{validate-CWSnKVIJ.mjs.map → validate-V9nCwq_-.mjs.map} +1 -1
- package/dist/{validation-0l8-RYj4.mjs → validation-BsVUJfsP.mjs} +10 -10
- package/dist/{validation-0l8-RYj4.mjs.map → validation-BsVUJfsP.mjs.map} +1 -1
- package/dist/version-907opKac.mjs +7 -0
- package/dist/{version-qmeO1XZY.mjs.map → version-907opKac.mjs.map} +1 -1
- package/dist/{widgets-hWcIicX8.mjs → widgets-DGv1Z04V.mjs} +4 -4
- package/dist/{widgets-hWcIicX8.mjs.map → widgets-DGv1Z04V.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-0_uxSrmf.d.mts → wxr-taxonomies-B4tMuN5T.d.mts} +1 -1
- package/dist/{wxr-taxonomies-0_uxSrmf.d.mts.map → wxr-taxonomies-B4tMuN5T.d.mts.map} +1 -1
- package/dist/{wxr-taxonomies-CNFcsNCr.mjs → wxr-taxonomies-Cs1N6O8z.mjs} +4 -4
- package/dist/{wxr-taxonomies-CNFcsNCr.mjs.map → wxr-taxonomies-Cs1N6O8z.mjs.map} +1 -1
- package/dist/{zod-generator-CacrR-i8.mjs → zod-generator-B5prQ5M4.mjs} +3 -3
- package/dist/{zod-generator-CacrR-i8.mjs.map → zod-generator-B5prQ5M4.mjs.map} +1 -1
- package/package.json +12 -8
- package/src/api/authorize.ts +10 -1
- package/src/api/error.ts +5 -5
- package/src/api/errors.ts +25 -0
- package/src/api/handlers/backup.ts +312 -0
- package/src/api/handlers/content.ts +147 -3
- package/src/api/handlers/dashboard.ts +2 -0
- package/src/api/handlers/device-flow.ts +2 -3
- package/src/api/handlers/index.ts +22 -0
- package/src/api/handlers/marketplace.ts +38 -0
- package/src/api/handlers/media-upload.ts +210 -0
- package/src/api/handlers/media-usage.ts +289 -0
- package/src/api/handlers/oauth-authorization.ts +2 -6
- package/src/api/handlers/plugin-settings.ts +218 -0
- package/src/api/handlers/plugins.ts +41 -0
- package/src/api/handlers/registry.ts +39 -0
- package/src/api/handlers/relations.ts +474 -0
- package/src/api/handlers/snapshot.ts +21 -3
- package/src/api/handlers/taxonomies.ts +26 -4
- package/src/api/handlers/validate-media-fields.ts +1 -1
- package/src/api/openapi/document.ts +72 -5
- package/src/api/parse.ts +2 -16
- package/src/api/public-url.ts +4 -2
- package/src/api/schemas/comments.ts +6 -0
- package/src/api/schemas/common.ts +6 -2
- package/src/api/schemas/content.ts +8 -0
- package/src/api/schemas/index.ts +2 -0
- package/src/api/schemas/media-usage.ts +120 -0
- package/src/api/schemas/media.ts +32 -1
- package/src/api/schemas/relations.ts +109 -0
- package/src/api/schemas/search.ts +1 -0
- package/src/astro/integration/index.ts +39 -0
- package/src/astro/integration/routes.ts +40 -0
- package/src/astro/integration/runtime.ts +30 -0
- package/src/astro/integration/virtual-modules.ts +41 -7
- package/src/astro/integration/vite-config.ts +17 -1
- package/src/astro/middleware/auth.ts +70 -78
- package/src/astro/middleware/csp.ts +5 -2
- package/src/astro/middleware/request-context.ts +162 -20
- package/src/astro/middleware.ts +108 -40
- package/src/astro/public-plugin-api-routes.ts +2 -1
- package/src/astro/routes/PluginRegistry.tsx +5 -2
- package/src/astro/routes/admin.astro +56 -16
- package/src/astro/routes/api/admin/api-tokens/index.ts +2 -2
- package/src/astro/routes/api/admin/bylines/[id]/translations.ts +2 -5
- package/src/astro/routes/api/admin/comments/[id]/status.ts +1 -2
- package/src/astro/routes/api/admin/comments/index.ts +1 -2
- package/src/astro/routes/api/admin/media-usage/repair.ts +24 -0
- package/src/astro/routes/api/admin/plugins/[id]/index.ts +6 -0
- package/src/astro/routes/api/admin/plugins/[id]/mcp.ts +42 -0
- package/src/astro/routes/api/admin/plugins/[id]/settings.ts +80 -0
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +2 -0
- package/src/astro/routes/api/admin/plugins/index.ts +9 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +2 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +2 -0
- package/src/astro/routes/api/admin/plugins/registry/install.ts +2 -0
- package/src/astro/routes/api/admin/plugins/updates.ts +2 -4
- package/src/astro/routes/api/auth/mode.ts +6 -14
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +21 -5
- package/src/astro/routes/api/auth/oauth/[provider].ts +24 -7
- package/src/astro/routes/api/comments/[collection]/[contentId]/index.ts +13 -0
- package/src/astro/routes/api/content/[collection]/[id]/compare.ts +3 -4
- package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +2 -3
- package/src/astro/routes/api/content/[collection]/[id]/permanent.ts +2 -3
- package/src/astro/routes/api/content/[collection]/[id]/preview-url.ts +3 -4
- package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/children.ts +95 -0
- package/src/astro/routes/api/content/[collection]/[id]/references/[relation]/parents.ts +47 -0
- package/src/astro/routes/api/content/[collection]/[id]/revisions.ts +3 -4
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +4 -6
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +3 -4
- package/src/astro/routes/api/content/[collection]/[id].ts +3 -4
- package/src/astro/routes/api/content/[collection]/authors.ts +2 -3
- package/src/astro/routes/api/content/[collection]/index.ts +6 -8
- package/src/astro/routes/api/content/[collection]/trash.ts +2 -3
- package/src/astro/routes/api/manifest.ts +2 -9
- package/src/astro/routes/api/mcp.ts +2 -1
- package/src/astro/routes/api/media/[id]/usage.ts +30 -0
- package/src/astro/routes/api/media/[id].ts +17 -6
- package/src/astro/routes/api/media/file/[...key].ts +8 -0
- package/src/astro/routes/api/media.ts +21 -2
- package/src/astro/routes/api/oauth/authorize.ts +2 -6
- package/src/astro/routes/api/plugins/[pluginId]/[...path].ts +17 -3
- package/src/astro/routes/api/relations/[id]/index.ts +84 -0
- package/src/astro/routes/api/relations/[id]/translations.ts +33 -0
- package/src/astro/routes/api/relations/index.ts +56 -0
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +1 -7
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +1 -2
- package/src/astro/routes/api/search/index.ts +2 -0
- package/src/astro/routes/api/settings/backups/archives/[name].ts +78 -0
- package/src/astro/routes/api/settings/backups/archives/index.ts +33 -0
- package/src/astro/routes/api/settings/backups/export.ts +43 -0
- package/src/astro/routes/api/settings/backups/index.ts +76 -0
- package/src/astro/routes/api/setup/admin-verify.ts +8 -4
- package/src/astro/routes/api/setup/admin.ts +11 -4
- package/src/astro/routes/api/well-known/oauth-authorization-server.ts +4 -1
- package/src/astro/routes/api/well-known/oauth-protected-resource.ts +5 -1
- package/src/astro/types.ts +50 -2
- package/src/auth/api-tokens.ts +1 -0
- package/src/auth/oauth-state-store.ts +3 -0
- package/src/auth/providers/github-admin.tsx +5 -6
- package/src/auth/providers/google-admin.tsx +5 -6
- package/src/auth/scopes.ts +3 -9
- package/src/cli/client-factory.ts +0 -1
- package/src/cli/commands/bundle-utils.ts +50 -1
- package/src/cli/commands/bundle.ts +9 -2
- package/src/cli/commands/export-seed.ts +1 -10
- package/src/cli/commands/media.ts +127 -0
- package/src/client/index.ts +123 -2
- package/src/client/transport.ts +1 -1
- package/src/comments/service.ts +1 -1
- package/src/comments/turnstile.ts +64 -0
- package/src/components/BlockquoteGroup.astro +34 -0
- package/src/components/CommentForm.astro +12 -5
- package/src/components/EmDashHead.astro +31 -9
- package/src/components/InlinePortableTextEditor.tsx +88 -33
- package/src/components/PortableText.astro +7 -1
- package/src/components/index.ts +2 -0
- package/src/components/marks/Link.astro +5 -1
- package/src/components/portable-text-blockquote-group.ts +68 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +32 -1
- package/src/database/dialect-helpers.ts +111 -3
- package/src/database/migrations/039_fix_fts5_triggers.ts +1 -1
- package/src/database/migrations/051_content_taxonomies_denorm.ts +120 -0
- package/src/database/migrations/052_media_usage_read_index.ts +26 -0
- package/src/database/migrations/053_plugin_mcp_tools.ts +21 -0
- package/src/database/migrations/runner.ts +52 -6
- package/src/database/pg-migration-lock.ts +72 -0
- package/src/database/repositories/audit.ts +2 -1
- package/src/database/repositories/comment.ts +1 -1
- package/src/database/repositories/content.ts +270 -37
- package/src/database/repositories/media-usage.ts +250 -1
- package/src/database/repositories/media.ts +1 -1
- package/src/database/repositories/plugin-storage.ts +29 -32
- package/src/database/repositories/redirect.ts +14 -2
- package/src/database/repositories/relation.ts +130 -5
- package/src/database/repositories/taxonomy.ts +66 -8
- package/src/database/repositories/types.ts +8 -0
- package/src/database/types.ts +23 -0
- package/src/db/adapters.ts +9 -0
- package/src/db/postgres.ts +5 -2
- package/src/emdash-runtime.ts +382 -70
- package/src/index.ts +6 -2
- package/src/loader.ts +293 -32
- package/src/mcp/server.ts +251 -8
- package/src/media/image-endpoint.ts +38 -2
- package/src/page/metadata.ts +27 -0
- package/src/plugin-types.ts +19 -0
- package/src/plugin-utils.ts +8 -6
- package/src/plugins/adapt-sandbox-entry.ts +30 -1
- package/src/plugins/context.ts +92 -0
- package/src/plugins/define-plugin.ts +17 -0
- package/src/plugins/index.ts +4 -0
- package/src/plugins/manifest-schema.ts +30 -1
- package/src/plugins/routes.ts +27 -1
- package/src/plugins/sandbox/runner-options.ts +16 -0
- package/src/plugins/sandbox/types.ts +6 -1
- package/src/plugins/state.ts +17 -1
- package/src/plugins/storage-query.ts +67 -33
- package/src/plugins/types.ts +100 -0
- package/src/schema/byline-registry.ts +1 -1
- package/src/schema/registry.ts +141 -5
- package/src/search/fts-manager.ts +34 -0
- package/src/search/match.ts +50 -0
- package/src/search/query.ts +94 -9
- package/src/seed/apply.ts +28 -29
- package/src/seo/hreflang.ts +192 -0
- package/src/seo/index.ts +22 -4
- package/src/storage/types.ts +6 -0
- package/src/taxonomies/index.ts +62 -45
- package/src/taxonomies/term-counts.ts +117 -0
- package/src/utils/base64.ts +7 -2
- package/src/utils/db-errors.ts +3 -1
- package/src/virtual-modules.d.ts +14 -0
- package/src/visual-editing/editable.ts +41 -35
- package/src/visual-editing/toolbar-bootstrap.ts +120 -0
- package/src/visual-editing/toolbar.ts +47 -1
- package/dist/adapters-hUy8vOB-.d.mts.map +0 -1
- package/dist/api-DxFSorgk.mjs.map +0 -1
- package/dist/api-tokens-DsvvCtdh.mjs +0 -3
- package/dist/apply-CDJqIjPU.mjs.map +0 -1
- package/dist/authorize-Dz88F_Fw.mjs.map +0 -1
- package/dist/base64-CmWvODNW.mjs.map +0 -1
- package/dist/byline-fields-2Lp5Hbgf.mjs.map +0 -1
- package/dist/byline-fields-CHE8UStY.d.mts.map +0 -1
- package/dist/content-DhgEth4k.mjs.map +0 -1
- package/dist/content-refresh-Br4gMzh8.mjs.map +0 -1
- package/dist/context-BRIpHARC.mjs.map +0 -1
- package/dist/dashboard-EvEKF5en.mjs.map +0 -1
- package/dist/db-errors-CK46D-ly.mjs.map +0 -1
- package/dist/device-flow-CfGP18Uw.mjs.map +0 -1
- package/dist/dialect-helpers-DRI5pyY3.mjs +0 -110
- package/dist/dialect-helpers-DRI5pyY3.mjs.map +0 -1
- package/dist/error-CkAseSqZ.mjs.map +0 -1
- package/dist/index-B9sIxwe4.d.mts.map +0 -1
- package/dist/loader-CB6YHeul.mjs.map +0 -1
- package/dist/manifest-schema-BHlgZM1W.mjs.map +0 -1
- package/dist/media-BrXIaMFN.mjs.map +0 -1
- package/dist/menus-b2T4clbO.mjs.map +0 -1
- package/dist/oauth-authorization-CXWkIGT4.mjs.map +0 -1
- package/dist/public-url-Danv47cS.mjs.map +0 -1
- package/dist/query-1Cp6U9oo.mjs.map +0 -1
- package/dist/redirect-IyfNirgS.mjs.map +0 -1
- package/dist/redirects-DXEXBAII.mjs.map +0 -1
- package/dist/registry-B57vp_X9.mjs.map +0 -1
- package/dist/runner-DvFWoz8-.d.mts.map +0 -1
- package/dist/runner-K8XK101B.mjs.map +0 -1
- package/dist/scheduled-publish-Drffrf2a.d.mts +0 -11
- package/dist/scheduled-publish-Drffrf2a.d.mts.map +0 -1
- package/dist/schema-CX9cfNkZ.mjs.map +0 -1
- package/dist/search-DZN2HZ-V.mjs.map +0 -1
- package/dist/taxonomies-Bs13SN-F.mjs.map +0 -1
- package/dist/taxonomies-kH9ABDUF.mjs.map +0 -1
- package/dist/taxonomy-BxGxZZdu.mjs.map +0 -1
- package/dist/types-CGbYowGQ.d.mts.map +0 -1
- package/dist/types-_HFLRzTn.d.mts.map +0 -1
- package/dist/version-qmeO1XZY.mjs +0 -7
- /package/dist/{ssrf-CmuGgCq3.mjs → ssrf-BB__xfNM.mjs} +0 -0
- /package/dist/{types-DROWRxYV.mjs → types-CK0LxPUQ.mjs} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments-BLE-jv5k.mjs","names":[],"sources":["../src/api/handlers/comments.ts"],"sourcesContent":["/**\n * Comment handlers — business logic for comment API routes.\n *\n * Standalone functions that return ApiResult<T>. Routes are thin wrappers.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { CommentRepository } from \"../../database/repositories/comment.js\";\nimport type { Comment, CommentStatus, PublicComment } from \"../../database/repositories/comment.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Public: List approved comments for content\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentList(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tcontentId: string,\n\toptions: { limit?: number; cursor?: string; threaded?: boolean } = {},\n): Promise<ApiResult<{ items: PublicComment[]; nextCursor?: string; total: number }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\n\t\t// Get total approved count\n\t\tconst total = await repo.countByContent(collection, contentId, \"approved\");\n\n\t\tlet publicItems: PublicComment[];\n\t\tlet nextCursor: string | undefined;\n\n\t\tif (options.threaded) {\n\t\t\t// Threaded mode: fetch all approved comments (capped) so threading\n\t\t\t// doesn't lose children that would fall on later pages.\n\t\t\tconst MAX_THREADED = 500;\n\t\t\tconst result = await repo.findByContent(collection, contentId, {\n\t\t\t\tstatus: \"approved\",\n\t\t\t\tlimit: MAX_THREADED,\n\t\t\t});\n\t\t\tconst threaded = CommentRepository.assembleThreads(result.items);\n\t\t\tpublicItems = threaded.map((c) => CommentRepository.toPublicComment(c));\n\t\t\t// No cursor for threaded mode — all comments returned at once\n\t\t} else {\n\t\t\tconst result = await repo.findByContent(collection, contentId, {\n\t\t\t\tstatus: \"approved\",\n\t\t\t\tlimit: options.limit,\n\t\t\t\tcursor: options.cursor,\n\t\t\t});\n\t\t\tpublicItems = result.items.map((c) => CommentRepository.toPublicComment(c));\n\t\t\tnextCursor = result.nextCursor;\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\titems: publicItems,\n\t\t\t\tnextCursor,\n\t\t\t\ttotal,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CURSOR\", message: error.message },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"Comment list error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_LIST_ERROR\",\n\t\t\t\tmessage: \"Failed to list comments\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Moderation inbox\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentInbox(\n\tdb: Kysely<Database>,\n\toptions: {\n\t\tstatus?: CommentStatus;\n\t\tcollection?: string;\n\t\tsearch?: string;\n\t\tlimit?: number;\n\t\tcursor?: string;\n\t} = {},\n): Promise<ApiResult<{ items: Comment[]; nextCursor?: string }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst status = options.status ?? \"pending\";\n\n\t\tconst result = await repo.findByStatus(status, {\n\t\t\tcollection: options.collection,\n\t\t\tsearch: options.search,\n\t\t\tlimit: options.limit,\n\t\t\tcursor: options.cursor,\n\t\t});\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\titems: result.items,\n\t\t\t\tnextCursor: result.nextCursor,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CURSOR\", message: error.message },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"Comment inbox error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_INBOX_ERROR\",\n\t\t\t\tmessage: \"Failed to list comments\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Status counts for inbox badges\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentCounts(\n\tdb: Kysely<Database>,\n): Promise<ApiResult<Record<CommentStatus, number>>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst counts = await repo.countByStatus();\n\t\treturn { success: true, data: counts };\n\t} catch (error) {\n\t\tconsole.error(\"Comment counts error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_COUNTS_ERROR\",\n\t\t\t\tmessage: \"Failed to get comment counts\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Get single comment detail\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentGet(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<Comment>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst comment = await repo.findById(id);\n\n\t\tif (!comment) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Comment not found: ${id}` },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: comment };\n\t} catch (error) {\n\t\tconsole.error(\"Comment get error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_GET_ERROR\",\n\t\t\t\tmessage: \"Failed to get comment\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Change comment status\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentStatusChange(\n\tdb: Kysely<Database>,\n\tid: string,\n\tstatus: CommentStatus,\n): Promise<ApiResult<Comment>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst updated = await repo.updateStatus(id, status);\n\n\t\tif (!updated) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Comment not found: ${id}` },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: updated };\n\t} catch (error) {\n\t\tconsole.error(\"Comment status change error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_STATUS_ERROR\",\n\t\t\t\tmessage: \"Failed to update comment status\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Hard delete comment\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentDelete(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst deleted = await repo.delete(id);\n\n\t\tif (!deleted) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Comment not found: ${id}` },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch (error) {\n\t\tconsole.error(\"Comment delete error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_DELETE_ERROR\",\n\t\t\t\tmessage: \"Failed to delete comment\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Bulk operations\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentBulk(\n\tdb: Kysely<Database>,\n\tids: string[],\n\taction: \"approve\" | \"spam\" | \"trash\" | \"delete\",\n): Promise<ApiResult<{ affected: number }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\n\t\tlet affected: number;\n\t\tif (action === \"delete\") {\n\t\t\taffected = await repo.bulkDelete(ids);\n\t\t} else {\n\t\t\tconst statusMap: Record<string, CommentStatus> = {\n\t\t\t\tapprove: \"approved\",\n\t\t\t\tspam: \"spam\",\n\t\t\t\ttrash: \"trash\",\n\t\t\t};\n\t\t\taffected = await repo.bulkUpdateStatus(ids, statusMap[action]);\n\t\t}\n\n\t\treturn { success: true, data: { affected } };\n\t} catch (error) {\n\t\tconsole.error(\"Comment bulk error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_BULK_ERROR\",\n\t\t\t\tmessage: \"Failed to perform bulk operation\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Anti-spam: Rate limiting\n// ---------------------------------------------------------------------------\n\n/**\n * Check if an IP has exceeded the comment rate limit.\n * Uses ip_hash in the comments table — no separate counter storage.\n */\nexport async function checkRateLimit(\n\tdb: Kysely<Database>,\n\tipHash: string,\n\tmaxPerWindow: number = 5,\n\twindowMinutes: number = 10,\n): Promise<boolean> {\n\tconst cutoff = new Date(Date.now() - windowMinutes * 60 * 1000).toISOString();\n\n\t// Count recent comments from this IP\n\tconst result = await db\n\t\t.selectFrom(\"_emdash_comments\")\n\t\t.select((eb) => eb.fn.count(\"id\").as(\"count\"))\n\t\t.where(\"ip_hash\", \"=\", ipHash)\n\t\t.where(\"created_at\", \">\", cutoff)\n\t\t.executeTakeFirst();\n\n\tconst count = Number(result?.count ?? 0);\n\treturn count >= maxPerWindow;\n}\n\n/**\n * Hash an IP address for storage (never store cleartext IPs).\n *\n * Uses full SHA-256 with a site-specific salt to prevent rainbow-table\n * recovery of IPs. The salt must be provided by the caller — typically\n * via `resolveSecretsCached(db).ipSalt` from `#config/secrets.js`. The\n * salt is generated and persisted on first need so it's stable across\n * requests within a deployment but unique per install.\n */\nexport async function hashIp(ip: string, salt: string): Promise<string> {\n\tconst data = `ip:${salt}:${ip}`;\n\tconst buf = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(data));\n\treturn Array.from(new Uint8Array(buf), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"comments-Bz6sCbgD.mjs","names":[],"sources":["../src/api/handlers/comments.ts"],"sourcesContent":["/**\n * Comment handlers — business logic for comment API routes.\n *\n * Standalone functions that return ApiResult<T>. Routes are thin wrappers.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport { CommentRepository } from \"../../database/repositories/comment.js\";\nimport type { Comment, CommentStatus, PublicComment } from \"../../database/repositories/comment.js\";\nimport { InvalidCursorError } from \"../../database/repositories/types.js\";\nimport type { Database } from \"../../database/types.js\";\nimport type { ApiResult } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Public: List approved comments for content\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentList(\n\tdb: Kysely<Database>,\n\tcollection: string,\n\tcontentId: string,\n\toptions: { limit?: number; cursor?: string; threaded?: boolean } = {},\n): Promise<ApiResult<{ items: PublicComment[]; nextCursor?: string; total: number }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\n\t\t// Get total approved count\n\t\tconst total = await repo.countByContent(collection, contentId, \"approved\");\n\n\t\tlet publicItems: PublicComment[];\n\t\tlet nextCursor: string | undefined;\n\n\t\tif (options.threaded) {\n\t\t\t// Threaded mode: fetch all approved comments (capped) so threading\n\t\t\t// doesn't lose children that would fall on later pages.\n\t\t\tconst MAX_THREADED = 500;\n\t\t\tconst result = await repo.findByContent(collection, contentId, {\n\t\t\t\tstatus: \"approved\",\n\t\t\t\tlimit: MAX_THREADED,\n\t\t\t});\n\t\t\tconst threaded = CommentRepository.assembleThreads(result.items);\n\t\t\tpublicItems = threaded.map((c) => CommentRepository.toPublicComment(c));\n\t\t\t// No cursor for threaded mode — all comments returned at once\n\t\t} else {\n\t\t\tconst result = await repo.findByContent(collection, contentId, {\n\t\t\t\tstatus: \"approved\",\n\t\t\t\tlimit: options.limit,\n\t\t\t\tcursor: options.cursor,\n\t\t\t});\n\t\t\tpublicItems = result.items.map((c) => CommentRepository.toPublicComment(c));\n\t\t\tnextCursor = result.nextCursor;\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\titems: publicItems,\n\t\t\t\tnextCursor,\n\t\t\t\ttotal,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CURSOR\", message: error.message },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"Comment list error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_LIST_ERROR\",\n\t\t\t\tmessage: \"Failed to list comments\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Moderation inbox\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentInbox(\n\tdb: Kysely<Database>,\n\toptions: {\n\t\tstatus?: CommentStatus;\n\t\tcollection?: string;\n\t\tsearch?: string;\n\t\tlimit?: number;\n\t\tcursor?: string;\n\t} = {},\n): Promise<ApiResult<{ items: Comment[]; nextCursor?: string }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst status = options.status ?? \"pending\";\n\n\t\tconst result = await repo.findByStatus(status, {\n\t\t\tcollection: options.collection,\n\t\t\tsearch: options.search,\n\t\t\tlimit: options.limit,\n\t\t\tcursor: options.cursor,\n\t\t});\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\titems: result.items,\n\t\t\t\tnextCursor: result.nextCursor,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof InvalidCursorError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"INVALID_CURSOR\", message: error.message },\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"Comment inbox error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_INBOX_ERROR\",\n\t\t\t\tmessage: \"Failed to list comments\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Status counts for inbox badges\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentCounts(\n\tdb: Kysely<Database>,\n): Promise<ApiResult<Record<CommentStatus, number>>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst counts = await repo.countByStatus();\n\t\treturn { success: true, data: counts };\n\t} catch (error) {\n\t\tconsole.error(\"Comment counts error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_COUNTS_ERROR\",\n\t\t\t\tmessage: \"Failed to get comment counts\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Get single comment detail\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentGet(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<Comment>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst comment = await repo.findById(id);\n\n\t\tif (!comment) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Comment not found: ${id}` },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: comment };\n\t} catch (error) {\n\t\tconsole.error(\"Comment get error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_GET_ERROR\",\n\t\t\t\tmessage: \"Failed to get comment\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Change comment status\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentStatusChange(\n\tdb: Kysely<Database>,\n\tid: string,\n\tstatus: CommentStatus,\n): Promise<ApiResult<Comment>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst updated = await repo.updateStatus(id, status);\n\n\t\tif (!updated) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Comment not found: ${id}` },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: updated };\n\t} catch (error) {\n\t\tconsole.error(\"Comment status change error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_STATUS_ERROR\",\n\t\t\t\tmessage: \"Failed to update comment status\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Hard delete comment\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentDelete(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\t\tconst deleted = await repo.delete(id);\n\n\t\tif (!deleted) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Comment not found: ${id}` },\n\t\t\t};\n\t\t}\n\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch (error) {\n\t\tconsole.error(\"Comment delete error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_DELETE_ERROR\",\n\t\t\t\tmessage: \"Failed to delete comment\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Bulk operations\n// ---------------------------------------------------------------------------\n\nexport async function handleCommentBulk(\n\tdb: Kysely<Database>,\n\tids: string[],\n\taction: \"approve\" | \"spam\" | \"trash\" | \"delete\",\n): Promise<ApiResult<{ affected: number }>> {\n\ttry {\n\t\tconst repo = new CommentRepository(db);\n\n\t\tlet affected: number;\n\t\tif (action === \"delete\") {\n\t\t\taffected = await repo.bulkDelete(ids);\n\t\t} else {\n\t\t\tconst statusMap: Record<string, CommentStatus> = {\n\t\t\t\tapprove: \"approved\",\n\t\t\t\tspam: \"spam\",\n\t\t\t\ttrash: \"trash\",\n\t\t\t};\n\t\t\taffected = await repo.bulkUpdateStatus(ids, statusMap[action]);\n\t\t}\n\n\t\treturn { success: true, data: { affected } };\n\t} catch (error) {\n\t\tconsole.error(\"Comment bulk error:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"COMMENT_BULK_ERROR\",\n\t\t\t\tmessage: \"Failed to perform bulk operation\",\n\t\t\t},\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Anti-spam: Rate limiting\n// ---------------------------------------------------------------------------\n\n/**\n * Check if an IP has exceeded the comment rate limit.\n * Uses ip_hash in the comments table — no separate counter storage.\n */\nexport async function checkRateLimit(\n\tdb: Kysely<Database>,\n\tipHash: string,\n\tmaxPerWindow: number = 5,\n\twindowMinutes: number = 10,\n): Promise<boolean> {\n\tconst cutoff = new Date(Date.now() - windowMinutes * 60 * 1000).toISOString();\n\n\t// Count recent comments from this IP\n\tconst result = await db\n\t\t.selectFrom(\"_emdash_comments\")\n\t\t.select((eb) => eb.fn.count(\"id\").as(\"count\"))\n\t\t.where(\"ip_hash\", \"=\", ipHash)\n\t\t.where(\"created_at\", \">\", cutoff)\n\t\t.executeTakeFirst();\n\n\tconst count = Number(result?.count ?? 0);\n\treturn count >= maxPerWindow;\n}\n\n/**\n * Hash an IP address for storage (never store cleartext IPs).\n *\n * Uses full SHA-256 with a site-specific salt to prevent rainbow-table\n * recovery of IPs. The salt must be provided by the caller — typically\n * via `resolveSecretsCached(db).ipSalt` from `#config/secrets.js`. The\n * salt is generated and persisted on first need so it's stable across\n * requests within a deployment but unique per install.\n */\nexport async function hashIp(ip: string, salt: string): Promise<string> {\n\tconst data = `ip:${salt}:${ip}`;\n\tconst buf = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(data));\n\treturn Array.from(new Uint8Array(buf), (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components-
|
|
1
|
+
{"version":3,"file":"components-DZkL4Fx0.mjs","names":[],"sources":["../src/widgets/components.ts"],"sourcesContent":["import type { WidgetComponentDef } from \"./types.js\";\n\n/**\n * Core widget components registry\n * These are built-in widgets that ship with EmDash\n */\nexport const coreWidgetComponents: WidgetComponentDef[] = [\n\t{\n\t\tid: \"core:recent-posts\",\n\t\tlabel: \"Recent Posts\",\n\t\tdescription: \"Display a list of recent posts\",\n\t\tprops: {\n\t\t\tcount: {\n\t\t\t\ttype: \"number\",\n\t\t\t\tlabel: \"Number of posts\",\n\t\t\t\tdefault: 5,\n\t\t\t},\n\t\t\tshowThumbnails: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tlabel: \"Show thumbnails\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tshowDate: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tlabel: \"Show date\",\n\t\t\t\tdefault: true,\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tid: \"core:categories\",\n\t\tlabel: \"Categories\",\n\t\tdescription: \"Display category list\",\n\t\tprops: {\n\t\t\tshowCount: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tlabel: \"Show post count\",\n\t\t\t\tdefault: true,\n\t\t\t},\n\t\t\thierarchical: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tlabel: \"Show hierarchy\",\n\t\t\t\tdefault: true,\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tid: \"core:tags\",\n\t\tlabel: \"Tags\",\n\t\tdescription: \"Display tag cloud\",\n\t\tprops: {\n\t\t\tshowCount: {\n\t\t\t\ttype: \"boolean\",\n\t\t\t\tlabel: \"Show count\",\n\t\t\t\tdefault: false,\n\t\t\t},\n\t\t\tlimit: {\n\t\t\t\ttype: \"number\",\n\t\t\t\tlabel: \"Maximum tags\",\n\t\t\t\tdefault: 20,\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tid: \"core:search\",\n\t\tlabel: \"Search\",\n\t\tdescription: \"Search form\",\n\t\tprops: {\n\t\t\tplaceholder: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tlabel: \"Placeholder text\",\n\t\t\t\tdefault: \"Search...\",\n\t\t\t},\n\t\t},\n\t},\n\t{\n\t\tid: \"core:archives\",\n\t\tlabel: \"Archives\",\n\t\tdescription: \"Monthly/yearly archives\",\n\t\tprops: {\n\t\t\ttype: {\n\t\t\t\ttype: \"select\",\n\t\t\t\tlabel: \"Group by\",\n\t\t\t\tdefault: \"monthly\",\n\t\t\t\toptions: [\n\t\t\t\t\t{ value: \"monthly\", label: \"Monthly\" },\n\t\t\t\t\t{ value: \"yearly\", label: \"Yearly\" },\n\t\t\t\t],\n\t\t\t},\n\t\t\tlimit: {\n\t\t\t\ttype: \"number\",\n\t\t\t\tlabel: \"Limit\",\n\t\t\t\tdefault: 12,\n\t\t\t},\n\t\t},\n\t},\n];\n\n/**\n * Get all widget component definitions (core + plugin-registered)\n * For now, only returns core components. Plugin widgets will be added later.\n */\nexport function getWidgetComponents(): WidgetComponentDef[] {\n\treturn [...coreWidgetComponents];\n}\n"],"mappings":";;;;;AAMA,MAAa,uBAA6C;CACzD;EACC,IAAI;EACJ,OAAO;EACP,aAAa;EACb,OAAO;GACN,OAAO;IACN,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD,gBAAgB;IACf,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD,UAAU;IACT,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD;EACD;CACD;EACC,IAAI;EACJ,OAAO;EACP,aAAa;EACb,OAAO;GACN,WAAW;IACV,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD,cAAc;IACb,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD;EACD;CACD;EACC,IAAI;EACJ,OAAO;EACP,aAAa;EACb,OAAO;GACN,WAAW;IACV,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD,OAAO;IACN,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD;EACD;CACD;EACC,IAAI;EACJ,OAAO;EACP,aAAa;EACb,OAAO,EACN,aAAa;GACZ,MAAM;GACN,OAAO;GACP,SAAS;GACT,EACD;EACD;CACD;EACC,IAAI;EACJ,OAAO;EACP,aAAa;EACb,OAAO;GACN,MAAM;IACL,MAAM;IACN,OAAO;IACP,SAAS;IACT,SAAS,CACR;KAAE,OAAO;KAAW,OAAO;KAAW,EACtC;KAAE,OAAO;KAAU,OAAO;KAAU,CACpC;IACD;GACD,OAAO;IACN,MAAM;IACN,OAAO;IACP,SAAS;IACT;GACD;EACD;CACD;;;;;AAMD,SAAgB,sBAA4C;AAC3D,QAAO,CAAC,GAAG,qBAAqB"}
|
|
@@ -1,11 +1,54 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as __exportAll } from "./runner-DfnZ5eUr.mjs";
|
|
2
2
|
import { t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
|
|
3
3
|
import { o as invalidateCollectionCache } from "./object-cache-Bok5j2ae.mjs";
|
|
4
|
-
import { n as
|
|
5
|
-
import {
|
|
4
|
+
import { n as chunks, t as SQL_BATCH_SIZE } from "./chunks-BxXyunY-.mjs";
|
|
5
|
+
import { n as isMissingTableError } from "./db-errors-CcWLaRiR.mjs";
|
|
6
|
+
import { n as slugify } from "./slugify-C_tqlU4G.mjs";
|
|
7
|
+
import { a as encodeCursor, i as decodeCursor, r as ScheduledNotDueError, t as EmDashValidationError } from "./types-D1iJ3DpO.mjs";
|
|
6
8
|
import { sql } from "kysely";
|
|
7
9
|
import { monotonicFactory, ulid } from "ulidx";
|
|
8
10
|
|
|
11
|
+
//#region src/search/match.ts
|
|
12
|
+
/**
|
|
13
|
+
* FTS5 match-expression builder for structured (non-user-syntax) queries.
|
|
14
|
+
*
|
|
15
|
+
* Unlike `escapeQuery` in `query.ts` (which powers the public search API and
|
|
16
|
+
* deliberately passes through FTS5 operators like AND/OR/NOT), this builder
|
|
17
|
+
* treats the input as plain words: every term is double-quoted with interior
|
|
18
|
+
* quotes escaped, so the result can never produce an FTS5 syntax error. Used
|
|
19
|
+
* by the admin content-list filter, where the input is a filter box, not a
|
|
20
|
+
* search-syntax field.
|
|
21
|
+
*/
|
|
22
|
+
const WHITESPACE_RE = /\s+/;
|
|
23
|
+
const DOUBLE_QUOTE_RE = /"/g;
|
|
24
|
+
const GLOB_SPECIAL_RE = /[[\]*?]/g;
|
|
25
|
+
/**
|
|
26
|
+
* Build a prefix-matching FTS5 MATCH expression from free-form input.
|
|
27
|
+
*
|
|
28
|
+
* `hello wor` becomes `"hello"* "wor"*` — implicit AND with per-term prefix
|
|
29
|
+
* matching. Returns `""` when the input contains no usable terms; callers
|
|
30
|
+
* must fall back to their non-FTS path in that case.
|
|
31
|
+
*/
|
|
32
|
+
function buildFtsPrefixMatch(input) {
|
|
33
|
+
const terms = input.trim().split(WHITESPACE_RE).map((term) => term.replace(DOUBLE_QUOTE_RE, "\"\"")).filter((term) => term.length > 0);
|
|
34
|
+
if (terms.length === 0) return "";
|
|
35
|
+
return terms.map((term) => `"${term}"*`).join(" ");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build a GLOB prefix pattern from free-form input, treating GLOB
|
|
39
|
+
* metacharacters (`* ? [ ]`) literally by wrapping each in a character
|
|
40
|
+
* class (GLOB has no ESCAPE clause).
|
|
41
|
+
*
|
|
42
|
+
* GLOB (unlike default LIKE) is case-sensitive, so with a lowercased
|
|
43
|
+
* pattern it matches slugs (lowercase by construction) while staying
|
|
44
|
+
* servable by the ordinary BINARY-collated slug index — SQLite's GLOB
|
|
45
|
+
* optimization turns a `prefix*` pattern into an index range scan.
|
|
46
|
+
*/
|
|
47
|
+
function buildSlugGlobPrefix(input) {
|
|
48
|
+
return `${input.trim().toLowerCase().replace(GLOB_SPECIAL_RE, (c) => `[${c}]`)}*`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
9
52
|
//#region src/database/repositories/revision.ts
|
|
10
53
|
const monotonic = monotonicFactory();
|
|
11
54
|
/**
|
|
@@ -357,14 +400,19 @@ var ContentRepository = class {
|
|
|
357
400
|
const looksLikeUlid = ULID_PATTERN.test(identifier);
|
|
358
401
|
const findById = includeTrashed ? (t, id) => this.findByIdIncludingTrashed(t, id) : (t, id) => this.findById(t, id);
|
|
359
402
|
const findBySlug = includeTrashed ? (t, s) => this.findBySlugIncludingTrashed(t, s, locale) : (t, s) => this.findBySlug(t, s, locale);
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
403
|
+
try {
|
|
404
|
+
if (looksLikeUlid) {
|
|
405
|
+
const byId = await findById(type, identifier);
|
|
406
|
+
if (byId) return byId;
|
|
407
|
+
return await findBySlug(type, identifier);
|
|
408
|
+
}
|
|
409
|
+
const bySlug = await findBySlug(type, identifier);
|
|
410
|
+
if (bySlug) return bySlug;
|
|
411
|
+
return await findById(type, identifier);
|
|
412
|
+
} catch (error) {
|
|
413
|
+
if (isMissingTableError(error)) return null;
|
|
414
|
+
throw error;
|
|
364
415
|
}
|
|
365
|
-
const bySlug = await findBySlug(type, identifier);
|
|
366
|
-
if (bySlug) return bySlug;
|
|
367
|
-
return findById(type, identifier);
|
|
368
416
|
}
|
|
369
417
|
/**
|
|
370
418
|
* Find content by slug
|
|
@@ -419,7 +467,7 @@ var ContentRepository = class {
|
|
|
419
467
|
if (options.where?.status) query = query.where("status", "=", options.where.status);
|
|
420
468
|
if (options.where?.authorId) query = query.where("author_id", "=", options.where.authorId);
|
|
421
469
|
if (options.where?.locale) query = query.where("locale", "=", options.where.locale);
|
|
422
|
-
query = this.applySearchFilter(query, options.where);
|
|
470
|
+
query = this.applySearchFilter(query, options.where, type);
|
|
423
471
|
query = this.applyDateFilter(query, options.where);
|
|
424
472
|
if (options.cursor) {
|
|
425
473
|
const { orderValue, id: cursorId } = decodeCursor(options.cursor);
|
|
@@ -446,10 +494,8 @@ var ContentRepository = class {
|
|
|
446
494
|
*/
|
|
447
495
|
async update(type, id, input) {
|
|
448
496
|
const tableName = getTableName(type);
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
version: sql`version + 1`
|
|
452
|
-
};
|
|
497
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
498
|
+
const updates = {};
|
|
453
499
|
if (input.status !== void 0) updates.status = input.status;
|
|
454
500
|
if (input.slug !== void 0) updates.slug = input.slug;
|
|
455
501
|
if (input.publishedAt !== void 0) updates.published_at = input.publishedAt;
|
|
@@ -462,7 +508,10 @@ var ContentRepository = class {
|
|
|
462
508
|
updates[key] = serializeValue(value);
|
|
463
509
|
}
|
|
464
510
|
}
|
|
511
|
+
if (Object.keys(updates).length > 0) updates.updated_at = now;
|
|
512
|
+
updates.version = sql`version + 1`;
|
|
465
513
|
await this.db.updateTable(tableName).set(updates).where("id", "=", id).where("deleted_at", "is", null).execute();
|
|
514
|
+
if (input.status !== void 0 || input.publishedAt !== void 0 || input.scheduledAt !== void 0) await this.restampEntryPivot(type, id);
|
|
466
515
|
invalidateCollectionCache(type);
|
|
467
516
|
const updated = await this.findById(type, id);
|
|
468
517
|
if (!updated) throw new Error("Content not found");
|
|
@@ -480,7 +529,10 @@ var ContentRepository = class {
|
|
|
480
529
|
WHERE id = ${id}
|
|
481
530
|
AND deleted_at IS NULL
|
|
482
531
|
`.execute(this.db)).numAffectedRows ?? 0n) > 0n;
|
|
483
|
-
if (changed)
|
|
532
|
+
if (changed) {
|
|
533
|
+
await this.restampEntryPivot(type, id);
|
|
534
|
+
invalidateCollectionCache(type);
|
|
535
|
+
}
|
|
484
536
|
return changed;
|
|
485
537
|
}
|
|
486
538
|
/**
|
|
@@ -496,10 +548,35 @@ var ContentRepository = class {
|
|
|
496
548
|
RETURNING *
|
|
497
549
|
`.execute(this.db)).rows[0];
|
|
498
550
|
if (!restored) return null;
|
|
551
|
+
await this.restampEntryPivot(type, id);
|
|
499
552
|
invalidateCollectionCache(type);
|
|
500
553
|
return this.mapRow(type, restored);
|
|
501
554
|
}
|
|
502
555
|
/**
|
|
556
|
+
* Re-stamp the denormalized filter + sort columns on every
|
|
557
|
+
* `content_taxonomies` pivot row for an entry from its authoritative `ec_*`
|
|
558
|
+
* row (migration 051). Called after any mutation that moves one of those
|
|
559
|
+
* columns so a taxonomy-filtered listing can seek the entry directly.
|
|
560
|
+
*
|
|
561
|
+
* A single correlated `UPDATE` reads the post-mutation values from `ec_*`, so
|
|
562
|
+
* the pivot converges to the authoritative row. This is NOT atomic with the
|
|
563
|
+
* `ec_*` mutation on D1 (no transactions), which is why the read path
|
|
564
|
+
* re-checks the real predicates on the joined `ec_*` row. Untagged entries
|
|
565
|
+
* have no pivot rows, so the statement is a cheap no-op for them.
|
|
566
|
+
*/
|
|
567
|
+
async restampEntryPivot(type, id) {
|
|
568
|
+
const tableName = getTableName(type);
|
|
569
|
+
await sql`
|
|
570
|
+
UPDATE content_taxonomies
|
|
571
|
+
SET (status, scheduled_at, deleted_at, locale, published_at, created_at) = (
|
|
572
|
+
SELECT status, scheduled_at, deleted_at, locale, published_at, created_at
|
|
573
|
+
FROM ${sql.ref(tableName)}
|
|
574
|
+
WHERE ${sql.ref(tableName)}.id = ${id}
|
|
575
|
+
)
|
|
576
|
+
WHERE collection = ${type} AND entry_id = ${id}
|
|
577
|
+
`.execute(this.db);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
503
580
|
* Permanently delete content (cannot be undone)
|
|
504
581
|
*/
|
|
505
582
|
/**
|
|
@@ -565,15 +642,34 @@ var ContentRepository = class {
|
|
|
565
642
|
return Number(result?.count || 0);
|
|
566
643
|
}
|
|
567
644
|
/**
|
|
568
|
-
* Apply the optional
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
* SQLite
|
|
645
|
+
* Apply the optional `q` filter.
|
|
646
|
+
*
|
|
647
|
+
* When the handler sets `useFts` (collection has a healthy FTS5 index
|
|
648
|
+
* covering the display columns; SQLite only), the filter is served from
|
|
649
|
+
* the index: a token-prefix MATCH against `_emdash_fts_<slug>` OR'd with
|
|
650
|
+
* an index-served `slug GLOB 'term*'` prefix (the slug is not in the FTS
|
|
651
|
+
* index). Both sides are index-backed, so SQLite's OR optimization avoids
|
|
652
|
+
* the full-table scan the LIKE fallback needs (#1517). The trade-off is
|
|
653
|
+
* search semantics: token-prefix matching instead of arbitrary substring.
|
|
654
|
+
*
|
|
655
|
+
* Fallback (Postgres, search disabled, or no usable terms): case-
|
|
656
|
+
* insensitive substring LIKE across the handler-resolved `searchColumns`
|
|
657
|
+
* (OR'd). User input is treated literally (LIKE wildcards escaped) and
|
|
658
|
+
* `lower()` is applied on both sides for SQLite/Postgres parity.
|
|
572
659
|
*/
|
|
573
|
-
applySearchFilter(query, where) {
|
|
660
|
+
applySearchFilter(query, where, type) {
|
|
574
661
|
const term = where?.q?.trim();
|
|
575
662
|
const columns = where?.searchColumns;
|
|
576
663
|
if (!term || !columns || columns.length === 0) return query;
|
|
664
|
+
if (where.useFts) {
|
|
665
|
+
const match = buildFtsPrefixMatch(term);
|
|
666
|
+
if (match) {
|
|
667
|
+
validateIdentifier(type, "collection slug");
|
|
668
|
+
const ftsTable = `_emdash_fts_${type}`;
|
|
669
|
+
const slugPrefix = buildSlugGlobPrefix(term);
|
|
670
|
+
return query.where((eb) => eb.or([sql`id IN (SELECT id FROM ${sql.ref(ftsTable)} WHERE ${sql.ref(ftsTable)} MATCH ${match})`, sql`slug GLOB ${slugPrefix}`]));
|
|
671
|
+
}
|
|
672
|
+
}
|
|
577
673
|
const pattern = `%${term.replace(LIKE_WILDCARD_RE, (c) => `\\${c}`)}%`;
|
|
578
674
|
return query.where((eb) => eb.or(columns.map((col) => {
|
|
579
675
|
validateIdentifier(col, "search column");
|
|
@@ -607,7 +703,7 @@ var ContentRepository = class {
|
|
|
607
703
|
if (where?.status) query = query.where("status", "=", where.status);
|
|
608
704
|
if (where?.authorId) query = query.where("author_id", "=", where.authorId);
|
|
609
705
|
if (where?.locale) query = query.where("locale", "=", where.locale);
|
|
610
|
-
query = this.applySearchFilter(query, where);
|
|
706
|
+
query = this.applySearchFilter(query, where, type);
|
|
611
707
|
query = this.applyDateFilter(query, where);
|
|
612
708
|
const result = await query.executeTakeFirst();
|
|
613
709
|
return Number(result?.count || 0);
|
|
@@ -627,12 +723,14 @@ var ContentRepository = class {
|
|
|
627
723
|
const result = await this.db.selectFrom(tableName).select((eb) => [
|
|
628
724
|
eb.fn.count("id").as("total"),
|
|
629
725
|
eb.fn.sum(eb.case().when("status", "=", "published").then(1).else(0).end()).as("published"),
|
|
630
|
-
eb.fn.sum(eb.case().when("status", "=", "draft").then(1).else(0).end()).as("draft")
|
|
726
|
+
eb.fn.sum(eb.case().when("status", "=", "draft").then(1).else(0).end()).as("draft"),
|
|
727
|
+
sql`SUM(CASE WHEN scheduled_at IS NOT NULL THEN 1 ELSE 0 END)`.as("scheduled")
|
|
631
728
|
]).where("deleted_at", "is", null).executeTakeFirst();
|
|
632
729
|
return {
|
|
633
730
|
total: Number(result?.total || 0),
|
|
634
731
|
published: Number(result?.published || 0),
|
|
635
|
-
draft: Number(result?.draft || 0)
|
|
732
|
+
draft: Number(result?.draft || 0),
|
|
733
|
+
scheduled: Number(result?.scheduled || 0)
|
|
636
734
|
};
|
|
637
735
|
}
|
|
638
736
|
/**
|
|
@@ -658,6 +756,7 @@ var ContentRepository = class {
|
|
|
658
756
|
WHERE id = ${id}
|
|
659
757
|
AND deleted_at IS NULL
|
|
660
758
|
`.execute(this.db);
|
|
759
|
+
await this.restampEntryPivot(type, id);
|
|
661
760
|
invalidateCollectionCache(type);
|
|
662
761
|
const updated = await this.findById(type, id);
|
|
663
762
|
if (!updated) throw new Error("Content not found");
|
|
@@ -684,6 +783,7 @@ var ContentRepository = class {
|
|
|
684
783
|
AND scheduled_at IS NOT NULL
|
|
685
784
|
AND deleted_at IS NULL
|
|
686
785
|
`.execute(this.db);
|
|
786
|
+
await this.restampEntryPivot(type, id);
|
|
687
787
|
invalidateCollectionCache(type);
|
|
688
788
|
const updated = await this.findById(type, id);
|
|
689
789
|
if (!updated) throw new Error("Content not found");
|
|
@@ -727,6 +827,96 @@ var ContentRepository = class {
|
|
|
727
827
|
`.execute(this.db)).rows.map((row) => this.mapRow(type, row));
|
|
728
828
|
}
|
|
729
829
|
/**
|
|
830
|
+
* Batch variant of {@link findTranslations}: every (non-deleted) locale
|
|
831
|
+
* variant for any of `translationGroups`, in one `WHERE translation_group IN
|
|
832
|
+
* (...)` query chunked at `SQL_BATCH_SIZE` for D1's bind-parameter limit.
|
|
833
|
+
* Lets callers resolve many edge groups without an N+1 per group. The caller
|
|
834
|
+
* groups the flat result by `translationGroup` itself.
|
|
835
|
+
*
|
|
836
|
+
* `publishedOnly` restricts the result to `status = 'published'` — reference
|
|
837
|
+
* reads pass this for callers without `content:read_drafts` so draft/scheduled
|
|
838
|
+
* entries never leak through an edge traversal.
|
|
839
|
+
*
|
|
840
|
+
* A reference edge stores only a collection slug (no SQL FK), so the table may
|
|
841
|
+
* have been dropped since the edge was written. That is a tolerated dangling
|
|
842
|
+
* state, not an error: a missing table resolves to no rows, mirroring how the
|
|
843
|
+
* content read handlers treat `isMissingTableError`.
|
|
844
|
+
*/
|
|
845
|
+
async findTranslationsForGroups(type, translationGroups, options = {}) {
|
|
846
|
+
if (translationGroups.length === 0) return [];
|
|
847
|
+
const tableName = getTableName(type);
|
|
848
|
+
const publishedFilter = options.publishedOnly ? sql`AND status = 'published'` : sql``;
|
|
849
|
+
const items = [];
|
|
850
|
+
try {
|
|
851
|
+
for (const chunk of chunks(translationGroups, SQL_BATCH_SIZE)) {
|
|
852
|
+
const result = await sql`
|
|
853
|
+
SELECT * FROM ${sql.ref(tableName)}
|
|
854
|
+
WHERE translation_group IN (${sql.join(chunk)})
|
|
855
|
+
AND deleted_at IS NULL
|
|
856
|
+
${publishedFilter}
|
|
857
|
+
ORDER BY locale ASC
|
|
858
|
+
`.execute(this.db);
|
|
859
|
+
for (const row of result.rows) items.push(this.mapRow(type, row));
|
|
860
|
+
}
|
|
861
|
+
} catch (error) {
|
|
862
|
+
if (isMissingTableError(error)) return [];
|
|
863
|
+
throw error;
|
|
864
|
+
}
|
|
865
|
+
return items;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* Batch variant of {@link findByIdOrSlug}: resolve many identifiers (each an
|
|
869
|
+
* id OR a slug) within `type` in a constant number of queries — one `WHERE id
|
|
870
|
+
* IN (...)` and one `WHERE slug IN (...)`, each chunked at `SQL_BATCH_SIZE`.
|
|
871
|
+
* Returns a map from the input identifier to its resolved item; identifiers
|
|
872
|
+
* that match nothing are absent. Used on write paths that accept a list of
|
|
873
|
+
* references, so a single request doesn't fan out to an N+1 of point lookups.
|
|
874
|
+
*
|
|
875
|
+
* Resolution mirrors {@link findByIdOrSlug}: a ULID-shaped identifier prefers
|
|
876
|
+
* the id match and falls back to slug; anything else prefers the slug match
|
|
877
|
+
* and falls back to id. Slug matches collapse to the lowest-locale variant
|
|
878
|
+
* (`ORDER BY locale ASC`), matching the slug-without-locale lookup.
|
|
879
|
+
*/
|
|
880
|
+
async findManyByIdOrSlug(type, identifiers) {
|
|
881
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
882
|
+
const unique = [...new Set(identifiers)];
|
|
883
|
+
if (unique.length === 0) return resolved;
|
|
884
|
+
const tableName = getTableName(type);
|
|
885
|
+
const byId = /* @__PURE__ */ new Map();
|
|
886
|
+
const bySlug = /* @__PURE__ */ new Map();
|
|
887
|
+
try {
|
|
888
|
+
for (const chunk of chunks(unique, SQL_BATCH_SIZE)) {
|
|
889
|
+
const idRows = await sql`
|
|
890
|
+
SELECT * FROM ${sql.ref(tableName)}
|
|
891
|
+
WHERE id IN (${sql.join(chunk)})
|
|
892
|
+
AND deleted_at IS NULL
|
|
893
|
+
`.execute(this.db);
|
|
894
|
+
for (const row of idRows.rows) {
|
|
895
|
+
const item = this.mapRow(type, row);
|
|
896
|
+
byId.set(item.id, item);
|
|
897
|
+
}
|
|
898
|
+
const slugRows = await sql`
|
|
899
|
+
SELECT * FROM ${sql.ref(tableName)}
|
|
900
|
+
WHERE slug IN (${sql.join(chunk)})
|
|
901
|
+
AND deleted_at IS NULL
|
|
902
|
+
ORDER BY locale ASC
|
|
903
|
+
`.execute(this.db);
|
|
904
|
+
for (const row of slugRows.rows) {
|
|
905
|
+
const item = this.mapRow(type, row);
|
|
906
|
+
if (item.slug != null && !bySlug.has(item.slug)) bySlug.set(item.slug, item);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
} catch (error) {
|
|
910
|
+
if (isMissingTableError(error)) return resolved;
|
|
911
|
+
throw error;
|
|
912
|
+
}
|
|
913
|
+
for (const identifier of unique) {
|
|
914
|
+
const item = ULID_PATTERN.test(identifier) ? byId.get(identifier) ?? bySlug.get(identifier) : bySlug.get(identifier) ?? byId.get(identifier);
|
|
915
|
+
if (item) resolved.set(identifier, item);
|
|
916
|
+
}
|
|
917
|
+
return resolved;
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
730
920
|
* Publish the current draft
|
|
731
921
|
*
|
|
732
922
|
* Promotes draft_revision_id to live_revision_id and clears draft pointer.
|
|
@@ -779,12 +969,17 @@ var ContentRepository = class {
|
|
|
779
969
|
})).id;
|
|
780
970
|
const revision = await revisionRepo.findById(revisionToPublish);
|
|
781
971
|
if (revision) {
|
|
782
|
-
|
|
783
|
-
if (
|
|
972
|
+
const stagedSlug = typeof revision.data._slug === "string" ? revision.data._slug : null;
|
|
973
|
+
if (stagedSlug !== null && stagedSlug !== existing.slug && existing.locale !== null) {
|
|
974
|
+
const conflict = await this.findBySlugIncludingTrashed(type, stagedSlug, existing.locale);
|
|
975
|
+
if (conflict && conflict.id !== id) throw new EmDashValidationError(`Cannot publish: slug '${stagedSlug}' is already used by another entry in this collection (id: ${conflict.id}). Choose a different slug.`, { code: "SLUG_CONFLICT" });
|
|
976
|
+
}
|
|
977
|
+
if (stagedSlug !== null) await sql`
|
|
784
978
|
UPDATE ${sql.ref(tableName)}
|
|
785
|
-
SET slug = ${
|
|
979
|
+
SET slug = ${stagedSlug}
|
|
786
980
|
WHERE id = ${id}
|
|
787
981
|
`.execute(this.db);
|
|
982
|
+
await this.syncDataColumns(type, id, revision.data);
|
|
788
983
|
}
|
|
789
984
|
if (publishedAt !== void 0) await sql`
|
|
790
985
|
UPDATE ${sql.ref(tableName)}
|
|
@@ -809,6 +1004,7 @@ var ContentRepository = class {
|
|
|
809
1004
|
AND deleted_at IS NULL
|
|
810
1005
|
`.execute(this.db);
|
|
811
1006
|
publishCommitted = true;
|
|
1007
|
+
await this.restampEntryPivot(type, id);
|
|
812
1008
|
const updated = await this.findById(type, id);
|
|
813
1009
|
if (!updated) throw new Error("Content not found");
|
|
814
1010
|
invalidateCollectionCache(type);
|
|
@@ -866,6 +1062,7 @@ var ContentRepository = class {
|
|
|
866
1062
|
WHERE id = ${id}
|
|
867
1063
|
AND deleted_at IS NULL
|
|
868
1064
|
`.execute(this.db);
|
|
1065
|
+
await this.restampEntryPivot(type, id);
|
|
869
1066
|
invalidateCollectionCache(type);
|
|
870
1067
|
const updated = await this.findById(type, id);
|
|
871
1068
|
if (!updated) throw new Error("Content not found");
|
|
@@ -884,15 +1081,13 @@ var ContentRepository = class {
|
|
|
884
1081
|
*/
|
|
885
1082
|
async setDraftRevision(type, id, revisionId) {
|
|
886
1083
|
const tableName = getTableName(type);
|
|
887
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
888
1084
|
if (!await this.findById(type, id)) throw new EmDashValidationError("Content item not found");
|
|
889
1085
|
const revision = await new RevisionRepository(this.db).findById(revisionId);
|
|
890
1086
|
if (!revision) throw new EmDashValidationError("Revision not found");
|
|
891
1087
|
if (revision.collection !== type || revision.entryId !== id) throw new EmDashValidationError("Revision does not belong to the specified content item");
|
|
892
1088
|
await sql`
|
|
893
1089
|
UPDATE ${sql.ref(tableName)}
|
|
894
|
-
SET draft_revision_id = ${revisionId}
|
|
895
|
-
updated_at = ${now}
|
|
1090
|
+
SET draft_revision_id = ${revisionId}
|
|
896
1091
|
WHERE id = ${id}
|
|
897
1092
|
AND deleted_at IS NULL
|
|
898
1093
|
`.execute(this.db);
|
|
@@ -906,14 +1101,12 @@ var ContentRepository = class {
|
|
|
906
1101
|
*/
|
|
907
1102
|
async discardDraft(type, id) {
|
|
908
1103
|
const tableName = getTableName(type);
|
|
909
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
910
1104
|
const existing = await this.findById(type, id);
|
|
911
1105
|
if (!existing) throw new EmDashValidationError("Content item not found");
|
|
912
1106
|
if (!existing.draftRevisionId) return existing;
|
|
913
1107
|
await sql`
|
|
914
1108
|
UPDATE ${sql.ref(tableName)}
|
|
915
|
-
SET draft_revision_id = NULL
|
|
916
|
-
updated_at = ${now}
|
|
1109
|
+
SET draft_revision_id = NULL
|
|
917
1110
|
WHERE id = ${id}
|
|
918
1111
|
AND deleted_at IS NULL
|
|
919
1112
|
`.execute(this.db);
|
|
@@ -1004,4 +1197,4 @@ var ContentRepository = class {
|
|
|
1004
1197
|
|
|
1005
1198
|
//#endregion
|
|
1006
1199
|
export { content_exports as n, RevisionRepository as r, ContentRepository as t };
|
|
1007
|
-
//# sourceMappingURL=content-
|
|
1200
|
+
//# sourceMappingURL=content-Ci04z2z-.mjs.map
|