emdash 0.13.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-ayIQ7rIe.mjs → api-CLwG_3dh.mjs} +523 -59
- 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-C6eYUWlZ.d.mts → bylines-DtDRNF1n.d.mts} +63 -18
- 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-UmOMt9T-.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-Dw7Z5PVU.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 +10 -8
- 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 +568 -22
- 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-ayIQ7rIe.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-C6eYUWlZ.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-UmOMt9T-.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-Dw7Z5PVU.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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menus-Bjf5R1Qq.mjs","names":[],"sources":["../src/database/repositories/menu.ts","../src/api/handlers/menus.ts"],"sourcesContent":["/**\n * Menu repository\n *\n * Owns every SQL touch for `_emdash_menus` and `_emdash_menu_items`, plus the\n * row→entity mapping. Matches the architecture used by every other resource\n * (content, taxonomies, redirects, comments, media): handlers stay thin and\n * orchestrate; the repository is the single place where snake_case DB columns\n * become camelCase entities (and vice versa).\n *\n * i18n: menus are per-locale. `(name, locale)` is unique. Translations of the\n * same menu share a `translation_group` ULID. Menu item `reference_id` stores\n * the referenced content's translation_group (not a specific row id) so a\n * single menu item survives content translations.\n */\n\nimport type { Kysely, Selectable } from \"kysely\";\nimport { ulid } from \"ulidx\";\n\nimport { withTransaction } from \"../transaction.js\";\nimport type { Database, MenuItemTable, MenuTable } from \"../types.js\";\n\n/**\n * Thrown from inside a repository transaction when the menu the caller\n * resolved earlier has since been deleted. Handlers translate this to a\n * `NOT_FOUND` API response. Necessary because D1 disables FK enforcement\n * (so `ON DELETE CASCADE` won't fire), and an unchecked `setItems` would\n * happily insert items whose `menu_id` no longer exists, leaving orphans.\n */\nexport class MenuGoneError extends Error {\n\tconstructor(public readonly menuId: string) {\n\t\tsuper(`Menu ${menuId} was deleted while being modified`);\n\t\tthis.name = \"MenuGoneError\";\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Entity shapes (camelCase — what the API returns)\n// ---------------------------------------------------------------------------\n\nexport interface Menu {\n\tid: string;\n\tname: string;\n\tlabel: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tlocale: string;\n\ttranslationGroup: string | null;\n}\n\nexport interface MenuItem {\n\tid: string;\n\tmenuId: string;\n\tparentId: string | null;\n\tsortOrder: number;\n\ttype: string;\n\treferenceCollection: string | null;\n\treferenceId: string | null;\n\tcustomUrl: string | null;\n\tlabel: string;\n\ttitleAttr: string | null;\n\ttarget: string | null;\n\tcssClasses: string | null;\n\tcreatedAt: string;\n\tlocale: string;\n\ttranslationGroup: string | null;\n}\n\nexport interface MenuListItem extends Menu {\n\titemCount: number;\n}\n\nexport interface MenuWithItems extends Menu {\n\titems: MenuItem[];\n}\n\nexport interface MenuTranslation {\n\tid: string;\n\tname: string;\n\tlabel: string;\n\tlocale: string;\n\tupdatedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Input shapes\n// ---------------------------------------------------------------------------\n\nexport interface CreateMenuInput {\n\tname: string;\n\tlabel: string;\n\tlocale?: string;\n\t/**\n\t * When set, the new menu joins the source menu's translation_group and\n\t * inherits its items (cloned, with new ULIDs but the same translation_group\n\t * per item so nav entries stay logically identified across translations).\n\t */\n\ttranslationOf?: string;\n}\n\nexport interface UpdateMenuInput {\n\tlabel?: string;\n}\n\nexport interface CreateMenuItemInput {\n\ttype: string;\n\tlabel: string;\n\treferenceCollection?: string;\n\treferenceId?: string;\n\tcustomUrl?: string;\n\ttarget?: string;\n\ttitleAttr?: string;\n\tcssClasses?: string;\n\tparentId?: string;\n\tsortOrder?: number;\n}\n\nexport interface UpdateMenuItemInput {\n\tlabel?: string;\n\tcustomUrl?: string;\n\ttarget?: string;\n\ttitleAttr?: string;\n\tcssClasses?: string;\n\tparentId?: string | null;\n\tsortOrder?: number;\n}\n\n/**\n * Item shape used by `setItems()`. Items are placed by array order. Children\n * point at parents via `parentIndex` (must reference an earlier index, so the\n * insert can resolve parents before children). The validation of that ordering\n * lives at the API boundary (`handleMenuSetItems`) so REST/MCP callers receive\n * the same error shape.\n */\nexport interface SetMenuItem {\n\tlabel: string;\n\ttype: \"custom\" | \"page\" | \"post\" | \"taxonomy\" | \"collection\";\n\tcustomUrl?: string;\n\treferenceCollection?: string;\n\treferenceId?: string;\n\ttitleAttr?: string;\n\ttarget?: string;\n\tcssClasses?: string;\n\tparentIndex?: number;\n}\n\nexport interface ReorderItem {\n\tid: string;\n\tparentId: string | null;\n\tsortOrder: number;\n}\n\n// ---------------------------------------------------------------------------\n// Row → entity mappers\n// ---------------------------------------------------------------------------\n\nfunction rowToMenu(row: Selectable<MenuTable>): Menu {\n\treturn {\n\t\tid: row.id,\n\t\tname: row.name,\n\t\tlabel: row.label,\n\t\tcreatedAt: row.created_at,\n\t\tupdatedAt: row.updated_at,\n\t\tlocale: row.locale,\n\t\ttranslationGroup: row.translation_group,\n\t};\n}\n\nfunction rowToMenuItem(row: Selectable<MenuItemTable>): MenuItem {\n\treturn {\n\t\tid: row.id,\n\t\tmenuId: row.menu_id,\n\t\tparentId: row.parent_id,\n\t\tsortOrder: row.sort_order,\n\t\ttype: row.type,\n\t\treferenceCollection: row.reference_collection,\n\t\treferenceId: row.reference_id,\n\t\tcustomUrl: row.custom_url,\n\t\tlabel: row.label,\n\t\ttitleAttr: row.title_attr,\n\t\ttarget: row.target,\n\t\tcssClasses: row.css_classes,\n\t\tcreatedAt: row.created_at,\n\t\tlocale: row.locale,\n\t\ttranslationGroup: row.translation_group,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Repository\n// ---------------------------------------------------------------------------\n\nexport class MenuRepository {\n\tconstructor(private db: Kysely<Database>) {}\n\n\t// --- Menus -------------------------------------------------------------\n\n\t/**\n\t * List menus with their item counts. When `locale` is omitted, returns\n\t * every locale variant as its own row (consistent with the admin listing\n\t * model: each translation is its own menu for editing purposes).\n\t */\n\tasync findMany(options: { locale?: string } = {}): Promise<MenuListItem[]> {\n\t\t// Single LEFT JOIN + GROUP BY for the per-menu count. Avoids N+1.\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_menus as m\")\n\t\t\t.leftJoin(\"_emdash_menu_items as i\", \"i.menu_id\", \"m.id\")\n\t\t\t.select(({ fn }) => [\n\t\t\t\t\"m.id\",\n\t\t\t\t\"m.name\",\n\t\t\t\t\"m.label\",\n\t\t\t\t\"m.created_at\",\n\t\t\t\t\"m.updated_at\",\n\t\t\t\t\"m.locale\",\n\t\t\t\t\"m.translation_group\",\n\t\t\t\tfn.count<number>(\"i.id\").as(\"itemCount\"),\n\t\t\t])\n\t\t\t.groupBy([\n\t\t\t\t\"m.id\",\n\t\t\t\t\"m.name\",\n\t\t\t\t\"m.label\",\n\t\t\t\t\"m.created_at\",\n\t\t\t\t\"m.updated_at\",\n\t\t\t\t\"m.locale\",\n\t\t\t\t\"m.translation_group\",\n\t\t\t])\n\t\t\t.orderBy(\"m.name\", \"asc\");\n\t\tif (options.locale !== undefined) query = query.where(\"m.locale\", \"=\", options.locale);\n\t\tconst rows = await query.execute();\n\n\t\treturn rows.map((row) => ({\n\t\t\t// Postgres returns count() as `string`; SQLite as `number`. Normalize.\n\t\t\titemCount: typeof row.itemCount === \"string\" ? Number(row.itemCount) : row.itemCount,\n\t\t\t...rowToMenu({\n\t\t\t\tid: row.id,\n\t\t\t\tname: row.name,\n\t\t\t\tlabel: row.label,\n\t\t\t\tcreated_at: row.created_at,\n\t\t\t\tupdated_at: row.updated_at,\n\t\t\t\tlocale: row.locale,\n\t\t\t\ttranslation_group: row.translation_group,\n\t\t\t}),\n\t\t}));\n\t}\n\n\t/**\n\t * Find every menu row matching `name` (one per locale on multi-locale\n\t * installs). Callers use this both to look up a single menu (when locale\n\t * is supplied) and to detect AMBIGUOUS_LOCALE situations (`length > 1`).\n\t */\n\tasync findByName(name: string, options: { locale?: string } = {}): Promise<Menu[]> {\n\t\tlet query = this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where(\"name\", \"=\", name)\n\t\t\t.orderBy(\"locale\", \"asc\");\n\t\tif (options.locale !== undefined) query = query.where(\"locale\", \"=\", options.locale);\n\t\tconst rows = await query.execute();\n\t\treturn rows.map(rowToMenu);\n\t}\n\n\tasync findById(id: string): Promise<Menu | null> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirst();\n\t\treturn row ? rowToMenu(row) : null;\n\t}\n\n\t/** Fetch a menu plus its items, ordered by `sort_order`. */\n\tasync findWithItems(menuId: string): Promise<MenuWithItems | null> {\n\t\tconst menu = await this.findById(menuId);\n\t\tif (!menu) return null;\n\t\tconst items = await this.findItems(menuId);\n\t\treturn { ...menu, items };\n\t}\n\n\tasync findItems(menuId: string): Promise<MenuItem[]> {\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t.execute();\n\t\treturn rows.map(rowToMenuItem);\n\t}\n\n\t/**\n\t * Returns true when a menu already exists for the given `(name, locale)`.\n\t * Used by the handler to surface a CONFLICT before attempting the insert.\n\t */\n\tasync existsByNameAndLocale(name: string, locale: string): Promise<boolean> {\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"name\", \"=\", name)\n\t\t\t.where(\"locale\", \"=\", locale)\n\t\t\t.executeTakeFirst();\n\t\treturn row !== undefined;\n\t}\n\n\t/**\n\t * Create a menu. When `translationOf` is supplied the new menu joins the\n\t * source menu's translation_group and clones its items (each clone gets a\n\t * fresh ULID, but inherits the source item's `translation_group` so a\n\t * given nav entry resolves to \"the same item\" across menu translations).\n\t *\n\t * If the source menu is missing this throws — callers should validate\n\t * existence via `findById` first to return a clean NOT_FOUND.\n\t */\n\tasync create(input: CreateMenuInput): Promise<Menu> {\n\t\tconst id = ulid();\n\n\t\tlet translationGroup: string = id;\n\t\tlet sourceMenuId: string | null = null;\n\t\tif (input.translationOf) {\n\t\t\tconst source = await this.findById(input.translationOf);\n\t\t\tif (!source) throw new Error(\"Source menu for translation not found\");\n\t\t\ttranslationGroup = source.translationGroup ?? source.id;\n\t\t\tsourceMenuId = source.id;\n\t\t}\n\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait trx\n\t\t\t\t.insertInto(\"_emdash_menus\")\n\t\t\t\t.values({\n\t\t\t\t\tid,\n\t\t\t\t\tname: input.name,\n\t\t\t\t\tlabel: input.label,\n\t\t\t\t\t...(input.locale !== undefined ? { locale: input.locale } : {}),\n\t\t\t\t\ttranslation_group: translationGroup,\n\t\t\t\t})\n\t\t\t\t.execute();\n\n\t\t\tif (sourceMenuId) {\n\t\t\t\tconst sourceItems = await trx\n\t\t\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t\t\t.selectAll()\n\t\t\t\t\t.where(\"menu_id\", \"=\", sourceMenuId)\n\t\t\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t\t\t.execute();\n\t\t\t\tif (sourceItems.length > 0) {\n\t\t\t\t\t// old-id → new-id map so parent pointers land on the clones.\n\t\t\t\t\tconst idMap = new Map<string, string>();\n\t\t\t\t\tfor (const item of sourceItems) idMap.set(item.id, ulid());\n\n\t\t\t\t\tawait trx\n\t\t\t\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t\t\t\t.values(\n\t\t\t\t\t\t\tsourceItems.map((item) => ({\n\t\t\t\t\t\t\t\tid: idMap.get(item.id)!,\n\t\t\t\t\t\t\t\tmenu_id: id,\n\t\t\t\t\t\t\t\tparent_id: item.parent_id ? (idMap.get(item.parent_id) ?? null) : null,\n\t\t\t\t\t\t\t\tsort_order: item.sort_order,\n\t\t\t\t\t\t\t\ttype: item.type,\n\t\t\t\t\t\t\t\treference_collection: item.reference_collection,\n\t\t\t\t\t\t\t\treference_id: item.reference_id,\n\t\t\t\t\t\t\t\tcustom_url: item.custom_url,\n\t\t\t\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t\t\t\ttitle_attr: item.title_attr,\n\t\t\t\t\t\t\t\ttarget: item.target,\n\t\t\t\t\t\t\t\tcss_classes: item.css_classes,\n\t\t\t\t\t\t\t\t...(input.locale !== undefined ? { locale: input.locale } : {}),\n\t\t\t\t\t\t\t\ttranslation_group: item.translation_group ?? item.id,\n\t\t\t\t\t\t\t})),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.execute();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tconst created = await this.findById(id);\n\t\tif (!created) throw new Error(\"Failed to create menu\");\n\t\treturn created;\n\t}\n\n\tasync update(id: string, input: UpdateMenuInput): Promise<Menu | null> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return null;\n\n\t\tconst values: Record<string, unknown> = {};\n\t\tif (input.label !== undefined) values.label = input.label;\n\n\t\tif (Object.keys(values).length > 0) {\n\t\t\tawait this.db.updateTable(\"_emdash_menus\").set(values).where(\"id\", \"=\", id).execute();\n\t\t}\n\n\t\treturn (await this.findById(id))!;\n\t}\n\n\t/**\n\t * Delete a menu. Items are deleted explicitly to avoid relying on the\n\t * `ON DELETE CASCADE` FK declared in migration 005, which migration 036\n\t * removed: that FK is what made #1021 destructive on D1 (the cascade\n\t * fired when the i18n migration dropped `_emdash_menus`), so dropping\n\t * the FK was the fix. The explicit delete keeps the runtime working\n\t * the same way before and after the migration.\n\t */\n\tasync delete(id: string): Promise<boolean> {\n\t\tconst existing = await this.findById(id);\n\t\tif (!existing) return false;\n\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\tawait trx.deleteFrom(\"_emdash_menu_items\").where(\"menu_id\", \"=\", id).execute();\n\t\t\tawait trx.deleteFrom(\"_emdash_menus\").where(\"id\", \"=\", id).execute();\n\t\t});\n\t\treturn true;\n\t}\n\n\t/**\n\t * List every translation of a menu (by id or translation_group).\n\t *\n\t * Returns `null` when neither the id nor the group resolves to a menu,\n\t * mapped to NOT_FOUND by the handler.\n\t */\n\tasync listTranslations(\n\t\tidOrGroup: string,\n\t): Promise<{ translationGroup: string | null; translations: MenuTranslation[] } | null> {\n\t\tconst anchor = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where((eb) => eb.or([eb(\"id\", \"=\", idOrGroup), eb(\"translation_group\", \"=\", idOrGroup)]))\n\t\t\t.executeTakeFirst();\n\t\tif (!anchor) return null;\n\n\t\tconst group = anchor.translation_group ?? anchor.id;\n\t\tconst rows = await this.db\n\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t.selectAll()\n\t\t\t.where(\"translation_group\", \"=\", group)\n\t\t\t.orderBy(\"locale\", \"asc\")\n\t\t\t.execute();\n\n\t\treturn {\n\t\t\ttranslationGroup: group,\n\t\t\ttranslations: rows.map((row) => ({\n\t\t\t\tid: row.id,\n\t\t\t\tname: row.name,\n\t\t\t\tlocale: row.locale,\n\t\t\t\tlabel: row.label,\n\t\t\t\tupdatedAt: row.updated_at,\n\t\t\t})),\n\t\t};\n\t}\n\n\t// --- Items -------------------------------------------------------------\n\n\t/**\n\t * Insert a menu item. `locale` is propagated from the parent menu so\n\t * `_emdash_menu_items.locale` mirrors the menu's locale (queries can scope\n\t * by locale without a join).\n\t *\n\t * When `sortOrder` is omitted, the next position within the same parent\n\t * scope is used (max + 1). The fresh `translation_group` defaults to the\n\t * item's own id, matching the migration 036 backfill.\n\t */\n\tasync createItem(menuId: string, locale: string, input: CreateMenuItemInput): Promise<MenuItem> {\n\t\tlet sortOrder = input.sortOrder ?? 0;\n\t\tif (input.sortOrder === undefined) {\n\t\t\tconst maxOrder = await this.db\n\t\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t\t.select(({ fn }) => fn.max(\"sort_order\").as(\"max\"))\n\t\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t\t.where(\"parent_id\", \"is\", input.parentId ?? null)\n\t\t\t\t.executeTakeFirst();\n\t\t\t// eslint-disable-next-line typescript/no-unsafe-type-assertion -- Kysely fn.max returns unknown; always a number for sort_order column\n\t\t\tsortOrder = ((maxOrder?.max as number) ?? -1) + 1;\n\t\t}\n\n\t\tconst id = ulid();\n\t\tawait this.db\n\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t.values({\n\t\t\t\tid,\n\t\t\t\tmenu_id: menuId,\n\t\t\t\tparent_id: input.parentId ?? null,\n\t\t\t\tsort_order: sortOrder,\n\t\t\t\ttype: input.type,\n\t\t\t\treference_collection: input.referenceCollection ?? null,\n\t\t\t\treference_id: input.referenceId ?? null,\n\t\t\t\tcustom_url: input.customUrl ?? null,\n\t\t\t\tlabel: input.label,\n\t\t\t\ttitle_attr: input.titleAttr ?? null,\n\t\t\t\ttarget: input.target ?? null,\n\t\t\t\tcss_classes: input.cssClasses ?? null,\n\t\t\t\tlocale,\n\t\t\t\ttranslation_group: id,\n\t\t\t})\n\t\t\t.execute();\n\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", id)\n\t\t\t.executeTakeFirstOrThrow();\n\t\treturn rowToMenuItem(row);\n\t}\n\n\t/**\n\t * Update a menu item. Caller must ensure the item belongs to the menu —\n\t * the `where(\"menu_id\", \"=\", menuId)` guard prevents cross-menu writes.\n\t * Returns `null` if the item is not found within the menu.\n\t */\n\tasync updateItem(\n\t\tmenuId: string,\n\t\titemId: string,\n\t\tinput: UpdateMenuItemInput,\n\t): Promise<MenuItem | null> {\n\t\tconst existing = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.select(\"id\")\n\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t.executeTakeFirst();\n\t\tif (!existing) return null;\n\n\t\tconst values: Record<string, unknown> = {};\n\t\tif (input.label !== undefined) values.label = input.label;\n\t\tif (input.customUrl !== undefined) values.custom_url = input.customUrl;\n\t\tif (input.target !== undefined) values.target = input.target;\n\t\tif (input.titleAttr !== undefined) values.title_attr = input.titleAttr;\n\t\tif (input.cssClasses !== undefined) values.css_classes = input.cssClasses;\n\t\tif (input.parentId !== undefined) values.parent_id = input.parentId;\n\t\tif (input.sortOrder !== undefined) values.sort_order = input.sortOrder;\n\n\t\tif (Object.keys(values).length > 0) {\n\t\t\tawait this.db\n\t\t\t\t.updateTable(\"_emdash_menu_items\")\n\t\t\t\t.set(values)\n\t\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t\t.execute();\n\t\t}\n\n\t\tconst row = await this.db\n\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t.selectAll()\n\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t.executeTakeFirstOrThrow();\n\t\treturn rowToMenuItem(row);\n\t}\n\n\t/** Delete an item scoped to its menu. Returns false if nothing was deleted. */\n\tasync deleteItem(menuId: string, itemId: string): Promise<boolean> {\n\t\tconst result = await this.db\n\t\t\t.deleteFrom(\"_emdash_menu_items\")\n\t\t\t.where(\"id\", \"=\", itemId)\n\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t.execute();\n\t\treturn result[0]?.numDeletedRows !== 0n;\n\t}\n\n\t/**\n\t * Atomic replace: delete every existing item and re-insert in order.\n\t * `parentIndex` (validated by the caller) is resolved against the live\n\t * insert order so children always reference real parent ids.\n\t *\n\t * Returns the count of inserted items (matches the existing handler API).\n\t */\n\tasync setItems(\n\t\tmenuId: string,\n\t\tlocale: string,\n\t\titems: SetMenuItem[],\n\t): Promise<{ itemCount: number }> {\n\t\tawait withTransaction(this.db, async (trx) => {\n\t\t\t// Re-check menu existence INSIDE the transaction. The handler\n\t\t\t// resolved by (name, locale) before this call; if a concurrent\n\t\t\t// menu_delete landed in between, inserting new items would\n\t\t\t// silently orphan them. The FK from migration 005 was removed\n\t\t\t// by migration 036 (#1021) and not restored, so nothing at the\n\t\t\t// schema level stops the orphans. Throw a MenuGoneError so the\n\t\t\t// rollback fires and the handler returns NOT_FOUND with the\n\t\t\t// original menu name in the message.\n\t\t\tconst stillThere = await trx\n\t\t\t\t.selectFrom(\"_emdash_menus\")\n\t\t\t\t.select(\"id\")\n\t\t\t\t.where(\"id\", \"=\", menuId)\n\t\t\t\t.executeTakeFirst();\n\t\t\tif (!stillThere) throw new MenuGoneError(menuId);\n\n\t\t\tawait trx.deleteFrom(\"_emdash_menu_items\").where(\"menu_id\", \"=\", menuId).execute();\n\n\t\t\tconst insertedIds: string[] = [];\n\t\t\tfor (let i = 0; i < items.length; i++) {\n\t\t\t\tconst item = items[i];\n\t\t\t\tif (!item) continue;\n\t\t\t\tconst id = ulid();\n\t\t\t\tconst parentId =\n\t\t\t\t\titem.parentIndex !== undefined ? (insertedIds[item.parentIndex] ?? null) : null;\n\t\t\t\tawait trx\n\t\t\t\t\t.insertInto(\"_emdash_menu_items\")\n\t\t\t\t\t.values({\n\t\t\t\t\t\tid,\n\t\t\t\t\t\tmenu_id: menuId,\n\t\t\t\t\t\tparent_id: parentId,\n\t\t\t\t\t\tsort_order: i,\n\t\t\t\t\t\ttype: item.type,\n\t\t\t\t\t\treference_collection: item.referenceCollection ?? null,\n\t\t\t\t\t\treference_id: item.referenceId ?? null,\n\t\t\t\t\t\tcustom_url: item.customUrl ?? null,\n\t\t\t\t\t\tlabel: item.label,\n\t\t\t\t\t\ttitle_attr: item.titleAttr ?? null,\n\t\t\t\t\t\ttarget: item.target ?? null,\n\t\t\t\t\t\tcss_classes: item.cssClasses ?? null,\n\t\t\t\t\t\tlocale,\n\t\t\t\t\t})\n\t\t\t\t\t.execute();\n\t\t\t\tinsertedIds.push(id);\n\t\t\t}\n\n\t\t\tawait trx\n\t\t\t\t.updateTable(\"_emdash_menus\")\n\t\t\t\t.set({ updated_at: new Date().toISOString() })\n\t\t\t\t.where(\"id\", \"=\", menuId)\n\t\t\t\t.execute();\n\t\t});\n\n\t\treturn { itemCount: items.length };\n\t}\n\n\t/**\n\t * Batch reorder items. Each entry is applied scoped to the menu so a\n\t * malicious payload cannot move foreign items into this menu's siblings.\n\t */\n\tasync reorderItems(menuId: string, items: ReorderItem[]): Promise<MenuItem[]> {\n\t\treturn withTransaction(this.db, async (trx) => {\n\t\t\tfor (const item of items) {\n\t\t\t\tawait trx\n\t\t\t\t\t.updateTable(\"_emdash_menu_items\")\n\t\t\t\t\t.set({ parent_id: item.parentId, sort_order: item.sortOrder })\n\t\t\t\t\t.where(\"id\", \"=\", item.id)\n\t\t\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t\t\t.execute();\n\t\t\t}\n\n\t\t\tconst rows = await trx\n\t\t\t\t.selectFrom(\"_emdash_menu_items\")\n\t\t\t\t.selectAll()\n\t\t\t\t.where(\"menu_id\", \"=\", menuId)\n\t\t\t\t.orderBy(\"sort_order\", \"asc\")\n\t\t\t\t.execute();\n\t\t\treturn rows.map(rowToMenuItem);\n\t\t});\n\t}\n}\n","/**\n * Menu CRUD handlers.\n *\n * Business logic for menu and menu-item endpoints. Routes are thin wrappers\n * that parse input, check auth, and call these.\n *\n * i18n: Menus are per-locale. `(name, locale)` is unique, so the same `name`\n * (e.g. \"primary\") can exist in several locales within one translation_group.\n * Menu items carry a `locale` + `translation_group` as well, and their\n * `reference_id` points at the referenced content's translation_group (not a\n * specific row id), so a single menu item target survives content translations.\n */\n\nimport type { Kysely } from \"kysely\";\n\nimport {\n\tMenuGoneError,\n\tMenuRepository,\n\ttype CreateMenuItemInput as CreateMenuItemRepoInput,\n\ttype Menu,\n\ttype MenuItem,\n\ttype MenuListItem,\n\ttype MenuWithItems,\n\ttype SetMenuItem,\n\ttype UpdateMenuItemInput as UpdateMenuItemRepoInput,\n} from \"../../database/repositories/menu.js\";\nimport type { Database } from \"../../database/types.js\";\nimport { getI18nConfig } from \"../../i18n/config.js\";\nimport type { ApiResult } from \"../types.js\";\n\n// Re-export entity types so route files and tests can import them from the\n// handler module without having to know about the repository layout.\nexport type {\n\tMenu,\n\tMenuItem,\n\tMenuListItem,\n\tMenuTranslation,\n\tMenuWithItems,\n} from \"../../database/repositories/menu.js\";\n\nexport interface MenuTranslationsResponse {\n\ttranslationGroup: string | null;\n\ttranslations: Array<{\n\t\tid: string;\n\t\tname: string;\n\t\tlocale: string;\n\t\tlabel: string;\n\t\tupdatedAt: string;\n\t}>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Error returned when a menu lookup by `name` matches multiple locale\n * variants and the caller did not pass `locale` to disambiguate. Maps to\n * HTTP 400 via `mapErrorStatus`. The available locales are surfaced in the\n * message so MCP/REST callers can recover by re-issuing with `locale`.\n */\nfunction ambiguousMenuLocaleError(\n\tname: string,\n\tlocales: readonly string[],\n): { success: false; error: { code: \"AMBIGUOUS_LOCALE\"; message: string } } {\n\tconst sortedLocales = locales.toSorted();\n\treturn {\n\t\tsuccess: false,\n\t\terror: {\n\t\t\tcode: \"AMBIGUOUS_LOCALE\",\n\t\t\tmessage: `Menu '${name}' exists in multiple locales (${sortedLocales.join(\n\t\t\t\t\", \",\n\t\t\t)}); pass 'locale' to disambiguate.`,\n\t\t},\n\t};\n}\n\ntype ResolveMenuResult =\n\t| { success: true; menu: Menu }\n\t| { success: false; error: { code: \"NOT_FOUND\" | \"AMBIGUOUS_LOCALE\"; message: string } };\n\n/**\n * Resolve a menu by name + optional locale to a single Menu, surfacing the\n * canonical NOT_FOUND / AMBIGUOUS_LOCALE errors. Every item handler relies on\n * this to translate (name, locale) into an unambiguous menu row.\n */\nasync function resolveMenu(\n\trepo: MenuRepository,\n\tname: string,\n\toptions: { locale?: string },\n): Promise<ResolveMenuResult> {\n\tconst matches = await repo.findByName(name, options);\n\tif (matches.length === 0) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\tmessage: `Menu '${name}' not found${options.locale ? ` in locale '${options.locale}'` : \"\"}`,\n\t\t\t},\n\t\t};\n\t}\n\tif (matches.length > 1) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: ambiguousMenuLocaleError(\n\t\t\t\tname,\n\t\t\t\tmatches.map((m) => m.locale),\n\t\t\t).error,\n\t\t};\n\t}\n\treturn { success: true, menu: matches[0] };\n}\n\n// ---------------------------------------------------------------------------\n// Menu handlers\n// ---------------------------------------------------------------------------\n\n/**\n * List menus with item counts. Filter by `locale` when provided.\n */\nexport async function handleMenuList(\n\tdb: Kysely<Database>,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuListItem[]>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst items = await repo.findMany(options);\n\t\treturn { success: true, data: items };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_LIST_ERROR\", message: \"Failed to fetch menus\" },\n\t\t};\n\t}\n}\n\n/**\n * Create a new menu. When `translationOf` is supplied the new menu joins the\n * source menu's translation_group (and gets the source's items cloned by the\n * repository).\n */\nexport async function handleMenuCreate(\n\tdb: Kysely<Database>,\n\tinput: { name: string; label: string; locale?: string; translationOf?: string },\n): Promise<ApiResult<Menu>> {\n\ttry {\n\t\t// Translating from a source menu only makes sense when the caller\n\t\t// names the target locale: otherwise we'd silently clone into the\n\t\t// configured default, which is almost never what's intended (and\n\t\t// will collide if the source is already the default-locale menu).\n\t\t// Enforced here so REST/SDK callers get the same guard as MCP.\n\t\tif (input.translationOf && !input.locale) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\t\tmessage: \"`locale` is required when `translationOf` is provided\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst repo = new MenuRepository(db);\n\n\t\t// Existence check up front so the repo's \"Source not found\" throw\n\t\t// becomes a clean NOT_FOUND on the API.\n\t\tif (input.translationOf) {\n\t\t\tconst source = await repo.findById(input.translationOf);\n\t\t\tif (!source) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Source menu for translation not found\" },\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Duplicate guard: same (name, locale). Falls back to the configured\n\t\t// defaultLocale to match the column DEFAULT set by migration 036.\n\t\tconst effectiveLocale = input.locale ?? getI18nConfig()?.defaultLocale ?? \"en\";\n\t\tif (await repo.existsByNameAndLocale(input.name, effectiveLocale)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"CONFLICT\",\n\t\t\t\t\tmessage: `Menu \"${input.name}\" already exists${\n\t\t\t\t\t\tinput.locale ? ` in locale \"${input.locale}\"` : \"\"\n\t\t\t\t\t}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\tconst menu = await repo.create(input);\n\t\treturn { success: true, data: menu };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_CREATE_ERROR\", message: \"Failed to create menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Get a single menu by name. Honours an optional `locale` filter; when two\n * menus share a name across locales, the locale distinguishes them.\n *\n * Historical behaviour: when `locale` is omitted, returns the lowest-locale\n * match (deterministic). Mirrors the pre-repo handler.\n */\nexport async function handleMenuGet(\n\tdb: Kysely<Database>,\n\tname: string,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuWithItems>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst matches = await repo.findByName(name, options);\n\t\tif (matches.length === 0) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Menu '${name}' not found` },\n\t\t\t};\n\t\t}\n\t\tconst menu = matches[0];\n\t\tconst items = await repo.findItems(menu.id);\n\t\treturn { success: true, data: { ...menu, items } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_GET_ERROR\", message: \"Failed to fetch menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Get a menu by id. Useful when the caller already has the id (e.g. after\n * creating a translation and navigating to it).\n */\nexport async function handleMenuGetById(\n\tdb: Kysely<Database>,\n\tid: string,\n): Promise<ApiResult<MenuWithItems>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst menu = await repo.findWithItems(id);\n\t\tif (!menu) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Menu '${id}' not found` },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: menu };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_GET_ERROR\", message: \"Failed to fetch menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Update a menu's label. The name + locale are immutable.\n */\nexport async function handleMenuUpdate(\n\tdb: Kysely<Database>,\n\tname: string,\n\tinput: { label?: string; locale?: string },\n): Promise<ApiResult<Menu>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, name, { locale: input.locale });\n\t\tif (!resolved.success) return resolved;\n\t\tconst updated = await repo.update(resolved.menu.id, { label: input.label });\n\t\tif (!updated) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: `Menu '${name}' not found` },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: updated };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_UPDATE_ERROR\", message: \"Failed to update menu\" },\n\t\t};\n\t}\n}\n\n/**\n * Delete a menu (and its items, via the repository's explicit cleanup).\n */\nexport async function handleMenuDelete(\n\tdb: Kysely<Database>,\n\tname: string,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, name, options);\n\t\tif (!resolved.success) return resolved;\n\t\tawait repo.delete(resolved.menu.id);\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_DELETE_ERROR\", message: \"Failed to delete menu\" },\n\t\t};\n\t}\n}\n\n/**\n * List every translation of a menu (by id or translation_group).\n */\nexport async function handleMenuTranslations(\n\tdb: Kysely<Database>,\n\tidOrGroup: string,\n): Promise<ApiResult<MenuTranslationsResponse>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst result = await repo.listTranslations(idOrGroup);\n\t\tif (!result) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Menu not found\" },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: result };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_TRANSLATIONS_ERROR\", message: \"Failed to list menu translations\" },\n\t\t};\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Menu item handlers\n// ---------------------------------------------------------------------------\n\nexport type CreateMenuItemInput = CreateMenuItemRepoInput;\nexport type UpdateMenuItemInput = UpdateMenuItemRepoInput;\nexport type MenuSetItemsInput = SetMenuItem;\n\n/**\n * Add an item to a menu. The item inherits the menu's locale.\n */\nexport async function handleMenuItemCreate(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\tinput: CreateMenuItemInput,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuItem>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst item = await repo.createItem(resolved.menu.id, resolved.menu.locale, input);\n\t\treturn { success: true, data: item };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_ITEM_CREATE_ERROR\", message: \"Failed to create menu item\" },\n\t\t};\n\t}\n}\n\n/**\n * Update a menu item.\n */\nexport async function handleMenuItemUpdate(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titemId: string,\n\tinput: UpdateMenuItemInput,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuItem>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst updated = await repo.updateItem(resolved.menu.id, itemId, input);\n\t\tif (!updated) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Menu item not found\" },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: updated };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_ITEM_UPDATE_ERROR\", message: \"Failed to update menu item\" },\n\t\t};\n\t}\n}\n\n/**\n * Delete a menu item.\n */\nexport async function handleMenuItemDelete(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titemId: string,\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<{ deleted: true }>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst deleted = await repo.deleteItem(resolved.menu.id, itemId);\n\t\tif (!deleted) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: { code: \"NOT_FOUND\", message: \"Menu item not found\" },\n\t\t\t};\n\t\t}\n\t\treturn { success: true, data: { deleted: true } };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_ITEM_DELETE_ERROR\", message: \"Failed to delete menu item\" },\n\t\t};\n\t}\n}\n\nexport interface ReorderItem {\n\tid: string;\n\tparentId: string | null;\n\tsortOrder: number;\n}\n\n// ---------------------------------------------------------------------------\n// Atomic-replace menu items (used by the MCP `menu_set_items` tool and admin)\n// ---------------------------------------------------------------------------\n\n/**\n * Replace the entire set of items for a menu in one atomic transaction.\n *\n * Existing items are deleted and the new list is inserted in the order\n * provided. `parentIndex` references resolve to actual parent IDs as the\n * insert proceeds.\n */\nexport async function handleMenuSetItems(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titems: MenuSetItemsInput[],\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<{ name: string; itemCount: number }>> {\n\t// Validate parentIndex references — must be strictly earlier so the array\n\t// can be inserted in order with parents resolved first. Negative indices\n\t// are caught by Zod's `.nonnegative()` at the MCP boundary, but we guard\n\t// explicitly so REST routes / direct handler use get the same error.\n\tfor (let i = 0; i < items.length; i++) {\n\t\tconst item = items[i];\n\t\tif (item?.parentIndex !== undefined) {\n\t\t\tif (item.parentIndex < 0 || item.parentIndex >= i) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tcode: \"VALIDATION_ERROR\",\n\t\t\t\t\t\tmessage: `item[${i}].parentIndex (${item.parentIndex}) must reference an earlier item`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst { itemCount } = await repo.setItems(resolved.menu.id, resolved.menu.locale, items);\n\t\treturn { success: true, data: { name: menuName, itemCount } };\n\t} catch (error) {\n\t\t// `MenuGoneError` is thrown from inside the repository transaction\n\t\t// when the menu was deleted concurrently between `resolveMenu` and the\n\t\t// setItems write. Returning NOT_FOUND mirrors the original handler's\n\t\t// in-transaction `notFoundSentinel` branch and keeps the response\n\t\t// shape stable for REST/MCP callers.\n\t\tif (error instanceof MenuGoneError) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: {\n\t\t\t\t\tcode: \"NOT_FOUND\",\n\t\t\t\t\tmessage: `Menu '${menuName}' not found${\n\t\t\t\t\t\toptions.locale ? ` in locale '${options.locale}'` : \"\"\n\t\t\t\t\t}`,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tconsole.error(\"[emdash] handleMenuSetItems failed:\", error);\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_SET_ITEMS_ERROR\", message: \"Failed to set menu items\" },\n\t\t};\n\t}\n}\n\n/**\n * Batch reorder menu items.\n */\nexport async function handleMenuItemReorder(\n\tdb: Kysely<Database>,\n\tmenuName: string,\n\titems: ReorderItem[],\n\toptions: { locale?: string } = {},\n): Promise<ApiResult<MenuItem[]>> {\n\ttry {\n\t\tconst repo = new MenuRepository(db);\n\t\tconst resolved = await resolveMenu(repo, menuName, options);\n\t\tif (!resolved.success) return resolved;\n\n\t\tconst updated = await repo.reorderItems(resolved.menu.id, items);\n\t\treturn { success: true, data: updated };\n\t} catch {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: { code: \"MENU_REORDER_ERROR\", message: \"Failed to reorder menu items\" },\n\t\t};\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { t as validateIdentifier } from "./validate-VPnKoIzW.mjs";
|
|
2
|
-
import { t as CommentRepository } from "./comment-
|
|
2
|
+
import { t as CommentRepository } from "./comment-_yzlBYPx.mjs";
|
|
3
3
|
import { t as OptionsRepository } from "./options-BL4X94qY.mjs";
|
|
4
|
-
import { t as PluginContextFactory } from "./context-
|
|
4
|
+
import { t as PluginContextFactory } from "./context-sAnCaUIR.mjs";
|
|
5
5
|
import { n as requestCached } from "./request-cache-dzCt8TZB.mjs";
|
|
6
|
-
import { r as getDb } from "./loader-
|
|
7
|
-
import {
|
|
8
|
-
import { r as normalizeCapabilities } from "./types-
|
|
9
|
-
import { dt as sanitizeHref } from "./redirects-
|
|
10
|
-
import { t as extractRequestMeta } from "./request-meta-
|
|
11
|
-
import { r as setCronTasksEnabled } from "./cron-
|
|
6
|
+
import { r as getDb } from "./loader-Chm5h7Gr.mjs";
|
|
7
|
+
import { n as resolveLocaleChain, t as resolveLocale } from "./resolve-Cj98DuqN.mjs";
|
|
8
|
+
import { r as normalizeCapabilities } from "./types-1NNkmTIn.mjs";
|
|
9
|
+
import { dt as sanitizeHref } from "./redirects-COMLwsV5.mjs";
|
|
10
|
+
import { t as extractRequestMeta } from "./request-meta-C_Cjii-T.mjs";
|
|
11
|
+
import { r as setCronTasksEnabled } from "./cron-Bd3b3iuj.mjs";
|
|
12
12
|
import { sql } from "kysely";
|
|
13
13
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
14
14
|
import { ulid } from "ulidx";
|
|
@@ -2472,7 +2472,7 @@ function createPluginManager(options) {
|
|
|
2472
2472
|
*/
|
|
2473
2473
|
var SandboxNotAvailableError = class extends Error {
|
|
2474
2474
|
constructor() {
|
|
2475
|
-
super("Plugin sandboxing is not available
|
|
2475
|
+
super("Plugin sandboxing is not available. Configure a sandbox runner: use @emdash-cms/cloudflare/sandbox on Cloudflare, or @emdash-cms/sandbox-workerd/sandbox on Node.js (requires workerd). Without sandboxing, use trusted plugins (from config) instead.");
|
|
2476
2476
|
this.name = "SandboxNotAvailableError";
|
|
2477
2477
|
}
|
|
2478
2478
|
};
|
|
@@ -2493,6 +2493,12 @@ var NoopSandboxRunner = class {
|
|
|
2493
2493
|
return false;
|
|
2494
2494
|
}
|
|
2495
2495
|
/**
|
|
2496
|
+
* Always returns false - no sandbox runtime to be healthy.
|
|
2497
|
+
*/
|
|
2498
|
+
isHealthy() {
|
|
2499
|
+
return false;
|
|
2500
|
+
}
|
|
2501
|
+
/**
|
|
2496
2502
|
* Always throws - can't load sandboxed plugins without isolation.
|
|
2497
2503
|
*/
|
|
2498
2504
|
async load(_manifest, _code) {
|
|
@@ -2515,6 +2521,19 @@ function createNoopSandboxRunner(_options) {
|
|
|
2515
2521
|
return new NoopSandboxRunner();
|
|
2516
2522
|
}
|
|
2517
2523
|
|
|
2524
|
+
//#endregion
|
|
2525
|
+
//#region src/plugins/sandbox/types.ts
|
|
2526
|
+
/**
|
|
2527
|
+
* Error thrown when the sandbox runtime is unavailable.
|
|
2528
|
+
* This happens when the sidecar process has crashed or hasn't started.
|
|
2529
|
+
*/
|
|
2530
|
+
var SandboxUnavailableError = class extends Error {
|
|
2531
|
+
constructor(pluginId, reason) {
|
|
2532
|
+
super(`Plugin sandbox unavailable for ${pluginId}: ${reason}`);
|
|
2533
|
+
this.name = "SandboxUnavailableError";
|
|
2534
|
+
}
|
|
2535
|
+
};
|
|
2536
|
+
|
|
2518
2537
|
//#endregion
|
|
2519
2538
|
//#region src/comments/query.ts
|
|
2520
2539
|
/**
|
|
@@ -2784,5 +2803,5 @@ async function resolveTaxonomyUrl(referenceGroup, db, locale) {
|
|
|
2784
2803
|
}
|
|
2785
2804
|
|
|
2786
2805
|
//#endregion
|
|
2787
|
-
export {
|
|
2788
|
-
//# sourceMappingURL=menus-
|
|
2806
|
+
export { file as C, reference as S, definePlugin as _, SandboxUnavailableError as a, prosemirrorToPortableText as b, createNoopSandboxRunner as c, PluginRouteError as d, PluginRouteRegistry as f, resolveExclusiveHooks as g, createHookPipeline as h, getComments as i, PluginManager as l, HookPipeline as m, getMenus as n, NoopSandboxRunner as o, EmailPipeline as p, getCommentCount as r, SandboxNotAvailableError as s, getMenu as t, createPluginManager as u, after as v, image as w, portableText as x, portableTextToProsemirror as y };
|
|
2807
|
+
//# sourceMappingURL=menus-C75SSmRy.mjs.map
|