fix(core): make term-list counts opt-out for the editor picker - #2243
Conversation
🦋 Changeset detectedLatest commit: 996d498 The changes in this PR will be included in the next version bump. This PR includes changesets to release 17 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-verification
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
This is the right fix in the right place. The admin terms endpoint was sharing its expensive visible-count aggregate between the Taxonomies settings page (which needs counts) and the content editor’s taxonomy picker (which doesn’t). Adding an includeCounts query flag with a backward-compatible default and having the editor opt out mirrors the existing public-side getTaxonomyTerms API and directly fixes the editor-open regression.
I read the full diff and the changed files, traced the admin call sites in TaxonomySidebar and TaxonomyManager, checked the route’s authorization/CSRF wiring, query-param parsing, and OpenAPI registration. The code is clean:
includeCountsdefaults totrue, so existing callers see identical responses.handleTermListskipsfetchVisibleTermCountsonly when opted out, and omitscountfrom the term object rather than returning a misleading0.- The editor sidebar always passes
includeCounts=false. - The
TermWithCounttype and OpenAPI response schema correctly becomecount?: number. - A changeset is included, and the new tests assert the actual aggregate behavior, not just response shape.
No AGENTS.md convention violations (localization, RTL, SQL safety, API envelope shape, authorization, locale filtering, index discipline, changesets, logged-out query counts, or comment discipline) stood out.
No blocking issues — LGTM.
khoinguyenpham04
left a comment
There was a problem hiding this comment.
just one thing before merge. the editor and TaxonomyManager need separate cache keys since one fetches counts and the other doesn’t.
The content editor's taxonomy sidebar lists terms to pick from and never renders a usage count, but it shares GET /_emdash/api/taxonomies/:name/terms with the Taxonomies settings page, which does. handleTermList aggregated counts unconditionally, so every editor open ran one `content_taxonomies x ec_*` UNION ALL per applicable taxonomy — a branch for each collection the taxonomy declares. Add an `includeCounts` query param (default true, so existing callers and the settings page are unchanged). When false the aggregate is skipped and `count` is omitted from each term rather than reported as a misleading 0. The editor sidebar passes includeCounts=false. emdash-cms#2219 made the public render path demand-driven; this is the admin-side counterpart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
9706f5b to
0e00ec9
Compare
The editor's taxonomy picker and the Taxonomies settings page read the same terms endpoint under the same react-query key, but the picker now opts out of counts. Within the app's 1 minute staleTime, the settings page mounting after an editor open was served the cached count-free list and rendered every term's count as 0 until something invalidated it. Add the count mode to both query keys. The existing prefix invalidations still match, so creating, editing or deleting a term refreshes both consumers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
This is a re-review of a PR I previously approved, and the current state is still the right fix in the right place. The additional changes since the prior review — adding the includeCounts mode to the TanStack Query cache keys and adding packages/admin/tests/components/taxonomy-term-cache.test.tsx — correctly close the only remaining cache-coherence risk: without the count mode in the key, the editor sidebar's count-free list would be served to the Taxonomies settings page, which renders counts.
I re-read the full diff and the changed files, traced the admin call sites, and checked the route, handler, schema, OpenAPI registration, and tests against AGENTS.md conventions. Everything looks clean:
includeCountsdefaults totrueat the API schema, route, and handler levels, so existing callers get identical responses.- The editor sidebar hardcodes
?includeCounts=false; the Taxonomies settings page still relies on the server default and gets real counts. TermWithCount.countand the OpenAPI response schema are correctly optional.- The query keys now distinguish count modes, and invalidations use broad prefixes that still invalidate both variants.
- The new tests assert observable behavior (SQL executed, cache isolation across components), not implementation trivia.
- No localization, RTL, SQL-safety, authorization, locale-filtering, logged-out-query-count, changeset, or comment-discipline issues stand out.
No blocking issues — LGTM.
khoinguyenpham04
left a comment
There was a problem hiding this comment.
LGTM! Thanks @MA2153
What does this PR do?
The content editor's taxonomy sidebar (
TaxonomySidebar, rendered byContentSettingsPanelon every editor open with nostaleTime) lists terms to pick from and never renders a usage count. It sharesGET /_emdash/api/taxonomies/:name/termswith the Taxonomies settings page, which does render counts — andhandleTermListaggregated counts unconditionally. Opening any entry therefore ran thecontent_taxonomies × ec_*UNION ALL aggregate once per applicable taxonomy, with one branch per collection the taxonomy declares:The endpoint now takes an
includeCountsquery param, defaulting totrue. Whenfalse, the aggregate is skipped andcountis omitted from each term rather than reported as a misleading0. The editor sidebar passesincludeCounts=false; the Taxonomies settings page keeps the default and still shows real counts.#2219 made the public render path demand-driven (
getTaxonomyTerms({ includeCounts })); this is the admin-side counterpart, and the param name matches.Compatibility: the default is unchanged, so existing API consumers see identical responses. The one ripple is type-level —
TermWithCount.countbecomesnumber | undefined, so TS consumers reading it must handleundefined. The only consumer in this repo (TaxonomyManager.tsx) already did ({term.count || 0}).Type of change
Checklist
pnpm typecheckpassespnpm lintpasses (pnpm lint:json→ 0 diagnostics, matching the pre-change baseline)pnpm testpasses (fullpackages/coresuite: 5022 passed, 3 skipped, 0 failed)pnpm formathas been runmsg-wrapped error. Nomessages.pochanges included.AI-generated code disclosure
Screenshots / test output
New test asserts on the SQL actually executed (logging Kysely, filtering for the aggregate's
per_collectionsubquery alias) — a response-shape assertion alone can't prove the work was skipped. Written first, failing on the two opt-out cases before the fix.Full core suite:
🤖 Generated with Claude Code