diff --git a/.changeset/query-db-collection-gctime-forward.md b/.changeset/query-db-collection-gctime-forward.md new file mode 100644 index 000000000..ba23d8bc7 --- /dev/null +++ b/.changeset/query-db-collection-gctime-forward.md @@ -0,0 +1,5 @@ +--- +'@tanstack/query-db-collection': patch +--- + +Forward `gcTime` from `queryCollectionOptions` to the underlying TanStack Query observer. The `gcTime` option was previously documented in the config shape but silently dropped before reaching the observer, leaving consumers stuck on the `queryClient` default. Closes #1546. diff --git a/packages/query-db-collection/src/query.ts b/packages/query-db-collection/src/query.ts index b29aac873..501203612 100644 --- a/packages/query-db-collection/src/query.ts +++ b/packages/query-db-collection/src/query.ts @@ -119,6 +119,13 @@ export interface QueryCollectionConfig< TQueryData, TQueryKey >[`staleTime`] + gcTime?: QueryObserverOptions< + TQueryData, + TError, + Array, + TQueryData, + TQueryKey + >[`gcTime`] persistedGcTime?: number /** @@ -578,6 +585,7 @@ export function queryCollectionOptions( retry, retryDelay, staleTime, + gcTime, persistedGcTime, getKey, onInsert, @@ -1163,6 +1171,7 @@ export function queryCollectionOptions( ...(retry !== undefined && { retry }), ...(retryDelay !== undefined && { retryDelay }), ...(staleTime !== undefined && { staleTime }), + ...(gcTime !== undefined && { gcTime }), } const localObserver = new QueryObserver< diff --git a/packages/query-db-collection/tests/query.test.ts b/packages/query-db-collection/tests/query.test.ts index 113fc0e1e..0c501ab02 100644 --- a/packages/query-db-collection/tests/query.test.ts +++ b/packages/query-db-collection/tests/query.test.ts @@ -3594,6 +3594,107 @@ describe(`QueryCollection`, () => { customQueryClient.clear() }) + it(`should forward gcTime from queryCollectionOptions to the underlying query`, async () => { + const customQueryClient = new QueryClient({ + defaultOptions: { + queries: { + gcTime: 60000, + }, + }, + }) + + const queryKey = [`gcTimeForwardTest`] + const items: Array = [{ id: `1`, name: `Item 1` }] + const queryFn = vi.fn().mockResolvedValue(items) + + const config: QueryCollectionConfig = { + id: `gcTimeForwardTest`, + queryClient: customQueryClient, + queryKey, + queryFn, + getKey, + startSync: true, + gcTime: 100000, + } + + const options = queryCollectionOptions(config) + const collection = createCollection(options) + + await vi.waitFor(() => { + expect(collection.status).toBe(`ready`) + }) + + const query = customQueryClient.getQueryCache().find({ queryKey }) + expect((query?.options as any).gcTime).toBe(100000) + + customQueryClient.clear() + }) + + it(`should fall back to QueryClient default gcTime when omitted`, async () => { + const customQueryClient = new QueryClient({ + defaultOptions: { + queries: { + gcTime: 45000, + }, + }, + }) + + const queryKey = [`gcTimeFallbackTest`] + const items: Array = [{ id: `1`, name: `Item 1` }] + const queryFn = vi.fn().mockResolvedValue(items) + + const config: QueryCollectionConfig = { + id: `gcTimeFallbackTest`, + queryClient: customQueryClient, + queryKey, + queryFn, + getKey, + startSync: true, + } + + const options = queryCollectionOptions(config) + const collection = createCollection(options) + + await vi.waitFor(() => { + expect(collection.status).toBe(`ready`) + }) + + const query = customQueryClient.getQueryCache().find({ queryKey }) + expect((query?.options as any).gcTime).toBe(45000) + + customQueryClient.clear() + }) + + it(`should accept Infinity as gcTime to disable garbage collection`, async () => { + const customQueryClient = new QueryClient() + + const queryKey = [`gcTimeInfinityTest`] + const items: Array = [{ id: `1`, name: `Item 1` }] + const queryFn = vi.fn().mockResolvedValue(items) + + const config: QueryCollectionConfig = { + id: `gcTimeInfinityTest`, + queryClient: customQueryClient, + queryKey, + queryFn, + getKey, + startSync: true, + gcTime: Infinity, + } + + const options = queryCollectionOptions(config) + const collection = createCollection(options) + + await vi.waitFor(() => { + expect(collection.status).toBe(`ready`) + }) + + const query = customQueryClient.getQueryCache().find({ queryKey }) + expect((query?.options as any).gcTime).toBe(Infinity) + + customQueryClient.clear() + }) + it(`should use retry from QueryClient defaultOptions when not overridden`, async () => { let callCount = 0 // Create a QueryClient with custom retry defaultOption