Skip to content

Commit 3e4f8c8

Browse files
gk9848970gaurav-dtautofix-ci[bot]TkDodo
authored
fix(eslint-plugin-query): Exhaustive deps rule not working for vue files (#10011)
* Fixed and added tests * Changeset * ci: apply automated fixes --------- Co-authored-by: gauravkumar <gaurav@drivetrain.ai> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
1 parent 53fc74e commit 3e4f8c8

4 files changed

Lines changed: 140 additions & 12 deletions

File tree

.changeset/slimy-taxes-make.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/eslint-plugin-query': patch
3+
---
4+
5+
exhaustive-deps rule fixed for vue files

packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,45 @@ ruleTester.run('exhaustive-deps', rule, {
548548
}
549549
`,
550550
},
551+
{
552+
name: 'should pass in Vue file when deps are correctly included (script setup)',
553+
filename: 'Component.vue',
554+
code: normalizeIndent`
555+
import { useQuery } from '@tanstack/vue-query'
556+
557+
const id = 1
558+
useQuery({
559+
queryKey: ['entity', id],
560+
queryFn: () => fetchEntity(id),
561+
})
562+
`,
563+
},
564+
{
565+
name: 'should not require imports in queryKey for Vue files',
566+
filename: 'Component.vue',
567+
code: normalizeIndent`
568+
import { useQuery } from '@tanstack/vue-query'
569+
import { fetchTodos } from './api'
570+
571+
useQuery({
572+
queryKey: ['todos'],
573+
queryFn: () => fetchTodos(),
574+
})
575+
`,
576+
},
577+
{
578+
name: 'should not require global fetch in queryKey for Vue files',
579+
filename: 'Component.vue',
580+
code: normalizeIndent`
581+
import { useQuery } from '@tanstack/vue-query'
582+
583+
const id = 1
584+
useQuery({
585+
queryKey: ['entity', id],
586+
queryFn: () => fetch('/api/entity/' + id),
587+
})
588+
`,
589+
},
551590
],
552591
invalid: [
553592
{
@@ -975,5 +1014,75 @@ ruleTester.run('exhaustive-deps', rule, {
9751014
},
9761015
],
9771016
},
1017+
{
1018+
name: 'should fail in Vue file when deps are missing (script setup)',
1019+
filename: 'Component.vue',
1020+
code: normalizeIndent`
1021+
import { useQuery } from '@tanstack/vue-query'
1022+
1023+
const id = 1
1024+
useQuery({
1025+
queryKey: ['entity'],
1026+
queryFn: () => fetchEntity(id),
1027+
})
1028+
`,
1029+
errors: [
1030+
{
1031+
messageId: 'missingDeps',
1032+
data: { deps: 'id' },
1033+
suggestions: [
1034+
{
1035+
messageId: 'fixTo',
1036+
data: { result: "['entity', id]" },
1037+
output: normalizeIndent`
1038+
import { useQuery } from '@tanstack/vue-query'
1039+
1040+
const id = 1
1041+
useQuery({
1042+
queryKey: ['entity', id],
1043+
queryFn: () => fetchEntity(id),
1044+
})
1045+
`,
1046+
},
1047+
],
1048+
},
1049+
],
1050+
},
1051+
{
1052+
name: 'should fail in Vue file when multiple deps are missing',
1053+
filename: 'Component.vue',
1054+
code: normalizeIndent`
1055+
import { useQuery } from '@tanstack/vue-query'
1056+
1057+
const userId = 1
1058+
const orgId = 2
1059+
useQuery({
1060+
queryKey: ['users'],
1061+
queryFn: () => fetchUser(userId, orgId),
1062+
})
1063+
`,
1064+
errors: [
1065+
{
1066+
messageId: 'missingDeps',
1067+
data: { deps: 'userId, orgId' },
1068+
suggestions: [
1069+
{
1070+
messageId: 'fixTo',
1071+
data: { result: "['users', userId, orgId]" },
1072+
output: normalizeIndent`
1073+
import { useQuery } from '@tanstack/vue-query'
1074+
1075+
const userId = 1
1076+
const orgId = 2
1077+
useQuery({
1078+
queryKey: ['users', userId, orgId],
1079+
queryFn: () => fetchUser(userId, orgId),
1080+
})
1081+
`,
1082+
},
1083+
],
1084+
},
1085+
],
1086+
},
9781087
],
9791088
})

packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export const rule = createRule({
8282
reference,
8383
scopeManager,
8484
node: getQueryFnRelevantNode(queryFn),
85+
filename: context.filename,
8586
}),
8687
)
8788

packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.utils.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,35 @@ export const ExhaustiveDepsUtils = {
88
reference: TSESLint.Scope.Reference
99
scopeManager: TSESLint.Scope.ScopeManager
1010
node: TSESTree.Node
11+
filename: string
1112
}) {
12-
const { sourceCode, reference, scopeManager, node } = params
13+
const { sourceCode, reference, scopeManager, node, filename } = params
1314
const component = ASTUtils.getFunctionAncestor(sourceCode, node)
1415

15-
if (component === undefined) {
16-
return false
17-
}
16+
if (component !== undefined) {
17+
if (
18+
!ASTUtils.isDeclaredInNode({
19+
scopeManager,
20+
reference,
21+
functionNode: component,
22+
})
23+
) {
24+
return false
25+
}
26+
} else {
27+
const isVueFile = filename.endsWith('.vue')
28+
29+
if (!isVueFile) {
30+
return false
31+
}
32+
33+
const definition = reference.resolved?.defs[0]
34+
const isGlobalVariable = definition === undefined
35+
const isImport = definition?.type === 'ImportBinding'
1836

19-
if (
20-
!ASTUtils.isDeclaredInNode({
21-
scopeManager,
22-
reference,
23-
functionNode: component,
24-
})
25-
) {
26-
return false
37+
if (isGlobalVariable || isImport) {
38+
return false
39+
}
2740
}
2841

2942
return (

0 commit comments

Comments
 (0)