emdash 0.26.0 → 0.27.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-DAAjOID4.d.mts → adapters-u037EnTR.d.mts} +1 -1
- package/dist/{adapters-DAAjOID4.d.mts.map → adapters-u037EnTR.d.mts.map} +1 -1
- package/dist/api/route-utils.mjs +10 -10
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/{api-BMfveMoB.mjs → api-80kycR9o.mjs} +84 -28
- package/dist/api-80kycR9o.mjs.map +1 -0
- package/dist/{apply--IVNSdXn.mjs → apply-DSypk6Iu.mjs} +19 -19
- package/dist/apply-DSypk6Iu.mjs.map +1 -0
- package/dist/astro/index.d.mts +7 -6
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +11 -3
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +6 -5
- package/dist/astro/middleware/auth.d.mts.map +1 -1
- package/dist/astro/middleware/auth.mjs +4 -3
- package/dist/astro/middleware/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.mjs +4 -4
- package/dist/astro/middleware.d.mts +1 -8
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +44 -43
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +3 -3
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +3 -3
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +3 -3
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +3 -3
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +4 -4
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +4 -4
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +9 -9
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +9 -9
- package/dist/astro/routes/api/admin/bylines/index.mjs +9 -9
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +6 -6
- 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 +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +27 -27
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +27 -27
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +27 -27
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/index.mjs +27 -27
- 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 +26 -26
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +27 -27
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +27 -27
- package/dist/astro/routes/api/admin/plugins/updates.mjs +26 -26
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +26 -26
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +26 -26
- 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 +3 -3
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
- package/dist/astro/routes/api/admin/users/index.mjs +3 -3
- package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/index.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +4 -4
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/signup/complete.mjs +3 -3
- package/dist/astro/routes/api/auth/signup/request.mjs +4 -4
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +6 -6
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +6 -6
- 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 +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +4 -4
- 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 +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +8 -8
- 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 +4 -4
- package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/index.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/trash.mjs +4 -4
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.d.mts +2 -2
- package/dist/astro/routes/api/import/probe.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +6 -5
- package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.mjs +8 -8
- package/dist/astro/routes/api/import/wordpress/media.d.mts +6 -5
- package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +5 -5
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +6 -6
- package/dist/astro/routes/api/manifest.d.mts.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +13 -4
- package/dist/astro/routes/api/manifest.mjs.map +1 -1
- package/dist/astro/routes/api/mcp.mjs +34 -34
- package/dist/astro/routes/api/media/_id_/confirm.mjs +4 -4
- package/dist/astro/routes/api/media/_id_.mjs +4 -4
- 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 +4 -4
- package/dist/astro/routes/api/media.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/items.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/translations.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_.mjs +5 -5
- package/dist/astro/routes/api/menus/index.mjs +5 -5
- package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
- package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
- package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
- package/dist/astro/routes/api/oauth/register.mjs +2 -2
- package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
- package/dist/astro/routes/api/oauth/token.mjs +2 -2
- package/dist/astro/routes/api/openapi.json.mjs +2 -2
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
- package/dist/astro/routes/api/redirects/404s/index.mjs +6 -6
- package/dist/astro/routes/api/redirects/404s/summary.mjs +6 -6
- package/dist/astro/routes/api/redirects/_id_.mjs +7 -7
- package/dist/astro/routes/api/redirects/index.mjs +7 -7
- 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 +26 -26
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +26 -26
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +26 -26
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +26 -26
- package/dist/astro/routes/api/schema/collections/index.mjs +26 -26
- package/dist/astro/routes/api/schema/index.mjs +6 -6
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +26 -26
- package/dist/astro/routes/api/schema/orphans/index.mjs +26 -26
- package/dist/astro/routes/api/search/enable.mjs +7 -7
- package/dist/astro/routes/api/search/index.mjs +6 -6
- package/dist/astro/routes/api/search/rebuild.mjs +7 -7
- package/dist/astro/routes/api/search/stats.mjs +6 -6
- package/dist/astro/routes/api/search/suggest.mjs +6 -6
- package/dist/astro/routes/api/sections/_slug_.mjs +6 -6
- package/dist/astro/routes/api/sections/index.mjs +6 -6
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +8 -8
- package/dist/astro/routes/api/setup/admin-verify.mjs +3 -3
- package/dist/astro/routes/api/setup/admin.mjs +3 -3
- package/dist/astro/routes/api/setup/dev-bypass.d.mts.map +1 -1
- package/dist/astro/routes/api/setup/dev-bypass.mjs +19 -17
- 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 +17 -17
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +3 -3
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/index.mjs +8 -8
- package/dist/astro/routes/api/themes/preview.mjs +3 -3
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +4 -4
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/index.mjs +6 -6
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +4 -4
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +4 -4
- package/dist/astro/routes/sitemap.xml.mjs +4 -4
- package/dist/astro/types.d.mts +8 -6
- 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-BZnOGJFo.mjs → authorize-C3a_zGsM.mjs} +2 -2
- package/dist/{authorize-BZnOGJFo.mjs.map → authorize-C3a_zGsM.mjs.map} +1 -1
- package/dist/{byline-LL8lyqdb.mjs → byline-DEKSVPTy.mjs} +5 -5
- package/dist/{byline-LL8lyqdb.mjs.map → byline-DEKSVPTy.mjs.map} +1 -1
- package/dist/{byline-fields-KD3JFRuH.d.mts → byline-fields-CtQ6blXd.d.mts} +32 -32
- package/dist/{byline-fields-KD3JFRuH.d.mts.map → byline-fields-CtQ6blXd.d.mts.map} +1 -1
- package/dist/{bylines-DE47vP8d.mjs → bylines-CiqgTHWF.mjs} +5 -5
- package/dist/{bylines-DE47vP8d.mjs.map → bylines-CiqgTHWF.mjs.map} +1 -1
- package/dist/{bylines-BmJ7Vg7J.mjs → bylines-Ds4-otXl.mjs} +4 -4
- package/dist/{bylines-BmJ7Vg7J.mjs.map → bylines-Ds4-otXl.mjs.map} +1 -1
- package/dist/{cache-D9jF5bYw.mjs → cache-Ciu3e3AF.mjs} +2 -2
- package/dist/{cache-D9jF5bYw.mjs.map → cache-Ciu3e3AF.mjs.map} +1 -1
- package/dist/{chunks-OCG163rN.mjs → chunks-CZFiauig.mjs} +2 -2
- package/dist/{chunks-OCG163rN.mjs.map → chunks-CZFiauig.mjs.map} +1 -1
- package/dist/cli/index.mjs +15 -15
- 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/{comment-D9BLDpZI.mjs → comment-CH1IrFFs.mjs} +2 -2
- package/dist/{comment-D9BLDpZI.mjs.map → comment-CH1IrFFs.mjs.map} +1 -1
- package/dist/{comment-reaction-Drl9SkNu.mjs → comment-reaction-kruNY-kP.mjs} +2 -2
- package/dist/{comment-reaction-Drl9SkNu.mjs.map → comment-reaction-kruNY-kP.mjs.map} +1 -1
- package/dist/{comments-BjJ9SKGU.mjs → comments-BUJyXbgq.mjs} +3 -3
- package/dist/{comments-BjJ9SKGU.mjs.map → comments-BUJyXbgq.mjs.map} +1 -1
- package/dist/{content-ncUWWjna.mjs → content-RmfHoWqK.mjs} +3 -3
- package/dist/{content-ncUWWjna.mjs.map → content-RmfHoWqK.mjs.map} +1 -1
- package/dist/{context-C_g-iJVA.mjs → context-CzUU_WzL.mjs} +7 -7
- package/dist/{context-C_g-iJVA.mjs.map → context-CzUU_WzL.mjs.map} +1 -1
- package/dist/{dashboard-CotyqQrW.mjs → dashboard-CVyGhift.mjs} +4 -4
- package/dist/{dashboard-CotyqQrW.mjs.map → dashboard-CVyGhift.mjs.map} +1 -1
- package/dist/db/index.d.mts +1 -1
- 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/{error-rVGiqWDt.mjs → error-BHkLZk-w.mjs} +2 -2
- package/dist/{error-rVGiqWDt.mjs.map → error-BHkLZk-w.mjs.map} +1 -1
- package/dist/{field-defs-cache-ljXzJCfc.mjs → field-defs-cache-BA-8ZPiT.mjs} +2 -2
- package/dist/{field-defs-cache-ljXzJCfc.mjs.map → field-defs-cache-BA-8ZPiT.mjs.map} +1 -1
- package/dist/{fts-manager-BbCCbEKA.mjs → fts-manager-Db9jGavf.mjs} +2 -2
- package/dist/{fts-manager-BbCCbEKA.mjs.map → fts-manager-Db9jGavf.mjs.map} +1 -1
- package/dist/{index-BRNabKrx.d.mts → index-CDZZjrLT.d.mts} +2407 -2365
- package/dist/index-CDZZjrLT.d.mts.map +1 -0
- package/dist/{index-Dt0OKJB4.d.mts → index-DGIjmUXQ.d.mts} +2 -2
- package/dist/{index-Dt0OKJB4.d.mts.map → index-DGIjmUXQ.d.mts.map} +1 -1
- package/dist/index.d.mts +11 -10
- package/dist/index.mjs +36 -36
- package/dist/{load-DMjXghbZ.mjs → load-DpHICVPh.mjs} +2 -2
- package/dist/{load-DMjXghbZ.mjs.map → load-DpHICVPh.mjs.map} +1 -1
- package/dist/{loader-BA_zhkS_.mjs → loader-4K37qA-y.mjs} +3 -3
- package/dist/{loader-BA_zhkS_.mjs.map → loader-4K37qA-y.mjs.map} +1 -1
- package/dist/media/local-runtime.d.mts +7 -6
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +4 -4
- package/dist/{media-C5t_eCnk.mjs → media-C0nRRfs1.mjs} +2 -2
- package/dist/{media-C5t_eCnk.mjs.map → media-C0nRRfs1.mjs.map} +1 -1
- package/dist/{menus-CYH09a41.mjs → menus-DzRyC1ID.mjs} +5 -5
- package/dist/{menus-CYH09a41.mjs.map → menus-DzRyC1ID.mjs.map} +1 -1
- package/dist/{menus-CBb6UrMU.mjs → menus-SL2K0xq2.mjs} +2 -2
- package/dist/{menus-CBb6UrMU.mjs.map → menus-SL2K0xq2.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/page/index.d.mts +1 -1
- package/dist/{parse-BwAdS7FZ.mjs → parse-CqyZj3Hp.mjs} +2 -2
- package/dist/{parse-BwAdS7FZ.mjs.map → parse-CqyZj3Hp.mjs.map} +1 -1
- package/dist/plugin-utils.d.mts +6 -5
- package/dist/plugin-utils.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +6 -5
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/{query-BpQb-blG.mjs → query-B0M-9LYR.mjs} +13 -13
- package/dist/{query-BpQb-blG.mjs.map → query-B0M-9LYR.mjs.map} +1 -1
- package/dist/{rate-limit-Dap6HMNM.mjs → rate-limit-BwoUdIpC.mjs} +2 -2
- package/dist/{rate-limit-Dap6HMNM.mjs.map → rate-limit-BwoUdIpC.mjs.map} +1 -1
- package/dist/{redirect-_M0trWoo.mjs → redirect-lMOzG04S.mjs} +2 -2
- package/dist/{redirect-_M0trWoo.mjs.map → redirect-lMOzG04S.mjs.map} +1 -1
- package/dist/{redirects-w0V9vj_j.mjs → redirects-9218MmYl.mjs} +3 -3
- package/dist/{redirects-w0V9vj_j.mjs.map → redirects-9218MmYl.mjs.map} +1 -1
- package/dist/{registry-g8yYt4cC.mjs → registry-DP-iEtdR.mjs} +4 -4
- package/dist/{registry-g8yYt4cC.mjs.map → registry-DP-iEtdR.mjs.map} +1 -1
- package/dist/runner-BbR3DfrL.d.mts.map +1 -1
- package/dist/{runner-DPdt_Wpa.mjs → runner-CFngB4WZ.mjs} +232 -199
- package/dist/runner-CFngB4WZ.mjs.map +1 -0
- package/dist/runtime.d.mts +6 -5
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +2 -2
- package/dist/scheduled-publish-BMljtY5G.d.mts +11 -0
- package/dist/scheduled-publish-BMljtY5G.d.mts.map +1 -0
- package/dist/{schema-DoLd3j2e.mjs → schema-BfJ7bIXH.mjs} +4 -4
- package/dist/{schema-DoLd3j2e.mjs.map → schema-BfJ7bIXH.mjs.map} +1 -1
- package/dist/{search-BR0ZeZmh.mjs → search-C7t3PH1J.mjs} +6 -4
- package/dist/search-C7t3PH1J.mjs.map +1 -0
- package/dist/{sections-5J2YJPqJ.mjs → sections-Dm0CVX23.mjs} +3 -3
- package/dist/{sections-5J2YJPqJ.mjs.map → sections-Dm0CVX23.mjs.map} +1 -1
- package/dist/seed/index.d.mts +1 -1
- package/dist/seed/index.mjs +14 -14
- package/dist/{seo-DKeXHkzE.mjs → seo-Dd3tbY_k.mjs} +2 -2
- package/dist/{seo-DKeXHkzE.mjs.map → seo-Dd3tbY_k.mjs.map} +1 -1
- package/dist/{service-BbO2s8gT.mjs → service-CTrqp_Jy.mjs} +2 -2
- package/dist/{service-BbO2s8gT.mjs.map → service-CTrqp_Jy.mjs.map} +1 -1
- package/dist/{settings-DJeki-97.mjs → settings-BX8cWBus.mjs} +3 -3
- package/dist/{settings-DJeki-97.mjs.map → settings-BX8cWBus.mjs.map} +1 -1
- package/dist/{settings-BMNr9Dmi.mjs → settings-CZ7ZP9cW.mjs} +3 -3
- package/dist/{settings-BMNr9Dmi.mjs.map → settings-CZ7ZP9cW.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/{taxonomies-CM_fUqLU.mjs → taxonomies-DChKcVxf.mjs} +4 -4
- package/dist/{taxonomies-CM_fUqLU.mjs.map → taxonomies-DChKcVxf.mjs.map} +1 -1
- package/dist/{taxonomies-D13i2ctt.mjs → taxonomies-ckPjz-6d.mjs} +5 -5
- package/dist/{taxonomies-D13i2ctt.mjs.map → taxonomies-ckPjz-6d.mjs.map} +1 -1
- package/dist/{taxonomy-BU0LjdVb.mjs → taxonomy-Cru-he6s.mjs} +3 -3
- package/dist/{taxonomy-BU0LjdVb.mjs.map → taxonomy-Cru-he6s.mjs.map} +1 -1
- package/dist/{transport-BZ-03aFT.d.mts → transport-Blrl2k_o.d.mts} +1 -1
- package/dist/{transport-BZ-03aFT.d.mts.map → transport-Blrl2k_o.d.mts.map} +1 -1
- package/dist/{types-BG8_XTLj.d.mts → types-BkZ8DUEI.d.mts} +1 -1
- package/dist/{types-BG8_XTLj.d.mts.map → types-BkZ8DUEI.d.mts.map} +1 -1
- package/dist/{types-DrYMm9s5.d.mts → types-ByChcBgE.d.mts} +1 -1
- package/dist/{types-DrYMm9s5.d.mts.map → types-ByChcBgE.d.mts.map} +1 -1
- package/dist/{types-BWqGVhFn.d.mts → types-CvuKO5Pn.d.mts} +1 -1
- package/dist/{types-BWqGVhFn.d.mts.map → types-CvuKO5Pn.d.mts.map} +1 -1
- package/dist/{types-CZgK3EMW.mjs → types-DU4TSFS5.mjs} +2 -2
- package/dist/{types-CZgK3EMW.mjs.map → types-DU4TSFS5.mjs.map} +1 -1
- package/dist/{types-CUsXGRVj.d.mts → types-Dbqff978.d.mts} +1 -1
- package/dist/{types-CUsXGRVj.d.mts.map → types-Dbqff978.d.mts.map} +1 -1
- package/dist/{types-fS7-VTdR.d.mts → types-Y09-wtyU.d.mts} +1 -1
- package/dist/{types-fS7-VTdR.d.mts.map → types-Y09-wtyU.d.mts.map} +1 -1
- package/dist/{user-DkG2jKCp.mjs → user-DgGbKL9s.mjs} +3 -3
- package/dist/{user-DkG2jKCp.mjs.map → user-DgGbKL9s.mjs.map} +1 -1
- package/dist/{validate-CG0V0wNR.d.mts → validate-9ECmtEpJ.d.mts} +9 -4
- package/dist/{validate-CG0V0wNR.d.mts.map → validate-9ECmtEpJ.d.mts.map} +1 -1
- package/dist/{validate-CuJ1Ps9j.mjs → validate-CRkcYZAR.mjs} +2 -2
- package/dist/{validate-CuJ1Ps9j.mjs.map → validate-CRkcYZAR.mjs.map} +1 -1
- package/dist/{validation-CwUfTdGF.mjs → validation-sR26SOwD.mjs} +5 -5
- package/dist/{validation-CwUfTdGF.mjs.map → validation-sR26SOwD.mjs.map} +1 -1
- package/dist/version-CrqhKGWn.mjs +7 -0
- package/dist/{version-BoNBItP_.mjs.map → version-CrqhKGWn.mjs.map} +1 -1
- package/dist/{widgets-BfOZ-ajY.mjs → widgets-DRgtn7Cl.mjs} +2 -2
- package/dist/{widgets-BfOZ-ajY.mjs.map → widgets-DRgtn7Cl.mjs.map} +1 -1
- package/dist/{zod-generator-gFsRuNNy.mjs → zod-generator-C5JaV--i.mjs} +2 -2
- package/dist/{zod-generator-gFsRuNNy.mjs.map → zod-generator-C5JaV--i.mjs.map} +1 -1
- package/package.json +8 -8
- package/src/api/handlers/content.ts +59 -16
- package/src/api/handlers/plugins.ts +77 -10
- package/src/astro/integration/vite-config.ts +19 -1
- package/src/astro/middleware/auth.ts +1 -0
- package/src/astro/middleware.ts +1 -0
- package/src/astro/routes/api/admin/plugins/[id]/disable.ts +6 -1
- package/src/astro/routes/api/admin/plugins/[id]/enable.ts +6 -1
- package/src/astro/routes/api/admin/plugins/[id]/index.ts +1 -0
- package/src/astro/routes/api/admin/plugins/index.ts +1 -0
- package/src/astro/routes/api/manifest.ts +20 -1
- package/src/astro/routes/api/setup/dev-bypass.ts +7 -2
- package/src/astro/types.ts +4 -0
- package/src/cli/commands/seed.ts +1 -1
- package/src/components/LiveSearch.astro +40 -4
- package/src/components/live-search-routing.ts +30 -0
- package/src/database/migrations/036_i18n_menus_and_taxonomies.ts +23 -18
- package/src/database/migrations/048_restore_content_taxonomies_term_index.ts +32 -0
- package/src/database/migrations/runner.ts +2 -0
- package/src/search/query.ts +3 -0
- package/src/search/types.ts +2 -0
- package/src/seed/apply.ts +2 -2
- package/src/seed/types.ts +6 -1
- package/dist/api-BMfveMoB.mjs.map +0 -1
- package/dist/apply--IVNSdXn.mjs.map +0 -1
- package/dist/index-BRNabKrx.d.mts.map +0 -1
- package/dist/runner-DPdt_Wpa.mjs.map +0 -1
- package/dist/search-BR0ZeZmh.mjs.map +0 -1
- package/dist/version-BoNBItP_.mjs +0 -7
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { Kysely } from "kysely";
|
|
6
6
|
|
|
7
7
|
import type { Database } from "../../database/types.js";
|
|
8
|
+
import type { SandboxedPluginEntry } from "../../emdash-runtime.js";
|
|
8
9
|
import { PluginStateRepository, type PluginState, type PluginStatus } from "../../plugins/state.js";
|
|
9
10
|
import type { ResolvedPlugin } from "../../plugins/types.js";
|
|
10
11
|
import type { ApiResult } from "../types.js";
|
|
@@ -17,6 +18,8 @@ export interface PluginInfo {
|
|
|
17
18
|
enabled: boolean;
|
|
18
19
|
status: PluginStatus;
|
|
19
20
|
source?: "config" | "marketplace" | "registry";
|
|
21
|
+
/** True for statically-sandboxed plugins (registered via `sandboxed: []`) */
|
|
22
|
+
sandboxed?: boolean;
|
|
20
23
|
marketplaceVersion?: string;
|
|
21
24
|
/** Publisher DID, for registry-source plugins */
|
|
22
25
|
registryPublisherDid?: string;
|
|
@@ -84,12 +87,43 @@ function buildPluginInfo(
|
|
|
84
87
|
};
|
|
85
88
|
}
|
|
86
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Build plugin info for a statically-sandboxed plugin entry
|
|
92
|
+
*/
|
|
93
|
+
function buildSandboxedPluginInfo(
|
|
94
|
+
entry: SandboxedPluginEntry,
|
|
95
|
+
state: PluginState | null,
|
|
96
|
+
): PluginInfo {
|
|
97
|
+
const status = state?.status ?? "active";
|
|
98
|
+
const enabled = status === "active";
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
id: entry.id,
|
|
102
|
+
name: state?.displayName || entry.id,
|
|
103
|
+
version: entry.version,
|
|
104
|
+
package: undefined, // v2 doesn't have package field
|
|
105
|
+
enabled,
|
|
106
|
+
status,
|
|
107
|
+
source: "config",
|
|
108
|
+
sandboxed: true,
|
|
109
|
+
capabilities: entry.capabilities,
|
|
110
|
+
hasAdminPages: (entry.adminPages?.length ?? 0) > 0,
|
|
111
|
+
hasDashboardWidgets: (entry.adminWidgets?.length ?? 0) > 0,
|
|
112
|
+
hasHooks: false,
|
|
113
|
+
installedAt: state?.installedAt?.toISOString(),
|
|
114
|
+
activatedAt: state?.activatedAt?.toISOString() ?? undefined,
|
|
115
|
+
deactivatedAt: state?.deactivatedAt?.toISOString() ?? undefined,
|
|
116
|
+
description: state?.description ?? undefined,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
87
120
|
/**
|
|
88
121
|
* List all configured plugins with their state
|
|
89
122
|
*/
|
|
90
123
|
export async function handlePluginList(
|
|
91
124
|
db: Kysely<Database>,
|
|
92
125
|
configuredPlugins: ResolvedPlugin[],
|
|
126
|
+
sandboxedPluginEntries: SandboxedPluginEntry[],
|
|
93
127
|
marketplaceUrl?: string,
|
|
94
128
|
): Promise<ApiResult<PluginListResponse>> {
|
|
95
129
|
try {
|
|
@@ -104,6 +138,14 @@ export async function handlePluginList(
|
|
|
104
138
|
return buildPluginInfo(plugin, state, marketplaceUrl);
|
|
105
139
|
});
|
|
106
140
|
|
|
141
|
+
// Include statically-sandboxed plugins (registered via `sandboxed: []`
|
|
142
|
+
// in astro.config.mjs).
|
|
143
|
+
for (const entry of sandboxedPluginEntries) {
|
|
144
|
+
if (configuredIds.has(entry.id)) continue;
|
|
145
|
+
configuredIds.add(entry.id);
|
|
146
|
+
items.push(buildSandboxedPluginInfo(entry, stateMap.get(entry.id) ?? null));
|
|
147
|
+
}
|
|
148
|
+
|
|
107
149
|
// Include runtime-installed plugins (marketplace or registry) that
|
|
108
150
|
// aren't in the configured plugins list.
|
|
109
151
|
for (const state of allStates) {
|
|
@@ -156,27 +198,37 @@ export async function handlePluginList(
|
|
|
156
198
|
export async function handlePluginGet(
|
|
157
199
|
db: Kysely<Database>,
|
|
158
200
|
configuredPlugins: ResolvedPlugin[],
|
|
201
|
+
sandboxedPluginEntries: SandboxedPluginEntry[],
|
|
159
202
|
pluginId: string,
|
|
160
203
|
marketplaceUrl?: string,
|
|
161
204
|
): Promise<ApiResult<PluginResponse>> {
|
|
162
205
|
try {
|
|
206
|
+
const stateRepo = new PluginStateRepository(db);
|
|
163
207
|
const plugin = configuredPlugins.find((p) => p.id === pluginId);
|
|
164
|
-
|
|
208
|
+
|
|
209
|
+
if (plugin) {
|
|
210
|
+
const state = await stateRepo.get(pluginId);
|
|
165
211
|
return {
|
|
166
|
-
success:
|
|
167
|
-
|
|
168
|
-
code: "NOT_FOUND",
|
|
169
|
-
message: `Plugin not found: ${pluginId}`,
|
|
170
|
-
},
|
|
212
|
+
success: true,
|
|
213
|
+
data: { item: buildPluginInfo(plugin, state, marketplaceUrl) },
|
|
171
214
|
};
|
|
172
215
|
}
|
|
173
216
|
|
|
174
|
-
const
|
|
175
|
-
|
|
217
|
+
const sandboxed = sandboxedPluginEntries.find((e) => e.id === pluginId);
|
|
218
|
+
if (sandboxed) {
|
|
219
|
+
const state = await stateRepo.get(pluginId);
|
|
220
|
+
return {
|
|
221
|
+
success: true,
|
|
222
|
+
data: { item: buildSandboxedPluginInfo(sandboxed, state) },
|
|
223
|
+
};
|
|
224
|
+
}
|
|
176
225
|
|
|
177
226
|
return {
|
|
178
|
-
success:
|
|
179
|
-
|
|
227
|
+
success: false,
|
|
228
|
+
error: {
|
|
229
|
+
code: "NOT_FOUND",
|
|
230
|
+
message: `Plugin not found: ${pluginId}`,
|
|
231
|
+
},
|
|
180
232
|
};
|
|
181
233
|
} catch {
|
|
182
234
|
return {
|
|
@@ -227,6 +279,7 @@ function buildStateOnlyPluginInfo(
|
|
|
227
279
|
export async function handlePluginEnable(
|
|
228
280
|
db: Kysely<Database>,
|
|
229
281
|
configuredPlugins: ResolvedPlugin[],
|
|
282
|
+
sandboxedPluginEntries: SandboxedPluginEntry[],
|
|
230
283
|
pluginId: string,
|
|
231
284
|
): Promise<ApiResult<PluginResponse>> {
|
|
232
285
|
try {
|
|
@@ -239,6 +292,13 @@ export async function handlePluginEnable(
|
|
|
239
292
|
return { success: true, data: { item: buildPluginInfo(plugin, state) } };
|
|
240
293
|
}
|
|
241
294
|
|
|
295
|
+
// Statically-sandboxed plugin: addressable via its build-time entry.
|
|
296
|
+
const sandboxed = sandboxedPluginEntries.find((e) => e.id === pluginId);
|
|
297
|
+
if (sandboxed) {
|
|
298
|
+
const state = await stateRepo.enable(pluginId, sandboxed.version);
|
|
299
|
+
return { success: true, data: { item: buildSandboxedPluginInfo(sandboxed, state) } };
|
|
300
|
+
}
|
|
301
|
+
|
|
242
302
|
// Runtime-installed plugin (marketplace or registry): only
|
|
243
303
|
// addressable through the state row. Fall back to the existing
|
|
244
304
|
// version recorded there.
|
|
@@ -268,6 +328,7 @@ export async function handlePluginEnable(
|
|
|
268
328
|
export async function handlePluginDisable(
|
|
269
329
|
db: Kysely<Database>,
|
|
270
330
|
configuredPlugins: ResolvedPlugin[],
|
|
331
|
+
sandboxedPluginEntries: SandboxedPluginEntry[],
|
|
271
332
|
pluginId: string,
|
|
272
333
|
): Promise<ApiResult<PluginResponse>> {
|
|
273
334
|
try {
|
|
@@ -279,6 +340,12 @@ export async function handlePluginDisable(
|
|
|
279
340
|
return { success: true, data: { item: buildPluginInfo(plugin, state) } };
|
|
280
341
|
}
|
|
281
342
|
|
|
343
|
+
const sandboxed = sandboxedPluginEntries.find((e) => e.id === pluginId);
|
|
344
|
+
if (sandboxed) {
|
|
345
|
+
const state = await stateRepo.disable(pluginId, sandboxed.version);
|
|
346
|
+
return { success: true, data: { item: buildSandboxedPluginInfo(sandboxed, state) } };
|
|
347
|
+
}
|
|
348
|
+
|
|
282
349
|
const existing = await stateRepo.get(pluginId);
|
|
283
350
|
if (!existing || (existing.source !== "marketplace" && existing.source !== "registry")) {
|
|
284
351
|
return {
|
|
@@ -444,7 +444,18 @@ export function createViteConfig(
|
|
|
444
444
|
// during pre-bundling and can't resolve them. Vite's exclude
|
|
445
445
|
// uses prefix matching (id.startsWith(m + "/")), so
|
|
446
446
|
// "virtual:emdash" matches all "virtual:emdash/*" imports.
|
|
447
|
-
|
|
447
|
+
//
|
|
448
|
+
// First-party packages must also stay excluded. In a
|
|
449
|
+
// real install (unlike the workspace symlink, which Vite never
|
|
450
|
+
// optimizes), the optimizer bundles their dist and code-splits
|
|
451
|
+
// lazily-executed dynamic imports (MCP tools, content
|
|
452
|
+
// validation) into hashed chunks. A mid-session re-optimization
|
|
453
|
+
// deletes those chunks while loaded modules still reference
|
|
454
|
+
// them, so every content write fails with "The file does not
|
|
455
|
+
// exist at .../deps_ssr/..." until the dev server restarts.
|
|
456
|
+
// Their CJS deps are still pre-bundled via the "parent > dep"
|
|
457
|
+
// include entries below, which resolve through excluded parents.
|
|
458
|
+
exclude: ["virtual:emdash", "emdash", "@emdash-cms/admin", "@emdash-cms/cloudflare"],
|
|
448
459
|
include: [
|
|
449
460
|
// EmDash direct deps
|
|
450
461
|
"emdash > @portabletext/toolkit",
|
|
@@ -455,6 +466,9 @@ export function createViteConfig(
|
|
|
455
466
|
"emdash > jose",
|
|
456
467
|
"emdash > jpeg-js",
|
|
457
468
|
"emdash > kysely",
|
|
469
|
+
// Only imported by the migration runner, so the first
|
|
470
|
+
// dev-bypass/setup request would otherwise discover it.
|
|
471
|
+
"emdash > kysely/migration",
|
|
458
472
|
"emdash > mime/lite",
|
|
459
473
|
"emdash > modern-tar",
|
|
460
474
|
"emdash > sanitize-html",
|
|
@@ -496,6 +510,7 @@ export function createViteConfig(
|
|
|
496
510
|
// Top-level deps (use astro > path for pnpm compat)
|
|
497
511
|
"astro > zod/v4",
|
|
498
512
|
"astro > zod/v4/core",
|
|
513
|
+
"astro/zod",
|
|
499
514
|
// zod-generator imports the bare `zod` entry, not `zod/v4`
|
|
500
515
|
"emdash > zod",
|
|
501
516
|
"@emdash-cms/cloudflare > kysely-d1",
|
|
@@ -507,6 +522,9 @@ export function createViteConfig(
|
|
|
507
522
|
"astro/assets/fonts/runtime.js",
|
|
508
523
|
"astro/assets/services/noop",
|
|
509
524
|
"@astrojs/cloudflare/image-service",
|
|
525
|
+
// Only imported by the /_image route, so the first image
|
|
526
|
+
// request would otherwise discover it.
|
|
527
|
+
"@astrojs/cloudflare/image-transform-endpoint",
|
|
510
528
|
],
|
|
511
529
|
},
|
|
512
530
|
}
|
|
@@ -120,6 +120,7 @@ const PUBLIC_API_EXACT = new Set([
|
|
|
120
120
|
// so unauthenticated callers only see published content. Admin endpoints
|
|
121
121
|
// (/enable, /rebuild, /stats) remain private because they're not in this set.
|
|
122
122
|
"/_emdash/api/search",
|
|
123
|
+
"/_emdash/api/search/suggest",
|
|
123
124
|
]);
|
|
124
125
|
|
|
125
126
|
// Build merged public routes at module load from auth provider descriptors.
|
package/src/astro/middleware.ts
CHANGED
|
@@ -752,6 +752,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
752
752
|
hooks: runtime.hooks,
|
|
753
753
|
email: runtime.email,
|
|
754
754
|
configuredPlugins: runtime.configuredPlugins,
|
|
755
|
+
sandboxedPluginEntries: runtime.sandboxedPluginEntries,
|
|
755
756
|
|
|
756
757
|
// Configuration (for checking database type, auth mode, etc.)
|
|
757
758
|
config,
|
|
@@ -28,7 +28,12 @@ export const POST: APIRoute = async ({ params, locals }) => {
|
|
|
28
28
|
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
const result = await handlePluginDisable(
|
|
31
|
+
const result = await handlePluginDisable(
|
|
32
|
+
emdash.db,
|
|
33
|
+
emdash.configuredPlugins,
|
|
34
|
+
emdash.sandboxedPluginEntries,
|
|
35
|
+
id,
|
|
36
|
+
);
|
|
32
37
|
|
|
33
38
|
if (!result.success) return unwrapResult(result);
|
|
34
39
|
|
|
@@ -28,7 +28,12 @@ export const POST: APIRoute = async ({ params, locals }) => {
|
|
|
28
28
|
return apiError("INVALID_REQUEST", "Plugin ID required", 400);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
const result = await handlePluginEnable(
|
|
31
|
+
const result = await handlePluginEnable(
|
|
32
|
+
emdash.db,
|
|
33
|
+
emdash.configuredPlugins,
|
|
34
|
+
emdash.sandboxedPluginEntries,
|
|
35
|
+
id,
|
|
36
|
+
);
|
|
32
37
|
|
|
33
38
|
if (!result.success) return unwrapResult(result);
|
|
34
39
|
|
|
@@ -11,6 +11,7 @@ import type { APIRoute } from "astro";
|
|
|
11
11
|
|
|
12
12
|
import { handleError } from "#api/error.js";
|
|
13
13
|
import { getAuthMode } from "#auth/mode.js";
|
|
14
|
+
import { OptionsRepository } from "#db/repositories/options.js";
|
|
14
15
|
|
|
15
16
|
import { COMMIT, VERSION } from "../../../version.js";
|
|
16
17
|
import type { EmDashManifest } from "../../types.js";
|
|
@@ -39,7 +40,25 @@ export const GET: APIRoute = async ({ locals }) => {
|
|
|
39
40
|
// doesn't assign it to globalThis, so getStoredConfig() always returned
|
|
40
41
|
// null and the React SPA never received custom logo/siteName/favicon.
|
|
41
42
|
// See issue #835.
|
|
42
|
-
|
|
43
|
+
let adminBranding = emdash?.config?.admin;
|
|
44
|
+
|
|
45
|
+
// When no build-time `admin.siteName` is configured, brand the admin with
|
|
46
|
+
// the site's own title so multi-site operators can tell backends apart
|
|
47
|
+
// (WordPress-style: wp-admin always shows the site name). Precedence:
|
|
48
|
+
// explicit `admin.siteName` → Site Title (Settings → General) → the title
|
|
49
|
+
// captured by the setup wizard → the bundled "EmDash" default in the SPA.
|
|
50
|
+
if (!adminBranding?.siteName && emdash?.db) {
|
|
51
|
+
try {
|
|
52
|
+
const options = new OptionsRepository(emdash.db);
|
|
53
|
+
const titles = await options.getMany<string>(["site:title", "emdash:site_title"]);
|
|
54
|
+
const siteTitle = titles.get("site:title") || titles.get("emdash:site_title");
|
|
55
|
+
if (siteTitle) {
|
|
56
|
+
adminBranding = { ...adminBranding, siteName: siteTitle };
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
// options table may not exist yet (pre-setup) — keep the default.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
43
62
|
|
|
44
63
|
// Check if self-signup is enabled (any allowed domain with enabled = 1)
|
|
45
64
|
// Only relevant for passkey auth — external auth providers handle their own signup
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* Usage:
|
|
11
11
|
* - GET with redirect: /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin
|
|
12
12
|
* - POST for API: Returns JSON with setup info
|
|
13
|
+
* - ?content=0 (or ?content=false): apply schema/structure only, skipping
|
|
14
|
+
* sample content entries, bylines, and taxonomy terms
|
|
13
15
|
*
|
|
14
16
|
* For agent/browser testing, navigate to:
|
|
15
17
|
* /_emdash/api/setup/dev-bypass?redirect=/_emdash/admin
|
|
@@ -57,12 +59,15 @@ async function handleDevBypass(context: Parameters<APIRoute>[0]): Promise<Respon
|
|
|
57
59
|
const migrations = await runMigrations(emdash.db);
|
|
58
60
|
console.log("[setup-dev-bypass] Migrations applied:", migrations.applied);
|
|
59
61
|
|
|
60
|
-
// Apply seed (user seed or built-in default)
|
|
62
|
+
// Apply seed (user seed or built-in default). `?content=0` (or `false`)
|
|
63
|
+
// applies schema/structure only — no sample content, bylines, or terms.
|
|
64
|
+
const contentParam = url.searchParams.get("content");
|
|
65
|
+
const includeContent = contentParam !== "0" && contentParam !== "false";
|
|
61
66
|
const seed = await loadSeed();
|
|
62
67
|
const validation = validateSeed(seed);
|
|
63
68
|
if (validation.valid) {
|
|
64
69
|
const seedResult = await applySeed(emdash.db, seed, {
|
|
65
|
-
includeContent
|
|
70
|
+
includeContent,
|
|
66
71
|
onConflict: "skip",
|
|
67
72
|
storage: emdash.storage ?? undefined,
|
|
68
73
|
});
|
package/src/astro/types.ts
CHANGED
|
@@ -434,6 +434,10 @@ export interface EmDashHandlers {
|
|
|
434
434
|
// Configured plugins (for plugin management)
|
|
435
435
|
configuredPlugins: import("../plugins/types.js").ResolvedPlugin[];
|
|
436
436
|
|
|
437
|
+
// Statically-sandboxed plugin entries (registered via `sandboxed: []`),
|
|
438
|
+
// surfaced through the admin plugin management API alongside configured plugins.
|
|
439
|
+
sandboxedPluginEntries: import("../emdash-runtime.js").SandboxedPluginEntry[];
|
|
440
|
+
|
|
437
441
|
// Configuration (for checking database type, auth mode, etc.)
|
|
438
442
|
config: import("./integration/runtime.js").EmDashConfig;
|
|
439
443
|
|
package/src/cli/commands/seed.ts
CHANGED
|
@@ -108,7 +108,7 @@ export const seedCommand = defineCommand({
|
|
|
108
108
|
},
|
|
109
109
|
"no-content": {
|
|
110
110
|
type: "boolean",
|
|
111
|
-
description: "Skip sample content",
|
|
111
|
+
description: "Skip sample data (content entries, bylines, taxonomy terms)",
|
|
112
112
|
default: false,
|
|
113
113
|
},
|
|
114
114
|
"on-conflict": {
|
|
@@ -34,6 +34,8 @@ export interface Props {
|
|
|
34
34
|
limit?: number;
|
|
35
35
|
/** CSS class for the container */
|
|
36
36
|
class?: string;
|
|
37
|
+
/** Inline style for the container */
|
|
38
|
+
style?: string;
|
|
37
39
|
/** CSS class for the input */
|
|
38
40
|
inputClass?: string;
|
|
39
41
|
/** CSS class for the results container */
|
|
@@ -48,6 +50,10 @@ export interface Props {
|
|
|
48
50
|
suggestMode?: boolean;
|
|
49
51
|
/** Expand input width on focus (provide collapsed and expanded widths) */
|
|
50
52
|
expandOnFocus?: { collapsed: string; expanded: string };
|
|
53
|
+
/** Search results page to navigate to when pressing Enter without a focused result */
|
|
54
|
+
searchPage?: string;
|
|
55
|
+
/** Per-collection URL templates, e.g. { posts: "/blog/:path" } */
|
|
56
|
+
routeMap?: Record<string, string>;
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
const {
|
|
@@ -57,6 +63,7 @@ const {
|
|
|
57
63
|
debounce = 300,
|
|
58
64
|
limit = 10,
|
|
59
65
|
class: className = "",
|
|
66
|
+
style: styleAttr = "",
|
|
60
67
|
inputClass = "",
|
|
61
68
|
resultsClass = "",
|
|
62
69
|
resultClass = "",
|
|
@@ -64,6 +71,8 @@ const {
|
|
|
64
71
|
autofocus = false,
|
|
65
72
|
suggestMode = false,
|
|
66
73
|
expandOnFocus,
|
|
74
|
+
searchPage = "",
|
|
75
|
+
routeMap = {},
|
|
67
76
|
} = Astro.props;
|
|
68
77
|
|
|
69
78
|
const config = {
|
|
@@ -74,11 +83,14 @@ const config = {
|
|
|
74
83
|
showSnippets,
|
|
75
84
|
suggestMode,
|
|
76
85
|
expandOnFocus: expandOnFocus ?? null,
|
|
86
|
+
searchPage,
|
|
87
|
+
routeMap,
|
|
77
88
|
};
|
|
78
89
|
---
|
|
79
90
|
|
|
80
91
|
<emdash-live-search
|
|
81
92
|
class:list={["emdash-live-search", className]}
|
|
93
|
+
style={styleAttr}
|
|
82
94
|
data-config={JSON.stringify(config)}
|
|
83
95
|
>
|
|
84
96
|
<input
|
|
@@ -109,6 +121,12 @@ const config = {
|
|
|
109
121
|
</emdash-live-search>
|
|
110
122
|
|
|
111
123
|
<script>
|
|
124
|
+
import {
|
|
125
|
+
buildLiveSearchResultUrl,
|
|
126
|
+
type LiveSearchRouteMap,
|
|
127
|
+
type LiveSearchRoutableResult,
|
|
128
|
+
} from "./live-search-routing.js";
|
|
129
|
+
|
|
112
130
|
interface SearchResult {
|
|
113
131
|
collection: string;
|
|
114
132
|
id: string;
|
|
@@ -121,6 +139,7 @@ const config = {
|
|
|
121
139
|
interface Suggestion {
|
|
122
140
|
collection: string;
|
|
123
141
|
id: string;
|
|
142
|
+
slug?: string | null;
|
|
124
143
|
title: string;
|
|
125
144
|
}
|
|
126
145
|
|
|
@@ -132,6 +151,8 @@ const config = {
|
|
|
132
151
|
showSnippets: boolean;
|
|
133
152
|
suggestMode: boolean;
|
|
134
153
|
expandOnFocus: { collapsed: string; expanded: string } | null;
|
|
154
|
+
searchPage: string;
|
|
155
|
+
routeMap: LiveSearchRouteMap;
|
|
135
156
|
}
|
|
136
157
|
|
|
137
158
|
class EmDashLiveSearch extends HTMLElement {
|
|
@@ -149,6 +170,8 @@ const config = {
|
|
|
149
170
|
showSnippets: true,
|
|
150
171
|
suggestMode: false,
|
|
151
172
|
expandOnFocus: null,
|
|
173
|
+
searchPage: "",
|
|
174
|
+
routeMap: {},
|
|
152
175
|
};
|
|
153
176
|
private debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
154
177
|
private abortController: AbortController | null = null;
|
|
@@ -268,11 +291,25 @@ const config = {
|
|
|
268
291
|
".emdash-live-search-result:focus, .emdash-live-search-result.focused"
|
|
269
292
|
) as HTMLAnchorElement | null;
|
|
270
293
|
if (focused?.href) {
|
|
294
|
+
e.preventDefault();
|
|
271
295
|
window.location.href = focused.href;
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const query = this.input?.value.trim();
|
|
300
|
+
if (query && this.config.searchPage) {
|
|
301
|
+
e.preventDefault();
|
|
302
|
+
const url = new URL(this.config.searchPage, window.location.origin);
|
|
303
|
+
url.searchParams.set("q", query);
|
|
304
|
+
window.location.href = url.toString();
|
|
272
305
|
}
|
|
273
306
|
}
|
|
274
307
|
}
|
|
275
308
|
|
|
309
|
+
private buildResultUrl(result: LiveSearchRoutableResult): string {
|
|
310
|
+
return buildLiveSearchResultUrl(result, this.config.routeMap);
|
|
311
|
+
}
|
|
312
|
+
|
|
276
313
|
private navigateResults(direction: number) {
|
|
277
314
|
if (!this.resultsList) return;
|
|
278
315
|
|
|
@@ -369,9 +406,7 @@ const config = {
|
|
|
369
406
|
const link = clone.querySelector("a");
|
|
370
407
|
|
|
371
408
|
if (link) {
|
|
372
|
-
|
|
373
|
-
const path = result.slug ?? result.id;
|
|
374
|
-
link.href = `/${result.collection}/${path}`;
|
|
409
|
+
link.href = this.buildResultUrl(result);
|
|
375
410
|
|
|
376
411
|
// Fill in title
|
|
377
412
|
const titleEl = link.querySelector(
|
|
@@ -430,7 +465,7 @@ const config = {
|
|
|
430
465
|
const link = clone.querySelector("a");
|
|
431
466
|
|
|
432
467
|
if (link) {
|
|
433
|
-
link.href =
|
|
468
|
+
link.href = this.buildResultUrl(suggestion);
|
|
434
469
|
|
|
435
470
|
const titleEl = link.querySelector(
|
|
436
471
|
".emdash-live-search-result-title"
|
|
@@ -456,6 +491,7 @@ const config = {
|
|
|
456
491
|
|
|
457
492
|
link.dataset.id = suggestion.id;
|
|
458
493
|
link.dataset.collection = suggestion.collection;
|
|
494
|
+
link.dataset.slug = suggestion.slug ?? "";
|
|
459
495
|
}
|
|
460
496
|
|
|
461
497
|
this.resultsList.appendChild(clone);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface LiveSearchRoutableResult {
|
|
2
|
+
collection: string;
|
|
3
|
+
id: string;
|
|
4
|
+
slug?: string | null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type LiveSearchRouteMap = Record<string, string>;
|
|
8
|
+
|
|
9
|
+
function replaceRouteToken(template: string, token: string, value: string): string {
|
|
10
|
+
return template.split(token).join(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function buildLiveSearchResultUrl(
|
|
14
|
+
result: LiveSearchRoutableResult,
|
|
15
|
+
routeMap: LiveSearchRouteMap = {},
|
|
16
|
+
): string {
|
|
17
|
+
const path = result.slug ?? result.id;
|
|
18
|
+
const template = routeMap[result.collection];
|
|
19
|
+
|
|
20
|
+
if (!template) {
|
|
21
|
+
return `/${result.collection}/${path}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return [
|
|
25
|
+
[":collection", result.collection],
|
|
26
|
+
[":id", result.id],
|
|
27
|
+
[":slug", result.slug ?? result.id],
|
|
28
|
+
[":path", path],
|
|
29
|
+
].reduce((url, [token, value]) => replaceRouteToken(url, token, value), template);
|
|
30
|
+
}
|
|
@@ -259,27 +259,32 @@ async function rebuildContentTaxonomies(db: Kysely<unknown>): Promise<void> {
|
|
|
259
259
|
// is load-bearing — if the translation_group seed ever changes, this needs
|
|
260
260
|
// an explicit remap *after* `rebuildTaxonomies` runs.
|
|
261
261
|
const fks = await sql<{ id: number }>`PRAGMA foreign_key_list(content_taxonomies)`.execute(db);
|
|
262
|
-
if (fks.rows.length
|
|
262
|
+
if (fks.rows.length > 0) {
|
|
263
|
+
await sql.raw(`DROP TABLE IF EXISTS "content_taxonomies_new"`).execute(db);
|
|
264
|
+
await db.schema
|
|
265
|
+
.createTable("content_taxonomies_new")
|
|
266
|
+
.addColumn("collection", "text", (c) => c.notNull())
|
|
267
|
+
.addColumn("entry_id", "text", (c) => c.notNull())
|
|
268
|
+
.addColumn("taxonomy_id", "text", (c) => c.notNull())
|
|
269
|
+
.addPrimaryKeyConstraint("content_taxonomies_pk", ["collection", "entry_id", "taxonomy_id"])
|
|
270
|
+
.execute();
|
|
263
271
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
.addColumn("entry_id", "text", (c) => c.notNull())
|
|
269
|
-
.addColumn("taxonomy_id", "text", (c) => c.notNull())
|
|
270
|
-
.addPrimaryKeyConstraint("content_taxonomies_pk", ["collection", "entry_id", "taxonomy_id"])
|
|
271
|
-
.execute();
|
|
272
|
-
|
|
273
|
-
await sql`
|
|
274
|
-
INSERT OR IGNORE INTO content_taxonomies_new (collection, entry_id, taxonomy_id)
|
|
275
|
-
SELECT collection, entry_id, taxonomy_id FROM content_taxonomies
|
|
276
|
-
`.execute(db);
|
|
272
|
+
await sql`
|
|
273
|
+
INSERT OR IGNORE INTO content_taxonomies_new (collection, entry_id, taxonomy_id)
|
|
274
|
+
SELECT collection, entry_id, taxonomy_id FROM content_taxonomies
|
|
275
|
+
`.execute(db);
|
|
277
276
|
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
await db.schema.dropTable("content_taxonomies").execute();
|
|
278
|
+
await sql`ALTER TABLE content_taxonomies_new RENAME TO content_taxonomies`.execute(db);
|
|
279
|
+
}
|
|
280
280
|
|
|
281
|
-
//
|
|
282
|
-
//
|
|
281
|
+
// Recreate the taxonomy_id index from migration 015 unconditionally, OUTSIDE
|
|
282
|
+
// the FK-presence guard above. The rebuild both strips the FK and drops the
|
|
283
|
+
// old table's indexes, but D1 auto-commits each DDL statement — so a first
|
|
284
|
+
// run that failed after the drop leaves the table with no FK and no index.
|
|
285
|
+
// The retry then finds zero FKs and skips the rebuild; if the index recreate
|
|
286
|
+
// lived inside that guard it would never run and the index would be lost for
|
|
287
|
+
// good (#1701). `IF NOT EXISTS` keeps this a no-op once present.
|
|
283
288
|
await sql`CREATE INDEX IF NOT EXISTS idx_content_taxonomies_term ON content_taxonomies(taxonomy_id)`.execute(
|
|
284
289
|
db,
|
|
285
290
|
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Restore `idx_content_taxonomies_term` on `content_taxonomies(taxonomy_id)` (#1701).
|
|
5
|
+
*
|
|
6
|
+
* Migration 015 created this index. 036's SQLite/D1 table rebuild recreated it,
|
|
7
|
+
* but the recreate was gated behind an FK-presence early-return: if a first run
|
|
8
|
+
* committed the rebuild (stripping the FK and dropping the old index) and then
|
|
9
|
+
* failed before the recreate, the retry saw zero FKs, skipped the whole body,
|
|
10
|
+
* and never restored the index — while 036 was still recorded as applied. The
|
|
11
|
+
* result was an install missing only this one index, with no forward migration
|
|
12
|
+
* to recover it (the sibling `idx_taxonomies_parent` case was fixed by 047).
|
|
13
|
+
*
|
|
14
|
+
* 036 has since been fixed to recreate the index unconditionally, so fresh
|
|
15
|
+
* installs are fine. This recovers the index on installs that hit the trap
|
|
16
|
+
* before that fix. The Postgres path in 036 alters in place and keeps its
|
|
17
|
+
* indexes, so it is unaffected; `ifNotExists` makes this a no-op there.
|
|
18
|
+
*
|
|
19
|
+
* Forward-only.
|
|
20
|
+
*/
|
|
21
|
+
export async function up(db: Kysely<unknown>): Promise<void> {
|
|
22
|
+
await db.schema
|
|
23
|
+
.createIndex("idx_content_taxonomies_term")
|
|
24
|
+
.ifNotExists()
|
|
25
|
+
.on("content_taxonomies")
|
|
26
|
+
.column("taxonomy_id")
|
|
27
|
+
.execute();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function down(db: Kysely<unknown>): Promise<void> {
|
|
31
|
+
await db.schema.dropIndex("idx_content_taxonomies_term").ifExists().execute();
|
|
32
|
+
}
|
|
@@ -49,6 +49,7 @@ import * as m044 from "./044_comment_reactions.js";
|
|
|
49
49
|
import * as m045 from "./045_taxonomy_parent_group.js";
|
|
50
50
|
import * as m046 from "./046_media_usage_index.js";
|
|
51
51
|
import * as m047 from "./047_restore_taxonomy_parent_index.js";
|
|
52
|
+
import * as m048 from "./048_restore_content_taxonomies_term_index.js";
|
|
52
53
|
|
|
53
54
|
const MIGRATIONS: Readonly<Record<string, Migration>> = Object.freeze({
|
|
54
55
|
"001_initial": m001,
|
|
@@ -97,6 +98,7 @@ const MIGRATIONS: Readonly<Record<string, Migration>> = Object.freeze({
|
|
|
97
98
|
"045_taxonomy_parent_group": m045,
|
|
98
99
|
"046_media_usage_index": m046,
|
|
99
100
|
"047_restore_taxonomy_parent_index": m047,
|
|
101
|
+
"048_restore_content_taxonomies_term_index": m048,
|
|
100
102
|
});
|
|
101
103
|
|
|
102
104
|
/** Total number of registered migrations. Exported for use in tests. */
|
package/src/search/query.ts
CHANGED
|
@@ -359,10 +359,12 @@ export async function getSuggestions(
|
|
|
359
359
|
try {
|
|
360
360
|
results = await sql<{
|
|
361
361
|
id: string;
|
|
362
|
+
slug: string | null;
|
|
362
363
|
title: string;
|
|
363
364
|
}>`
|
|
364
365
|
SELECT
|
|
365
366
|
c.id,
|
|
367
|
+
c.slug,
|
|
366
368
|
c.title
|
|
367
369
|
FROM "${sql.raw(ftsTable)}" f
|
|
368
370
|
JOIN "${sql.raw(contentTable)}" c ON f.id = c.id
|
|
@@ -389,6 +391,7 @@ export async function getSuggestions(
|
|
|
389
391
|
suggestions.push({
|
|
390
392
|
collection,
|
|
391
393
|
id: row.id,
|
|
394
|
+
slug: row.slug,
|
|
392
395
|
title: row.title,
|
|
393
396
|
});
|
|
394
397
|
}
|