From ce45495268c1ccc2d55fd0855a07fcc6cd4957bf Mon Sep 17 00:00:00 2001 From: gauravkumar Date: Thu, 1 Jan 2026 00:30:11 +0530 Subject: [PATCH 1/3] Fixed and added tests --- .../src/__tests__/exhaustive-deps.test.ts | 109 ++++++++++++++++++ .../exhaustive-deps/exhaustive-deps.rule.ts | 1 + .../exhaustive-deps/exhaustive-deps.utils.ts | 38 ++++-- 3 files changed, 136 insertions(+), 12 deletions(-) diff --git a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts index f27b058ec5..78a0a2fd6f 100644 --- a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts @@ -548,6 +548,45 @@ ruleTester.run('exhaustive-deps', rule, { } `, }, + { + name: 'should pass in Vue file when deps are correctly included (script setup)', + filename: 'Component.vue', + code: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + + const id = 1 + useQuery({ + queryKey: ['entity', id], + queryFn: () => fetchEntity(id), + }) + `, + }, + { + name: 'should not require imports in queryKey for Vue files', + filename: 'Component.vue', + code: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + import { fetchTodos } from './api' + + useQuery({ + queryKey: ['todos'], + queryFn: () => fetchTodos(), + }) + `, + }, + { + name: 'should not require global fetch in queryKey for Vue files', + filename: 'Component.vue', + code: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + + const id = 1 + useQuery({ + queryKey: ['entity', id], + queryFn: () => fetch('/api/entity/' + id), + }) + `, + }, ], invalid: [ { @@ -975,5 +1014,75 @@ ruleTester.run('exhaustive-deps', rule, { }, ], }, + { + name: 'should fail in Vue file when deps are missing (script setup)', + filename: 'Component.vue', + code: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + + const id = 1 + useQuery({ + queryKey: ['entity'], + queryFn: () => fetchEntity(id), + }) + `, + errors: [ + { + messageId: 'missingDeps', + data: { deps: 'id' }, + suggestions: [ + { + messageId: 'fixTo', + data: { result: "['entity', id]" }, + output: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + + const id = 1 + useQuery({ + queryKey: ['entity', id], + queryFn: () => fetchEntity(id), + }) + `, + }, + ], + }, + ], + }, + { + name: 'should fail in Vue file when multiple deps are missing', + filename: 'Component.vue', + code: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + + const userId = 1 + const orgId = 2 + useQuery({ + queryKey: ['users'], + queryFn: () => fetchUser(userId, orgId), + }) + `, + errors: [ + { + messageId: 'missingDeps', + data: { deps: 'userId, orgId' }, + suggestions: [ + { + messageId: 'fixTo', + data: { result: "['users', userId, orgId]" }, + output: normalizeIndent` + import { useQuery } from '@tanstack/vue-query' + + const userId = 1 + const orgId = 2 + useQuery({ + queryKey: ['users', userId, orgId], + queryFn: () => fetchUser(userId, orgId), + }) + `, + }, + ], + }, + ], + }, ], }) diff --git a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts index 15c0918e97..c3a12e5e18 100644 --- a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts +++ b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts @@ -82,6 +82,7 @@ export const rule = createRule({ reference, scopeManager, node: getQueryFnRelevantNode(queryFn), + filename: context.filename, }), ) diff --git a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts index 5762f506d1..c7f14ba6b6 100644 --- a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts +++ b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts @@ -8,22 +8,36 @@ export const ExhaustiveDepsUtils = { reference: TSESLint.Scope.Reference scopeManager: TSESLint.Scope.ScopeManager node: TSESTree.Node + filename: string }) { - const { sourceCode, reference, scopeManager, node } = params + const { sourceCode, reference, scopeManager, node, filename } = params const component = ASTUtils.getFunctionAncestor(sourceCode, node) - if (component === undefined) { - return false - } + if (component !== undefined) { + if ( + !ASTUtils.isDeclaredInNode({ + scopeManager, + reference, + functionNode: component, + }) + ) { + return false + } + } else { + const isVueFile = filename.endsWith('.vue') + + if (!isVueFile) { + return false + } + + const definition = reference.resolved?.defs[0] + const isGlobalVariable = definition === undefined + const isImport = definition?.type === 'ImportBinding' + + if (isGlobalVariable || isImport) { + return false + } - if ( - !ASTUtils.isDeclaredInNode({ - scopeManager, - reference, - functionNode: component, - }) - ) { - return false } return ( From a0e0e832f5c84668b8e11fb8d80cb4030dfc2015 Mon Sep 17 00:00:00 2001 From: gauravkumar Date: Thu, 1 Jan 2026 00:38:09 +0530 Subject: [PATCH 2/3] Changeset --- .changeset/slimy-taxes-make.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slimy-taxes-make.md diff --git a/.changeset/slimy-taxes-make.md b/.changeset/slimy-taxes-make.md new file mode 100644 index 0000000000..1dc1cf8302 --- /dev/null +++ b/.changeset/slimy-taxes-make.md @@ -0,0 +1,5 @@ +--- +'@tanstack/eslint-plugin-query': patch +--- + +exhaustive-deps rule fixed for vue files From 0e5521129a76c7d448eb8ca31a5d9446565cc59f Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 31 Dec 2025 19:31:31 +0000 Subject: [PATCH 3/3] ci: apply automated fixes --- .../src/rules/exhaustive-deps/exhaustive-deps.utils.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts index c7f14ba6b6..c0533e3910 100644 --- a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts +++ b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts @@ -37,7 +37,6 @@ export const ExhaustiveDepsUtils = { if (isGlobalVariable || isImport) { return false } - } return (