emdash 0.18.0 → 0.20.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-C5AWLJSD.d.mts → adapters-BzIHV3sw.d.mts} +1 -1
- package/dist/{adapters-C5AWLJSD.d.mts.map → adapters-BzIHV3sw.d.mts.map} +1 -1
- package/dist/{allowed-origins-CyYLEJkp.mjs → allowed-origins-B1u7Qnvg.mjs} +2 -2
- package/dist/{allowed-origins-CyYLEJkp.mjs.map → allowed-origins-B1u7Qnvg.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +15 -15
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +3 -3
- package/dist/{api-Cs7DAACP.mjs → api-DStv36ik.mjs} +123 -20
- package/dist/api-DStv36ik.mjs.map +1 -0
- package/dist/{api-tokens-VrXNiNvV.mjs → api-tokens-DPfhPu5V.mjs} +2 -2
- package/dist/{api-tokens-VrXNiNvV.mjs.map → api-tokens-DPfhPu5V.mjs.map} +1 -1
- package/dist/{apply-BWMV4Zmw.mjs → apply-Dr7snAMT.mjs} +23 -23
- package/dist/apply-Dr7snAMT.mjs.map +1 -0
- package/dist/astro/index.d.mts +10 -10
- package/dist/astro/index.d.mts.map +1 -1
- package/dist/astro/index.mjs +115 -25
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/middleware/auth.d.mts +9 -9
- package/dist/astro/middleware/auth.mjs +6 -6
- package/dist/astro/middleware/redirect.mjs +4 -4
- package/dist/astro/middleware/request-context.mjs +2 -2
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts +26 -4
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +242 -259
- 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 +4 -4
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -5
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +8 -8
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +8 -8
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +8 -8
- 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 +11 -11
- package/dist/astro/routes/api/admin/comments/_id_.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/bulk.mjs +8 -8
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +8 -8
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +5 -5
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/index.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +33 -33
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/updates.mjs +33 -33
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +33 -33
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +33 -33
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +3 -3
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +4 -4
- package/dist/astro/routes/api/admin/users/index.mjs +5 -5
- package/dist/astro/routes/api/auth/dev-bypass.mjs +5 -5
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +10 -10
- package/dist/astro/routes/api/auth/invite/index.mjs +7 -7
- package/dist/astro/routes/api/auth/invite/register-options.mjs +9 -9
- package/dist/astro/routes/api/auth/logout.mjs +3 -3
- package/dist/astro/routes/api/auth/magic-link/send.mjs +8 -8
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +3 -3
- package/dist/astro/routes/api/auth/me.mjs +6 -6
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +4 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- 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 +10 -10
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +9 -9
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +10 -10
- package/dist/astro/routes/api/auth/passkey/verify.mjs +10 -10
- package/dist/astro/routes/api/auth/signup/complete.mjs +10 -10
- package/dist/astro/routes/api/auth/signup/request.mjs +8 -8
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +11 -11
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +6 -5
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs.map +1 -1
- 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 +8 -8
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +9 -8
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs.map +1 -1
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +12 -10
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs.map +1 -1
- 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 +6 -5
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +9 -8
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/authors.d.mts +8 -0
- package/dist/astro/routes/api/content/_collection_/authors.d.mts.map +1 -0
- package/dist/astro/routes/api/content/_collection_/authors.mjs +19 -0
- package/dist/astro/routes/api/content/_collection_/authors.mjs.map +1 -0
- 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 +7 -7
- 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 +6 -6
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +4 -4
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
- package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/media.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +8 -8
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +6 -6
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +9 -9
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/mcp.mjs +29 -29
- package/dist/astro/routes/api/media/_id_/confirm.mjs +6 -6
- 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 +7 -7
- package/dist/astro/routes/api/media.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +7 -7
- package/dist/astro/routes/api/menus/_name_/items.mjs +7 -7
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +7 -7
- package/dist/astro/routes/api/menus/_name_/translations.mjs +7 -7
- package/dist/astro/routes/api/menus/_name_.mjs +7 -7
- package/dist/astro/routes/api/menus/index.mjs +7 -7
- package/dist/astro/routes/api/oauth/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/authorize.mjs +6 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +8 -8
- package/dist/astro/routes/api/oauth/device/token.mjs +7 -7
- package/dist/astro/routes/api/oauth/register.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/refresh.mjs +6 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +6 -6
- package/dist/astro/routes/api/oauth/token.mjs +6 -6
- package/dist/astro/routes/api/openapi.json.mjs +17 -3
- package/dist/astro/routes/api/openapi.json.mjs.map +1 -1
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
- package/dist/astro/routes/api/redirects/404s/index.mjs +9 -9
- package/dist/astro/routes/api/redirects/404s/summary.mjs +9 -9
- package/dist/astro/routes/api/redirects/_id_.mjs +10 -10
- package/dist/astro/routes/api/redirects/index.mjs +10 -10
- 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 +33 -33
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +33 -33
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +33 -33
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +33 -33
- package/dist/astro/routes/api/schema/collections/index.mjs +33 -33
- package/dist/astro/routes/api/schema/index.mjs +9 -14
- package/dist/astro/routes/api/schema/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +33 -33
- package/dist/astro/routes/api/schema/orphans/index.mjs +33 -33
- 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 +5 -5
- package/dist/astro/routes/api/settings.mjs +12 -12
- package/dist/astro/routes/api/setup/admin-verify.mjs +11 -11
- package/dist/astro/routes/api/setup/admin.mjs +10 -10
- package/dist/astro/routes/api/setup/dev-bypass.mjs +23 -23
- package/dist/astro/routes/api/setup/dev-reset.mjs +3 -3
- package/dist/astro/routes/api/setup/index.mjs +23 -23
- package/dist/astro/routes/api/setup/status.mjs +4 -4
- package/dist/astro/routes/api/snapshot.mjs +6 -6
- 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 +6 -6
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/well-known/auth.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +2 -2
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +2 -2
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +9 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +9 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/_name_.mjs +6 -5
- package/dist/astro/routes/api/widget-areas/_name_.mjs.map +1 -1
- package/dist/astro/routes/api/widget-areas/index.mjs +9 -8
- package/dist/astro/routes/api/widget-areas/index.mjs.map +1 -1
- package/dist/astro/routes/api/widget-components.mjs +3 -3
- package/dist/astro/routes/robots.txt.mjs +7 -7
- package/dist/astro/routes/sitemap-_collection_.xml.d.mts.map +1 -1
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +16 -9
- package/dist/astro/routes/sitemap-_collection_.xml.mjs.map +1 -1
- package/dist/astro/routes/sitemap.xml.mjs +8 -8
- package/dist/astro/types.d.mts +19 -12
- 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-CotM4Yiu.mjs → authorize-DsMSVSaY.mjs} +2 -2
- package/dist/{authorize-CotM4Yiu.mjs.map → authorize-DsMSVSaY.mjs.map} +1 -1
- package/dist/{byline-CWQ9aSoz.mjs → byline-DUx48sJp.mjs} +6 -6
- package/dist/{byline-CWQ9aSoz.mjs.map → byline-DUx48sJp.mjs.map} +1 -1
- package/dist/{byline-fields-DC3Wkk-U.mjs → byline-fields--WxSNS79.mjs} +2 -2
- package/dist/{byline-fields-DC3Wkk-U.mjs.map → byline-fields--WxSNS79.mjs.map} +1 -1
- package/dist/{byline-fields-Dr-xcb6S.mjs → byline-fields-8TMtkBnH.mjs} +3 -3
- package/dist/{byline-fields-Dr-xcb6S.mjs.map → byline-fields-8TMtkBnH.mjs.map} +1 -1
- package/dist/{byline-fields-BNy7Ng1U.d.mts → byline-fields-DbibsvTl.d.mts} +30 -2
- package/dist/byline-fields-DbibsvTl.d.mts.map +1 -0
- package/dist/{byline-registry-CxK5g559.mjs → byline-registry-CWP7I71B.mjs} +3 -3
- package/dist/{byline-registry-CxK5g559.mjs.map → byline-registry-CWP7I71B.mjs.map} +1 -1
- package/dist/{bylines-LJMgENMI.mjs → bylines-BdxWCnPL.mjs} +3 -3
- package/dist/{bylines-LJMgENMI.mjs.map → bylines-BdxWCnPL.mjs.map} +1 -1
- package/dist/{bylines-BJSva1Un.mjs → bylines-s8c2DXbH.mjs} +50 -6
- package/dist/{bylines-BJSva1Un.mjs.map → bylines-s8c2DXbH.mjs.map} +1 -1
- package/dist/{cache-lZL7SgVb.mjs → cache-B_HzASVT.mjs} +3 -3
- package/dist/{cache-lZL7SgVb.mjs.map → cache-B_HzASVT.mjs.map} +1 -1
- package/dist/{challenge-store-DGwuCc4R.mjs → challenge-store-DXX3rfdI.mjs} +1 -1
- package/dist/{challenge-store-DGwuCc4R.mjs.map → challenge-store-DXX3rfdI.mjs.map} +1 -1
- package/dist/{chunks-BU-vP9Dh.mjs → chunks-BerYVuve.mjs} +2 -2
- package/dist/{chunks-BU-vP9Dh.mjs.map → chunks-BerYVuve.mjs.map} +1 -1
- package/dist/cli/index.mjs +46 -32
- 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/client/index.mjs +1 -1
- package/dist/{comment-C4jVbCM8.mjs → comment-sqQxNpN3.mjs} +2 -2
- package/dist/{comment-C4jVbCM8.mjs.map → comment-sqQxNpN3.mjs.map} +1 -1
- package/dist/{comments-BTAbC0Ek.mjs → comments-Vkivawyl.mjs} +3 -3
- package/dist/{comments-BTAbC0Ek.mjs.map → comments-Vkivawyl.mjs.map} +1 -1
- package/dist/{components-CTfpu3PZ.mjs → components-CK0cuUoH.mjs} +1 -1
- package/dist/{components-CTfpu3PZ.mjs.map → components-CK0cuUoH.mjs.map} +1 -1
- package/dist/{content-CyqOmOzm.mjs → content-BIlVx-RX.mjs} +132 -43
- package/dist/content-BIlVx-RX.mjs.map +1 -0
- package/dist/{context-DZ7bEh5-.mjs → context-Y7BRkWes.mjs} +10 -10
- package/dist/{context-DZ7bEh5-.mjs.map → context-Y7BRkWes.mjs.map} +1 -1
- package/dist/{cron-DZovZUnC.mjs → cron-BJ2ClIlj.mjs} +4 -3
- package/dist/cron-BJ2ClIlj.mjs.map +1 -0
- package/dist/{dashboard-B5WQpNTP.mjs → dashboard-2JgAMWxK.mjs} +4 -4
- package/dist/{dashboard-B5WQpNTP.mjs.map → dashboard-2JgAMWxK.mjs.map} +1 -1
- package/dist/database/instrumentation.d.mts +10 -1
- package/dist/database/instrumentation.d.mts.map +1 -1
- package/dist/database/instrumentation.mjs +13 -1
- package/dist/database/instrumentation.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/{default-xLFNSsZ9.mjs → default-IlBaTFxM.mjs} +1 -1
- package/dist/{default-xLFNSsZ9.mjs.map → default-IlBaTFxM.mjs.map} +1 -1
- package/dist/{device-flow-ptLrVINd.mjs → device-flow-R23SIbQ2.mjs} +5 -5
- package/dist/{device-flow-ptLrVINd.mjs.map → device-flow-R23SIbQ2.mjs.map} +1 -1
- package/dist/{error-DJOsMVSt.mjs → error-RwM4dD35.mjs} +2 -2
- package/dist/{error-DJOsMVSt.mjs.map → error-RwM4dD35.mjs.map} +1 -1
- package/dist/{escape-bIyGoW5W.mjs → escape-Ds07EEyu.mjs} +1 -1
- package/dist/{escape-bIyGoW5W.mjs.map → escape-Ds07EEyu.mjs.map} +1 -1
- package/dist/{fts-manager-DR1ERA0c.mjs → fts-manager-1RgHmopc.mjs} +2 -2
- package/dist/{fts-manager-DR1ERA0c.mjs.map → fts-manager-1RgHmopc.mjs.map} +1 -1
- package/dist/{index-CjKdMZ3U.d.mts → index-B1keaX5Y.d.mts} +237 -24
- package/dist/index-B1keaX5Y.d.mts.map +1 -0
- package/dist/{index-D60_SzHG.d.mts → index-DR56od45.d.mts} +3 -3
- package/dist/{index-D60_SzHG.d.mts.map → index-DR56od45.d.mts.map} +1 -1
- package/dist/index.d.mts +17 -17
- package/dist/index.mjs +46 -46
- package/dist/{load-6ZrRhepW.mjs → load-BBetCvLC.mjs} +2 -2
- package/dist/{load-6ZrRhepW.mjs.map → load-BBetCvLC.mjs.map} +1 -1
- package/dist/{loader-Dyx8dhFV.mjs → loader-ZN1ll-d-.mjs} +36 -37
- package/dist/loader-ZN1ll-d-.mjs.map +1 -0
- package/dist/{manifest-schema-Cj-YrzrF.mjs → manifest-schema-BtwbL_vj.mjs} +55 -2
- package/dist/manifest-schema-BtwbL_vj.mjs.map +1 -0
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +1 -1
- package/dist/media/local-runtime.d.mts +11 -11
- package/dist/media/local-runtime.mjs +6 -6
- package/dist/{media-C-oovGCG.mjs → media-JOf3pNkw.mjs} +2 -2
- package/dist/{media-C-oovGCG.mjs.map → media-JOf3pNkw.mjs.map} +1 -1
- package/dist/{media-allowlist-CMcoYIjQ.mjs → media-allowlist-Dknq-OFY.mjs} +1 -1
- package/dist/{media-allowlist-CMcoYIjQ.mjs.map → media-allowlist-Dknq-OFY.mjs.map} +1 -1
- package/dist/media-url-VClf8glU.mjs +26 -0
- package/dist/media-url-VClf8glU.mjs.map +1 -0
- package/dist/{menus-DugoYwTX.mjs → menus-DX4_E01q.mjs} +3 -3
- package/dist/{menus-DugoYwTX.mjs.map → menus-DX4_E01q.mjs.map} +1 -1
- package/dist/{menus-BKkxXCmd.mjs → menus-DrQLusqj.mjs} +87 -37
- package/dist/menus-DrQLusqj.mjs.map +1 -0
- package/dist/{mode-BjlXswIw.mjs → mode-CO2vQHfq.mjs} +1 -1
- package/dist/{mode-BjlXswIw.mjs.map → mode-CO2vQHfq.mjs.map} +1 -1
- package/dist/{normalize-DVV8nbrL.mjs → normalize-CK5o04zr.mjs} +2 -2
- package/dist/{normalize-DVV8nbrL.mjs.map → normalize-CK5o04zr.mjs.map} +1 -1
- package/dist/{oauth-authorization-DvBAL75d.mjs → oauth-authorization-Bw4NdF_S.mjs} +5 -5
- package/dist/{oauth-authorization-DvBAL75d.mjs.map → oauth-authorization-Bw4NdF_S.mjs.map} +1 -1
- package/dist/{oauth-clients-8mPDStMv.mjs → oauth-clients-BGGFp57s.mjs} +1 -1
- package/dist/{oauth-clients-8mPDStMv.mjs.map → oauth-clients-BGGFp57s.mjs.map} +1 -1
- package/dist/{oauth-state-store-BJ7YtrfD.mjs → oauth-state-store-97x0xtN2.mjs} +1 -1
- package/dist/{oauth-state-store-BJ7YtrfD.mjs.map → oauth-state-store-97x0xtN2.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-BdDSDvjF.mjs → oauth-user-lookup-B_vnZHKO.mjs} +1 -1
- package/dist/{oauth-user-lookup-BdDSDvjF.mjs.map → oauth-user-lookup-B_vnZHKO.mjs.map} +1 -1
- package/dist/{options-BL4X94qY.mjs → options-BPCVnesz.mjs} +1 -1
- package/dist/{options-BL4X94qY.mjs.map → options-BPCVnesz.mjs.map} +1 -1
- package/dist/{options-tb7DJROi.d.mts → options-DyYIYpPd.d.mts} +3 -3
- package/dist/{options-tb7DJROi.d.mts.map → options-DyYIYpPd.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-BBkFmLVr.mjs → parse-CrGndy1A.mjs} +2 -2
- package/dist/{parse-BBkFmLVr.mjs.map → parse-CrGndy1A.mjs.map} +1 -1
- package/dist/{passkey-config-BDVM86Tj.mjs → passkey-config-C3QgnQnU.mjs} +1 -1
- package/dist/{passkey-config-BDVM86Tj.mjs.map → passkey-config-C3QgnQnU.mjs.map} +1 -1
- package/dist/{patterns-CqG5Ya3i.mjs → patterns-p-RBdTbM.mjs} +1 -1
- package/dist/{patterns-CqG5Ya3i.mjs.map → patterns-p-RBdTbM.mjs.map} +1 -1
- package/dist/{placeholder-B9lUUEmj.d.mts → placeholder-CVBv5z8k.d.mts} +1 -1
- package/dist/{placeholder-B9lUUEmj.d.mts.map → placeholder-CVBv5z8k.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugin-utils.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.mjs +2 -2
- package/dist/{public-url-egRHCy1m.mjs → public-url-BFVC2OTJ.mjs} +1 -1
- package/dist/{public-url-egRHCy1m.mjs.map → public-url-BFVC2OTJ.mjs.map} +1 -1
- package/dist/{query-Ctlq1aOk.mjs → query-CbUcI4Xk.mjs} +33 -17
- package/dist/query-CbUcI4Xk.mjs.map +1 -0
- package/dist/{rate-limit-CH6W6ikK.mjs → rate-limit-C7hjdkS5.mjs} +2 -2
- package/dist/{rate-limit-CH6W6ikK.mjs.map → rate-limit-C7hjdkS5.mjs.map} +1 -1
- package/dist/{redirect-Cw3JTlmj.mjs → redirect-B_q19j4v.mjs} +1 -1
- package/dist/{redirect-Cw3JTlmj.mjs.map → redirect-B_q19j4v.mjs.map} +1 -1
- package/dist/{redirect-C6tJA7tk.mjs → redirect-CRWIt8Zj.mjs} +3 -3
- package/dist/{redirect-C6tJA7tk.mjs.map → redirect-CRWIt8Zj.mjs.map} +1 -1
- package/dist/{redirects-C0L9JUk4.mjs → redirects-CCbCqCCd.mjs} +28 -4
- package/dist/redirects-CCbCqCCd.mjs.map +1 -0
- package/dist/{redirects-CacE9eQa.mjs → redirects-DxVoR7PI.mjs} +5 -5
- package/dist/{redirects-CacE9eQa.mjs.map → redirects-DxVoR7PI.mjs.map} +1 -1
- package/dist/{registry-CIDxZbhh.mjs → registry-brYh-rAT.mjs} +6 -6
- package/dist/{registry-CIDxZbhh.mjs.map → registry-brYh-rAT.mjs.map} +1 -1
- package/dist/{request-cache-BYMs-BGX.mjs → request-cache-D32LpnmI.mjs} +1 -1
- package/dist/{request-cache-BYMs-BGX.mjs.map → request-cache-D32LpnmI.mjs.map} +1 -1
- package/dist/request-context.d.mts +7 -0
- package/dist/request-context.d.mts.map +1 -1
- package/dist/request-context.mjs +2 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{runner-pt6Wl-l-.mjs → runner--4wMWwKM.mjs} +217 -166
- package/dist/runner--4wMWwKM.mjs.map +1 -0
- package/dist/{runner-DM1yR5qd.d.mts → runner-DTdhuI9i.d.mts} +2 -2
- package/dist/{runner-DM1yR5qd.d.mts.map → runner-DTdhuI9i.d.mts.map} +1 -1
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +2 -2
- package/dist/{schema-B4tk0HAG.mjs → schema-C1E70ug_.mjs} +5 -5
- package/dist/{schema-B4tk0HAG.mjs.map → schema-C1E70ug_.mjs.map} +1 -1
- package/dist/{search-f-fNfwab.mjs → search-B3SGZw91.mjs} +4 -4
- package/dist/{search-f-fNfwab.mjs.map → search-B3SGZw91.mjs.map} +1 -1
- package/dist/{secrets-YYbTgB1w.mjs → secrets-ChPTmy9x.mjs} +2 -2
- package/dist/{secrets-YYbTgB1w.mjs.map → secrets-ChPTmy9x.mjs.map} +1 -1
- package/dist/{sections-biElLfT9.mjs → sections-D_lVzwRZ.mjs} +3 -3
- package/dist/{sections-biElLfT9.mjs.map → sections-D_lVzwRZ.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +17 -17
- package/dist/seo/index.d.mts +1 -1
- package/dist/seo/index.d.mts.map +1 -1
- package/dist/seo/index.mjs +3 -12
- package/dist/seo/index.mjs.map +1 -1
- package/dist/{seo-BR39kvTF.mjs → seo-B5e6y9Wk.mjs} +2 -2
- package/dist/{seo-BR39kvTF.mjs.map → seo-B5e6y9Wk.mjs.map} +1 -1
- package/dist/{seo-DfjLvu8i.mjs → seo-D_LPkOtu.mjs} +4 -3
- package/dist/seo-D_LPkOtu.mjs.map +1 -0
- package/dist/{service-BhR2acnc.mjs → service-ChDcsTBs.mjs} +3 -3
- package/dist/{service-BhR2acnc.mjs.map → service-ChDcsTBs.mjs.map} +1 -1
- package/dist/{settings-D_NJvjgN.mjs → settings-Cv47v9u8.mjs} +3 -3
- package/dist/{settings-D_NJvjgN.mjs.map → settings-Cv47v9u8.mjs.map} +1 -1
- package/dist/settings-DfxiWY_s.mjs +411 -0
- package/dist/settings-DfxiWY_s.mjs.map +1 -0
- package/dist/{setup-complete-VoEZfasi.mjs → setup-complete-yvPE4OsP.mjs} +2 -2
- package/dist/{setup-complete-VoEZfasi.mjs.map → setup-complete-yvPE4OsP.mjs.map} +1 -1
- package/dist/{setup-nonce-Bm0uKqmf.mjs → setup-nonce-C9aFzb94.mjs} +1 -1
- package/dist/{setup-nonce-Bm0uKqmf.mjs.map → setup-nonce-C9aFzb94.mjs.map} +1 -1
- package/dist/{site-url-Cm8-sJy7.mjs → site-url-CnHlmAs9.mjs} +2 -2
- package/dist/{site-url-Cm8-sJy7.mjs.map → site-url-CnHlmAs9.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/{taxonomies-Mhn9rjTQ.mjs → taxonomies-BILwiyGk.mjs} +4 -4
- package/dist/{taxonomies-Mhn9rjTQ.mjs.map → taxonomies-BILwiyGk.mjs.map} +1 -1
- package/dist/{taxonomies-Crtzy4MT.mjs → taxonomies-BdAmbOwx.mjs} +50 -12
- package/dist/taxonomies-BdAmbOwx.mjs.map +1 -0
- package/dist/{taxonomy-DTZrIQpi.mjs → taxonomy-CdllE4oq.mjs} +3 -3
- package/dist/{taxonomy-DTZrIQpi.mjs.map → taxonomy-CdllE4oq.mjs.map} +1 -1
- package/dist/{transaction-NQj4VJ7Z.mjs → transaction-x2tJQ-A1.mjs} +1 -1
- package/dist/{transaction-NQj4VJ7Z.mjs.map → transaction-x2tJQ-A1.mjs.map} +1 -1
- package/dist/{transport-OnMNbsIA.d.mts → transport-B7PPP2CC.d.mts} +1 -1
- package/dist/{transport-OnMNbsIA.d.mts.map → transport-B7PPP2CC.d.mts.map} +1 -1
- package/dist/{transport--Ck3RBin.mjs → transport-CmpLD7W3.mjs} +1 -1
- package/dist/{transport--Ck3RBin.mjs.map → transport-CmpLD7W3.mjs.map} +1 -1
- package/dist/{types-DWnN7weG.d.mts → types-BFgrqwSk.d.mts} +1 -1
- package/dist/{types-DWnN7weG.d.mts.map → types-BFgrqwSk.d.mts.map} +1 -1
- package/dist/{types-Qa7-HJJC.d.mts → types-BH8-30hc.d.mts} +1 -1
- package/dist/{types-Qa7-HJJC.d.mts.map → types-BH8-30hc.d.mts.map} +1 -1
- package/dist/{types-DawhLFwy.d.mts → types-BPzXTV9x.d.mts} +26 -1
- package/dist/{types-DawhLFwy.d.mts.map → types-BPzXTV9x.d.mts.map} +1 -1
- package/dist/{types-DbCWhHet.d.mts → types-BUUVn1zr.d.mts} +2 -2
- package/dist/types-BUUVn1zr.d.mts.map +1 -0
- package/dist/{types-K3MDsxpy.mjs → types-BXSUSAjt.mjs} +16 -3
- package/dist/{types-K3MDsxpy.mjs.map → types-BXSUSAjt.mjs.map} +1 -1
- package/dist/{types-DMwSpvcw.d.mts → types-CPAPl93j.d.mts} +9 -3
- package/dist/{types-DMwSpvcw.d.mts.map → types-CPAPl93j.d.mts.map} +1 -1
- package/dist/types-CZI4E3qG.mjs +3 -0
- package/dist/{types-kwqCOUxj.d.mts → types-D4kUqbHh.d.mts} +1 -1
- package/dist/{types-kwqCOUxj.d.mts.map → types-D4kUqbHh.d.mts.map} +1 -1
- package/dist/{types-i8_uzhMD.d.mts → types-DTniiNto.d.mts} +19 -4
- package/dist/types-DTniiNto.d.mts.map +1 -0
- package/dist/{types-D8bhH891.mjs → types-DZk_y-MU.mjs} +1 -1
- package/dist/types-DZk_y-MU.mjs.map +1 -0
- package/dist/{types-DX6v9KzJ.d.mts → types-S15DXXNi.d.mts} +1 -1
- package/dist/{types-DX6v9KzJ.d.mts.map → types-S15DXXNi.d.mts.map} +1 -1
- package/dist/{user-DzEUl5zA.mjs → user-C0um7wrg.mjs} +18 -2
- package/dist/user-C0um7wrg.mjs.map +1 -0
- package/dist/{validate-JCXcsqiY.mjs → validate-Bz4vqcX1.mjs} +6 -3
- package/dist/validate-Bz4vqcX1.mjs.map +1 -0
- package/dist/{validate-Dy6nkNls.d.mts → validate-CNwkPWzz.d.mts} +13 -5
- package/dist/validate-CNwkPWzz.d.mts.map +1 -0
- package/dist/{validation-Bq-VyKJg.mjs → validation-DgGTJm3u.mjs} +5 -5
- package/dist/{validation-Bq-VyKJg.mjs.map → validation-DgGTJm3u.mjs.map} +1 -1
- package/dist/version-D-5txk2m.mjs +7 -0
- package/dist/{version-CnS-Cr8A.mjs.map → version-D-5txk2m.mjs.map} +1 -1
- package/dist/{widgets-Bap1eS1X.mjs → widgets-DZfmAbE4.mjs} +47 -44
- package/dist/widgets-DZfmAbE4.mjs.map +1 -0
- package/dist/{zod-generator-BSDpkqSH.mjs → zod-generator-Djo_VHCt.mjs} +2 -2
- package/dist/{zod-generator-BSDpkqSH.mjs.map → zod-generator-Djo_VHCt.mjs.map} +1 -1
- package/package.json +10 -10
- package/src/api/handlers/content.ts +107 -8
- package/src/api/handlers/index.ts +2 -0
- package/src/api/handlers/marketplace.ts +2 -5
- package/src/api/handlers/registry.ts +70 -0
- package/src/api/handlers/seo.ts +9 -1
- package/src/api/openapi/document.ts +25 -0
- package/src/api/schemas/content.ts +33 -0
- package/src/api/schemas/schema.ts +13 -1
- package/src/astro/integration/index.ts +98 -0
- package/src/astro/integration/routes.ts +6 -0
- package/src/astro/integration/virtual-modules.ts +39 -0
- package/src/astro/integration/vite-config.ts +12 -0
- package/src/astro/middleware.ts +48 -6
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +8 -4
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +4 -2
- package/src/astro/routes/api/content/[collection]/[id].ts +4 -2
- package/src/astro/routes/api/content/[collection]/authors.ts +34 -0
- package/src/astro/routes/api/schema/index.ts +7 -15
- package/src/astro/routes/sitemap-[collection].xml.ts +13 -2
- package/src/astro/types.ts +8 -1
- package/src/bylines/index.ts +57 -0
- package/src/cli/commands/bundle-utils.ts +2 -0
- package/src/cli/commands/export-seed.ts +28 -12
- package/src/cli/commands/secrets.ts +2 -2
- package/src/components/EmDashImage.astro +22 -4
- package/src/components/Image.astro +20 -3
- package/src/database/instrumentation.ts +13 -0
- package/src/database/migrations/043_content_references.ts +121 -0
- package/src/database/migrations/runner.ts +2 -0
- package/src/database/repositories/content.ts +225 -67
- package/src/database/repositories/index.ts +7 -0
- package/src/database/repositories/relation.ts +467 -0
- package/src/database/repositories/types.ts +31 -0
- package/src/database/repositories/user.ts +18 -0
- package/src/database/types.ts +34 -0
- package/src/emdash-runtime.ts +172 -67
- package/src/index.ts +8 -1
- package/src/loader.ts +81 -39
- package/src/media/responsive.ts +125 -0
- package/src/plugins/cron.ts +3 -2
- package/src/plugins/index.ts +5 -0
- package/src/plugins/manifest-schema.ts +75 -0
- package/src/plugins/marketplace.ts +2 -5
- package/src/plugins/scheduler/node.ts +9 -2
- package/src/plugins/types.ts +12 -0
- package/src/query.ts +45 -7
- package/src/request-context.ts +8 -0
- package/src/scheduled-publish.ts +153 -0
- package/src/schema/types.ts +11 -1
- package/src/seed/apply.ts +16 -6
- package/src/seed/types.ts +9 -0
- package/src/seed/validate.ts +15 -0
- package/src/seo/index.ts +2 -28
- package/src/seo/media-url.ts +32 -0
- package/src/settings/index.ts +32 -40
- package/src/taxonomies/index.ts +79 -12
- package/src/utils/isolate-cache.ts +189 -0
- package/src/virtual-modules.d.ts +11 -0
- package/src/widgets/index.ts +57 -54
- package/dist/api-Cs7DAACP.mjs.map +0 -1
- package/dist/apply-BWMV4Zmw.mjs.map +0 -1
- package/dist/byline-fields-BNy7Ng1U.d.mts.map +0 -1
- package/dist/content-CyqOmOzm.mjs.map +0 -1
- package/dist/cron-DZovZUnC.mjs.map +0 -1
- package/dist/index-CjKdMZ3U.d.mts.map +0 -1
- package/dist/loader-Dyx8dhFV.mjs.map +0 -1
- package/dist/manifest-schema-Cj-YrzrF.mjs.map +0 -1
- package/dist/menus-BKkxXCmd.mjs.map +0 -1
- package/dist/query-Ctlq1aOk.mjs.map +0 -1
- package/dist/redirects-C0L9JUk4.mjs.map +0 -1
- package/dist/runner-pt6Wl-l-.mjs.map +0 -1
- package/dist/seo-DfjLvu8i.mjs.map +0 -1
- package/dist/settings-b5zW1R1T.mjs +0 -235
- package/dist/settings-b5zW1R1T.mjs.map +0 -1
- package/dist/taxonomies-Crtzy4MT.mjs.map +0 -1
- package/dist/types-Cj2S6FuC.mjs +0 -3
- package/dist/types-D8bhH891.mjs.map +0 -1
- package/dist/types-DbCWhHet.d.mts.map +0 -1
- package/dist/types-i8_uzhMD.d.mts.map +0 -1
- package/dist/user-DzEUl5zA.mjs.map +0 -1
- package/dist/validate-Dy6nkNls.d.mts.map +0 -1
- package/dist/validate-JCXcsqiY.mjs.map +0 -1
- package/dist/version-CnS-Cr8A.mjs +0 -7
- package/dist/widgets-Bap1eS1X.mjs.map +0 -1
- package/src/plugins/scheduler/piggyback.ts +0 -71
- /package/dist/{api-tokens-B6VgoE6M.mjs → api-tokens-Oq39ba-Z.mjs} +0 -0
|
@@ -63,6 +63,9 @@ export const RESOLVED_VIRTUAL_SEED_ID = "\0" + VIRTUAL_SEED_ID;
|
|
|
63
63
|
export const VIRTUAL_WAIT_UNTIL_ID = "virtual:emdash/wait-until";
|
|
64
64
|
export const RESOLVED_VIRTUAL_WAIT_UNTIL_ID = "\0" + VIRTUAL_WAIT_UNTIL_ID;
|
|
65
65
|
|
|
66
|
+
export const VIRTUAL_SCHEDULER_ID = "virtual:emdash/scheduler";
|
|
67
|
+
export const RESOLVED_VIRTUAL_SCHEDULER_ID = "\0" + VIRTUAL_SCHEDULER_ID;
|
|
68
|
+
|
|
66
69
|
/**
|
|
67
70
|
* Generates the config virtual module.
|
|
68
71
|
*/
|
|
@@ -413,6 +416,42 @@ export function generateWaitUntilModule(adapterName: string | undefined): string
|
|
|
413
416
|
return `export const waitUntil = undefined;`;
|
|
414
417
|
}
|
|
415
418
|
|
|
419
|
+
/**
|
|
420
|
+
* Generates the scheduler virtual module.
|
|
421
|
+
*
|
|
422
|
+
* Decides — at build time, from the Astro adapter — whether the runtime gets a
|
|
423
|
+
* long-lived timer heartbeat. A *production* Cloudflare build has no persistent
|
|
424
|
+
* timers, so the Worker's `scheduled()` handler (a Cron Trigger) drives
|
|
425
|
+
* `runScheduledTasks()` instead and this exports `null`. Every other case — any
|
|
426
|
+
* other adapter (Node, Bun), and crucially local `astro dev` even under the
|
|
427
|
+
* Cloudflare adapter (no Cron Trigger fires in dev) — gets a `NodeCronScheduler`
|
|
428
|
+
* factory so plugin cron, scheduled publishing, and cleanup still run.
|
|
429
|
+
*
|
|
430
|
+
* Keeping the adapter check here — rather than in core's runtime — means the
|
|
431
|
+
* runtime has no Cloudflare-specific code path; it just calls `createScheduler`
|
|
432
|
+
* if one was injected. Mirrors the wait-until module's approach.
|
|
433
|
+
*/
|
|
434
|
+
export function generateSchedulerModule(
|
|
435
|
+
adapterName: string | undefined,
|
|
436
|
+
command: "build" | "serve" | undefined,
|
|
437
|
+
): string {
|
|
438
|
+
// Only suppress the timer for an actual Cloudflare *build* — that artifact
|
|
439
|
+
// runs in workerd where a Cron Trigger drives scheduled work. In `serve`
|
|
440
|
+
// (local dev) nothing fires the Cron Trigger, so fall through to the timer.
|
|
441
|
+
if (adapterName === "@astrojs/cloudflare" && command !== "serve") {
|
|
442
|
+
return `// Serverless build: an external Cron Trigger drives scheduled work.
|
|
443
|
+
export const createScheduler = null;
|
|
444
|
+
`;
|
|
445
|
+
}
|
|
446
|
+
return `// Long-lived runtime (or local dev): drive scheduled work from an in-process timer.
|
|
447
|
+
import { NodeCronScheduler } from "emdash";
|
|
448
|
+
|
|
449
|
+
export function createScheduler(executor) {
|
|
450
|
+
return new NodeCronScheduler(executor);
|
|
451
|
+
}
|
|
452
|
+
`;
|
|
453
|
+
}
|
|
454
|
+
|
|
416
455
|
/**
|
|
417
456
|
* Generates the seed virtual module.
|
|
418
457
|
* Reads the user's seed file at build time (in Node context) and embeds it,
|
|
@@ -42,8 +42,11 @@ import {
|
|
|
42
42
|
RESOLVED_VIRTUAL_SEED_ID,
|
|
43
43
|
VIRTUAL_WAIT_UNTIL_ID,
|
|
44
44
|
RESOLVED_VIRTUAL_WAIT_UNTIL_ID,
|
|
45
|
+
VIRTUAL_SCHEDULER_ID,
|
|
46
|
+
RESOLVED_VIRTUAL_SCHEDULER_ID,
|
|
45
47
|
generateSeedModule,
|
|
46
48
|
generateWaitUntilModule,
|
|
49
|
+
generateSchedulerModule,
|
|
47
50
|
generateConfigModule,
|
|
48
51
|
generateDialectModule,
|
|
49
52
|
generateStorageModule,
|
|
@@ -203,6 +206,9 @@ export function createVirtualModulesPlugin(options: VitePluginOptions): Plugin {
|
|
|
203
206
|
if (id === VIRTUAL_WAIT_UNTIL_ID) {
|
|
204
207
|
return RESOLVED_VIRTUAL_WAIT_UNTIL_ID;
|
|
205
208
|
}
|
|
209
|
+
if (id === VIRTUAL_SCHEDULER_ID) {
|
|
210
|
+
return RESOLVED_VIRTUAL_SCHEDULER_ID;
|
|
211
|
+
}
|
|
206
212
|
},
|
|
207
213
|
load(id: string) {
|
|
208
214
|
if (id === RESOLVED_VIRTUAL_CONFIG_ID) {
|
|
@@ -271,6 +277,12 @@ export function createVirtualModulesPlugin(options: VitePluginOptions): Plugin {
|
|
|
271
277
|
if (id === RESOLVED_VIRTUAL_WAIT_UNTIL_ID) {
|
|
272
278
|
return generateWaitUntilModule(astroConfig.adapter?.name);
|
|
273
279
|
}
|
|
280
|
+
// Generate scheduler module — a NodeCronScheduler factory on
|
|
281
|
+
// long-lived runtimes, or null under the Cloudflare adapter where
|
|
282
|
+
// a Cron Trigger drives scheduled work instead.
|
|
283
|
+
if (id === RESOLVED_VIRTUAL_SCHEDULER_ID) {
|
|
284
|
+
return generateSchedulerModule(astroConfig.adapter?.name, viteCommand);
|
|
285
|
+
}
|
|
274
286
|
},
|
|
275
287
|
};
|
|
276
288
|
}
|
package/src/astro/middleware.ts
CHANGED
|
@@ -25,6 +25,8 @@ import * as virtualSandboxRunnerModule from "virtual:emdash/sandbox-runner";
|
|
|
25
25
|
// @ts-ignore - virtual module
|
|
26
26
|
import { sandboxedPlugins as virtualSandboxedPlugins } from "virtual:emdash/sandboxed-plugins";
|
|
27
27
|
// @ts-ignore - virtual module
|
|
28
|
+
import { createScheduler as virtualCreateScheduler } from "virtual:emdash/scheduler";
|
|
29
|
+
// @ts-ignore - virtual module
|
|
28
30
|
import { createStorage as virtualCreateStorage } from "virtual:emdash/storage";
|
|
29
31
|
|
|
30
32
|
import { after } from "../after.js";
|
|
@@ -39,6 +41,7 @@ import {
|
|
|
39
41
|
type RuntimeDependencies,
|
|
40
42
|
type SandboxedPluginEntry,
|
|
41
43
|
type MediaProviderEntry,
|
|
44
|
+
type CreateSchedulerFn,
|
|
42
45
|
} from "../emdash-runtime.js";
|
|
43
46
|
import { setI18nConfig } from "../i18n/config.js";
|
|
44
47
|
import type { Database, Storage } from "../index.js";
|
|
@@ -52,6 +55,7 @@ import {
|
|
|
52
55
|
type RequestMetrics,
|
|
53
56
|
runWithContext,
|
|
54
57
|
} from "../request-context.js";
|
|
58
|
+
import type { PublishedRef } from "../scheduled-publish.js";
|
|
55
59
|
import { isMissingTableError } from "../utils/db-errors.js";
|
|
56
60
|
import { createInitLock, type InitLock, initWithLock } from "../utils/init-lock.js";
|
|
57
61
|
import type { EmDashConfig } from "./integration/runtime.js";
|
|
@@ -174,6 +178,7 @@ function buildDependencies(config: EmDashConfig): RuntimeDependencies {
|
|
|
174
178
|
plugins: getPlugins(),
|
|
175
179
|
createDialect: virtualCreateDialect as (config: Record<string, unknown>) => unknown,
|
|
176
180
|
createStorage: virtualCreateStorage as ((config: Record<string, unknown>) => Storage) | null,
|
|
181
|
+
createScheduler: virtualCreateScheduler as CreateSchedulerFn | null,
|
|
177
182
|
sandboxEnabled: sandboxModule.sandboxEnabled as boolean,
|
|
178
183
|
sandboxBypassed: (sandboxModule.sandboxBypassed as boolean) ?? false,
|
|
179
184
|
sandboxedPluginEntries: (virtualSandboxedPlugins as SandboxedPluginEntry[]) || [],
|
|
@@ -243,6 +248,29 @@ async function getRuntime(
|
|
|
243
248
|
);
|
|
244
249
|
}
|
|
245
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Run scheduled maintenance (cron tasks, scheduled publishing, system cleanup)
|
|
253
|
+
* outside any request. Resolves the runtime from the build-time virtual config
|
|
254
|
+
* and the cached singleton — the same instance request handlers use.
|
|
255
|
+
*
|
|
256
|
+
* Wired into a platform heartbeat that is not a request: the Cloudflare Worker's
|
|
257
|
+
* `scheduled()` handler (Cron Trigger) calls this. On Node the runtime's own
|
|
258
|
+
* timer-based scheduler already drives the same work, so this isn't needed there.
|
|
259
|
+
*
|
|
260
|
+
* Returns the content promoted by the publishing sweep so the caller can purge
|
|
261
|
+
* edge-cache tags for it. `onPublished` (optional) is awaited after each
|
|
262
|
+
* collection's batch so the caller can invalidate edge-cache tags incrementally
|
|
263
|
+
* rather than only after the whole sweep.
|
|
264
|
+
*/
|
|
265
|
+
export async function runScheduledTasks(
|
|
266
|
+
options: { onPublished?: (refs: PublishedRef[]) => Promise<void> } = {},
|
|
267
|
+
): Promise<{ published: PublishedRef[] }> {
|
|
268
|
+
const config = getConfig();
|
|
269
|
+
if (!config) return { published: [] };
|
|
270
|
+
const runtime = await getRuntime(config);
|
|
271
|
+
return runtime.runScheduledTasks(options);
|
|
272
|
+
}
|
|
273
|
+
|
|
246
274
|
/**
|
|
247
275
|
* Astro attaches AstroCookies to outgoing responses via a well-known global
|
|
248
276
|
* symbol. Cloning a Response (`new Response(body, init)`) drops non-header
|
|
@@ -305,6 +333,9 @@ function pushMetricsTimings(
|
|
|
305
333
|
timings.push({ name: "db.last", dur: metrics.dbLastOffset, desc: "Last query at" });
|
|
306
334
|
}
|
|
307
335
|
}
|
|
336
|
+
if (metrics.rpcCount > 0) {
|
|
337
|
+
timings.push({ name: "rpc.count", dur: metrics.rpcCount, desc: "DB round trips" });
|
|
338
|
+
}
|
|
308
339
|
if (metrics.cacheHits + metrics.cacheMisses > 0) {
|
|
309
340
|
timings.push({ name: "cache.hit", dur: metrics.cacheHits, desc: "Cache hits" });
|
|
310
341
|
timings.push({ name: "cache.miss", dur: metrics.cacheMisses, desc: "Cache misses" });
|
|
@@ -482,9 +513,15 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
482
513
|
? { ...parent, db: anonScoped.db }
|
|
483
514
|
: { editMode: false, db: anonScoped.db, metrics };
|
|
484
515
|
return runWithContext(ctx, async () => {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
516
|
+
// commit() in finally: the write reached the primary independently
|
|
517
|
+
// of render, so the bookmark cookie must be persisted even if
|
|
518
|
+
// render throws -- otherwise a write-then-failed-render leaves the
|
|
519
|
+
// next request able to read pre-write state off a lagging replica.
|
|
520
|
+
try {
|
|
521
|
+
return await runAnon();
|
|
522
|
+
} finally {
|
|
523
|
+
anonScoped.commit();
|
|
524
|
+
}
|
|
488
525
|
});
|
|
489
526
|
}
|
|
490
527
|
return runAnon();
|
|
@@ -653,9 +690,14 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
653
690
|
? { ...parent, db: scoped.db }
|
|
654
691
|
: { editMode: false, db: scoped.db, metrics };
|
|
655
692
|
return runWithContext(ctx, async () => {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
693
|
+
// commit() in finally: persist the bookmark cookie even if render
|
|
694
|
+
// throws -- the write already reached the primary, so a failed
|
|
695
|
+
// render must not strand the next request on a stale replica read.
|
|
696
|
+
try {
|
|
697
|
+
return await renderAndFinalize();
|
|
698
|
+
} finally {
|
|
699
|
+
scoped.commit();
|
|
700
|
+
}
|
|
659
701
|
});
|
|
660
702
|
}
|
|
661
703
|
|
|
@@ -11,7 +11,7 @@ import { apiError, mapErrorStatus, unwrapResult } from "#api/error.js";
|
|
|
11
11
|
|
|
12
12
|
export const prerender = false;
|
|
13
13
|
|
|
14
|
-
export const POST: APIRoute = async ({ params, locals, cache }) => {
|
|
14
|
+
export const POST: APIRoute = async ({ params, locals, url, cache }) => {
|
|
15
15
|
const { emdash, user } = locals;
|
|
16
16
|
const collection = params.collection!;
|
|
17
17
|
const id = params.id!;
|
|
@@ -20,8 +20,10 @@ export const POST: APIRoute = async ({ params, locals, cache }) => {
|
|
|
20
20
|
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
const locale = url.searchParams.get("locale") || undefined;
|
|
24
|
+
|
|
23
25
|
// Fetch item to check ownership
|
|
24
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
26
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
25
27
|
if (!existing.success) {
|
|
26
28
|
return apiError(
|
|
27
29
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -20,7 +20,7 @@ import { contentPublishBody } from "#api/schemas.js";
|
|
|
20
20
|
|
|
21
21
|
export const prerender = false;
|
|
22
22
|
|
|
23
|
-
export const POST: APIRoute = async ({ params, request, locals, cache }) => {
|
|
23
|
+
export const POST: APIRoute = async ({ params, request, locals, url, cache }) => {
|
|
24
24
|
const { emdash, user } = locals;
|
|
25
25
|
const collection = params.collection!;
|
|
26
26
|
const id = params.id!;
|
|
@@ -34,8 +34,10 @@ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
34
34
|
const body = await parseOptionalBody(request, contentPublishBody, {});
|
|
35
35
|
if (isParseError(body)) return body;
|
|
36
36
|
|
|
37
|
+
const locale = url.searchParams.get("locale") || undefined;
|
|
38
|
+
|
|
37
39
|
// Fetch item to check ownership
|
|
38
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
40
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
39
41
|
if (!existing.success) {
|
|
40
42
|
return apiError(
|
|
41
43
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -34,7 +34,7 @@ function extractOwnership(data: unknown): { authorId: string; resolvedId: string
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
export const POST: APIRoute = async ({ params, request, locals, cache }) => {
|
|
37
|
+
export const POST: APIRoute = async ({ params, request, locals, url, cache }) => {
|
|
38
38
|
const { emdash, user } = locals;
|
|
39
39
|
const collection = params.collection!;
|
|
40
40
|
const id = params.id!;
|
|
@@ -45,8 +45,10 @@ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
45
45
|
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
const locale = url.searchParams.get("locale") || undefined;
|
|
49
|
+
|
|
48
50
|
// Fetch item to check ownership
|
|
49
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
51
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
50
52
|
if (!existing.success) {
|
|
51
53
|
return apiError(
|
|
52
54
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -68,7 +70,7 @@ export const POST: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
68
70
|
return unwrapResult(result);
|
|
69
71
|
};
|
|
70
72
|
|
|
71
|
-
export const DELETE: APIRoute = async ({ params, locals, cache }) => {
|
|
73
|
+
export const DELETE: APIRoute = async ({ params, locals, url, cache }) => {
|
|
72
74
|
const { emdash, user } = locals;
|
|
73
75
|
const collection = params.collection!;
|
|
74
76
|
const id = params.id!;
|
|
@@ -77,8 +79,10 @@ export const DELETE: APIRoute = async ({ params, locals, cache }) => {
|
|
|
77
79
|
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
const locale = url.searchParams.get("locale") || undefined;
|
|
83
|
+
|
|
80
84
|
// Fetch item to check ownership
|
|
81
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
85
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
82
86
|
if (!existing.success) {
|
|
83
87
|
return apiError(
|
|
84
88
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -11,7 +11,7 @@ import { apiError, mapErrorStatus, unwrapResult } from "#api/error.js";
|
|
|
11
11
|
|
|
12
12
|
export const prerender = false;
|
|
13
13
|
|
|
14
|
-
export const POST: APIRoute = async ({ params, locals, cache }) => {
|
|
14
|
+
export const POST: APIRoute = async ({ params, locals, url, cache }) => {
|
|
15
15
|
const { emdash, user } = locals;
|
|
16
16
|
const collection = params.collection!;
|
|
17
17
|
const id = params.id!;
|
|
@@ -20,8 +20,10 @@ export const POST: APIRoute = async ({ params, locals, cache }) => {
|
|
|
20
20
|
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
const locale = url.searchParams.get("locale") || undefined;
|
|
24
|
+
|
|
23
25
|
// Fetch item to check ownership
|
|
24
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
26
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
25
27
|
if (!existing.success) {
|
|
26
28
|
return apiError(
|
|
27
29
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -132,7 +132,7 @@ export const PUT: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
132
132
|
return unwrapResult(result);
|
|
133
133
|
};
|
|
134
134
|
|
|
135
|
-
export const DELETE: APIRoute = async ({ params, locals, cache }) => {
|
|
135
|
+
export const DELETE: APIRoute = async ({ params, locals, url, cache }) => {
|
|
136
136
|
const { emdash, user } = locals;
|
|
137
137
|
const collection = params.collection!;
|
|
138
138
|
const id = params.id!;
|
|
@@ -141,8 +141,10 @@ export const DELETE: APIRoute = async ({ params, locals, cache }) => {
|
|
|
141
141
|
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
const locale = url.searchParams.get("locale") || undefined;
|
|
145
|
+
|
|
144
146
|
// Fetch item to check ownership
|
|
145
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
147
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
146
148
|
if (!existing.success) {
|
|
147
149
|
return apiError(
|
|
148
150
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content authors endpoint - injected by EmDash integration
|
|
3
|
+
*
|
|
4
|
+
* GET /_emdash/api/content/{collection}/authors - List the distinct authors
|
|
5
|
+
* of a collection's live content, for the admin author filter.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { APIRoute } from "astro";
|
|
9
|
+
|
|
10
|
+
import { requirePerm } from "#api/authorize.js";
|
|
11
|
+
import { apiError, unwrapResult } from "#api/error.js";
|
|
12
|
+
|
|
13
|
+
export const prerender = false;
|
|
14
|
+
|
|
15
|
+
export const GET: APIRoute = async ({ params, locals }) => {
|
|
16
|
+
const { emdash, user } = locals;
|
|
17
|
+
const collection = params.collection!;
|
|
18
|
+
|
|
19
|
+
// Editorial capability, not plain read. This response carries author
|
|
20
|
+
// emails (PII) and reveals the authors of unpublished entries, so it must
|
|
21
|
+
// not be reachable by subscribers (content:read). content:read_drafts is
|
|
22
|
+
// the same tier the list route requires before it stops forcing
|
|
23
|
+
// status=published, so the visibility surfaces line up.
|
|
24
|
+
const denied = requirePerm(user, "content:read_drafts");
|
|
25
|
+
if (denied) return denied;
|
|
26
|
+
|
|
27
|
+
if (!emdash?.handleContentAuthors) {
|
|
28
|
+
return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const result = await emdash.handleContentAuthors(collection);
|
|
32
|
+
|
|
33
|
+
return unwrapResult(result);
|
|
34
|
+
};
|
|
@@ -13,7 +13,7 @@ import type { APIRoute } from "astro";
|
|
|
13
13
|
import { hashString } from "emdash";
|
|
14
14
|
|
|
15
15
|
import { requirePerm } from "#api/authorize.js";
|
|
16
|
-
import { handleError, requireDb } from "#api/error.js";
|
|
16
|
+
import { apiSuccess, handleError, requireDb } from "#api/error.js";
|
|
17
17
|
import { SchemaRegistry } from "#schema/registry.js";
|
|
18
18
|
import { generateTypeScript } from "#schema/zod-generator.js";
|
|
19
19
|
|
|
@@ -89,20 +89,12 @@ import type { PortableTextBlock } from "emdash";
|
|
|
89
89
|
|
|
90
90
|
const version = await hashString(JSON.stringify(schemaExport));
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
status: 200,
|
|
99
|
-
headers: {
|
|
100
|
-
"Content-Type": "application/json",
|
|
101
|
-
"Cache-Control": "private, no-store",
|
|
102
|
-
"X-Schema-Version": version,
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
);
|
|
92
|
+
const response = apiSuccess({
|
|
93
|
+
...schemaExport,
|
|
94
|
+
version,
|
|
95
|
+
});
|
|
96
|
+
response.headers.set("X-Schema-Version", version);
|
|
97
|
+
return response;
|
|
106
98
|
} catch (error) {
|
|
107
99
|
return handleError(error, "Schema export failed", "SCHEMA_EXPORT_ERROR");
|
|
108
100
|
}
|
|
@@ -23,6 +23,7 @@ import { getSiteSettingsWithDb } from "#settings/index.js";
|
|
|
23
23
|
|
|
24
24
|
import { getI18nConfig, isI18nEnabled } from "../../i18n/config.js";
|
|
25
25
|
import { interpolateUrlPattern, localizePath } from "../../i18n/resolve.js";
|
|
26
|
+
import { buildSeoImageUrl } from "../../seo/media-url.js";
|
|
26
27
|
|
|
27
28
|
export const prerender = false;
|
|
28
29
|
|
|
@@ -112,8 +113,8 @@ export const GET: APIRoute = async ({ params, locals, url }) => {
|
|
|
112
113
|
const lines: string[] = ['<?xml version="1.0" encoding="UTF-8"?>'];
|
|
113
114
|
lines.push(
|
|
114
115
|
useXhtml
|
|
115
|
-
? '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">'
|
|
116
|
-
: '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">',
|
|
116
|
+
? '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">'
|
|
117
|
+
: '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">',
|
|
117
118
|
);
|
|
118
119
|
|
|
119
120
|
const writeUrl = async (entry: Entry, siblings: Entry[] | null) => {
|
|
@@ -127,6 +128,16 @@ export const GET: APIRoute = async ({ params, locals, url }) => {
|
|
|
127
128
|
lines.push(` <loc>${escapeXml(loc)}</loc>`);
|
|
128
129
|
lines.push(` <lastmod>${escapeXml(entry.updatedAt)}</lastmod>`);
|
|
129
130
|
|
|
131
|
+
// Google image sitemap extension: advertise the entry's SEO
|
|
132
|
+
// image (the same "preferred image" used for og:image) so it
|
|
133
|
+
// can be discovered and indexed for Google Images.
|
|
134
|
+
if (entry.image) {
|
|
135
|
+
const imageLoc = buildSeoImageUrl(entry.image, siteUrl);
|
|
136
|
+
lines.push(" <image:image>");
|
|
137
|
+
lines.push(` <image:loc>${escapeXml(imageLoc)}</image:loc>`);
|
|
138
|
+
lines.push(" </image:image>");
|
|
139
|
+
}
|
|
140
|
+
|
|
130
141
|
if (useXhtml && siblings && siblings.length > 1) {
|
|
131
142
|
// Emit one xhtml:link per sibling (including self -- Google
|
|
132
143
|
// recommends including the page's own hreflang annotation).
|
package/src/astro/types.ts
CHANGED
|
@@ -233,9 +233,16 @@ export interface EmDashHandlers {
|
|
|
233
233
|
orderBy?: string;
|
|
234
234
|
order?: "asc" | "desc";
|
|
235
235
|
locale?: string;
|
|
236
|
+
q?: string;
|
|
237
|
+
authorId?: string;
|
|
238
|
+
dateField?: "createdAt" | "updatedAt" | "publishedAt";
|
|
239
|
+
dateFrom?: string;
|
|
240
|
+
dateTo?: string;
|
|
236
241
|
},
|
|
237
242
|
) => Promise<HandlerResponse>;
|
|
238
243
|
|
|
244
|
+
handleContentAuthors: (collection: string) => Promise<HandlerResponse>;
|
|
245
|
+
|
|
239
246
|
handleContentGet: (
|
|
240
247
|
collection: string,
|
|
241
248
|
id: string,
|
|
@@ -313,7 +320,7 @@ export interface EmDashHandlers {
|
|
|
313
320
|
handleContentPublish: (
|
|
314
321
|
collection: string,
|
|
315
322
|
id: string,
|
|
316
|
-
options?: { publishedAt?: string },
|
|
323
|
+
options?: { publishedAt?: string; requireScheduledDue?: boolean },
|
|
317
324
|
) => Promise<HandlerResponse>;
|
|
318
325
|
|
|
319
326
|
handleContentUnpublish: (collection: string, id: string) => Promise<HandlerResponse>;
|
package/src/bylines/index.ts
CHANGED
|
@@ -320,6 +320,63 @@ export async function getBylinesForEntries(
|
|
|
320
320
|
return result;
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Get content entries credited to a byline, in any credit position.
|
|
325
|
+
*
|
|
326
|
+
* Unlike filtering on the content table's `primary_byline_id` column (which
|
|
327
|
+
* only finds entries where the byline is the first/primary credit), this
|
|
328
|
+
* matches every explicit credit recorded in `_emdash_content_bylines`, so
|
|
329
|
+
* co-authored entries where the byline is a secondary credit are included.
|
|
330
|
+
*
|
|
331
|
+
* `byline` is matched against the byline's `translation_group` (the value
|
|
332
|
+
* stored on credits since migration 040), so a single credit spans every
|
|
333
|
+
* locale variant of the byline. Pass `byline.translationGroup ?? byline.id`
|
|
334
|
+
* from `getByline` / `getBylineBySlug`. An array matches any of the given
|
|
335
|
+
* bylines (OR).
|
|
336
|
+
*
|
|
337
|
+
* The result respects the active locale, status, ordering, and eager
|
|
338
|
+
* hydration of `getEmDashCollection`.
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* ```ts
|
|
342
|
+
* import { getBylineBySlug, getEntriesByByline } from "emdash";
|
|
343
|
+
*
|
|
344
|
+
* const byline = await getBylineBySlug("jane-doe");
|
|
345
|
+
* if (byline) {
|
|
346
|
+
* const posts = await getEntriesByByline("posts", byline.translationGroup ?? byline.id, {
|
|
347
|
+
* orderBy: { published_at: "desc" },
|
|
348
|
+
* });
|
|
349
|
+
* }
|
|
350
|
+
* ```
|
|
351
|
+
*
|
|
352
|
+
* @param collection - The collection slug (e.g. "posts")
|
|
353
|
+
* @param byline - A byline translation group, or an array of them (OR)
|
|
354
|
+
* @param options - Optional locale, ordering, status, and limit
|
|
355
|
+
*/
|
|
356
|
+
export async function getEntriesByByline(
|
|
357
|
+
collection: string,
|
|
358
|
+
byline: string | string[],
|
|
359
|
+
options: {
|
|
360
|
+
locale?: string;
|
|
361
|
+
orderBy?: Record<string, "asc" | "desc">;
|
|
362
|
+
status?: "draft" | "published" | "archived";
|
|
363
|
+
limit?: number;
|
|
364
|
+
} = {},
|
|
365
|
+
): Promise<Array<{ id: string; data: Record<string, unknown> }>> {
|
|
366
|
+
const { getEmDashCollection } = await import("../query.js");
|
|
367
|
+
|
|
368
|
+
const queryOptions: Record<string, unknown> = {
|
|
369
|
+
where: { byline },
|
|
370
|
+
};
|
|
371
|
+
if (options.locale !== undefined) queryOptions.locale = options.locale;
|
|
372
|
+
if (options.orderBy !== undefined) queryOptions.orderBy = options.orderBy;
|
|
373
|
+
if (options.status !== undefined) queryOptions.status = options.status;
|
|
374
|
+
if (options.limit !== undefined) queryOptions.limit = options.limit;
|
|
375
|
+
|
|
376
|
+
const { entries } = await getEmDashCollection(collection, queryOptions);
|
|
377
|
+
return entries;
|
|
378
|
+
}
|
|
379
|
+
|
|
323
380
|
/** Reads `author_id` + `primary_byline_id` for one entry in a single query. */
|
|
324
381
|
async function getEntryContext(
|
|
325
382
|
db: Awaited<ReturnType<typeof getDb>>,
|
|
@@ -13,6 +13,7 @@ import { pipeline } from "node:stream/promises";
|
|
|
13
13
|
import { imageSize } from "image-size";
|
|
14
14
|
import { packTar } from "modern-tar/fs";
|
|
15
15
|
|
|
16
|
+
import { capabilitiesToDeclaredAccess } from "../../plugins/types.js";
|
|
16
17
|
import type {
|
|
17
18
|
PluginManifest,
|
|
18
19
|
ResolvedPlugin,
|
|
@@ -151,6 +152,7 @@ export function extractManifest(plugin: ResolvedPlugin): PluginManifest {
|
|
|
151
152
|
return {
|
|
152
153
|
id: plugin.id,
|
|
153
154
|
version: plugin.version,
|
|
155
|
+
declaredAccess: capabilitiesToDeclaredAccess(plugin.capabilities, plugin.allowedHosts),
|
|
154
156
|
capabilities: plugin.capabilities,
|
|
155
157
|
allowedHosts: plugin.allowedHosts,
|
|
156
158
|
storage: plugin.storage,
|
|
@@ -20,7 +20,7 @@ import { OptionsRepository } from "../../database/repositories/options.js";
|
|
|
20
20
|
import { TaxonomyRepository } from "../../database/repositories/taxonomy.js";
|
|
21
21
|
import type { Database } from "../../database/types.js";
|
|
22
22
|
import { validateIdentifier } from "../../database/validate.js";
|
|
23
|
-
import { isI18nEnabled } from "../../i18n/config.js";
|
|
23
|
+
import { getI18nConfig, isI18nEnabled } from "../../i18n/config.js";
|
|
24
24
|
import { SchemaRegistry } from "../../schema/registry.js";
|
|
25
25
|
import type { FieldType } from "../../schema/types.js";
|
|
26
26
|
import type {
|
|
@@ -128,7 +128,12 @@ export async function exportSeed(db: Kysely<Database>, withContent?: string): Pr
|
|
|
128
128
|
// middleware, but the CLI never does, so `isI18nEnabled()` is always false
|
|
129
129
|
// under `emdash export-seed` (#1330). Detecting multiple locales in the data
|
|
130
130
|
// keeps the export locale-aware without the runtime flag.
|
|
131
|
-
const i18nEnabled = await
|
|
131
|
+
const { i18nEnabled, defaultLocale } = await detectLocaleInfo(db, seed.collections);
|
|
132
|
+
|
|
133
|
+
// Self-describe the default locale so a non-`en` single-locale project
|
|
134
|
+
// survives the round-trip: `emdash seed` runs outside the runtime and would
|
|
135
|
+
// otherwise backfill omitted locales as `en` (#1421).
|
|
136
|
+
if (defaultLocale) seed.defaultLocale = defaultLocale;
|
|
132
137
|
|
|
133
138
|
// 3. Export taxonomy definitions and terms
|
|
134
139
|
seed.taxonomies = await exportTaxonomies(db, i18nEnabled);
|
|
@@ -216,7 +221,7 @@ async function exportBylines(
|
|
|
216
221
|
}
|
|
217
222
|
|
|
218
223
|
/**
|
|
219
|
-
* Determine
|
|
224
|
+
* Determine locale-awareness and the data's default locale for the export.
|
|
220
225
|
*
|
|
221
226
|
* The runtime initializes the i18n config in middleware, but the CLI never does,
|
|
222
227
|
* so `isI18nEnabled()` is always false under `emdash export-seed` (#1330). When
|
|
@@ -227,39 +232,50 @@ async function exportBylines(
|
|
|
227
232
|
* genuinely single-locale project from a multi-locale one. This keeps
|
|
228
233
|
* single-locale exports on bare ids and gives multi-locale exports the
|
|
229
234
|
* per-locale suffix they need to avoid duplicate seed ids.
|
|
235
|
+
*
|
|
236
|
+
* `defaultLocale` self-describes the single-locale case so a non-`en` default
|
|
237
|
+
* survives the round-trip (#1421). When more than one locale is present every
|
|
238
|
+
* row already carries its own `locale`, so no fallback is needed and we leave it
|
|
239
|
+
* undefined rather than guess which locale is the "default" without the runtime
|
|
240
|
+
* config.
|
|
230
241
|
*/
|
|
231
|
-
async function
|
|
242
|
+
async function detectLocaleInfo(
|
|
232
243
|
db: Kysely<Database>,
|
|
233
244
|
collections: SeedCollection[],
|
|
234
|
-
): Promise<boolean> {
|
|
235
|
-
|
|
245
|
+
): Promise<{ i18nEnabled: boolean; defaultLocale: string | undefined }> {
|
|
246
|
+
const config = getI18nConfig();
|
|
247
|
+
if (isI18nEnabled() && config) {
|
|
248
|
+
return { i18nEnabled: true, defaultLocale: config.defaultLocale };
|
|
249
|
+
}
|
|
236
250
|
|
|
237
251
|
const locales = new Set<string>();
|
|
238
|
-
const collectDistinctLocales = async (tableRef: ReturnType<typeof sql.ref>): Promise<
|
|
252
|
+
const collectDistinctLocales = async (tableRef: ReturnType<typeof sql.ref>): Promise<void> => {
|
|
239
253
|
const result = await sql<{ locale: string | null }>`
|
|
240
254
|
SELECT DISTINCT locale FROM ${tableRef}
|
|
241
255
|
`.execute(db);
|
|
242
256
|
for (const row of result.rows) {
|
|
243
257
|
if (row.locale) locales.add(row.locale);
|
|
244
258
|
}
|
|
245
|
-
return locales.size > 1;
|
|
246
259
|
};
|
|
247
260
|
|
|
248
|
-
|
|
249
|
-
|
|
261
|
+
await collectDistinctLocales(sql.ref("_emdash_taxonomy_defs"));
|
|
262
|
+
await collectDistinctLocales(sql.ref("_emdash_menus"));
|
|
250
263
|
|
|
251
264
|
for (const collection of collections) {
|
|
252
265
|
validateIdentifier(collection.slug, "collection slug");
|
|
253
266
|
// On D1, deleteCollection is non-atomic, so a collection row can outlive
|
|
254
267
|
// its ec_* table. Skip missing tables rather than crashing the export.
|
|
255
268
|
try {
|
|
256
|
-
|
|
269
|
+
await collectDistinctLocales(sql.ref(`ec_${collection.slug}`));
|
|
257
270
|
} catch (error) {
|
|
258
271
|
if (!isMissingTableError(error)) throw error;
|
|
259
272
|
}
|
|
260
273
|
}
|
|
261
274
|
|
|
262
|
-
return
|
|
275
|
+
return {
|
|
276
|
+
i18nEnabled: locales.size > 1,
|
|
277
|
+
defaultLocale: locales.size === 1 ? [...locales][0] : undefined,
|
|
278
|
+
};
|
|
263
279
|
}
|
|
264
280
|
|
|
265
281
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Pure (no-DB) commands for working with EmDash secrets:
|
|
5
5
|
*
|
|
6
6
|
* - `emdash secrets generate` — emits a fresh `EMDASH_ENCRYPTION_KEY`.
|
|
7
|
-
* Optionally writes it to
|
|
7
|
+
* Optionally writes it to a local-secrets file (`.env`).
|
|
8
8
|
* - `emdash secrets fingerprint <key>` — prints the kid for a key,
|
|
9
9
|
* useful in CI for verifying what's been deployed without exposing
|
|
10
10
|
* the raw value.
|
|
@@ -87,7 +87,7 @@ const generateCommand = defineCommand({
|
|
|
87
87
|
write: {
|
|
88
88
|
type: "string",
|
|
89
89
|
description:
|
|
90
|
-
"Optional path to write the key to (e.g. .
|
|
90
|
+
"Optional path to write the key to (e.g. .env). " +
|
|
91
91
|
"Won't overwrite an existing entry without --force.",
|
|
92
92
|
},
|
|
93
93
|
force: {
|