emdash 0.25.1 → 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.d.mts +3 -3
- package/dist/api/route-utils.mjs +11 -11
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/{api-D2_sbavn.mjs → api-80kycR9o.mjs} +86 -30
- package/dist/api-80kycR9o.mjs.map +1 -0
- package/dist/{apply-Bk2mAuLn.mjs → apply-DSypk6Iu.mjs} +20 -18
- package/dist/apply-DSypk6Iu.mjs.map +1 -0
- package/dist/astro/index.d.mts +11 -10
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +12 -3
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +10 -9
- 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 +2 -9
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +86 -85
- 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 +10 -10
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +10 -10
- package/dist/astro/routes/api/admin/bylines/index.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/bulk.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/index.mjs +7 -7
- 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 +29 -29
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +29 -29
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +29 -29
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/index.mjs +29 -29
- 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 +28 -28
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +29 -29
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +28 -28
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +29 -29
- package/dist/astro/routes/api/admin/plugins/updates.mjs +28 -28
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +28 -28
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +28 -28
- 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 +7 -7
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +7 -7
- 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 +9 -9
- 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 +8 -8
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- 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 +10 -9
- package/dist/astro/routes/api/import/wordpress/execute.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/media.d.mts +10 -9
- 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 +7 -7
- 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 +6 -6
- package/dist/astro/routes/api/menus/_name_/items.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_/translations.mjs +6 -6
- package/dist/astro/routes/api/menus/_name_.mjs +6 -6
- package/dist/astro/routes/api/menus/index.mjs +6 -6
- 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 +28 -28
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +28 -28
- package/dist/astro/routes/api/schema/collections/index.mjs +28 -28
- package/dist/astro/routes/api/schema/index.mjs +6 -6
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +28 -28
- package/dist/astro/routes/api/schema/orphans/index.mjs +28 -28
- 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 +9 -9
- 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 +20 -18
- 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 +18 -18
- 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 +9 -9
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +9 -9
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +9 -9
- package/dist/astro/routes/api/taxonomies/index.mjs +9 -9
- 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 +5 -5
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +10 -9
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +5 -5
- package/dist/astro/types.d.mts +12 -10
- 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-CuxZ0i2t.mjs → authorize-C3a_zGsM.mjs} +2 -2
- package/dist/{authorize-CuxZ0i2t.mjs.map → authorize-C3a_zGsM.mjs.map} +1 -1
- package/dist/{byline-C-YajfV7.mjs → byline-DEKSVPTy.mjs} +6 -6
- package/dist/{byline-C-YajfV7.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-CPc_q2Vd.mjs → bylines-CiqgTHWF.mjs} +5 -5
- package/dist/{bylines-CPc_q2Vd.mjs.map → bylines-CiqgTHWF.mjs.map} +1 -1
- package/dist/{bylines-D4KADDAi.mjs → bylines-Ds4-otXl.mjs} +4 -4
- package/dist/{bylines-D4KADDAi.mjs.map → bylines-Ds4-otXl.mjs.map} +1 -1
- package/dist/{cache-C35VWD5D.mjs → cache-Ciu3e3AF.mjs} +2 -2
- package/dist/{cache-C35VWD5D.mjs.map → cache-Ciu3e3AF.mjs.map} +1 -1
- package/dist/{chunks-BHgcHh2C.mjs → chunks-CZFiauig.mjs} +2 -2
- package/dist/{chunks-BHgcHh2C.mjs.map → chunks-CZFiauig.mjs.map} +1 -1
- package/dist/cli/index.mjs +17 -17
- 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-BDx50EX5.mjs → comment-CH1IrFFs.mjs} +3 -3
- package/dist/{comment-BDx50EX5.mjs.map → comment-CH1IrFFs.mjs.map} +1 -1
- package/dist/{comment-reaction-Gv_pgfI3.mjs → comment-reaction-kruNY-kP.mjs} +2 -2
- package/dist/{comment-reaction-Gv_pgfI3.mjs.map → comment-reaction-kruNY-kP.mjs.map} +1 -1
- package/dist/{comments-CXHuQ6jI.mjs → comments-BUJyXbgq.mjs} +3 -3
- package/dist/{comments-CXHuQ6jI.mjs.map → comments-BUJyXbgq.mjs.map} +1 -1
- package/dist/{content-B43-YrIq.mjs → content-RmfHoWqK.mjs} +4 -4
- package/dist/{content-B43-YrIq.mjs.map → content-RmfHoWqK.mjs.map} +1 -1
- package/dist/{context-BW3N7wyt.mjs → context-CzUU_WzL.mjs} +7 -7
- package/dist/{context-BW3N7wyt.mjs.map → context-CzUU_WzL.mjs.map} +1 -1
- package/dist/{dashboard-FIe0S512.mjs → dashboard-CVyGhift.mjs} +4 -4
- package/dist/{dashboard-FIe0S512.mjs.map → dashboard-CVyGhift.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/{error-DXnK2wF4.mjs → error-BHkLZk-w.mjs} +2 -2
- package/dist/{error-DXnK2wF4.mjs.map → error-BHkLZk-w.mjs.map} +1 -1
- package/dist/{field-defs-cache-CYYx8xlG.mjs → field-defs-cache-BA-8ZPiT.mjs} +2 -2
- package/dist/{field-defs-cache-CYYx8xlG.mjs.map → field-defs-cache-BA-8ZPiT.mjs.map} +1 -1
- package/dist/{fts-manager-DW_NR-Fs.mjs → fts-manager-Db9jGavf.mjs} +2 -2
- package/dist/{fts-manager-DW_NR-Fs.mjs.map → fts-manager-Db9jGavf.mjs.map} +1 -1
- package/dist/{index-Cz6_JBL3.d.mts → index-CDZZjrLT.d.mts} +2430 -2363
- package/dist/index-CDZZjrLT.d.mts.map +1 -0
- package/dist/{index-qbL02uhs.d.mts → index-DGIjmUXQ.d.mts} +3 -3
- package/dist/{index-qbL02uhs.d.mts.map → index-DGIjmUXQ.d.mts.map} +1 -1
- package/dist/index.d.mts +16 -15
- package/dist/index.mjs +38 -38
- package/dist/{load-DMFi4n1p.mjs → load-DpHICVPh.mjs} +2 -2
- package/dist/{load-DMFi4n1p.mjs.map → load-DpHICVPh.mjs.map} +1 -1
- package/dist/{loader-DrpofRon.mjs → loader-4K37qA-y.mjs} +81 -18
- package/dist/loader-4K37qA-y.mjs.map +1 -0
- package/dist/{manifest-schema-BOfPXse0.mjs → manifest-schema-kPGX7VS-.mjs} +3 -1
- package/dist/manifest-schema-kPGX7VS-.mjs.map +1 -0
- package/dist/media/local-runtime.d.mts +11 -10
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +5 -5
- package/dist/{media-BjKxjzk8.mjs → media-C0nRRfs1.mjs} +2 -2
- package/dist/{media-BjKxjzk8.mjs.map → media-C0nRRfs1.mjs.map} +1 -1
- package/dist/{menus-CxqJ-z-N.mjs → menus-DzRyC1ID.mjs} +50 -68
- package/dist/menus-DzRyC1ID.mjs.map +1 -0
- package/dist/{menus-8O6xNcYW.mjs → menus-SL2K0xq2.mjs} +3 -3
- package/dist/{menus-8O6xNcYW.mjs.map → menus-SL2K0xq2.mjs.map} +1 -1
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-SEb2IM4Z.mjs → object-cache-CHbHv83-.mjs} +8 -4
- package/dist/object-cache-CHbHv83-.mjs.map +1 -0
- package/dist/{options-BvClpP5Q.d.mts → options-41nCWqi9.d.mts} +2 -2
- package/dist/{options-BvClpP5Q.d.mts.map → options-41nCWqi9.d.mts.map} +1 -1
- package/dist/page/index.d.mts +6 -3
- package/dist/page/index.d.mts.map +1 -1
- package/dist/page/index.mjs +3 -2
- package/dist/page/index.mjs.map +1 -1
- package/dist/{parse-DqMWHQ8x.mjs → parse-CqyZj3Hp.mjs} +2 -2
- package/dist/{parse-DqMWHQ8x.mjs.map → parse-CqyZj3Hp.mjs.map} +1 -1
- package/dist/plugin-types.d.mts +4 -2
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +10 -9
- package/dist/plugin-utils.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +10 -9
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
- package/dist/{query-34pfm02Q.mjs → query-B0M-9LYR.mjs} +14 -14
- package/dist/{query-34pfm02Q.mjs.map → query-B0M-9LYR.mjs.map} +1 -1
- package/dist/{rate-limit-CBQK4ygJ.mjs → rate-limit-BwoUdIpC.mjs} +2 -2
- package/dist/{rate-limit-CBQK4ygJ.mjs.map → rate-limit-BwoUdIpC.mjs.map} +1 -1
- package/dist/{redirect-C1KVGYWe.mjs → redirect-lMOzG04S.mjs} +2 -2
- package/dist/{redirect-C1KVGYWe.mjs.map → redirect-lMOzG04S.mjs.map} +1 -1
- package/dist/{redirects-DgnypVir.mjs → redirects-9218MmYl.mjs} +3 -3
- package/dist/{redirects-DgnypVir.mjs.map → redirects-9218MmYl.mjs.map} +1 -1
- package/dist/{registry-3aOAS4My.mjs → registry-DP-iEtdR.mjs} +4 -4
- package/dist/{registry-3aOAS4My.mjs.map → registry-DP-iEtdR.mjs.map} +1 -1
- package/dist/{runner-CEtq-6Sm.d.mts → runner-BbR3DfrL.d.mts} +2 -2
- package/dist/{runner-CEtq-6Sm.d.mts.map → runner-BbR3DfrL.d.mts.map} +1 -1
- package/dist/{runner-BsquExlK.mjs → runner-CFngB4WZ.mjs} +296 -191
- package/dist/runner-CFngB4WZ.mjs.map +1 -0
- package/dist/runtime.d.mts +10 -9
- 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-BGwx8AQY.mjs → schema-BfJ7bIXH.mjs} +5 -5
- package/dist/{schema-BGwx8AQY.mjs.map → schema-BfJ7bIXH.mjs.map} +1 -1
- package/dist/{search-Gl747zMP.mjs → search-C7t3PH1J.mjs} +6 -4
- package/dist/search-C7t3PH1J.mjs.map +1 -0
- package/dist/{sections-C-umuuLj.mjs → sections-Dm0CVX23.mjs} +3 -3
- package/dist/{sections-C-umuuLj.mjs.map → sections-Dm0CVX23.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +15 -15
- package/dist/{seo-BNzkiK_W.mjs → seo-Dd3tbY_k.mjs} +3 -3
- package/dist/{seo-BNzkiK_W.mjs.map → seo-Dd3tbY_k.mjs.map} +1 -1
- package/dist/{service-CQHK_10l.mjs → service-CTrqp_Jy.mjs} +2 -2
- package/dist/{service-CQHK_10l.mjs.map → service-CTrqp_Jy.mjs.map} +1 -1
- package/dist/{settings-C4tXRYiG.mjs → settings-BX8cWBus.mjs} +4 -4
- package/dist/{settings-C4tXRYiG.mjs.map → settings-BX8cWBus.mjs.map} +1 -1
- package/dist/{settings-fPSR6dJa.mjs → settings-CZ7ZP9cW.mjs} +3 -3
- package/dist/{settings-fPSR6dJa.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-DbAtL6m4.mjs → taxonomies-DChKcVxf.mjs} +5 -4
- package/dist/taxonomies-DChKcVxf.mjs.map +1 -0
- package/dist/{taxonomies-n8w72lLQ.mjs → taxonomies-ckPjz-6d.mjs} +75 -20
- package/dist/taxonomies-ckPjz-6d.mjs.map +1 -0
- package/dist/{taxonomy-BBUlGug5.mjs → taxonomy-Cru-he6s.mjs} +4 -4
- package/dist/{taxonomy-BBUlGug5.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-h2Cwbzi2.d.mts → types-BYnDBVwe.d.mts} +24 -5
- package/dist/{types-h2Cwbzi2.d.mts.map → types-BYnDBVwe.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-CmI1OyQg.mjs → types-DU4TSFS5.mjs} +2 -2
- package/dist/{types-CmI1OyQg.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/{types-B-gIxFCE.d.mts → types-xIfVRNLp.d.mts} +38 -1
- package/dist/types-xIfVRNLp.d.mts.map +1 -0
- package/dist/{user-JAuc8VUf.mjs → user-DgGbKL9s.mjs} +3 -3
- package/dist/{user-JAuc8VUf.mjs.map → user-DgGbKL9s.mjs.map} +1 -1
- package/dist/{validate-Va_An3qb.d.mts → validate-9ECmtEpJ.d.mts} +10 -5
- package/dist/{validate-Va_An3qb.d.mts.map → validate-9ECmtEpJ.d.mts.map} +1 -1
- package/dist/{validate-BzXHWnkV.mjs → validate-CRkcYZAR.mjs} +2 -2
- package/dist/{validate-BzXHWnkV.mjs.map → validate-CRkcYZAR.mjs.map} +1 -1
- package/dist/{validation-B6DKPTtU.mjs → validation-sR26SOwD.mjs} +5 -5
- package/dist/{validation-B6DKPTtU.mjs.map → validation-sR26SOwD.mjs.map} +1 -1
- package/dist/version-CrqhKGWn.mjs +7 -0
- package/dist/{version-DHdCA24u.mjs.map → version-CrqhKGWn.mjs.map} +1 -1
- package/dist/{widgets-C2RbFN0G.mjs → widgets-DRgtn7Cl.mjs} +2 -2
- package/dist/{widgets-C2RbFN0G.mjs.map → widgets-DRgtn7Cl.mjs.map} +1 -1
- package/dist/{zod-generator-xEHODMJf.mjs → zod-generator-C5JaV--i.mjs} +6 -3
- package/dist/zod-generator-C5JaV--i.mjs.map +1 -0
- package/package.json +8 -8
- package/src/api/handlers/content.ts +59 -16
- package/src/api/handlers/plugins.ts +77 -10
- package/src/api/handlers/taxonomies.ts +5 -1
- package/src/astro/integration/virtual-modules.ts +15 -0
- 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/routes/sitemap-[collection].xml.ts +5 -4
- package/src/astro/types.ts +4 -0
- package/src/cli/commands/seed.ts +1 -1
- package/src/components/EmDashHead.astro +23 -3
- package/src/components/JsonLdScript.astro +9 -0
- 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 +39 -18
- package/src/database/migrations/046_media_usage_index.ts +115 -0
- package/src/database/migrations/047_restore_taxonomy_parent_index.ts +29 -0
- package/src/database/migrations/048_restore_content_taxonomies_term_index.ts +32 -0
- package/src/database/migrations/runner.ts +6 -0
- package/src/database/repositories/media-usage.ts +444 -0
- package/src/database/types.ts +39 -0
- package/src/emdash-runtime.ts +61 -52
- package/src/index.ts +3 -0
- package/src/loader.ts +110 -31
- package/src/media/usage/extractor.ts +302 -0
- package/src/media/usage/types.ts +46 -0
- package/src/object-cache/index.ts +8 -2
- package/src/page/metadata.ts +23 -3
- package/src/plugin-types.ts +10 -0
- package/src/plugins/define-plugin.ts +14 -5
- package/src/plugins/hooks.ts +53 -65
- package/src/plugins/index.ts +5 -0
- package/src/plugins/manager.ts +22 -0
- package/src/plugins/manifest-schema.ts +2 -0
- package/src/plugins/types.ts +35 -3
- package/src/schema/zod-generator.ts +9 -1
- package/src/search/query.ts +3 -0
- package/src/search/types.ts +2 -0
- package/src/seed/apply.ts +8 -2
- package/src/seed/types.ts +6 -1
- package/src/taxonomies/index.ts +121 -18
- package/dist/api-D2_sbavn.mjs.map +0 -1
- package/dist/apply-Bk2mAuLn.mjs.map +0 -1
- package/dist/index-Cz6_JBL3.d.mts.map +0 -1
- package/dist/loader-DrpofRon.mjs.map +0 -1
- package/dist/manifest-schema-BOfPXse0.mjs.map +0 -1
- package/dist/menus-CxqJ-z-N.mjs.map +0 -1
- package/dist/object-cache-SEb2IM4Z.mjs.map +0 -1
- package/dist/runner-BsquExlK.mjs.map +0 -1
- package/dist/search-Gl747zMP.mjs.map +0 -1
- package/dist/taxonomies-DbAtL6m4.mjs.map +0 -1
- package/dist/taxonomies-n8w72lLQ.mjs.map +0 -1
- package/dist/types-B-gIxFCE.d.mts.map +0 -1
- package/dist/version-DHdCA24u.mjs +0 -7
- package/dist/zod-generator-xEHODMJf.mjs.map +0 -1
|
@@ -327,6 +327,36 @@ async function resolveSearchColumns(db: Kysely<Database>, collection: string): P
|
|
|
327
327
|
return columns;
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
+
/**
|
|
331
|
+
* Create a 301 auto-redirect from an entry's old URL to its new one after a
|
|
332
|
+
* slug change, using the collection's URL pattern. Shared by
|
|
333
|
+
* handleContentUpdate (direct slug edits) and handleContentPublish (slug edits
|
|
334
|
+
* staged as `_slug` in a draft revision, which only land on publish).
|
|
335
|
+
*/
|
|
336
|
+
async function createSlugChangeRedirect(
|
|
337
|
+
db: Kysely<Database>,
|
|
338
|
+
collection: string,
|
|
339
|
+
oldSlug: string,
|
|
340
|
+
newSlug: string,
|
|
341
|
+
contentId: string,
|
|
342
|
+
): Promise<void> {
|
|
343
|
+
const collectionRow = await db
|
|
344
|
+
.selectFrom("_emdash_collections")
|
|
345
|
+
.select("url_pattern")
|
|
346
|
+
.where("slug", "=", collection)
|
|
347
|
+
.executeTakeFirst();
|
|
348
|
+
|
|
349
|
+
const redirectRepo = new RedirectRepository(db);
|
|
350
|
+
await redirectRepo.createAutoRedirect(
|
|
351
|
+
collection,
|
|
352
|
+
oldSlug,
|
|
353
|
+
newSlug,
|
|
354
|
+
contentId,
|
|
355
|
+
collectionRow?.url_pattern ?? null,
|
|
356
|
+
);
|
|
357
|
+
invalidateRedirectCache();
|
|
358
|
+
}
|
|
359
|
+
|
|
330
360
|
/** Matches a date-only `YYYY-MM-DD` bound (no time component). */
|
|
331
361
|
const DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
332
362
|
|
|
@@ -865,21 +895,7 @@ export async function handleContentUpdate(
|
|
|
865
895
|
|
|
866
896
|
// Create auto-redirect when slug changes
|
|
867
897
|
if (oldSlug && body.slug) {
|
|
868
|
-
|
|
869
|
-
.selectFrom("_emdash_collections")
|
|
870
|
-
.select("url_pattern")
|
|
871
|
-
.where("slug", "=", collection)
|
|
872
|
-
.executeTakeFirst();
|
|
873
|
-
|
|
874
|
-
const redirectRepo = new RedirectRepository(trx);
|
|
875
|
-
await redirectRepo.createAutoRedirect(
|
|
876
|
-
collection,
|
|
877
|
-
oldSlug,
|
|
878
|
-
body.slug,
|
|
879
|
-
resolvedId,
|
|
880
|
-
collectionRow?.url_pattern ?? null,
|
|
881
|
-
);
|
|
882
|
-
invalidateRedirectCache();
|
|
898
|
+
await createSlugChangeRedirect(trx, collection, oldSlug, body.slug, resolvedId);
|
|
883
899
|
}
|
|
884
900
|
|
|
885
901
|
// Sync non-translatable fields to sibling locales in the same
|
|
@@ -1362,7 +1378,34 @@ export async function handleContentPublish(
|
|
|
1362
1378
|
const item = await withTransaction(db, async (trx) => {
|
|
1363
1379
|
const repo = new ContentRepository(trx);
|
|
1364
1380
|
const resolvedId = (await resolveId(repo, collection, id)) ?? id;
|
|
1365
|
-
|
|
1381
|
+
|
|
1382
|
+
// Capture the pre-publish state. For revision-supporting collections a
|
|
1383
|
+
// slug edit is staged as `_slug` in the draft revision and only lands
|
|
1384
|
+
// on the live `slug` column here, inside `repo.publish()` — it never
|
|
1385
|
+
// passes through handleContentUpdate, where slug-change auto-redirects
|
|
1386
|
+
// are normally created.
|
|
1387
|
+
const existing = await repo.findById(collection, resolvedId);
|
|
1388
|
+
|
|
1389
|
+
const published = await repo.publish(
|
|
1390
|
+
collection,
|
|
1391
|
+
resolvedId,
|
|
1392
|
+
options.publishedAt,
|
|
1393
|
+
options.requireScheduledDue,
|
|
1394
|
+
);
|
|
1395
|
+
|
|
1396
|
+
// Leave a 301 behind when publishing changed the slug of an entry that
|
|
1397
|
+
// was already published — its old URL was live and may be indexed or
|
|
1398
|
+
// linked. A first publish is excluded: a draft's URL was never public.
|
|
1399
|
+
if (
|
|
1400
|
+
existing?.status === "published" &&
|
|
1401
|
+
existing.slug &&
|
|
1402
|
+
published.slug &&
|
|
1403
|
+
existing.slug !== published.slug
|
|
1404
|
+
) {
|
|
1405
|
+
await createSlugChangeRedirect(trx, collection, existing.slug, published.slug, resolvedId);
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
return published;
|
|
1366
1409
|
});
|
|
1367
1410
|
|
|
1368
1411
|
const hasSeo = await collectionHasSeo(db, collection);
|
|
@@ -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 {
|
|
@@ -12,7 +12,7 @@ import { ulid } from "ulidx";
|
|
|
12
12
|
|
|
13
13
|
import { TaxonomyRepository } from "../../database/repositories/taxonomy.js";
|
|
14
14
|
import type { Database, TaxonomyDefTable } from "../../database/types.js";
|
|
15
|
-
import { invalidateTermCache } from "../../taxonomies/index.js";
|
|
15
|
+
import { invalidateTaxonomyDefsCache, invalidateTermCache } from "../../taxonomies/index.js";
|
|
16
16
|
import type { ApiResult } from "../types.js";
|
|
17
17
|
|
|
18
18
|
const NAME_PATTERN = /^[a-z][a-z0-9_]*$/;
|
|
@@ -290,6 +290,10 @@ export async function handleTaxonomyCreate(
|
|
|
290
290
|
})
|
|
291
291
|
.execute();
|
|
292
292
|
|
|
293
|
+
// A new def changes which taxonomies exist — drop the isolate-wide
|
|
294
|
+
// defs/names caches so this isolate reflects it immediately.
|
|
295
|
+
invalidateTaxonomyDefsCache();
|
|
296
|
+
|
|
293
297
|
const row = await db
|
|
294
298
|
.selectFrom("_emdash_taxonomy_defs")
|
|
295
299
|
.selectAll()
|
|
@@ -242,6 +242,21 @@ export function generatePluginsModule(descriptors: PluginDescriptor[]): string {
|
|
|
242
242
|
let needsAdapter = false;
|
|
243
243
|
|
|
244
244
|
descriptors.forEach((descriptor, index) => {
|
|
245
|
+
// Every `plugins: []` entry must resolve to a file/package entrypoint that
|
|
246
|
+
// can be statically imported and bundled at build time. An in-process
|
|
247
|
+
// `definePlugin({...})` result passed directly has no entrypoint; without
|
|
248
|
+
// this guard the generator emitted `import pluginDefN from "undefined";`,
|
|
249
|
+
// which failed deep in Rollup with `failed to resolve import "undefined"`
|
|
250
|
+
// (#1416). Fail fast with an actionable message instead.
|
|
251
|
+
if (!descriptor.entrypoint) {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`[emdash] Plugin "${descriptor.id}" has no \`entrypoint\`. The astro integration's ` +
|
|
254
|
+
`\`plugins: []\` requires plugins that resolve to a file/package entrypoint so they can be ` +
|
|
255
|
+
`bundled at build time; an in-process \`definePlugin({...})\` result passed directly is not ` +
|
|
256
|
+
`supported. Move the plugin into its own module and reference it via a factory that returns ` +
|
|
257
|
+
`a descriptor with an \`entrypoint\` (e.g. \`plugins: [myPlugin()]\`).`,
|
|
258
|
+
);
|
|
259
|
+
}
|
|
245
260
|
if (descriptor.format === "standard") {
|
|
246
261
|
// Standard format: import default export, wrap with adaptSandboxEntry
|
|
247
262
|
needsAdapter = true;
|
|
@@ -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
|
});
|
|
@@ -138,11 +138,12 @@ export const GET: APIRoute = async ({ params, locals, url }) => {
|
|
|
138
138
|
lines.push(" </image:image>");
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
const alternateEntries = siblings ?? (useXhtml ? [entry] : null);
|
|
142
|
+
if (useXhtml && alternateEntries) {
|
|
142
143
|
// Emit one xhtml:link per sibling (including self -- Google
|
|
143
144
|
// recommends including the page's own hreflang annotation).
|
|
144
145
|
// Siblings with unroutable locales are skipped here too.
|
|
145
|
-
for (const sib of
|
|
146
|
+
for (const sib of alternateEntries) {
|
|
146
147
|
const sibLoc = await resolveEntryUrl(sib);
|
|
147
148
|
if (sibLoc === null) continue;
|
|
148
149
|
lines.push(
|
|
@@ -154,13 +155,13 @@ export const GET: APIRoute = async ({ params, locals, url }) => {
|
|
|
154
155
|
// the first sibling with a routable URL. Stable order:
|
|
155
156
|
// rows arrive sorted by updated_at DESC from the handler.
|
|
156
157
|
const defaultSibling =
|
|
157
|
-
i18nConfig &&
|
|
158
|
+
i18nConfig && alternateEntries.find((s) => s.locale === i18nConfig.defaultLocale);
|
|
158
159
|
let xDefaultLoc: string | null = null;
|
|
159
160
|
if (defaultSibling) {
|
|
160
161
|
xDefaultLoc = await resolveEntryUrl(defaultSibling);
|
|
161
162
|
}
|
|
162
163
|
if (xDefaultLoc === null) {
|
|
163
|
-
for (const sib of
|
|
164
|
+
for (const sib of alternateEntries) {
|
|
164
165
|
const sibLoc = await resolveEntryUrl(sib);
|
|
165
166
|
if (sibLoc !== null) {
|
|
166
167
|
xDefaultLoc = sibLoc;
|
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": {
|
|
@@ -17,8 +17,14 @@
|
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
import type { PublicPageContext, PageMetadataContribution } from "../plugins/types.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
createSha256CspHash,
|
|
22
|
+
resolvePageMetadata,
|
|
23
|
+
renderPageMetadata,
|
|
24
|
+
type ResolvedPageMetadata,
|
|
25
|
+
} from "../page/metadata.js";
|
|
21
26
|
import { renderFragments } from "../page/fragments.js";
|
|
27
|
+
import JsonLdScript from "./JsonLdScript.astro";
|
|
22
28
|
import {
|
|
23
29
|
generateBaseSeoContributions,
|
|
24
30
|
generateSiteSeoContributions,
|
|
@@ -38,6 +44,7 @@ const runtime = getPageRuntime(Astro.locals as Record<string, unknown>);
|
|
|
38
44
|
let metadataHtml = "";
|
|
39
45
|
let siteIdentityHtml = "";
|
|
40
46
|
let fragmentsHtml = "";
|
|
47
|
+
let jsonLdScripts: ResolvedPageMetadata["jsonld"] = [];
|
|
41
48
|
|
|
42
49
|
if (runtime) {
|
|
43
50
|
// Run independent async loads in parallel: site settings (SEO meta
|
|
@@ -79,17 +86,30 @@ if (runtime) {
|
|
|
79
86
|
const siteContributions = generateSiteSeoContributions(siteSettings.seo);
|
|
80
87
|
const allContributions = [...pluginContributions, ...siteContributions, ...baseContributions];
|
|
81
88
|
const resolved = resolvePageMetadata(allContributions);
|
|
82
|
-
|
|
89
|
+
jsonLdScripts = resolved.jsonld;
|
|
90
|
+
metadataHtml = renderPageMetadata(resolved, { includeJsonLd: false });
|
|
83
91
|
siteIdentityHtml = renderSiteIdentity({ favicon: siteSettings.favicon });
|
|
84
92
|
fragmentsHtml = renderFragments(fragments, "head");
|
|
85
93
|
} else {
|
|
86
94
|
// No runtime (EmDash not initialized) — still render base SEO
|
|
87
95
|
const baseContributions: PageMetadataContribution[] = generateBaseSeoContributions(page);
|
|
88
96
|
const resolved = resolvePageMetadata(baseContributions);
|
|
89
|
-
|
|
97
|
+
jsonLdScripts = resolved.jsonld;
|
|
98
|
+
metadataHtml = renderPageMetadata(resolved, { includeJsonLd: false });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (Astro.csp && jsonLdScripts.length > 0) {
|
|
102
|
+
await Promise.all(
|
|
103
|
+
jsonLdScripts.map(async ({ json }) => {
|
|
104
|
+
Astro.csp?.insertScriptHash(await createSha256CspHash(json));
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
90
107
|
}
|
|
91
108
|
---
|
|
92
109
|
|
|
93
110
|
<Fragment set:html={metadataHtml} />
|
|
111
|
+
{
|
|
112
|
+
jsonLdScripts.map(({ json }) => <JsonLdScript json={json} />)
|
|
113
|
+
}
|
|
94
114
|
<Fragment set:html={siteIdentityHtml} />
|
|
95
115
|
<Fragment set:html={fragmentsHtml} />
|