From b9d8bf948c1e4c03e2de6426f37596367574b25f Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:11:02 +0100 Subject: [PATCH] fix(base): strip empty filter groups at the query boundary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The view-draft layer stores `{op: 'and', children: []}` as an explicit "override baseline with no predicates" marker. That payload was leaking into /bases/rows requests once local filter/sort drafts were enabled — harmless server-side (buildWhere maps an empty group to TRUE) but it destabilised the React Query key and cluttered request payloads. Normalise empty groups to undefined at the hook level. --- .../src/features/base/queries/base-row-query.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/apps/client/src/features/base/queries/base-row-query.ts b/apps/client/src/features/base/queries/base-row-query.ts index 3321348e6..5350fe7df 100644 --- a/apps/client/src/features/base/queries/base-row-query.ts +++ b/apps/client/src/features/base/queries/base-row-query.ts @@ -32,6 +32,17 @@ type RowCacheContext = { snapshots: [readonly unknown[], InfiniteData> | undefined][]; }; +// An empty group filter (`{op: 'and', children: []}`) is the draft-layer's +// explicit "override baseline with no predicates" marker — see +// use-view-draft.ts. It carries no server-side meaning (buildWhere maps it +// to TRUE), so strip it at the query boundary to keep request payloads +// clean and cache keys stable when the user resets filters. +function normalizeFilter(filter: FilterNode | undefined): FilterNode | undefined { + if (!filter) return undefined; + if ('children' in filter && filter.children.length === 0) return undefined; + return filter; +} + // Generate a fresh requestId and pre-register it as outbound so the // incoming socket echo is suppressed by `useBaseSocket`. function newRequestId(): string { @@ -50,7 +61,7 @@ export function useBaseRowsQuery( sorts?: ViewSortConfig[], search?: SearchSpec, ) { - const activeFilter = filter ?? undefined; + const activeFilter = normalizeFilter(filter); const activeSorts = sorts?.length ? sorts : undefined; const activeSearch = search?.query ? search : undefined;