emdash 0.22.0 → 0.24.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-DAAjOID4.d.mts} +1 -1
- package/dist/{adapters-hUy8vOB-.d.mts.map → adapters-DAAjOID4.d.mts.map} +1 -1
- package/dist/{allowed-origins-DjlhyfNN.mjs → allowed-origins-D5FxMUo8.mjs} +2 -2
- package/dist/{allowed-origins-DjlhyfNN.mjs.map → allowed-origins-D5FxMUo8.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +15 -15
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/api/schemas/index.mjs +3 -3
- package/dist/{api-BDuM4bEy.mjs → api-d_0wi9fW.mjs} +20 -20
- package/dist/{api-BDuM4bEy.mjs.map → api-d_0wi9fW.mjs.map} +1 -1
- package/dist/{api-tokens-ViYKeIp9.mjs → api-tokens-D6ppjIVi.mjs} +2 -2
- package/dist/{api-tokens-ViYKeIp9.mjs.map → api-tokens-D6ppjIVi.mjs.map} +1 -1
- package/dist/{apply-wDqQoxX4.mjs → apply-BE9UaWX0.mjs} +17 -17
- package/dist/{apply-wDqQoxX4.mjs.map → apply-BE9UaWX0.mjs.map} +1 -1
- package/dist/astro/index.d.mts +11 -11
- package/dist/astro/index.mjs +36 -11
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +9 -9
- package/dist/astro/middleware/auth.mjs +7 -7
- package/dist/astro/middleware/redirect.mjs +5 -5
- package/dist/astro/middleware/request-context.d.mts.map +1 -1
- package/dist/astro/middleware/request-context.mjs +5 -3
- 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 +362 -141
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -8
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -8
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -8
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +13 -12
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +13 -12
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +13 -12
- package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +11 -11
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +9 -9
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +35 -34
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +35 -34
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +34 -33
- 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 +34 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +34 -33
- 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 +35 -34
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +35 -34
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +34 -33
- 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 +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +34 -33
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
- package/dist/astro/routes/api/admin/users/index.mjs +6 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +10 -10
- package/dist/astro/routes/api/auth/invite/index.mjs +7 -7
- package/dist/astro/routes/api/auth/invite/register-options.mjs +9 -9
- package/dist/astro/routes/api/auth/logout.mjs +3 -3
- package/dist/astro/routes/api/auth/magic-link/send.mjs +9 -9
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/me.mjs +7 -7
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +9 -9
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +10 -10
- package/dist/astro/routes/api/auth/passkey/verify.mjs +10 -10
- package/dist/astro/routes/api/auth/signup/complete.mjs +10 -10
- package/dist/astro/routes/api/auth/signup/request.mjs +9 -9
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +12 -12
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +10 -10
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +12 -12
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/index.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- package/dist/astro/routes/api/dev/emails.mjs +3 -3
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
- package/dist/astro/routes/api/import/wordpress/execute.mjs +10 -9
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +13 -12
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/mcp.mjs +39 -39
- package/dist/astro/routes/api/media/_id_/confirm.mjs +7 -7
- package/dist/astro/routes/api/media/_id_.mjs +7 -7
- package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
- package/dist/astro/routes/api/media/providers/index.mjs +3 -3
- package/dist/astro/routes/api/media/upload-url.mjs +9 -9
- package/dist/astro/routes/api/media.mjs +12 -12
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/items.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/translations.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_.mjs +8 -8
- package/dist/astro/routes/api/menus/index.mjs +8 -8
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +9 -9
- package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
- package/dist/astro/routes/api/oauth/register.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
- package/dist/astro/routes/api/oauth/token.mjs +6 -6
- package/dist/astro/routes/api/openapi.json.mjs +4 -4
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
- package/dist/astro/routes/api/redirects/404s/index.mjs +9 -9
- package/dist/astro/routes/api/redirects/404s/summary.mjs +9 -9
- package/dist/astro/routes/api/redirects/_id_.mjs +10 -10
- package/dist/astro/routes/api/redirects/index.mjs +10 -10
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +34 -33
- 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 +34 -33
- 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 +34 -33
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +8 -7
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +34 -33
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +34 -33
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +10 -10
- package/dist/astro/routes/api/search/index.mjs +9 -9
- package/dist/astro/routes/api/search/rebuild.mjs +10 -10
- package/dist/astro/routes/api/search/stats.mjs +6 -6
- package/dist/astro/routes/api/search/suggest.mjs +9 -9
- package/dist/astro/routes/api/sections/_slug_.mjs +9 -9
- package/dist/astro/routes/api/sections/index.mjs +9 -9
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +11 -11
- package/dist/astro/routes/api/setup/admin-verify.mjs +11 -11
- package/dist/astro/routes/api/setup/admin.mjs +10 -10
- package/dist/astro/routes/api/setup/dev-bypass.mjs +23 -22
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +24 -23
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +4 -4
- package/dist/astro/routes/api/snapshot.mjs +6 -6
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +12 -12
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +12 -12
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +12 -12
- package/dist/astro/routes/api/taxonomies/index.mjs +12 -12
- package/dist/astro/routes/api/themes/preview.mjs +5 -5
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/well-known/auth.mjs +1 -1
- 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 +7 -7
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +9 -9
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +9 -9
- package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/index.mjs +9 -9
- package/dist/astro/routes/api/widget-components.mjs +3 -3
- package/dist/astro/routes/robots.txt.mjs +5 -5
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +8 -8
- package/dist/astro/routes/sitemap.xml.mjs +6 -6
- package/dist/astro/types.d.mts +12 -12
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{authorize-C0EYoUeV.mjs → authorize-B__u-iZJ.mjs} +2 -2
- package/dist/{authorize-C0EYoUeV.mjs.map → authorize-B__u-iZJ.mjs.map} +1 -1
- package/dist/{byline-CC0WS4Gu.mjs → byline-C-YajfV7.mjs} +18 -76
- package/dist/byline-C-YajfV7.mjs.map +1 -0
- package/dist/{byline-fields-53i9Et0x.mjs → byline-fields-B-KXkg5R.mjs} +2 -2
- package/dist/{byline-fields-53i9Et0x.mjs.map → byline-fields-B-KXkg5R.mjs.map} +1 -1
- package/dist/{byline-fields-DNp0HNKc.mjs → byline-fields-DaMKzkhO.mjs} +1 -1
- package/dist/{byline-fields-DNp0HNKc.mjs.map → byline-fields-DaMKzkhO.mjs.map} +1 -1
- package/dist/{byline-fields-jy07PZJM.d.mts → byline-fields-RFPkDLRw.d.mts} +21 -1
- package/dist/byline-fields-RFPkDLRw.d.mts.map +1 -0
- package/dist/{bylines-CCO1CYnH.mjs → bylines-BMtJnPnG.mjs} +7 -7
- package/dist/{bylines-CCO1CYnH.mjs.map → bylines-BMtJnPnG.mjs.map} +1 -1
- package/dist/{bylines-DGekMGGm.mjs → bylines-D4KADDAi.mjs} +4 -4
- package/dist/{bylines-DGekMGGm.mjs.map → bylines-D4KADDAi.mjs.map} +1 -1
- package/dist/{cache-pXTpun6s.mjs → cache-BUJe2w6Z.mjs} +2 -2
- package/dist/{cache-pXTpun6s.mjs.map → cache-BUJe2w6Z.mjs.map} +1 -1
- package/dist/{challenge-store-C6E_kWTs.mjs → challenge-store-LhiqMccz.mjs} +1 -1
- package/dist/{challenge-store-C6E_kWTs.mjs.map → challenge-store-LhiqMccz.mjs.map} +1 -1
- package/dist/{chunks-SyjZaYwV.mjs → chunks-BHgcHh2C.mjs} +2 -2
- package/dist/{chunks-SyjZaYwV.mjs.map → chunks-BHgcHh2C.mjs.map} +1 -1
- package/dist/cli/index.mjs +25 -24
- 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 -2
- package/dist/{comment-80UyJJUR.mjs → comment-BDx50EX5.mjs} +2 -2
- package/dist/{comment-80UyJJUR.mjs.map → comment-BDx50EX5.mjs.map} +1 -1
- package/dist/{comment-reaction-B6AdcpXw.mjs → comment-reaction-Gv_pgfI3.mjs} +2 -2
- package/dist/{comment-reaction-B6AdcpXw.mjs.map → comment-reaction-Gv_pgfI3.mjs.map} +1 -1
- package/dist/{comments-CtPkT2tp.mjs → comments-CXHuQ6jI.mjs} +3 -3
- package/dist/{comments-CtPkT2tp.mjs.map → comments-CXHuQ6jI.mjs.map} +1 -1
- package/dist/{components-D6ZnrzbB.mjs → components-CYt4uVK9.mjs} +1 -1
- package/dist/{components-D6ZnrzbB.mjs.map → components-CYt4uVK9.mjs.map} +1 -1
- package/dist/{content-2PTDNnoh.mjs → content-PoVGKjp0.mjs} +3 -3
- package/dist/{content-2PTDNnoh.mjs.map → content-PoVGKjp0.mjs.map} +1 -1
- package/dist/{context-f1__jpzF.mjs → context-Dvws41_A.mjs} +62 -24
- package/dist/context-Dvws41_A.mjs.map +1 -0
- package/dist/{cron-CQPxBjYs.mjs → cron-C5LVoNmP.mjs} +14 -2
- package/dist/cron-C5LVoNmP.mjs.map +1 -0
- package/dist/{dashboard-BOESNcwE.mjs → dashboard-DsYU8JKS.mjs} +4 -4
- package/dist/{dashboard-BOESNcwE.mjs.map → dashboard-DsYU8JKS.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-CrC5w3Jz.mjs → db-errors-UXB1CK42.mjs} +1 -1
- package/dist/{db-errors-CrC5w3Jz.mjs.map → db-errors-UXB1CK42.mjs.map} +1 -1
- package/dist/{default-CpBEPn6a.mjs → default-CeRG-Ot4.mjs} +1 -1
- package/dist/{default-CpBEPn6a.mjs.map → default-CeRG-Ot4.mjs.map} +1 -1
- package/dist/{device-flow-Bn-qiDrw.mjs → device-flow-DENDCQ9F.mjs} +4 -4
- package/dist/{device-flow-Bn-qiDrw.mjs.map → device-flow-DENDCQ9F.mjs.map} +1 -1
- package/dist/{email-console-B9VS6eN4.mjs → email-console-DJP32ucW.mjs} +1 -1
- package/dist/{email-console-B9VS6eN4.mjs.map → email-console-DJP32ucW.mjs.map} +1 -1
- package/dist/{error-BQ1pxs0L.mjs → error-lq_fL-RS.mjs} +2 -2
- package/dist/{error-BQ1pxs0L.mjs.map → error-lq_fL-RS.mjs.map} +1 -1
- package/dist/{escape-BtbJWyaW.mjs → escape-Bjio4ZsM.mjs} +1 -1
- package/dist/{escape-BtbJWyaW.mjs.map → escape-Bjio4ZsM.mjs.map} +1 -1
- package/dist/field-defs-cache-CYYx8xlG.mjs +77 -0
- package/dist/field-defs-cache-CYYx8xlG.mjs.map +1 -0
- package/dist/{fts-manager-DtiWqwNJ.mjs → fts-manager-DW_NR-Fs.mjs} +2 -2
- package/dist/{fts-manager-DtiWqwNJ.mjs.map → fts-manager-DW_NR-Fs.mjs.map} +1 -1
- package/dist/{hash-BowcuPwv.mjs → hash-DrvzIXcz.mjs} +1 -1
- package/dist/{hash-BowcuPwv.mjs.map → hash-DrvzIXcz.mjs.map} +1 -1
- package/dist/{import-DqSGOlmR.mjs → import-Bb1T9WJS.mjs} +3 -3
- package/dist/{import-DqSGOlmR.mjs.map → import-Bb1T9WJS.mjs.map} +1 -1
- package/dist/{index-C2dLNT6S.d.mts → index-BroXT-vD.d.mts} +136 -38
- package/dist/index-BroXT-vD.d.mts.map +1 -0
- package/dist/{index-ZDEwR7qW.d.mts → index-qbL02uhs.d.mts} +3 -3
- package/dist/{index-ZDEwR7qW.d.mts.map → index-qbL02uhs.d.mts.map} +1 -1
- package/dist/index.d.mts +17 -17
- package/dist/index.mjs +55 -54
- package/dist/{load-Dtoo7KcJ.mjs → load-DMFi4n1p.mjs} +2 -2
- package/dist/{load-Dtoo7KcJ.mjs.map → load-DMFi4n1p.mjs.map} +1 -1
- package/dist/{loader-C8Z48Uof.mjs → loader-BR2SgfEc.mjs} +77 -12
- package/dist/loader-BR2SgfEc.mjs.map +1 -0
- package/dist/{manifest-schema-DDSbwkAL.mjs → manifest-schema-BWKnQYQF.mjs} +1 -1
- package/dist/{manifest-schema-DDSbwkAL.mjs.map → manifest-schema-BWKnQYQF.mjs.map} +1 -1
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +19 -11
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +11 -9
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-Bw0sA6rb.mjs → media-CTjJoJTh.mjs} +2 -2
- package/dist/{media-Bw0sA6rb.mjs.map → media-CTjJoJTh.mjs.map} +1 -1
- package/dist/{media-allowlist-DunzrKFM.mjs → media-allowlist-B77I5_bw.mjs} +2 -2
- package/dist/{media-allowlist-DunzrKFM.mjs.map → media-allowlist-B77I5_bw.mjs.map} +1 -1
- package/dist/{media-url-S22B6aPr.mjs → media-url-O4rm9-SQ.mjs} +1 -1
- package/dist/{media-url-S22B6aPr.mjs.map → media-url-O4rm9-SQ.mjs.map} +1 -1
- package/dist/{menus-CYs0WZoL.mjs → menus-8O6xNcYW.mjs} +2 -2
- package/dist/{menus-CYs0WZoL.mjs.map → menus-8O6xNcYW.mjs.map} +1 -1
- package/dist/{menus-DOs1MQJg.mjs → menus-GvRSpgIA.mjs} +57 -14
- package/dist/menus-GvRSpgIA.mjs.map +1 -0
- package/dist/{mime-DYpsOAny.mjs → mime-BTzvzJ8M.mjs} +1 -1
- package/dist/{mime-DYpsOAny.mjs.map → mime-BTzvzJ8M.mjs.map} +1 -1
- package/dist/{mode-CFh8Dw8G.mjs → mode-BB0F8xTC.mjs} +1 -1
- package/dist/{mode-CFh8Dw8G.mjs.map → mode-BB0F8xTC.mjs.map} +1 -1
- package/dist/{normalize-Uam4_Vkr.mjs → normalize-ClbNIenm.mjs} +1 -1
- package/dist/{normalize-Uam4_Vkr.mjs.map → normalize-ClbNIenm.mjs.map} +1 -1
- package/dist/{oauth-authorization-BN-t83Uy.mjs → oauth-authorization-CsvzIp_F.mjs} +4 -4
- package/dist/{oauth-authorization-BN-t83Uy.mjs.map → oauth-authorization-CsvzIp_F.mjs.map} +1 -1
- package/dist/{oauth-clients-R6I_V0qz.mjs → oauth-clients-C9SYwEbZ.mjs} +1 -1
- package/dist/{oauth-clients-R6I_V0qz.mjs.map → oauth-clients-C9SYwEbZ.mjs.map} +1 -1
- package/dist/{oauth-state-store-Csoc6kkR.mjs → oauth-state-store---zrApfB.mjs} +1 -1
- package/dist/{oauth-state-store-Csoc6kkR.mjs.map → oauth-state-store---zrApfB.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-d7VYjTpx.mjs → oauth-user-lookup-SHsWRlG9.mjs} +1 -1
- package/dist/{oauth-user-lookup-d7VYjTpx.mjs.map → oauth-user-lookup-SHsWRlG9.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{options-DFFpvNJU.d.mts → options-CqECG0gM.d.mts} +3 -3
- package/dist/{options-DFFpvNJU.d.mts.map → options-CqECG0gM.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-qrHlnzTy.mjs → parse-DHI873qU.mjs} +2 -2
- package/dist/{parse-qrHlnzTy.mjs.map → parse-DHI873qU.mjs.map} +1 -1
- package/dist/{passkey-config-BJTbcnI5.mjs → passkey-config-C0YfSBko.mjs} +1 -1
- package/dist/{passkey-config-BJTbcnI5.mjs.map → passkey-config-C0YfSBko.mjs.map} +1 -1
- package/dist/{placeholder-CIDCpyEY.mjs → placeholder-B0s2mWu5.mjs} +1 -1
- package/dist/{placeholder-CIDCpyEY.mjs.map → placeholder-B0s2mWu5.mjs.map} +1 -1
- package/dist/{placeholder-CirPauNG.d.mts → placeholder-QoI4gEzP.d.mts} +1 -1
- package/dist/{placeholder-CirPauNG.d.mts.map → placeholder-QoI4gEzP.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 +2 -2
- package/dist/{portable-text-BIFhrU6T.mjs → portable-text-BICg8bTk.mjs} +1 -1
- package/dist/{portable-text-BIFhrU6T.mjs.map → portable-text-BICg8bTk.mjs.map} +1 -1
- package/dist/{preview-IDye9SPQ.mjs → preview-DKGCt2_p.mjs} +2 -2
- package/dist/{preview-IDye9SPQ.mjs.map → preview-DKGCt2_p.mjs.map} +1 -1
- package/dist/{public-url-8lFyQ8ZF.mjs → public-url-CTVqgMmg.mjs} +1 -1
- package/dist/{public-url-8lFyQ8ZF.mjs.map → public-url-CTVqgMmg.mjs.map} +1 -1
- package/dist/{query-B1RVFUNM.mjs → query-DZdlS6Cu.mjs} +92 -14
- package/dist/query-DZdlS6Cu.mjs.map +1 -0
- package/dist/{rate-limit-DfNAqIWW.mjs → rate-limit-D1Y6VFVP.mjs} +2 -2
- package/dist/{rate-limit-DfNAqIWW.mjs.map → rate-limit-D1Y6VFVP.mjs.map} +1 -1
- package/dist/{redirect-Bifv_yHv.mjs → redirect-C1KVGYWe.mjs} +2 -2
- package/dist/{redirect-Bifv_yHv.mjs.map → redirect-C1KVGYWe.mjs.map} +1 -1
- package/dist/{redirect-B4wuX2A5.mjs → redirect-CS-PHtNh.mjs} +1 -1
- package/dist/{redirect-B4wuX2A5.mjs.map → redirect-CS-PHtNh.mjs.map} +1 -1
- package/dist/{redirects-CT_vb3NV.mjs → redirects-DgnypVir.mjs} +4 -4
- package/dist/{redirects-CT_vb3NV.mjs.map → redirects-DgnypVir.mjs.map} +1 -1
- package/dist/{redirects-DUvXgzCX.mjs → redirects-x9eFPeyi.mjs} +4 -2
- package/dist/redirects-x9eFPeyi.mjs.map +1 -0
- package/dist/{registry-CjK96fHD.mjs → registry-CJkCubOJ.mjs} +4 -4
- package/dist/{registry-CjK96fHD.mjs.map → registry-CJkCubOJ.mjs.map} +1 -1
- package/dist/{request-meta-ei3ATilC.mjs → request-meta-CmS1tDFf.mjs} +2 -2
- package/dist/{request-meta-ei3ATilC.mjs.map → request-meta-CmS1tDFf.mjs.map} +1 -1
- package/dist/{resolve-CpbBglV0.mjs → resolve-C7I0qiR0.mjs} +1 -1
- package/dist/{resolve-CpbBglV0.mjs.map → resolve-C7I0qiR0.mjs.map} +1 -1
- package/dist/{runner-DYYnW530.mjs → runner-BsquExlK.mjs} +246 -174
- package/dist/runner-BsquExlK.mjs.map +1 -0
- package/dist/{runner-jdXtFEd3.d.mts → runner-CEtq-6Sm.d.mts} +2 -2
- package/dist/{runner-jdXtFEd3.d.mts.map → runner-CEtq-6Sm.d.mts.map} +1 -1
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +2 -2
- package/dist/{schema-5z2Jfnbm.mjs → schema-DMjXuvNU.mjs} +4 -4
- package/dist/{schema-5z2Jfnbm.mjs.map → schema-DMjXuvNU.mjs.map} +1 -1
- package/dist/{search-D9FkoM-k.mjs → search-D1wKk3lc.mjs} +4 -4
- package/dist/{search-D9FkoM-k.mjs.map → search-D1wKk3lc.mjs.map} +1 -1
- package/dist/{secrets-BUE5UQys.mjs → secrets-BSf9pRRY.mjs} +2 -2
- package/dist/{secrets-BUE5UQys.mjs.map → secrets-BSf9pRRY.mjs.map} +1 -1
- package/dist/{sections-DWYZo6HK.mjs → sections-CCMic8dB.mjs} +3 -3
- package/dist/{sections-DWYZo6HK.mjs.map → sections-CCMic8dB.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +17 -16
- package/dist/seo/index.d.mts +1 -1
- package/dist/seo/index.mjs +1 -1
- package/dist/{seo-Cu47j3mJ.mjs → seo-3QrZ1EPT.mjs} +2 -2
- package/dist/{seo-Cu47j3mJ.mjs.map → seo-3QrZ1EPT.mjs.map} +1 -1
- package/dist/{seo-DRnqnstF.mjs → seo-DCEF-AVr.mjs} +1 -1
- package/dist/{seo-DRnqnstF.mjs.map → seo-DCEF-AVr.mjs.map} +1 -1
- package/dist/{service-DTmtqCnw.mjs → service-CQHK_10l.mjs} +3 -3
- package/dist/{service-DTmtqCnw.mjs.map → service-CQHK_10l.mjs.map} +1 -1
- package/dist/{session-user-DmtPMNa1.mjs → session-user-B8aLtKAH.mjs} +1 -1
- package/dist/{session-user-DmtPMNa1.mjs.map → session-user-B8aLtKAH.mjs.map} +1 -1
- package/dist/{settings-DUrVDN0c.mjs → settings-C3Yi5Co3.mjs} +3 -3
- package/dist/{settings-DUrVDN0c.mjs.map → settings-C3Yi5Co3.mjs.map} +1 -1
- package/dist/{settings-yaxu9mU-.mjs → settings-D9rvaLuY.mjs} +4 -4
- package/dist/{settings-yaxu9mU-.mjs.map → settings-D9rvaLuY.mjs.map} +1 -1
- package/dist/{setup-complete-BWFHzgvZ.mjs → setup-complete-gEiySUc-.mjs} +1 -1
- package/dist/{setup-complete-BWFHzgvZ.mjs.map → setup-complete-gEiySUc-.mjs.map} +1 -1
- package/dist/{setup-nonce-DFWG-J5c.mjs → setup-nonce-DzS50zme.mjs} +1 -1
- package/dist/{setup-nonce-DFWG-J5c.mjs.map → setup-nonce-DzS50zme.mjs.map} +1 -1
- package/dist/{single-flight-cache-B5p5cNOL.mjs → single-flight-cache-Cdfkic3t.mjs} +1 -1
- package/dist/{single-flight-cache-B5p5cNOL.mjs.map → single-flight-cache-Cdfkic3t.mjs.map} +1 -1
- package/dist/{site-url-BOTPgmeM.mjs → site-url-BLebyON8.mjs} +1 -1
- package/dist/{site-url-BOTPgmeM.mjs.map → site-url-BLebyON8.mjs.map} +1 -1
- package/dist/{ssrf-B0VeRLrp.mjs → ssrf-BRKb343l.mjs} +1 -1
- package/dist/{ssrf-B0VeRLrp.mjs.map → ssrf-BRKb343l.mjs.map} +1 -1
- package/dist/{status-CB2basWJ.mjs → status-vUK0SA17.mjs} +1 -1
- package/dist/{status-CB2basWJ.mjs.map → status-vUK0SA17.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-Be9B1jEj.mjs → taxonomies-CurpLtNC.mjs} +52 -24
- package/dist/taxonomies-CurpLtNC.mjs.map +1 -0
- package/dist/{taxonomies-CJmkEpdS.mjs → taxonomies-DhLaNJji.mjs} +34 -27
- package/dist/taxonomies-DhLaNJji.mjs.map +1 -0
- package/dist/{taxonomy-B2HQuVf5.mjs → taxonomy-BBUlGug5.mjs} +33 -7
- package/dist/taxonomy-BBUlGug5.mjs.map +1 -0
- package/dist/{tokens-BvrJvIB6.mjs → tokens-LeuXF9gG.mjs} +1 -1
- package/dist/{tokens-BvrJvIB6.mjs.map → tokens-LeuXF9gG.mjs.map} +1 -1
- package/dist/{transport-k7YjfmEn.d.mts → transport-BZ-03aFT.d.mts} +1 -1
- package/dist/{transport-k7YjfmEn.d.mts.map → transport-BZ-03aFT.d.mts.map} +1 -1
- package/dist/{transport-B4rXnSTf.mjs → transport-_2nBz7e9.mjs} +1 -1
- package/dist/{transport-B4rXnSTf.mjs.map → transport-_2nBz7e9.mjs.map} +1 -1
- package/dist/{trusted-proxy-DY1_UqHr.mjs → trusted-proxy-DZY5WCn2.mjs} +1 -1
- package/dist/{trusted-proxy-DY1_UqHr.mjs.map → trusted-proxy-DZY5WCn2.mjs.map} +1 -1
- package/dist/{types-Czg1S3gB.d.mts → types-B-gIxFCE.d.mts} +1 -1
- package/dist/{types-Czg1S3gB.d.mts.map → types-B-gIxFCE.d.mts.map} +1 -1
- package/dist/{types-DXLVzV2w.d.mts → types-BG8_XTLj.d.mts} +1 -1
- package/dist/{types-DXLVzV2w.d.mts.map → types-BG8_XTLj.d.mts.map} +1 -1
- package/dist/{types-CWGYDYqF.d.mts → types-BWh2MjmA.d.mts} +15 -2
- package/dist/types-BWh2MjmA.d.mts.map +1 -0
- package/dist/{types-CgvhU-hF.d.mts → types-BWqGVhFn.d.mts} +1 -1
- package/dist/{types-CgvhU-hF.d.mts.map → types-BWqGVhFn.d.mts.map} +1 -1
- package/dist/{types-DYF2_Vf4.mjs → types-CQAugunJ.mjs} +1 -1
- package/dist/{types-DYF2_Vf4.mjs.map → types-CQAugunJ.mjs.map} +1 -1
- package/dist/{types-DPCpkzvS.d.mts → types-CTLJYMhN.d.mts} +1 -1
- package/dist/{types-DPCpkzvS.d.mts.map → types-CTLJYMhN.d.mts.map} +1 -1
- package/dist/{types-CmivgZbp.d.mts → types-CUsXGRVj.d.mts} +1 -1
- package/dist/{types-CmivgZbp.d.mts.map → types-CUsXGRVj.d.mts.map} +1 -1
- package/dist/{types-DXOIbece.mjs → types-CmI1OyQg.mjs} +2 -2
- package/dist/types-CmI1OyQg.mjs.map +1 -0
- package/dist/{types-CKNXt63n.d.mts → types-DrYMm9s5.d.mts} +1 -1
- package/dist/{types-CKNXt63n.d.mts.map → types-DrYMm9s5.d.mts.map} +1 -1
- package/dist/{types-CIKX2HO5.d.mts → types-TTx8uP7V.d.mts} +2 -2
- package/dist/{types-CIKX2HO5.d.mts.map → types-TTx8uP7V.d.mts.map} +1 -1
- package/dist/{types-DCNNfeCv.d.mts → types-fS7-VTdR.d.mts} +1 -1
- package/dist/{types-DCNNfeCv.d.mts.map → types-fS7-VTdR.d.mts.map} +1 -1
- package/dist/{user-Db-Rti_z.mjs → user-JAuc8VUf.mjs} +3 -3
- package/dist/{user-Db-Rti_z.mjs.map → user-JAuc8VUf.mjs.map} +1 -1
- package/dist/{utils-LbHcSRTj.mjs → utils-B7A57fm9.mjs} +1 -1
- package/dist/{utils-LbHcSRTj.mjs.map → utils-B7A57fm9.mjs.map} +1 -1
- package/dist/{validate-Bwl64sxv.mjs → validate-BzXHWnkV.mjs} +2 -2
- package/dist/{validate-Bwl64sxv.mjs.map → validate-BzXHWnkV.mjs.map} +1 -1
- package/dist/{validate-CE2M0nvx.d.mts → validate-DOFrIb-c.d.mts} +5 -5
- package/dist/{validate-CE2M0nvx.d.mts.map → validate-DOFrIb-c.d.mts.map} +1 -1
- package/dist/{validation-C_yOvFaO.mjs → validation-CY1gk4Ar.mjs} +6 -6
- package/dist/{validation-C_yOvFaO.mjs.map → validation-CY1gk4Ar.mjs.map} +1 -1
- package/dist/version-B5nHxI5Y.mjs +7 -0
- package/dist/{version-RnYXYjzD.mjs.map → version-B5nHxI5Y.mjs.map} +1 -1
- package/dist/{widgets-8GONuRHo.mjs → widgets-Dri0spI4.mjs} +3 -3
- package/dist/{widgets-8GONuRHo.mjs.map → widgets-Dri0spI4.mjs.map} +1 -1
- package/dist/{zod-generator-D481JjzD.mjs → zod-generator-xEHODMJf.mjs} +51 -15
- package/dist/zod-generator-xEHODMJf.mjs.map +1 -0
- package/package.json +8 -7
- package/src/api/handlers/taxonomies.ts +62 -32
- package/src/api/schemas/bylines.ts +8 -0
- package/src/astro/integration/shims/use-sync-external-store-with-selector.js +71 -0
- package/src/astro/integration/shims/use-sync-external-store.js +1 -0
- package/src/astro/integration/virtual-modules.ts +8 -0
- package/src/astro/integration/vite-config.ts +56 -9
- package/src/astro/middleware/request-context.ts +6 -1
- package/src/astro/middleware/scoped-db.ts +131 -0
- package/src/astro/middleware/stream-end-metrics.ts +4 -8
- package/src/astro/middleware.ts +103 -31
- package/src/astro/routes/admin.astro +5 -1
- package/src/astro/routes/api/schema/index.ts +9 -3
- package/src/cli/commands/export-seed.ts +15 -11
- package/src/components/Block.astro +71 -0
- package/src/components/EmDashMedia.astro +1 -2
- package/src/components/Image.astro +36 -2
- package/src/components/InlinePortableTextEditor.tsx +10 -2
- package/src/components/index.ts +5 -0
- package/src/components/portable-text-text-align.ts +38 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +5 -1
- package/src/content/converters/prosemirror-to-portable-text.ts +8 -0
- package/src/content/converters/types.ts +1 -0
- package/src/database/migrations/045_taxonomy_parent_group.ts +68 -0
- package/src/database/migrations/runner.ts +2 -0
- package/src/database/repositories/byline.ts +14 -0
- package/src/database/repositories/taxonomy.ts +50 -7
- package/src/database/repositories/types.ts +13 -0
- package/src/emdash-runtime.ts +226 -71
- package/src/loader.ts +161 -13
- package/src/media/local-runtime.ts +18 -5
- package/src/plugins/context.ts +94 -22
- package/src/plugins/cron.ts +18 -2
- package/src/plugins/routes.ts +40 -1
- package/src/query.ts +201 -19
- package/src/schema/zod-generator.ts +53 -8
- package/src/taxonomies/index.ts +46 -8
- package/src/ui.ts +5 -0
- package/src/virtual-modules.d.ts +13 -0
- package/dist/byline-CC0WS4Gu.mjs.map +0 -1
- package/dist/byline-fields-jy07PZJM.d.mts.map +0 -1
- package/dist/context-f1__jpzF.mjs.map +0 -1
- package/dist/cron-CQPxBjYs.mjs.map +0 -1
- package/dist/index-C2dLNT6S.d.mts.map +0 -1
- package/dist/loader-C8Z48Uof.mjs.map +0 -1
- package/dist/menus-DOs1MQJg.mjs.map +0 -1
- package/dist/query-B1RVFUNM.mjs.map +0 -1
- package/dist/redirects-DUvXgzCX.mjs.map +0 -1
- package/dist/runner-DYYnW530.mjs.map +0 -1
- package/dist/taxonomies-Be9B1jEj.mjs.map +0 -1
- package/dist/taxonomies-CJmkEpdS.mjs.map +0 -1
- package/dist/taxonomy-B2HQuVf5.mjs.map +0 -1
- package/dist/types-CWGYDYqF.d.mts.map +0 -1
- package/dist/types-DXOIbece.mjs.map +0 -1
- package/dist/version-RnYXYjzD.mjs +0 -7
- package/dist/zod-generator-D481JjzD.mjs.map +0 -1
- /package/dist/{api-tokens-BVH-H8Z9.mjs → api-tokens-B4BQybOp.mjs} +0 -0
- /package/dist/{ssrf-Cz1e2QPn.mjs → ssrf-CcX9zvMK.mjs} +0 -0
- /package/dist/{types-Bfr2Pj6z.mjs → types-BvbeGEtr.mjs} +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-scoped database lifecycle helpers.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from middleware.ts so they can be unit-tested without pulling in
|
|
5
|
+
* the virtual:emdash/* module graph. The middleware imports these to settle a
|
|
6
|
+
* request-scoped db adapter's lifecycle around the response.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Astro attaches AstroCookies to outgoing responses via a well-known global
|
|
11
|
+
* symbol. Cloning a Response (`new Response(body, init)`) drops non-header
|
|
12
|
+
* metadata, so any helper that wraps the response must explicitly forward this
|
|
13
|
+
* symbol or `cookies.set()` calls will be silently dropped. `Symbol.for`
|
|
14
|
+
* returns the same registry symbol everywhere, so this matches the copy in
|
|
15
|
+
* middleware.ts.
|
|
16
|
+
*/
|
|
17
|
+
export const ASTRO_COOKIES_SYMBOL = Symbol.for("astro.cookies");
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Run a request-scoped db's `close()` once the response body has finished
|
|
21
|
+
* streaming. Astro streams HTML and components issue DB queries during that
|
|
22
|
+
* stream, so a connection-backed adapter (e.g. Postgres over Hyperdrive) must
|
|
23
|
+
* not be torn down until the body is flushed. Bodyless responses (redirects,
|
|
24
|
+
* 304s, errors) close immediately. A guard makes close idempotent and a stream
|
|
25
|
+
* `cancel` (client disconnect) still triggers it so connections never leak.
|
|
26
|
+
*
|
|
27
|
+
* No-op for adapters without a `close` (D1): the response passes through.
|
|
28
|
+
*/
|
|
29
|
+
export function wrapResponseForScopedClose(response: Response, close: () => void): Response {
|
|
30
|
+
let closed = false;
|
|
31
|
+
const runClose = () => {
|
|
32
|
+
if (closed) return;
|
|
33
|
+
closed = true;
|
|
34
|
+
try {
|
|
35
|
+
close();
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error("[emdash] request-scoped db close failed:", error);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
if (!response.body) {
|
|
42
|
+
runClose();
|
|
43
|
+
return response;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const transform = new TransformStream<Uint8Array, Uint8Array>({
|
|
47
|
+
flush: runClose,
|
|
48
|
+
cancel: runClose,
|
|
49
|
+
});
|
|
50
|
+
const wrapped = new Response(response.body.pipeThrough(transform), response);
|
|
51
|
+
const astroCookies = Reflect.get(response, ASTRO_COOKIES_SYMBOL);
|
|
52
|
+
if (astroCookies !== undefined) {
|
|
53
|
+
Reflect.set(wrapped, ASTRO_COOKIES_SYMBOL, astroCookies);
|
|
54
|
+
}
|
|
55
|
+
// Byte counts are preserved by the identity transform, but a stale
|
|
56
|
+
// Content-Length on a reconstructed streaming Response risks truncation.
|
|
57
|
+
wrapped.headers.delete("Content-Length");
|
|
58
|
+
return wrapped;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Run the request body under a request-scoped db, then settle its lifecycle:
|
|
63
|
+
* `commit()` runs before the response is returned (so per-request state like a
|
|
64
|
+
* D1 bookmark cookie is persisted in the headers, even if render throws), while
|
|
65
|
+
* `close()` (if any) is deferred to stream-end so a connection-backed adapter
|
|
66
|
+
* isn't torn down mid-render. On error the connection is closed immediately
|
|
67
|
+
* before rethrowing so it never leaks.
|
|
68
|
+
*
|
|
69
|
+
* On the error path both `commit()` and `close()` are defended: a throw from
|
|
70
|
+
* either is logged and swallowed so it can't replace the propagating render
|
|
71
|
+
* error (which is the one the caller needs to see). On the success path
|
|
72
|
+
* `commit()` is guarded too — if it throws, the connection is closed before the
|
|
73
|
+
* failure is surfaced, so it never leaks. For the current adapters `commit()`
|
|
74
|
+
* is a no-op (Hyperdrive) or a cookie write (D1, no `close`) and `close()` is
|
|
75
|
+
* fire-and-forget, so these guards only matter for a future connection-backed
|
|
76
|
+
* adapter with throwing teardown, but the helper is generic and must not leak
|
|
77
|
+
* or mask.
|
|
78
|
+
*/
|
|
79
|
+
export async function finishScoped(
|
|
80
|
+
scoped: { commit: () => void; close?: () => void },
|
|
81
|
+
run: () => Promise<Response>,
|
|
82
|
+
): Promise<Response> {
|
|
83
|
+
let response: Response;
|
|
84
|
+
try {
|
|
85
|
+
response = await run();
|
|
86
|
+
} catch (error) {
|
|
87
|
+
// A render error is already propagating; neither commit nor close may
|
|
88
|
+
// mask it, and close must still run so the connection doesn't leak.
|
|
89
|
+
commitSafely(scoped.commit);
|
|
90
|
+
closeSafely(scoped.close);
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
scoped.commit();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
// commit() failed on the success path: close the connection now (the
|
|
97
|
+
// response won't be wrapped, so stream-end close would never run) and
|
|
98
|
+
// surface the failure. close is swallowed so it can't mask the commit
|
|
99
|
+
// error that the caller needs to see.
|
|
100
|
+
closeSafely(scoped.close);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
return scoped.close ? wrapResponseForScopedClose(response, scoped.close) : response;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Run commit() swallowing any error. Used where an exception is already
|
|
108
|
+
* propagating (or about to be thrown) and a commit failure must neither mask it
|
|
109
|
+
* nor skip the subsequent close().
|
|
110
|
+
*/
|
|
111
|
+
function commitSafely(commit: () => void): void {
|
|
112
|
+
try {
|
|
113
|
+
commit();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error("[emdash] request-scoped db commit failed during error handling:", error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Run close() swallowing any error. Used on the error/commit-failure paths
|
|
121
|
+
* where another exception is the one the caller must see; a throwing teardown
|
|
122
|
+
* must not replace it.
|
|
123
|
+
*/
|
|
124
|
+
function closeSafely(close: (() => void) | undefined): void {
|
|
125
|
+
if (!close) return;
|
|
126
|
+
try {
|
|
127
|
+
close();
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.error("[emdash] request-scoped db close failed during error handling:", error);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -20,17 +20,13 @@
|
|
|
20
20
|
|
|
21
21
|
import { flushRecorder, isInstrumentationEnabled } from "../../database/instrumentation.js";
|
|
22
22
|
import { getRequestContext } from "../../request-context.js";
|
|
23
|
+
// Reuse the single source of truth for Astro's well-known cookies symbol
|
|
24
|
+
// rather than redefining `Symbol.for("astro.cookies")` here — it must stay in
|
|
25
|
+
// lockstep with the copy the rest of the middleware forwards.
|
|
26
|
+
import { ASTRO_COOKIES_SYMBOL } from "./scoped-db.js";
|
|
23
27
|
|
|
24
28
|
export const STREAM_END_PREFIX = "[emdash-stream-end]";
|
|
25
29
|
|
|
26
|
-
/**
|
|
27
|
-
* Astro attaches AstroCookies to outgoing responses via a well-known global
|
|
28
|
-
* symbol. Constructing a new Response drops non-header metadata, so the
|
|
29
|
-
* symbol must be forwarded explicitly or `cookies.set()` calls are silently
|
|
30
|
-
* dropped. Same pattern as finalizeResponse in ../middleware.ts.
|
|
31
|
-
*/
|
|
32
|
-
const ASTRO_COOKIES_SYMBOL = Symbol.for("astro.cookies");
|
|
33
|
-
|
|
34
30
|
/** Shape of the NDJSON snapshot emitted when the body finishes streaming. */
|
|
35
31
|
export interface StreamEndSnapshot {
|
|
36
32
|
route?: string;
|
package/src/astro/middleware.ts
CHANGED
|
@@ -12,6 +12,7 @@ import type { Kysely } from "kysely";
|
|
|
12
12
|
import virtualConfig from "virtual:emdash/config";
|
|
13
13
|
// @ts-ignore - virtual module
|
|
14
14
|
import {
|
|
15
|
+
createCoalescingDialect as virtualCreateCoalescingDialect,
|
|
15
16
|
createDialect as virtualCreateDialect,
|
|
16
17
|
createRequestScopedDb as virtualCreateRequestScopedDb,
|
|
17
18
|
} from "virtual:emdash/dialect";
|
|
@@ -59,6 +60,7 @@ import type { PublishedRef } from "../scheduled-publish.js";
|
|
|
59
60
|
import { isMissingTableError } from "../utils/db-errors.js";
|
|
60
61
|
import { createInitLock, type InitLock, initWithLock } from "../utils/init-lock.js";
|
|
61
62
|
import type { EmDashConfig } from "./integration/runtime.js";
|
|
63
|
+
import { ASTRO_COOKIES_SYMBOL, finishScoped } from "./middleware/scoped-db.js";
|
|
62
64
|
import { wrapBodyForStreamMetrics } from "./middleware/stream-end-metrics.js";
|
|
63
65
|
import { prefetchLayoutData } from "./prefetch.js";
|
|
64
66
|
import { createPublicPluginApiRouteHandler } from "./public-plugin-api-routes.js";
|
|
@@ -179,6 +181,10 @@ function buildDependencies(config: EmDashConfig): RuntimeDependencies {
|
|
|
179
181
|
config,
|
|
180
182
|
plugins: getPlugins(),
|
|
181
183
|
createDialect: virtualCreateDialect as (config: Record<string, unknown>) => unknown,
|
|
184
|
+
// Optional: only batching backends (D1, DO) export this; undefined otherwise.
|
|
185
|
+
createCoalescingDialect: virtualCreateCoalescingDialect as
|
|
186
|
+
| ((config: Record<string, unknown>) => unknown)
|
|
187
|
+
| undefined,
|
|
182
188
|
createStorage: virtualCreateStorage as ((config: Record<string, unknown>) => Storage) | null,
|
|
183
189
|
createScheduler: virtualCreateScheduler as CreateSchedulerFn | null,
|
|
184
190
|
sandboxEnabled: sandboxModule.sandboxEnabled as boolean,
|
|
@@ -270,16 +276,71 @@ export async function runScheduledTasks(
|
|
|
270
276
|
const config = getConfig();
|
|
271
277
|
if (!config) return { published: [] };
|
|
272
278
|
const runtime = await getRuntime(config);
|
|
273
|
-
|
|
279
|
+
|
|
280
|
+
// Connection-backed adapters (e.g. Postgres over Hyperdrive) cannot reuse
|
|
281
|
+
// the per-isolate singleton from a Cron Trigger: its socket belongs to the
|
|
282
|
+
// request that opened it, and workerd rejects cross-event I/O. Open an
|
|
283
|
+
// event-scoped connection for the sweep and run the batch under it in ALS —
|
|
284
|
+
// the runtime's db getter, the cron executor, and plugin cron contexts all
|
|
285
|
+
// resolve the connection from ALS — then close it. Gated on the adapter
|
|
286
|
+
// being connection-backed (it exposes `close()`); stateless adapters (D1,
|
|
287
|
+
// Node SQLite) return null or a close-less scope and keep using the
|
|
288
|
+
// singleton, so their cron path is unchanged.
|
|
289
|
+
const scoped = createRequestScopedDb({
|
|
290
|
+
config: config.database?.config,
|
|
291
|
+
isAuthenticated: false,
|
|
292
|
+
// The sweep publishes and cleans up — a write workload — so a
|
|
293
|
+
// connection-backed adapter routes it to the primary.
|
|
294
|
+
isWrite: true,
|
|
295
|
+
cookies: NOOP_COOKIE_JAR,
|
|
296
|
+
url: CRON_EVENT_URL,
|
|
297
|
+
});
|
|
298
|
+
if (!scoped?.close) {
|
|
299
|
+
// Stateless adapter (or no per-request scoping): the singleton is safe
|
|
300
|
+
// outside a request. Any close-less scope created above is discarded.
|
|
301
|
+
return runtime.runScheduledTasks(options);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const parent = getRequestContext();
|
|
305
|
+
const ctx = parent
|
|
306
|
+
? { ...parent, db: scoped.db }
|
|
307
|
+
: { editMode: false, db: scoped.db, metrics: createRequestMetrics(performance.now()) };
|
|
308
|
+
try {
|
|
309
|
+
return await runWithContext(ctx, () => runtime.runScheduledTasks(options));
|
|
310
|
+
} finally {
|
|
311
|
+
// Guard both so a throw in teardown can't mask the sweep result or skip
|
|
312
|
+
// close() and leak the connection. Mirrors closeSafely() in scoped-db.ts.
|
|
313
|
+
try {
|
|
314
|
+
scoped.commit();
|
|
315
|
+
} catch (error) {
|
|
316
|
+
console.error("[scheduled] request-scoped db commit failed:", error);
|
|
317
|
+
}
|
|
318
|
+
try {
|
|
319
|
+
scoped.close();
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error("[scheduled] request-scoped db close failed:", error);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
274
324
|
}
|
|
275
325
|
|
|
276
326
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
280
|
-
*
|
|
327
|
+
* A cookie jar that reads nothing and writes nothing, for request-scoped db
|
|
328
|
+
* adapters invoked outside an HTTP request (the Cron Trigger sweep). Connection
|
|
329
|
+
* adapters like Hyperdrive ignore cookies entirely; the D1 session adapter
|
|
330
|
+
* reads/writes a bookmark cookie, but cron never reaches that path (it has no
|
|
331
|
+
* `close()`), so the no-ops are never observed.
|
|
332
|
+
*/
|
|
333
|
+
const NOOP_COOKIE_JAR = {
|
|
334
|
+
get: () => undefined,
|
|
335
|
+
set: () => {},
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Synthetic URL for the cron sweep's request-scoped db opts. Only the D1
|
|
340
|
+
* session adapter inspects `url` (for cookie `secure`), and cron doesn't take
|
|
341
|
+
* that path, so the value is never used — it exists to satisfy the contract.
|
|
281
342
|
*/
|
|
282
|
-
const
|
|
343
|
+
const CRON_EVENT_URL = new URL("https://cron.emdash.internal/");
|
|
283
344
|
|
|
284
345
|
/**
|
|
285
346
|
* Baseline security headers applied to all responses.
|
|
@@ -294,9 +355,19 @@ function finalizeResponse(
|
|
|
294
355
|
if (astroCookies !== undefined) {
|
|
295
356
|
Reflect.set(res, ASTRO_COOKIES_SYMBOL, astroCookies);
|
|
296
357
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
358
|
+
// Set-if-absent so a host app that sets stricter values on its own routes
|
|
359
|
+
// wins. The middleware registers `order: 'pre'` (#1282), so on the response
|
|
360
|
+
// path it runs *after* host middleware; unconditional `set()` would clobber
|
|
361
|
+
// the host's headers on every public route (#1393). Mirrors the CSP guard.
|
|
362
|
+
if (!res.headers.has("X-Content-Type-Options")) {
|
|
363
|
+
res.headers.set("X-Content-Type-Options", "nosniff");
|
|
364
|
+
}
|
|
365
|
+
if (!res.headers.has("Referrer-Policy")) {
|
|
366
|
+
res.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
367
|
+
}
|
|
368
|
+
if (!res.headers.has("Permissions-Policy")) {
|
|
369
|
+
res.headers.set("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=()");
|
|
370
|
+
}
|
|
300
371
|
if (!res.headers.has("Content-Security-Policy")) {
|
|
301
372
|
res.headers.set("X-Frame-Options", "SAMEORIGIN");
|
|
302
373
|
}
|
|
@@ -356,12 +427,12 @@ const SITEMAP_COLLECTION_RE = /^\/sitemap-[a-z][a-z0-9_]*\.xml$/;
|
|
|
356
427
|
*/
|
|
357
428
|
function createRequestScopedDb(
|
|
358
429
|
opts: RequestScopedDbOpts,
|
|
359
|
-
): { db: Kysely<Database>; commit: () => void } | null {
|
|
430
|
+
): { db: Kysely<Database>; commit: () => void; close?: () => void } | null {
|
|
360
431
|
if (typeof virtualCreateRequestScopedDb !== "function") return null;
|
|
361
432
|
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- adapter returns Kysely<unknown>; cast to Database since core owns that type
|
|
362
433
|
const fn = virtualCreateRequestScopedDb as (
|
|
363
434
|
o: RequestScopedDbOpts,
|
|
364
|
-
) => { db: Kysely<Database>; commit: () => void } | null;
|
|
435
|
+
) => { db: Kysely<Database>; commit: () => void; close?: () => void } | null;
|
|
365
436
|
return fn(opts);
|
|
366
437
|
}
|
|
367
438
|
|
|
@@ -546,15 +617,10 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
546
617
|
.startsWith("text/html");
|
|
547
618
|
return runWithContext(ctx, async () => {
|
|
548
619
|
if (acceptsHtml) after(() => prefetchLayoutData());
|
|
549
|
-
// commit()
|
|
550
|
-
//
|
|
551
|
-
//
|
|
552
|
-
|
|
553
|
-
try {
|
|
554
|
-
return await runAnon();
|
|
555
|
-
} finally {
|
|
556
|
-
anonScoped.commit();
|
|
557
|
-
}
|
|
620
|
+
// commit() persists per-request state (e.g. the D1 bookmark cookie)
|
|
621
|
+
// before the response is returned, even if render throws; close()
|
|
622
|
+
// (connection teardown) is deferred to stream-end. See finishScoped.
|
|
623
|
+
return finishScoped(anonScoped, runAnon);
|
|
558
624
|
});
|
|
559
625
|
}
|
|
560
626
|
return runAnon();
|
|
@@ -658,7 +724,17 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
658
724
|
|
|
659
725
|
// Direct access (for advanced use cases)
|
|
660
726
|
storage: runtime.storage,
|
|
661
|
-
|
|
727
|
+
// Lazy getter, not an eager snapshot: `locals.emdash` is built
|
|
728
|
+
// before the per-request scoped db is installed in ALS, so reading
|
|
729
|
+
// `runtime.db` here would capture the per-isolate singleton. Routes
|
|
730
|
+
// access `emdash.db` later, during the request, when the scoped db
|
|
731
|
+
// is active. For a stateless binding (D1) the two are equivalent,
|
|
732
|
+
// but for a request-bound connection (pg/Hyperdrive) the singleton
|
|
733
|
+
// belongs to the cold-start request and reusing it from a warm
|
|
734
|
+
// request hangs on workerd's cross-request I/O guard.
|
|
735
|
+
get db() {
|
|
736
|
+
return runtime.db;
|
|
737
|
+
},
|
|
662
738
|
getPublicMediaUrl: createPublicMediaUrlResolver(runtime.storage),
|
|
663
739
|
hooks: runtime.hooks,
|
|
664
740
|
email: runtime.email,
|
|
@@ -722,16 +798,12 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
722
798
|
const ctx = parent
|
|
723
799
|
? { ...parent, db: scoped.db }
|
|
724
800
|
: { editMode: false, db: scoped.db, metrics };
|
|
725
|
-
return runWithContext(ctx,
|
|
726
|
-
// commit()
|
|
727
|
-
//
|
|
728
|
-
//
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
} finally {
|
|
732
|
-
scoped.commit();
|
|
733
|
-
}
|
|
734
|
-
});
|
|
801
|
+
return runWithContext(ctx, () =>
|
|
802
|
+
// commit() persists per-request state (e.g. the D1 bookmark cookie)
|
|
803
|
+
// before the response returns, even if render throws; close()
|
|
804
|
+
// (connection teardown) is deferred to stream-end. See finishScoped.
|
|
805
|
+
finishScoped(scoped, renderAndFinalize),
|
|
806
|
+
);
|
|
735
807
|
}
|
|
736
808
|
|
|
737
809
|
return renderAndFinalize();
|
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* This page serves the EmDash admin React SPA.
|
|
6
6
|
* AdminWrapper imports plugin admin modules and passes them to AdminApp.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
// `?url` keeps the admin stylesheet out of the page's CSS module graph so
|
|
9
|
+
// Astro's dev SSR doesn't inject it into every public route's <head>. We emit
|
|
10
|
+
// it as a route-scoped <link> below instead. See #1281.
|
|
11
|
+
import adminStylesUrl from "@emdash-cms/admin/styles.css?url";
|
|
9
12
|
// Use package-qualified import so Astro generates a proper module URL
|
|
10
13
|
// (relative imports resolve to absolute paths which break client hydration)
|
|
11
14
|
import AdminWrapper from "emdash/routes/PluginRegistry";
|
|
@@ -28,6 +31,7 @@ const pageTitle = adminConfig?.siteName ? `${adminConfig.siteName} Admin` : "EmD
|
|
|
28
31
|
<head>
|
|
29
32
|
<meta charset="UTF-8" />
|
|
30
33
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
34
|
+
<link rel="stylesheet" href={adminStylesUrl} />
|
|
31
35
|
<Font cssVariable="--font-emdash" />
|
|
32
36
|
{adminConfig?.favicon ? (
|
|
33
37
|
<link rel="icon" href={adminConfig.favicon} />
|
|
@@ -15,7 +15,7 @@ import { hashString } from "emdash";
|
|
|
15
15
|
import { requirePerm } from "#api/authorize.js";
|
|
16
16
|
import { apiSuccess, handleError, requireDb } from "#api/error.js";
|
|
17
17
|
import { SchemaRegistry } from "#schema/registry.js";
|
|
18
|
-
import { generateTypeScript } from "#schema/zod-generator.js";
|
|
18
|
+
import { generateTypeScript, uniqueInterfaceNames } from "#schema/zod-generator.js";
|
|
19
19
|
|
|
20
20
|
export const prerender = false;
|
|
21
21
|
|
|
@@ -45,8 +45,14 @@ export const GET: APIRoute = async ({ request, locals }) => {
|
|
|
45
45
|
const format = url.searchParams.get("format");
|
|
46
46
|
|
|
47
47
|
if (format === "typescript") {
|
|
48
|
-
// Generate TypeScript definitions
|
|
49
|
-
|
|
48
|
+
// Generate TypeScript definitions. Singularizing slugs can collapse
|
|
49
|
+
// distinct collections onto the same interface name, so resolve names
|
|
50
|
+
// up front to keep every emitted interface unique (`book` + `books`
|
|
51
|
+
// would otherwise both emit `Book`).
|
|
52
|
+
const interfaceNames = uniqueInterfaceNames(collectionsWithFields);
|
|
53
|
+
const types = collectionsWithFields
|
|
54
|
+
.map((c) => generateTypeScript(c, interfaceNames.get(c.slug)))
|
|
55
|
+
.join("\n\n");
|
|
50
56
|
|
|
51
57
|
const header = `// Generated by EmDash CLI
|
|
52
58
|
// Do not edit manually - run \`emdash types\` to regenerate
|
|
@@ -153,13 +153,16 @@ export async function exportSeed(db: Kysely<Database>, withContent?: string): Pr
|
|
|
153
153
|
|
|
154
154
|
// 7. Export content (if requested)
|
|
155
155
|
if (withContent !== undefined) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
// Treat "all" as a synonym for the bare flag and "true". The args help
|
|
157
|
+
// text documents `all` as a valid value, but without this the literal
|
|
158
|
+
// string is read as a collection name and matches no collection (#1329).
|
|
159
|
+
const includeAll = withContent === "" || withContent === "true" || withContent === "all";
|
|
160
|
+
const collections = includeAll
|
|
161
|
+
? null // all collections
|
|
162
|
+
: withContent
|
|
163
|
+
.split(",")
|
|
164
|
+
.map((s) => s.trim())
|
|
165
|
+
.filter(Boolean);
|
|
163
166
|
|
|
164
167
|
seed.content = await exportContent(
|
|
165
168
|
db,
|
|
@@ -372,9 +375,10 @@ async function exportTaxonomies(
|
|
|
372
375
|
// Terms in this def's locale.
|
|
373
376
|
const terms = await termRepo.findByName(def.name, { locale: def.locale });
|
|
374
377
|
|
|
375
|
-
//
|
|
376
|
-
|
|
377
|
-
|
|
378
|
+
// translation_group -> slug for parent resolution within this locale.
|
|
379
|
+
// `parentId` stores the parent's translation_group, not a row id.
|
|
380
|
+
const groupToSlug = new Map<string, string>();
|
|
381
|
+
for (const term of terms) groupToSlug.set(term.translationGroup ?? term.id, term.slug);
|
|
378
382
|
|
|
379
383
|
// translation_group -> seed id of the anchor term.
|
|
380
384
|
const termGroupToSeedId = new Map<string, string>();
|
|
@@ -393,7 +397,7 @@ async function exportTaxonomies(
|
|
|
393
397
|
description: typeof term.data?.description === "string" ? term.data.description : undefined,
|
|
394
398
|
};
|
|
395
399
|
|
|
396
|
-
if (term.parentId) seedTerm.parent =
|
|
400
|
+
if (term.parentId) seedTerm.parent = groupToSlug.get(term.parentId);
|
|
397
401
|
|
|
398
402
|
if (i18nEnabled && term.locale) {
|
|
399
403
|
seedTerm.locale = term.locale;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* EmDash custom block override for `astro-portabletext`.
|
|
4
|
+
*
|
|
5
|
+
* Renders the same HTML as the upstream Block component (h1..h6, blockquote,
|
|
6
|
+
* `<p>` for `normal`) and additionally surfaces `textAlign` from the rich-text
|
|
7
|
+
* editor as a WordPress-style `has-text-align-{value}` class on the rendered
|
|
8
|
+
* paragraph or heading.
|
|
9
|
+
*
|
|
10
|
+
* `left` is the editor default and intentionally does not produce a class —
|
|
11
|
+
* paragraphs/headings without explicit alignment render exactly as they did
|
|
12
|
+
* before this fix, so existing content is byte-for-byte unchanged.
|
|
13
|
+
*
|
|
14
|
+
* Related: https://github.com/emdash-cms/emdash/issues/1201
|
|
15
|
+
*/
|
|
16
|
+
import type { BlockProps } from "astro-portabletext/types";
|
|
17
|
+
|
|
18
|
+
import { textAlignClassName } from "./portable-text-text-align.js";
|
|
19
|
+
|
|
20
|
+
type TextAlignedNode = BlockProps["node"] & { textAlign?: string };
|
|
21
|
+
type Props = Omit<BlockProps, "node"> & { node: TextAlignedNode };
|
|
22
|
+
|
|
23
|
+
const props = Astro.props as Props;
|
|
24
|
+
const { node, index: _index, isInline: _isInline, ...attrs } = props;
|
|
25
|
+
|
|
26
|
+
const styleIs = (style: string) => style === node.style;
|
|
27
|
+
|
|
28
|
+
// Allowlist-based; attacker-controlled PT data cannot inject arbitrary classes.
|
|
29
|
+
// See `./portable-text-text-align.ts`.
|
|
30
|
+
const alignClass = textAlignClassName(node.textAlign);
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
{
|
|
34
|
+
styleIs("h1") ? (
|
|
35
|
+
<h1 class={alignClass} {...attrs}>
|
|
36
|
+
<slot />
|
|
37
|
+
</h1>
|
|
38
|
+
) : styleIs("h2") ? (
|
|
39
|
+
<h2 class={alignClass} {...attrs}>
|
|
40
|
+
<slot />
|
|
41
|
+
</h2>
|
|
42
|
+
) : styleIs("h3") ? (
|
|
43
|
+
<h3 class={alignClass} {...attrs}>
|
|
44
|
+
<slot />
|
|
45
|
+
</h3>
|
|
46
|
+
) : styleIs("h4") ? (
|
|
47
|
+
<h4 class={alignClass} {...attrs}>
|
|
48
|
+
<slot />
|
|
49
|
+
</h4>
|
|
50
|
+
) : styleIs("h5") ? (
|
|
51
|
+
<h5 class={alignClass} {...attrs}>
|
|
52
|
+
<slot />
|
|
53
|
+
</h5>
|
|
54
|
+
) : styleIs("h6") ? (
|
|
55
|
+
<h6 class={alignClass} {...attrs}>
|
|
56
|
+
<slot />
|
|
57
|
+
</h6>
|
|
58
|
+
) : styleIs("blockquote") ? (
|
|
59
|
+
<blockquote class={alignClass} {...attrs}>
|
|
60
|
+
<slot />
|
|
61
|
+
</blockquote>
|
|
62
|
+
) : styleIs("normal") ? (
|
|
63
|
+
<p class={alignClass} {...attrs}>
|
|
64
|
+
<slot />
|
|
65
|
+
</p>
|
|
66
|
+
) : (
|
|
67
|
+
<p class={alignClass} {...attrs}>
|
|
68
|
+
<slot />
|
|
69
|
+
</p>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
@@ -158,9 +158,8 @@ const finalAlt = alt ?? (embed?.type === "image" ? embed.alt : undefined) ?? med
|
|
|
158
158
|
</audio>
|
|
159
159
|
)}
|
|
160
160
|
|
|
161
|
+
{/* Custom component embeds (Mux player, etc.) require dynamic import. Placeholder until that lands. */}
|
|
161
162
|
{embed?.type === "component" && (
|
|
162
|
-
<!-- Custom component embeds (Mux player, etc.) require dynamic import -->
|
|
163
|
-
<!-- For now, show a placeholder - full implementation TBD -->
|
|
164
163
|
<div class="emdash-media-component" data-package={embed.package} data-export={embed.export}>
|
|
165
164
|
<p>Custom media component: {embed.package}</p>
|
|
166
165
|
</div>
|
|
@@ -38,6 +38,8 @@ export interface Props {
|
|
|
38
38
|
displayWidth?: number;
|
|
39
39
|
/** Display height for this instance (overrides original) */
|
|
40
40
|
displayHeight?: number;
|
|
41
|
+
/** Alignment for this image instance (e.g. from a WordPress import) */
|
|
42
|
+
alignment?: "left" | "center" | "right" | "wide" | "full";
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -63,7 +65,7 @@ if (!node?.asset) {
|
|
|
63
65
|
return null;
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
const { asset, alt = "", caption, width, height, displayWidth, displayHeight } = node;
|
|
68
|
+
const { asset, alt = "", caption, width, height, displayWidth, displayHeight, alignment } = node;
|
|
67
69
|
|
|
68
70
|
// Calculate aspect ratio from original dimensions
|
|
69
71
|
const aspectRatio = width && height ? width / height : undefined;
|
|
@@ -168,7 +170,7 @@ const baseStyle = aspectRatio
|
|
|
168
170
|
const imgStyle = placeholderStyle ? `${baseStyle} ${placeholderStyle}` : baseStyle;
|
|
169
171
|
---
|
|
170
172
|
|
|
171
|
-
<figure class="emdash-image">
|
|
173
|
+
<figure class:list={["emdash-image", alignment && `emdash-image--align-${alignment}`]}>
|
|
172
174
|
<img
|
|
173
175
|
src={src}
|
|
174
176
|
srcset={srcset}
|
|
@@ -197,4 +199,36 @@ const imgStyle = placeholderStyle ? `${baseStyle} ${placeholderStyle}` : baseSty
|
|
|
197
199
|
margin-top: 0.5rem;
|
|
198
200
|
text-align: center;
|
|
199
201
|
}
|
|
202
|
+
/* Alignment (WordPress-style). Floats wrap surrounding text; wide/full span the column. */
|
|
203
|
+
.emdash-image--align-left,
|
|
204
|
+
.emdash-image--align-right {
|
|
205
|
+
width: fit-content;
|
|
206
|
+
max-width: 50%;
|
|
207
|
+
}
|
|
208
|
+
.emdash-image--align-left {
|
|
209
|
+
float: left;
|
|
210
|
+
margin: 0 1.5rem 1rem 0;
|
|
211
|
+
}
|
|
212
|
+
.emdash-image--align-right {
|
|
213
|
+
float: right;
|
|
214
|
+
margin: 0 0 1rem 1.5rem;
|
|
215
|
+
}
|
|
216
|
+
.emdash-image--align-center {
|
|
217
|
+
width: fit-content;
|
|
218
|
+
margin-inline: auto;
|
|
219
|
+
}
|
|
220
|
+
.emdash-image--align-wide,
|
|
221
|
+
.emdash-image--align-full {
|
|
222
|
+
width: 100%;
|
|
223
|
+
}
|
|
224
|
+
/* On narrow screens, un-float left/right so the image is not cramped beside text. */
|
|
225
|
+
@media (max-width: 640px) {
|
|
226
|
+
.emdash-image--align-left,
|
|
227
|
+
.emdash-image--align-right {
|
|
228
|
+
float: none;
|
|
229
|
+
width: 100%;
|
|
230
|
+
max-width: 100%;
|
|
231
|
+
margin-inline: 0;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
200
234
|
</style>
|
|
@@ -51,6 +51,7 @@ interface PTTextBlock {
|
|
|
51
51
|
level?: number;
|
|
52
52
|
children: PTSpan[];
|
|
53
53
|
markDefs?: PTMarkDef[];
|
|
54
|
+
textAlign?: "left" | "center" | "right" | "justify";
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
type PTBlock = PTTextBlock | { _type: string; _key: string; [key: string]: unknown };
|
|
@@ -119,12 +120,15 @@ function convertPMNode(node: PMNode): PTBlock | PTBlock[] | null {
|
|
|
119
120
|
case "paragraph": {
|
|
120
121
|
const { children, markDefs } = convertInline(node.content || []);
|
|
121
122
|
if (children.length === 0) return null;
|
|
123
|
+
const ta = node.attrs?.textAlign;
|
|
124
|
+
const textAlign = ta === "center" || ta === "right" || ta === "justify" ? ta : undefined;
|
|
122
125
|
return {
|
|
123
126
|
_type: "block",
|
|
124
127
|
_key: k(),
|
|
125
128
|
style: "normal",
|
|
126
129
|
children,
|
|
127
130
|
markDefs: markDefs.length > 0 ? markDefs : undefined,
|
|
131
|
+
...(textAlign ? { textAlign } : {}),
|
|
128
132
|
};
|
|
129
133
|
}
|
|
130
134
|
case "heading": {
|
|
@@ -140,12 +144,15 @@ function convertPMNode(node: PMNode): PTBlock | PTBlock[] | null {
|
|
|
140
144
|
6: "h6",
|
|
141
145
|
};
|
|
142
146
|
const headingStyle = headingStyles[level] ?? "h1";
|
|
147
|
+
const ta = node.attrs?.textAlign;
|
|
148
|
+
const textAlign = ta === "center" || ta === "right" || ta === "justify" ? ta : undefined;
|
|
143
149
|
return {
|
|
144
150
|
_type: "block",
|
|
145
151
|
_key: k(),
|
|
146
152
|
style: headingStyle,
|
|
147
153
|
children,
|
|
148
154
|
markDefs: markDefs.length > 0 ? markDefs : undefined,
|
|
155
|
+
...(textAlign ? { textAlign } : {}),
|
|
149
156
|
};
|
|
150
157
|
}
|
|
151
158
|
case "bulletList":
|
|
@@ -361,7 +368,7 @@ function portableTextToPM(blocks: PTBlock[]): JSONContent {
|
|
|
361
368
|
|
|
362
369
|
function convertPTBlock(block: PTBlock): JSONContent | null {
|
|
363
370
|
if (isPTTextBlock(block)) {
|
|
364
|
-
const { style = "normal", children, markDefs = [] } = block;
|
|
371
|
+
const { style = "normal", children, markDefs = [], textAlign } = block;
|
|
365
372
|
const pmContent = convertPTSpans(children, markDefs);
|
|
366
373
|
|
|
367
374
|
if (style === "blockquote") {
|
|
@@ -379,12 +386,13 @@ function convertPTBlock(block: PTBlock): JSONContent | null {
|
|
|
379
386
|
const level = parseInt(style.substring(1), 10);
|
|
380
387
|
return {
|
|
381
388
|
type: "heading",
|
|
382
|
-
attrs: { level },
|
|
389
|
+
attrs: { level, ...(textAlign ? { textAlign } : {}) },
|
|
383
390
|
content: pmContent.length > 0 ? pmContent : undefined,
|
|
384
391
|
};
|
|
385
392
|
}
|
|
386
393
|
return {
|
|
387
394
|
type: "paragraph",
|
|
395
|
+
attrs: textAlign ? { textAlign } : undefined,
|
|
388
396
|
content: pmContent.length > 0 ? pmContent : undefined,
|
|
389
397
|
};
|
|
390
398
|
}
|