emdash 0.30.0 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/route-utils.mjs +13 -13
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/api/schemas/index.mjs +3 -3
- package/dist/{api-b8WIiGU4.mjs → api-BkqFzIu4.mjs} +23 -23
- package/dist/api-BkqFzIu4.mjs.map +1 -0
- package/dist/{apply-CmIJK9j8.mjs → apply-DuXsqll7.mjs} +26 -25
- package/dist/apply-DuXsqll7.mjs.map +1 -0
- package/dist/astro/index.d.mts +2 -2
- package/dist/astro/index.mjs +1 -1
- package/dist/astro/middleware/auth.d.mts +2 -2
- package/dist/astro/middleware/auth.mjs +2 -2
- package/dist/astro/middleware/redirect.mjs +5 -5
- package/dist/astro/middleware/request-context.mjs +1 -1
- package/dist/astro/middleware.d.mts +2 -2
- package/dist/astro/middleware.mjs +146 -70
- package/dist/astro/middleware.mjs.map +1 -1
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +6 -6
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +6 -6
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +2 -2
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +3 -3
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +3 -3
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +7 -7
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +7 -7
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +7 -7
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +14 -14
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +14 -14
- package/dist/astro/routes/api/admin/bylines/index.d.mts.map +1 -1
- package/dist/astro/routes/api/admin/bylines/index.mjs +18 -17
- 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 +9 -9
- package/dist/astro/routes/api/admin/comments/counts.mjs +5 -5
- package/dist/astro/routes/api/admin/comments/index.mjs +9 -9
- 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/media-usage/repair.mjs +10 -10
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/mcp.mjs +4 -4
- package/dist/astro/routes/api/admin/plugins/_id_/settings.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/index.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +3 -3
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/registry/_id_/uninstall.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/registry/_id_/update.mjs +35 -35
- package/dist/astro/routes/api/admin/plugins/registry/artifact.mjs +34 -34
- package/dist/astro/routes/api/admin/plugins/registry/install.mjs +35 -35
- package/dist/astro/routes/api/admin/plugins/updates.mjs +34 -34
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +34 -34
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +3 -3
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +34 -34
- 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 +6 -6
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +2 -2
- package/dist/astro/routes/api/admin/users/index.mjs +6 -6
- package/dist/astro/routes/api/auth/dev-bypass.mjs +4 -4
- package/dist/astro/routes/api/auth/invite/accept.mjs +2 -2
- package/dist/astro/routes/api/auth/invite/complete.mjs +6 -6
- package/dist/astro/routes/api/auth/invite/index.mjs +6 -6
- package/dist/astro/routes/api/auth/invite/register-options.mjs +6 -6
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +7 -7
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +7 -7
- package/dist/astro/routes/api/auth/mode.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/index.mjs +2 -2
- package/dist/astro/routes/api/auth/passkey/options.mjs +7 -7
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +6 -6
- package/dist/astro/routes/api/auth/passkey/verify.mjs +6 -6
- package/dist/astro/routes/api/auth/signup/complete.mjs +6 -6
- package/dist/astro/routes/api/auth/signup/request.mjs +7 -7
- package/dist/astro/routes/api/auth/signup/verify.mjs +2 -2
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +10 -10
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +10 -10
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/children.mjs +14 -14
- package/dist/astro/routes/api/content/_collection_/_id_/references/_relation_/parents.mjs +14 -14
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +13 -13
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/authors.mjs +3 -3
- package/dist/astro/routes/api/content/_collection_/index.mjs +7 -7
- package/dist/astro/routes/api/content/_collection_/trash.mjs +7 -7
- package/dist/astro/routes/api/dashboard.mjs +7 -7
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/import/probe.mjs +12 -12
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +3 -3
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +2 -2
- package/dist/astro/routes/api/import/wordpress/execute.mjs +11 -11
- package/dist/astro/routes/api/import/wordpress/media.d.mts +2 -2
- package/dist/astro/routes/api/import/wordpress/media.mjs +7 -7
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +2 -2
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +9 -9
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +12 -12
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +2 -2
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +19 -19
- package/dist/astro/routes/api/manifest.mjs +3 -3
- package/dist/astro/routes/api/mcp.mjs +39 -39
- package/dist/astro/routes/api/media/_id_/confirm.mjs +7 -7
- package/dist/astro/routes/api/media/_id_/usage.mjs +11 -11
- package/dist/astro/routes/api/media/_id_.mjs +10 -10
- package/dist/astro/routes/api/media/file/_...key_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +3 -3
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +3 -3
- package/dist/astro/routes/api/media/providers/index.mjs +3 -3
- package/dist/astro/routes/api/media/upload-url.mjs +7 -7
- package/dist/astro/routes/api/media.mjs +10 -10
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/items.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_/translations.mjs +8 -8
- package/dist/astro/routes/api/menus/_name_.mjs +8 -8
- package/dist/astro/routes/api/menus/index.mjs +8 -8
- package/dist/astro/routes/api/oauth/authorize.d.mts.map +1 -1
- package/dist/astro/routes/api/oauth/authorize.mjs +23 -9
- package/dist/astro/routes/api/oauth/authorize.mjs.map +1 -1
- package/dist/astro/routes/api/oauth/device/authorize.mjs +3 -3
- package/dist/astro/routes/api/oauth/device/code.mjs +4 -4
- package/dist/astro/routes/api/oauth/device/token.mjs +4 -4
- package/dist/astro/routes/api/oauth/register.mjs +2 -2
- package/dist/astro/routes/api/oauth/token/refresh.mjs +3 -3
- package/dist/astro/routes/api/oauth/token/revoke.mjs +3 -3
- package/dist/astro/routes/api/oauth/token.mjs +2 -2
- package/dist/astro/routes/api/openapi.json.mjs +4 -4
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
- package/dist/astro/routes/api/redirects/404s/index.mjs +10 -10
- package/dist/astro/routes/api/redirects/404s/summary.mjs +10 -10
- package/dist/astro/routes/api/redirects/_id_.mjs +11 -11
- package/dist/astro/routes/api/redirects/index.mjs +11 -11
- package/dist/astro/routes/api/relations/_id_/index.mjs +14 -14
- package/dist/astro/routes/api/relations/_id_/translations.mjs +10 -10
- package/dist/astro/routes/api/relations/index.mjs +14 -14
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +3 -3
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +3 -3
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +34 -34
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +34 -34
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +34 -34
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +34 -34
- package/dist/astro/routes/api/schema/collections/index.mjs +34 -34
- package/dist/astro/routes/api/schema/index.mjs +8 -8
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +34 -34
- package/dist/astro/routes/api/schema/orphans/index.mjs +34 -34
- package/dist/astro/routes/api/search/enable.mjs +11 -11
- package/dist/astro/routes/api/search/index.mjs +10 -10
- package/dist/astro/routes/api/search/rebuild.mjs +11 -11
- package/dist/astro/routes/api/search/stats.mjs +7 -7
- package/dist/astro/routes/api/search/suggest.mjs +10 -10
- package/dist/astro/routes/api/sections/_slug_.mjs +10 -10
- package/dist/astro/routes/api/sections/index.mjs +10 -10
- package/dist/astro/routes/api/settings/backups/archives/_name_.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/archives/index.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/export.mjs +4 -4
- package/dist/astro/routes/api/settings/backups/index.mjs +5 -5
- package/dist/astro/routes/api/settings/email.mjs +4 -4
- package/dist/astro/routes/api/settings.mjs +12 -12
- package/dist/astro/routes/api/setup/admin-verify.mjs +6 -6
- package/dist/astro/routes/api/setup/admin.mjs +6 -6
- package/dist/astro/routes/api/setup/dev-bypass.mjs +18 -18
- 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 +3 -3
- package/dist/astro/routes/api/snapshot.mjs +4 -4
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +13 -13
- package/dist/astro/routes/api/taxonomies/index.mjs +13 -13
- package/dist/astro/routes/api/themes/preview.mjs +4 -4
- package/dist/astro/routes/api/typegen.mjs +5 -5
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +7 -7
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +10 -10
- package/dist/astro/routes/api/widget-areas/_name_.mjs +6 -6
- package/dist/astro/routes/api/widget-areas/index.mjs +10 -10
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +5 -5
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +7 -7
- package/dist/astro/routes/sitemap.xml.mjs +5 -5
- package/dist/astro/types.d.mts +2 -2
- package/dist/{authorize-WxsiePzy.mjs → authorize-6WPZa1xZ.mjs} +2 -2
- package/dist/{authorize-WxsiePzy.mjs.map → authorize-6WPZa1xZ.mjs.map} +1 -1
- package/dist/{backup-S8kFWtwD.mjs → backup-DoW-H0r4.mjs} +2 -2
- package/dist/{backup-S8kFWtwD.mjs.map → backup-DoW-H0r4.mjs.map} +1 -1
- package/dist/{byline-XEjchwzZ.mjs → byline-BTOxUlFF.mjs} +6 -6
- package/dist/{byline-XEjchwzZ.mjs.map → byline-BTOxUlFF.mjs.map} +1 -1
- package/dist/{bylines-czseViYo.mjs → bylines-Bc-3xtpz.mjs} +6 -6
- package/dist/{bylines-czseViYo.mjs.map → bylines-Bc-3xtpz.mjs.map} +1 -1
- package/dist/{bylines-BJbT4gKS.mjs → bylines-oVN0iPwX.mjs} +12 -8
- package/dist/bylines-oVN0iPwX.mjs.map +1 -0
- package/dist/{cache-CGCd6AVM.mjs → cache-DDwy3JDW.mjs} +2 -2
- package/dist/{cache-CGCd6AVM.mjs.map → cache-DDwy3JDW.mjs.map} +1 -1
- package/dist/{chunks-BxXyunY-.mjs → chunks-Bq-5DPrD.mjs} +2 -2
- package/dist/{chunks-BxXyunY-.mjs.map → chunks-Bq-5DPrD.mjs.map} +1 -1
- package/dist/cli/index.mjs +18 -18
- package/dist/{comment-DPT0WKyd.mjs → comment-B9cUud8H.mjs} +2 -2
- package/dist/{comment-DPT0WKyd.mjs.map → comment-B9cUud8H.mjs.map} +1 -1
- package/dist/{comment-reaction-C65MldIB.mjs → comment-reaction-VUXO981F.mjs} +2 -2
- package/dist/{comment-reaction-C65MldIB.mjs.map → comment-reaction-VUXO981F.mjs.map} +1 -1
- package/dist/{comments-Bz6sCbgD.mjs → comments-PXj1E9Si.mjs} +3 -3
- package/dist/{comments-Bz6sCbgD.mjs.map → comments-PXj1E9Si.mjs.map} +1 -1
- package/dist/{config-CVssduLe.mjs → config-B6b_BobR.mjs} +6 -2
- package/dist/config-B6b_BobR.mjs.map +1 -0
- package/dist/{content-Ci04z2z-.mjs → content-BC43pICM.mjs} +4 -4
- package/dist/{content-Ci04z2z-.mjs.map → content-BC43pICM.mjs.map} +1 -1
- package/dist/{content-refresh-D4khvC0R.mjs → content-refresh-CPMSauD3.mjs} +4 -4
- package/dist/{content-refresh-D4khvC0R.mjs.map → content-refresh-CPMSauD3.mjs.map} +1 -1
- package/dist/{context-B6hc7zJL.mjs → context-DOurRIrb.mjs} +10 -10
- package/dist/{context-B6hc7zJL.mjs.map → context-DOurRIrb.mjs.map} +1 -1
- package/dist/{dashboard-C5NkXFbi.mjs → dashboard-CBm4zhc3.mjs} +4 -4
- package/dist/{dashboard-C5NkXFbi.mjs.map → dashboard-CBm4zhc3.mjs.map} +1 -1
- package/dist/database/pg-migration-lock.d.mts.map +1 -1
- package/dist/database/pg-migration-lock.mjs +1 -4
- package/dist/database/pg-migration-lock.mjs.map +1 -1
- package/dist/db/index.mjs +2 -2
- package/dist/{dialect-helpers-HxEQGl_1.mjs → dialect-helpers-BtOwo2us.mjs} +4 -4
- package/dist/dialect-helpers-BtOwo2us.mjs.map +1 -0
- package/dist/{error-CEGF6UZb.mjs → error-DJ98TRbQ.mjs} +2 -2
- package/dist/{error-CEGF6UZb.mjs.map → error-DJ98TRbQ.mjs.map} +1 -1
- package/dist/{field-defs-cache-DvmlgP-D.mjs → field-defs-cache-KfNJ_qLQ.mjs} +2 -2
- package/dist/{field-defs-cache-DvmlgP-D.mjs.map → field-defs-cache-KfNJ_qLQ.mjs.map} +1 -1
- package/dist/{fts-manager-DzqIBrrW.mjs → fts-manager-hyCU9OOp.mjs} +3 -3
- package/dist/{fts-manager-DzqIBrrW.mjs.map → fts-manager-hyCU9OOp.mjs.map} +1 -1
- package/dist/{hreflang-db2Tpb2o.mjs → hreflang-CbYeCzl9.mjs} +7 -7
- package/dist/{hreflang-db2Tpb2o.mjs.map → hreflang-CbYeCzl9.mjs.map} +1 -1
- package/dist/{import-Dmkm8S1W.mjs → import-oDYCgNYQ.mjs} +2 -2
- package/dist/{import-Dmkm8S1W.mjs.map → import-oDYCgNYQ.mjs.map} +1 -1
- package/dist/{index-wYnC6u4o.d.mts → index-BZJ_5FOX.d.mts} +50 -4
- package/dist/index-BZJ_5FOX.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +48 -48
- package/dist/{load-Cx27ki1l.mjs → load-Dg5gtWma.mjs} +2 -2
- package/dist/{load-Cx27ki1l.mjs.map → load-Dg5gtWma.mjs.map} +1 -1
- package/dist/{loader-Be3ouI5L.mjs → loader-D4rigvjR.mjs} +4 -4
- package/dist/{loader-Be3ouI5L.mjs.map → loader-D4rigvjR.mjs.map} +1 -1
- package/dist/media/local-runtime.d.mts +2 -2
- package/dist/media/local-runtime.mjs +5 -5
- package/dist/{media-kIV1IxFf.mjs → media-BJ6SRY3g.mjs} +8 -4
- package/dist/media-BJ6SRY3g.mjs.map +1 -0
- package/dist/{media-BjhhENaJ.mjs → media-its1WLYv.mjs} +2 -2
- package/dist/{media-BjhhENaJ.mjs.map → media-its1WLYv.mjs.map} +1 -1
- package/dist/{media-upload-D2wk3EIt.mjs → media-upload-DNu3QySc.mjs} +4 -4
- package/dist/{media-upload-D2wk3EIt.mjs.map → media-upload-DNu3QySc.mjs.map} +1 -1
- package/dist/{media-usage-CljdO1mc.mjs → media-usage-DPQ3K4xB.mjs} +6 -6
- package/dist/{media-usage-CljdO1mc.mjs.map → media-usage-DPQ3K4xB.mjs.map} +1 -1
- package/dist/{menus-CZyG6rvx.mjs → menus-BMGzWyWH.mjs} +15 -8
- package/dist/menus-BMGzWyWH.mjs.map +1 -0
- package/dist/{menus-BcyElFtI.mjs → menus-CPf_SW7u.mjs} +86 -8
- package/dist/menus-CPf_SW7u.mjs.map +1 -0
- package/dist/{parse-C_-6klII.mjs → parse-53zyxlpv.mjs} +2 -2
- package/dist/{parse-C_-6klII.mjs.map → parse-53zyxlpv.mjs.map} +1 -1
- package/dist/plugin-utils.d.mts +2 -2
- package/dist/plugins/adapt-sandbox-entry.d.mts +2 -2
- package/dist/{query-DR73ZNfm.mjs → query-Bz9bWZfm.mjs} +14 -14
- package/dist/{query-DR73ZNfm.mjs.map → query-Bz9bWZfm.mjs.map} +1 -1
- package/dist/{query-Di7DOmPV.mjs → query-DdFGHzQF.mjs} +3 -3
- package/dist/{query-Di7DOmPV.mjs.map → query-DdFGHzQF.mjs.map} +1 -1
- package/dist/{rate-limit-CMj83JNW.mjs → rate-limit-D3IEiUi2.mjs} +2 -2
- package/dist/{rate-limit-CMj83JNW.mjs.map → rate-limit-D3IEiUi2.mjs.map} +1 -1
- package/dist/{redirect-CgLPYflR.mjs → redirect-BoUac4NT.mjs} +3 -3
- package/dist/{redirect-CgLPYflR.mjs.map → redirect-BoUac4NT.mjs.map} +1 -1
- package/dist/{redirects-B7t9bKsL.mjs → redirects-ChbpqKiS.mjs} +3 -3
- package/dist/{redirects-B7t9bKsL.mjs.map → redirects-ChbpqKiS.mjs.map} +1 -1
- package/dist/{redirects-BBq3n2Rj.mjs → redirects-D457qwt0.mjs} +8 -8
- package/dist/redirects-D457qwt0.mjs.map +1 -0
- package/dist/{registry-FV15nLge.mjs → registry-y21kjhfG.mjs} +6 -6
- package/dist/{registry-FV15nLge.mjs.map → registry-y21kjhfG.mjs.map} +1 -1
- package/dist/{relation-9M9j_UWo.mjs → relation-Du0r04E0.mjs} +3 -3
- package/dist/{relation-9M9j_UWo.mjs.map → relation-Du0r04E0.mjs.map} +1 -1
- package/dist/{relations-5_avdrN_.mjs → relations-CZMpBqEd.mjs} +3 -3
- package/dist/{relations-5_avdrN_.mjs.map → relations-CZMpBqEd.mjs.map} +1 -1
- package/dist/{relations-BKvO39-9.mjs → relations-DtX1UMBH.mjs} +13 -7
- package/dist/relations-DtX1UMBH.mjs.map +1 -0
- package/dist/{relations-Bh8jlFsU.d.mts → relations-qKmSj9KM.d.mts} +27 -23
- package/dist/relations-qKmSj9KM.d.mts.map +1 -0
- package/dist/{resolve-Cd9dzclN.mjs → resolve-DFr4kq72.mjs} +2 -2
- package/dist/{resolve-Cd9dzclN.mjs.map → resolve-DFr4kq72.mjs.map} +1 -1
- package/dist/{runner-DfnZ5eUr.mjs → runner-BdeLEgad.mjs} +3 -3
- package/dist/{runner-DfnZ5eUr.mjs.map → runner-BdeLEgad.mjs.map} +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.mjs +3 -3
- package/dist/{schema-BXxlHeAf.mjs → schema-BH8P8vaC.mjs} +3 -3
- package/dist/{schema-BXxlHeAf.mjs.map → schema-BH8P8vaC.mjs.map} +1 -1
- package/dist/{scopes-Bl4IwHA-.mjs → scopes-DTIkIaGA.mjs} +2 -2
- package/dist/{scopes-Bl4IwHA-.mjs.map → scopes-DTIkIaGA.mjs.map} +1 -1
- package/dist/{search-Bff-7jFt.mjs → search-D-Yhpmvs.mjs} +8 -7
- package/dist/search-D-Yhpmvs.mjs.map +1 -0
- package/dist/{secrets-CSwQIl4q.mjs → secrets-CQ-69kF9.mjs} +23 -17
- package/dist/secrets-CQ-69kF9.mjs.map +1 -0
- package/dist/{sections-CwW4s1al.mjs → sections-CzVBAKjw.mjs} +3 -3
- package/dist/{sections-CwW4s1al.mjs.map → sections-CzVBAKjw.mjs.map} +1 -1
- package/dist/seed/index.mjs +16 -16
- package/dist/seo/index.mjs +12 -12
- package/dist/{seo-2cmFHZns.mjs → seo-kJzVAmmu.mjs} +2 -2
- package/dist/{seo-2cmFHZns.mjs.map → seo-kJzVAmmu.mjs.map} +1 -1
- package/dist/{service-DkGTWGIi.mjs → service-CQnc276a.mjs} +2 -2
- package/dist/{service-DkGTWGIi.mjs.map → service-CQnc276a.mjs.map} +1 -1
- package/dist/{settings-CpA4lQFt.mjs → settings-C2PaBS49.mjs} +3 -3
- package/dist/{settings-CpA4lQFt.mjs.map → settings-C2PaBS49.mjs.map} +1 -1
- package/dist/{settings-C4s8hFQm.mjs → settings-Dtc0DU31.mjs} +3 -3
- package/dist/{settings-C4s8hFQm.mjs.map → settings-Dtc0DU31.mjs.map} +1 -1
- package/dist/{taxonomies-Ce49uIzY.mjs → taxonomies-BN6M9Nrv.mjs} +26 -17
- package/dist/taxonomies-BN6M9Nrv.mjs.map +1 -0
- package/dist/{taxonomies-DjSKBZpq.mjs → taxonomies-r7pqLBCn.mjs} +53 -24
- package/dist/taxonomies-r7pqLBCn.mjs.map +1 -0
- package/dist/{taxonomy-DfVooU4W.mjs → taxonomy-0mCI25HN.mjs} +3 -3
- package/dist/{taxonomy-DfVooU4W.mjs.map → taxonomy-0mCI25HN.mjs.map} +1 -1
- package/dist/{types-D1iJ3DpO.mjs → types-CrRUFdej.mjs} +2 -2
- package/dist/{types-D1iJ3DpO.mjs.map → types-CrRUFdej.mjs.map} +1 -1
- package/dist/{user-Bh-L1qo6.mjs → user-aTXqmXBz.mjs} +3 -3
- package/dist/{user-Bh-L1qo6.mjs.map → user-aTXqmXBz.mjs.map} +1 -1
- package/dist/{validate-V9nCwq_-.mjs → validate-CDT1jl6_.mjs} +11 -6
- package/dist/validate-CDT1jl6_.mjs.map +1 -0
- package/dist/validate-DULfgpJP.d.mts.map +1 -1
- package/dist/{validation-BsVUJfsP.mjs → validation-DlD0E35W.mjs} +8 -8
- package/dist/{validation-BsVUJfsP.mjs.map → validation-DlD0E35W.mjs.map} +1 -1
- package/dist/version-BRMngh9I.mjs +7 -0
- package/dist/{version-907opKac.mjs.map → version-BRMngh9I.mjs.map} +1 -1
- package/dist/{widgets-DGv1Z04V.mjs → widgets-5fipNkMT.mjs} +2 -2
- package/dist/{widgets-DGv1Z04V.mjs.map → widgets-5fipNkMT.mjs.map} +1 -1
- package/dist/{wxr-taxonomies-Cs1N6O8z.mjs → wxr-taxonomies-DrihupaC.mjs} +4 -4
- package/dist/{wxr-taxonomies-Cs1N6O8z.mjs.map → wxr-taxonomies-DrihupaC.mjs.map} +1 -1
- package/dist/{zod-generator-B5prQ5M4.mjs → zod-generator-CwkHWz4f.mjs} +2 -2
- package/dist/{zod-generator-B5prQ5M4.mjs.map → zod-generator-CwkHWz4f.mjs.map} +1 -1
- package/package.json +7 -7
- package/src/api/handlers/bylines.ts +5 -4
- package/src/api/handlers/content.ts +25 -7
- package/src/api/handlers/menus.ts +11 -6
- package/src/api/handlers/relations.ts +7 -2
- package/src/api/handlers/taxonomies.ts +22 -14
- package/src/api/schemas/bylines.ts +4 -4
- package/src/api/schemas/common.ts +7 -6
- package/src/api/schemas/menus.ts +2 -1
- package/src/api/schemas/relations.ts +3 -1
- package/src/api/schemas/taxonomies.ts +4 -2
- package/src/astro/prefetch.ts +7 -2
- package/src/astro/routes/api/admin/bylines/index.ts +5 -8
- package/src/astro/routes/api/oauth/authorize.ts +42 -10
- package/src/components/Gallery.astro +141 -26
- package/src/components/widgets/Categories.astro +1 -1
- package/src/components/widgets/Tags.astro +1 -1
- package/src/config/secrets.ts +25 -19
- package/src/content/converters/gallery.ts +61 -0
- package/src/content/converters/portable-text-to-prosemirror.ts +19 -0
- package/src/content/converters/prosemirror-to-portable-text.ts +18 -0
- package/src/content/converters/types.ts +36 -0
- package/src/database/dialect-helpers.ts +3 -4
- package/src/database/pg-migration-lock.ts +1 -4
- package/src/emdash-runtime.ts +55 -17
- package/src/i18n/config.ts +8 -0
- package/src/i18n/repair-locale-casing.ts +51 -0
- package/src/search/query.ts +3 -2
- package/src/seed/apply.ts +9 -7
- package/src/seed/validate.ts +15 -4
- package/src/taxonomies/index.ts +64 -23
- package/dist/api-b8WIiGU4.mjs.map +0 -1
- package/dist/apply-CmIJK9j8.mjs.map +0 -1
- package/dist/bylines-BJbT4gKS.mjs.map +0 -1
- package/dist/config-CVssduLe.mjs.map +0 -1
- package/dist/dialect-helpers-HxEQGl_1.mjs.map +0 -1
- package/dist/index-wYnC6u4o.d.mts.map +0 -1
- package/dist/media-kIV1IxFf.mjs.map +0 -1
- package/dist/menus-BcyElFtI.mjs.map +0 -1
- package/dist/menus-CZyG6rvx.mjs.map +0 -1
- package/dist/redirects-BBq3n2Rj.mjs.map +0 -1
- package/dist/relations-BKvO39-9.mjs.map +0 -1
- package/dist/relations-Bh8jlFsU.d.mts.map +0 -1
- package/dist/search-Bff-7jFt.mjs.map +0 -1
- package/dist/secrets-CSwQIl4q.mjs.map +0 -1
- package/dist/taxonomies-Ce49uIzY.mjs.map +0 -1
- package/dist/taxonomies-DjSKBZpq.mjs.map +0 -1
- package/dist/validate-V9nCwq_-.mjs.map +0 -1
- package/dist/version-907opKac.mjs +0 -7
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Kysely } from "kysely";
|
|
2
|
+
import { sql } from "kysely";
|
|
3
|
+
|
|
4
|
+
import { listTablesLike } from "../database/dialect-helpers.js";
|
|
5
|
+
import type { Database } from "../database/types.js";
|
|
6
|
+
|
|
7
|
+
/** Rewrite stored locales to the exact casing used by the site configuration. */
|
|
8
|
+
export async function repairLocaleCasing(
|
|
9
|
+
db: Kysely<Database>,
|
|
10
|
+
configuredLocales: readonly string[],
|
|
11
|
+
): Promise<void> {
|
|
12
|
+
const tableNames = await listTablesLike(db, "ec_%");
|
|
13
|
+
|
|
14
|
+
for (const tableName of tableNames) {
|
|
15
|
+
const table = sql.ref(tableName);
|
|
16
|
+
const slug = tableName.slice("ec_".length);
|
|
17
|
+
for (const locale of configuredLocales) {
|
|
18
|
+
await sql`
|
|
19
|
+
UPDATE ${table} AS target
|
|
20
|
+
SET locale = ${locale}
|
|
21
|
+
WHERE lower(target.locale) = lower(${locale})
|
|
22
|
+
AND target.locale != ${locale}
|
|
23
|
+
AND NOT EXISTS (
|
|
24
|
+
SELECT 1
|
|
25
|
+
FROM ${table} AS existing
|
|
26
|
+
WHERE existing.slug = target.slug AND existing.locale = ${locale}
|
|
27
|
+
)
|
|
28
|
+
AND target.id = (
|
|
29
|
+
SELECT MIN(candidate.id)
|
|
30
|
+
FROM ${table} AS candidate
|
|
31
|
+
WHERE candidate.slug = target.slug
|
|
32
|
+
AND lower(candidate.locale) = lower(${locale})
|
|
33
|
+
AND candidate.locale != ${locale}
|
|
34
|
+
)
|
|
35
|
+
`.execute(db);
|
|
36
|
+
|
|
37
|
+
await sql`
|
|
38
|
+
UPDATE content_taxonomies AS pivot
|
|
39
|
+
SET locale = ${locale}
|
|
40
|
+
WHERE pivot.collection = ${slug}
|
|
41
|
+
AND lower(pivot.locale) = lower(${locale})
|
|
42
|
+
AND pivot.locale != ${locale}
|
|
43
|
+
AND EXISTS (
|
|
44
|
+
SELECT 1
|
|
45
|
+
FROM ${table} AS content
|
|
46
|
+
WHERE content.id = pivot.entry_id AND content.locale = ${locale}
|
|
47
|
+
)
|
|
48
|
+
`.execute(db);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
package/src/search/query.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { sql } from "kysely";
|
|
|
10
10
|
import { encodeCursor, decodeCursor, InvalidCursorError } from "../database/repositories/types.js";
|
|
11
11
|
import type { Database } from "../database/types.js";
|
|
12
12
|
import { validateIdentifier } from "../database/validate.js";
|
|
13
|
+
import { resolveConfiguredLocale } from "../i18n/config.js";
|
|
13
14
|
import { getDb } from "../loader.js";
|
|
14
15
|
import { FTSManager } from "./fts-manager.js";
|
|
15
16
|
import type {
|
|
@@ -250,7 +251,7 @@ async function searchSingleCollection(
|
|
|
250
251
|
const contentTable = ftsManager.getContentTableName(collection);
|
|
251
252
|
const limit = options.limit ?? 20;
|
|
252
253
|
const status = options.status ?? "published";
|
|
253
|
-
const locale = options.locale;
|
|
254
|
+
const locale = options.locale ? resolveConfiguredLocale(options.locale) : undefined;
|
|
254
255
|
|
|
255
256
|
// Check if FTS table exists
|
|
256
257
|
if (!(await ftsManager.ftsTableExists(collection))) {
|
|
@@ -397,7 +398,7 @@ export async function getSuggestions(
|
|
|
397
398
|
options: SuggestOptions = {},
|
|
398
399
|
): Promise<Suggestion[]> {
|
|
399
400
|
const limit = options.limit ?? 5;
|
|
400
|
-
const locale = options.locale;
|
|
401
|
+
const locale = options.locale ? resolveConfiguredLocale(options.locale) : undefined;
|
|
401
402
|
|
|
402
403
|
// Get searchable collections
|
|
403
404
|
let collections = options.collections;
|
package/src/seed/apply.ts
CHANGED
|
@@ -19,7 +19,7 @@ import { TaxonomyRepository } from "../database/repositories/taxonomy.js";
|
|
|
19
19
|
import { withTransaction } from "../database/transaction.js";
|
|
20
20
|
import type { Database } from "../database/types.js";
|
|
21
21
|
import type { MediaValue } from "../fields/types.js";
|
|
22
|
-
import { getI18nConfig } from "../i18n/config.js";
|
|
22
|
+
import { getI18nConfig, resolveConfiguredLocale } from "../i18n/config.js";
|
|
23
23
|
import { ssrfSafeFetch, validateExternalUrl } from "../import/ssrf.js";
|
|
24
24
|
import { markContentMediaUsageCollectionStaleSafely } from "../media/usage/content-refresh.js";
|
|
25
25
|
import { SchemaRegistry } from "../schema/registry.js";
|
|
@@ -263,7 +263,7 @@ export async function applySeed(
|
|
|
263
263
|
const termSeedIdMap = new Map<string, string>();
|
|
264
264
|
|
|
265
265
|
for (const taxonomy of seed.taxonomies) {
|
|
266
|
-
const defLocale = taxonomy.locale ?? defaultLocale;
|
|
266
|
+
const defLocale = resolveConfiguredLocale(taxonomy.locale ?? defaultLocale);
|
|
267
267
|
|
|
268
268
|
// (name, locale) is the UNIQUE key after migration 036.
|
|
269
269
|
const existingDef = await db
|
|
@@ -340,7 +340,7 @@ export async function applySeed(
|
|
|
340
340
|
);
|
|
341
341
|
} else {
|
|
342
342
|
for (const term of taxonomy.terms) {
|
|
343
|
-
const termLocale = term.locale ?? defLocale;
|
|
343
|
+
const termLocale = resolveConfiguredLocale(term.locale ?? defLocale);
|
|
344
344
|
const existing = await termRepo.findBySlug(taxonomy.name, term.slug, termLocale);
|
|
345
345
|
if (existing) {
|
|
346
346
|
if (onConflict === "error") {
|
|
@@ -464,7 +464,7 @@ export async function applySeed(
|
|
|
464
464
|
// Resolve the entry's locale up front so a non-`en` single-locale
|
|
465
465
|
// export (which omits `locale`) is filed under the project default
|
|
466
466
|
// rather than `en` (#1421).
|
|
467
|
-
const entryLocale = entry.locale ?? defaultLocale;
|
|
467
|
+
const entryLocale = resolveConfiguredLocale(entry.locale ?? defaultLocale);
|
|
468
468
|
|
|
469
469
|
// Check if entry exists (by slug + locale for locale-aware lookup)
|
|
470
470
|
const existing = await contentRepo.findBySlug(collectionSlug, entry.slug, entryLocale);
|
|
@@ -621,7 +621,7 @@ export async function applySeed(
|
|
|
621
621
|
const itemSeedIdMap = new Map<string, { id: string; translationGroup: string }>();
|
|
622
622
|
|
|
623
623
|
for (const menu of seed.menus) {
|
|
624
|
-
const locale = menu.locale ?? defaultLocale;
|
|
624
|
+
const locale = resolveConfiguredLocale(menu.locale ?? defaultLocale);
|
|
625
625
|
let lookup = db
|
|
626
626
|
.selectFrom("_emdash_menus")
|
|
627
627
|
.selectAll()
|
|
@@ -867,6 +867,8 @@ async function applyHierarchicalTerms(
|
|
|
867
867
|
): Promise<void> {
|
|
868
868
|
// "locale::slug" -> id, so the same slug can resolve per locale.
|
|
869
869
|
const slugToId = new Map<string, string>();
|
|
870
|
+
const resolveTermLocale = (term: SeedTaxonomyTerm) =>
|
|
871
|
+
resolveConfiguredLocale(term.locale ?? defLocale);
|
|
870
872
|
|
|
871
873
|
// Multiple passes — handles deep nesting and translationOf forward refs.
|
|
872
874
|
let remaining = [...terms];
|
|
@@ -876,7 +878,7 @@ async function applyHierarchicalTerms(
|
|
|
876
878
|
const processedThisPass: string[] = [];
|
|
877
879
|
|
|
878
880
|
for (const term of remaining) {
|
|
879
|
-
const termLocale = term
|
|
881
|
+
const termLocale = resolveTermLocale(term);
|
|
880
882
|
const parentReady = !term.parent || slugToId.has(`${termLocale}::${term.parent}`);
|
|
881
883
|
const translationReady = !term.translationOf || termSeedIdMap.has(term.translationOf);
|
|
882
884
|
|
|
@@ -921,7 +923,7 @@ async function applyHierarchicalTerms(
|
|
|
921
923
|
}
|
|
922
924
|
|
|
923
925
|
remaining = remaining.filter(
|
|
924
|
-
(
|
|
926
|
+
(term) => !processedThisPass.includes(term.slug + "::" + resolveTermLocale(term)),
|
|
925
927
|
);
|
|
926
928
|
maxPasses--;
|
|
927
929
|
}
|
package/src/seed/validate.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Validates a seed file structure before applying it.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import { getI18nConfig, resolveConfiguredLocale } from "../i18n/config.js";
|
|
7
8
|
import { FIELD_TYPES } from "../schema/types.js";
|
|
8
9
|
import type { SeedFile, SeedMenuItem, ValidationResult } from "./types.js";
|
|
9
10
|
|
|
@@ -49,6 +50,9 @@ export function validateSeed(data: unknown): ValidationResult {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
const seed = data as Partial<SeedFile>;
|
|
53
|
+
const defaultLocale =
|
|
54
|
+
getI18nConfig()?.defaultLocale ??
|
|
55
|
+
(typeof seed.defaultLocale === "string" ? seed.defaultLocale : "en");
|
|
52
56
|
|
|
53
57
|
// Required fields
|
|
54
58
|
if (!seed.version) {
|
|
@@ -163,7 +167,8 @@ export function validateSeed(data: unknown): ValidationResult {
|
|
|
163
167
|
errors.push(`${prefix}: name is required`);
|
|
164
168
|
} else {
|
|
165
169
|
// Uniqueness is per (name, locale).
|
|
166
|
-
const
|
|
170
|
+
const locale = resolveConfiguredLocale(taxonomy.locale ?? defaultLocale);
|
|
171
|
+
const key = `${taxonomy.name}::${locale}`;
|
|
167
172
|
if (taxonomyNames.has(key)) {
|
|
168
173
|
errors.push(
|
|
169
174
|
taxonomy.locale
|
|
@@ -206,7 +211,10 @@ export function validateSeed(data: unknown): ValidationResult {
|
|
|
206
211
|
} else {
|
|
207
212
|
// Uniqueness is per (slug, locale) so the same slug can repeat
|
|
208
213
|
// across locale variants of the def.
|
|
209
|
-
const
|
|
214
|
+
const locale = resolveConfiguredLocale(
|
|
215
|
+
term.locale ?? taxonomy.locale ?? defaultLocale,
|
|
216
|
+
);
|
|
217
|
+
const key = `${term.slug}::${locale}`;
|
|
210
218
|
if (termSlugs.has(key)) {
|
|
211
219
|
errors.push(
|
|
212
220
|
`${termPrefix}.slug: duplicate term slug "${term.slug}" in taxonomy "${taxonomy.name}"`,
|
|
@@ -233,7 +241,9 @@ export function validateSeed(data: unknown): ValidationResult {
|
|
|
233
241
|
if (taxonomy.hierarchical && taxonomy.terms) {
|
|
234
242
|
for (let j = 0; j < taxonomy.terms.length; j++) {
|
|
235
243
|
const term = taxonomy.terms[j];
|
|
236
|
-
const termLocale =
|
|
244
|
+
const termLocale = resolveConfiguredLocale(
|
|
245
|
+
term.locale ?? taxonomy.locale ?? defaultLocale,
|
|
246
|
+
);
|
|
237
247
|
if (term.parent && !termSlugs.has(`${term.parent}::${termLocale}`)) {
|
|
238
248
|
errors.push(
|
|
239
249
|
`${prefix}.terms[${j}].parent: parent term "${term.parent}" not found in taxonomy`,
|
|
@@ -268,7 +278,8 @@ export function validateSeed(data: unknown): ValidationResult {
|
|
|
268
278
|
} else {
|
|
269
279
|
// Uniqueness is per (name, locale) — siblings of a translation
|
|
270
280
|
// group share name but differ in locale.
|
|
271
|
-
const
|
|
281
|
+
const locale = resolveConfiguredLocale(menu.locale ?? defaultLocale);
|
|
282
|
+
const key = `${menu.name}::${locale}`;
|
|
272
283
|
if (menuNames.has(key)) {
|
|
273
284
|
errors.push(
|
|
274
285
|
menu.locale
|
package/src/taxonomies/index.ts
CHANGED
|
@@ -31,6 +31,15 @@ export interface TaxonomyQueryOptions {
|
|
|
31
31
|
locale?: string;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
export interface TaxonomyTermsOptions extends TaxonomyQueryOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Populate each term's `count`. Counts aggregate the whole
|
|
37
|
+
* `content_taxonomies` pivot against every declared collection, so callers
|
|
38
|
+
* that don't render a count should opt out. Defaults to `true`.
|
|
39
|
+
*/
|
|
40
|
+
includeCounts?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
34
43
|
/** Invalidate cached taxonomy term data and any content that hydrates terms. */
|
|
35
44
|
export function invalidateTermCache(): void {
|
|
36
45
|
invalidateTaxonomyObjectCache();
|
|
@@ -230,21 +239,54 @@ function termCountNamespaces(collections: string[]): string[] {
|
|
|
230
239
|
/**
|
|
231
240
|
* All terms of a taxonomy in a specific locale (flat for non-hierarchical,
|
|
232
241
|
* tree for hierarchical).
|
|
242
|
+
*
|
|
243
|
+
* The term list and the visible-entry counts are loaded and cached separately:
|
|
244
|
+
* the list depends only on the taxonomy epoch, while the counts additionally
|
|
245
|
+
* depend on every counted collection's content epoch and cost an aggregate over
|
|
246
|
+
* the whole assignment pivot. Callers that don't render counts pass
|
|
247
|
+
* `includeCounts: false` and skip that aggregate entirely, while still sharing
|
|
248
|
+
* the term list with callers that do.
|
|
233
249
|
*/
|
|
234
250
|
export async function getTaxonomyTerms(
|
|
235
251
|
taxonomyName: string,
|
|
236
|
-
options:
|
|
252
|
+
options: TaxonomyTermsOptions = {},
|
|
237
253
|
): Promise<TaxonomyTerm[]> {
|
|
238
254
|
const locale = resolveLocale(options.locale);
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
255
|
+
const def = await getTaxonomyDef(taxonomyName, options);
|
|
256
|
+
if (!def) return [];
|
|
257
|
+
if (options.includeCounts === false) return getTermList(def, locale);
|
|
258
|
+
|
|
259
|
+
// The two are independent, so run them concurrently to save a round trip.
|
|
260
|
+
const [terms, counts] = await Promise.all([
|
|
261
|
+
getTermList(def, locale),
|
|
262
|
+
getVisibleTermCounts(def.name, def.collections),
|
|
263
|
+
]);
|
|
264
|
+
return withCounts(terms, counts);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** Terms without counts, under the cache keys the layout prefetch warms. */
|
|
268
|
+
function getTermList(def: TaxonomyDef, locale: string | undefined): Promise<TaxonomyTerm[]> {
|
|
269
|
+
const localeKey = locale ?? "*";
|
|
270
|
+
return requestCached(`taxonomy-terms:${def.name}:${localeKey}`, () =>
|
|
271
|
+
cachedQuery({
|
|
272
|
+
namespace: CacheNamespace.TAXONOMIES,
|
|
273
|
+
key: `termList:${def.name}:${localeKey}`,
|
|
245
274
|
load: () => loadTaxonomyTerms(def, locale),
|
|
246
|
-
})
|
|
247
|
-
|
|
275
|
+
}),
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Copy a term list with counts attached. Counts are keyed by translation_group
|
|
281
|
+
* (what the pivot stores) and are locale-independent. Rebuilds every node so
|
|
282
|
+
* the shared, cached count-free list is never mutated.
|
|
283
|
+
*/
|
|
284
|
+
function withCounts(terms: TaxonomyTerm[], counts: Map<string, number>): TaxonomyTerm[] {
|
|
285
|
+
return terms.map((term) => ({
|
|
286
|
+
...term,
|
|
287
|
+
count: counts.get(term.translationGroup ?? term.id) ?? 0,
|
|
288
|
+
children: withCounts(term.children, counts),
|
|
289
|
+
}));
|
|
248
290
|
}
|
|
249
291
|
|
|
250
292
|
async function loadTaxonomyTerms(
|
|
@@ -260,14 +302,7 @@ async function loadTaxonomyTerms(
|
|
|
260
302
|
.orderBy("label", "asc");
|
|
261
303
|
if (locale !== undefined) termsQuery = termsQuery.where("locale", "=", locale);
|
|
262
304
|
|
|
263
|
-
|
|
264
|
-
// locale-independent. Only publicly visible entries are counted (#581);
|
|
265
|
-
// the map is request-cached so a term detail rendered on the same page
|
|
266
|
-
// reuses it. Independent of the terms query, so run both concurrently.
|
|
267
|
-
const [rows, counts] = await Promise.all([
|
|
268
|
-
termsQuery.execute(),
|
|
269
|
-
getVisibleTermCounts(def.name, def.collections),
|
|
270
|
-
]);
|
|
305
|
+
const rows = await termsQuery.execute();
|
|
271
306
|
|
|
272
307
|
const flatTerms: TaxonomyTermRow[] = rows.map((row) => ({
|
|
273
308
|
id: row.id,
|
|
@@ -280,7 +315,7 @@ async function loadTaxonomyTerms(
|
|
|
280
315
|
translation_group: row.translation_group,
|
|
281
316
|
}));
|
|
282
317
|
|
|
283
|
-
if (def.hierarchical) return buildTree(flatTerms
|
|
318
|
+
if (def.hierarchical) return buildTree(flatTerms);
|
|
284
319
|
|
|
285
320
|
return flatTerms.map((term) => ({
|
|
286
321
|
id: term.id,
|
|
@@ -289,7 +324,6 @@ async function loadTaxonomyTerms(
|
|
|
289
324
|
label: term.label,
|
|
290
325
|
description: term.data ? JSON.parse(term.data).description : undefined,
|
|
291
326
|
children: [],
|
|
292
|
-
count: counts.get(term.translation_group ?? term.id) ?? 0,
|
|
293
327
|
locale: term.locale,
|
|
294
328
|
translationGroup: term.translation_group,
|
|
295
329
|
}));
|
|
@@ -312,8 +346,16 @@ function getVisibleTermCounts(
|
|
|
312
346
|
// entry.
|
|
313
347
|
const scope = [...new Set(collections)].toSorted().join(",");
|
|
314
348
|
return requestCached(`taxonomy-term-counts:${taxonomyName}:${scope}`, async () => {
|
|
315
|
-
|
|
316
|
-
|
|
349
|
+
// A Map is not JSON-representable — cache the entries, rebuild on read.
|
|
350
|
+
const entries = await cachedQuery({
|
|
351
|
+
namespace: termCountNamespaces(collections),
|
|
352
|
+
key: `termCounts:${taxonomyName}:${scope}`,
|
|
353
|
+
load: async (): Promise<Array<[string, number]>> => {
|
|
354
|
+
const db = await getDb();
|
|
355
|
+
return [...(await fetchVisibleTermCounts(db, taxonomyName, collections))];
|
|
356
|
+
},
|
|
357
|
+
});
|
|
358
|
+
return new Map(entries);
|
|
317
359
|
});
|
|
318
360
|
}
|
|
319
361
|
|
|
@@ -796,7 +838,7 @@ function rowToTaxonomyDef(row: {
|
|
|
796
838
|
/**
|
|
797
839
|
* Build tree structure from flat terms
|
|
798
840
|
*/
|
|
799
|
-
function buildTree(flatTerms: TaxonomyTermRow[]
|
|
841
|
+
function buildTree(flatTerms: TaxonomyTermRow[]): TaxonomyTerm[] {
|
|
800
842
|
// parent_id holds the parent's translation_group, so link children by it.
|
|
801
843
|
// Key by (locale, group): a child's parent lives in the same locale, and an
|
|
802
844
|
// unfiltered set mixes locales whose translated siblings share a group —
|
|
@@ -814,7 +856,6 @@ function buildTree(flatTerms: TaxonomyTermRow[], counts: Map<string, number>): T
|
|
|
814
856
|
parentId: term.parent_id ?? undefined,
|
|
815
857
|
description: term.data ? JSON.parse(term.data).description : undefined,
|
|
816
858
|
children: [],
|
|
817
|
-
count: counts.get(term.translation_group ?? term.id) ?? 0,
|
|
818
859
|
locale: term.locale,
|
|
819
860
|
translationGroup: term.translation_group,
|
|
820
861
|
};
|