emdash 0.14.0 → 0.15.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-9DybjTO6.d.mts → adapters-C4yd_UJR.d.mts} +1 -1
- package/dist/{adapters-9DybjTO6.d.mts.map → adapters-C4yd_UJR.d.mts.map} +1 -1
- package/dist/{allowed-origins-CDdG-4Gd.mjs → allowed-origins-D0fFk9a6.mjs} +2 -2
- package/dist/{allowed-origins-CDdG-4Gd.mjs.map → allowed-origins-D0fFk9a6.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-BMLZuwM4.mjs → api-CLwG_3dh.mjs} +519 -55
- package/dist/api-CLwG_3dh.mjs.map +1 -0
- package/dist/{api-tokens-eYymBhIT.mjs → api-tokens-ucpcNXDt.mjs} +2 -2
- package/dist/{api-tokens-eYymBhIT.mjs.map → api-tokens-ucpcNXDt.mjs.map} +1 -1
- package/dist/{apply-v4DBgjPw.mjs → apply-wJhM_bwU.mjs} +17 -17
- package/dist/{apply-v4DBgjPw.mjs.map → apply-wJhM_bwU.mjs.map} +1 -1
- package/dist/astro/index.d.mts +10 -10
- package/dist/astro/index.mjs +21 -5
- 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/auth.mjs.map +1 -1
- package/dist/astro/middleware/redirect.mjs +4 -4
- package/dist/astro/middleware/request-context.mjs +2 -2
- package/dist/astro/middleware/request-context.mjs.map +1 -1
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware.d.mts.map +1 -1
- package/dist/astro/middleware.mjs +353 -71
- 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/bylines/_id_/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -17
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts +9 -0
- package/dist/astro/routes/api/admin/bylines/_id_/translations.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +70 -0
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs.map +1 -0
- package/dist/astro/routes/api/admin/bylines/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +25 -16
- 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 +32 -31
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +32 -31
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +31 -30
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +31 -30
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +33 -31
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/index.mjs +31 -30
- 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 +31 -30
- 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 +33 -31
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +31 -30
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts +8 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +59 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs.map +1 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts +8 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.d.mts.map +1 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +72 -0
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs.map +1 -0
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +31 -30
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/plugins/updates.mjs +44 -31
- package/dist/astro/routes/api/admin/plugins/updates.mjs.map +1 -1
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +31 -30
- 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 +31 -30
- 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.mjs +5 -5
- 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_/callback.mjs.map +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +2 -2
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs.map +1 -1
- 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_/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_/duplicate.mjs.map +1 -1
- 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_/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_/restore.mjs.map +1 -1
- 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_/schedule.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +10 -9
- 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_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs.map +1 -1
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +6 -6
- 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 +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
- package/dist/astro/routes/api/import/wordpress/execute.mjs +9 -8
- 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 +8 -8
- package/dist/astro/routes/api/import/wordpress/prepare.mjs.map +1 -1
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +7 -7
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs.map +1 -1
- 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 +11 -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 +29 -29
- 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 +7 -7
- package/dist/astro/routes/api/media/upload-url.mjs.map +1 -1
- 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 +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 +3 -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 +8 -8
- package/dist/astro/routes/api/redirects/404s/index.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/404s/summary.mjs +8 -8
- package/dist/astro/routes/api/redirects/404s/summary.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/_id_.mjs +9 -9
- package/dist/astro/routes/api/redirects/_id_.mjs.map +1 -1
- package/dist/astro/routes/api/redirects/index.mjs +9 -9
- package/dist/astro/routes/api/redirects/index.mjs.map +1 -1
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +31 -30
- 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 +31 -30
- 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 +31 -30
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +31 -30
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/collections/index.mjs +31 -30
- 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/index.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +31 -30
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/schema/orphans/index.mjs +31 -30
- 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/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/sections/index.mjs +8 -8
- package/dist/astro/routes/api/sections/index.mjs.map +1 -1
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +10 -10
- 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 +22 -22
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +22 -22
- 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 +11 -10
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +11 -10
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +11 -10
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs.map +1 -1
- package/dist/astro/routes/api/taxonomies/index.mjs +11 -10
- package/dist/astro/routes/api/taxonomies/index.mjs.map +1 -1
- 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 +5 -5
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +4 -4
- package/dist/astro/routes/sitemap.xml.mjs +5 -5
- 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-BlyCH-96.mjs → authorize-Bkwe8kuL.mjs} +2 -2
- package/dist/{authorize-BlyCH-96.mjs.map → authorize-Bkwe8kuL.mjs.map} +1 -1
- package/dist/byline-CTaWkMh5.mjs +404 -0
- package/dist/byline-CTaWkMh5.mjs.map +1 -0
- package/dist/bylines-BYHWU3T7.mjs +174 -0
- package/dist/bylines-BYHWU3T7.mjs.map +1 -0
- package/dist/{bylines-BdUP8NuI.d.mts → bylines-DtDRNF1n.d.mts} +59 -14
- package/dist/bylines-DtDRNF1n.d.mts.map +1 -0
- package/dist/bylines-H0Xh5TMy.mjs +118 -0
- package/dist/bylines-H0Xh5TMy.mjs.map +1 -0
- package/dist/{cache-CXCpjWiL.mjs → cache-CNk1jIxp.mjs} +2 -2
- package/dist/{cache-CXCpjWiL.mjs.map → cache-CNk1jIxp.mjs.map} +1 -1
- package/dist/{challenge-store-CJ0OOHOr.mjs → challenge-store-Dng1SxKT.mjs} +1 -1
- package/dist/{challenge-store-CJ0OOHOr.mjs.map → challenge-store-Dng1SxKT.mjs.map} +1 -1
- package/dist/{chunks-DyGtu1Bv.mjs → chunks-BkfVdD-3.mjs} +2 -2
- package/dist/{chunks-DyGtu1Bv.mjs.map → chunks-BkfVdD-3.mjs.map} +1 -1
- package/dist/cli/index.mjs +21 -29
- 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/client/index.mjs.map +1 -1
- package/dist/{comment-Dd9MI82-.mjs → comment-_yzlBYPx.mjs} +2 -2
- package/dist/{comment-Dd9MI82-.mjs.map → comment-_yzlBYPx.mjs.map} +1 -1
- package/dist/{comments-koGI0FrK.mjs → comments-DxID-rsd.mjs} +3 -3
- package/dist/{comments-koGI0FrK.mjs.map → comments-DxID-rsd.mjs.map} +1 -1
- package/dist/{components-mZem7pbe.mjs → components-Dx3DM0gg.mjs} +1 -1
- package/dist/{components-mZem7pbe.mjs.map → components-Dx3DM0gg.mjs.map} +1 -1
- package/dist/config-CVssduLe.mjs.map +1 -1
- package/dist/{content-D6YG26WG.mjs → content-C0ooIs-f.mjs} +3 -3
- package/dist/{content-D6YG26WG.mjs.map → content-C0ooIs-f.mjs.map} +1 -1
- package/dist/{context-qF8d3IPR.mjs → context-sAnCaUIR.mjs} +10 -10
- package/dist/context-sAnCaUIR.mjs.map +1 -0
- package/dist/{cron-H8eJ46dv.mjs → cron-Bd3b3iuj.mjs} +1 -1
- package/dist/{cron-H8eJ46dv.mjs.map → cron-Bd3b3iuj.mjs.map} +1 -1
- package/dist/{dashboard-BmWSIUwY.mjs → dashboard-Cqw3ay2X.mjs} +4 -4
- package/dist/{dashboard-BmWSIUwY.mjs.map → dashboard-Cqw3ay2X.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-Dbs22Gg4.mjs → default-BvTAYCzx.mjs} +1 -1
- package/dist/{default-Dbs22Gg4.mjs.map → default-BvTAYCzx.mjs.map} +1 -1
- package/dist/{device-flow-BqJRxa0Q.mjs → device-flow-B9oG8PwP.mjs} +4 -4
- package/dist/{device-flow-BqJRxa0Q.mjs.map → device-flow-B9oG8PwP.mjs.map} +1 -1
- package/dist/{email-console-Dmp5Q-P2.mjs → email-console-CubRll9q.mjs} +1 -1
- package/dist/email-console-CubRll9q.mjs.map +1 -0
- package/dist/{error-tSQWIl5U.mjs → error-CPh_8eLq.mjs} +16 -8
- package/dist/error-CPh_8eLq.mjs.map +1 -0
- package/dist/{escape-B8bdIryO.mjs → escape-Cg6kMELH.mjs} +1 -1
- package/dist/{escape-B8bdIryO.mjs.map → escape-Cg6kMELH.mjs.map} +1 -1
- package/dist/{fts-manager-B633C-kQ.mjs → fts-manager-Mnrtn-r2.mjs} +2 -2
- package/dist/{fts-manager-B633C-kQ.mjs.map → fts-manager-Mnrtn-r2.mjs.map} +1 -1
- package/dist/{import-CNfLOgDE.mjs → import-DG80rC_I.mjs} +3 -3
- package/dist/{import-CNfLOgDE.mjs.map → import-DG80rC_I.mjs.map} +1 -1
- package/dist/{index-BV8iJ-6s.d.mts → index-Bv1Wf1zB.d.mts} +235 -18
- package/dist/index-Bv1Wf1zB.d.mts.map +1 -0
- package/dist/{index-D2gvztOP.d.mts → index-CC42STEm.d.mts} +3 -3
- package/dist/{index-D2gvztOP.d.mts.map → index-CC42STEm.d.mts.map} +1 -1
- package/dist/index.d.mts +17 -17
- package/dist/index.mjs +50 -49
- package/dist/{load-QzYRpVN3.mjs → load-DmXNVhst.mjs} +2 -2
- package/dist/{load-QzYRpVN3.mjs.map → load-DmXNVhst.mjs.map} +1 -1
- package/dist/{loader-Cs6-Bqe6.mjs → loader-Chm5h7Gr.mjs} +3 -3
- package/dist/loader-Chm5h7Gr.mjs.map +1 -0
- package/dist/{manifest-schema-HCtSh4Jq.mjs → manifest-schema-Czqf0TLu.mjs} +1 -1
- package/dist/{manifest-schema-HCtSh4Jq.mjs.map → manifest-schema-Czqf0TLu.mjs.map} +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/local-runtime.d.mts +11 -11
- package/dist/media/local-runtime.mjs +4 -4
- package/dist/{media-allowlist-B8EX01DH.mjs → media-allowlist-BNloC69x.mjs} +1 -1
- package/dist/{media-allowlist-B8EX01DH.mjs.map → media-allowlist-BNloC69x.mjs.map} +1 -1
- package/dist/{media-Dg7he9uK.mjs → media-oqRcNiQf.mjs} +2 -2
- package/dist/media-oqRcNiQf.mjs.map +1 -0
- package/dist/{menus-DOzIecHi.mjs → menus-Bjf5R1Qq.mjs} +2 -2
- package/dist/menus-Bjf5R1Qq.mjs.map +1 -0
- package/dist/{menus-X4Z-eBA1.mjs → menus-C75SSmRy.mjs} +30 -11
- package/dist/menus-C75SSmRy.mjs.map +1 -0
- package/dist/mime-KV5TqkMN.mjs.map +1 -1
- package/dist/{mode-DPRPvJYm.mjs → mode-CaaiebZI.mjs} +1 -1
- package/dist/{mode-DPRPvJYm.mjs.map → mode-CaaiebZI.mjs.map} +1 -1
- package/dist/{oauth-authorization-62GmpGIH.mjs → oauth-authorization-CTMeVfvj.mjs} +4 -4
- package/dist/{oauth-authorization-62GmpGIH.mjs.map → oauth-authorization-CTMeVfvj.mjs.map} +1 -1
- package/dist/{oauth-clients-D_B0_-Bz.mjs → oauth-clients-eJCbkVSG.mjs} +1 -1
- package/dist/oauth-clients-eJCbkVSG.mjs.map +1 -0
- package/dist/{oauth-state-store-DpsZViTu.mjs → oauth-state-store-vOSdOeGe.mjs} +1 -1
- package/dist/{oauth-state-store-DpsZViTu.mjs.map → oauth-state-store-vOSdOeGe.mjs.map} +1 -1
- package/dist/{oauth-user-lookup-meyS2oB1.mjs → oauth-user-lookup-3JwsVw6N.mjs} +1 -1
- package/dist/{oauth-user-lookup-meyS2oB1.mjs.map → oauth-user-lookup-3JwsVw6N.mjs.map} +1 -1
- package/dist/options-BL4X94qY.mjs.map +1 -1
- package/dist/{options-Cq64Wx0O.d.mts → options-DhV-gwJb.d.mts} +4 -4
- package/dist/options-DhV-gwJb.d.mts.map +1 -0
- package/dist/page/index.d.mts +2 -2
- package/dist/{parse-BFTPon-J.mjs → parse-3-caTKgt.mjs} +2 -2
- package/dist/{parse-BFTPon-J.mjs.map → parse-3-caTKgt.mjs.map} +1 -1
- package/dist/{passkey-config-Cg86_ISa.mjs → passkey-config-BloQOT3y.mjs} +1 -1
- package/dist/{passkey-config-Cg86_ISa.mjs.map → passkey-config-BloQOT3y.mjs.map} +1 -1
- package/dist/{placeholder-D3cFCU9y.d.mts → placeholder-KCkkCtgQ.d.mts} +1 -1
- package/dist/{placeholder-D3cFCU9y.d.mts.map → placeholder-KCkkCtgQ.d.mts.map} +1 -1
- package/dist/plugin-types.d.mts +1 -1
- package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.d.mts.map +1 -1
- package/dist/plugins/adapt-sandbox-entry.mjs +26 -15
- package/dist/plugins/adapt-sandbox-entry.mjs.map +1 -1
- package/dist/{preview-C1LOEbWZ.mjs → preview-D4z0WONU.mjs} +2 -2
- package/dist/{preview-C1LOEbWZ.mjs.map → preview-D4z0WONU.mjs.map} +1 -1
- package/dist/{public-url-CseXl9Fv.mjs → public-url-CUWWFME2.mjs} +1 -1
- package/dist/{public-url-CseXl9Fv.mjs.map → public-url-CUWWFME2.mjs.map} +1 -1
- package/dist/{query-axZmO6Tn.mjs → query-BJn8TOPk.mjs} +16 -13
- package/dist/{query-axZmO6Tn.mjs.map → query-BJn8TOPk.mjs.map} +1 -1
- package/dist/{rate-limit-t5CVjCO6.mjs → rate-limit-D_-gAeJ0.mjs} +2 -2
- package/dist/{rate-limit-t5CVjCO6.mjs.map → rate-limit-D_-gAeJ0.mjs.map} +1 -1
- package/dist/{redirect-DGRsLO2I.mjs → redirect-BINiRYq4.mjs} +1 -1
- package/dist/{redirect-DGRsLO2I.mjs.map → redirect-BINiRYq4.mjs.map} +1 -1
- package/dist/{redirect-DkaDxq8e.mjs → redirect-CNv4mHX2.mjs} +2 -2
- package/dist/{redirect-DkaDxq8e.mjs.map → redirect-CNv4mHX2.mjs.map} +1 -1
- package/dist/{redirects-D1fdd68T.mjs → redirects-B-CUZ1Xh.mjs} +3 -3
- package/dist/{redirects-D1fdd68T.mjs.map → redirects-B-CUZ1Xh.mjs.map} +1 -1
- package/dist/{redirects-Dmj6KRU3.mjs → redirects-COMLwsV5.mjs} +19 -5
- package/dist/redirects-COMLwsV5.mjs.map +1 -0
- package/dist/{registry-BnCeHYsf.mjs → registry-DqrAQDXH.mjs} +4 -4
- package/dist/{registry-BnCeHYsf.mjs.map → registry-DqrAQDXH.mjs.map} +1 -1
- package/dist/request-cache-dzCt8TZB.mjs.map +1 -1
- package/dist/request-context.mjs.map +1 -1
- package/dist/{request-meta-CLCwSQOS.mjs → request-meta-C_Cjii-T.mjs} +2 -2
- package/dist/{request-meta-CLCwSQOS.mjs.map → request-meta-C_Cjii-T.mjs.map} +1 -1
- package/dist/resolve-Cj98DuqN.mjs +39 -0
- package/dist/resolve-Cj98DuqN.mjs.map +1 -0
- package/dist/{runner-DdnQIwz_.mjs → runner-CGlojznK.mjs} +472 -165
- package/dist/runner-CGlojznK.mjs.map +1 -0
- package/dist/{runner-DcfZewkO.d.mts → runner-CNHRo1mT.d.mts} +2 -2
- package/dist/{runner-DcfZewkO.d.mts.map → runner-CNHRo1mT.d.mts.map} +1 -1
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +2 -2
- package/dist/{schema-BmqagCwG.mjs → schema-Djdlfi5G.mjs} +4 -4
- package/dist/{schema-BmqagCwG.mjs.map → schema-Djdlfi5G.mjs.map} +1 -1
- package/dist/{search-CPrvO5u8.mjs → search-By-NN3da.mjs} +4 -4
- package/dist/{search-CPrvO5u8.mjs.map → search-By-NN3da.mjs.map} +1 -1
- package/dist/{secrets-6pgZyq0K.mjs → secrets-rPdhEBkD.mjs} +1 -1
- package/dist/{secrets-6pgZyq0K.mjs.map → secrets-rPdhEBkD.mjs.map} +1 -1
- package/dist/{sections-Cm-zb-gZ.mjs → sections-DcBIlOq1.mjs} +3 -3
- package/dist/{sections-Cm-zb-gZ.mjs.map → sections-DcBIlOq1.mjs.map} +1 -1
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +16 -16
- package/dist/seo/index.d.mts +1 -1
- package/dist/{seo-DRq9-EPP.mjs → seo-bjDoq9Eg.mjs} +2 -2
- package/dist/{seo-DRq9-EPP.mjs.map → seo-bjDoq9Eg.mjs.map} +1 -1
- package/dist/{service-vByySp-2.mjs → service-BuuTdGAT.mjs} +3 -3
- package/dist/{service-vByySp-2.mjs.map → service-BuuTdGAT.mjs.map} +1 -1
- package/dist/{settings-CBBj7HUd.mjs → settings-CJnKiWuR.mjs} +3 -3
- package/dist/{settings-CBBj7HUd.mjs.map → settings-CJnKiWuR.mjs.map} +1 -1
- package/dist/{settings-xQKsWnzQ.mjs → settings-hcubRfkr.mjs} +3 -3
- package/dist/settings-hcubRfkr.mjs.map +1 -0
- package/dist/{setup-BGAJ2uXs.mjs → setup-Cf_TyOv5.mjs} +2 -2
- package/dist/{setup-BGAJ2uXs.mjs.map → setup-Cf_TyOv5.mjs.map} +1 -1
- package/dist/{setup-complete-C6ZCLhKo.mjs → setup-complete-MzzN9u0b.mjs} +1 -1
- package/dist/{setup-complete-C6ZCLhKo.mjs.map → setup-complete-MzzN9u0b.mjs.map} +1 -1
- package/dist/{setup-nonce-CY1gQiAU.mjs → setup-nonce-DXuriHsg.mjs} +1 -1
- package/dist/{setup-nonce-CY1gQiAU.mjs.map → setup-nonce-DXuriHsg.mjs.map} +1 -1
- package/dist/{site-url-D-M4Fd8O.mjs → site-url-xkhw1tcz.mjs} +1 -1
- package/dist/{site-url-D-M4Fd8O.mjs.map → site-url-xkhw1tcz.mjs.map} +1 -1
- package/dist/{ssrf-DzFN_qV-.mjs → ssrf-MZ-zrG6-.mjs} +1 -1
- package/dist/{ssrf-DzFN_qV-.mjs.map → ssrf-MZ-zrG6-.mjs.map} +1 -1
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/local.mjs.map +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +1 -1
- package/dist/storage/s3.mjs.map +1 -1
- package/dist/{taxonomies-Dc0mzlms.mjs → taxonomies-CLs9HPE2.mjs} +4 -4
- package/dist/{taxonomies-Dc0mzlms.mjs.map → taxonomies-CLs9HPE2.mjs.map} +1 -1
- package/dist/{taxonomies-Cn9UpaR2.mjs → taxonomies-WamPVA2x.mjs} +7 -42
- package/dist/taxonomies-WamPVA2x.mjs.map +1 -0
- package/dist/{taxonomy-wPfusMK9.mjs → taxonomy-D4Uc2LsZ.mjs} +3 -3
- package/dist/{taxonomy-wPfusMK9.mjs.map → taxonomy-D4Uc2LsZ.mjs.map} +1 -1
- package/dist/{tokens-DILYNZMi.mjs → tokens-N8otWMmj.mjs} +1 -1
- package/dist/{tokens-DILYNZMi.mjs.map → tokens-N8otWMmj.mjs.map} +1 -1
- package/dist/{transport-fw-mKJzT.mjs → transport-B6CHddbu.mjs} +1 -1
- package/dist/{transport-fw-mKJzT.mjs.map → transport-B6CHddbu.mjs.map} +1 -1
- package/dist/{transport-GeXlLscf.d.mts → transport-DOxLfUir.d.mts} +1 -1
- package/dist/{transport-GeXlLscf.d.mts.map → transport-DOxLfUir.d.mts.map} +1 -1
- package/dist/{trusted-proxy-CJhQIk65.mjs → trusted-proxy-97pajC2f.mjs} +1 -1
- package/dist/{trusted-proxy-CJhQIk65.mjs.map → trusted-proxy-97pajC2f.mjs.map} +1 -1
- package/dist/{types-CwXMEPRr.mjs → types-ByV5sgsv.mjs} +2 -2
- package/dist/types-ByV5sgsv.mjs.map +1 -0
- package/dist/{types-Dz9CGX_d.mjs → types-Cd9UCu3t.mjs} +1 -1
- package/dist/{types-Dz9CGX_d.mjs.map → types-Cd9UCu3t.mjs.map} +1 -1
- package/dist/{types-DmxPPXGf.d.mts → types-CkDSF81F.d.mts} +1 -1
- package/dist/{types-DmxPPXGf.d.mts.map → types-CkDSF81F.d.mts.map} +1 -1
- package/dist/{types-BWhaSS7U.d.mts → types-CpUuGcd5.d.mts} +1 -1
- package/dist/{types-BWhaSS7U.d.mts.map → types-CpUuGcd5.d.mts.map} +1 -1
- package/dist/{types-DFowNO60.d.mts → types-D599-ruj.d.mts} +1 -1
- package/dist/{types-DFowNO60.d.mts.map → types-D599-ruj.d.mts.map} +1 -1
- package/dist/{types-B05e2naf.d.mts → types-DGHWRQgr.d.mts} +3 -3
- package/dist/{types-B05e2naf.d.mts.map → types-DGHWRQgr.d.mts.map} +1 -1
- package/dist/{types-CzvJd1ND.d.mts → types-DaYDYW6g.d.mts} +14 -1
- package/dist/types-DaYDYW6g.d.mts.map +1 -0
- package/dist/{types-C1KKK4VP.d.mts → types-DaqNzqVt.d.mts} +16 -1
- package/dist/{types-C1KKK4VP.d.mts.map → types-DaqNzqVt.d.mts.map} +1 -1
- package/dist/{types-DW1l0gCv.d.mts → types-Dgo6y-Ut.d.mts} +1 -1
- package/dist/{types-DW1l0gCv.d.mts.map → types-Dgo6y-Ut.d.mts.map} +1 -1
- package/dist/{types-Cb2UCDJg.d.mts → types-bYmRn_Uy.d.mts} +1 -1
- package/dist/{types-Cb2UCDJg.d.mts.map → types-bYmRn_Uy.d.mts.map} +1 -1
- package/dist/{user-Dr1bOCqS.mjs → user-D3BD5zdT.mjs} +2 -2
- package/dist/{user-Dr1bOCqS.mjs.map → user-D3BD5zdT.mjs.map} +1 -1
- package/dist/{utils-_F-rWBTN.mjs → utils-C3wTAP-P.mjs} +1 -1
- package/dist/{utils-_F-rWBTN.mjs.map → utils-C3wTAP-P.mjs.map} +1 -1
- package/dist/{validate-BpQGsmd7.d.mts → validate-DQtHw9NT.d.mts} +5 -5
- package/dist/{validate-BpQGsmd7.d.mts.map → validate-DQtHw9NT.d.mts.map} +1 -1
- package/dist/{validate-DlFxcVVK.mjs → validate-mz87i8_1.mjs} +2 -2
- package/dist/{validate-DlFxcVVK.mjs.map → validate-mz87i8_1.mjs.map} +1 -1
- package/dist/{validation-BiFJqUp5.mjs → validation-DKHhXjPr.mjs} +5 -5
- package/dist/{validation-BiFJqUp5.mjs.map → validation-DKHhXjPr.mjs.map} +1 -1
- package/dist/version-Ct7C6RSo.mjs +7 -0
- package/dist/{version-DNmQakZO.mjs.map → version-Ct7C6RSo.mjs.map} +1 -1
- package/dist/{widgets-B9j_yzlk.mjs → widgets-lShIQXU5.mjs} +3 -3
- package/dist/widgets-lShIQXU5.mjs.map +1 -0
- package/dist/{zod-generator-DSyz01KE.mjs → zod-generator-dvxgmd1M.mjs} +2 -2
- package/dist/{zod-generator-DSyz01KE.mjs.map → zod-generator-dvxgmd1M.mjs.map} +1 -1
- package/package.json +11 -9
- package/src/api/error.ts +18 -3
- package/src/api/errors.ts +6 -0
- package/src/api/handlers/bylines.ts +161 -0
- package/src/api/handlers/content.ts +125 -43
- package/src/api/handlers/index.ts +6 -0
- package/src/api/handlers/marketplace.ts +27 -5
- package/src/api/handlers/oauth-clients.ts +1 -1
- package/src/api/handlers/registry.ts +553 -4
- package/src/api/openapi/document.ts +1 -1
- package/src/api/schemas/bylines.ts +46 -0
- package/src/astro/integration/index.ts +1 -1
- package/src/astro/integration/routes.ts +5 -0
- package/src/astro/integration/runtime.ts +12 -1
- package/src/astro/integration/virtual-modules.ts +19 -2
- package/src/astro/integration/vite-config.ts +2 -2
- package/src/astro/middleware/auth.ts +7 -7
- package/src/astro/middleware/request-context.ts +1 -1
- package/src/astro/middleware.ts +31 -20
- package/src/astro/routes/api/admin/bylines/[id]/index.ts +3 -12
- package/src/astro/routes/api/admin/bylines/[id]/translations.ts +99 -0
- package/src/astro/routes/api/admin/bylines/index.ts +22 -11
- package/src/astro/routes/api/admin/plugins/[id]/update.ts +1 -0
- package/src/astro/routes/api/admin/plugins/marketplace/[id]/install.ts +6 -1
- package/src/astro/routes/api/admin/plugins/registry/[id]/uninstall.ts +51 -0
- package/src/astro/routes/api/admin/plugins/registry/[id]/update.ts +79 -0
- package/src/astro/routes/api/admin/plugins/updates.ts +43 -6
- package/src/astro/routes/api/admin/themes/marketplace/index.ts +1 -1
- package/src/astro/routes/api/auth/oauth/[provider]/callback.ts +2 -2
- package/src/astro/routes/api/auth/oauth/[provider].ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/discard-draft.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/duplicate.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/publish.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/restore.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/schedule.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id]/terms/[taxonomy].ts +6 -6
- package/src/astro/routes/api/content/[collection]/[id]/translations.ts +1 -1
- package/src/astro/routes/api/content/[collection]/[id]/unpublish.ts +2 -2
- package/src/astro/routes/api/content/[collection]/[id].ts +6 -6
- package/src/astro/routes/api/import/wordpress/execute.ts +1 -1
- package/src/astro/routes/api/import/wordpress/prepare.ts +2 -2
- package/src/astro/routes/api/import/wordpress/rewrite-urls.ts +3 -3
- package/src/astro/routes/api/import/wordpress-plugin/execute.ts +2 -2
- package/src/astro/routes/api/media/upload-url.ts +1 -1
- package/src/astro/routes/api/redirects/404s/index.ts +3 -3
- package/src/astro/routes/api/redirects/404s/summary.ts +1 -1
- package/src/astro/routes/api/redirects/[id].ts +3 -3
- package/src/astro/routes/api/redirects/index.ts +2 -2
- package/src/astro/routes/api/schema/collections/[slug]/fields/[fieldSlug].ts +4 -4
- package/src/astro/routes/api/schema/collections/[slug]/fields/index.ts +2 -6
- package/src/astro/routes/api/schema/collections/[slug]/fields/reorder.ts +1 -1
- package/src/astro/routes/api/schema/collections/[slug]/index.ts +6 -6
- package/src/astro/routes/api/schema/collections/index.ts +4 -4
- package/src/astro/routes/api/schema/index.ts +1 -1
- package/src/astro/routes/api/schema/orphans/[slug].ts +1 -1
- package/src/astro/routes/api/schema/orphans/index.ts +1 -1
- package/src/astro/routes/api/sections/[slug].ts +3 -3
- package/src/astro/routes/api/sections/index.ts +2 -2
- package/src/astro/types.ts +4 -0
- package/src/auth/rate-limit.ts +1 -1
- package/src/auth/trusted-proxy.ts +1 -1
- package/src/bylines/index.ts +154 -55
- package/src/cli/commands/init.ts +4 -8
- package/src/client/index.ts +1 -1
- package/src/components/InlinePortableTextEditor.tsx +5 -1
- package/src/components/inline-code-block.tsx +343 -0
- package/src/config/secrets.ts +3 -3
- package/src/database/migrations/006_taxonomy_defs.ts +1 -1
- package/src/database/migrations/014_draft_revisions.ts +6 -6
- package/src/database/migrations/040_byline_i18n.ts +497 -0
- package/src/database/migrations/runner.ts +4 -1
- package/src/database/repositories/audit.ts +2 -2
- package/src/database/repositories/byline.ts +320 -50
- package/src/database/repositories/media.ts +2 -2
- package/src/database/repositories/menu.ts +1 -1
- package/src/database/repositories/options.ts +3 -3
- package/src/database/repositories/plugin-storage.ts +3 -3
- package/src/database/repositories/types.ts +13 -0
- package/src/database/types.ts +15 -0
- package/src/emdash-runtime.ts +492 -20
- package/src/i18n/config.ts +1 -1
- package/src/index.ts +7 -0
- package/src/loader.ts +1 -1
- package/src/mcp/server.ts +3 -3
- package/src/media/mime.ts +1 -1
- package/src/page/absolute-url.ts +1 -1
- package/src/plugins/adapt-sandbox-entry.ts +45 -40
- package/src/plugins/email-console.ts +1 -1
- package/src/plugins/index.ts +1 -0
- package/src/plugins/marketplace.ts +1 -1
- package/src/plugins/sandbox/index.ts +1 -0
- package/src/plugins/sandbox/noop.ts +11 -3
- package/src/plugins/sandbox/types.ts +28 -0
- package/src/query.ts +17 -2
- package/src/registry/config.ts +1 -1
- package/src/request-cache.ts +3 -3
- package/src/request-context.ts +1 -1
- package/src/settings/index.ts +4 -4
- package/src/storage/local.ts +1 -1
- package/src/storage/s3.ts +3 -3
- package/src/widgets/index.ts +1 -1
- package/dist/api-BMLZuwM4.mjs.map +0 -1
- package/dist/byline-D09BaS4j.mjs +0 -220
- package/dist/byline-D09BaS4j.mjs.map +0 -1
- package/dist/bylines-BTM2xtP8.mjs +0 -113
- package/dist/bylines-BTM2xtP8.mjs.map +0 -1
- package/dist/bylines-BdUP8NuI.d.mts.map +0 -1
- package/dist/context-qF8d3IPR.mjs.map +0 -1
- package/dist/email-console-Dmp5Q-P2.mjs.map +0 -1
- package/dist/error-tSQWIl5U.mjs.map +0 -1
- package/dist/index-BV8iJ-6s.d.mts.map +0 -1
- package/dist/loader-Cs6-Bqe6.mjs.map +0 -1
- package/dist/media-Dg7he9uK.mjs.map +0 -1
- package/dist/menus-DOzIecHi.mjs.map +0 -1
- package/dist/menus-X4Z-eBA1.mjs.map +0 -1
- package/dist/oauth-clients-D_B0_-Bz.mjs.map +0 -1
- package/dist/options-Cq64Wx0O.d.mts.map +0 -1
- package/dist/redirects-Dmj6KRU3.mjs.map +0 -1
- package/dist/runner-DdnQIwz_.mjs.map +0 -1
- package/dist/settings-xQKsWnzQ.mjs.map +0 -1
- package/dist/taxonomies-Cn9UpaR2.mjs.map +0 -1
- package/dist/types-CwXMEPRr.mjs.map +0 -1
- package/dist/types-CzvJd1ND.d.mts.map +0 -1
- package/dist/version-DNmQakZO.mjs +0 -7
- package/dist/widgets-B9j_yzlk.mjs.map +0 -1
- /package/dist/{api-tokens-D3C9v02m.mjs → api-tokens-iPIHAY8N.mjs} +0 -0
- /package/dist/{ssrf-CTul4uQi.mjs → ssrf-BIcd-aXW.mjs} +0 -0
- /package/dist/{types-Db67HHlU.mjs → types-1NNkmTIn.mjs} +0 -0
|
@@ -24,6 +24,18 @@ export interface CreateBylineInput {
|
|
|
24
24
|
websiteUrl?: string | null;
|
|
25
25
|
userId?: string | null;
|
|
26
26
|
isGuest?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Locale this byline row belongs to. When omitted, the DB DEFAULT (the
|
|
29
|
+
* configured `defaultLocale` after migration 040) is used. Keeps behaviour
|
|
30
|
+
* consistent with `TaxonomyRepository.create`.
|
|
31
|
+
*/
|
|
32
|
+
locale?: string;
|
|
33
|
+
/**
|
|
34
|
+
* When set, the new row joins the source byline's translation_group rather
|
|
35
|
+
* than minting a fresh one. The source must exist; otherwise the create
|
|
36
|
+
* throws. Mirrors `TaxonomyRepository.create`.
|
|
37
|
+
*/
|
|
38
|
+
translationOf?: string;
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
export interface UpdateBylineInput {
|
|
@@ -53,9 +65,29 @@ function rowToByline(row: BylineRow): BylineSummary {
|
|
|
53
65
|
isGuest: row.is_guest === 1,
|
|
54
66
|
createdAt: row.created_at,
|
|
55
67
|
updatedAt: row.updated_at,
|
|
68
|
+
locale: row.locale,
|
|
69
|
+
translationGroup: row.translation_group,
|
|
56
70
|
};
|
|
57
71
|
}
|
|
58
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Byline repository for content credits.
|
|
75
|
+
*
|
|
76
|
+
* Bylines are per-locale (migration 040). Translations of the same byline
|
|
77
|
+
* share a `translation_group` ULID. `_emdash_content_bylines.byline_id` and
|
|
78
|
+
* `ec_*.primary_byline_id` store the translation_group (not a row id) so a
|
|
79
|
+
* single credit spans every locale variant of a byline.
|
|
80
|
+
*
|
|
81
|
+
* The repository does not resolve locale fallbacks on its own — callers
|
|
82
|
+
* supply the locale they want. Hydration is strict per locale: a credit at
|
|
83
|
+
* locale X renders iff a byline row exists at locale X within the credited
|
|
84
|
+
* translation group. This mirrors `TaxonomyRepository.getTermsForEntry` and
|
|
85
|
+
* the convention established by PR #916.
|
|
86
|
+
*
|
|
87
|
+
* Runtime helpers in `packages/core/src/bylines/index.ts` may layer fallback
|
|
88
|
+
* resolution on top for the "look up one byline by slug" path, but the
|
|
89
|
+
* relation-hydration methods on this class are always strict.
|
|
90
|
+
*/
|
|
59
91
|
export class BylineRepository {
|
|
60
92
|
constructor(private db: Kysely<Database>) {}
|
|
61
93
|
|
|
@@ -68,21 +100,28 @@ export class BylineRepository {
|
|
|
68
100
|
return row ? rowToByline(row) : null;
|
|
69
101
|
}
|
|
70
102
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Find a byline by slug. When `locale` is provided, filter by it strictly.
|
|
105
|
+
* When omitted, returns the lowest-locale-code match (deterministic across
|
|
106
|
+
* calls). Mirrors `TaxonomyRepository.findBySlug`.
|
|
107
|
+
*/
|
|
108
|
+
async findBySlug(slug: string, options?: { locale?: string }): Promise<BylineSummary | null> {
|
|
109
|
+
let query = this.db.selectFrom("_emdash_bylines").selectAll().where("slug", "=", slug);
|
|
110
|
+
if (options?.locale !== undefined) query = query.where("locale", "=", options.locale);
|
|
111
|
+
const row = await query.orderBy("locale", "asc").executeTakeFirst();
|
|
77
112
|
return row ? rowToByline(row) : null;
|
|
78
113
|
}
|
|
79
114
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
115
|
+
/**
|
|
116
|
+
* Find the byline linked to a CMS user. Post-migration 040 the partial
|
|
117
|
+
* unique on user_id is `(user_id, locale)`, so `locale` is required to
|
|
118
|
+
* disambiguate when multiple locale variants exist. When omitted, returns
|
|
119
|
+
* the lowest-locale-code match.
|
|
120
|
+
*/
|
|
121
|
+
async findByUserId(userId: string, options?: { locale?: string }): Promise<BylineSummary | null> {
|
|
122
|
+
let query = this.db.selectFrom("_emdash_bylines").selectAll().where("user_id", "=", userId);
|
|
123
|
+
if (options?.locale !== undefined) query = query.where("locale", "=", options.locale);
|
|
124
|
+
const row = await query.orderBy("locale", "asc").executeTakeFirst();
|
|
86
125
|
return row ? rowToByline(row) : null;
|
|
87
126
|
}
|
|
88
127
|
|
|
@@ -90,6 +129,7 @@ export class BylineRepository {
|
|
|
90
129
|
search?: string;
|
|
91
130
|
isGuest?: boolean;
|
|
92
131
|
userId?: string;
|
|
132
|
+
locale?: string;
|
|
93
133
|
cursor?: string;
|
|
94
134
|
limit?: number;
|
|
95
135
|
}): Promise<FindManyResult<BylineSummary>> {
|
|
@@ -121,6 +161,10 @@ export class BylineRepository {
|
|
|
121
161
|
query = query.where("user_id", "=", options.userId);
|
|
122
162
|
}
|
|
123
163
|
|
|
164
|
+
if (options?.locale !== undefined) {
|
|
165
|
+
query = query.where("locale", "=", options.locale);
|
|
166
|
+
}
|
|
167
|
+
|
|
124
168
|
if (options?.cursor) {
|
|
125
169
|
const decoded = decodeCursor(options.cursor);
|
|
126
170
|
query = query.where((eb) =>
|
|
@@ -145,10 +189,44 @@ export class BylineRepository {
|
|
|
145
189
|
return result;
|
|
146
190
|
}
|
|
147
191
|
|
|
192
|
+
/**
|
|
193
|
+
* List every sibling row in `translation_group`. Used by the admin
|
|
194
|
+
* `TranslationsPanel` to render one entry per configured locale.
|
|
195
|
+
*/
|
|
196
|
+
async listTranslations(id: string): Promise<BylineSummary[]> {
|
|
197
|
+
const anchor = await this.findById(id);
|
|
198
|
+
if (!anchor) return [];
|
|
199
|
+
const group = anchor.translationGroup ?? anchor.id;
|
|
200
|
+
return this.findByTranslationGroup(group);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Direct lookup by `translation_group`. Returns every locale variant of a
|
|
205
|
+
* byline, ordered by locale code (deterministic).
|
|
206
|
+
*/
|
|
207
|
+
async findByTranslationGroup(translationGroup: string): Promise<BylineSummary[]> {
|
|
208
|
+
const rows = await this.db
|
|
209
|
+
.selectFrom("_emdash_bylines")
|
|
210
|
+
.selectAll()
|
|
211
|
+
.where("translation_group", "=", translationGroup)
|
|
212
|
+
.orderBy("locale", "asc")
|
|
213
|
+
.execute();
|
|
214
|
+
return rows.map(rowToByline);
|
|
215
|
+
}
|
|
216
|
+
|
|
148
217
|
async create(input: CreateBylineInput): Promise<BylineSummary> {
|
|
149
218
|
const id = ulid();
|
|
150
219
|
const now = new Date().toISOString();
|
|
151
220
|
|
|
221
|
+
// translationOf joins the source byline's group; otherwise we mint a
|
|
222
|
+
// fresh group equal to id (matching migration 040's backfill pattern).
|
|
223
|
+
let translationGroup: string = id;
|
|
224
|
+
if (input.translationOf) {
|
|
225
|
+
const source = await this.findById(input.translationOf);
|
|
226
|
+
if (!source) throw new Error("Source byline for translation not found");
|
|
227
|
+
translationGroup = source.translationGroup ?? source.id;
|
|
228
|
+
}
|
|
229
|
+
|
|
152
230
|
await this.db
|
|
153
231
|
.insertInto("_emdash_bylines")
|
|
154
232
|
.values({
|
|
@@ -162,6 +240,10 @@ export class BylineRepository {
|
|
|
162
240
|
is_guest: input.isGuest ? 1 : 0,
|
|
163
241
|
created_at: now,
|
|
164
242
|
updated_at: now,
|
|
243
|
+
// When omitted the DB DEFAULT (configured defaultLocale) is used —
|
|
244
|
+
// keeps behaviour consistent with TaxonomyRepository.create.
|
|
245
|
+
...(input.locale !== undefined ? { locale: input.locale } : {}),
|
|
246
|
+
translation_group: translationGroup,
|
|
165
247
|
})
|
|
166
248
|
.execute();
|
|
167
249
|
|
|
@@ -192,22 +274,46 @@ export class BylineRepository {
|
|
|
192
274
|
return await this.findById(id);
|
|
193
275
|
}
|
|
194
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Delete a byline row. When this row is the last sibling in its
|
|
279
|
+
* translation group, also drops every junction row pointing at the group
|
|
280
|
+
* and clears `primary_byline_id` references. When other siblings remain
|
|
281
|
+
* in the group, junctions and `primary_byline_id` pointers stay intact —
|
|
282
|
+
* the credit lives on at other locales.
|
|
283
|
+
*
|
|
284
|
+
* Migration 040 dropped the FK on `_emdash_content_bylines.byline_id`, so
|
|
285
|
+
* this cascade is implemented here in application code.
|
|
286
|
+
*/
|
|
195
287
|
async delete(id: string): Promise<boolean> {
|
|
196
288
|
const existing = await this.findById(id);
|
|
197
289
|
if (!existing) return false;
|
|
198
290
|
|
|
199
|
-
|
|
200
|
-
await trx.deleteFrom("_emdash_content_bylines").where("byline_id", "=", id).execute();
|
|
291
|
+
const group = existing.translationGroup ?? existing.id;
|
|
201
292
|
|
|
293
|
+
await withTransaction(this.db, async (trx) => {
|
|
202
294
|
await trx.deleteFrom("_emdash_bylines").where("id", "=", id).execute();
|
|
203
295
|
|
|
296
|
+
// Count remaining siblings in the translation group. If none
|
|
297
|
+
// remain, purge dependent rows; otherwise leave them intact so
|
|
298
|
+
// the credit still resolves at other locales.
|
|
299
|
+
const remaining = await trx
|
|
300
|
+
.selectFrom("_emdash_bylines")
|
|
301
|
+
.select(({ fn }) => [fn.count<number>("id").as("count")])
|
|
302
|
+
.where("translation_group", "=", group)
|
|
303
|
+
.executeTakeFirst();
|
|
304
|
+
const remainingCount = Number(remaining?.count ?? 0);
|
|
305
|
+
if (remainingCount > 0) return;
|
|
306
|
+
|
|
307
|
+
// Last sibling gone: cascade in application code.
|
|
308
|
+
await trx.deleteFrom("_emdash_content_bylines").where("byline_id", "=", group).execute();
|
|
309
|
+
|
|
204
310
|
const tableNames = await listTablesLike(trx, "ec_%");
|
|
205
311
|
for (const tableName of tableNames) {
|
|
206
312
|
validateIdentifier(tableName, "content table");
|
|
207
313
|
await sql`
|
|
208
314
|
UPDATE ${sql.ref(tableName)}
|
|
209
315
|
SET primary_byline_id = NULL
|
|
210
|
-
WHERE primary_byline_id = ${
|
|
316
|
+
WHERE primary_byline_id = ${group}
|
|
211
317
|
`.execute(trx);
|
|
212
318
|
}
|
|
213
319
|
});
|
|
@@ -215,13 +321,21 @@ export class BylineRepository {
|
|
|
215
321
|
return true;
|
|
216
322
|
}
|
|
217
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Strict per-locale credit hydration. Joins `_emdash_content_bylines` to
|
|
326
|
+
* `_emdash_bylines` on `translation_group = byline_id`, then filters to
|
|
327
|
+
* the requested locale. Credits whose translation group lacks a row at
|
|
328
|
+
* the requested locale are omitted — callers wanting fallback behaviour
|
|
329
|
+
* apply it themselves. Mirrors `TaxonomyRepository.getTermsForEntry`.
|
|
330
|
+
*/
|
|
218
331
|
async getContentBylines(
|
|
219
332
|
collectionSlug: string,
|
|
220
333
|
contentId: string,
|
|
334
|
+
options?: { locale?: string },
|
|
221
335
|
): Promise<ContentBylineCredit[]> {
|
|
222
|
-
|
|
336
|
+
let query = this.db
|
|
223
337
|
.selectFrom("_emdash_content_bylines as cb")
|
|
224
|
-
.innerJoin("_emdash_bylines as b", "b.
|
|
338
|
+
.innerJoin("_emdash_bylines as b", "b.translation_group", "cb.byline_id")
|
|
225
339
|
.select([
|
|
226
340
|
"cb.sort_order as sort_order",
|
|
227
341
|
"cb.role_label as role_label",
|
|
@@ -235,12 +349,15 @@ export class BylineRepository {
|
|
|
235
349
|
"b.is_guest as is_guest",
|
|
236
350
|
"b.created_at as created_at",
|
|
237
351
|
"b.updated_at as updated_at",
|
|
352
|
+
"b.locale as locale",
|
|
353
|
+
"b.translation_group as translation_group",
|
|
238
354
|
])
|
|
239
355
|
.where("cb.collection_slug", "=", collectionSlug)
|
|
240
356
|
.where("cb.content_id", "=", contentId)
|
|
241
|
-
.orderBy("cb.sort_order", "asc")
|
|
242
|
-
|
|
357
|
+
.orderBy("cb.sort_order", "asc");
|
|
358
|
+
if (options?.locale !== undefined) query = query.where("b.locale", "=", options.locale);
|
|
243
359
|
|
|
360
|
+
const rows = await query.execute();
|
|
244
361
|
return rows.map((row) => ({
|
|
245
362
|
byline: rowToByline(row),
|
|
246
363
|
sortOrder: row.sort_order,
|
|
@@ -249,21 +366,68 @@ export class BylineRepository {
|
|
|
249
366
|
}
|
|
250
367
|
|
|
251
368
|
/**
|
|
252
|
-
*
|
|
253
|
-
*
|
|
369
|
+
* Does this entry have any explicit byline credits — at any locale?
|
|
370
|
+
*
|
|
371
|
+
* Used to disambiguate "no credits exist" (fall back to author-linked
|
|
372
|
+
* byline) from "credits exist but don't resolve at the requested locale"
|
|
373
|
+
* (strict per-locale model: render no byline). Without this check the
|
|
374
|
+
* locale-strict hydration would silently turn a missing translation into
|
|
375
|
+
* an author-inferred byline, contradicting editorial intent.
|
|
376
|
+
*/
|
|
377
|
+
async hasContentBylines(collectionSlug: string, contentId: string): Promise<boolean> {
|
|
378
|
+
const row = await this.db
|
|
379
|
+
.selectFrom("_emdash_content_bylines")
|
|
380
|
+
.select("id")
|
|
381
|
+
.where("collection_slug", "=", collectionSlug)
|
|
382
|
+
.where("content_id", "=", contentId)
|
|
383
|
+
.limit(1)
|
|
384
|
+
.executeTakeFirst();
|
|
385
|
+
return row !== undefined;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Batch variant of `hasContentBylines`. Returns the set of content IDs
|
|
390
|
+
* that have at least one junction row (locale-agnostic).
|
|
391
|
+
*/
|
|
392
|
+
async hasContentBylinesMany(collectionSlug: string, contentIds: string[]): Promise<Set<string>> {
|
|
393
|
+
const result = new Set<string>();
|
|
394
|
+
if (contentIds.length === 0) return result;
|
|
395
|
+
|
|
396
|
+
const uniqueContentIds = [...new Set(contentIds)];
|
|
397
|
+
for (const chunk of chunks(uniqueContentIds, SQL_BATCH_SIZE)) {
|
|
398
|
+
const rows = await this.db
|
|
399
|
+
.selectFrom("_emdash_content_bylines")
|
|
400
|
+
.select("content_id")
|
|
401
|
+
.distinct()
|
|
402
|
+
.where("collection_slug", "=", collectionSlug)
|
|
403
|
+
.where("content_id", "in", chunk)
|
|
404
|
+
.execute();
|
|
405
|
+
for (const row of rows) result.add(row.content_id);
|
|
406
|
+
}
|
|
407
|
+
return result;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Batch variant of `getContentBylines`. Same strict-per-locale semantics
|
|
412
|
+
* applied to the requested locale (single value, not per-entry).
|
|
413
|
+
*
|
|
414
|
+
* When callers need per-entry-locale filtering (e.g. a list endpoint
|
|
415
|
+
* returning entries at mixed locales), they should group the input ids by
|
|
416
|
+
* the entry's locale and call this method once per group.
|
|
254
417
|
*/
|
|
255
418
|
async getContentBylinesMany(
|
|
256
419
|
collectionSlug: string,
|
|
257
420
|
contentIds: string[],
|
|
421
|
+
options?: { locale?: string },
|
|
258
422
|
): Promise<Map<string, ContentBylineCredit[]>> {
|
|
259
423
|
const result = new Map<string, ContentBylineCredit[]>();
|
|
260
424
|
if (contentIds.length === 0) return result;
|
|
261
425
|
|
|
262
426
|
const uniqueContentIds = [...new Set(contentIds)];
|
|
263
427
|
for (const chunk of chunks(uniqueContentIds, SQL_BATCH_SIZE)) {
|
|
264
|
-
|
|
428
|
+
let query = this.db
|
|
265
429
|
.selectFrom("_emdash_content_bylines as cb")
|
|
266
|
-
.innerJoin("_emdash_bylines as b", "b.
|
|
430
|
+
.innerJoin("_emdash_bylines as b", "b.translation_group", "cb.byline_id")
|
|
267
431
|
.select([
|
|
268
432
|
"cb.content_id as content_id",
|
|
269
433
|
"cb.sort_order as sort_order",
|
|
@@ -278,11 +442,15 @@ export class BylineRepository {
|
|
|
278
442
|
"b.is_guest as is_guest",
|
|
279
443
|
"b.created_at as created_at",
|
|
280
444
|
"b.updated_at as updated_at",
|
|
445
|
+
"b.locale as locale",
|
|
446
|
+
"b.translation_group as translation_group",
|
|
281
447
|
])
|
|
282
448
|
.where("cb.collection_slug", "=", collectionSlug)
|
|
283
449
|
.where("cb.content_id", "in", chunk)
|
|
284
|
-
.orderBy("cb.sort_order", "asc")
|
|
285
|
-
|
|
450
|
+
.orderBy("cb.sort_order", "asc");
|
|
451
|
+
if (options?.locale !== undefined) query = query.where("b.locale", "=", options.locale);
|
|
452
|
+
|
|
453
|
+
const rows = await query.execute();
|
|
286
454
|
|
|
287
455
|
for (const row of rows) {
|
|
288
456
|
const contentId = row.content_id;
|
|
@@ -305,18 +473,20 @@ export class BylineRepository {
|
|
|
305
473
|
|
|
306
474
|
/**
|
|
307
475
|
* Batch-fetch byline profiles linked to user IDs in a single query.
|
|
308
|
-
*
|
|
476
|
+
* Strict-locale variant of `findByUserId`.
|
|
309
477
|
*/
|
|
310
|
-
async findByUserIds(
|
|
478
|
+
async findByUserIds(
|
|
479
|
+
userIds: string[],
|
|
480
|
+
options?: { locale?: string },
|
|
481
|
+
): Promise<Map<string, BylineSummary>> {
|
|
311
482
|
const result = new Map<string, BylineSummary>();
|
|
312
483
|
if (userIds.length === 0) return result;
|
|
313
484
|
|
|
314
485
|
for (const chunk of chunks(userIds, SQL_BATCH_SIZE)) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
.execute();
|
|
486
|
+
let query = this.db.selectFrom("_emdash_bylines").selectAll().where("user_id", "in", chunk);
|
|
487
|
+
if (options?.locale !== undefined) query = query.where("locale", "=", options.locale);
|
|
488
|
+
|
|
489
|
+
const rows = await query.execute();
|
|
320
490
|
|
|
321
491
|
for (const row of rows) {
|
|
322
492
|
if (row.user_id) {
|
|
@@ -327,6 +497,85 @@ export class BylineRepository {
|
|
|
327
497
|
return result;
|
|
328
498
|
}
|
|
329
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Clone every junction row from `sourceContentId` to `targetContentId`,
|
|
502
|
+
* preserving `sort_order` and `role_label`. Used by the content
|
|
503
|
+
* translation flow: a newly created translation inherits the source's
|
|
504
|
+
* byline credits at the storage level. Because the junction stores
|
|
505
|
+
* `translation_group` (not a row id), the copy is locale-agnostic — the
|
|
506
|
+
* credits resolve to whichever locale variants of each byline exist when
|
|
507
|
+
* the translated entry is hydrated.
|
|
508
|
+
*
|
|
509
|
+
* No-op when the source has no credits. Skips when the target already
|
|
510
|
+
* has credits (idempotent for re-runs).
|
|
511
|
+
*/
|
|
512
|
+
async copyContentBylines(
|
|
513
|
+
collection: string,
|
|
514
|
+
sourceContentId: string,
|
|
515
|
+
targetContentId: string,
|
|
516
|
+
): Promise<void> {
|
|
517
|
+
validateIdentifier(collection, "collection slug");
|
|
518
|
+
const tableName = `ec_${collection}`;
|
|
519
|
+
validateIdentifier(tableName, "content table");
|
|
520
|
+
|
|
521
|
+
// Like `setContentBylines`, this method is expected to be called
|
|
522
|
+
// within a transaction context (content handlers wrap in
|
|
523
|
+
// withTransaction). All operations use `this.db` directly so an
|
|
524
|
+
// outer transaction can serialise the copy alongside the create.
|
|
525
|
+
const existing = await this.db
|
|
526
|
+
.selectFrom("_emdash_content_bylines")
|
|
527
|
+
.select("id")
|
|
528
|
+
.where("collection_slug", "=", collection)
|
|
529
|
+
.where("content_id", "=", targetContentId)
|
|
530
|
+
.executeTakeFirst();
|
|
531
|
+
if (existing) return;
|
|
532
|
+
|
|
533
|
+
const sourceRows = await this.db
|
|
534
|
+
.selectFrom("_emdash_content_bylines")
|
|
535
|
+
.select(["byline_id", "sort_order", "role_label"])
|
|
536
|
+
.where("collection_slug", "=", collection)
|
|
537
|
+
.where("content_id", "=", sourceContentId)
|
|
538
|
+
.orderBy("sort_order", "asc")
|
|
539
|
+
.execute();
|
|
540
|
+
if (sourceRows.length === 0) return;
|
|
541
|
+
|
|
542
|
+
const now = new Date().toISOString();
|
|
543
|
+
await this.db
|
|
544
|
+
.insertInto("_emdash_content_bylines")
|
|
545
|
+
.values(
|
|
546
|
+
sourceRows.map((row) => ({
|
|
547
|
+
id: ulid(),
|
|
548
|
+
collection_slug: collection,
|
|
549
|
+
content_id: targetContentId,
|
|
550
|
+
byline_id: row.byline_id,
|
|
551
|
+
sort_order: row.sort_order,
|
|
552
|
+
role_label: row.role_label,
|
|
553
|
+
created_at: now,
|
|
554
|
+
})),
|
|
555
|
+
)
|
|
556
|
+
.execute();
|
|
557
|
+
|
|
558
|
+
// Mirror primary_byline_id from source so the cached pointer on the
|
|
559
|
+
// target row matches the junction state we just wrote.
|
|
560
|
+
const firstByline = sourceRows[0]?.byline_id ?? null;
|
|
561
|
+
await sql`
|
|
562
|
+
UPDATE ${sql.ref(tableName)}
|
|
563
|
+
SET primary_byline_id = ${firstByline}
|
|
564
|
+
WHERE id = ${targetContentId}
|
|
565
|
+
`.execute(this.db);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Replace the set of byline credits on a content entry. Accepts row ids
|
|
570
|
+
* at the wire (consistent with how the admin sends them), translates
|
|
571
|
+
* each to its `translation_group` on write, and stores the group in
|
|
572
|
+
* `_emdash_content_bylines.byline_id` and `ec_*.primary_byline_id`.
|
|
573
|
+
*
|
|
574
|
+
* The returned credits are hydrated with strict-locale matching at the
|
|
575
|
+
* locale of the rows the caller supplied (i.e. the locale of the byline
|
|
576
|
+
* each `bylineId` resolves to) — adequate for the autosave round-trip,
|
|
577
|
+
* which then re-hydrates the entry against its own locale separately.
|
|
578
|
+
*/
|
|
330
579
|
async setContentBylines(
|
|
331
580
|
collectionSlug: string,
|
|
332
581
|
contentId: string,
|
|
@@ -336,29 +585,48 @@ export class BylineRepository {
|
|
|
336
585
|
const tableName = `ec_${collectionSlug}`;
|
|
337
586
|
validateIdentifier(tableName, "content table");
|
|
338
587
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
// wrapping in a transaction when atomicity is required.
|
|
350
|
-
if (bylines.length > 0) {
|
|
351
|
-
const ids = bylines.map((item) => item.bylineId);
|
|
588
|
+
// Resolve each wire row id to its translation_group up front so we
|
|
589
|
+
// can (a) validate the rows exist and (b) dedupe by the value that
|
|
590
|
+
// actually lands in the junction. Deduping by wire row id BEFORE
|
|
591
|
+
// resolving would let two locale siblings of the same byline slip
|
|
592
|
+
// through and trigger a UNIQUE(collection, content, byline_id)
|
|
593
|
+
// failure at insert time. A single SELECT keeps this O(1) DB
|
|
594
|
+
// calls regardless of how many credits are being set.
|
|
595
|
+
const idToGroup = new Map<string, string>();
|
|
596
|
+
if (inputBylines.length > 0) {
|
|
597
|
+
const wireIds = [...new Set(inputBylines.map((item) => item.bylineId))];
|
|
352
598
|
const rows = await this.db
|
|
353
599
|
.selectFrom("_emdash_bylines")
|
|
354
|
-
.select("id")
|
|
355
|
-
.where("id", "in",
|
|
600
|
+
.select(["id", "translation_group"])
|
|
601
|
+
.where("id", "in", wireIds)
|
|
356
602
|
.execute();
|
|
357
|
-
if (rows.length !==
|
|
603
|
+
if (rows.length !== wireIds.length) {
|
|
358
604
|
throw new Error("One or more byline IDs do not exist");
|
|
359
605
|
}
|
|
606
|
+
for (const row of rows) {
|
|
607
|
+
idToGroup.set(row.id, row.translation_group ?? row.id);
|
|
608
|
+
}
|
|
360
609
|
}
|
|
361
610
|
|
|
611
|
+
// Dedupe by translation_group. Preserves the order of first
|
|
612
|
+
// occurrence so the editor's intent (which sibling appears first)
|
|
613
|
+
// is honored. `roleLabel` follows the first occurrence too.
|
|
614
|
+
const seenGroups = new Set<string>();
|
|
615
|
+
const bylines: Array<ContentBylineInput & { group: string }> = [];
|
|
616
|
+
for (const item of inputBylines) {
|
|
617
|
+
const group = idToGroup.get(item.bylineId);
|
|
618
|
+
if (!group) {
|
|
619
|
+
throw new Error(`Missing translation_group for byline ${item.bylineId}`);
|
|
620
|
+
}
|
|
621
|
+
if (seenGroups.has(group)) continue;
|
|
622
|
+
seenGroups.add(group);
|
|
623
|
+
bylines.push({ ...item, group });
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// This method is expected to be called within a transaction context
|
|
627
|
+
// (content handlers wrap in withTransaction, seed applies sequentially).
|
|
628
|
+
// All operations use this.db directly -- callers are responsible for
|
|
629
|
+
// wrapping in a transaction when atomicity is required.
|
|
362
630
|
await this.db
|
|
363
631
|
.deleteFrom("_emdash_content_bylines")
|
|
364
632
|
.where("collection_slug", "=", collectionSlug)
|
|
@@ -367,13 +635,14 @@ export class BylineRepository {
|
|
|
367
635
|
|
|
368
636
|
for (let i = 0; i < bylines.length; i++) {
|
|
369
637
|
const item = bylines[i];
|
|
638
|
+
if (!item) continue;
|
|
370
639
|
await this.db
|
|
371
640
|
.insertInto("_emdash_content_bylines")
|
|
372
641
|
.values({
|
|
373
642
|
id: ulid(),
|
|
374
643
|
collection_slug: collectionSlug,
|
|
375
644
|
content_id: contentId,
|
|
376
|
-
byline_id: item.
|
|
645
|
+
byline_id: item.group,
|
|
377
646
|
sort_order: i,
|
|
378
647
|
role_label: item.roleLabel ?? null,
|
|
379
648
|
created_at: new Date().toISOString(),
|
|
@@ -381,9 +650,10 @@ export class BylineRepository {
|
|
|
381
650
|
.execute();
|
|
382
651
|
}
|
|
383
652
|
|
|
653
|
+
const primaryGroup = bylines[0]?.group ?? null;
|
|
384
654
|
await sql`
|
|
385
655
|
UPDATE ${sql.ref(tableName)}
|
|
386
|
-
SET primary_byline_id = ${
|
|
656
|
+
SET primary_byline_id = ${primaryGroup}
|
|
387
657
|
WHERE id = ${contentId}
|
|
388
658
|
`.execute(this.db);
|
|
389
659
|
|
|
@@ -20,7 +20,7 @@ function normalizeMimeFilter(input?: string | readonly string[]): string[] {
|
|
|
20
20
|
return arr
|
|
21
21
|
.filter((entry): entry is string => typeof entry === "string" && entry.length > 0)
|
|
22
22
|
.map((entry) =>
|
|
23
|
-
entry.endsWith("/") ? entry.toLowerCase() : entry.split(";")[0]
|
|
23
|
+
entry.endsWith("/") ? entry.toLowerCase() : entry.split(";")[0].trim().toLowerCase(),
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -365,7 +365,7 @@ export class MediaRepository {
|
|
|
365
365
|
contentHash: row.content_hash,
|
|
366
366
|
blurhash: row.blurhash,
|
|
367
367
|
dominantColor: row.dominant_color,
|
|
368
|
-
// eslint-disable-next-line typescript
|
|
368
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- DB stores string; validated at insert but linter can't follow
|
|
369
369
|
status: row.status as MediaStatus,
|
|
370
370
|
createdAt: row.created_at,
|
|
371
371
|
authorId: row.author_id,
|
|
@@ -463,7 +463,7 @@ export class MenuRepository {
|
|
|
463
463
|
.where("menu_id", "=", menuId)
|
|
464
464
|
.where("parent_id", "is", input.parentId ?? null)
|
|
465
465
|
.executeTakeFirst();
|
|
466
|
-
// eslint-disable-next-line typescript
|
|
466
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- Kysely fn.max returns unknown; always a number for sort_order column
|
|
467
467
|
sortOrder = ((maxOrder?.max as number) ?? -1) + 1;
|
|
468
468
|
}
|
|
469
469
|
|
|
@@ -26,7 +26,7 @@ export class OptionsRepository {
|
|
|
26
26
|
.executeTakeFirst();
|
|
27
27
|
|
|
28
28
|
if (!row) return null;
|
|
29
|
-
// eslint-disable-next-line typescript
|
|
29
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T
|
|
30
30
|
return JSON.parse(row.value) as T;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -116,7 +116,7 @@ export class OptionsRepository {
|
|
|
116
116
|
|
|
117
117
|
const result = new Map<string, T>();
|
|
118
118
|
for (const row of rows) {
|
|
119
|
-
// eslint-disable-next-line typescript
|
|
119
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T
|
|
120
120
|
result.set(row.name, JSON.parse(row.value) as T);
|
|
121
121
|
}
|
|
122
122
|
return result;
|
|
@@ -160,7 +160,7 @@ export class OptionsRepository {
|
|
|
160
160
|
|
|
161
161
|
const result = new Map<string, T>();
|
|
162
162
|
for (const row of rows) {
|
|
163
|
-
// eslint-disable-next-line typescript
|
|
163
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T
|
|
164
164
|
result.set(row.name, JSON.parse(row.value) as T);
|
|
165
165
|
}
|
|
166
166
|
return result;
|
|
@@ -57,7 +57,7 @@ export class PluginStorageRepository<T = unknown> implements StorageCollection<T
|
|
|
57
57
|
.executeTakeFirst();
|
|
58
58
|
|
|
59
59
|
if (!row) return null;
|
|
60
|
-
// eslint-disable-next-line typescript
|
|
60
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T
|
|
61
61
|
return JSON.parse(row.data) as T;
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -132,7 +132,7 @@ export class PluginStorageRepository<T = unknown> implements StorageCollection<T
|
|
|
132
132
|
|
|
133
133
|
const result = new Map<string, T>();
|
|
134
134
|
for (const row of rows) {
|
|
135
|
-
// eslint-disable-next-line typescript
|
|
135
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T
|
|
136
136
|
result.set(row.id, JSON.parse(row.data) as T);
|
|
137
137
|
}
|
|
138
138
|
return result;
|
|
@@ -255,7 +255,7 @@ export class PluginStorageRepository<T = unknown> implements StorageCollection<T
|
|
|
255
255
|
const hasMore = rows.length > limit;
|
|
256
256
|
const items = rows.slice(0, limit).map((row) => ({
|
|
257
257
|
id: row.id,
|
|
258
|
-
// eslint-disable-next-line typescript
|
|
258
|
+
// eslint-disable-next-line typescript/no-unsafe-type-assertion -- JSON.parse returns any; generic callers provide T
|
|
259
259
|
data: JSON.parse(row.data) as T,
|
|
260
260
|
}));
|
|
261
261
|
|
|
@@ -63,6 +63,19 @@ export interface BylineSummary {
|
|
|
63
63
|
isGuest: boolean;
|
|
64
64
|
createdAt: string;
|
|
65
65
|
updatedAt: string;
|
|
66
|
+
/**
|
|
67
|
+
* Locale this byline row is presented in. Added by migration 040.
|
|
68
|
+
* `(slug, locale)` is unique; a single slug can repeat across locales.
|
|
69
|
+
*/
|
|
70
|
+
locale: string;
|
|
71
|
+
/**
|
|
72
|
+
* Shared across translations of the same byline. Added by migration 040.
|
|
73
|
+
* `_emdash_content_bylines.byline_id` and `ec_*.primary_byline_id` store
|
|
74
|
+
* this value, so a credit spans every locale variant of a byline.
|
|
75
|
+
* Nullable in storage for backwards compatibility; new rows always
|
|
76
|
+
* populate it.
|
|
77
|
+
*/
|
|
78
|
+
translationGroup: string | null;
|
|
66
79
|
}
|
|
67
80
|
|
|
68
81
|
export interface ContentBylineCredit {
|
package/src/database/types.ts
CHANGED
|
@@ -502,6 +502,21 @@ export interface BylineTable {
|
|
|
502
502
|
is_guest: number;
|
|
503
503
|
created_at: Generated<string>;
|
|
504
504
|
updated_at: Generated<string>;
|
|
505
|
+
/**
|
|
506
|
+
* Locale this byline row is presented in. Added by migration 040. Backfilled
|
|
507
|
+
* to the configured `defaultLocale` for pre-040 rows. `(slug, locale)` is
|
|
508
|
+
* unique; the partial unique on `user_id` widens to `(user_id, locale)`.
|
|
509
|
+
*/
|
|
510
|
+
locale: Generated<string>;
|
|
511
|
+
/**
|
|
512
|
+
* Shared across translations of the same byline. Added by migration 040.
|
|
513
|
+
* Equals `id` for the anchor row; siblings inherit it from their source.
|
|
514
|
+
* `_emdash_content_bylines.byline_id` and `ec_*.primary_byline_id` store
|
|
515
|
+
* this value rather than a row id, so credits span every locale variant of
|
|
516
|
+
* a byline. Nullable in the schema for backwards compatibility; new rows
|
|
517
|
+
* always populate it.
|
|
518
|
+
*/
|
|
519
|
+
translation_group: string | null;
|
|
505
520
|
}
|
|
506
521
|
|
|
507
522
|
export interface ContentBylineTable {
|