fix(vue-query): unwrap getter options in fetchQuery#11103
Conversation
📝 WalkthroughWalkthrough
ChangesFetch query getter options
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant VueQueryQueryClient
participant QueryClientOrigin
Caller->>VueQueryQueryClient: fetchQuery(getter)
VueQueryQueryClient->>VueQueryQueryClient: evaluate getter and deep-unref options
VueQueryQueryClient->>QueryClientOrigin: fetchQuery(unwrapped options)
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/vue-query/src/queryClient.ts`:
- Around line 36-41: Update the fetchQuery overload’s getter branch to accept ()
=> MaybeRefDeep<FetchQueryOptions<...>> instead of only () =>
FetchQueryOptions<...>, matching cloneDeepUnrefOrGet runtime support for
ref-bearing options while preserving the existing non-getter overload behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 74cf3a52-8bdf-4c55-9ef2-fac18a9d7107
📒 Files selected for processing (3)
.changeset/vue-query-fetch-query-getter-options.mdpackages/vue-query/src/__tests__/queryClient.test.tspackages/vue-query/src/queryClient.ts
| type MaybeRefDeepOrGetter<T> = MaybeRefDeep<T> | (() => T) | ||
|
|
||
| function cloneDeepUnrefOrGet<T>(value: MaybeRefDeepOrGetter<T>): T { | ||
| const unwrapped = typeof value === 'function' ? (value as () => T)() : value | ||
|
|
||
| return cloneDeepUnref(unwrapped as MaybeRefDeep<T>) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map relevant files and locate the types/overloads/test cases.
git ls-files packages/vue-query/src/queryClient.ts packages/vue-query/src | sed -n '1,120p'
printf '\n--- outline queryClient.ts ---\n'
ast-grep outline packages/vue-query/src/queryClient.ts --view expanded || true
printf '\n--- search for MaybeRefDeepOrGetter and getter overloads ---\n'
rg -n "MaybeRefDeepOrGetter|cloneDeepUnrefOrGet|FetchQueryOptions|MaybeRefDeep<FetchQueryOptions|\\(\\) =>" packages/vue-query/src packages/vue-query/test -S || true
printf '\n--- find query getter-related tests ---\n'
rg -n "queryKeyRef|getter|deep ref|MaybeRefDeep" packages/vue-query -S || trueRepository: TanStack/query
Length of output: 50371
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the relevant portion of queryClient.ts with line numbers.
sed -n '1,180p' packages/vue-query/src/queryClient.ts | cat -nRepository: TanStack/query
Length of output: 6963
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect package typings and tests around the Vue Query client helpers.
find packages/vue-query -maxdepth 3 -type f | sort | sed -n '1,200p'Repository: TanStack/query
Length of output: 3128
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,220p' packages/vue-query/src/queryClient.ts | cat -nRepository: TanStack/query
Length of output: 8707
🌐 Web query:
packages/vue-query/src/queryClient.ts MaybeRefDeepOrGetter FetchQueryOptions vue query getter deep refs
💡 Result:
In TanStack Vue Query, MaybeRefDeepOrGetter is a type utility introduced to support both MaybeRef (Vue refs) and getter functions (() => T) within query options [1]. This allows for more flexible, reactive configurations that can handle complex, nested structures [1]. ### Core Concepts * MaybeRefDeep: Recursively transforms properties of type T into MaybeRef<T>, allowing deep reactivity where individual properties of an options object can be Vue refs [2]. * MaybeRefOrGetter: A union type (MaybeRef<T> | (() => T)) that allows passing either a static value, a Vue ref, or a getter function [2]. * MaybeRefDeepOrGetter: Extends the concept to handle deeply reactive objects while also permitting the entire object (or specific parts of it) to be returned by a getter function [1]. ### Technical Context in queryClient.ts In packages/vue-query/src/queryClient.ts, methods like fetchQuery and prefetchQuery utilize these type utilities to normalize incoming options [3][4]. Specifically, these methods apply cloneDeepUnref to the options object before passing them to the underlying query-core implementation [3][4]. cloneDeepUnref is a utility defined in packages/vue-query/src/utils.ts that performs several key tasks [5]: 1. Deep Unwrapping: It recursively traverses the options object to unwrap Ref values [5]. 2. Getter Resolution: It can be configured (by setting unrefGetters to true) to execute getter functions, allowing it to resolve reactive dependencies even when they are wrapped in functions rather than just refs [5]. 3. Integration: This mechanism bridges the gap between Vue's reactive system and the imperative, static-options-based nature of the core TanStack Query library [3][5]. ### Recent Developments Recent PRs and issues indicate ongoing refinements to these type utilities to ensure that getters and plain properties are handled correctly across all query methods, such as ensureQueryData and fetchQuery [6][7]. The goal of these changes is to maintain strict TypeScript compatibility while providing a seamless developer experience that mirrors how useQuery handles reactive options [6][1].
Citations:
- 1: feat(vue-query): Add mutationOptions #10036
- 2: https://github.com/TanStack/query/blob/main/packages/vue-query/src/types.ts
- 3: https://github.com/TanStack/query/blob/d4fd9417/packages/vue-query/src/queryClient.ts
- 4: https://github.com/TanStack/query/blob/d6884583/packages/vue-query/src/queryClient.ts
- 5: https://github.com/TanStack/query/blob/feb1efd8/packages/vue-query/src/utils.ts
- 6: fix(vue-query): fix type of queryOptions to allow plain properies or getters #10452
- 7: [vue-query]: type issue with
queryOptionsinsideensureQueryData#6477
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the exact helper and overload area in the source file.
nl -ba packages/vue-query/src/queryClient.ts | sed -n '30,70p;290,320p'Repository: TanStack/query
Length of output: 192
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the fetchQuery/prefetchQuery typings and the relevant d.ts tests.
sed -n '260,360p' packages/vue-query/src/queryClient.ts | cat -n
printf '\n--- queryClient.test-d.ts ---\n'
sed -n '1,220p' packages/vue-query/src/__tests__/queryClient.test-d.ts | cat -nRepository: TanStack/query
Length of output: 9424
Allow deep refs in fetchQuery getters. cloneDeepUnrefOrGet() unwraps getter results, but the fetchQuery overload still types the getter branch as () => FetchQueryOptions<...>. That rejects getters returning ref-bearing options even though runtime accepts them. Change it to () => MaybeRefDeep<FetchQueryOptions<...>> so the type surface matches behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/vue-query/src/queryClient.ts` around lines 36 - 41, Update the
fetchQuery overload’s getter branch to accept () =>
MaybeRefDeep<FetchQueryOptions<...>> instead of only () =>
FetchQueryOptions<...>, matching cloneDeepUnrefOrGet runtime support for
ref-bearing options while preserving the existing non-getter overload behavior.
Fixes #11102
🎯 Changes
QueryClient.fetchQueryhas an overload that accepts a getter function returningFetchQueryOptions, but the runtime path passed that top-level function directly to query-core.This PR evaluates top-level getter options before applying the existing deep-unref behavior.
Changes included:
cloneDeepUnrefqueryClient.fetchQueryfetchQuery(() => options)@tanstack/vue-query✅ Checklist
pnpm run test:pr.🚀 Release Impact
Tests
pnpm run test:prpnpm nx run @tanstack/vue-query:test:lib -- queryClient.test.tspnpm nx run @tanstack/vue-query:test:typespnpm nx run @tanstack/vue-query:test:eslintpnpm exec prettier --check .changeset/vue-query-fetch-query-getter-options.md packages/vue-query/src/queryClient.ts packages/vue-query/src/__tests__/queryClient.test.ts