emdash 0.16.0 → 0.17.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-C4yd_UJR.d.mts → adapters-C5AWLJSD.d.mts} +1 -1
- package/dist/{adapters-C4yd_UJR.d.mts.map → adapters-C5AWLJSD.d.mts.map} +1 -1
- package/dist/{allowed-origins-D0fFk9a6.mjs → allowed-origins-CyYLEJkp.mjs} +2 -2
- package/dist/{allowed-origins-D0fFk9a6.mjs.map → allowed-origins-CyYLEJkp.mjs.map} +1 -1
- package/dist/api/route-utils.d.mts +3 -3
- package/dist/api/route-utils.mjs +16 -16
- package/dist/api/schemas/index.d.mts +2 -2
- package/dist/api/schemas/index.mjs +3 -3
- package/dist/{api-BNKqxyFX.mjs → api-Dmz40c2V.mjs} +44 -22
- package/dist/api-Dmz40c2V.mjs.map +1 -0
- package/dist/{api-tokens-ucpcNXDt.mjs → api-tokens-VrXNiNvV.mjs} +2 -2
- package/dist/{api-tokens-ucpcNXDt.mjs.map → api-tokens-VrXNiNvV.mjs.map} +1 -1
- package/dist/{apply-BOPaD-s9.mjs → apply-CgamLmed.mjs} +93 -31
- package/dist/apply-CgamLmed.mjs.map +1 -0
- package/dist/astro/index.d.mts +10 -10
- package/dist/astro/index.mjs +19 -3
- 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.d.mts.map +1 -1
- package/dist/astro/middleware/redirect.mjs +9 -5
- package/dist/astro/middleware/redirect.mjs.map +1 -1
- package/dist/astro/middleware/request-context.mjs +2 -2
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.mjs +66 -65
- 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.d.mts +8 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +23 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_.d.mts +10 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +55 -0
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/index.d.mts +9 -0
- package/dist/astro/routes/api/admin/byline-fields/index.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +43 -0
- package/dist/astro/routes/api/admin/byline-fields/index.mjs.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/reorder.d.mts +8 -0
- package/dist/astro/routes/api/admin/byline-fields/reorder.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +27 -0
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs.map +1 -0
- package/dist/astro/routes/api/admin/bylines/_id_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +27 -28
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +13 -12
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +15 -13
- package/dist/astro/routes/api/admin/bylines/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +10 -10
- 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 +4 -4
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- 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 +35 -34
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +35 -34
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +35 -34
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +35 -34
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +34 -33
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +34 -33
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +34 -33
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +2 -2
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +5 -5
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
- 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 +9 -9
- package/dist/astro/routes/api/auth/invite/index.mjs +6 -6
- package/dist/astro/routes/api/auth/invite/register-options.mjs +8 -8
- 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.d.mts.map +1 -1
- package/dist/astro/routes/api/auth/me.mjs +18 -11
- package/dist/astro/routes/api/auth/me.mjs.map +1 -1
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +3 -3
- 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 +8 -8
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +9 -9
- package/dist/astro/routes/api/auth/passkey/verify.mjs +9 -9
- package/dist/astro/routes/api/auth/signup/complete.mjs +9 -9
- 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 +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 +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +6 -6
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +6 -6
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +18 -13
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs.map +1 -1
- 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_.d.mts.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +9 -7
- package/dist/astro/routes/api/content/_collection_/_id_.mjs.map +1 -1
- 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 +3 -3
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +10 -10
- 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 +11 -10
- package/dist/astro/routes/api/import/wordpress/execute.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/media.mjs +8 -8
- 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 +10 -10
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +13 -11
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs.map +1 -1
- package/dist/astro/routes/api/manifest.mjs +4 -4
- package/dist/astro/routes/api/mcp.mjs +34 -30
- package/dist/astro/routes/api/mcp.mjs.map +1 -1
- 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 +8 -8
- package/dist/astro/routes/api/media.d.mts.map +1 -1
- package/dist/astro/routes/api/media.mjs +13 -12
- package/dist/astro/routes/api/media.mjs.map +1 -1
- 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 +9 -9
- package/dist/astro/routes/api/oauth/device/token.mjs +8 -8
- 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 +10 -7
- 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 +8 -8
- package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
- package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
- package/dist/astro/routes/api/redirects/index.mjs +9 -9
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +34 -33
- package/dist/astro/routes/api/schema/collections/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/index.mjs +6 -6
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +34 -33
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +34 -33
- package/dist/astro/routes/api/schema/orphans/index.mjs.map +1 -1
- package/dist/astro/routes/api/search/enable.mjs +9 -9
- package/dist/astro/routes/api/search/index.mjs +8 -8
- package/dist/astro/routes/api/search/rebuild.mjs +9 -9
- package/dist/astro/routes/api/search/stats.mjs +6 -6
- package/dist/astro/routes/api/search/suggest.mjs +8 -8
- package/dist/astro/routes/api/sections/_slug_.mjs +8 -8
- package/dist/astro/routes/api/sections/index.mjs +8 -8
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +11 -11
- package/dist/astro/routes/api/setup/admin-verify.mjs +10 -10
- package/dist/astro/routes/api/setup/admin.mjs +9 -9
- package/dist/astro/routes/api/setup/dev-bypass.mjs +24 -23
- package/dist/astro/routes/api/setup/dev-bypass.mjs.map +1 -1
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +24 -23
- package/dist/astro/routes/api/setup/index.mjs.map +1 -1
- package/dist/astro/routes/api/setup/status.mjs +4 -4
- package/dist/astro/routes/api/snapshot.mjs +5 -5
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +12 -12
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +12 -12
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +12 -12
- package/dist/astro/routes/api/taxonomies/index.mjs +12 -12
- package/dist/astro/routes/api/themes/preview.mjs +5 -5
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/well-known/auth.mjs +1 -1
- 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 +8 -8
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +8 -8
- package/dist/astro/routes/api/widget-areas/_name_.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/index.mjs +8 -8
- package/dist/astro/routes/api/widget-components.mjs +3 -3
- package/dist/astro/routes/robots.txt.mjs +6 -6
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +8 -8
- package/dist/astro/routes/sitemap.xml.mjs +7 -7
- package/dist/astro/types.d.mts +13 -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-Bn4S4DUT.mjs → authorize-_wWM_44T.mjs} +2 -2
- package/dist/{authorize-Bn4S4DUT.mjs.map → authorize-_wWM_44T.mjs.map} +1 -1
- package/dist/byline-BrIVWLm-.mjs +925 -0
- package/dist/byline-BrIVWLm-.mjs.map +1 -0
- package/dist/{bylines-B2_XmnSU.d.mts → byline-fields-BNy7Ng1U.d.mts} +154 -26
- package/dist/byline-fields-BNy7Ng1U.d.mts.map +1 -0
- package/dist/byline-fields-DC3Wkk-U.mjs +123 -0
- package/dist/byline-fields-DC3Wkk-U.mjs.map +1 -0
- package/dist/byline-fields-Dr-xcb6S.mjs +238 -0
- package/dist/byline-fields-Dr-xcb6S.mjs.map +1 -0
- package/dist/byline-registry-CxK5g559.mjs +406 -0
- package/dist/byline-registry-CxK5g559.mjs.map +1 -0
- package/dist/{bylines-n6nykUyI.mjs → bylines-C_POWmGT.mjs} +25 -11
- package/dist/{bylines-n6nykUyI.mjs.map → bylines-C_POWmGT.mjs.map} +1 -1
- package/dist/bylines-sqExMElV.mjs +204 -0
- package/dist/bylines-sqExMElV.mjs.map +1 -0
- package/dist/{cache-BcI1yUjR.mjs → cache-wsDkA8ru.mjs} +2 -2
- package/dist/{cache-BcI1yUjR.mjs.map → cache-wsDkA8ru.mjs.map} +1 -1
- package/dist/{challenge-store-Dng1SxKT.mjs → challenge-store-DGwuCc4R.mjs} +1 -1
- package/dist/{challenge-store-Dng1SxKT.mjs.map → challenge-store-DGwuCc4R.mjs.map} +1 -1
- package/dist/{chunks-cYG4SnIP.mjs → chunks-BAYkM-CF.mjs} +2 -2
- package/dist/{chunks-cYG4SnIP.mjs.map → chunks-BAYkM-CF.mjs.map} +1 -1
- package/dist/cli/index.mjs +29 -23
- package/dist/cli/index.mjs.map +1 -1
- package/dist/client/cf-access.d.mts +1 -1
- package/dist/client/index.d.mts +2 -1
- package/dist/client/index.d.mts.map +1 -1
- package/dist/client/index.mjs +4 -2
- package/dist/client/index.mjs.map +1 -1
- package/dist/{comment-C76G-9tz.mjs → comment-Cd29aktf.mjs} +2 -2
- package/dist/{comment-C76G-9tz.mjs.map → comment-Cd29aktf.mjs.map} +1 -1
- package/dist/{comments-CCxFFGY1.mjs → comments-B7ufhkxN.mjs} +3 -3
- package/dist/{comments-CCxFFGY1.mjs.map → comments-B7ufhkxN.mjs.map} +1 -1
- package/dist/{components-Dx3DM0gg.mjs → components-CTfpu3PZ.mjs} +1 -1
- package/dist/{components-Dx3DM0gg.mjs.map → components-CTfpu3PZ.mjs.map} +1 -1
- package/dist/{content-8voQNTXX.mjs → content-BbqKo3Kc.mjs} +22 -3
- package/dist/content-BbqKo3Kc.mjs.map +1 -0
- package/dist/{context-B7qiYrz2.mjs → context-BsF1rhoI.mjs} +9 -9
- package/dist/{context-B7qiYrz2.mjs.map → context-BsF1rhoI.mjs.map} +1 -1
- package/dist/{cron-Bd3b3iuj.mjs → cron-DZovZUnC.mjs} +1 -1
- package/dist/{cron-Bd3b3iuj.mjs.map → cron-DZovZUnC.mjs.map} +1 -1
- package/dist/{dashboard-BeaFSPpx.mjs → dashboard-BwIX9r-X.mjs} +4 -4
- package/dist/{dashboard-BeaFSPpx.mjs.map → dashboard-BwIX9r-X.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/{db-errors-BiYqoX-n.mjs → db-errors-CtzxKBxe.mjs} +1 -1
- package/dist/{db-errors-BiYqoX-n.mjs.map → db-errors-CtzxKBxe.mjs.map} +1 -1
- package/dist/{default-BvTAYCzx.mjs → default-xLFNSsZ9.mjs} +1 -1
- package/dist/{default-BvTAYCzx.mjs.map → default-xLFNSsZ9.mjs.map} +1 -1
- package/dist/{device-flow-B9oG8PwP.mjs → device-flow-ptLrVINd.mjs} +4 -4
- package/dist/{device-flow-B9oG8PwP.mjs.map → device-flow-ptLrVINd.mjs.map} +1 -1
- package/dist/{email-console-CubRll9q.mjs → email-console-DHT2Fbpj.mjs} +1 -1
- package/dist/{email-console-CubRll9q.mjs.map → email-console-DHT2Fbpj.mjs.map} +1 -1
- package/dist/{error-ChfADBuu.mjs → error-npZWBSb7.mjs} +7 -3
- package/dist/error-npZWBSb7.mjs.map +1 -0
- package/dist/{escape-Cg6kMELH.mjs → escape-bIyGoW5W.mjs} +1 -1
- package/dist/{escape-Cg6kMELH.mjs.map → escape-bIyGoW5W.mjs.map} +1 -1
- package/dist/{fts-manager-C_b-4x8u.mjs → fts-manager-DmUAk-kQ.mjs} +2 -2
- package/dist/{fts-manager-C_b-4x8u.mjs.map → fts-manager-DmUAk-kQ.mjs.map} +1 -1
- package/dist/{hash-DlUxGhQS.mjs → hash-9w3pd3-m.mjs} +1 -1
- package/dist/{hash-DlUxGhQS.mjs.map → hash-9w3pd3-m.mjs.map} +1 -1
- package/dist/{import-DG80rC_I.mjs → import-Dh8bWmyq.mjs} +3 -3
- package/dist/{import-DG80rC_I.mjs.map → import-Dh8bWmyq.mjs.map} +1 -1
- package/dist/{index-BPZFAcgE.d.mts → index-CjKdMZ3U.d.mts} +39 -17
- package/dist/index-CjKdMZ3U.d.mts.map +1 -0
- package/dist/{index-CC42STEm.d.mts → index-D60_SzHG.d.mts} +3 -3
- package/dist/{index-CC42STEm.d.mts.map → index-D60_SzHG.d.mts.map} +1 -1
- package/dist/index.d.mts +17 -17
- package/dist/index.mjs +55 -54
- package/dist/{load-CLFRjk9r.mjs → load-DsoLq7ex.mjs} +2 -2
- package/dist/{load-CLFRjk9r.mjs.map → load-DsoLq7ex.mjs.map} +1 -1
- package/dist/{loader-D-vIJjfY.mjs → loader-CJ6lWO0d.mjs} +75 -19
- package/dist/loader-CJ6lWO0d.mjs.map +1 -0
- package/dist/{manifest-schema-Czqf0TLu.mjs → manifest-schema-Cj-YrzrF.mjs} +1 -1
- package/dist/{manifest-schema-Czqf0TLu.mjs.map → manifest-schema-Cj-YrzrF.mjs.map} +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +11 -11
- package/dist/media/local-runtime.mjs +5 -5
- package/dist/{media-allowlist-BNloC69x.mjs → media-allowlist-CMcoYIjQ.mjs} +2 -2
- package/dist/{media-allowlist-BNloC69x.mjs.map → media-allowlist-CMcoYIjQ.mjs.map} +1 -1
- package/dist/{media-CKQd8AYU.mjs → media-jk_HzzOl.mjs} +7 -2
- package/dist/media-jk_HzzOl.mjs.map +1 -0
- package/dist/{menus-arUNspyU.mjs → menus-B-5-3aon.mjs} +2 -2
- package/dist/{menus-arUNspyU.mjs.map → menus-B-5-3aon.mjs.map} +1 -1
- package/dist/{menus-C-nWT5Tu.mjs → menus-CyMO6GBx.mjs} +27 -11
- package/dist/menus-CyMO6GBx.mjs.map +1 -0
- package/dist/{mime-KV5TqkMN.mjs → mime-CCEzze7W.mjs} +1 -1
- package/dist/{mime-KV5TqkMN.mjs.map → mime-CCEzze7W.mjs.map} +1 -1
- package/dist/{mode-CaaiebZI.mjs → mode-BjlXswIw.mjs} +1 -1
- package/dist/{mode-CaaiebZI.mjs.map → mode-BjlXswIw.mjs.map} +1 -1
- package/dist/{normalize-CN5kRSMC.mjs → normalize-DVV8nbrL.mjs} +1 -1
- package/dist/{normalize-CN5kRSMC.mjs.map → normalize-DVV8nbrL.mjs.map} +1 -1
- package/dist/{oauth-authorization-CTMeVfvj.mjs → oauth-authorization-DvBAL75d.mjs} +4 -4
- package/dist/{oauth-authorization-CTMeVfvj.mjs.map → oauth-authorization-DvBAL75d.mjs.map} +1 -1
- package/dist/{oauth-clients-eJCbkVSG.mjs → oauth-clients-8mPDStMv.mjs} +1 -1
- package/dist/{oauth-clients-eJCbkVSG.mjs.map → oauth-clients-8mPDStMv.mjs.map} +1 -1
- package/dist/{oauth-state-store-vOSdOeGe.mjs → oauth-state-store-BJ7YtrfD.mjs} +1 -1
- package/dist/{oauth-state-store-vOSdOeGe.mjs.map → oauth-state-store-BJ7YtrfD.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-3JwsVw6N.mjs → oauth-user-lookup-BdDSDvjF.mjs} +1 -1
- package/dist/{oauth-user-lookup-3JwsVw6N.mjs.map → oauth-user-lookup-BdDSDvjF.mjs.map} +1 -1
- package/dist/{options-DhV-gwJb.d.mts → options-tb7DJROi.d.mts} +3 -3
- package/dist/{options-DhV-gwJb.d.mts.map → options-tb7DJROi.d.mts.map} +1 -1
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-DHbXfvxO.mjs → parse-4zO5Y2DL.mjs} +2 -2
- package/dist/{parse-DHbXfvxO.mjs.map → parse-4zO5Y2DL.mjs.map} +1 -1
- package/dist/{passkey-config-BloQOT3y.mjs → passkey-config-BDVM86Tj.mjs} +1 -1
- package/dist/{passkey-config-BloQOT3y.mjs.map → passkey-config-BDVM86Tj.mjs.map} +1 -1
- package/dist/{placeholder-KCkkCtgQ.d.mts → placeholder-B9lUUEmj.d.mts} +1 -1
- package/dist/{placeholder-KCkkCtgQ.d.mts.map → placeholder-B9lUUEmj.d.mts.map} +1 -1
- package/dist/{placeholder-LqmHqvBw.mjs → placeholder-BZxr8W1j.mjs} +1 -1
- package/dist/{placeholder-LqmHqvBw.mjs.map → placeholder-BZxr8W1j.mjs.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/{preview-D4z0WONU.mjs → preview-BfuRkVKW.mjs} +2 -2
- package/dist/{preview-D4z0WONU.mjs.map → preview-BfuRkVKW.mjs.map} +1 -1
- package/dist/{public-url-CUWWFME2.mjs → public-url-egRHCy1m.mjs} +1 -1
- package/dist/{public-url-CUWWFME2.mjs.map → public-url-egRHCy1m.mjs.map} +1 -1
- package/dist/{query-7m6-l0f_.mjs → query-CuvjwhrE.mjs} +12 -12
- package/dist/{query-7m6-l0f_.mjs.map → query-CuvjwhrE.mjs.map} +1 -1
- package/dist/{rate-limit-D8RAXN8b.mjs → rate-limit-D6VQqBk_.mjs} +2 -2
- package/dist/{rate-limit-D8RAXN8b.mjs.map → rate-limit-D6VQqBk_.mjs.map} +1 -1
- package/dist/{redirect-CjfDGrTd.mjs → redirect-BZUJltlj.mjs} +2 -2
- package/dist/{redirect-CjfDGrTd.mjs.map → redirect-BZUJltlj.mjs.map} +1 -1
- package/dist/{redirect-BINiRYq4.mjs → redirect-Cw3JTlmj.mjs} +1 -1
- package/dist/{redirect-BINiRYq4.mjs.map → redirect-Cw3JTlmj.mjs.map} +1 -1
- package/dist/{redirects-COMLwsV5.mjs → redirects-C0L9JUk4.mjs} +19 -6
- package/dist/redirects-C0L9JUk4.mjs.map +1 -0
- package/dist/{redirects-CowoEHdE.mjs → redirects-DnYuqsEf.mjs} +3 -3
- package/dist/{redirects-CowoEHdE.mjs.map → redirects-DnYuqsEf.mjs.map} +1 -1
- package/dist/{registry-Cyp-dx6J.mjs → registry-Dn6gsx3L.mjs} +13 -5
- package/dist/{registry-Cyp-dx6J.mjs.map → registry-Dn6gsx3L.mjs.map} +1 -1
- package/dist/{request-cache-dzCt8TZB.mjs → request-cache-BYMs-BGX.mjs} +23 -2
- package/dist/{request-cache-dzCt8TZB.mjs.map → request-cache-BYMs-BGX.mjs.map} +1 -1
- package/dist/{request-meta-C_Cjii-T.mjs → request-meta-7ByVLxB-.mjs} +2 -2
- package/dist/{request-meta-C_Cjii-T.mjs.map → request-meta-7ByVLxB-.mjs.map} +1 -1
- package/dist/{resolve-D6sM-SgF.mjs → resolve-BqYMVG0D.mjs} +1 -1
- package/dist/{resolve-D6sM-SgF.mjs.map → resolve-BqYMVG0D.mjs.map} +1 -1
- package/dist/{runner-DSQBurMS.d.mts → runner-DM1yR5qd.d.mts} +2 -2
- package/dist/{runner-DSQBurMS.d.mts.map → runner-DM1yR5qd.d.mts.map} +1 -1
- package/dist/{runner-Drnvs96u.mjs → runner-eAgyIkeg.mjs} +284 -158
- package/dist/runner-eAgyIkeg.mjs.map +1 -0
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +2 -2
- package/dist/{schema-CI9mYPX3.mjs → schema--mYZX4D7.mjs} +5 -5
- package/dist/{schema-CI9mYPX3.mjs.map → schema--mYZX4D7.mjs.map} +1 -1
- package/dist/{search-DKz_mGBP.mjs → search-C6U_NvZI.mjs} +4 -4
- package/dist/{search-DKz_mGBP.mjs.map → search-C6U_NvZI.mjs.map} +1 -1
- package/dist/{secrets-rPdhEBkD.mjs → secrets-YYbTgB1w.mjs} +1 -1
- package/dist/{secrets-rPdhEBkD.mjs.map → secrets-YYbTgB1w.mjs.map} +1 -1
- package/dist/{sections-DBbCDIAT.mjs → sections-Ba-rJLKb.mjs} +3 -3
- package/dist/{sections-DBbCDIAT.mjs.map → sections-Ba-rJLKb.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +18 -17
- package/dist/seo/index.d.mts +1 -1
- package/dist/{seo-BGCyDlkb.mjs → seo-BTzb5ksq.mjs} +2 -2
- package/dist/{seo-BGCyDlkb.mjs.map → seo-BTzb5ksq.mjs.map} +1 -1
- package/dist/{seo-Dq707mNQ.mjs → seo-DfjLvu8i.mjs} +1 -1
- package/dist/{seo-Dq707mNQ.mjs.map → seo-DfjLvu8i.mjs.map} +1 -1
- package/dist/{service-B0H7U1Y9.mjs → service-Cn-kIfZn.mjs} +3 -3
- package/dist/{service-B0H7U1Y9.mjs.map → service-Cn-kIfZn.mjs.map} +1 -1
- package/dist/{settings-DfwNyQkf.mjs → settings-C65OSm41.mjs} +3 -3
- package/dist/{settings-DfwNyQkf.mjs.map → settings-C65OSm41.mjs.map} +1 -1
- package/dist/{settings-BSXRtTzk.mjs → settings-ChlQbwU0.mjs} +4 -4
- package/dist/{settings-BSXRtTzk.mjs.map → settings-ChlQbwU0.mjs.map} +1 -1
- package/dist/{setup-complete-MzzN9u0b.mjs → setup-complete-VoEZfasi.mjs} +1 -1
- package/dist/{setup-complete-MzzN9u0b.mjs.map → setup-complete-VoEZfasi.mjs.map} +1 -1
- package/dist/{setup-nonce-DXuriHsg.mjs → setup-nonce-Bm0uKqmf.mjs} +1 -1
- package/dist/{setup-nonce-DXuriHsg.mjs.map → setup-nonce-Bm0uKqmf.mjs.map} +1 -1
- package/dist/{site-url-xkhw1tcz.mjs → site-url-Cm8-sJy7.mjs} +1 -1
- package/dist/{site-url-xkhw1tcz.mjs.map → site-url-Cm8-sJy7.mjs.map} +1 -1
- package/dist/{ssrf-MZ-zrG6-.mjs → ssrf-BsVGIE0Z.mjs} +1 -1
- package/dist/{ssrf-MZ-zrG6-.mjs.map → ssrf-BsVGIE0Z.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/{taxonomies-CcvrMLbR.mjs → taxonomies-CgpzAU6F.mjs} +8 -8
- package/dist/{taxonomies-CcvrMLbR.mjs.map → taxonomies-CgpzAU6F.mjs.map} +1 -1
- package/dist/{taxonomies-4vx0nmMr.mjs → taxonomies-D72gTOg_.mjs} +4 -4
- package/dist/{taxonomies-4vx0nmMr.mjs.map → taxonomies-D72gTOg_.mjs.map} +1 -1
- package/dist/{taxonomy-zqGQUqgu.mjs → taxonomy-BBK-UAEo.mjs} +3 -3
- package/dist/{taxonomy-zqGQUqgu.mjs.map → taxonomy-BBK-UAEo.mjs.map} +1 -1
- package/dist/{tokens-N8otWMmj.mjs → tokens-Bx2afeT-.mjs} +1 -1
- package/dist/{tokens-N8otWMmj.mjs.map → tokens-Bx2afeT-.mjs.map} +1 -1
- package/dist/{transport-B6CHddbu.mjs → transport--Ck3RBin.mjs} +1 -1
- package/dist/{transport-B6CHddbu.mjs.map → transport--Ck3RBin.mjs.map} +1 -1
- package/dist/{transport-C2MGqtL6.d.mts → transport-OnMNbsIA.d.mts} +1 -1
- package/dist/{transport-C2MGqtL6.d.mts.map → transport-OnMNbsIA.d.mts.map} +1 -1
- package/dist/{trusted-proxy-97pajC2f.mjs → trusted-proxy-B4AfnoAp.mjs} +1 -1
- package/dist/{trusted-proxy-97pajC2f.mjs.map → trusted-proxy-B4AfnoAp.mjs.map} +1 -1
- package/dist/types-D8bhH891.mjs +125 -0
- package/dist/{types-DSZl1Dsv.mjs.map → types-D8bhH891.mjs.map} +1 -1
- package/dist/{types-DGHWRQgr.d.mts → types-DMwSpvcw.d.mts} +2 -2
- package/dist/{types-DGHWRQgr.d.mts.map → types-DMwSpvcw.d.mts.map} +1 -1
- package/dist/{types-bYmRn_Uy.d.mts → types-DWnN7weG.d.mts} +1 -1
- package/dist/{types-bYmRn_Uy.d.mts.map → types-DWnN7weG.d.mts.map} +1 -1
- package/dist/{types-Dgo6y-Ut.d.mts → types-DX6v9KzJ.d.mts} +1 -1
- package/dist/{types-Dgo6y-Ut.d.mts.map → types-DX6v9KzJ.d.mts.map} +1 -1
- package/dist/{types-DaqNzqVt.d.mts → types-DawhLFwy.d.mts} +35 -1
- package/dist/{types-DaqNzqVt.d.mts.map → types-DawhLFwy.d.mts.map} +1 -1
- package/dist/{types-CpUuGcd5.d.mts → types-DbCWhHet.d.mts} +8 -2
- package/dist/{types-CpUuGcd5.d.mts.map → types-DbCWhHet.d.mts.map} +1 -1
- package/dist/{types-Cd9UCu3t.mjs → types-DpFmlNyB.mjs} +1 -1
- package/dist/{types-Cd9UCu3t.mjs.map → types-DpFmlNyB.mjs.map} +1 -1
- package/dist/{types-D599-ruj.d.mts → types-Qa7-HJJC.d.mts} +1 -1
- package/dist/{types-D599-ruj.d.mts.map → types-Qa7-HJJC.d.mts.map} +1 -1
- package/dist/{types-B0bmgwMG.mjs → types-SF1DwGf2.mjs} +2 -2
- package/dist/types-SF1DwGf2.mjs.map +1 -0
- package/dist/{types-DaYDYW6g.d.mts → types-i8_uzhMD.d.mts} +40 -2
- package/dist/types-i8_uzhMD.d.mts.map +1 -0
- package/dist/{types-CkDSF81F.d.mts → types-kwqCOUxj.d.mts} +1 -1
- package/dist/{types-CkDSF81F.d.mts.map → types-kwqCOUxj.d.mts.map} +1 -1
- package/dist/{user-hUSOaIJy.mjs → user-X4rtyO4Y.mjs} +2 -2
- package/dist/{user-hUSOaIJy.mjs.map → user-X4rtyO4Y.mjs.map} +1 -1
- package/dist/{utils-C3wTAP-P.mjs → utils-C4Ih4DML.mjs} +1 -1
- package/dist/{utils-C3wTAP-P.mjs.map → utils-C4Ih4DML.mjs.map} +1 -1
- package/dist/{validate-IGltez8n.mjs → validate-DactmcJG.mjs} +23 -3
- package/dist/validate-DactmcJG.mjs.map +1 -0
- package/dist/{validate-DQtHw9NT.d.mts → validate-Dy6nkNls.d.mts} +25 -5
- package/dist/{validate-DQtHw9NT.d.mts.map → validate-Dy6nkNls.d.mts.map} +1 -1
- package/dist/{validation-Bmymau7y.mjs → validation-BYA4i85b.mjs} +6 -6
- package/dist/{validation-Bmymau7y.mjs.map → validation-BYA4i85b.mjs.map} +1 -1
- package/dist/version-FGcv0ooe.mjs +7 -0
- package/dist/{version-BTc87L3L.mjs.map → version-FGcv0ooe.mjs.map} +1 -1
- package/dist/{widgets-yHQa4c6c.mjs → widgets-DG-1jxnz.mjs} +3 -3
- package/dist/{widgets-yHQa4c6c.mjs.map → widgets-DG-1jxnz.mjs.map} +1 -1
- package/dist/{zod-generator-B80aap1J.mjs → zod-generator-BNAObjSt.mjs} +3 -3
- package/dist/{zod-generator-B80aap1J.mjs.map → zod-generator-BNAObjSt.mjs.map} +1 -1
- package/package.json +7 -7
- package/src/api/errors.ts +7 -0
- package/src/api/handlers/byline-fields.ts +212 -0
- package/src/api/handlers/bylines.ts +126 -5
- package/src/api/handlers/content.ts +43 -2
- package/src/api/handlers/media.ts +2 -0
- package/src/api/openapi/document.ts +3 -0
- package/src/api/schemas/byline-fields.ts +188 -0
- package/src/api/schemas/bylines.ts +42 -0
- package/src/api/schemas/content.ts +2 -0
- package/src/api/schemas/index.ts +1 -0
- package/src/api/schemas/media.ts +2 -0
- package/src/astro/integration/routes.ts +27 -0
- package/src/astro/middleware/redirect.ts +5 -1
- package/src/astro/routes/api/admin/byline-fields/[slug]/usage.ts +36 -0
- package/src/astro/routes/api/admin/byline-fields/[slug].ts +92 -0
- package/src/astro/routes/api/admin/byline-fields/index.ts +66 -0
- package/src/astro/routes/api/admin/byline-fields/reorder.ts +39 -0
- package/src/astro/routes/api/admin/bylines/[id]/index.ts +23 -21
- package/src/astro/routes/api/admin/bylines/index.ts +1 -0
- package/src/astro/routes/api/auth/me.ts +21 -10
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +15 -3
- package/src/astro/routes/api/content/[collection]/[id].ts +3 -1
- package/src/astro/routes/api/media.ts +1 -0
- package/src/astro/types.ts +1 -0
- package/src/bylines/field-defs-cache.ts +138 -0
- package/src/bylines/index.ts +37 -4
- package/src/cli/commands/content.ts +4 -2
- package/src/client/index.ts +4 -1
- package/src/components/InlinePortableTextEditor.tsx +69 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +7 -0
- package/src/content/converters/prosemirror-to-portable-text.ts +16 -0
- package/src/content/converters/types.ts +10 -0
- package/src/database/migrations/041_content_locale_list_index.ts +47 -0
- package/src/database/migrations/042_byline_fields.ts +157 -0
- package/src/database/migrations/runner.ts +4 -0
- package/src/database/repositories/byline.ts +758 -50
- package/src/database/repositories/content.ts +43 -3
- package/src/database/repositories/media.ts +14 -0
- package/src/database/repositories/types.ts +38 -0
- package/src/database/types.ts +44 -0
- package/src/emdash-runtime.ts +4 -1
- package/src/index.ts +1 -0
- package/src/loader.ts +98 -10
- package/src/mcp/server.ts +10 -1
- package/src/request-cache.ts +23 -0
- package/src/schema/byline-registry.ts +671 -0
- package/src/schema/registry.ts +14 -0
- package/src/schema/types.ts +133 -0
- package/src/seed/apply.ts +101 -14
- package/src/seed/types.ts +21 -0
- package/src/seed/validate.ts +39 -0
- package/dist/api-BNKqxyFX.mjs.map +0 -1
- package/dist/apply-BOPaD-s9.mjs.map +0 -1
- package/dist/byline-BDylH_m4.mjs +0 -404
- package/dist/byline-BDylH_m4.mjs.map +0 -1
- package/dist/bylines-B2_XmnSU.d.mts.map +0 -1
- package/dist/bylines-B7TFEvFf.mjs +0 -118
- package/dist/bylines-B7TFEvFf.mjs.map +0 -1
- package/dist/content-8voQNTXX.mjs.map +0 -1
- package/dist/error-ChfADBuu.mjs.map +0 -1
- package/dist/index-BPZFAcgE.d.mts.map +0 -1
- package/dist/loader-D-vIJjfY.mjs.map +0 -1
- package/dist/media-CKQd8AYU.mjs.map +0 -1
- package/dist/menus-C-nWT5Tu.mjs.map +0 -1
- package/dist/redirects-COMLwsV5.mjs.map +0 -1
- package/dist/runner-Drnvs96u.mjs.map +0 -1
- package/dist/setup-Cf_TyOv5.mjs +0 -137
- package/dist/setup-Cf_TyOv5.mjs.map +0 -1
- package/dist/types-B0bmgwMG.mjs.map +0 -1
- package/dist/types-DSZl1Dsv.mjs +0 -83
- package/dist/types-DaYDYW6g.d.mts.map +0 -1
- package/dist/validate-IGltez8n.mjs.map +0 -1
- package/dist/version-BTc87L3L.mjs +0 -7
- /package/dist/{api-tokens-iPIHAY8N.mjs → api-tokens-B6VgoE6M.mjs} +0 -0
- /package/dist/{ssrf-BIcd-aXW.mjs → ssrf-BvgVcfNQ.mjs} +0 -0
- /package/dist/{types-1NNkmTIn.mjs → types-Cj2S6FuC.mjs} +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byline custom-field schema management — single field CRUD.
|
|
3
|
+
*
|
|
4
|
+
* - GET /_emdash/api/admin/byline-fields/{slug} read one definition
|
|
5
|
+
* - PATCH /_emdash/api/admin/byline-fields/{slug} update label / required /
|
|
6
|
+
* translatable / validation /
|
|
7
|
+
* sort order
|
|
8
|
+
* - DELETE /_emdash/api/admin/byline-fields/{slug} drop the definition and all
|
|
9
|
+
* stored values (FK CASCADE +
|
|
10
|
+
* app-level cleanup; see
|
|
11
|
+
* `BylineSchemaRegistry.deleteField`)
|
|
12
|
+
*
|
|
13
|
+
* Thin wrappers around the handler layer; status mapping happens in
|
|
14
|
+
* `unwrapResult`. `slug` and `type` are immutable post-create — see
|
|
15
|
+
* `bylineFieldUpdateBody`. Flipping `translatable` while value rows
|
|
16
|
+
* exist surfaces as a 409 `TRANSLATABLE_LOCKED`.
|
|
17
|
+
*
|
|
18
|
+
* Phase 4 of Discussion #1174.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import type { APIRoute } from "astro";
|
|
22
|
+
|
|
23
|
+
import { requirePerm } from "#api/authorize.js";
|
|
24
|
+
import { apiError, requireDb, unwrapResult } from "#api/error.js";
|
|
25
|
+
import {
|
|
26
|
+
handleBylineFieldDelete,
|
|
27
|
+
handleBylineFieldGet,
|
|
28
|
+
handleBylineFieldUpdate,
|
|
29
|
+
} from "#api/handlers/byline-fields.js";
|
|
30
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
31
|
+
import { bylineFieldUpdateBody } from "#api/schemas.js";
|
|
32
|
+
|
|
33
|
+
export const prerender = false;
|
|
34
|
+
|
|
35
|
+
// GET requires `schema:read` (Editor+); see sibling `index.ts` GET
|
|
36
|
+
// for rationale.
|
|
37
|
+
export const GET: APIRoute = async ({ params, locals }) => {
|
|
38
|
+
const { emdash, user } = locals;
|
|
39
|
+
const denied = requirePerm(user, "schema:read");
|
|
40
|
+
if (denied) return denied;
|
|
41
|
+
|
|
42
|
+
const dbErr = requireDb(emdash?.db);
|
|
43
|
+
if (dbErr) return dbErr;
|
|
44
|
+
|
|
45
|
+
const slug = params.slug;
|
|
46
|
+
if (!slug) return apiError("MISSING_PARAM", "Field slug is required", 400);
|
|
47
|
+
|
|
48
|
+
const result = await handleBylineFieldGet(emdash.db, slug);
|
|
49
|
+
return unwrapResult(result);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const PATCH: APIRoute = async ({ params, request, locals }) => {
|
|
53
|
+
const { emdash, user } = locals;
|
|
54
|
+
const denied = requirePerm(user, "schema:manage");
|
|
55
|
+
if (denied) return denied;
|
|
56
|
+
|
|
57
|
+
const dbErr = requireDb(emdash?.db);
|
|
58
|
+
if (dbErr) return dbErr;
|
|
59
|
+
|
|
60
|
+
const slug = params.slug;
|
|
61
|
+
if (!slug) return apiError("MISSING_PARAM", "Field slug is required", 400);
|
|
62
|
+
|
|
63
|
+
const body = await parseBody(request, bylineFieldUpdateBody);
|
|
64
|
+
if (isParseError(body)) return body;
|
|
65
|
+
|
|
66
|
+
const result = await handleBylineFieldUpdate(emdash.db, slug, {
|
|
67
|
+
label: body.label,
|
|
68
|
+
required: body.required,
|
|
69
|
+
translatable: body.translatable,
|
|
70
|
+
// `null` clears the stored validation; `undefined` leaves it as-is.
|
|
71
|
+
// The zod schema makes `validation` itself optional, so an absent
|
|
72
|
+
// key reaches the handler as `undefined`.
|
|
73
|
+
validation: body.validation,
|
|
74
|
+
sortOrder: body.sortOrder,
|
|
75
|
+
});
|
|
76
|
+
return unwrapResult(result);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const DELETE: APIRoute = async ({ params, locals }) => {
|
|
80
|
+
const { emdash, user } = locals;
|
|
81
|
+
const denied = requirePerm(user, "schema:manage");
|
|
82
|
+
if (denied) return denied;
|
|
83
|
+
|
|
84
|
+
const dbErr = requireDb(emdash?.db);
|
|
85
|
+
if (dbErr) return dbErr;
|
|
86
|
+
|
|
87
|
+
const slug = params.slug;
|
|
88
|
+
if (!slug) return apiError("MISSING_PARAM", "Field slug is required", 400);
|
|
89
|
+
|
|
90
|
+
const result = await handleBylineFieldDelete(emdash.db, slug);
|
|
91
|
+
return unwrapResult(result);
|
|
92
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byline custom-field schema management — list + create.
|
|
3
|
+
*
|
|
4
|
+
* - GET /_emdash/api/admin/byline-fields list every registered field
|
|
5
|
+
* - POST /_emdash/api/admin/byline-fields create a new field definition
|
|
6
|
+
*
|
|
7
|
+
* Thin wrappers around `handleBylineFieldList` / `handleBylineFieldCreate`
|
|
8
|
+
* in `api/handlers/byline-fields.ts`. Both endpoints require
|
|
9
|
+
* `schema:manage`. Reserved-slug + identifier validation runs at the
|
|
10
|
+
* zod layer in `bylineFieldCreateBody`; the registry repeats the check
|
|
11
|
+
* for defence-in-depth. Domain errors surface as typed `ErrorCode`s and
|
|
12
|
+
* are mapped to HTTP statuses by `unwrapResult` → `mapErrorStatus`.
|
|
13
|
+
*
|
|
14
|
+
* Phase 4 of Discussion #1174.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { APIRoute } from "astro";
|
|
18
|
+
|
|
19
|
+
import { requirePerm } from "#api/authorize.js";
|
|
20
|
+
import { requireDb, unwrapResult } from "#api/error.js";
|
|
21
|
+
import { handleBylineFieldCreate, handleBylineFieldList } from "#api/handlers/byline-fields.js";
|
|
22
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
23
|
+
import { bylineFieldCreateBody } from "#api/schemas.js";
|
|
24
|
+
|
|
25
|
+
export const prerender = false;
|
|
26
|
+
|
|
27
|
+
// GET requires `schema:read` (Editor+), not `schema:manage` — Phase 6
|
|
28
|
+
// of #1174 surfaced the split: editors need to read field definitions
|
|
29
|
+
// to render custom-field inputs in the byline edit form, while only
|
|
30
|
+
// admins manage the registry. The Phase 4 review-round constraint
|
|
31
|
+
// "every endpoint returns 403 for a user without schema:manage" is
|
|
32
|
+
// superseded for the read endpoints; mutations remain admin-only.
|
|
33
|
+
export const GET: APIRoute = async ({ locals }) => {
|
|
34
|
+
const { emdash, user } = locals;
|
|
35
|
+
const denied = requirePerm(user, "schema:read");
|
|
36
|
+
if (denied) return denied;
|
|
37
|
+
|
|
38
|
+
const dbErr = requireDb(emdash?.db);
|
|
39
|
+
if (dbErr) return dbErr;
|
|
40
|
+
|
|
41
|
+
const result = await handleBylineFieldList(emdash.db);
|
|
42
|
+
return unwrapResult(result);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
46
|
+
const { emdash, user } = locals;
|
|
47
|
+
const denied = requirePerm(user, "schema:manage");
|
|
48
|
+
if (denied) return denied;
|
|
49
|
+
|
|
50
|
+
const dbErr = requireDb(emdash?.db);
|
|
51
|
+
if (dbErr) return dbErr;
|
|
52
|
+
|
|
53
|
+
const body = await parseBody(request, bylineFieldCreateBody);
|
|
54
|
+
if (isParseError(body)) return body;
|
|
55
|
+
|
|
56
|
+
const result = await handleBylineFieldCreate(emdash.db, {
|
|
57
|
+
slug: body.slug,
|
|
58
|
+
label: body.label,
|
|
59
|
+
type: body.type,
|
|
60
|
+
required: body.required,
|
|
61
|
+
translatable: body.translatable,
|
|
62
|
+
validation: body.validation ?? null,
|
|
63
|
+
sortOrder: body.sortOrder,
|
|
64
|
+
});
|
|
65
|
+
return unwrapResult(result, 201);
|
|
66
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byline field reorder.
|
|
3
|
+
*
|
|
4
|
+
* POST /_emdash/api/admin/byline-fields/reorder
|
|
5
|
+
*
|
|
6
|
+
* Body: `{ slugs: string[] }` — the exact set of currently registered
|
|
7
|
+
* slugs in the desired order. The registry rejects any drift
|
|
8
|
+
* (`REORDER_MISMATCH` → 400). Empty `[]` against an empty registered
|
|
9
|
+
* set is a no-op by registry contract; the zod schema permits it.
|
|
10
|
+
*
|
|
11
|
+
* Thin wrapper around `handleBylineFieldReorder`.
|
|
12
|
+
*
|
|
13
|
+
* Phase 4 of Discussion #1174.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { APIRoute } from "astro";
|
|
17
|
+
|
|
18
|
+
import { requirePerm } from "#api/authorize.js";
|
|
19
|
+
import { requireDb, unwrapResult } from "#api/error.js";
|
|
20
|
+
import { handleBylineFieldReorder } from "#api/handlers/byline-fields.js";
|
|
21
|
+
import { isParseError, parseBody } from "#api/parse.js";
|
|
22
|
+
import { bylineFieldReorderBody } from "#api/schemas.js";
|
|
23
|
+
|
|
24
|
+
export const prerender = false;
|
|
25
|
+
|
|
26
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
27
|
+
const { emdash, user } = locals;
|
|
28
|
+
const denied = requirePerm(user, "schema:manage");
|
|
29
|
+
if (denied) return denied;
|
|
30
|
+
|
|
31
|
+
const dbErr = requireDb(emdash?.db);
|
|
32
|
+
if (dbErr) return dbErr;
|
|
33
|
+
|
|
34
|
+
const body = await parseBody(request, bylineFieldReorderBody);
|
|
35
|
+
if (isParseError(body)) return body;
|
|
36
|
+
|
|
37
|
+
const result = await handleBylineFieldReorder(emdash.db, body.slugs);
|
|
38
|
+
return unwrapResult(result);
|
|
39
|
+
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { APIRoute } from "astro";
|
|
2
2
|
|
|
3
3
|
import { requirePerm } from "#api/authorize.js";
|
|
4
|
-
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
4
|
+
import { apiError, apiSuccess, handleError, requireDb, unwrapResult } from "#api/error.js";
|
|
5
|
+
import { handleBylineUpdate } from "#api/handlers/bylines.js";
|
|
5
6
|
import { isParseError, parseBody } from "#api/parse.js";
|
|
6
7
|
import { bylineUpdateBody } from "#api/schemas.js";
|
|
7
8
|
import { invalidateBylineCache } from "#bylines/index.js";
|
|
@@ -33,31 +34,32 @@ export const PUT: APIRoute = async ({ params, request, locals }) => {
|
|
|
33
34
|
const denied = requirePerm(user, "bylines:manage");
|
|
34
35
|
if (denied) return denied;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
37
|
+
const dbErr = requireDb(emdash?.db);
|
|
38
|
+
if (dbErr) return dbErr;
|
|
39
39
|
|
|
40
40
|
const body = await parseBody(request, bylineUpdateBody);
|
|
41
41
|
if (isParseError(body)) return body;
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
43
|
+
const result = await handleBylineUpdate(emdash.db, params.id!, {
|
|
44
|
+
slug: body.slug,
|
|
45
|
+
displayName: body.displayName,
|
|
46
|
+
bio: body.bio ?? null,
|
|
47
|
+
avatarMediaId: body.avatarMediaId ?? null,
|
|
48
|
+
websiteUrl: body.websiteUrl ?? null,
|
|
49
|
+
userId: body.userId ?? null,
|
|
50
|
+
isGuest: body.isGuest,
|
|
51
|
+
// Forward `customFields` only when present so the repo treats an
|
|
52
|
+
// omitted key as "leave existing values untouched". An empty
|
|
53
|
+
// object also no-ops by repo convention — see
|
|
54
|
+
// `BylineRepository.update`. Validation (unknown slug, type
|
|
55
|
+
// mismatch, select-choice) happens inside the repo and surfaces
|
|
56
|
+
// as `EmDashValidationError`, which the handler maps to a 400
|
|
57
|
+
// `VALIDATION_ERROR` for `unwrapResult` / `mapErrorStatus`.
|
|
58
|
+
customFields: body.customFields,
|
|
59
|
+
});
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return apiSuccess(byline);
|
|
58
|
-
} catch (error) {
|
|
59
|
-
return handleError(error, "Failed to update byline", "BYLINE_UPDATE_ERROR");
|
|
60
|
-
}
|
|
61
|
+
if (result.success) invalidateBylineCache();
|
|
62
|
+
return unwrapResult(result);
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
export const DELETE: APIRoute = async ({ params, locals }) => {
|
|
@@ -9,21 +9,22 @@ import type { APIRoute } from "astro";
|
|
|
9
9
|
|
|
10
10
|
export const prerender = false;
|
|
11
11
|
|
|
12
|
-
import { apiError, apiSuccess } from "#api/error.js";
|
|
12
|
+
import { apiError, apiSuccess, handleError } from "#api/error.js";
|
|
13
13
|
import { isParseError, parseBody } from "#api/parse.js";
|
|
14
14
|
import { authMeActionBody } from "#api/schemas.js";
|
|
15
|
+
import { UserRepository } from "#db/repositories/user.js";
|
|
15
16
|
|
|
16
|
-
export const GET: APIRoute = async ({ locals
|
|
17
|
+
export const GET: APIRoute = async ({ locals }) => {
|
|
17
18
|
const { user } = locals;
|
|
18
19
|
|
|
19
20
|
if (!user) {
|
|
20
21
|
return apiError("NOT_AUTHENTICATED", "Not authenticated", 401);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
// Check if this is the user's first login (for welcome modal)
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
const isFirstLogin = !
|
|
24
|
+
// Check if this is the user's first login (for welcome modal).
|
|
25
|
+
// The flag is persisted in the user's `data` JSON column so it survives
|
|
26
|
+
// session expiry / rotation.
|
|
27
|
+
const isFirstLogin = !user.data?.welcomeDismissed;
|
|
27
28
|
|
|
28
29
|
// Return safe user info (no sensitive data)
|
|
29
30
|
return apiSuccess({
|
|
@@ -41,19 +42,29 @@ export const GET: APIRoute = async ({ locals, session }) => {
|
|
|
41
42
|
*
|
|
42
43
|
* Mark that the user has seen the welcome modal.
|
|
43
44
|
*/
|
|
44
|
-
export const POST: APIRoute = async ({ request, locals
|
|
45
|
-
const { user } = locals;
|
|
45
|
+
export const POST: APIRoute = async ({ request, locals }) => {
|
|
46
|
+
const { user, emdash } = locals;
|
|
46
47
|
|
|
47
48
|
if (!user) {
|
|
48
49
|
return apiError("NOT_AUTHENTICATED", "Not authenticated", 401);
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
if (!emdash) return apiError("NOT_CONFIGURED", "EmDash is not initialized", 500);
|
|
53
|
+
|
|
51
54
|
const body = await parseBody(request, authMeActionBody);
|
|
52
55
|
if (isParseError(body)) return body;
|
|
53
56
|
|
|
54
57
|
if (body.action === "dismissWelcome") {
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
try {
|
|
59
|
+
// Persist in the user's data column so it survives session expiry.
|
|
60
|
+
const userRepo = new UserRepository(emdash.db);
|
|
61
|
+
await userRepo.update(user.id, {
|
|
62
|
+
data: { ...user.data, welcomeDismissed: true },
|
|
63
|
+
});
|
|
64
|
+
return apiSuccess({ success: true });
|
|
65
|
+
} catch (error) {
|
|
66
|
+
return handleError(error, "Failed to dismiss welcome", "WELCOME_DISMISS_ERROR");
|
|
67
|
+
}
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
return apiError("UNKNOWN_ACTION", "Unknown action", 400);
|
|
@@ -11,6 +11,7 @@ import { requirePerm, requireOwnerPerm } from "#api/authorize.js";
|
|
|
11
11
|
import { apiError, apiSuccess, handleError, requireDb } from "#api/error.js";
|
|
12
12
|
import { parseBody, isParseError } from "#api/parse.js";
|
|
13
13
|
import { contentTermsBody } from "#api/schemas.js";
|
|
14
|
+
import { ContentRepository } from "#db/repositories/content.js";
|
|
14
15
|
import { TaxonomyRepository } from "#db/repositories/taxonomy.js";
|
|
15
16
|
import { invalidateTermCache } from "#taxonomies/index.js";
|
|
16
17
|
|
|
@@ -34,8 +35,16 @@ export const GET: APIRoute = async ({ params, locals }) => {
|
|
|
34
35
|
if (dbErr) return dbErr;
|
|
35
36
|
|
|
36
37
|
try {
|
|
38
|
+
// Terms are stored against the per-locale entry row but their
|
|
39
|
+
// translation_group spans every locale. Resolve the entry's own locale
|
|
40
|
+
// server-side (deterministic, not client-spoofable) so only the matching
|
|
41
|
+
// term variant is returned — see issue #1218.
|
|
42
|
+
const entry = await new ContentRepository(emdash.db).findByIdOrSlug(collection, id);
|
|
43
|
+
if (!entry) return apiError("NOT_FOUND", "Content not found", 404);
|
|
44
|
+
const locale = entry.locale ?? undefined;
|
|
45
|
+
|
|
37
46
|
const repo = new TaxonomyRepository(emdash.db);
|
|
38
|
-
const terms = await repo.getTermsForEntry(collection, id, taxonomy);
|
|
47
|
+
const terms = await repo.getTermsForEntry(collection, entry.id, taxonomy, locale);
|
|
39
48
|
|
|
40
49
|
return apiSuccess({
|
|
41
50
|
terms: terms.map((t) => ({
|
|
@@ -101,6 +110,9 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
|
|
|
101
110
|
// Resolve the canonical content ID from the handler result.
|
|
102
111
|
// The URL `id` param may be a slug; we must use the real ID for term storage.
|
|
103
112
|
const canonicalId = typeof existingItem?.id === "string" ? existingItem.id : id;
|
|
113
|
+
// The entry is per-locale; scope the term read to its locale so only the
|
|
114
|
+
// matching translation variant is returned in the response — see #1218.
|
|
115
|
+
const entryLocale = typeof existingItem?.locale === "string" ? existingItem.locale : undefined;
|
|
104
116
|
|
|
105
117
|
try {
|
|
106
118
|
const body = await parseBody(request, contentTermsBody);
|
|
@@ -131,8 +143,8 @@ export const POST: APIRoute = async ({ params, request, locals }) => {
|
|
|
131
143
|
// so hydration on subsequent reads issues a fresh query.
|
|
132
144
|
invalidateTermCache();
|
|
133
145
|
|
|
134
|
-
// Get the updated terms using the canonical ID
|
|
135
|
-
const terms = await repo.getTermsForEntry(collection, canonicalId, taxonomy);
|
|
146
|
+
// Get the updated terms using the canonical ID, scoped to the entry locale
|
|
147
|
+
const terms = await repo.getTermsForEntry(collection, canonicalId, taxonomy, entryLocale);
|
|
136
148
|
|
|
137
149
|
return apiSuccess({
|
|
138
150
|
terms: terms.map((t) => ({
|
|
@@ -68,6 +68,7 @@ export const PUT: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
68
68
|
const { emdash, user } = locals;
|
|
69
69
|
const collection = params.collection!;
|
|
70
70
|
const id = params.id!;
|
|
71
|
+
const locale = new URL(request.url).searchParams.get("locale") || undefined;
|
|
71
72
|
const body = await parseBody(request, contentUpdateBody);
|
|
72
73
|
if (isParseError(body)) return body;
|
|
73
74
|
|
|
@@ -76,7 +77,7 @@ export const PUT: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
// Fetch item to check ownership
|
|
79
|
-
const existing = await emdash.handleContentGet(collection, id);
|
|
80
|
+
const existing = await emdash.handleContentGet(collection, id, locale);
|
|
80
81
|
if (!existing.success) {
|
|
81
82
|
return apiError(
|
|
82
83
|
existing.error?.code ?? "UNKNOWN_ERROR",
|
|
@@ -120,6 +121,7 @@ export const PUT: APIRoute = async ({ params, request, locals, cache }) => {
|
|
|
120
121
|
// Pass _rev through for optimistic concurrency validation
|
|
121
122
|
const result = await emdash.handleContentUpdate(collection, resolvedId, {
|
|
122
123
|
...updateBody,
|
|
124
|
+
locale,
|
|
123
125
|
_rev: body._rev,
|
|
124
126
|
});
|
|
125
127
|
|
package/src/astro/types.ts
CHANGED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byline field-definitions cache
|
|
3
|
+
*
|
|
4
|
+
* Discussion #1174 / Phase 3. Two-tier cache for the byline custom-field
|
|
5
|
+
* registry, mirroring the `settings/index.ts` pattern.
|
|
6
|
+
*
|
|
7
|
+
* **Tier 1 — per-isolate (globalThis).** Field definitions change rarely
|
|
8
|
+
* but are read on every byline hydration (admin pages, content rendering,
|
|
9
|
+
* API responses). Caching at the isolate level drops the SELECT-from-
|
|
10
|
+
* `_emdash_byline_fields` from once-per-hydration to once-per-isolate-
|
|
11
|
+
* after-bump. The cache holds a Promise (not the resolved value) so
|
|
12
|
+
* concurrent cold-isolate readers share the in-flight query.
|
|
13
|
+
*
|
|
14
|
+
* Stored on globalThis under `Symbol.for("emdash:byline-field-defs")` so
|
|
15
|
+
* Vite SSR chunk duplication can't produce two independent caches (same
|
|
16
|
+
* pattern as `request-cache.ts` and `request-context.ts`).
|
|
17
|
+
*
|
|
18
|
+
* **Tier 2 — per-request.** Wraps both the version read and the defs
|
|
19
|
+
* fetch in `requestCached` so a single page render that hits byline
|
|
20
|
+
* hydration multiple times (e.g. list view + individual byline lookups
|
|
21
|
+
* in a sidebar) pays at most one version read and one defs fetch in
|
|
22
|
+
* total. The defs cache key includes the version, so a (highly
|
|
23
|
+
* unlikely) mid-request bump still produces a self-consistent view —
|
|
24
|
+
* the second call sees a different key and refetches.
|
|
25
|
+
*
|
|
26
|
+
* **Invalidation.** `options.byline_fields_version` is bumped by every
|
|
27
|
+
* `BylineSchemaRegistry` mutation (Phase 2). Each isolate independently
|
|
28
|
+
* reads the persisted version on the next request and compares against
|
|
29
|
+
* its cached version; mismatch triggers a refetch and overwrite. Other
|
|
30
|
+
* isolates see the change within one request after the bump propagates.
|
|
31
|
+
*
|
|
32
|
+
* **Isolated databases bypass the global cache.** Playground and DO
|
|
33
|
+
* preview sessions set `requestContext.dbIsIsolated = true`, signalling
|
|
34
|
+
* the per-request `db` points at an isolated schema that may diverge
|
|
35
|
+
* from the singleton. Schema-derived caches keyed by the singleton's
|
|
36
|
+
* version would silently leak the singleton's defs into the isolated
|
|
37
|
+
* request. We follow the `loader.ts:74` `getTaxonomyNames` precedent:
|
|
38
|
+
* skip both reading from and writing to the global holder when the
|
|
39
|
+
* request is isolated. The per-request cache (`requestCached`) is keyed
|
|
40
|
+
* by the WeakMap'd `EmDashRequestContext`, so it can't cross-pollinate
|
|
41
|
+
* between requests — it stays in play even for isolated DBs.
|
|
42
|
+
*
|
|
43
|
+
* **Why a versioned cache and not a TTL?** The version counter gives
|
|
44
|
+
* deterministic invalidation without the staleness window a TTL would
|
|
45
|
+
* impose. Field-definition changes need to be visible to the next
|
|
46
|
+
* request, not eventually. The cost is one cheap `options` read per
|
|
47
|
+
* request — cheaper than the field-defs fetch it replaces, and cheaper
|
|
48
|
+
* than maintaining a TTL state machine.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
import type { Kysely } from "kysely";
|
|
52
|
+
|
|
53
|
+
import type { Database } from "../database/types.js";
|
|
54
|
+
import { requestCached } from "../request-cache.js";
|
|
55
|
+
import { getRequestContext } from "../request-context.js";
|
|
56
|
+
import { BylineSchemaRegistry } from "../schema/byline-registry.js";
|
|
57
|
+
import type { BylineFieldDefinition } from "../schema/types.js";
|
|
58
|
+
|
|
59
|
+
interface FieldDefsHolder {
|
|
60
|
+
/** In-flight or resolved defs promise for the cached version. Null until first read. */
|
|
61
|
+
cached: Promise<BylineFieldDefinition[]> | null;
|
|
62
|
+
/** Persisted-version value that `cached` was fetched against. */
|
|
63
|
+
cachedVersion: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const HOLDER_KEY = Symbol.for("emdash:byline-field-defs");
|
|
67
|
+
const g = globalThis as Record<symbol, unknown>;
|
|
68
|
+
const holder: FieldDefsHolder =
|
|
69
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- globalThis singleton pattern (see request-cache.ts)
|
|
70
|
+
(g[HOLDER_KEY] as FieldDefsHolder | undefined) ??
|
|
71
|
+
(() => {
|
|
72
|
+
const h: FieldDefsHolder = { cached: null, cachedVersion: -1 };
|
|
73
|
+
g[HOLDER_KEY] = h;
|
|
74
|
+
return h;
|
|
75
|
+
})();
|
|
76
|
+
|
|
77
|
+
const REQUEST_CACHE_KEY_VERSION = "byline-fields-version";
|
|
78
|
+
const REQUEST_CACHE_KEY_DEFS_PREFIX = "byline-field-defs:";
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Read the persisted `options.byline_fields_version` counter. Cached for
|
|
82
|
+
* the duration of the current request via `requestCached`. Returns `0`
|
|
83
|
+
* when the row is missing (matches `BylineSchemaRegistry.getVersion`).
|
|
84
|
+
*/
|
|
85
|
+
async function getBylineFieldsVersion(db: Kysely<Database>): Promise<number> {
|
|
86
|
+
return requestCached(REQUEST_CACHE_KEY_VERSION, () => new BylineSchemaRegistry(db).getVersion());
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Resolve registered byline custom-field definitions. Two-tier cache:
|
|
91
|
+
* per-request via `requestCached`, then per-isolate via the global
|
|
92
|
+
* holder.
|
|
93
|
+
*
|
|
94
|
+
* The global holder is bypassed for isolated requests (playground / DO
|
|
95
|
+
* preview, which point at a divergent schema) and for dirty versions
|
|
96
|
+
* (odd counter — see `BylineSchemaRegistry`'s class JSDoc — indicates
|
|
97
|
+
* an in-flight or crashed mutation). Both bypass paths still hit the
|
|
98
|
+
* per-request cache, so a single render dedupes within itself.
|
|
99
|
+
*
|
|
100
|
+
* Always returns an array. Empty = no custom fields registered.
|
|
101
|
+
*/
|
|
102
|
+
export async function getBylineFieldDefs(db: Kysely<Database>): Promise<BylineFieldDefinition[]> {
|
|
103
|
+
const isolated = getRequestContext()?.dbIsIsolated === true;
|
|
104
|
+
const version = await getBylineFieldsVersion(db);
|
|
105
|
+
const dirty = version % 2 !== 0;
|
|
106
|
+
return requestCached(`${REQUEST_CACHE_KEY_DEFS_PREFIX}${version}`, async () => {
|
|
107
|
+
if (isolated || dirty) {
|
|
108
|
+
return new BylineSchemaRegistry(db).listFields();
|
|
109
|
+
}
|
|
110
|
+
if (holder.cached !== null && holder.cachedVersion === version) {
|
|
111
|
+
return holder.cached;
|
|
112
|
+
}
|
|
113
|
+
const defs = new BylineSchemaRegistry(db).listFields().catch((error) => {
|
|
114
|
+
if (holder.cached === defs) {
|
|
115
|
+
holder.cached = null;
|
|
116
|
+
holder.cachedVersion = -1;
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
});
|
|
120
|
+
holder.cached = defs;
|
|
121
|
+
holder.cachedVersion = version;
|
|
122
|
+
return defs;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Test/internal helper: clear the per-isolate cache. Useful for unit
|
|
128
|
+
* tests that mutate the registry directly and need to force a refetch
|
|
129
|
+
* without going through the full version-bump path.
|
|
130
|
+
*
|
|
131
|
+
* Production code paths should rely on the version counter for
|
|
132
|
+
* invalidation — calling this from a write path would bypass the
|
|
133
|
+
* coordination that lets other isolates see the change.
|
|
134
|
+
*/
|
|
135
|
+
export function resetBylineFieldDefsCacheForTests(): void {
|
|
136
|
+
holder.cached = null;
|
|
137
|
+
holder.cachedVersion = -1;
|
|
138
|
+
}
|
package/src/bylines/index.ts
CHANGED
|
@@ -220,10 +220,20 @@ export async function getBylinesForEntries(
|
|
|
220
220
|
// previous "has any bylines" probe, without the extra round-trip.
|
|
221
221
|
// Pre-migration databases (bylines table missing) fall through to the
|
|
222
222
|
// `isMissingTableError` catch below and return empty.
|
|
223
|
+
//
|
|
224
|
+
// Each bucket's `getContentBylinesMany` call uses `skipHydration: true`
|
|
225
|
+
// so the per-bucket fetches return bylines with `customFields = {}`.
|
|
226
|
+
// We then hydrate the union of returned bylines in a SINGLE batched
|
|
227
|
+
// pass via `hydrateBylineCustomFields`. This keeps mixed-locale list
|
|
228
|
+
// hydration at one batched group-shared query (and one batched
|
|
229
|
+
// translatable query) per request, even when locale buckets reference
|
|
230
|
+
// disjoint translation_groups — the strict reading of the Phase 3
|
|
231
|
+
// query-count envelope.
|
|
223
232
|
const explicitByEntry = new Map<string, ContentBylineCredit[]>();
|
|
224
233
|
const entriesNeedingAuthorCheck: BylineEntry[] = [];
|
|
234
|
+
const hydrationTargets: BylineSummary[] = [];
|
|
225
235
|
for (const [locale, bucket] of buckets) {
|
|
226
|
-
const localeOpt = locale ? { locale } :
|
|
236
|
+
const localeOpt = locale ? { locale, skipHydration: true } : { skipHydration: true };
|
|
227
237
|
const bucketIds = bucket.map((e) => e.id);
|
|
228
238
|
let bylinesMap;
|
|
229
239
|
try {
|
|
@@ -232,7 +242,10 @@ export async function getBylinesForEntries(
|
|
|
232
242
|
if (isMissingTableError(error)) return result;
|
|
233
243
|
throw error;
|
|
234
244
|
}
|
|
235
|
-
for (const [id, list] of bylinesMap)
|
|
245
|
+
for (const [id, list] of bylinesMap) {
|
|
246
|
+
explicitByEntry.set(id, list);
|
|
247
|
+
for (const credit of list) hydrationTargets.push(credit.byline);
|
|
248
|
+
}
|
|
236
249
|
|
|
237
250
|
for (const entry of bucket) {
|
|
238
251
|
const hasResolved = bylinesMap.has(entry.id) && bylinesMap.get(entry.id)!.length > 0;
|
|
@@ -255,19 +268,39 @@ export async function getBylinesForEntries(
|
|
|
255
268
|
}
|
|
256
269
|
|
|
257
270
|
for (const [locale, bucket] of authorBuckets) {
|
|
258
|
-
const localeOpt
|
|
271
|
+
const localeOpt: { locale?: string; skipHydration: true } = locale
|
|
272
|
+
? { locale, skipHydration: true }
|
|
273
|
+
: { skipHydration: true };
|
|
259
274
|
const authorIds = bucket.map((e) => e.authorId).filter((id): id is string => id !== null);
|
|
260
275
|
const uniqueAuthorIds = [...new Set(authorIds)];
|
|
261
276
|
if (uniqueAuthorIds.length === 0) continue;
|
|
277
|
+
// `skipHydration: true` returns bylines with `customFields = {}`
|
|
278
|
+
// so the fallback path participates in the single batched
|
|
279
|
+
// `hydrateBylineCustomFields` call below — keeping the query
|
|
280
|
+
// envelope at "+1 group-shared query per hydration pass" even
|
|
281
|
+
// when author bylines across locale buckets reference disjoint
|
|
282
|
+
// translation_groups.
|
|
262
283
|
const authorBylineMap = await repo.findByUserIds(uniqueAuthorIds, localeOpt);
|
|
263
284
|
for (const entry of bucket) {
|
|
264
285
|
if (!entry.authorId) continue;
|
|
265
286
|
const f = authorBylineMap.get(entry.authorId);
|
|
266
|
-
if (f)
|
|
287
|
+
if (f) {
|
|
288
|
+
fallbackByEntry.set(entry.id, f);
|
|
289
|
+
hydrationTargets.push(f);
|
|
290
|
+
}
|
|
267
291
|
}
|
|
268
292
|
}
|
|
269
293
|
}
|
|
270
294
|
|
|
295
|
+
// Single batched hydration over every byline returned from both the
|
|
296
|
+
// per-bucket explicit-credit fetches AND the per-bucket author-
|
|
297
|
+
// fallback fetches. One translatable query + one group-shared query
|
|
298
|
+
// for the whole pass, regardless of bucket count or whether
|
|
299
|
+
// translation_groups overlap across locales.
|
|
300
|
+
if (hydrationTargets.length > 0) {
|
|
301
|
+
await repo.hydrateBylineCustomFields(hydrationTargets);
|
|
302
|
+
}
|
|
303
|
+
|
|
271
304
|
for (const { id } of entries) {
|
|
272
305
|
const explicit = explicitByEntry.get(id);
|
|
273
306
|
if (explicit && explicit.length > 0) {
|
|
@@ -233,6 +233,7 @@ const updateCommand = defineCommand({
|
|
|
233
233
|
description: "Revision token from get (prevents overwriting unseen changes)",
|
|
234
234
|
required: true,
|
|
235
235
|
},
|
|
236
|
+
locale: { type: "string", description: "Locale for slug resolution" },
|
|
236
237
|
draft: {
|
|
237
238
|
type: "boolean",
|
|
238
239
|
description: "Keep as draft instead of auto-publishing",
|
|
@@ -247,17 +248,18 @@ const updateCommand = defineCommand({
|
|
|
247
248
|
const updated = await client.update(args.collection, args.id, {
|
|
248
249
|
data,
|
|
249
250
|
_rev: args.rev,
|
|
251
|
+
locale: args.locale,
|
|
250
252
|
});
|
|
251
253
|
|
|
252
254
|
// Auto-publish unless --draft is set.
|
|
253
255
|
// Only publish if the update created a draft revision (i.e. the
|
|
254
256
|
// collection supports revisions and data went to a draft).
|
|
255
257
|
if (!args.draft && updated.draftRevisionId) {
|
|
256
|
-
await client.publish(args.collection,
|
|
258
|
+
await client.publish(args.collection, updated.id);
|
|
257
259
|
}
|
|
258
260
|
|
|
259
261
|
// Re-fetch to return the current state
|
|
260
|
-
const item = await client.get(args.collection,
|
|
262
|
+
const item = await client.get(args.collection, updated.id);
|
|
261
263
|
output(item, args);
|
|
262
264
|
} catch (error) {
|
|
263
265
|
consola.error(error instanceof Error ? error.message : "Unknown error");
|