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
|
@@ -22,11 +22,6 @@ import type {
|
|
|
22
22
|
PluginStorageConfig,
|
|
23
23
|
} from "./types.js";
|
|
24
24
|
|
|
25
|
-
// Plugin ID validation patterns
|
|
26
|
-
const SIMPLE_ID = /^[a-z0-9-]+$/;
|
|
27
|
-
const SCOPED_ID = /^@[a-z0-9-]+\/[a-z0-9-]+$/;
|
|
28
|
-
const SEMVER_PATTERN = /^\d+\.\d+\.\d+/;
|
|
29
|
-
|
|
30
25
|
/**
|
|
31
26
|
* Define a native EmDash plugin.
|
|
32
27
|
*
|
|
@@ -94,6 +89,20 @@ export function definePlugin<TStorage extends PluginStorageConfig>(
|
|
|
94
89
|
function defineNativePlugin<TStorage extends PluginStorageConfig>(
|
|
95
90
|
definition: PluginDefinition<TStorage>,
|
|
96
91
|
): ResolvedPlugin<TStorage> {
|
|
92
|
+
// Declared function-local (not module scope) on purpose. Under
|
|
93
|
+
// `ssr.noExternal` the worker entry can instantiate native plugins during a
|
|
94
|
+
// circular module init, reaching this function before module-scope consts
|
|
95
|
+
// initialize -> "Cannot access 'SIMPLE_ID' before initialization" -> every
|
|
96
|
+
// route 500s on Cloudflare Workers. Call-time consts evaluate after the
|
|
97
|
+
// literals are parsed, so the temporal dead zone cannot occur regardless of
|
|
98
|
+
// bundle ordering. See #1370.
|
|
99
|
+
// oxlint-disable-next-line e18e/prefer-static-regex -- call-time on purpose (see #1370)
|
|
100
|
+
const SIMPLE_ID = /^[a-z0-9-]+$/;
|
|
101
|
+
// oxlint-disable-next-line e18e/prefer-static-regex -- call-time on purpose (see #1370)
|
|
102
|
+
const SCOPED_ID = /^@[a-z0-9-]+\/[a-z0-9-]+$/;
|
|
103
|
+
// oxlint-disable-next-line e18e/prefer-static-regex -- call-time on purpose (see #1370)
|
|
104
|
+
const SEMVER_PATTERN = /^\d+\.\d+\.\d+/;
|
|
105
|
+
|
|
97
106
|
const {
|
|
98
107
|
id,
|
|
99
108
|
version,
|
package/src/plugins/hooks.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
PluginContext,
|
|
18
18
|
ContentHookEvent,
|
|
19
19
|
ContentDeleteEvent,
|
|
20
|
-
|
|
20
|
+
ContentStateChangeEvent,
|
|
21
21
|
MediaUploadEvent,
|
|
22
22
|
MediaAfterUploadEvent,
|
|
23
23
|
LifecycleEvent,
|
|
@@ -33,7 +33,9 @@ import type {
|
|
|
33
33
|
ContentAfterDeleteHandler,
|
|
34
34
|
ContentAfterPublishHandler,
|
|
35
35
|
ContentAfterRestoreHandler,
|
|
36
|
+
ContentAfterScheduleHandler,
|
|
36
37
|
ContentAfterUnpublishHandler,
|
|
38
|
+
ContentAfterUnscheduleHandler,
|
|
37
39
|
MediaBeforeUploadHandler,
|
|
38
40
|
MediaAfterUploadHandler,
|
|
39
41
|
LifecycleHandler,
|
|
@@ -68,6 +70,8 @@ type HookNameV2 =
|
|
|
68
70
|
| "content:afterPublish"
|
|
69
71
|
| "content:afterUnpublish"
|
|
70
72
|
| "content:afterRestore"
|
|
73
|
+
| "content:afterSchedule"
|
|
74
|
+
| "content:afterUnschedule"
|
|
71
75
|
| "media:beforeUpload"
|
|
72
76
|
| "media:afterUpload"
|
|
73
77
|
| "cron"
|
|
@@ -84,6 +88,13 @@ type HookNameV2 =
|
|
|
84
88
|
/**
|
|
85
89
|
* Map from hook name to handler type — used for type-safe hook retrieval
|
|
86
90
|
*/
|
|
91
|
+
type ContentStateChangeHookName =
|
|
92
|
+
| "content:afterPublish"
|
|
93
|
+
| "content:afterUnpublish"
|
|
94
|
+
| "content:afterRestore"
|
|
95
|
+
| "content:afterSchedule"
|
|
96
|
+
| "content:afterUnschedule";
|
|
97
|
+
|
|
87
98
|
interface HookHandlerMap {
|
|
88
99
|
"plugin:install": LifecycleHandler;
|
|
89
100
|
"plugin:activate": LifecycleHandler;
|
|
@@ -96,6 +107,8 @@ interface HookHandlerMap {
|
|
|
96
107
|
"content:afterPublish": ContentAfterPublishHandler;
|
|
97
108
|
"content:afterUnpublish": ContentAfterUnpublishHandler;
|
|
98
109
|
"content:afterRestore": ContentAfterRestoreHandler;
|
|
110
|
+
"content:afterSchedule": ContentAfterScheduleHandler;
|
|
111
|
+
"content:afterUnschedule": ContentAfterUnscheduleHandler;
|
|
99
112
|
"media:beforeUpload": MediaBeforeUploadHandler;
|
|
100
113
|
"media:afterUpload": MediaAfterUploadHandler;
|
|
101
114
|
cron: CronHandler;
|
|
@@ -224,6 +237,8 @@ export class HookPipeline {
|
|
|
224
237
|
this.registerPluginHook(plugin, "content:afterPublish");
|
|
225
238
|
this.registerPluginHook(plugin, "content:afterUnpublish");
|
|
226
239
|
this.registerPluginHook(plugin, "content:afterRestore");
|
|
240
|
+
this.registerPluginHook(plugin, "content:afterSchedule");
|
|
241
|
+
this.registerPluginHook(plugin, "content:afterUnschedule");
|
|
227
242
|
this.registerPluginHook(plugin, "media:beforeUpload");
|
|
228
243
|
this.registerPluginHook(plugin, "media:afterUpload");
|
|
229
244
|
this.registerPluginHook(plugin, "cron");
|
|
@@ -269,6 +284,8 @@ export class HookPipeline {
|
|
|
269
284
|
["content:afterPublish", "content:read"],
|
|
270
285
|
["content:afterUnpublish", "content:read"],
|
|
271
286
|
["content:afterRestore", "content:read"],
|
|
287
|
+
["content:afterSchedule", "content:read"],
|
|
288
|
+
["content:afterUnschedule", "content:read"],
|
|
272
289
|
// Media
|
|
273
290
|
["media:beforeUpload", "media:write"],
|
|
274
291
|
["media:afterUpload", "media:read"],
|
|
@@ -653,18 +670,19 @@ export class HookPipeline {
|
|
|
653
670
|
}
|
|
654
671
|
|
|
655
672
|
/**
|
|
656
|
-
* Run content
|
|
673
|
+
* Run content state-change hooks that all share the same event shape.
|
|
657
674
|
*/
|
|
658
|
-
async
|
|
675
|
+
private async runContentStateChangeHook(
|
|
676
|
+
name: ContentStateChangeHookName,
|
|
659
677
|
content: Record<string, unknown>,
|
|
660
678
|
collection: string,
|
|
661
679
|
): Promise<HookResult<void>[]> {
|
|
662
|
-
const hooks = this.getTypedHooks(
|
|
680
|
+
const hooks = this.getTypedHooks(name);
|
|
663
681
|
const results: HookResult<void>[] = [];
|
|
664
682
|
|
|
665
683
|
for (const hook of hooks) {
|
|
666
684
|
const { handler } = hook;
|
|
667
|
-
const event:
|
|
685
|
+
const event: ContentStateChangeEvent = { content, collection };
|
|
668
686
|
const ctx = this.getContext(hook.pluginId);
|
|
669
687
|
const start = Date.now();
|
|
670
688
|
|
|
@@ -692,6 +710,16 @@ export class HookPipeline {
|
|
|
692
710
|
return results;
|
|
693
711
|
}
|
|
694
712
|
|
|
713
|
+
/**
|
|
714
|
+
* Run content:afterPublish hooks (fire-and-forget).
|
|
715
|
+
*/
|
|
716
|
+
async runContentAfterPublish(
|
|
717
|
+
content: Record<string, unknown>,
|
|
718
|
+
collection: string,
|
|
719
|
+
): Promise<HookResult<void>[]> {
|
|
720
|
+
return this.runContentStateChangeHook("content:afterPublish", content, collection);
|
|
721
|
+
}
|
|
722
|
+
|
|
695
723
|
/**
|
|
696
724
|
* Run content:afterUnpublish hooks (fire-and-forget).
|
|
697
725
|
*/
|
|
@@ -699,37 +727,7 @@ export class HookPipeline {
|
|
|
699
727
|
content: Record<string, unknown>,
|
|
700
728
|
collection: string,
|
|
701
729
|
): Promise<HookResult<void>[]> {
|
|
702
|
-
|
|
703
|
-
const results: HookResult<void>[] = [];
|
|
704
|
-
|
|
705
|
-
for (const hook of hooks) {
|
|
706
|
-
const { handler } = hook;
|
|
707
|
-
const event: ContentPublishStateChangeEvent = { content, collection };
|
|
708
|
-
const ctx = this.getContext(hook.pluginId);
|
|
709
|
-
const start = Date.now();
|
|
710
|
-
|
|
711
|
-
try {
|
|
712
|
-
await this.executeWithTimeout(() => handler(event, ctx), hook.timeout);
|
|
713
|
-
results.push({
|
|
714
|
-
success: true,
|
|
715
|
-
pluginId: hook.pluginId,
|
|
716
|
-
duration: Date.now() - start,
|
|
717
|
-
});
|
|
718
|
-
} catch (error) {
|
|
719
|
-
results.push({
|
|
720
|
-
success: false,
|
|
721
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
722
|
-
pluginId: hook.pluginId,
|
|
723
|
-
duration: Date.now() - start,
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
if (hook.errorPolicy === "abort") {
|
|
727
|
-
throw error;
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
return results;
|
|
730
|
+
return this.runContentStateChangeHook("content:afterUnpublish", content, collection);
|
|
733
731
|
}
|
|
734
732
|
|
|
735
733
|
/**
|
|
@@ -739,37 +737,27 @@ export class HookPipeline {
|
|
|
739
737
|
content: Record<string, unknown>,
|
|
740
738
|
collection: string,
|
|
741
739
|
): Promise<HookResult<void>[]> {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
for (const hook of hooks) {
|
|
746
|
-
const { handler } = hook;
|
|
747
|
-
const event: ContentPublishStateChangeEvent = { content, collection };
|
|
748
|
-
const ctx = this.getContext(hook.pluginId);
|
|
749
|
-
const start = Date.now();
|
|
750
|
-
|
|
751
|
-
try {
|
|
752
|
-
await this.executeWithTimeout(() => handler(event, ctx), hook.timeout);
|
|
753
|
-
results.push({
|
|
754
|
-
success: true,
|
|
755
|
-
pluginId: hook.pluginId,
|
|
756
|
-
duration: Date.now() - start,
|
|
757
|
-
});
|
|
758
|
-
} catch (error) {
|
|
759
|
-
results.push({
|
|
760
|
-
success: false,
|
|
761
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
762
|
-
pluginId: hook.pluginId,
|
|
763
|
-
duration: Date.now() - start,
|
|
764
|
-
});
|
|
740
|
+
return this.runContentStateChangeHook("content:afterRestore", content, collection);
|
|
741
|
+
}
|
|
765
742
|
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
743
|
+
/**
|
|
744
|
+
* Run content:afterSchedule hooks (fire-and-forget).
|
|
745
|
+
*/
|
|
746
|
+
async runContentAfterSchedule(
|
|
747
|
+
content: Record<string, unknown>,
|
|
748
|
+
collection: string,
|
|
749
|
+
): Promise<HookResult<void>[]> {
|
|
750
|
+
return this.runContentStateChangeHook("content:afterSchedule", content, collection);
|
|
751
|
+
}
|
|
771
752
|
|
|
772
|
-
|
|
753
|
+
/**
|
|
754
|
+
* Run content:afterUnschedule hooks (fire-and-forget).
|
|
755
|
+
*/
|
|
756
|
+
async runContentAfterUnschedule(
|
|
757
|
+
content: Record<string, unknown>,
|
|
758
|
+
collection: string,
|
|
759
|
+
): Promise<HookResult<void>[]> {
|
|
760
|
+
return this.runContentStateChangeHook("content:afterUnschedule", content, collection);
|
|
773
761
|
}
|
|
774
762
|
|
|
775
763
|
// =========================================================================
|
package/src/plugins/index.ts
CHANGED
|
@@ -128,6 +128,9 @@ export type {
|
|
|
128
128
|
ContentHookEvent,
|
|
129
129
|
ContentDeleteEvent,
|
|
130
130
|
ContentPublishStateChangeEvent,
|
|
131
|
+
ContentRestoreStateChangeEvent,
|
|
132
|
+
ContentScheduleStateChangeEvent,
|
|
133
|
+
ContentStateChangeEvent,
|
|
131
134
|
MediaUploadEvent,
|
|
132
135
|
MediaAfterUploadEvent,
|
|
133
136
|
LifecycleEvent,
|
|
@@ -149,6 +152,8 @@ export type {
|
|
|
149
152
|
ContentBeforeDeleteHandler,
|
|
150
153
|
ContentAfterDeleteHandler,
|
|
151
154
|
ContentAfterRestoreHandler,
|
|
155
|
+
ContentAfterScheduleHandler,
|
|
156
|
+
ContentAfterUnscheduleHandler,
|
|
152
157
|
MediaBeforeUploadHandler,
|
|
153
158
|
MediaAfterUploadHandler,
|
|
154
159
|
LifecycleHandler,
|
package/src/plugins/manager.ts
CHANGED
|
@@ -381,6 +381,28 @@ export class PluginManager {
|
|
|
381
381
|
return this.hookPipeline!.runContentAfterRestore(content, collection);
|
|
382
382
|
}
|
|
383
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Run content:afterSchedule hooks across all active plugins
|
|
386
|
+
*/
|
|
387
|
+
async runContentAfterSchedule(
|
|
388
|
+
content: Record<string, unknown>,
|
|
389
|
+
collection: string,
|
|
390
|
+
): Promise<HookResult<void>[]> {
|
|
391
|
+
this.ensureInitialized();
|
|
392
|
+
return this.hookPipeline!.runContentAfterSchedule(content, collection);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Run content:afterUnschedule hooks across all active plugins
|
|
397
|
+
*/
|
|
398
|
+
async runContentAfterUnschedule(
|
|
399
|
+
content: Record<string, unknown>,
|
|
400
|
+
collection: string,
|
|
401
|
+
): Promise<HookResult<void>[]> {
|
|
402
|
+
this.ensureInitialized();
|
|
403
|
+
return this.hookPipeline!.runContentAfterUnschedule(content, collection);
|
|
404
|
+
}
|
|
405
|
+
|
|
384
406
|
/**
|
|
385
407
|
* Run media:beforeUpload hooks across all active plugins
|
|
386
408
|
*/
|
package/src/plugins/types.ts
CHANGED
|
@@ -725,13 +725,29 @@ export interface ContentDeleteEvent {
|
|
|
725
725
|
}
|
|
726
726
|
|
|
727
727
|
/**
|
|
728
|
-
* Content
|
|
728
|
+
* Content state-change hook event (fired after publish, unpublish, restore,
|
|
729
|
+
* schedule, or unschedule).
|
|
729
730
|
*/
|
|
730
|
-
export interface
|
|
731
|
+
export interface ContentStateChangeEvent {
|
|
731
732
|
content: Record<string, unknown>;
|
|
732
733
|
collection: string;
|
|
733
734
|
}
|
|
734
735
|
|
|
736
|
+
/**
|
|
737
|
+
* Content publish/unpublish hook event.
|
|
738
|
+
*/
|
|
739
|
+
export type ContentPublishStateChangeEvent = ContentStateChangeEvent;
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* Content restore hook event.
|
|
743
|
+
*/
|
|
744
|
+
export type ContentRestoreStateChangeEvent = ContentStateChangeEvent;
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* Content schedule/unschedule hook event.
|
|
748
|
+
*/
|
|
749
|
+
export type ContentScheduleStateChangeEvent = ContentStateChangeEvent;
|
|
750
|
+
|
|
735
751
|
/**
|
|
736
752
|
* Media hook event
|
|
737
753
|
*/
|
|
@@ -792,7 +808,17 @@ export type ContentAfterUnpublishHandler = (
|
|
|
792
808
|
) => Promise<void>;
|
|
793
809
|
|
|
794
810
|
export type ContentAfterRestoreHandler = (
|
|
795
|
-
event:
|
|
811
|
+
event: ContentRestoreStateChangeEvent,
|
|
812
|
+
ctx: PluginContext,
|
|
813
|
+
) => Promise<void>;
|
|
814
|
+
|
|
815
|
+
export type ContentAfterScheduleHandler = (
|
|
816
|
+
event: ContentScheduleStateChangeEvent,
|
|
817
|
+
ctx: PluginContext,
|
|
818
|
+
) => Promise<void>;
|
|
819
|
+
|
|
820
|
+
export type ContentAfterUnscheduleHandler = (
|
|
821
|
+
event: ContentScheduleStateChangeEvent,
|
|
796
822
|
ctx: PluginContext,
|
|
797
823
|
) => Promise<void>;
|
|
798
824
|
|
|
@@ -982,6 +1008,10 @@ export interface PluginHooks {
|
|
|
982
1008
|
| HookConfig<ContentAfterUnpublishHandler>
|
|
983
1009
|
| ContentAfterUnpublishHandler;
|
|
984
1010
|
"content:afterRestore"?: HookConfig<ContentAfterRestoreHandler> | ContentAfterRestoreHandler;
|
|
1011
|
+
"content:afterSchedule"?: HookConfig<ContentAfterScheduleHandler> | ContentAfterScheduleHandler;
|
|
1012
|
+
"content:afterUnschedule"?:
|
|
1013
|
+
| HookConfig<ContentAfterUnscheduleHandler>
|
|
1014
|
+
| ContentAfterUnscheduleHandler;
|
|
985
1015
|
|
|
986
1016
|
// Media hooks
|
|
987
1017
|
"media:beforeUpload"?: HookConfig<MediaBeforeUploadHandler> | MediaBeforeUploadHandler;
|
|
@@ -1302,6 +1332,8 @@ export interface ResolvedPluginHooks {
|
|
|
1302
1332
|
"content:afterPublish"?: ResolvedHook<ContentAfterPublishHandler>;
|
|
1303
1333
|
"content:afterUnpublish"?: ResolvedHook<ContentAfterUnpublishHandler>;
|
|
1304
1334
|
"content:afterRestore"?: ResolvedHook<ContentAfterRestoreHandler>;
|
|
1335
|
+
"content:afterSchedule"?: ResolvedHook<ContentAfterScheduleHandler>;
|
|
1336
|
+
"content:afterUnschedule"?: ResolvedHook<ContentAfterUnscheduleHandler>;
|
|
1305
1337
|
"media:beforeUpload"?: ResolvedHook<MediaBeforeUploadHandler>;
|
|
1306
1338
|
"media:afterUpload"?: ResolvedHook<MediaAfterUploadHandler>;
|
|
1307
1339
|
cron?: ResolvedHook<CronHandler>;
|
|
@@ -86,7 +86,15 @@ function getBaseSchema(type: FieldType, field: Field): ZodTypeAny {
|
|
|
86
86
|
return z.preprocess((v) => (v === 0 || v === 1 ? Boolean(v) : v), z.boolean());
|
|
87
87
|
|
|
88
88
|
case "datetime":
|
|
89
|
-
|
|
89
|
+
// Accept every value that legitimately round-trips through the admin
|
|
90
|
+
// and seeds: ISO with `Z`, ISO with a timezone offset, a naive
|
|
91
|
+
// datetime (`YYYY-MM-DDTHH:mm[:ss]` -- what `<input type="datetime-local">`
|
|
92
|
+
// and many seeds produce), and a date-only value. The admin re-sends
|
|
93
|
+
// every loaded field on autosave, so a stored naive datetime must
|
|
94
|
+
// validate or the entry becomes unsavable through its own editor
|
|
95
|
+
// (#1368; same class as #867). `z.iso.*` retains semantic validation,
|
|
96
|
+
// so impossible dates are still rejected.
|
|
97
|
+
return z.iso.datetime({ offset: true, local: true }).or(z.iso.date());
|
|
90
98
|
|
|
91
99
|
case "select": {
|
|
92
100
|
const options = field.validation?.options;
|
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
|
}
|
package/src/search/types.ts
CHANGED
package/src/seed/apply.ts
CHANGED
|
@@ -296,7 +296,7 @@ export async function applySeed(
|
|
|
296
296
|
defSeedIdMap.set(taxonomy.id, { id: defId, translationGroup: defTranslationGroup });
|
|
297
297
|
|
|
298
298
|
// Create terms (if provided)
|
|
299
|
-
if (taxonomy.terms && taxonomy.terms.length > 0) {
|
|
299
|
+
if (includeContent && taxonomy.terms && taxonomy.terms.length > 0) {
|
|
300
300
|
const termRepo = new TaxonomyRepository(db);
|
|
301
301
|
|
|
302
302
|
if (taxonomy.hierarchical) {
|
|
@@ -346,10 +346,16 @@ export async function applySeed(
|
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
348
|
}
|
|
349
|
+
|
|
350
|
+
// Seeded/updated defs change which taxonomies exist — clear the
|
|
351
|
+
// isolate-wide defs + names caches so later reads in this isolate
|
|
352
|
+
// (e.g. an auto-seed triggered mid-request) reflect them immediately.
|
|
353
|
+
const { invalidateTaxonomyDefsCache } = await import("../taxonomies/index.js");
|
|
354
|
+
invalidateTaxonomyDefsCache();
|
|
349
355
|
}
|
|
350
356
|
|
|
351
357
|
// 6. Bylines
|
|
352
|
-
if (seed.bylines) {
|
|
358
|
+
if (includeContent && seed.bylines) {
|
|
353
359
|
const bylineRepo = new BylineRepository(db);
|
|
354
360
|
for (const byline of seed.bylines) {
|
|
355
361
|
const existing = await bylineRepo.findBySlug(byline.slug);
|
package/src/seed/types.ts
CHANGED
|
@@ -288,7 +288,12 @@ export interface SeedBylineCredit {
|
|
|
288
288
|
* Options for applying a seed
|
|
289
289
|
*/
|
|
290
290
|
export interface SeedApplyOptions {
|
|
291
|
-
/**
|
|
291
|
+
/**
|
|
292
|
+
* Include sample data: content entries, bylines, and taxonomy terms
|
|
293
|
+
* (default: false). Schema and structure (collections, fields, taxonomy
|
|
294
|
+
* definitions, menus, settings, redirects, widget areas, sections) are
|
|
295
|
+
* always applied.
|
|
296
|
+
*/
|
|
292
297
|
includeContent?: boolean;
|
|
293
298
|
|
|
294
299
|
/** How to handle conflicts (default: "skip") */
|
package/src/taxonomies/index.ts
CHANGED
|
@@ -12,14 +12,16 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { resolveLocale, resolveLocaleChain } from "../i18n/resolve.js";
|
|
15
|
-
import { getDb } from "../loader.js";
|
|
15
|
+
import { getDb, resetTaxonomyNamesCache } from "../loader.js";
|
|
16
16
|
import {
|
|
17
17
|
cachedQuery,
|
|
18
18
|
CacheNamespace,
|
|
19
19
|
contentNamespace,
|
|
20
20
|
invalidateTaxonomyObjectCache,
|
|
21
|
+
isObjectCacheActive,
|
|
21
22
|
} from "../object-cache/index.js";
|
|
22
23
|
import { peekRequestCache, requestCached, setRequestCacheEntry } from "../request-cache.js";
|
|
24
|
+
import { getRequestContext } from "../request-context.js";
|
|
23
25
|
import { chunks, SQL_BATCH_SIZE } from "../utils/chunks.js";
|
|
24
26
|
import { isMissingTableError } from "../utils/db-errors.js";
|
|
25
27
|
import type { TaxonomyDef, TaxonomyTerm, TaxonomyTermRow } from "./types.js";
|
|
@@ -28,35 +30,136 @@ export interface TaxonomyQueryOptions {
|
|
|
28
30
|
locale?: string;
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
/** Invalidate cached taxonomy term data and any content that hydrates terms. */
|
|
34
|
+
export function invalidateTermCache(): void {
|
|
35
|
+
invalidateTaxonomyObjectCache();
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
39
|
+
* Worker-isolate cache for taxonomy definitions, keyed by resolved locale.
|
|
40
|
+
*
|
|
41
|
+
* Taxonomy *definitions* (the "category"/"tag" taxonomies themselves, not
|
|
42
|
+
* their terms) are read on every public render that hydrates entry terms —
|
|
43
|
+
* `getAllTermsForEntries` → `getCollectionTaxonomyNames` → `getTaxonomyDefs` —
|
|
44
|
+
* but change extremely rarely: they're created via the admin API or applied
|
|
45
|
+
* from a seed, and there is no edit/delete-def path. Caching them across the
|
|
46
|
+
* isolate lifetime drops the per-render `SELECT * FROM _emdash_taxonomy_defs`
|
|
47
|
+
* to once-per-isolate.
|
|
48
|
+
*
|
|
49
|
+
* Stored on globalThis behind a Symbol key (same pattern as
|
|
50
|
+
* `settings/index.ts`) so the bundler duplicating this module across SSR
|
|
51
|
+
* chunks can't produce two independent caches.
|
|
52
|
+
*
|
|
53
|
+
* When the distributed object cache is configured, it is authoritative and this
|
|
54
|
+
* fallback is bypassed so cross-isolate epoch invalidation cannot be undercut
|
|
55
|
+
* by stale per-isolate data on an object-cache miss.
|
|
56
|
+
*
|
|
57
|
+
* **Isolated databases bypass the cache.** Playground / DO preview requests
|
|
58
|
+
* set `requestContext.dbIsIsolated`; they point at a divergent schema, so we
|
|
59
|
+
* skip both reading and writing the global holder and fall back to the
|
|
60
|
+
* per-request cache (same precedent as `getTaxonomyNames` / byline field defs).
|
|
35
61
|
*/
|
|
36
|
-
|
|
62
|
+
interface TaxonomyDefsHolder {
|
|
63
|
+
version: number;
|
|
64
|
+
/** locale key ("*" for "all locales") → { version it was fetched at, promise }. */
|
|
65
|
+
cache: Map<string, { version: number; promise: Promise<TaxonomyDef[]> }>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const TAXONOMY_DEFS_CACHE_KEY = Symbol.for("emdash:taxonomy-defs");
|
|
69
|
+
const taxonomyDefsStore = globalThis as Record<symbol, unknown>;
|
|
70
|
+
const defsHolder: TaxonomyDefsHolder =
|
|
71
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see settings/index.ts)
|
|
72
|
+
(taxonomyDefsStore[TAXONOMY_DEFS_CACHE_KEY] as TaxonomyDefsHolder | undefined) ??
|
|
73
|
+
(() => {
|
|
74
|
+
const h: TaxonomyDefsHolder = { version: 0, cache: new Map() };
|
|
75
|
+
taxonomyDefsStore[TAXONOMY_DEFS_CACHE_KEY] = h;
|
|
76
|
+
return h;
|
|
77
|
+
})();
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Invalidate the isolate-wide taxonomy-definitions cache (and the related
|
|
81
|
+
* loader taxonomy-names cache). Called from every taxonomy-def write path
|
|
82
|
+
* (`handleTaxonomyCreate`, seed application). Other isolates refresh on their
|
|
83
|
+
* next recycle — staleness bounded by isolate lifetime.
|
|
84
|
+
*/
|
|
85
|
+
export function invalidateTaxonomyDefsCache(): void {
|
|
86
|
+
defsHolder.version++;
|
|
87
|
+
defsHolder.cache.clear();
|
|
88
|
+
resetTaxonomyNamesCache();
|
|
37
89
|
invalidateTaxonomyObjectCache();
|
|
38
90
|
}
|
|
39
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Test/internal helper: clear the per-isolate taxonomy-defs cache. Useful for
|
|
94
|
+
* unit tests that insert defs directly and need to force a refetch without
|
|
95
|
+
* going through a write path. Production code should rely on
|
|
96
|
+
* `invalidateTaxonomyDefsCache()`.
|
|
97
|
+
*/
|
|
98
|
+
export function resetTaxonomyDefsCacheForTests(): void {
|
|
99
|
+
defsHolder.version++;
|
|
100
|
+
defsHolder.cache.clear();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Fetch taxonomy definitions straight from the database (no caching).
|
|
105
|
+
*/
|
|
106
|
+
async function fetchTaxonomyDefs(locale: string | undefined): Promise<TaxonomyDef[]> {
|
|
107
|
+
const db = await getDb();
|
|
108
|
+
let query = db.selectFrom("_emdash_taxonomy_defs").selectAll();
|
|
109
|
+
if (locale !== undefined) query = query.where("locale", "=", locale);
|
|
110
|
+
const rows = await query.execute();
|
|
111
|
+
return rows.map(rowToTaxonomyDef);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Resolve taxonomy defs through the isolate fallback cache, bypassing it for
|
|
116
|
+
* isolated databases. The returned promise is cached (not the resolved value)
|
|
117
|
+
* so concurrent cold-isolate readers share one in-flight query; a rejection
|
|
118
|
+
* evicts the entry so the next caller retries.
|
|
119
|
+
*/
|
|
120
|
+
function loadTaxonomyDefs(localeKey: string, locale: string | undefined): Promise<TaxonomyDef[]> {
|
|
121
|
+
if (getRequestContext()?.dbIsIsolated === true) {
|
|
122
|
+
return fetchTaxonomyDefs(locale);
|
|
123
|
+
}
|
|
124
|
+
const existing = defsHolder.cache.get(localeKey);
|
|
125
|
+
if (existing && existing.version === defsHolder.version) {
|
|
126
|
+
return existing.promise;
|
|
127
|
+
}
|
|
128
|
+
const version = defsHolder.version;
|
|
129
|
+
const promise = fetchTaxonomyDefs(locale).catch((error: unknown) => {
|
|
130
|
+
const current = defsHolder.cache.get(localeKey);
|
|
131
|
+
if (current && current.promise === promise) {
|
|
132
|
+
defsHolder.cache.delete(localeKey);
|
|
133
|
+
}
|
|
134
|
+
throw error;
|
|
135
|
+
});
|
|
136
|
+
defsHolder.cache.set(localeKey, { version, promise });
|
|
137
|
+
return promise;
|
|
138
|
+
}
|
|
139
|
+
|
|
40
140
|
/**
|
|
41
141
|
* Get every taxonomy definition. Definitions are per-locale (one row per
|
|
42
142
|
* locale inside the same translation_group) — by default we resolve to the
|
|
43
143
|
* active locale.
|
|
144
|
+
*
|
|
145
|
+
* Two-tier cache: per-request via `requestCached` (so a single render that
|
|
146
|
+
* hydrates terms for several collections pays at most one call), then
|
|
147
|
+
* per-isolate via the global holder (so warm renders issue zero queries).
|
|
148
|
+
* The `requestCached` key is unchanged so `getTaxonomyDef`'s peek still hits.
|
|
44
149
|
*/
|
|
45
150
|
export async function getTaxonomyDefs(options: TaxonomyQueryOptions = {}): Promise<TaxonomyDef[]> {
|
|
46
151
|
const locale = resolveLocale(options.locale);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}),
|
|
59
|
-
);
|
|
152
|
+
const localeKey = locale ?? "*";
|
|
153
|
+
return requestCached(`taxonomy-defs:${localeKey}`, async () => {
|
|
154
|
+
if (await isObjectCacheActive()) {
|
|
155
|
+
return cachedQuery({
|
|
156
|
+
namespace: CacheNamespace.TAXONOMIES,
|
|
157
|
+
key: `defs:${localeKey}`,
|
|
158
|
+
load: () => fetchTaxonomyDefs(locale),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return loadTaxonomyDefs(localeKey, locale);
|
|
162
|
+
});
|
|
60
163
|
}
|
|
61
164
|
|
|
62
165
|
/**
|