emdash 0.24.1 → 0.26.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/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +12 -11
- package/dist/api/route-utils.mjs.map +1 -1
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/api/schemas/index.mjs +2 -2
- package/dist/{api-d_0wi9fW.mjs → api-BMfveMoB.mjs} +24 -20
- package/dist/api-BMfveMoB.mjs.map +1 -0
- package/dist/{apply-BE9UaWX0.mjs → apply--IVNSdXn.mjs} +19 -16
- package/dist/apply--IVNSdXn.mjs.map +1 -0
- package/dist/astro/index.d.mts +9 -9
- package/dist/astro/index.mjs +3 -2
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +8 -8
- package/dist/astro/middleware/auth.mjs +2 -2
- package/dist/astro/middleware/redirect.mjs +4 -4
- package/dist/astro/middleware.d.mts +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +99 -70
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +5 -5
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +5 -5
- 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 +6 -6
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +6 -6
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +6 -6
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +12 -12
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +12 -12
- package/dist/astro/routes/api/admin/bylines/index.mjs +12 -12
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
- package/dist/astro/routes/api/admin/comments/_id_.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/bulk.mjs +9 -9
- package/dist/astro/routes/api/admin/comments/counts.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/index.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +32 -32
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +31 -31
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +32 -32
- package/dist/astro/routes/api/admin/plugins/updates.mjs +31 -31
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +31 -31
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +31 -31
- 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 +5 -5
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
- package/dist/astro/routes/api/admin/users/index.mjs +5 -5
- 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 +5 -5
- package/dist/astro/routes/api/auth/invite/index.mjs +5 -5
- package/dist/astro/routes/api/auth/invite/register-options.mjs +5 -5
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +6 -6
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +5 -5
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +5 -5
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +5 -5
- package/dist/astro/routes/api/auth/passkey/verify.mjs +5 -5
- package/dist/astro/routes/api/auth/signup/complete.mjs +5 -5
- package/dist/astro/routes/api/auth/signup/request.mjs +6 -6
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +9 -9
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +9 -9
- 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 +6 -6
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -6
- 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 +6 -6
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +11 -11
- 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 +6 -6
- package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/index.mjs +6 -6
- package/dist/astro/routes/api/content/_collection_/trash.mjs +6 -6
- 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 +2 -2
- package/dist/astro/routes/api/import/probe.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +8 -8
- package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/media.d.mts +13 -1
- package/dist/astro/routes/api/import/wordpress/media.d.mts.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +13 -9
- package/dist/astro/routes/api/import/wordpress/media.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +8 -8
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +8 -8
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +9 -9
- package/dist/astro/routes/api/manifest.mjs +3 -3
- package/dist/astro/routes/api/mcp.mjs +36 -36
- package/dist/astro/routes/api/media/_id_/confirm.d.mts.map +1 -1
- package/dist/astro/routes/api/media/_id_/confirm.mjs +44 -8
- package/dist/astro/routes/api/media/_id_/confirm.mjs.map +1 -1
- package/dist/astro/routes/api/media/_id_.mjs +6 -6
- 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 +8 -8
- package/dist/astro/routes/api/media.mjs +22 -21
- package/dist/astro/routes/api/media.mjs.map +1 -1
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/items.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/translations.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_.mjs +8 -8
- package/dist/astro/routes/api/menus/index.mjs +8 -8
- package/dist/astro/routes/api/oauth/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 +3 -3
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
- package/dist/astro/routes/api/redirects/404s/index.mjs +8 -8
- package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
- package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
- package/dist/astro/routes/api/redirects/index.mjs +9 -9
- 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 +31 -31
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +31 -31
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +31 -31
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +31 -31
- package/dist/astro/routes/api/schema/collections/index.mjs +31 -31
- package/dist/astro/routes/api/schema/index.mjs +6 -6
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +31 -31
- package/dist/astro/routes/api/schema/orphans/index.mjs +31 -31
- package/dist/astro/routes/api/search/enable.mjs +9 -9
- package/dist/astro/routes/api/search/index.mjs +8 -8
- package/dist/astro/routes/api/search/rebuild.mjs +9 -9
- package/dist/astro/routes/api/search/stats.mjs +6 -6
- package/dist/astro/routes/api/search/suggest.mjs +8 -8
- package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
- package/dist/astro/routes/api/sections/index.mjs +8 -8
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +11 -11
- package/dist/astro/routes/api/setup/admin-verify.mjs +5 -5
- package/dist/astro/routes/api/setup/admin.mjs +5 -5
- package/dist/astro/routes/api/setup/dev-bypass.mjs +17 -17
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +20 -20
- 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 +11 -11
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -11
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -11
- package/dist/astro/routes/api/taxonomies/index.mjs +11 -11
- 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 +6 -6
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
- 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 +11 -10
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +6 -6
- package/dist/astro/types.d.mts +10 -10
- package/dist/{authorize-B__u-iZJ.mjs → authorize-BZnOGJFo.mjs} +2 -2
- package/dist/{authorize-B__u-iZJ.mjs.map → authorize-BZnOGJFo.mjs.map} +1 -1
- package/dist/{byline-C-YajfV7.mjs → byline-LL8lyqdb.mjs} +6 -6
- package/dist/{byline-C-YajfV7.mjs.map → byline-LL8lyqdb.mjs.map} +1 -1
- package/dist/{byline-fields-Ca56gaT6.d.mts → byline-fields-KD3JFRuH.d.mts} +24 -6
- package/dist/byline-fields-KD3JFRuH.d.mts.map +1 -0
- package/dist/{byline-fields-B-KXkg5R.mjs → byline-fields-eyJMblSr.mjs} +2 -2
- package/dist/{byline-fields-B-KXkg5R.mjs.map → byline-fields-eyJMblSr.mjs.map} +1 -1
- package/dist/{bylines-D4KADDAi.mjs → bylines-BmJ7Vg7J.mjs} +4 -4
- package/dist/{bylines-D4KADDAi.mjs.map → bylines-BmJ7Vg7J.mjs.map} +1 -1
- package/dist/{bylines-BMtJnPnG.mjs → bylines-DE47vP8d.mjs} +6 -6
- package/dist/{bylines-BMtJnPnG.mjs.map → bylines-DE47vP8d.mjs.map} +1 -1
- package/dist/{cache-BUJe2w6Z.mjs → cache-D9jF5bYw.mjs} +2 -2
- package/dist/{cache-BUJe2w6Z.mjs.map → cache-D9jF5bYw.mjs.map} +1 -1
- package/dist/{chunks-BHgcHh2C.mjs → chunks-OCG163rN.mjs} +2 -2
- package/dist/{chunks-BHgcHh2C.mjs.map → chunks-OCG163rN.mjs.map} +1 -1
- package/dist/cli/index.mjs +17 -17
- package/dist/{comment-BDx50EX5.mjs → comment-D9BLDpZI.mjs} +3 -3
- package/dist/{comment-BDx50EX5.mjs.map → comment-D9BLDpZI.mjs.map} +1 -1
- package/dist/{comment-reaction-Gv_pgfI3.mjs → comment-reaction-Drl9SkNu.mjs} +2 -2
- package/dist/{comment-reaction-Gv_pgfI3.mjs.map → comment-reaction-Drl9SkNu.mjs.map} +1 -1
- package/dist/{comments-CXHuQ6jI.mjs → comments-BjJ9SKGU.mjs} +3 -3
- package/dist/{comments-CXHuQ6jI.mjs.map → comments-BjJ9SKGU.mjs.map} +1 -1
- package/dist/{content-PoVGKjp0.mjs → content-ncUWWjna.mjs} +10 -8
- package/dist/content-ncUWWjna.mjs.map +1 -0
- package/dist/{context-Dvws41_A.mjs → context-C_g-iJVA.mjs} +14 -8
- package/dist/context-C_g-iJVA.mjs.map +1 -0
- package/dist/{dashboard-DsYU8JKS.mjs → dashboard-CotyqQrW.mjs} +4 -4
- package/dist/{dashboard-DsYU8JKS.mjs.map → dashboard-CotyqQrW.mjs.map} +1 -1
- package/dist/db/index.d.mts +2 -2
- package/dist/db/index.mjs +1 -1
- package/dist/{db-errors-UXB1CK42.mjs → db-errors-CK46D-ly.mjs} +1 -1
- package/dist/{db-errors-UXB1CK42.mjs.map → db-errors-CK46D-ly.mjs.map} +1 -1
- package/dist/{placeholder-B0s2mWu5.mjs → enrich-BQ0mxJRs.mjs} +61 -10
- package/dist/enrich-BQ0mxJRs.mjs.map +1 -0
- package/dist/{error-lq_fL-RS.mjs → error-rVGiqWDt.mjs} +3 -2
- package/dist/error-rVGiqWDt.mjs.map +1 -0
- package/dist/{field-defs-cache-CYYx8xlG.mjs → field-defs-cache-ljXzJCfc.mjs} +2 -2
- package/dist/{field-defs-cache-CYYx8xlG.mjs.map → field-defs-cache-ljXzJCfc.mjs.map} +1 -1
- package/dist/{fts-manager-DW_NR-Fs.mjs → fts-manager-BbCCbEKA.mjs} +2 -2
- package/dist/{fts-manager-DW_NR-Fs.mjs.map → fts-manager-BbCCbEKA.mjs.map} +1 -1
- package/dist/{index-BroXT-vD.d.mts → index-BRNabKrx.d.mts} +53 -15
- package/dist/index-BRNabKrx.d.mts.map +1 -0
- package/dist/{index-qbL02uhs.d.mts → index-Dt0OKJB4.d.mts} +2 -2
- package/dist/{index-qbL02uhs.d.mts.map → index-Dt0OKJB4.d.mts.map} +1 -1
- package/dist/index.d.mts +12 -12
- package/dist/index.mjs +43 -43
- package/dist/{load-DMFi4n1p.mjs → load-DMjXghbZ.mjs} +2 -2
- package/dist/{load-DMFi4n1p.mjs.map → load-DMjXghbZ.mjs.map} +1 -1
- package/dist/{loader-BR2SgfEc.mjs → loader-BA_zhkS_.mjs} +82 -19
- package/dist/loader-BA_zhkS_.mjs.map +1 -0
- package/dist/{manifest-schema-BWKnQYQF.mjs → manifest-schema-kPGX7VS-.mjs} +4 -1
- package/dist/manifest-schema-kPGX7VS-.mjs.map +1 -0
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +45 -2
- package/dist/media/index.d.mts.map +1 -1
- package/dist/media/index.mjs +5 -3
- package/dist/media/index.mjs.map +1 -1
- package/dist/media/local-runtime.d.mts +9 -9
- package/dist/media/local-runtime.d.mts.map +1 -1
- package/dist/media/local-runtime.mjs +17 -5
- package/dist/media/local-runtime.mjs.map +1 -1
- package/dist/{media-CTjJoJTh.mjs → media-C5t_eCnk.mjs} +4 -2
- package/dist/media-C5t_eCnk.mjs.map +1 -0
- package/dist/{media-allowlist-B77I5_bw.mjs → media-allowlist-Du8t1u6a.mjs} +2 -2
- package/dist/{media-allowlist-B77I5_bw.mjs.map → media-allowlist-Du8t1u6a.mjs.map} +1 -1
- package/dist/{menus-8O6xNcYW.mjs → menus-CBb6UrMU.mjs} +3 -3
- package/dist/{menus-8O6xNcYW.mjs.map → menus-CBb6UrMU.mjs.map} +1 -1
- package/dist/{menus-GvRSpgIA.mjs → menus-CYH09a41.mjs} +65 -41
- package/dist/menus-CYH09a41.mjs.map +1 -0
- package/dist/{mime-BTzvzJ8M.mjs → mime-CCEzze7W.mjs} +1 -1
- package/dist/{mime-BTzvzJ8M.mjs.map → mime-CCEzze7W.mjs.map} +1 -1
- package/dist/{normalize-ClbNIenm.mjs → normalize-CeglrBT9.mjs} +11 -2
- package/dist/normalize-CeglrBT9.mjs.map +1 -0
- package/dist/{object-cache-SEb2IM4Z.mjs → object-cache-CHbHv83-.mjs} +8 -4
- package/dist/object-cache-CHbHv83-.mjs.map +1 -0
- package/dist/{options-CqECG0gM.d.mts → options-41nCWqi9.d.mts} +3 -3
- package/dist/{options-CqECG0gM.d.mts.map → options-41nCWqi9.d.mts.map} +1 -1
- package/dist/page/index.d.mts +5 -2
- 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-DHI873qU.mjs → parse-BwAdS7FZ.mjs} +2 -2
- package/dist/{parse-DHI873qU.mjs.map → parse-BwAdS7FZ.mjs.map} +1 -1
- package/dist/{placeholder-QoI4gEzP.d.mts → placeholder-Cuce9U-m.d.mts} +20 -5
- package/dist/placeholder-Cuce9U-m.d.mts.map +1 -0
- package/dist/plugin-types.d.mts +5 -2
- package/dist/plugin-types.d.mts.map +1 -1
- package/dist/plugin-utils.d.mts +8 -8
- package/dist/plugins/adapt-sandbox-entry.d.mts +8 -8
- package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
- package/dist/{query-DZdlS6Cu.mjs → query-BpQb-blG.mjs} +15 -15
- package/dist/{query-DZdlS6Cu.mjs.map → query-BpQb-blG.mjs.map} +1 -1
- package/dist/{rate-limit-D1Y6VFVP.mjs → rate-limit-Dap6HMNM.mjs} +2 -2
- package/dist/{rate-limit-D1Y6VFVP.mjs.map → rate-limit-Dap6HMNM.mjs.map} +1 -1
- package/dist/{redirect-C1KVGYWe.mjs → redirect-_M0trWoo.mjs} +2 -2
- package/dist/{redirect-C1KVGYWe.mjs.map → redirect-_M0trWoo.mjs.map} +1 -1
- package/dist/{redirects-x9eFPeyi.mjs → redirects-Dcbuisoj.mjs} +2 -1
- package/dist/redirects-Dcbuisoj.mjs.map +1 -0
- package/dist/{redirects-DgnypVir.mjs → redirects-w0V9vj_j.mjs} +3 -3
- package/dist/{redirects-DgnypVir.mjs.map → redirects-w0V9vj_j.mjs.map} +1 -1
- package/dist/{registry-CJkCubOJ.mjs → registry-g8yYt4cC.mjs} +14 -4
- package/dist/registry-g8yYt4cC.mjs.map +1 -0
- 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-DPdt_Wpa.mjs} +250 -178
- package/dist/runner-DPdt_Wpa.mjs.map +1 -0
- package/dist/runtime.d.mts +9 -9
- package/dist/runtime.mjs +2 -2
- package/dist/{schema-DMjXuvNU.mjs → schema-DoLd3j2e.mjs} +5 -5
- package/dist/{schema-DMjXuvNU.mjs.map → schema-DoLd3j2e.mjs.map} +1 -1
- package/dist/{search-D1wKk3lc.mjs → search-BR0ZeZmh.mjs} +4 -4
- package/dist/{search-D1wKk3lc.mjs.map → search-BR0ZeZmh.mjs.map} +1 -1
- package/dist/{sections-CCMic8dB.mjs → sections-5J2YJPqJ.mjs} +3 -3
- package/dist/{sections-CCMic8dB.mjs.map → sections-5J2YJPqJ.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +15 -15
- package/dist/seo/index.d.mts +1 -1
- package/dist/{seo-DCEF-AVr.mjs → seo-BkhuuaaE.mjs} +25 -3
- package/dist/seo-BkhuuaaE.mjs.map +1 -0
- package/dist/{seo-3QrZ1EPT.mjs → seo-DKeXHkzE.mjs} +3 -3
- package/dist/{seo-3QrZ1EPT.mjs.map → seo-DKeXHkzE.mjs.map} +1 -1
- package/dist/{service-CQHK_10l.mjs → service-BbO2s8gT.mjs} +2 -2
- package/dist/{service-CQHK_10l.mjs.map → service-BbO2s8gT.mjs.map} +1 -1
- package/dist/{settings-C3Yi5Co3.mjs → settings-BMNr9Dmi.mjs} +3 -3
- package/dist/{settings-C3Yi5Co3.mjs.map → settings-BMNr9Dmi.mjs.map} +1 -1
- package/dist/{settings-D9rvaLuY.mjs → settings-DJeki-97.mjs} +4 -4
- package/dist/{settings-D9rvaLuY.mjs.map → settings-DJeki-97.mjs.map} +1 -1
- package/dist/{taxonomies-DhLaNJji.mjs → taxonomies-CM_fUqLU.mjs} +5 -4
- package/dist/taxonomies-CM_fUqLU.mjs.map +1 -0
- package/dist/{taxonomies-CurpLtNC.mjs → taxonomies-D13i2ctt.mjs} +76 -21
- package/dist/taxonomies-D13i2ctt.mjs.map +1 -0
- package/dist/{taxonomy-BBUlGug5.mjs → taxonomy-BU0LjdVb.mjs} +4 -4
- package/dist/{taxonomy-BBUlGug5.mjs.map → taxonomy-BU0LjdVb.mjs.map} +1 -1
- package/dist/{types-TTx8uP7V.d.mts → types-BYnDBVwe.d.mts} +27 -5
- package/dist/{types-TTx8uP7V.d.mts.map → types-BYnDBVwe.d.mts.map} +1 -1
- package/dist/{types-CTLJYMhN.d.mts → types-CNlaBFzx.d.mts} +11 -1
- package/dist/{types-CTLJYMhN.d.mts.map → types-CNlaBFzx.d.mts.map} +1 -1
- package/dist/{types-CmI1OyQg.mjs → types-CZgK3EMW.mjs} +2 -2
- package/dist/{types-CmI1OyQg.mjs.map → types-CZgK3EMW.mjs.map} +1 -1
- package/dist/{types-BWh2MjmA.d.mts → types-ETmO_jQr.d.mts} +2 -2
- package/dist/{types-BWh2MjmA.d.mts.map → types-ETmO_jQr.d.mts.map} +1 -1
- package/dist/types-tM44hEcf.mjs.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-DkG2jKCp.mjs} +3 -3
- package/dist/{user-JAuc8VUf.mjs.map → user-DkG2jKCp.mjs.map} +1 -1
- package/dist/{validate-DOFrIb-c.d.mts → validate-CG0V0wNR.d.mts} +3 -3
- package/dist/{validate-DOFrIb-c.d.mts.map → validate-CG0V0wNR.d.mts.map} +1 -1
- package/dist/{validate-BzXHWnkV.mjs → validate-CuJ1Ps9j.mjs} +2 -2
- package/dist/{validate-BzXHWnkV.mjs.map → validate-CuJ1Ps9j.mjs.map} +1 -1
- package/dist/{validation-CY1gk4Ar.mjs → validation-CwUfTdGF.mjs} +6 -6
- package/dist/{validation-CY1gk4Ar.mjs.map → validation-CwUfTdGF.mjs.map} +1 -1
- package/dist/version-BoNBItP_.mjs +7 -0
- package/dist/{version-C0JPFUG8.mjs.map → version-BoNBItP_.mjs.map} +1 -1
- package/dist/{widgets-Dri0spI4.mjs → widgets-BfOZ-ajY.mjs} +2 -2
- package/dist/{widgets-Dri0spI4.mjs.map → widgets-BfOZ-ajY.mjs.map} +1 -1
- package/dist/{zod-generator-xEHODMJf.mjs → zod-generator-gFsRuNNy.mjs} +6 -3
- package/dist/zod-generator-gFsRuNNy.mjs.map +1 -0
- package/package.json +6 -6
- package/src/api/errors.ts +1 -0
- package/src/api/handlers/content.ts +4 -4
- package/src/api/handlers/seo.ts +30 -2
- package/src/api/handlers/taxonomies.ts +5 -1
- package/src/api/schemas/schema.ts +1 -0
- package/src/astro/integration/virtual-modules.ts +15 -0
- package/src/astro/middleware.ts +14 -1
- package/src/astro/routes/api/import/wordpress/media.ts +9 -3
- package/src/astro/routes/api/media/[id]/confirm.ts +62 -2
- package/src/astro/routes/api/media.ts +17 -19
- package/src/astro/routes/sitemap-[collection].xml.ts +5 -4
- package/src/components/EmDashHead.astro +23 -3
- package/src/components/EmDashImage.astro +4 -7
- package/src/components/Image.astro +14 -4
- package/src/components/InlinePortableTextEditor.tsx +48 -1
- package/src/components/JsonLdScript.astro +9 -0
- package/src/database/migrations/036_i18n_menus_and_taxonomies.ts +16 -0
- 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/runner.ts +4 -0
- package/src/database/repositories/content.ts +8 -5
- package/src/database/repositories/media-usage.ts +444 -0
- package/src/database/repositories/media.ts +9 -1
- package/src/database/types.ts +39 -0
- package/src/emdash-runtime.ts +72 -25
- package/src/index.ts +3 -0
- package/src/loader.ts +110 -31
- package/src/media/enrich.ts +78 -0
- package/src/media/index.ts +1 -0
- package/src/media/local-runtime.ts +19 -0
- package/src/media/normalize.ts +20 -1
- package/src/media/placeholder.ts +29 -9
- package/src/media/types.ts +14 -0
- 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 +12 -0
- package/src/plugins/context.ts +8 -0
- package/src/plugins/define-plugin.ts +14 -5
- package/src/plugins/hooks.ts +66 -33
- package/src/plugins/index.ts +6 -0
- package/src/plugins/manager.ts +33 -0
- package/src/plugins/manifest-schema.ts +3 -0
- package/src/plugins/types.ts +41 -2
- package/src/schema/registry.ts +25 -0
- package/src/schema/types.ts +10 -0
- package/src/schema/zod-generator.ts +9 -1
- package/src/seed/apply.ts +7 -0
- package/src/taxonomies/index.ts +121 -18
- package/dist/api-d_0wi9fW.mjs.map +0 -1
- package/dist/apply-BE9UaWX0.mjs.map +0 -1
- package/dist/byline-fields-Ca56gaT6.d.mts.map +0 -1
- package/dist/content-PoVGKjp0.mjs.map +0 -1
- package/dist/context-Dvws41_A.mjs.map +0 -1
- package/dist/error-lq_fL-RS.mjs.map +0 -1
- package/dist/index-BroXT-vD.d.mts.map +0 -1
- package/dist/loader-BR2SgfEc.mjs.map +0 -1
- package/dist/manifest-schema-BWKnQYQF.mjs.map +0 -1
- package/dist/media-CTjJoJTh.mjs.map +0 -1
- package/dist/menus-GvRSpgIA.mjs.map +0 -1
- package/dist/normalize-ClbNIenm.mjs.map +0 -1
- package/dist/object-cache-SEb2IM4Z.mjs.map +0 -1
- package/dist/placeholder-B0s2mWu5.mjs.map +0 -1
- package/dist/placeholder-QoI4gEzP.d.mts.map +0 -1
- package/dist/redirects-x9eFPeyi.mjs.map +0 -1
- package/dist/registry-CJkCubOJ.mjs.map +0 -1
- package/dist/runner-BsquExlK.mjs.map +0 -1
- package/dist/seo-DCEF-AVr.mjs.map +0 -1
- package/dist/taxonomies-CurpLtNC.mjs.map +0 -1
- package/dist/taxonomies-DhLaNJji.mjs.map +0 -1
- package/dist/types-B-gIxFCE.d.mts.map +0 -1
- package/dist/version-C0JPFUG8.mjs +0 -7
- package/dist/zod-generator-xEHODMJf.mjs.map +0 -1
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,
|
|
@@ -32,7 +32,10 @@ import type {
|
|
|
32
32
|
ContentBeforeDeleteHandler,
|
|
33
33
|
ContentAfterDeleteHandler,
|
|
34
34
|
ContentAfterPublishHandler,
|
|
35
|
+
ContentAfterRestoreHandler,
|
|
36
|
+
ContentAfterScheduleHandler,
|
|
35
37
|
ContentAfterUnpublishHandler,
|
|
38
|
+
ContentAfterUnscheduleHandler,
|
|
36
39
|
MediaBeforeUploadHandler,
|
|
37
40
|
MediaAfterUploadHandler,
|
|
38
41
|
LifecycleHandler,
|
|
@@ -66,6 +69,9 @@ type HookNameV2 =
|
|
|
66
69
|
| "content:afterDelete"
|
|
67
70
|
| "content:afterPublish"
|
|
68
71
|
| "content:afterUnpublish"
|
|
72
|
+
| "content:afterRestore"
|
|
73
|
+
| "content:afterSchedule"
|
|
74
|
+
| "content:afterUnschedule"
|
|
69
75
|
| "media:beforeUpload"
|
|
70
76
|
| "media:afterUpload"
|
|
71
77
|
| "cron"
|
|
@@ -82,6 +88,13 @@ type HookNameV2 =
|
|
|
82
88
|
/**
|
|
83
89
|
* Map from hook name to handler type — used for type-safe hook retrieval
|
|
84
90
|
*/
|
|
91
|
+
type ContentStateChangeHookName =
|
|
92
|
+
| "content:afterPublish"
|
|
93
|
+
| "content:afterUnpublish"
|
|
94
|
+
| "content:afterRestore"
|
|
95
|
+
| "content:afterSchedule"
|
|
96
|
+
| "content:afterUnschedule";
|
|
97
|
+
|
|
85
98
|
interface HookHandlerMap {
|
|
86
99
|
"plugin:install": LifecycleHandler;
|
|
87
100
|
"plugin:activate": LifecycleHandler;
|
|
@@ -93,6 +106,9 @@ interface HookHandlerMap {
|
|
|
93
106
|
"content:afterDelete": ContentAfterDeleteHandler;
|
|
94
107
|
"content:afterPublish": ContentAfterPublishHandler;
|
|
95
108
|
"content:afterUnpublish": ContentAfterUnpublishHandler;
|
|
109
|
+
"content:afterRestore": ContentAfterRestoreHandler;
|
|
110
|
+
"content:afterSchedule": ContentAfterScheduleHandler;
|
|
111
|
+
"content:afterUnschedule": ContentAfterUnscheduleHandler;
|
|
96
112
|
"media:beforeUpload": MediaBeforeUploadHandler;
|
|
97
113
|
"media:afterUpload": MediaAfterUploadHandler;
|
|
98
114
|
cron: CronHandler;
|
|
@@ -220,6 +236,9 @@ export class HookPipeline {
|
|
|
220
236
|
this.registerPluginHook(plugin, "content:afterDelete");
|
|
221
237
|
this.registerPluginHook(plugin, "content:afterPublish");
|
|
222
238
|
this.registerPluginHook(plugin, "content:afterUnpublish");
|
|
239
|
+
this.registerPluginHook(plugin, "content:afterRestore");
|
|
240
|
+
this.registerPluginHook(plugin, "content:afterSchedule");
|
|
241
|
+
this.registerPluginHook(plugin, "content:afterUnschedule");
|
|
223
242
|
this.registerPluginHook(plugin, "media:beforeUpload");
|
|
224
243
|
this.registerPluginHook(plugin, "media:afterUpload");
|
|
225
244
|
this.registerPluginHook(plugin, "cron");
|
|
@@ -264,6 +283,9 @@ export class HookPipeline {
|
|
|
264
283
|
["content:afterDelete", "content:read"],
|
|
265
284
|
["content:afterPublish", "content:read"],
|
|
266
285
|
["content:afterUnpublish", "content:read"],
|
|
286
|
+
["content:afterRestore", "content:read"],
|
|
287
|
+
["content:afterSchedule", "content:read"],
|
|
288
|
+
["content:afterUnschedule", "content:read"],
|
|
267
289
|
// Media
|
|
268
290
|
["media:beforeUpload", "media:write"],
|
|
269
291
|
["media:afterUpload", "media:read"],
|
|
@@ -648,18 +670,19 @@ export class HookPipeline {
|
|
|
648
670
|
}
|
|
649
671
|
|
|
650
672
|
/**
|
|
651
|
-
* Run content
|
|
673
|
+
* Run content state-change hooks that all share the same event shape.
|
|
652
674
|
*/
|
|
653
|
-
async
|
|
675
|
+
private async runContentStateChangeHook(
|
|
676
|
+
name: ContentStateChangeHookName,
|
|
654
677
|
content: Record<string, unknown>,
|
|
655
678
|
collection: string,
|
|
656
679
|
): Promise<HookResult<void>[]> {
|
|
657
|
-
const hooks = this.getTypedHooks(
|
|
680
|
+
const hooks = this.getTypedHooks(name);
|
|
658
681
|
const results: HookResult<void>[] = [];
|
|
659
682
|
|
|
660
683
|
for (const hook of hooks) {
|
|
661
684
|
const { handler } = hook;
|
|
662
|
-
const event:
|
|
685
|
+
const event: ContentStateChangeEvent = { content, collection };
|
|
663
686
|
const ctx = this.getContext(hook.pluginId);
|
|
664
687
|
const start = Date.now();
|
|
665
688
|
|
|
@@ -687,6 +710,16 @@ export class HookPipeline {
|
|
|
687
710
|
return results;
|
|
688
711
|
}
|
|
689
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
|
+
|
|
690
723
|
/**
|
|
691
724
|
* Run content:afterUnpublish hooks (fire-and-forget).
|
|
692
725
|
*/
|
|
@@ -694,37 +727,37 @@ export class HookPipeline {
|
|
|
694
727
|
content: Record<string, unknown>,
|
|
695
728
|
collection: string,
|
|
696
729
|
): Promise<HookResult<void>[]> {
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
for (const hook of hooks) {
|
|
701
|
-
const { handler } = hook;
|
|
702
|
-
const event: ContentPublishStateChangeEvent = { content, collection };
|
|
703
|
-
const ctx = this.getContext(hook.pluginId);
|
|
704
|
-
const start = Date.now();
|
|
730
|
+
return this.runContentStateChangeHook("content:afterUnpublish", content, collection);
|
|
731
|
+
}
|
|
705
732
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
success: false,
|
|
716
|
-
error: error instanceof Error ? error : new Error(String(error)),
|
|
717
|
-
pluginId: hook.pluginId,
|
|
718
|
-
duration: Date.now() - start,
|
|
719
|
-
});
|
|
733
|
+
/**
|
|
734
|
+
* Run content:afterRestore hooks (fire-and-forget).
|
|
735
|
+
*/
|
|
736
|
+
async runContentAfterRestore(
|
|
737
|
+
content: Record<string, unknown>,
|
|
738
|
+
collection: string,
|
|
739
|
+
): Promise<HookResult<void>[]> {
|
|
740
|
+
return this.runContentStateChangeHook("content:afterRestore", content, collection);
|
|
741
|
+
}
|
|
720
742
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
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
|
+
}
|
|
726
752
|
|
|
727
|
-
|
|
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);
|
|
728
761
|
}
|
|
729
762
|
|
|
730
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,
|
|
@@ -148,6 +151,9 @@ export type {
|
|
|
148
151
|
ContentAfterSaveHandler,
|
|
149
152
|
ContentBeforeDeleteHandler,
|
|
150
153
|
ContentAfterDeleteHandler,
|
|
154
|
+
ContentAfterRestoreHandler,
|
|
155
|
+
ContentAfterScheduleHandler,
|
|
156
|
+
ContentAfterUnscheduleHandler,
|
|
151
157
|
MediaBeforeUploadHandler,
|
|
152
158
|
MediaAfterUploadHandler,
|
|
153
159
|
LifecycleHandler,
|
package/src/plugins/manager.ts
CHANGED
|
@@ -370,6 +370,39 @@ export class PluginManager {
|
|
|
370
370
|
return this.hookPipeline!.runContentAfterUnpublish(content, collection);
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
/**
|
|
374
|
+
* Run content:afterRestore hooks across all active plugins
|
|
375
|
+
*/
|
|
376
|
+
async runContentAfterRestore(
|
|
377
|
+
content: Record<string, unknown>,
|
|
378
|
+
collection: string,
|
|
379
|
+
): Promise<HookResult<void>[]> {
|
|
380
|
+
this.ensureInitialized();
|
|
381
|
+
return this.hookPipeline!.runContentAfterRestore(content, collection);
|
|
382
|
+
}
|
|
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
|
+
|
|
373
406
|
/**
|
|
374
407
|
* Run media:beforeUpload hooks across all active plugins
|
|
375
408
|
*/
|
|
@@ -97,6 +97,9 @@ export const HOOK_NAMES = [
|
|
|
97
97
|
"content:afterDelete",
|
|
98
98
|
"content:afterPublish",
|
|
99
99
|
"content:afterUnpublish",
|
|
100
|
+
"content:afterRestore",
|
|
101
|
+
"content:afterSchedule",
|
|
102
|
+
"content:afterUnschedule",
|
|
100
103
|
"media:beforeUpload",
|
|
101
104
|
"media:afterUpload",
|
|
102
105
|
"cron",
|
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
|
*/
|
|
@@ -791,6 +807,21 @@ export type ContentAfterUnpublishHandler = (
|
|
|
791
807
|
ctx: PluginContext,
|
|
792
808
|
) => Promise<void>;
|
|
793
809
|
|
|
810
|
+
export type ContentAfterRestoreHandler = (
|
|
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,
|
|
822
|
+
ctx: PluginContext,
|
|
823
|
+
) => Promise<void>;
|
|
824
|
+
|
|
794
825
|
export type MediaBeforeUploadHandler = (
|
|
795
826
|
event: MediaUploadEvent,
|
|
796
827
|
ctx: PluginContext,
|
|
@@ -976,6 +1007,11 @@ export interface PluginHooks {
|
|
|
976
1007
|
"content:afterUnpublish"?:
|
|
977
1008
|
| HookConfig<ContentAfterUnpublishHandler>
|
|
978
1009
|
| ContentAfterUnpublishHandler;
|
|
1010
|
+
"content:afterRestore"?: HookConfig<ContentAfterRestoreHandler> | ContentAfterRestoreHandler;
|
|
1011
|
+
"content:afterSchedule"?: HookConfig<ContentAfterScheduleHandler> | ContentAfterScheduleHandler;
|
|
1012
|
+
"content:afterUnschedule"?:
|
|
1013
|
+
| HookConfig<ContentAfterUnscheduleHandler>
|
|
1014
|
+
| ContentAfterUnscheduleHandler;
|
|
979
1015
|
|
|
980
1016
|
// Media hooks
|
|
981
1017
|
"media:beforeUpload"?: HookConfig<MediaBeforeUploadHandler> | MediaBeforeUploadHandler;
|
|
@@ -1295,6 +1331,9 @@ export interface ResolvedPluginHooks {
|
|
|
1295
1331
|
"content:afterDelete"?: ResolvedHook<ContentAfterDeleteHandler>;
|
|
1296
1332
|
"content:afterPublish"?: ResolvedHook<ContentAfterPublishHandler>;
|
|
1297
1333
|
"content:afterUnpublish"?: ResolvedHook<ContentAfterUnpublishHandler>;
|
|
1334
|
+
"content:afterRestore"?: ResolvedHook<ContentAfterRestoreHandler>;
|
|
1335
|
+
"content:afterSchedule"?: ResolvedHook<ContentAfterScheduleHandler>;
|
|
1336
|
+
"content:afterUnschedule"?: ResolvedHook<ContentAfterUnscheduleHandler>;
|
|
1298
1337
|
"media:beforeUpload"?: ResolvedHook<MediaBeforeUploadHandler>;
|
|
1299
1338
|
"media:afterUpload"?: ResolvedHook<MediaAfterUploadHandler>;
|
|
1300
1339
|
cron?: ResolvedHook<CronHandler>;
|
package/src/schema/registry.ts
CHANGED
|
@@ -530,10 +530,35 @@ export class SchemaRegistry {
|
|
|
530
530
|
// an explicit `null` clears the column.
|
|
531
531
|
const nextValidation = input.validation === undefined ? field.validation : input.validation;
|
|
532
532
|
|
|
533
|
+
// A field-type change is only safe when the underlying column type stays
|
|
534
|
+
// the same. There is no in-place column migration (only addColumn/
|
|
535
|
+
// dropColumn), so a change that would alter the SQLite column affinity
|
|
536
|
+
// (e.g. `text` TEXT -> `portableText` JSON) is rejected rather than
|
|
537
|
+
// silently rewriting only the metadata — which would leave `column_type`
|
|
538
|
+
// pointing at a column type the real `ec_*` column doesn't have (#1397).
|
|
539
|
+
let nextType = field.type;
|
|
540
|
+
let nextColumnType = field.columnType;
|
|
541
|
+
if (input.type !== undefined && input.type !== field.type) {
|
|
542
|
+
const newColumnType = FIELD_TYPE_TO_COLUMN[input.type];
|
|
543
|
+
if (newColumnType !== field.columnType) {
|
|
544
|
+
throw new SchemaError(
|
|
545
|
+
`Cannot change field "${fieldSlug}" in collection "${collectionSlug}" from type ` +
|
|
546
|
+
`"${field.type}" to "${input.type}": the underlying column type would change from ` +
|
|
547
|
+
`${field.columnType} to ${newColumnType}, which requires a manual content migration. ` +
|
|
548
|
+
`Drop and re-create the field, or migrate the column data, before changing its type.`,
|
|
549
|
+
"FIELD_TYPE_COLUMN_CHANGE",
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
nextType = input.type;
|
|
553
|
+
nextColumnType = newColumnType;
|
|
554
|
+
}
|
|
555
|
+
|
|
533
556
|
return withTransaction(this.db, async (trx) => {
|
|
534
557
|
await trx
|
|
535
558
|
.updateTable("_emdash_fields")
|
|
536
559
|
.set({
|
|
560
|
+
type: nextType,
|
|
561
|
+
column_type: nextColumnType,
|
|
537
562
|
label: input.label ?? field.label,
|
|
538
563
|
required:
|
|
539
564
|
input.required !== undefined ? (input.required ? 1 : 0) : field.required ? 1 : 0,
|
package/src/schema/types.ts
CHANGED
|
@@ -264,6 +264,16 @@ export interface CreateFieldInput {
|
|
|
264
264
|
*/
|
|
265
265
|
export interface UpdateFieldInput {
|
|
266
266
|
label?: string;
|
|
267
|
+
/**
|
|
268
|
+
* Change the field's type. Only type changes that keep the same underlying
|
|
269
|
+
* column type (per `FIELD_TYPE_TO_COLUMN`) are allowed — e.g. `string` to
|
|
270
|
+
* `slug` (both TEXT). A change that would alter the column affinity (e.g.
|
|
271
|
+
* `text` TEXT to `portableText` JSON) is rejected, because there is no
|
|
272
|
+
* in-place column migration and silently rewriting the metadata would
|
|
273
|
+
* desync `column_type` from the real `ec_*` column. Omit to keep the
|
|
274
|
+
* current type.
|
|
275
|
+
*/
|
|
276
|
+
type?: FieldType;
|
|
267
277
|
required?: boolean;
|
|
268
278
|
unique?: boolean;
|
|
269
279
|
defaultValue?: unknown;
|
|
@@ -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/seed/apply.ts
CHANGED
|
@@ -159,6 +159,7 @@ export async function applySeed(
|
|
|
159
159
|
if (existingField) {
|
|
160
160
|
await registry.updateField(collection.slug, field.slug, {
|
|
161
161
|
label: field.label,
|
|
162
|
+
type: field.type,
|
|
162
163
|
required: field.required || false,
|
|
163
164
|
unique: field.unique || false,
|
|
164
165
|
searchable: field.searchable || false,
|
|
@@ -345,6 +346,12 @@ export async function applySeed(
|
|
|
345
346
|
}
|
|
346
347
|
}
|
|
347
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();
|
|
348
355
|
}
|
|
349
356
|
|
|
350
357
|
// 6. Bylines
|
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
|
/**
|