emdash 0.20.0 → 0.22.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-BzIHV3sw.d.mts → adapters-hUy8vOB-.d.mts} +1 -1
- package/dist/{adapters-BzIHV3sw.d.mts.map → adapters-hUy8vOB-.d.mts.map} +1 -1
- package/dist/after-B1IIdH3Y.mjs +29 -0
- package/dist/after-B1IIdH3Y.mjs.map +1 -0
- package/dist/{allowed-origins-B1u7Qnvg.mjs → allowed-origins-DjlhyfNN.mjs} +2 -2
- package/dist/{allowed-origins-B1u7Qnvg.mjs.map → allowed-origins-DjlhyfNN.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +20 -18
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +4 -3
- package/dist/{api-DStv36ik.mjs → api-BDuM4bEy.mjs} +31 -25
- package/dist/api-BDuM4bEy.mjs.map +1 -0
- package/dist/{api-tokens-DPfhPu5V.mjs → api-tokens-ViYKeIp9.mjs} +13 -3
- package/dist/api-tokens-ViYKeIp9.mjs.map +1 -0
- package/dist/{apply-Dr7snAMT.mjs → apply-wDqQoxX4.mjs} +18 -18
- package/dist/{apply-Dr7snAMT.mjs.map → apply-wDqQoxX4.mjs.map} +1 -1
- package/dist/astro/image-endpoint.d.mts +8 -0
- package/dist/astro/image-endpoint.d.mts.map +1 -0
- package/dist/astro/image-endpoint.mjs +55 -0
- package/dist/astro/image-endpoint.mjs.map +1 -0
- package/dist/astro/index.d.mts +36 -11
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +160 -35
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +9 -9
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +12 -10
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +14 -5
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +5 -4
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +157 -80
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -6
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +10 -9
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +10 -9
- package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +10 -9
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +17 -14
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +17 -14
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +17 -14
- package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +15 -12
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -6
- package/dist/astro/routes/api/admin/comments/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/bulk.mjs +12 -9
- package/dist/astro/routes/api/admin/comments/bulk.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/counts.mjs +8 -6
- package/dist/astro/routes/api/admin/comments/counts.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/index.mjs +12 -9
- 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/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 +40 -37
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +40 -37
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +39 -36
- 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 +39 -36
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +40 -37
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +40 -37
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +39 -36
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +39 -36
- 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 +39 -36
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +4 -4
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +8 -7
- package/dist/astro/routes/api/admin/users/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +5 -5
- package/dist/astro/routes/api/admin/users/index.mjs +7 -6
- package/dist/astro/routes/api/admin/users/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -6
- package/dist/astro/routes/api/auth/invite/accept.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/complete.mjs +12 -11
- package/dist/astro/routes/api/auth/invite/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/index.mjs +9 -8
- package/dist/astro/routes/api/auth/invite/index.mjs.map +1 -1
- package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -10
- 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 +11 -10
- package/dist/astro/routes/api/auth/magic-link/send.mjs.map +1 -1
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +4 -4
- package/dist/astro/routes/api/auth/me.mjs +8 -7
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -6
- 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 +13 -12
- package/dist/astro/routes/api/auth/passkey/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -10
- package/dist/astro/routes/api/auth/passkey/register/options.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -11
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -11
- package/dist/astro/routes/api/auth/passkey/verify.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/complete.mjs +12 -11
- package/dist/astro/routes/api/auth/signup/complete.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/request.mjs +11 -10
- package/dist/astro/routes/api/auth/signup/request.mjs.map +1 -1
- package/dist/astro/routes/api/auth/signup/verify.mjs +3 -3
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +16 -13
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs.map +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts +9 -0
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.d.mts.map +1 -0
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +179 -0
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs.map +1 -0
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +13 -11
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +17 -14
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/index.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/trash.mjs.map +1 -1
- package/dist/astro/routes/api/dashboard.mjs +10 -8
- package/dist/astro/routes/api/dashboard.mjs.map +1 -1
- package/dist/astro/routes/api/dev/emails.mjs +4 -4
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +12 -11
- 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 +9 -9
- package/dist/astro/routes/api/import/wordpress/execute.mjs +16 -14
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +10 -9
- package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +11 -10
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +10 -9
- 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 +12 -11
- 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 +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +18 -15
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +5 -5
- package/dist/astro/routes/api/mcp.mjs +213 -45
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +8 -7
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +8 -7
- package/dist/astro/routes/api/media/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/media/file/_...key_.mjs +3 -3
- 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 +10 -9
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- package/dist/astro/routes/api/media.mjs +13 -12
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +11 -8
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items.mjs +11 -8
- package/dist/astro/routes/api/menus/_name_/items.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +11 -8
- package/dist/astro/routes/api/menus/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/translations.mjs +11 -8
- package/dist/astro/routes/api/menus/_name_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_.mjs +11 -8
- package/dist/astro/routes/api/menus/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/menus/index.mjs +11 -8
- package/dist/astro/routes/api/menus/index.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -7
- package/dist/astro/routes/api/oauth/device/code.mjs +10 -10
- package/dist/astro/routes/api/oauth/device/token.mjs +9 -9
- package/dist/astro/routes/api/oauth/register.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -7
- package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -7
- package/dist/astro/routes/api/oauth/token.mjs +7 -7
- package/dist/astro/routes/api/openapi.json.mjs +5 -4
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +5 -5
- package/dist/astro/routes/api/redirects/404s/index.mjs +11 -10
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +11 -10
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +12 -11
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +12 -11
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +4 -4
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +4 -4
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +39 -36
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +39 -36
- 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 +39 -36
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +39 -36
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +39 -36
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +7 -7
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +39 -36
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +39 -36
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +11 -10
- package/dist/astro/routes/api/search/enable.mjs.map +1 -1
- package/dist/astro/routes/api/search/index.mjs +10 -9
- package/dist/astro/routes/api/search/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/rebuild.mjs +11 -10
- package/dist/astro/routes/api/search/rebuild.mjs.map +1 -1
- package/dist/astro/routes/api/search/stats.mjs +7 -7
- package/dist/astro/routes/api/search/suggest.mjs +10 -9
- package/dist/astro/routes/api/search/suggest.mjs.map +1 -1
- package/dist/astro/routes/api/sections/_slug_.mjs +10 -9
- package/dist/astro/routes/api/sections/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +10 -9
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/email.mjs +6 -6
- package/dist/astro/routes/api/settings.mjs +16 -13
- package/dist/astro/routes/api/settings.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin-verify.mjs +13 -12
- package/dist/astro/routes/api/setup/admin-verify.mjs.map +1 -1
- package/dist/astro/routes/api/setup/admin.mjs +12 -11
- package/dist/astro/routes/api/setup/admin.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +29 -26
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +4 -4
- package/dist/astro/routes/api/setup/index.mjs +29 -26
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/snapshot.mjs +10 -8
- package/dist/astro/routes/api/snapshot.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +16 -13
- 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 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +16 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +16 -13
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- package/dist/astro/routes/api/themes/preview.mjs +8 -7
- package/dist/astro/routes/api/themes/preview.mjs.map +1 -1
- 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.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +8 -7
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +11 -10
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +11 -10
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/index.mjs +11 -10
- 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 +10 -8
- package/dist/astro/routes/robots.txt.mjs.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +13 -11
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +11 -9
- package/dist/astro/routes/sitemap.xml.mjs.map +1 -1
- package/dist/astro/types.d.mts +16 -12
- 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-DsMSVSaY.mjs → authorize-C0EYoUeV.mjs} +2 -2
- package/dist/{authorize-DsMSVSaY.mjs.map → authorize-C0EYoUeV.mjs.map} +1 -1
- package/dist/{base64-CqR-7kqF.mjs → base64-CmWvODNW.mjs} +1 -1
- package/dist/{base64-CqR-7kqF.mjs.map → base64-CmWvODNW.mjs.map} +1 -1
- package/dist/{byline-DUx48sJp.mjs → byline-CC0WS4Gu.mjs} +40 -18
- package/dist/byline-CC0WS4Gu.mjs.map +1 -0
- package/dist/{byline-fields-8TMtkBnH.mjs → byline-fields-53i9Et0x.mjs} +3 -3
- package/dist/{byline-fields-8TMtkBnH.mjs.map → byline-fields-53i9Et0x.mjs.map} +1 -1
- package/dist/{byline-fields--WxSNS79.mjs → byline-fields-DNp0HNKc.mjs} +2 -2
- package/dist/{byline-fields--WxSNS79.mjs.map → byline-fields-DNp0HNKc.mjs.map} +1 -1
- package/dist/{byline-fields-DbibsvTl.d.mts → byline-fields-jy07PZJM.d.mts} +9 -4
- package/dist/byline-fields-jy07PZJM.d.mts.map +1 -0
- package/dist/{byline-registry-CWP7I71B.mjs → byline-registry-BOjqDOim.mjs} +3 -3
- package/dist/{byline-registry-CWP7I71B.mjs.map → byline-registry-BOjqDOim.mjs.map} +1 -1
- package/dist/{bylines-s8c2DXbH.mjs → bylines-CCO1CYnH.mjs} +8 -8
- package/dist/{bylines-s8c2DXbH.mjs.map → bylines-CCO1CYnH.mjs.map} +1 -1
- package/dist/{bylines-BdxWCnPL.mjs → bylines-DGekMGGm.mjs} +10 -4
- package/dist/{bylines-BdxWCnPL.mjs.map → bylines-DGekMGGm.mjs.map} +1 -1
- package/dist/{cache-B_HzASVT.mjs → cache-pXTpun6s.mjs} +3 -3
- package/dist/{cache-B_HzASVT.mjs.map → cache-pXTpun6s.mjs.map} +1 -1
- package/dist/{challenge-store-DXX3rfdI.mjs → challenge-store-C6E_kWTs.mjs} +1 -1
- package/dist/{challenge-store-DXX3rfdI.mjs.map → challenge-store-C6E_kWTs.mjs.map} +1 -1
- package/dist/{chunks-BerYVuve.mjs → chunks-SyjZaYwV.mjs} +2 -2
- package/dist/{chunks-BerYVuve.mjs.map → chunks-SyjZaYwV.mjs.map} +1 -1
- package/dist/cli/index.mjs +29 -27
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +1 -1
- package/dist/client/index.mjs +2 -1
- package/dist/client/index.mjs.map +1 -1
- package/dist/{comment-sqQxNpN3.mjs → comment-80UyJJUR.mjs} +11 -3
- package/dist/comment-80UyJJUR.mjs.map +1 -0
- package/dist/comment-reaction-B6AdcpXw.mjs +85 -0
- package/dist/comment-reaction-B6AdcpXw.mjs.map +1 -0
- package/dist/{comments-Vkivawyl.mjs → comments-CtPkT2tp.mjs} +3 -3
- package/dist/{comments-Vkivawyl.mjs.map → comments-CtPkT2tp.mjs.map} +1 -1
- package/dist/{components-CK0cuUoH.mjs → components-D6ZnrzbB.mjs} +1 -1
- package/dist/{components-CK0cuUoH.mjs.map → components-D6ZnrzbB.mjs.map} +1 -1
- package/dist/{content-BIlVx-RX.mjs → content-2PTDNnoh.mjs} +22 -7
- package/dist/content-2PTDNnoh.mjs.map +1 -0
- package/dist/{context-Y7BRkWes.mjs → context-f1__jpzF.mjs} +11 -11
- package/dist/{context-Y7BRkWes.mjs.map → context-f1__jpzF.mjs.map} +1 -1
- package/dist/{cron-BJ2ClIlj.mjs → cron-CQPxBjYs.mjs} +1 -1
- package/dist/{cron-BJ2ClIlj.mjs.map → cron-CQPxBjYs.mjs.map} +1 -1
- package/dist/{dashboard-2JgAMWxK.mjs → dashboard-BOESNcwE.mjs} +4 -4
- package/dist/{dashboard-2JgAMWxK.mjs.map → dashboard-BOESNcwE.mjs.map} +1 -1
- package/dist/database/instrumentation.d.mts +19 -0
- package/dist/database/instrumentation.d.mts.map +1 -1
- package/dist/database/instrumentation.mjs +8 -1
- package/dist/database/instrumentation.mjs.map +1 -1
- package/dist/db/index.d.mts +3 -3
- package/dist/db/index.mjs +1 -1
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{db-errors-CtzxKBxe.mjs → db-errors-CrC5w3Jz.mjs} +1 -1
- package/dist/{db-errors-CtzxKBxe.mjs.map → db-errors-CrC5w3Jz.mjs.map} +1 -1
- package/dist/{default-IlBaTFxM.mjs → default-CpBEPn6a.mjs} +1 -1
- package/dist/{default-IlBaTFxM.mjs.map → default-CpBEPn6a.mjs.map} +1 -1
- package/dist/{device-flow-R23SIbQ2.mjs → device-flow-Bn-qiDrw.mjs} +5 -5
- package/dist/{device-flow-R23SIbQ2.mjs.map → device-flow-Bn-qiDrw.mjs.map} +1 -1
- package/dist/{email-console-DHT2Fbpj.mjs → email-console-B9VS6eN4.mjs} +1 -1
- package/dist/{email-console-DHT2Fbpj.mjs.map → email-console-B9VS6eN4.mjs.map} +1 -1
- package/dist/{error-RwM4dD35.mjs → error-BQ1pxs0L.mjs} +2 -2
- package/dist/{error-RwM4dD35.mjs.map → error-BQ1pxs0L.mjs.map} +1 -1
- package/dist/{escape-Ds07EEyu.mjs → escape-BtbJWyaW.mjs} +1 -1
- package/dist/{escape-Ds07EEyu.mjs.map → escape-BtbJWyaW.mjs.map} +1 -1
- package/dist/{fts-manager-1RgHmopc.mjs → fts-manager-DtiWqwNJ.mjs} +2 -2
- package/dist/{fts-manager-1RgHmopc.mjs.map → fts-manager-DtiWqwNJ.mjs.map} +1 -1
- package/dist/{hash-9w3pd3-m.mjs → hash-BowcuPwv.mjs} +1 -1
- package/dist/{hash-9w3pd3-m.mjs.map → hash-BowcuPwv.mjs.map} +1 -1
- package/dist/{import-Dh8bWmyq.mjs → import-DqSGOlmR.mjs} +4 -4
- package/dist/{import-Dh8bWmyq.mjs.map → import-DqSGOlmR.mjs.map} +1 -1
- package/dist/{index-B1keaX5Y.d.mts → index-C2dLNT6S.d.mts} +169 -14
- package/dist/index-C2dLNT6S.d.mts.map +1 -0
- package/dist/{index-DR56od45.d.mts → index-ZDEwR7qW.d.mts} +3 -3
- package/dist/{index-DR56od45.d.mts.map → index-ZDEwR7qW.d.mts.map} +1 -1
- package/dist/index.d.mts +18 -17
- package/dist/index.mjs +63 -59
- package/dist/init-lock-6b309ZrF.mjs +56 -0
- package/dist/init-lock-6b309ZrF.mjs.map +1 -0
- package/dist/{load-BBetCvLC.mjs → load-Dtoo7KcJ.mjs} +2 -2
- package/dist/{load-BBetCvLC.mjs.map → load-Dtoo7KcJ.mjs.map} +1 -1
- package/dist/{loader-ZN1ll-d-.mjs → loader-C8Z48Uof.mjs} +4 -4
- package/dist/{loader-ZN1ll-d-.mjs.map → loader-C8Z48Uof.mjs.map} +1 -1
- package/dist/{manifest-schema-BtwbL_vj.mjs → manifest-schema-DDSbwkAL.mjs} +1 -1
- package/dist/{manifest-schema-BtwbL_vj.mjs.map → manifest-schema-DDSbwkAL.mjs.map} +1 -1
- package/dist/media/image-endpoint.d.mts +74 -0
- package/dist/media/image-endpoint.d.mts.map +1 -0
- package/dist/media/image-endpoint.mjs +162 -0
- package/dist/media/image-endpoint.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +11 -11
- package/dist/media/local-runtime.mjs +9 -7
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-JOf3pNkw.mjs → media-Bw0sA6rb.mjs} +2 -2
- package/dist/{media-JOf3pNkw.mjs.map → media-Bw0sA6rb.mjs.map} +1 -1
- package/dist/{media-allowlist-Dknq-OFY.mjs → media-allowlist-DunzrKFM.mjs} +2 -2
- package/dist/{media-allowlist-Dknq-OFY.mjs.map → media-allowlist-DunzrKFM.mjs.map} +1 -1
- package/dist/{media-url-VClf8glU.mjs → media-url-S22B6aPr.mjs} +1 -1
- package/dist/{media-url-VClf8glU.mjs.map → media-url-S22B6aPr.mjs.map} +1 -1
- package/dist/{menus-DX4_E01q.mjs → menus-CYs0WZoL.mjs} +20 -6
- package/dist/menus-CYs0WZoL.mjs.map +1 -0
- package/dist/{menus-DrQLusqj.mjs → menus-DOs1MQJg.mjs} +120 -20
- package/dist/menus-DOs1MQJg.mjs.map +1 -0
- package/dist/{mime-CCEzze7W.mjs → mime-DYpsOAny.mjs} +1 -1
- package/dist/{mime-CCEzze7W.mjs.map → mime-DYpsOAny.mjs.map} +1 -1
- package/dist/{mode-CO2vQHfq.mjs → mode-CFh8Dw8G.mjs} +1 -1
- package/dist/{mode-CO2vQHfq.mjs.map → mode-CFh8Dw8G.mjs.map} +1 -1
- package/dist/{normalize-CK5o04zr.mjs → normalize-Uam4_Vkr.mjs} +1 -1
- package/dist/{normalize-CK5o04zr.mjs.map → normalize-Uam4_Vkr.mjs.map} +1 -1
- package/dist/{oauth-authorization-Bw4NdF_S.mjs → oauth-authorization-BN-t83Uy.mjs} +5 -5
- package/dist/{oauth-authorization-Bw4NdF_S.mjs.map → oauth-authorization-BN-t83Uy.mjs.map} +1 -1
- package/dist/{oauth-clients-BGGFp57s.mjs → oauth-clients-R6I_V0qz.mjs} +1 -1
- package/dist/{oauth-clients-BGGFp57s.mjs.map → oauth-clients-R6I_V0qz.mjs.map} +1 -1
- package/dist/{oauth-state-store-97x0xtN2.mjs → oauth-state-store-Csoc6kkR.mjs} +1 -1
- package/dist/{oauth-state-store-97x0xtN2.mjs.map → oauth-state-store-Csoc6kkR.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-B_vnZHKO.mjs → oauth-user-lookup-d7VYjTpx.mjs} +1 -1
- package/dist/{oauth-user-lookup-B_vnZHKO.mjs.map → oauth-user-lookup-d7VYjTpx.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +15 -0
- package/dist/object-cache/memory.d.mts.map +1 -0
- package/dist/object-cache/memory.mjs +56 -0
- package/dist/object-cache/memory.mjs.map +1 -0
- package/dist/object-cache-SEb2IM4Z.mjs +373 -0
- package/dist/object-cache-SEb2IM4Z.mjs.map +1 -0
- package/dist/{options-DyYIYpPd.d.mts → options-DFFpvNJU.d.mts} +3 -3
- package/dist/{options-DyYIYpPd.d.mts.map → options-DFFpvNJU.d.mts.map} +1 -1
- package/dist/{options-BPCVnesz.mjs → options-DTTML-Tx.mjs} +1 -1
- package/dist/{options-BPCVnesz.mjs.map → options-DTTML-Tx.mjs.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-CrGndy1A.mjs → parse-qrHlnzTy.mjs} +2 -2
- package/dist/{parse-CrGndy1A.mjs.map → parse-qrHlnzTy.mjs.map} +1 -1
- package/dist/{passkey-config-C3QgnQnU.mjs → passkey-config-BJTbcnI5.mjs} +1 -1
- package/dist/{passkey-config-C3QgnQnU.mjs.map → passkey-config-BJTbcnI5.mjs.map} +1 -1
- package/dist/{patterns-p-RBdTbM.mjs → patterns-BKmjvM7K.mjs} +1 -1
- package/dist/{patterns-p-RBdTbM.mjs.map → patterns-BKmjvM7K.mjs.map} +1 -1
- package/dist/{placeholder-BZxr8W1j.mjs → placeholder-CIDCpyEY.mjs} +1 -1
- package/dist/{placeholder-BZxr8W1j.mjs.map → placeholder-CIDCpyEY.mjs.map} +1 -1
- package/dist/{placeholder-CVBv5z8k.d.mts → placeholder-CirPauNG.d.mts} +1 -1
- package/dist/{placeholder-CVBv5z8k.d.mts.map → placeholder-CirPauNG.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugin-utils.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.mjs +4 -2
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/{transport-CmpLD7W3.mjs → portable-text-BIFhrU6T.mjs} +2 -135
- package/dist/portable-text-BIFhrU6T.mjs.map +1 -0
- package/dist/{preview-BfuRkVKW.mjs → preview-IDye9SPQ.mjs} +2 -2
- package/dist/{preview-BfuRkVKW.mjs.map → preview-IDye9SPQ.mjs.map} +1 -1
- package/dist/{public-url-BFVC2OTJ.mjs → public-url-8lFyQ8ZF.mjs} +1 -1
- package/dist/{public-url-BFVC2OTJ.mjs.map → public-url-8lFyQ8ZF.mjs.map} +1 -1
- package/dist/{query-CbUcI4Xk.mjs → query-B1RVFUNM.mjs} +159 -31
- package/dist/query-B1RVFUNM.mjs.map +1 -0
- package/dist/{rate-limit-C7hjdkS5.mjs → rate-limit-DfNAqIWW.mjs} +2 -2
- package/dist/{rate-limit-C7hjdkS5.mjs.map → rate-limit-DfNAqIWW.mjs.map} +1 -1
- package/dist/{redirect-B_q19j4v.mjs → redirect-B4wuX2A5.mjs} +1 -1
- package/dist/{redirect-B_q19j4v.mjs.map → redirect-B4wuX2A5.mjs.map} +1 -1
- package/dist/{redirect-CRWIt8Zj.mjs → redirect-Bifv_yHv.mjs} +3 -3
- package/dist/{redirect-CRWIt8Zj.mjs.map → redirect-Bifv_yHv.mjs.map} +1 -1
- package/dist/{redirects-DxVoR7PI.mjs → redirects-CT_vb3NV.mjs} +24 -18
- package/dist/redirects-CT_vb3NV.mjs.map +1 -0
- package/dist/{redirects-CCbCqCCd.mjs → redirects-DUvXgzCX.mjs} +14 -10
- package/dist/redirects-DUvXgzCX.mjs.map +1 -0
- package/dist/{registry-brYh-rAT.mjs → registry-CjK96fHD.mjs} +6 -6
- package/dist/{registry-brYh-rAT.mjs.map → registry-CjK96fHD.mjs.map} +1 -1
- package/dist/{request-cache-D32LpnmI.mjs → request-cache-KCNHp_RJ.mjs} +1 -1
- package/dist/{request-cache-D32LpnmI.mjs.map → request-cache-KCNHp_RJ.mjs.map} +1 -1
- package/dist/{request-meta-7ByVLxB-.mjs → request-meta-ei3ATilC.mjs} +2 -2
- package/dist/{request-meta-7ByVLxB-.mjs.map → request-meta-ei3ATilC.mjs.map} +1 -1
- package/dist/{resolve-BqYMVG0D.mjs → resolve-CpbBglV0.mjs} +1 -1
- package/dist/{resolve-BqYMVG0D.mjs.map → resolve-CpbBglV0.mjs.map} +1 -1
- package/dist/{runner--4wMWwKM.mjs → runner-DYYnW530.mjs} +201 -170
- package/dist/runner-DYYnW530.mjs.map +1 -0
- package/dist/{runner-DTdhuI9i.d.mts → runner-jdXtFEd3.d.mts} +2 -2
- package/dist/{runner-DTdhuI9i.d.mts.map → runner-jdXtFEd3.d.mts.map} +1 -1
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +3 -3
- package/dist/{schema-C1E70ug_.mjs → schema-5z2Jfnbm.mjs} +13 -8
- package/dist/schema-5z2Jfnbm.mjs.map +1 -0
- package/dist/{search-B3SGZw91.mjs → search-D9FkoM-k.mjs} +4 -4
- package/dist/{search-B3SGZw91.mjs.map → search-D9FkoM-k.mjs.map} +1 -1
- package/dist/{secrets-ChPTmy9x.mjs → secrets-BUE5UQys.mjs} +23 -13
- package/dist/secrets-BUE5UQys.mjs.map +1 -0
- package/dist/{sections-D_lVzwRZ.mjs → sections-DWYZo6HK.mjs} +3 -3
- package/dist/{sections-D_lVzwRZ.mjs.map → sections-DWYZo6HK.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +22 -20
- package/dist/seo/index.d.mts +1 -1
- package/dist/seo/index.mjs +1 -1
- package/dist/{seo-B5e6y9Wk.mjs → seo-Cu47j3mJ.mjs} +5 -2
- package/dist/seo-Cu47j3mJ.mjs.map +1 -0
- package/dist/{seo-D_LPkOtu.mjs → seo-DRnqnstF.mjs} +1 -1
- package/dist/{seo-D_LPkOtu.mjs.map → seo-DRnqnstF.mjs.map} +1 -1
- package/dist/{service-ChDcsTBs.mjs → service-DTmtqCnw.mjs} +3 -3
- package/dist/{service-ChDcsTBs.mjs.map → service-DTmtqCnw.mjs.map} +1 -1
- package/dist/session-user-DmtPMNa1.mjs +51 -0
- package/dist/session-user-DmtPMNa1.mjs.map +1 -0
- package/dist/{settings-Cv47v9u8.mjs → settings-DUrVDN0c.mjs} +3 -3
- package/dist/{settings-Cv47v9u8.mjs.map → settings-DUrVDN0c.mjs.map} +1 -1
- package/dist/settings-yaxu9mU-.mjs +245 -0
- package/dist/settings-yaxu9mU-.mjs.map +1 -0
- package/dist/{setup-complete-yvPE4OsP.mjs → setup-complete-BWFHzgvZ.mjs} +2 -2
- package/dist/{setup-complete-yvPE4OsP.mjs.map → setup-complete-BWFHzgvZ.mjs.map} +1 -1
- package/dist/{setup-nonce-C9aFzb94.mjs → setup-nonce-DFWG-J5c.mjs} +1 -1
- package/dist/{setup-nonce-C9aFzb94.mjs.map → setup-nonce-DFWG-J5c.mjs.map} +1 -1
- package/dist/single-flight-cache-B5p5cNOL.mjs +104 -0
- package/dist/single-flight-cache-B5p5cNOL.mjs.map +1 -0
- package/dist/{site-url-CnHlmAs9.mjs → site-url-BOTPgmeM.mjs} +2 -2
- package/dist/{site-url-CnHlmAs9.mjs.map → site-url-BOTPgmeM.mjs.map} +1 -1
- package/dist/{slugify-Cjh1ssOZ.mjs → slugify-Cce3dTdg.mjs} +1 -1
- package/dist/{slugify-Cjh1ssOZ.mjs.map → slugify-Cce3dTdg.mjs.map} +1 -1
- package/dist/{ssrf-BsVGIE0Z.mjs → ssrf-B0VeRLrp.mjs} +1 -1
- package/dist/{ssrf-BsVGIE0Z.mjs.map → ssrf-B0VeRLrp.mjs.map} +1 -1
- package/dist/status-CB2basWJ.mjs +30 -0
- package/dist/status-CB2basWJ.mjs.map +1 -0
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +2 -2
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/{taxonomies-BdAmbOwx.mjs → taxonomies-Be9B1jEj.mjs} +156 -122
- package/dist/taxonomies-Be9B1jEj.mjs.map +1 -0
- package/dist/{taxonomies-BILwiyGk.mjs → taxonomies-CJmkEpdS.mjs} +7 -7
- package/dist/{taxonomies-BILwiyGk.mjs.map → taxonomies-CJmkEpdS.mjs.map} +1 -1
- package/dist/{taxonomy-CdllE4oq.mjs → taxonomy-B2HQuVf5.mjs} +19 -6
- package/dist/taxonomy-B2HQuVf5.mjs.map +1 -0
- package/dist/{tokens-Bx2afeT-.mjs → tokens-BvrJvIB6.mjs} +2 -2
- package/dist/{tokens-Bx2afeT-.mjs.map → tokens-BvrJvIB6.mjs.map} +1 -1
- package/dist/{transaction-x2tJQ-A1.mjs → transaction-qfqpPVpu.mjs} +1 -1
- package/dist/{transaction-x2tJQ-A1.mjs.map → transaction-qfqpPVpu.mjs.map} +1 -1
- package/dist/transport-B4rXnSTf.mjs +135 -0
- package/dist/transport-B4rXnSTf.mjs.map +1 -0
- package/dist/{transport-B7PPP2CC.d.mts → transport-k7YjfmEn.d.mts} +1 -1
- package/dist/{transport-B7PPP2CC.d.mts.map → transport-k7YjfmEn.d.mts.map} +1 -1
- package/dist/{trusted-proxy-B4AfnoAp.mjs → trusted-proxy-DY1_UqHr.mjs} +1 -1
- package/dist/{trusted-proxy-B4AfnoAp.mjs.map → trusted-proxy-DY1_UqHr.mjs.map} +1 -1
- package/dist/{types-CPAPl93j.d.mts → types-CIKX2HO5.d.mts} +2 -2
- package/dist/{types-CPAPl93j.d.mts.map → types-CIKX2HO5.d.mts.map} +1 -1
- package/dist/{types-D4kUqbHh.d.mts → types-CKNXt63n.d.mts} +1 -1
- package/dist/{types-D4kUqbHh.d.mts.map → types-CKNXt63n.d.mts.map} +1 -1
- package/dist/{types-DTniiNto.d.mts → types-CWGYDYqF.d.mts} +2 -2
- package/dist/{types-DTniiNto.d.mts.map → types-CWGYDYqF.d.mts.map} +1 -1
- package/dist/{types-BH8-30hc.d.mts → types-CgvhU-hF.d.mts} +1 -1
- package/dist/{types-BH8-30hc.d.mts.map → types-CgvhU-hF.d.mts.map} +1 -1
- package/dist/{types-BFgrqwSk.d.mts → types-CmivgZbp.d.mts} +1 -1
- package/dist/{types-BFgrqwSk.d.mts.map → types-CmivgZbp.d.mts.map} +1 -1
- package/dist/{types-BPzXTV9x.d.mts → types-Czg1S3gB.d.mts} +9 -1
- package/dist/{types-BPzXTV9x.d.mts.map → types-Czg1S3gB.d.mts.map} +1 -1
- package/dist/types-DCNNfeCv.d.mts +124 -0
- package/dist/types-DCNNfeCv.d.mts.map +1 -0
- package/dist/{types-BUUVn1zr.d.mts → types-DPCpkzvS.d.mts} +1 -1
- package/dist/{types-BUUVn1zr.d.mts.map → types-DPCpkzvS.d.mts.map} +1 -1
- package/dist/{types-S15DXXNi.d.mts → types-DXLVzV2w.d.mts} +1 -1
- package/dist/{types-S15DXXNi.d.mts.map → types-DXLVzV2w.d.mts.map} +1 -1
- package/dist/{types-BXSUSAjt.mjs → types-DXOIbece.mjs} +3 -3
- package/dist/{types-BXSUSAjt.mjs.map → types-DXOIbece.mjs.map} +1 -1
- package/dist/{types-DpFmlNyB.mjs → types-DYF2_Vf4.mjs} +1 -1
- package/dist/{types-DpFmlNyB.mjs.map → types-DYF2_Vf4.mjs.map} +1 -1
- package/dist/{types-DZk_y-MU.mjs → types-tM44hEcf.mjs} +1 -1
- package/dist/{types-DZk_y-MU.mjs.map → types-tM44hEcf.mjs.map} +1 -1
- package/dist/{user-C0um7wrg.mjs → user-Db-Rti_z.mjs} +3 -3
- package/dist/{user-C0um7wrg.mjs.map → user-Db-Rti_z.mjs.map} +1 -1
- package/dist/{utils-C4Ih4DML.mjs → utils-LbHcSRTj.mjs} +2 -2
- package/dist/{utils-C4Ih4DML.mjs.map → utils-LbHcSRTj.mjs.map} +1 -1
- package/dist/{validate-Bz4vqcX1.mjs → validate-Bwl64sxv.mjs} +3 -3
- package/dist/{validate-Bz4vqcX1.mjs.map → validate-Bwl64sxv.mjs.map} +1 -1
- package/dist/{validate-CNwkPWzz.d.mts → validate-CE2M0nvx.d.mts} +5 -5
- package/dist/{validate-CNwkPWzz.d.mts.map → validate-CE2M0nvx.d.mts.map} +1 -1
- package/dist/{validation-DgGTJm3u.mjs → validation-C_yOvFaO.mjs} +6 -6
- package/dist/{validation-DgGTJm3u.mjs.map → validation-C_yOvFaO.mjs.map} +1 -1
- package/dist/version-RnYXYjzD.mjs +7 -0
- package/dist/{version-D-5txk2m.mjs.map → version-RnYXYjzD.mjs.map} +1 -1
- package/dist/{widgets-DZfmAbE4.mjs → widgets-8GONuRHo.mjs} +4 -4
- package/dist/{widgets-DZfmAbE4.mjs.map → widgets-8GONuRHo.mjs.map} +1 -1
- package/dist/{zod-generator-Djo_VHCt.mjs → zod-generator-D481JjzD.mjs} +3 -3
- package/dist/{zod-generator-Djo_VHCt.mjs.map → zod-generator-D481JjzD.mjs.map} +1 -1
- package/package.json +18 -6
- package/src/api/handlers/api-tokens.ts +19 -0
- package/src/api/handlers/comment-reactions.ts +165 -0
- package/src/api/handlers/redirects.ts +24 -13
- package/src/api/handlers/schema.ts +8 -0
- package/src/api/schemas/comments.ts +10 -0
- package/src/api/schemas/redirects.ts +11 -4
- package/src/astro/image-endpoint.ts +84 -0
- package/src/astro/index.ts +6 -0
- package/src/astro/integration/index.ts +127 -30
- package/src/astro/integration/routes.ts +51 -9
- package/src/astro/integration/runtime.ts +65 -1
- package/src/astro/integration/virtual-modules.ts +32 -0
- package/src/astro/integration/vite-config.ts +16 -0
- package/src/astro/middleware/auth.ts +4 -3
- package/src/astro/middleware/redirect.ts +12 -0
- package/src/astro/middleware/stream-end-metrics.ts +11 -1
- package/src/astro/middleware.ts +41 -3
- package/src/astro/object-cache/adapters.ts +50 -0
- package/src/astro/prefetch.ts +77 -0
- package/src/astro/routes/api/comments/[collection]/[contentId]/reactions.ts +97 -0
- package/src/astro/routes/api/setup/dev-bypass.ts +5 -1
- package/src/astro/routes/api/snapshot.ts +3 -1
- package/src/astro/session-user.ts +57 -0
- package/src/astro/types.ts +1 -0
- package/src/bylines/field-defs-cache.ts +70 -20
- package/src/cli/commands/doctor.ts +1 -1
- package/src/comments/query.ts +78 -7
- package/src/comments/ranking.ts +58 -0
- package/src/components/Comments.astro +136 -1
- package/src/config/secrets.ts +28 -14
- package/src/database/instrumentation.ts +21 -1
- package/src/database/migrations/044_comment_reactions.ts +56 -0
- package/src/database/migrations/runner.ts +2 -0
- package/src/database/repositories/byline.ts +13 -0
- package/src/database/repositories/comment-reaction.ts +132 -0
- package/src/database/repositories/comment.ts +10 -0
- package/src/database/repositories/content.ts +25 -3
- package/src/database/repositories/menu.ts +13 -1
- package/src/database/repositories/seo.ts +3 -0
- package/src/database/repositories/taxonomy.ts +13 -1
- package/src/database/types.ts +9 -0
- package/src/emdash-runtime.ts +23 -9
- package/src/index.ts +22 -0
- package/src/mcp/server.ts +307 -20
- package/src/media/image-endpoint.ts +167 -0
- package/src/menus/index.ts +11 -4
- package/src/object-cache/codec.ts +73 -0
- package/src/object-cache/index.ts +495 -0
- package/src/object-cache/memory.ts +91 -0
- package/src/object-cache/types.ts +124 -0
- package/src/plugins/adapt-sandbox-entry.ts +11 -1
- package/src/query.ts +196 -17
- package/src/redirects/status.ts +27 -0
- package/src/schema/query.ts +11 -4
- package/src/settings/index.ts +30 -17
- package/src/taxonomies/index.ts +237 -165
- package/src/utils/{isolate-cache.ts → single-flight-cache.ts} +26 -21
- package/src/virtual-modules.d.ts +11 -0
- package/dist/api-DStv36ik.mjs.map +0 -1
- package/dist/api-tokens-DPfhPu5V.mjs.map +0 -1
- package/dist/byline-DUx48sJp.mjs.map +0 -1
- package/dist/byline-fields-DbibsvTl.d.mts.map +0 -1
- package/dist/comment-sqQxNpN3.mjs.map +0 -1
- package/dist/content-BIlVx-RX.mjs.map +0 -1
- package/dist/index-B1keaX5Y.d.mts.map +0 -1
- package/dist/menus-DX4_E01q.mjs.map +0 -1
- package/dist/menus-DrQLusqj.mjs.map +0 -1
- package/dist/query-CbUcI4Xk.mjs.map +0 -1
- package/dist/redirects-CCbCqCCd.mjs.map +0 -1
- package/dist/redirects-DxVoR7PI.mjs.map +0 -1
- package/dist/runner--4wMWwKM.mjs.map +0 -1
- package/dist/schema-C1E70ug_.mjs.map +0 -1
- package/dist/secrets-ChPTmy9x.mjs.map +0 -1
- package/dist/seo-B5e6y9Wk.mjs.map +0 -1
- package/dist/settings-DfxiWY_s.mjs +0 -411
- package/dist/settings-DfxiWY_s.mjs.map +0 -1
- package/dist/taxonomies-BdAmbOwx.mjs.map +0 -1
- package/dist/taxonomy-CdllE4oq.mjs.map +0 -1
- package/dist/transport-CmpLD7W3.mjs.map +0 -1
- package/dist/version-D-5txk2m.mjs +0 -7
- /package/dist/{api-tokens-Oq39ba-Z.mjs → api-tokens-BVH-H8Z9.mjs} +0 -0
- /package/dist/{ssrf-BvgVcfNQ.mjs → ssrf-Cz1e2QPn.mjs} +0 -0
- /package/dist/{types-CZI4E3qG.mjs → types-Bfr2Pj6z.mjs} +0 -0
package/src/astro/middleware.ts
CHANGED
|
@@ -60,7 +60,9 @@ import { isMissingTableError } from "../utils/db-errors.js";
|
|
|
60
60
|
import { createInitLock, type InitLock, initWithLock } from "../utils/init-lock.js";
|
|
61
61
|
import type { EmDashConfig } from "./integration/runtime.js";
|
|
62
62
|
import { wrapBodyForStreamMetrics } from "./middleware/stream-end-metrics.js";
|
|
63
|
+
import { prefetchLayoutData } from "./prefetch.js";
|
|
63
64
|
import { createPublicPluginApiRouteHandler } from "./public-plugin-api-routes.js";
|
|
65
|
+
import { resolveSessionUser } from "./session-user.js";
|
|
64
66
|
import type { EmDashHandlers } from "./types.js";
|
|
65
67
|
|
|
66
68
|
/**
|
|
@@ -415,7 +417,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
415
417
|
// turns normal traffic into a flood of KV read misses. See #733.
|
|
416
418
|
const hasSessionCookie = cookies.get("astro-session") !== undefined;
|
|
417
419
|
const sessionUser =
|
|
418
|
-
context.isPrerendered || !hasSessionCookie ? null : await context.session
|
|
420
|
+
context.isPrerendered || !hasSessionCookie ? null : await resolveSessionUser(context.session);
|
|
419
421
|
|
|
420
422
|
if (!isEmDashRoute && !isPublicRuntimeRoute && !hasEditCookie && !hasPreviewToken) {
|
|
421
423
|
if (!sessionUser && !playgroundDb) {
|
|
@@ -428,7 +430,13 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
428
430
|
// Do a one-time lightweight probe using the same getDb() instance the
|
|
429
431
|
// page will use: if the migrations table doesn't exist, no migrations
|
|
430
432
|
// have ever run -- redirect to the setup wizard.
|
|
431
|
-
|
|
433
|
+
// Skip the probe when prerendering: a prerendered route is built to
|
|
434
|
+
// static HTML, so returning context.redirect("/_emdash/admin/setup")
|
|
435
|
+
// below would bake that redirect into the page and ship it to
|
|
436
|
+
// production. The build database is legitimately empty in CI and there
|
|
437
|
+
// is no live visitor to send to the wizard at build time (session reads
|
|
438
|
+
// are already skipped for prerender above for the same reason).
|
|
439
|
+
if (!isSetupVerified() && !context.isPrerendered) {
|
|
432
440
|
const t0 = performance.now();
|
|
433
441
|
try {
|
|
434
442
|
const { getDb } = await import("../loader.js");
|
|
@@ -475,6 +483,10 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
475
483
|
collectPageMetadata: runtime.collectPageMetadata.bind(runtime),
|
|
476
484
|
collectPageFragments: runtime.collectPageFragments.bind(runtime),
|
|
477
485
|
getPublicMediaUrl: createPublicMediaUrlResolver(runtime.storage),
|
|
486
|
+
// Exposed so the wrapped image endpoint (`/_image`) can read media
|
|
487
|
+
// bytes from storage on the anonymous fast path -- public `<img>`
|
|
488
|
+
// requests carry no session.
|
|
489
|
+
storage: runtime.storage,
|
|
478
490
|
} as EmDashHandlers;
|
|
479
491
|
} catch {
|
|
480
492
|
// Non-fatal — EmDashHead will fall back to base SEO contributions
|
|
@@ -512,7 +524,28 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
512
524
|
const ctx = parent
|
|
513
525
|
? { ...parent, db: anonScoped.db }
|
|
514
526
|
: { editMode: false, db: anonScoped.db, metrics };
|
|
527
|
+
// Eagerly warm site-global layout data (menus, widget areas,
|
|
528
|
+
// taxonomy terms, settings) concurrently so the layout's
|
|
529
|
+
// per-component reads overlap into ~one wall-clock round trip and
|
|
530
|
+
// hit a warm cache instead of serializing. Three guards:
|
|
531
|
+
// - request-scoped (remote) backend only -- this branch implies it;
|
|
532
|
+
// pointless on synchronous local SQLite.
|
|
533
|
+
// - HTML navigations only -- feeds/sitemaps/JSON don't render the
|
|
534
|
+
// layout, so prefetching their chrome is pure waste.
|
|
535
|
+
// - via after(): it runs immediately (still warms the render) but
|
|
536
|
+
// hands the promise to waitUntil, so the surplus warm-up (chrome a
|
|
537
|
+
// given page doesn't render) is kept alive past the response rather
|
|
538
|
+
// than erroring on workerd as orphaned request I/O.
|
|
539
|
+
// Gate on the CLIENT'S PREFERRED type (leading media range), not a
|
|
540
|
+
// substring -- browser navigations lead with `text/html`, while feed
|
|
541
|
+
// readers lead with `application/rss+xml` etc. and only list
|
|
542
|
+
// `text/html;q=0.8` later, so a substring match would leak onto feeds.
|
|
543
|
+
const acceptsHtml = (request.headers.get("accept") ?? "")
|
|
544
|
+
.split(",", 1)[0]!
|
|
545
|
+
.trim()
|
|
546
|
+
.startsWith("text/html");
|
|
515
547
|
return runWithContext(ctx, async () => {
|
|
548
|
+
if (acceptsHtml) after(() => prefetchLayoutData());
|
|
516
549
|
// commit() in finally: the write reached the primary independently
|
|
517
550
|
// of render, so the bookmark cookie must be persisted even if
|
|
518
551
|
// render throws -- otherwise a write-then-failed-render leaves the
|
|
@@ -723,7 +756,12 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
723
756
|
try {
|
|
724
757
|
return await runWithContext({ editMode: false, queryRecorder, metrics }, run);
|
|
725
758
|
} finally {
|
|
726
|
-
|
|
759
|
+
// Streamed responses defer the flush to stream end (see
|
|
760
|
+
// wrapBodyForStreamMetrics) so the log captures queries issued while
|
|
761
|
+
// the body renders. Only flush here for responses that were not
|
|
762
|
+
// wrapped (no body: redirects, 304s, bodyless errors), where all
|
|
763
|
+
// queries have already run by the time middleware returns.
|
|
764
|
+
if (queryRecorder && !queryRecorder.deferredFlush) flushRecorder(queryRecorder);
|
|
727
765
|
}
|
|
728
766
|
});
|
|
729
767
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object-cache adapter functions (config time).
|
|
3
|
+
*
|
|
4
|
+
* These run in `astro.config.mjs` and return serializable
|
|
5
|
+
* {@link ObjectCacheDescriptor}s. The backend is instantiated at runtime by
|
|
6
|
+
* loading the descriptor's `entrypoint`.
|
|
7
|
+
*
|
|
8
|
+
* For Cloudflare KV, use `kvCache()` from `@emdash-cms/cloudflare`.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* // astro.config.mjs (Node / local)
|
|
13
|
+
* import emdash, { memoryCache } from "emdash/astro";
|
|
14
|
+
*
|
|
15
|
+
* export default defineConfig({
|
|
16
|
+
* integrations: [emdash({ objectCache: memoryCache() })],
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type { ObjectCacheDescriptor, ObjectCacheRuntimeConfig } from "../../object-cache/types.js";
|
|
22
|
+
|
|
23
|
+
/** Options for {@link memoryCache}. */
|
|
24
|
+
export interface MemoryCacheOptions extends ObjectCacheRuntimeConfig {
|
|
25
|
+
/**
|
|
26
|
+
* Soft cap on the number of cached keys per isolate before FIFO eviction.
|
|
27
|
+
* @default 1000
|
|
28
|
+
*/
|
|
29
|
+
maxEntries?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* In-isolate memory object cache.
|
|
34
|
+
*
|
|
35
|
+
* Caches query results across requests within a single isolate/process. On
|
|
36
|
+
* Node (one long-lived process) this is a genuine cross-request cache; on
|
|
37
|
+
* multi-isolate platforms (Cloudflare) prefer `kvCache()` so the cache is
|
|
38
|
+
* shared. Useful for local development regardless of target.
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* emdash({ objectCache: memoryCache({ defaultTtl: 600 }) })
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function memoryCache(options: MemoryCacheOptions = {}): ObjectCacheDescriptor {
|
|
46
|
+
return {
|
|
47
|
+
entrypoint: "emdash/object-cache/memory",
|
|
48
|
+
config: { ...options },
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eager, transparent prefetch of site-global "chrome" data.
|
|
3
|
+
*
|
|
4
|
+
* On a public page render, the shared layout pulls the same site-global data on
|
|
5
|
+
* every request -- menus, widget areas, taxonomy term lists, site settings --
|
|
6
|
+
* but each is awaited inside a separately-rendered Astro component, so they
|
|
7
|
+
* execute as serial DB round trips. This fires them all CONCURRENTLY at the
|
|
8
|
+
* very start of the request, before `next()`:
|
|
9
|
+
*
|
|
10
|
+
* - On remote backends (D1, Durable Objects) the round trips overlap instead
|
|
11
|
+
* of serializing, collapsing ~N sequential RTTs into ~1 wall-clock RTT. On
|
|
12
|
+
* a coalescing backend they additionally batch into a single round trip.
|
|
13
|
+
* - The results land in the per-request `requestCached` store under the exact
|
|
14
|
+
* keys the layout helpers use, so when the components render they hit a warm
|
|
15
|
+
* (in-flight or resolved) cache entry instead of issuing their own query.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here changes what templates call -- it warms the real helpers, so the
|
|
18
|
+
* cache keys and value shapes are guaranteed identical. The caller gates this to
|
|
19
|
+
* the public-page path on a request-scoped (remote) backend; it is a no-op-ish
|
|
20
|
+
* waste on synchronous local SQLite, so don't call it there.
|
|
21
|
+
*
|
|
22
|
+
* Fire-and-forget: never awaited by middleware, never throws (a prefetch failure
|
|
23
|
+
* must not affect the request -- the helpers will simply run on demand).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { getDb } from "../loader.js";
|
|
27
|
+
import { getMenu } from "../menus/index.js";
|
|
28
|
+
import { setRequestCacheEntry } from "../request-cache.js";
|
|
29
|
+
import { getSiteSettings } from "../settings/index.js";
|
|
30
|
+
import { getTaxonomyDefs, getTaxonomyTerms } from "../taxonomies/index.js";
|
|
31
|
+
import { getWidgetAreas } from "../widgets/index.js";
|
|
32
|
+
|
|
33
|
+
/** Warm widget areas: one bulk load, primed under each per-area cache key. */
|
|
34
|
+
async function prefetchWidgetAreas(): Promise<void> {
|
|
35
|
+
const areas = await getWidgetAreas();
|
|
36
|
+
// getWidgetArea(name) caches under `widget-area:${name}` and returns the same
|
|
37
|
+
// WidgetArea shape getWidgetAreas yields, so priming here makes those calls hit.
|
|
38
|
+
for (const area of areas) {
|
|
39
|
+
setRequestCacheEntry(`widget-area:${area.name}`, area);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Warm every taxonomy's term list via the real helper (primes per-name keys). */
|
|
44
|
+
async function prefetchTaxonomyTerms(): Promise<void> {
|
|
45
|
+
const defs = await getTaxonomyDefs();
|
|
46
|
+
await Promise.allSettled(defs.map((def) => getTaxonomyTerms(def.name)));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Warm every menu via the real helper (primes `menu:${name}:${locale}`). */
|
|
50
|
+
async function prefetchMenus(): Promise<void> {
|
|
51
|
+
const db = await getDb();
|
|
52
|
+
// The layout calls getMenu(name) with hardcoded names; we can't know them, so
|
|
53
|
+
// discover every menu name and warm them all (small, bounded chrome table).
|
|
54
|
+
const rows = await db.selectFrom("_emdash_menus").select("name").distinct().execute();
|
|
55
|
+
const names = [...new Set(rows.map((r) => r.name))];
|
|
56
|
+
await Promise.allSettled(names.map((name) => getMenu(name)));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Concurrently warm the site-global layout data for the current request.
|
|
61
|
+
* Safe to call only inside the request ALS frame that owns the (remote)
|
|
62
|
+
* request-scoped db. Never throws.
|
|
63
|
+
*/
|
|
64
|
+
export async function prefetchLayoutData(): Promise<void> {
|
|
65
|
+
try {
|
|
66
|
+
await Promise.allSettled([
|
|
67
|
+
getSiteSettings(),
|
|
68
|
+
prefetchMenus(),
|
|
69
|
+
prefetchWidgetAreas(),
|
|
70
|
+
prefetchTaxonomyTerms(),
|
|
71
|
+
]);
|
|
72
|
+
} catch (error) {
|
|
73
|
+
// Defensive: Promise.allSettled shouldn't reject, but never let a prefetch
|
|
74
|
+
// failure surface to the request.
|
|
75
|
+
console.error("[emdash] layout prefetch failed (non-fatal):", error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public comment reaction endpoints (Tier 1 of the best-in-class comments RFC).
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/comments/:collection/:contentId/reactions
|
|
5
|
+
* - Aggregate reaction counts for the content's approved comments, plus the
|
|
6
|
+
* current visitor's active reactions.
|
|
7
|
+
* POST /_emdash/api/comments/:collection/:contentId/reactions
|
|
8
|
+
* - Toggle a reaction on a comment. Public, honeypot- and rate-limit-gated.
|
|
9
|
+
*
|
|
10
|
+
* Inherits the `/_emdash/api/comments/` public prefix (no auth); the POST still
|
|
11
|
+
* requires the `X-EmDash-Request: 1` CSRF header like the comment POST.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { APIRoute } from "astro";
|
|
15
|
+
|
|
16
|
+
import { apiError, apiSuccess, handleError, requireDb, unwrapResult } from "#api/error.js";
|
|
17
|
+
import { handleReactionCounts, handleReactionToggle } from "#api/handlers/comment-reactions.js";
|
|
18
|
+
import { hashIp } from "#api/handlers/comments.js";
|
|
19
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
20
|
+
import { createReactionBody } from "#api/schemas.js";
|
|
21
|
+
import { resolveSecretsCached } from "#config/secrets.js";
|
|
22
|
+
import { extractRequestMeta } from "#plugins/request-meta.js";
|
|
23
|
+
|
|
24
|
+
export const prerender = false;
|
|
25
|
+
|
|
26
|
+
export const GET: APIRoute = async ({ params, request, locals }) => {
|
|
27
|
+
const { emdash } = locals;
|
|
28
|
+
const { collection, contentId } = params;
|
|
29
|
+
|
|
30
|
+
if (!collection || !contentId) {
|
|
31
|
+
return apiError("VALIDATION_ERROR", "Collection and content ID required", 400);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const dbErr = requireDb(emdash?.db);
|
|
35
|
+
if (dbErr) return dbErr;
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// Salted voter hash from request IP (same primitive as comment ip_hash).
|
|
39
|
+
// Behind Cloudflare (CF-Connecting-IP) or a configured trusted proxy this
|
|
40
|
+
// is per-visitor. Without a trusted IP it collapses to a shared "unknown"
|
|
41
|
+
// bucket, so reaction dedup degrades for those visitors — a real
|
|
42
|
+
// per-visitor token is Tier 2 (visitor identity). Operators should set
|
|
43
|
+
// trustedProxyHeaders; see the comment ingest route for the same note.
|
|
44
|
+
const meta = extractRequestMeta(request, emdash.config);
|
|
45
|
+
let voterHash = "unknown";
|
|
46
|
+
if (meta.ip) {
|
|
47
|
+
const { ipSalt } = await resolveSecretsCached(emdash.db);
|
|
48
|
+
voterHash = await hashIp(meta.ip, ipSalt);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const result = await handleReactionCounts(emdash.db, collection, contentId, voterHash);
|
|
52
|
+
return unwrapResult(result);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return handleError(error, "Failed to read reactions", "REACTION_COUNTS_ERROR");
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const POST: APIRoute = async ({ params, request, locals }) => {
|
|
59
|
+
const { emdash } = locals;
|
|
60
|
+
const { collection, contentId } = params;
|
|
61
|
+
|
|
62
|
+
if (!collection || !contentId) {
|
|
63
|
+
return apiError("VALIDATION_ERROR", "Collection and content ID required", 400);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const dbErr = requireDb(emdash?.db);
|
|
67
|
+
if (dbErr) return dbErr;
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const body = await parseBody(request, createReactionBody);
|
|
71
|
+
if (isParseError(body)) return body;
|
|
72
|
+
|
|
73
|
+
// Anti-spam: honeypot — hidden field filled only by bots. Silently accept.
|
|
74
|
+
if (body.website_url) {
|
|
75
|
+
return apiSuccess({ reacted: false, counts: {} });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const meta = extractRequestMeta(request, emdash.config);
|
|
79
|
+
let voterHash = "unknown";
|
|
80
|
+
if (meta.ip) {
|
|
81
|
+
const { ipSalt } = await resolveSecretsCached(emdash.db);
|
|
82
|
+
voterHash = await hashIp(meta.ip, ipSalt);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const result = await handleReactionToggle(emdash.db, {
|
|
86
|
+
collection,
|
|
87
|
+
contentId,
|
|
88
|
+
commentId: body.commentId,
|
|
89
|
+
reaction: body.reaction,
|
|
90
|
+
voterHash,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
return unwrapResult(result, 200);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
return handleError(error, "Failed to toggle reaction", "REACTION_TOGGLE_ERROR");
|
|
96
|
+
}
|
|
97
|
+
};
|
|
@@ -23,7 +23,7 @@ import { ulid } from "ulidx";
|
|
|
23
23
|
|
|
24
24
|
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
25
25
|
import { escapeHtml } from "#api/escape.js";
|
|
26
|
-
import { handleApiTokenCreate } from "#api/handlers/api-tokens.js";
|
|
26
|
+
import { deleteApiTokensByName, handleApiTokenCreate } from "#api/handlers/api-tokens.js";
|
|
27
27
|
import { getPublicOrigin } from "#api/public-url.js";
|
|
28
28
|
import { isSafeRedirect } from "#api/redirect.js";
|
|
29
29
|
import { runMigrations } from "#db/migrations/runner.js";
|
|
@@ -134,6 +134,10 @@ async function handleDevBypass(context: Parameters<APIRoute>[0]): Promise<Respon
|
|
|
134
134
|
// Optionally create a PAT token (?token=1) for headless/CLI testing.
|
|
135
135
|
let token: string | undefined;
|
|
136
136
|
if (url.searchParams.has("token")) {
|
|
137
|
+
// Idempotent by name: a prior reset can leave a stale dev-bypass-token,
|
|
138
|
+
// and the raw token is only available at creation, so drop any existing
|
|
139
|
+
// one and mint a fresh, usable PAT rather than accumulating duplicates.
|
|
140
|
+
await deleteApiTokensByName(emdash.db, user.id, "dev-bypass-token");
|
|
137
141
|
const result = await handleApiTokenCreate(emdash.db, user.id, {
|
|
138
142
|
name: "dev-bypass-token",
|
|
139
143
|
scopes: [
|
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
import { getPublicOrigin } from "#api/public-url.js";
|
|
21
21
|
import { resolveSecretsCached } from "#config/secrets.js";
|
|
22
22
|
|
|
23
|
+
import { resolveSessionUser } from "../../session-user.js";
|
|
24
|
+
|
|
23
25
|
export const prerender = false;
|
|
24
26
|
|
|
25
27
|
export const GET: APIRoute = async ({ request, locals, url, session }) => {
|
|
@@ -31,7 +33,7 @@ export const GET: APIRoute = async ({ request, locals, url, session }) => {
|
|
|
31
33
|
if (!user && session && emdash?.db) {
|
|
32
34
|
try {
|
|
33
35
|
const { createKyselyAdapter } = await import("@emdash-cms/auth/adapters/kysely");
|
|
34
|
-
const sessionUser = await session
|
|
36
|
+
const sessionUser = await resolveSessionUser(session);
|
|
35
37
|
if (sessionUser?.id) {
|
|
36
38
|
const adapter = createKyselyAdapter(emdash.db);
|
|
37
39
|
const resolved = await adapter.getUserById(sessionUser.id);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { after } from "../after.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Backstop timeout for resolving the session user. A live session-store read
|
|
5
|
+
* settles in a few ms, so this only ever fires on a genuinely stalled read.
|
|
6
|
+
*/
|
|
7
|
+
export const SESSION_GET_TIMEOUT_MS = 3_000;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the Astro session user without risking an isolate-wide hang.
|
|
11
|
+
*
|
|
12
|
+
* On Cloudflare Workers, a request cancelled mid-`session.get()` (client
|
|
13
|
+
* disconnect, context teardown) can leave the underlying session-store read as
|
|
14
|
+
* a promise that never settles — neither resolving nor rejecting. Awaiting it
|
|
15
|
+
* directly hangs the request, and because the stalled promise is shared at the
|
|
16
|
+
* isolate level, every later session-bearing request hangs too (observed as
|
|
17
|
+
* 0-CPU, multi-minute, `canceled` responses; see #1274). A surrounding
|
|
18
|
+
* try/catch cannot help: the promise never rejects.
|
|
19
|
+
*
|
|
20
|
+
* Two layers, mirroring the reclaimable-cache pattern used elsewhere in core:
|
|
21
|
+
* 1. `after()` anchors the read so a cancelled request still drives it to
|
|
22
|
+
* completion — the promise settles and the isolate is not poisoned for
|
|
23
|
+
* subsequent requests (prevents the hang rather than merely surviving it).
|
|
24
|
+
* 2. A timeout is a fail-closed backstop: a still-stalled (or rejecting) read
|
|
25
|
+
* resolves to `undefined`, and every caller treats the absence of a session
|
|
26
|
+
* user as unauthenticated (anonymous on public routes, 401/redirect on
|
|
27
|
+
* protected ones). It can only ever drop privileges for that one request,
|
|
28
|
+
* never grant them.
|
|
29
|
+
*
|
|
30
|
+
* Used by every session read on the request path: the main middleware (the
|
|
31
|
+
* first read on a session-bearing request), the auth middleware, and the
|
|
32
|
+
* preview-snapshot route (which bypasses the auth middleware).
|
|
33
|
+
*/
|
|
34
|
+
export async function resolveSessionUser<T>(
|
|
35
|
+
session: { get(key: "user"): Promise<T> } | undefined,
|
|
36
|
+
timeoutMs = SESSION_GET_TIMEOUT_MS,
|
|
37
|
+
): Promise<T | undefined> {
|
|
38
|
+
if (!session) return undefined;
|
|
39
|
+
const read: Promise<T | undefined> = Promise.resolve(session.get("user")).catch(() => undefined);
|
|
40
|
+
// Keep the worker alive past response/cancellation so the read completes and
|
|
41
|
+
// the shared promise settles — this is what prevents the isolate poisoning.
|
|
42
|
+
after(() =>
|
|
43
|
+
read.then(
|
|
44
|
+
() => undefined,
|
|
45
|
+
() => undefined,
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
49
|
+
const timeout = new Promise<undefined>((resolve) => {
|
|
50
|
+
timer = setTimeout(resolve, timeoutMs, undefined);
|
|
51
|
+
});
|
|
52
|
+
try {
|
|
53
|
+
return await Promise.race([read, timeout]);
|
|
54
|
+
} finally {
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/astro/types.ts
CHANGED
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
* but are read on every byline hydration (admin pages, content rendering,
|
|
9
9
|
* API responses). Caching at the isolate level drops the SELECT-from-
|
|
10
10
|
* `_emdash_byline_fields` from once-per-hydration to once-per-isolate-
|
|
11
|
-
* after-bump. The cache holds
|
|
12
|
-
*
|
|
11
|
+
* after-bump. The cache holds the resolved *value* behind a reclaimable
|
|
12
|
+
* single-flight lock (see `utils/single-flight-cache.ts`), never an
|
|
13
|
+
* in-flight promise: concurrent cold-isolate readers coalesce onto one
|
|
14
|
+
* query by polling the published value, so a reader whose request is
|
|
15
|
+
* cancelled mid-query can never strand later byline hydrations on the
|
|
16
|
+
* isolate (the workerd never-settling-promise hazard that produced 524s).
|
|
13
17
|
*
|
|
14
18
|
* Stored on globalThis under `Symbol.for("emdash:byline-field-defs")` so
|
|
15
19
|
* Vite SSR chunk duplication can't produce two independent caches (same
|
|
@@ -50,17 +54,23 @@
|
|
|
50
54
|
|
|
51
55
|
import type { Kysely } from "kysely";
|
|
52
56
|
|
|
57
|
+
import { after } from "../after.js";
|
|
53
58
|
import type { Database } from "../database/types.js";
|
|
54
59
|
import { requestCached } from "../request-cache.js";
|
|
55
60
|
import { getRequestContext } from "../request-context.js";
|
|
56
61
|
import { BylineSchemaRegistry } from "../schema/byline-registry.js";
|
|
57
62
|
import type { BylineFieldDefinition } from "../schema/types.js";
|
|
63
|
+
import { createInitLock, type InitLock, initWithLock } from "../utils/init-lock.js";
|
|
58
64
|
|
|
59
65
|
interface FieldDefsHolder {
|
|
60
|
-
/**
|
|
61
|
-
|
|
62
|
-
/**
|
|
66
|
+
/** Last resolved defs, valid only when `hasValue` is true. */
|
|
67
|
+
value: BylineFieldDefinition[] | null;
|
|
68
|
+
/** Presence flag, separate from `value` so an empty-array result still caches. */
|
|
69
|
+
hasValue: boolean;
|
|
70
|
+
/** Persisted-version value that `value` was fetched against. */
|
|
63
71
|
cachedVersion: number;
|
|
72
|
+
/** Reclaimable single-flight lock so a cancelled owner can't wedge readers. */
|
|
73
|
+
lock: InitLock;
|
|
64
74
|
}
|
|
65
75
|
|
|
66
76
|
const HOLDER_KEY = Symbol.for("emdash:byline-field-defs");
|
|
@@ -69,7 +79,12 @@ const holder: FieldDefsHolder =
|
|
|
69
79
|
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-cache.ts)
|
|
70
80
|
(g[HOLDER_KEY] as FieldDefsHolder | undefined) ??
|
|
71
81
|
(() => {
|
|
72
|
-
const h: FieldDefsHolder = {
|
|
82
|
+
const h: FieldDefsHolder = {
|
|
83
|
+
value: null,
|
|
84
|
+
hasValue: false,
|
|
85
|
+
cachedVersion: -1,
|
|
86
|
+
lock: createInitLock(),
|
|
87
|
+
};
|
|
73
88
|
g[HOLDER_KEY] = h;
|
|
74
89
|
return h;
|
|
75
90
|
})();
|
|
@@ -77,6 +92,16 @@ const holder: FieldDefsHolder =
|
|
|
77
92
|
const REQUEST_CACHE_KEY_VERSION = "byline-fields-version";
|
|
78
93
|
const REQUEST_CACHE_KEY_DEFS_PREFIX = "byline-field-defs:";
|
|
79
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Reclaim window for the single-flight lock: if an owner holds it past
|
|
97
|
+
* this without publishing (e.g. its request was cancelled and the
|
|
98
|
+
* anchored fetch hasn't completed yet), the next reader reclaims and
|
|
99
|
+
* refetches. `listFields` is a single fast SELECT, so this only needs to
|
|
100
|
+
* cover a genuinely slow/stranded query. Mutable solely so tests can
|
|
101
|
+
* shorten it; production never changes it.
|
|
102
|
+
*/
|
|
103
|
+
let reclaimDeadlineMs = 10_000;
|
|
104
|
+
|
|
80
105
|
/**
|
|
81
106
|
* Read the persisted `options.byline_fields_version` counter. Cached for
|
|
82
107
|
* the duration of the current request via `requestCached`. Returns `0`
|
|
@@ -107,19 +132,29 @@ export async function getBylineFieldDefs(db: Kysely<Database>): Promise<BylineFi
|
|
|
107
132
|
if (isolated || dirty) {
|
|
108
133
|
return new BylineSchemaRegistry(db).listFields();
|
|
109
134
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
// Per-isolate single-flight cache keyed on the persisted version.
|
|
136
|
+
// Coalesce concurrent cold readers via the lock and read the
|
|
137
|
+
// published value; never await another request's in-flight promise
|
|
138
|
+
// (a cancelled owner would otherwise strand every later byline
|
|
139
|
+
// hydration on the isolate). The fetch is anchored so a cancelled
|
|
140
|
+
// originator still drives it to completion and populates the cache.
|
|
141
|
+
return initWithLock<BylineFieldDefinition[]>(
|
|
142
|
+
holder.lock,
|
|
143
|
+
() => (holder.hasValue && holder.cachedVersion === version ? holder.value : null),
|
|
144
|
+
(isCurrentClaim) =>
|
|
145
|
+
(async () => {
|
|
146
|
+
const defs = await new BylineSchemaRegistry(db).listFields();
|
|
147
|
+
// Publish only while still the current claim, and never
|
|
148
|
+
// regress over a newer version a concurrent reader stored.
|
|
149
|
+
if (isCurrentClaim() && version >= holder.cachedVersion) {
|
|
150
|
+
holder.value = defs;
|
|
151
|
+
holder.hasValue = true;
|
|
152
|
+
holder.cachedVersion = version;
|
|
153
|
+
}
|
|
154
|
+
return defs;
|
|
155
|
+
})(),
|
|
156
|
+
{ deadlineMs: reclaimDeadlineMs, anchor: (promise) => after(() => promise) },
|
|
157
|
+
);
|
|
123
158
|
});
|
|
124
159
|
}
|
|
125
160
|
|
|
@@ -133,6 +168,21 @@ export async function getBylineFieldDefs(db: Kysely<Database>): Promise<BylineFi
|
|
|
133
168
|
* coordination that lets other isolates see the change.
|
|
134
169
|
*/
|
|
135
170
|
export function resetBylineFieldDefsCacheForTests(): void {
|
|
136
|
-
holder.
|
|
171
|
+
holder.value = null;
|
|
172
|
+
holder.hasValue = false;
|
|
137
173
|
holder.cachedVersion = -1;
|
|
174
|
+
holder.lock.ownerStartedAt = null;
|
|
175
|
+
holder.lock.generation = 0;
|
|
176
|
+
reclaimDeadlineMs = 10_000;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Test-only: shorten the single-flight reclaim window so a "stranded
|
|
181
|
+
* owner" scenario can be exercised without waiting out the production
|
|
182
|
+
* deadline. Reset by `resetBylineFieldDefsCacheForTests`.
|
|
183
|
+
*
|
|
184
|
+
* @internal
|
|
185
|
+
*/
|
|
186
|
+
export function setBylineFieldDefsReclaimDeadlineForTests(ms: number): void {
|
|
187
|
+
reclaimDeadlineMs = ms;
|
|
138
188
|
}
|
|
@@ -124,7 +124,7 @@ async function checkDatabase(dbPath: string): Promise<CheckResult[]> {
|
|
|
124
124
|
try {
|
|
125
125
|
const usersResult = await sql<{
|
|
126
126
|
count: number;
|
|
127
|
-
}>`SELECT COUNT(id) as count FROM
|
|
127
|
+
}>`SELECT COUNT(id) as count FROM users`.execute(db);
|
|
128
128
|
const count = usersResult.rows[0]?.count ?? 0;
|
|
129
129
|
results.push({
|
|
130
130
|
name: "users",
|