emdash 0.17.2 → 0.18.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.mjs +10 -10
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/{api-B7GATEYo.mjs → api-Cs7DAACP.mjs} +12 -12
- package/dist/{api-B7GATEYo.mjs.map → api-Cs7DAACP.mjs.map} +1 -1
- package/dist/{apply-BrVqULFe.mjs → apply-BWMV4Zmw.mjs} +16 -16
- package/dist/{apply-BrVqULFe.mjs.map → apply-BWMV4Zmw.mjs.map} +1 -1
- package/dist/astro/index.d.mts +2 -2
- package/dist/astro/index.mjs +1 -1
- package/dist/astro/middleware/auth.d.mts +2 -2
- package/dist/astro/middleware/auth.mjs +2 -2
- package/dist/astro/middleware/redirect.mjs +4 -4
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +250 -83
- 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 +8 -8
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +8 -8
- package/dist/astro/routes/api/admin/bylines/index.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +7 -7
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +6 -6
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +6 -6
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/index.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +25 -25
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +26 -26
- package/dist/astro/routes/api/admin/plugins/updates.mjs +25 -25
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +25 -25
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +25 -25
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
- package/dist/astro/routes/api/admin/users/index.mjs +3 -3
- package/dist/astro/routes/api/auth/dev-bypass.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/index.mjs +3 -3
- package/dist/astro/routes/api/auth/invite/register-options.mjs +3 -3
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +4 -4
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +4 -4
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/passkey/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/signup/complete.mjs +3 -3
- package/dist/astro/routes/api/auth/signup/request.mjs +4 -4
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +6 -6
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/index.mjs +4 -4
- package/dist/astro/routes/api/content/_collection_/trash.mjs +4 -4
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +2 -2
- package/dist/astro/routes/api/import/wordpress/execute.mjs +7 -7
- 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.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +5 -5
- package/dist/astro/routes/api/manifest.mjs +3 -3
- package/dist/astro/routes/api/mcp.mjs +26 -26
- package/dist/astro/routes/api/media/_id_/confirm.mjs +4 -4
- package/dist/astro/routes/api/media/_id_.mjs +4 -4
- package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
- package/dist/astro/routes/api/media/providers/index.mjs +3 -3
- package/dist/astro/routes/api/media/upload-url.mjs +4 -4
- package/dist/astro/routes/api/media.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/items.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_/translations.mjs +5 -5
- package/dist/astro/routes/api/menus/_name_.mjs +5 -5
- package/dist/astro/routes/api/menus/index.mjs +5 -5
- package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
- package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
- package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
- package/dist/astro/routes/api/oauth/register.mjs +2 -2
- package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
- package/dist/astro/routes/api/oauth/token.mjs +2 -2
- package/dist/astro/routes/api/openapi.json.mjs +2 -2
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +3 -3
- package/dist/astro/routes/api/redirects/404s/index.mjs +6 -6
- package/dist/astro/routes/api/redirects/404s/summary.mjs +6 -6
- package/dist/astro/routes/api/redirects/_id_.mjs +7 -7
- package/dist/astro/routes/api/redirects/index.mjs +7 -7
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +25 -25
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +25 -25
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +25 -25
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +25 -25
- package/dist/astro/routes/api/schema/collections/index.mjs +25 -25
- package/dist/astro/routes/api/schema/index.mjs +6 -6
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +25 -25
- package/dist/astro/routes/api/schema/orphans/index.mjs +25 -25
- package/dist/astro/routes/api/search/enable.mjs +7 -7
- package/dist/astro/routes/api/search/index.mjs +6 -6
- package/dist/astro/routes/api/search/rebuild.mjs +7 -7
- package/dist/astro/routes/api/search/stats.mjs +6 -6
- package/dist/astro/routes/api/search/suggest.mjs +6 -6
- package/dist/astro/routes/api/sections/_slug_.mjs +6 -6
- package/dist/astro/routes/api/sections/index.mjs +6 -6
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +8 -8
- package/dist/astro/routes/api/setup/admin-verify.mjs +3 -3
- package/dist/astro/routes/api/setup/admin.mjs +3 -3
- package/dist/astro/routes/api/setup/dev-bypass.mjs +15 -15
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +16 -16
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +3 -3
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +8 -8
- package/dist/astro/routes/api/taxonomies/index.mjs +8 -8
- package/dist/astro/routes/api/themes/preview.mjs +3 -3
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +4 -4
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/index.mjs +6 -6
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +4 -4
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +4 -4
- package/dist/astro/routes/sitemap.xml.mjs +4 -4
- package/dist/astro/types.d.mts +2 -2
- package/dist/{authorize-CLTmOUyx.mjs → authorize-CotM4Yiu.mjs} +2 -2
- package/dist/{authorize-CLTmOUyx.mjs.map → authorize-CotM4Yiu.mjs.map} +1 -1
- package/dist/{byline-CAhk4FrG.mjs → byline-CWQ9aSoz.mjs} +3 -3
- package/dist/{byline-CAhk4FrG.mjs.map → byline-CWQ9aSoz.mjs.map} +1 -1
- package/dist/{byline-fields-CR5hGLMw.d.mts → byline-fields-BNy7Ng1U.d.mts} +28 -28
- package/dist/{byline-fields-CR5hGLMw.d.mts.map → byline-fields-BNy7Ng1U.d.mts.map} +1 -1
- package/dist/{bylines-DCczH3AV.mjs → bylines-BJSva1Un.mjs} +4 -4
- package/dist/{bylines-DCczH3AV.mjs.map → bylines-BJSva1Un.mjs.map} +1 -1
- package/dist/{bylines-CbrD7STW.mjs → bylines-LJMgENMI.mjs} +3 -3
- package/dist/{bylines-CbrD7STW.mjs.map → bylines-LJMgENMI.mjs.map} +1 -1
- package/dist/{cache-DIHHyPkt.mjs → cache-lZL7SgVb.mjs} +2 -2
- package/dist/{cache-DIHHyPkt.mjs.map → cache-lZL7SgVb.mjs.map} +1 -1
- package/dist/{chunks-DnnHlRG3.mjs → chunks-BU-vP9Dh.mjs} +2 -2
- package/dist/{chunks-DnnHlRG3.mjs.map → chunks-BU-vP9Dh.mjs.map} +1 -1
- package/dist/cli/index.mjs +13 -13
- package/dist/{comment-DkAfGX9E.mjs → comment-C4jVbCM8.mjs} +2 -2
- package/dist/{comment-DkAfGX9E.mjs.map → comment-C4jVbCM8.mjs.map} +1 -1
- package/dist/{comments-DLFnXs7J.mjs → comments-BTAbC0Ek.mjs} +3 -3
- package/dist/{comments-DLFnXs7J.mjs.map → comments-BTAbC0Ek.mjs.map} +1 -1
- package/dist/{content-C7aJ7keg.mjs → content-CyqOmOzm.mjs} +3 -3
- package/dist/{content-C7aJ7keg.mjs.map → content-CyqOmOzm.mjs.map} +1 -1
- package/dist/{context-Ca0HkaIh.mjs → context-DZ7bEh5-.mjs} +7 -7
- package/dist/{context-Ca0HkaIh.mjs.map → context-DZ7bEh5-.mjs.map} +1 -1
- package/dist/{dashboard-BrfLIsX1.mjs → dashboard-B5WQpNTP.mjs} +4 -4
- package/dist/{dashboard-BrfLIsX1.mjs.map → dashboard-B5WQpNTP.mjs.map} +1 -1
- package/dist/db/index.mjs +1 -1
- package/dist/{error-Bk9s3Ism.mjs → error-DJOsMVSt.mjs} +2 -2
- package/dist/{error-Bk9s3Ism.mjs.map → error-DJOsMVSt.mjs.map} +1 -1
- package/dist/{fts-manager-XpDfbIKo.mjs → fts-manager-DR1ERA0c.mjs} +2 -2
- package/dist/{fts-manager-XpDfbIKo.mjs.map → fts-manager-DR1ERA0c.mjs.map} +1 -1
- package/dist/{index-C8ciqSMJ.d.mts → index-CjKdMZ3U.d.mts} +4 -4
- package/dist/{index-C8ciqSMJ.d.mts.map → index-CjKdMZ3U.d.mts.map} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +34 -34
- package/dist/{load-CF5oETkh.mjs → load-6ZrRhepW.mjs} +2 -2
- package/dist/{load-CF5oETkh.mjs.map → load-6ZrRhepW.mjs.map} +1 -1
- package/dist/{loader-BxyvbrZP.mjs → loader-Dyx8dhFV.mjs} +3 -3
- package/dist/{loader-BxyvbrZP.mjs.map → loader-Dyx8dhFV.mjs.map} +1 -1
- package/dist/media/local-runtime.d.mts +2 -2
- package/dist/media/local-runtime.mjs +4 -4
- package/dist/{media-Cyz5BhSN.mjs → media-C-oovGCG.mjs} +2 -2
- package/dist/{media-Cyz5BhSN.mjs.map → media-C-oovGCG.mjs.map} +1 -1
- package/dist/{menus-CIdZ_Q6U.mjs → menus-BKkxXCmd.mjs} +30 -11
- package/dist/menus-BKkxXCmd.mjs.map +1 -0
- package/dist/{menus-PFp8FDuO.mjs → menus-DugoYwTX.mjs} +2 -2
- package/dist/{menus-PFp8FDuO.mjs.map → menus-DugoYwTX.mjs.map} +1 -1
- package/dist/{parse-B-K21lvm.mjs → parse-BBkFmLVr.mjs} +2 -2
- package/dist/{parse-B-K21lvm.mjs.map → parse-BBkFmLVr.mjs.map} +1 -1
- package/dist/plugin-utils.d.mts +2 -2
- package/dist/plugins/adapt-sandbox-entry.d.mts +2 -2
- package/dist/{query-Cc649nDl.mjs → query-Ctlq1aOk.mjs} +10 -10
- package/dist/{query-Cc649nDl.mjs.map → query-Ctlq1aOk.mjs.map} +1 -1
- package/dist/{rate-limit-BI1OdpQH.mjs → rate-limit-CH6W6ikK.mjs} +2 -2
- package/dist/{rate-limit-BI1OdpQH.mjs.map → rate-limit-CH6W6ikK.mjs.map} +1 -1
- package/dist/{redirect-C-FeA4j9.mjs → redirect-C6tJA7tk.mjs} +2 -2
- package/dist/{redirect-C-FeA4j9.mjs.map → redirect-C6tJA7tk.mjs.map} +1 -1
- package/dist/{redirects-C1UgU9E0.mjs → redirects-CacE9eQa.mjs} +3 -3
- package/dist/{redirects-C1UgU9E0.mjs.map → redirects-CacE9eQa.mjs.map} +1 -1
- package/dist/{registry-C-T_PWgp.mjs → registry-CIDxZbhh.mjs} +4 -4
- package/dist/{registry-C-T_PWgp.mjs.map → registry-CIDxZbhh.mjs.map} +1 -1
- package/dist/runner-DM1yR5qd.d.mts.map +1 -1
- package/dist/{runner-BiuUfx-V.mjs → runner-pt6Wl-l-.mjs} +8 -3
- package/dist/{runner-BiuUfx-V.mjs.map → runner-pt6Wl-l-.mjs.map} +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.mjs +2 -2
- package/dist/{schema-BpCJh2lU.mjs → schema-B4tk0HAG.mjs} +4 -4
- package/dist/{schema-BpCJh2lU.mjs.map → schema-B4tk0HAG.mjs.map} +1 -1
- package/dist/{search-BrF7k0Ho.mjs → search-f-fNfwab.mjs} +4 -4
- package/dist/{search-BrF7k0Ho.mjs.map → search-f-fNfwab.mjs.map} +1 -1
- package/dist/{sections-8DEa-dWt.mjs → sections-biElLfT9.mjs} +3 -3
- package/dist/{sections-8DEa-dWt.mjs.map → sections-biElLfT9.mjs.map} +1 -1
- package/dist/seed/index.mjs +13 -13
- package/dist/{seo-CKr7pLfA.mjs → seo-BR39kvTF.mjs} +2 -2
- package/dist/{seo-CKr7pLfA.mjs.map → seo-BR39kvTF.mjs.map} +1 -1
- package/dist/{service-9P2cdyR_.mjs → service-BhR2acnc.mjs} +2 -2
- package/dist/{service-9P2cdyR_.mjs.map → service-BhR2acnc.mjs.map} +1 -1
- package/dist/{settings-DYVzINdn.mjs → settings-D_NJvjgN.mjs} +3 -3
- package/dist/{settings-DYVzINdn.mjs.map → settings-D_NJvjgN.mjs.map} +1 -1
- package/dist/{settings-Jro4YcUb.mjs → settings-b5zW1R1T.mjs} +3 -3
- package/dist/{settings-Jro4YcUb.mjs.map → settings-b5zW1R1T.mjs.map} +1 -1
- package/dist/{taxonomies-CGD6y79Q.mjs → taxonomies-Crtzy4MT.mjs} +8 -7
- package/dist/taxonomies-Crtzy4MT.mjs.map +1 -0
- package/dist/{taxonomies-C0bVme_m.mjs → taxonomies-Mhn9rjTQ.mjs} +4 -4
- package/dist/{taxonomies-C0bVme_m.mjs.map → taxonomies-Mhn9rjTQ.mjs.map} +1 -1
- package/dist/{taxonomy-Db5xwphL.mjs → taxonomy-DTZrIQpi.mjs} +3 -3
- package/dist/{taxonomy-Db5xwphL.mjs.map → taxonomy-DTZrIQpi.mjs.map} +1 -1
- package/dist/{types-CfyYQ7eY.mjs → types-K3MDsxpy.mjs} +2 -2
- package/dist/{types-CfyYQ7eY.mjs.map → types-K3MDsxpy.mjs.map} +1 -1
- package/dist/{user-tLdHUEXV.mjs → user-DzEUl5zA.mjs} +2 -2
- package/dist/{user-tLdHUEXV.mjs.map → user-DzEUl5zA.mjs.map} +1 -1
- package/dist/{validate-DWmnRg6E.mjs → validate-JCXcsqiY.mjs} +2 -2
- package/dist/{validate-DWmnRg6E.mjs.map → validate-JCXcsqiY.mjs.map} +1 -1
- package/dist/{validation-BQ_TP-On.mjs → validation-Bq-VyKJg.mjs} +5 -5
- package/dist/{validation-BQ_TP-On.mjs.map → validation-Bq-VyKJg.mjs.map} +1 -1
- package/dist/version-CnS-Cr8A.mjs +7 -0
- package/dist/{version-CgcnMvqS.mjs.map → version-CnS-Cr8A.mjs.map} +1 -1
- package/dist/{widgets-DzlINGI6.mjs → widgets-Bap1eS1X.mjs} +2 -2
- package/dist/{widgets-DzlINGI6.mjs.map → widgets-Bap1eS1X.mjs.map} +1 -1
- package/dist/{zod-generator-MMm56Prt.mjs → zod-generator-BSDpkqSH.mjs} +4 -3
- package/dist/zod-generator-BSDpkqSH.mjs.map +1 -0
- package/package.json +7 -7
- package/src/astro/middleware/stream-end-metrics.ts +96 -0
- package/src/astro/middleware.ts +80 -32
- package/src/components/EmDashImage.astro +1 -0
- package/src/database/migrations/runner.ts +7 -2
- package/src/emdash-runtime.ts +177 -126
- package/src/menus/index.ts +27 -9
- package/src/plugins/hooks.ts +35 -6
- package/src/plugins/manager.ts +1 -0
- package/src/schema/zod-generator.ts +6 -2
- package/src/taxonomies/index.ts +12 -8
- package/src/utils/init-lock.ts +143 -0
- package/dist/menus-CIdZ_Q6U.mjs.map +0 -1
- package/dist/taxonomies-CGD6y79Q.mjs.map +0 -1
- package/dist/version-CgcnMvqS.mjs +0 -7
- package/dist/zod-generator-MMm56Prt.mjs.map +0 -1
package/src/plugins/hooks.ts
CHANGED
|
@@ -1297,6 +1297,13 @@ export interface ExclusiveHookResolutionOptions {
|
|
|
1297
1297
|
isActive: (pluginId: string) => boolean;
|
|
1298
1298
|
/** Read an option value from persistent storage. */
|
|
1299
1299
|
getOption: (key: string) => Promise<string | null>;
|
|
1300
|
+
/**
|
|
1301
|
+
* Batch-read option values for many keys in a single round trip.
|
|
1302
|
+
* When provided, resolution reads all current selections through this
|
|
1303
|
+
* instead of one getOption() call per hook. Keys absent from the
|
|
1304
|
+
* returned map are treated as unset.
|
|
1305
|
+
*/
|
|
1306
|
+
getOptions?: (keys: string[]) => Promise<ReadonlyMap<string, string>>;
|
|
1300
1307
|
/** Write an option value to persistent storage. */
|
|
1301
1308
|
setOption: (key: string, value: string) => Promise<void>;
|
|
1302
1309
|
/** Delete an option from persistent storage. */
|
|
@@ -1322,8 +1329,26 @@ const EXCLUSIVE_HOOK_KEY_PREFIX = "emdash:exclusive_hook:";
|
|
|
1322
1329
|
* 5. If multiple providers and no hint → leave unselected (admin must choose).
|
|
1323
1330
|
*/
|
|
1324
1331
|
export async function resolveExclusiveHooks(opts: ExclusiveHookResolutionOptions): Promise<void> {
|
|
1325
|
-
const { pipeline, isActive, getOption, setOption, deleteOption, preferredHints } =
|
|
1332
|
+
const { pipeline, isActive, getOption, getOptions, setOption, deleteOption, preferredHints } =
|
|
1333
|
+
opts;
|
|
1326
1334
|
const exclusiveHookNames = pipeline.getRegisteredExclusiveHooks();
|
|
1335
|
+
if (exclusiveHookNames.length === 0) return;
|
|
1336
|
+
|
|
1337
|
+
// Batch-read current selections in one round trip when the caller
|
|
1338
|
+
// provides a batch reader (1 query instead of N sequential gets).
|
|
1339
|
+
let batchedSelections: ReadonlyMap<string, string> | undefined;
|
|
1340
|
+
if (getOptions) {
|
|
1341
|
+
try {
|
|
1342
|
+
batchedSelections = await getOptions(
|
|
1343
|
+
exclusiveHookNames.map((hookName) => `${EXCLUSIVE_HOOK_KEY_PREFIX}${hookName}`),
|
|
1344
|
+
);
|
|
1345
|
+
} catch {
|
|
1346
|
+
// Options table may not be ready. Matches the per-key tolerance
|
|
1347
|
+
// below: every hook's read would fail, so resolution is skipped
|
|
1348
|
+
// entirely without touching any selection.
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1327
1352
|
|
|
1328
1353
|
for (const hookName of exclusiveHookNames) {
|
|
1329
1354
|
const providers = pipeline.getExclusiveHookProviders(hookName);
|
|
@@ -1333,11 +1358,15 @@ export async function resolveExclusiveHooks(opts: ExclusiveHookResolutionOptions
|
|
|
1333
1358
|
|
|
1334
1359
|
const key = `${EXCLUSIVE_HOOK_KEY_PREFIX}${hookName}`;
|
|
1335
1360
|
let currentSelection: string | null = null;
|
|
1336
|
-
|
|
1337
|
-
currentSelection =
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1361
|
+
if (batchedSelections) {
|
|
1362
|
+
currentSelection = batchedSelections.get(key) ?? null;
|
|
1363
|
+
} else {
|
|
1364
|
+
try {
|
|
1365
|
+
currentSelection = await getOption(key);
|
|
1366
|
+
} catch {
|
|
1367
|
+
// Options table may not be ready
|
|
1368
|
+
continue;
|
|
1369
|
+
}
|
|
1341
1370
|
}
|
|
1342
1371
|
|
|
1343
1372
|
// If selection exists and the plugin is still active → keep it
|
package/src/plugins/manager.ts
CHANGED
|
@@ -544,6 +544,7 @@ export class PluginManager {
|
|
|
544
544
|
pipeline: this.hookPipeline!,
|
|
545
545
|
isActive: (pluginId) => this.isActive(pluginId),
|
|
546
546
|
getOption: (key) => optionsRepo.get<string>(key),
|
|
547
|
+
getOptions: (keys) => optionsRepo.getMany<string>(keys),
|
|
547
548
|
setOption: (key, value) => optionsRepo.set(key, value),
|
|
548
549
|
deleteOption: async (key) => {
|
|
549
550
|
await optionsRepo.delete(key);
|
|
@@ -288,6 +288,9 @@ export function generateTypeScript(collection: CollectionWithFields): string {
|
|
|
288
288
|
lines.push(` publishedAt: Date | null;`);
|
|
289
289
|
// Bylines are eagerly loaded by getEmDashCollection/getEmDashEntry
|
|
290
290
|
lines.push(` bylines?: ContentBylineCredit[];`);
|
|
291
|
+
// Taxonomy terms are eagerly loaded by getEmDashCollection/getEmDashEntry,
|
|
292
|
+
// keyed by taxonomy name (e.g. data.terms?.tag)
|
|
293
|
+
lines.push(` terms?: Record<string, TaxonomyTerm[]>;`);
|
|
291
294
|
lines.push(`}`);
|
|
292
295
|
|
|
293
296
|
return lines.join("\n");
|
|
@@ -312,8 +315,9 @@ export function generateTypesFile(collections: CollectionWithFields[]): string {
|
|
|
312
315
|
c.fields.some((f) => f.type === "portableText"),
|
|
313
316
|
);
|
|
314
317
|
|
|
315
|
-
// Build imports - ContentBylineCredit
|
|
316
|
-
|
|
318
|
+
// Build imports - ContentBylineCredit and TaxonomyTerm are always needed
|
|
319
|
+
// for the hydrated bylines/terms fields
|
|
320
|
+
const imports = ["ContentBylineCredit", "TaxonomyTerm"];
|
|
317
321
|
if (needsPortableText) {
|
|
318
322
|
imports.push("PortableTextBlock");
|
|
319
323
|
}
|
package/src/taxonomies/index.ts
CHANGED
|
@@ -189,13 +189,6 @@ export async function getTerm(
|
|
|
189
189
|
|
|
190
190
|
if (!row) return null;
|
|
191
191
|
|
|
192
|
-
const countResult = await db
|
|
193
|
-
.selectFrom("content_taxonomies")
|
|
194
|
-
.select((eb) => eb.fn.count<number>("entry_id").as("count"))
|
|
195
|
-
.where("taxonomy_id", "=", row.translation_group ?? row.id)
|
|
196
|
-
.executeTakeFirst();
|
|
197
|
-
const count = countResult?.count ?? 0;
|
|
198
|
-
|
|
199
192
|
let childrenQuery = db
|
|
200
193
|
.selectFrom("taxonomies")
|
|
201
194
|
.selectAll()
|
|
@@ -203,7 +196,18 @@ export async function getTerm(
|
|
|
203
196
|
.orderBy("label", "asc");
|
|
204
197
|
const termLocale = row.locale;
|
|
205
198
|
if (termLocale) childrenQuery = childrenQuery.where("locale", "=", termLocale);
|
|
206
|
-
|
|
199
|
+
|
|
200
|
+
// The usage-count and children queries both depend only on the term row,
|
|
201
|
+
// so run them concurrently to save a round trip on remote databases.
|
|
202
|
+
const [countResult, childRows] = await Promise.all([
|
|
203
|
+
db
|
|
204
|
+
.selectFrom("content_taxonomies")
|
|
205
|
+
.select((eb) => eb.fn.count<number>("entry_id").as("count"))
|
|
206
|
+
.where("taxonomy_id", "=", row.translation_group ?? row.id)
|
|
207
|
+
.executeTakeFirst(),
|
|
208
|
+
childrenQuery.execute(),
|
|
209
|
+
]);
|
|
210
|
+
const count = countResult?.count ?? 0;
|
|
207
211
|
|
|
208
212
|
const children = childRows.map<TaxonomyTerm>((child) => ({
|
|
209
213
|
id: child.id,
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reclaimable initialization lock for isolate-lifetime singletons.
|
|
3
|
+
*
|
|
4
|
+
* Guards "first request initializes, everyone else waits" sections
|
|
5
|
+
* (runtime creation, database init) against a workerd failure mode: if the
|
|
6
|
+
* request that owns the initialization is cancelled mid-await (client
|
|
7
|
+
* disconnect, context teardown), its continuation — including any `finally`
|
|
8
|
+
* that would release the lock — never runs. A plain boolean or shared
|
|
9
|
+
* promise then stays stuck forever and every subsequent request in the
|
|
10
|
+
* isolate hangs until the platform kills it (observed as 524s at the
|
|
11
|
+
* 100-second wall limit, with the isolate poisoned until eviction).
|
|
12
|
+
*
|
|
13
|
+
* This lock instead records *when* the owner started. Waiters poll — we
|
|
14
|
+
* deliberately never await a promise created by another request, which
|
|
15
|
+
* workerd flags — and if the owner has held the lock past `deadlineMs`,
|
|
16
|
+
* the next waiter assumes the owner is dead, reclaims the lock, and runs
|
|
17
|
+
* the initialization itself. Waiters also give up after `maxWaitMs` so a
|
|
18
|
+
* request degrades to an error response rather than hanging.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export interface InitLock {
|
|
22
|
+
/** Epoch ms when the current owner claimed the lock, or null when free. */
|
|
23
|
+
ownerStartedAt: number | null;
|
|
24
|
+
/**
|
|
25
|
+
* Monotonic claim counter identifying the current owner. Release is
|
|
26
|
+
* gated on it: a slow owner that finishes after a waiter has reclaimed
|
|
27
|
+
* the lock must not clear the reclaimer's claim — that would let yet
|
|
28
|
+
* another caller claim the lock and start a third concurrent init.
|
|
29
|
+
*/
|
|
30
|
+
generation: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createInitLock(): InitLock {
|
|
34
|
+
return { ownerStartedAt: null, generation: 0 };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface InitLockOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Reclaim the lock if the owner has held it longer than this. Must be
|
|
40
|
+
* comfortably above the slowest legitimate init (cold migrations on a
|
|
41
|
+
* contended D1, including the concurrent-migrator wait) — a too-short
|
|
42
|
+
* deadline risks two concurrent inits, a too-long one delays recovery
|
|
43
|
+
* of a poisoned isolate. Nested locks must compose: an outer lock's
|
|
44
|
+
* deadline must exceed the deadline of any lock its init acquires.
|
|
45
|
+
*/
|
|
46
|
+
deadlineMs?: number;
|
|
47
|
+
/** Waiter poll interval. */
|
|
48
|
+
pollMs?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Give up waiting after this long and throw instead of hanging.
|
|
51
|
+
* Defaults to `deadlineMs` plus headroom so a waiter always survives
|
|
52
|
+
* long enough to reclaim a dead owner before giving up.
|
|
53
|
+
*/
|
|
54
|
+
maxWaitMs?: number;
|
|
55
|
+
/**
|
|
56
|
+
* Called with the in-flight init promise (errors pre-swallowed) so the
|
|
57
|
+
* caller can hand it to the host's lifetime extender (waitUntil via
|
|
58
|
+
* `after()`). If the owning request is cancelled mid-init, the anchored
|
|
59
|
+
* promise keeps the context alive: init completes, populates the cache,
|
|
60
|
+
* and the `finally` below releases the lock — preventing the poisoning
|
|
61
|
+
* instead of merely recovering from it via reclaim.
|
|
62
|
+
*/
|
|
63
|
+
anchor?: (promise: Promise<void>) => void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const DEFAULT_DEADLINE_MS = 15_000;
|
|
67
|
+
const DEFAULT_POLL_MS = 50;
|
|
68
|
+
const MAX_WAIT_HEADROOM_MS = 15_000;
|
|
69
|
+
|
|
70
|
+
function sleep(ms: number): Promise<void> {
|
|
71
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Return the cached value if present, otherwise initialize it under the
|
|
76
|
+
* lock. `init` is responsible for storing the value so that `getCached`
|
|
77
|
+
* returns it on subsequent calls — waiters re-check `getCached` after the
|
|
78
|
+
* owner finishes rather than sharing the owner's promise.
|
|
79
|
+
*
|
|
80
|
+
* `init` receives an `isCurrentClaim` predicate and must gate its cache
|
|
81
|
+
* publication on it: a slow init that was reclaimed past the deadline
|
|
82
|
+
* must not overwrite the value published by the reclaimer (for the
|
|
83
|
+
* runtime singleton that would orphan the reclaimer's active cron
|
|
84
|
+
* scheduler). A losing init should also tear down any side resources it
|
|
85
|
+
* started, since its result will never be published.
|
|
86
|
+
*/
|
|
87
|
+
export async function initWithLock<T>(
|
|
88
|
+
lock: InitLock,
|
|
89
|
+
getCached: () => T | null | undefined,
|
|
90
|
+
init: (isCurrentClaim: () => boolean) => Promise<T>,
|
|
91
|
+
options?: InitLockOptions,
|
|
92
|
+
): Promise<T> {
|
|
93
|
+
const deadlineMs = options?.deadlineMs ?? DEFAULT_DEADLINE_MS;
|
|
94
|
+
const pollMs = options?.pollMs ?? DEFAULT_POLL_MS;
|
|
95
|
+
const maxWaitMs = options?.maxWaitMs ?? deadlineMs + MAX_WAIT_HEADROOM_MS;
|
|
96
|
+
// Date.now() is deliberate and only works because every loop iteration
|
|
97
|
+
// awaits: in workerd the clock only advances across I/O, so a sync spin
|
|
98
|
+
// would never observe the deadline. Don't "optimize" away the sleep.
|
|
99
|
+
const waitStart = Date.now();
|
|
100
|
+
|
|
101
|
+
for (;;) {
|
|
102
|
+
const cached = getCached();
|
|
103
|
+
if (cached !== null && cached !== undefined) {
|
|
104
|
+
return cached;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const ownerStartedAt = lock.ownerStartedAt;
|
|
108
|
+
if (ownerStartedAt === null || Date.now() - ownerStartedAt > deadlineMs) {
|
|
109
|
+
// Free, or the owner has been gone past the deadline — claim it.
|
|
110
|
+
// Synchronous between awaits, so two waiters can't both claim.
|
|
111
|
+
lock.generation += 1;
|
|
112
|
+
const claim = lock.generation;
|
|
113
|
+
lock.ownerStartedAt = Date.now();
|
|
114
|
+
try {
|
|
115
|
+
// Promise.resolve().then(...) so a synchronous throw from
|
|
116
|
+
// init still becomes a rejection after the anchor attaches.
|
|
117
|
+
const isCurrentClaim = () => lock.generation === claim;
|
|
118
|
+
const initPromise = Promise.resolve().then(() => init(isCurrentClaim));
|
|
119
|
+
options?.anchor?.(
|
|
120
|
+
initPromise.then(
|
|
121
|
+
() => undefined,
|
|
122
|
+
() => undefined,
|
|
123
|
+
),
|
|
124
|
+
);
|
|
125
|
+
return await initPromise;
|
|
126
|
+
} finally {
|
|
127
|
+
// If this request dies mid-init unanchored this never runs;
|
|
128
|
+
// the next waiter reclaims after deadlineMs instead. Release
|
|
129
|
+
// only while still the current owner: a reclaimer may have
|
|
130
|
+
// taken the lock while this (slow) init was running, and
|
|
131
|
+
// clearing its claim would admit a third concurrent init.
|
|
132
|
+
if (lock.generation === claim) {
|
|
133
|
+
lock.ownerStartedAt = null;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (Date.now() - waitStart > maxWaitMs) {
|
|
139
|
+
throw new Error(`initWithLock: timed out after ${maxWaitMs}ms waiting for initialization`);
|
|
140
|
+
}
|
|
141
|
+
await sleep(pollMs);
|
|
142
|
+
}
|
|
143
|
+
}
|