Skip to content

Commit c1e67ed

Browse files
Merge branch 'main' into svelte-5-adapter
2 parents 62be7d5 + 4f4866e commit c1e67ed

File tree

9 files changed

+113
-25
lines changed

9 files changed

+113
-25
lines changed

.github/workflows/release.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ jobs:
3636
run: npx nx-cloud stop-all-agents
3737
- name: Version Packages
3838
run: pnpm run changeset:version
39+
env:
40+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3941
- name: Commit version files
4042
run: |
4143
if [[ -n "$(git status --porcelain)" ]]; then
@@ -48,7 +50,9 @@ jobs:
4850
env:
4951
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5052
- name: Publish Packages
51-
run: pnpm run changeset:publish
53+
run: |
54+
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
55+
pnpm run changeset:publish
5256
env:
5357
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
5458
- name: Upload coverage to Codecov

examples/react/algolia/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"react-dom": "^19.0.0"
1616
},
1717
"devDependencies": {
18-
"@tanstack/eslint-plugin-query": "^5.90.1",
18+
"@tanstack/eslint-plugin-query": "^5.90.2",
1919
"@types/react": "^18.2.79",
2020
"@types/react-dom": "^18.2.25",
2121
"@vitejs/plugin-react": "^4.3.4",

examples/react/basic/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"react-dom": "^19.0.0"
1818
},
1919
"devDependencies": {
20-
"@tanstack/eslint-plugin-query": "^5.90.1",
20+
"@tanstack/eslint-plugin-query": "^5.90.2",
2121
"@types/react": "^18.2.79",
2222
"@types/react-dom": "^18.2.25",
2323
"@vitejs/plugin-react": "^4.3.4",

examples/react/eslint-legacy/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"react-dom": "^19.0.0"
1818
},
1919
"devDependencies": {
20-
"@tanstack/eslint-plugin-query": "^5.90.1",
20+
"@tanstack/eslint-plugin-query": "^5.90.2",
2121
"@types/react": "^18.2.79",
2222
"@types/react-dom": "^18.2.25",
2323
"@vitejs/plugin-react": "^4.3.4",

examples/solid/simple/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"solid-js": "^1.9.7"
1414
},
1515
"devDependencies": {
16-
"@tanstack/eslint-plugin-query": "^5.90.1",
16+
"@tanstack/eslint-plugin-query": "^5.90.2",
1717
"typescript": "5.8.3",
1818
"vite": "^6.3.6",
1919
"vite-plugin-solid": "^2.11.6"
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# @tanstack/eslint-plugin-query
2+
3+
## 5.90.2
4+
5+
### Patch Changes
6+
7+
- fix: exhaustive-deps with variables and type assertions ([#9687](https://github.com/TanStack/query/pull/9687))

packages/eslint-plugin-query/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tanstack/eslint-plugin-query",
3-
"version": "5.90.1",
3+
"version": "5.90.2",
44
"description": "ESLint plugin for TanStack Query",
55
"author": "Eliya Cohen",
66
"license": "MIT",

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,39 @@ ruleTester.run('exhaustive-deps', rule, {
226226
})
227227
`,
228228
},
229+
{
230+
name: 'should pass with queryKeyFactory result assigned to a variable',
231+
code: `
232+
function fooQueryKeyFactory(dep: string) {
233+
return ["foo", dep];
234+
}
235+
236+
const useFoo = (dep: string) => {
237+
const queryKey = fooQueryKeyFactory(dep);
238+
return useQuery({
239+
queryKey,
240+
queryFn: () => Promise.resolve(dep),
241+
})
242+
}
243+
`,
244+
},
245+
{
246+
name: 'should pass with queryKeyFactory result assigned to a variable 2',
247+
code: `
248+
function fooQueryKeyFactory(dep: string) {
249+
const x = ["foo", dep] as const;
250+
return x as const;
251+
}
252+
253+
const useFoo = (dep: string) => {
254+
const queryKey = fooQueryKeyFactory(dep);
255+
return useQuery({
256+
queryKey,
257+
queryFn: () => Promise.resolve(dep),
258+
})
259+
}
260+
`,
261+
},
229262
{
230263
name: 'should not treat new Error as missing dependency',
231264
code: normalizeIndent`
@@ -246,6 +279,30 @@ ruleTester.run('exhaustive-deps', rule, {
246279
}
247280
`,
248281
},
282+
{
283+
name: 'should see id when there is a const assertion of a variable dereference',
284+
code: normalizeIndent`
285+
const useX = (id: number) => {
286+
const queryKey = ['foo', id]
287+
return useQuery({
288+
queryKey: queryKey as const,
289+
queryFn: async () => id,
290+
})
291+
}
292+
`,
293+
},
294+
{
295+
name: 'should see id when there is a const assertion assigned to a variable',
296+
code: normalizeIndent`
297+
const useX = (id: number) => {
298+
const queryKey = ['foo', id] as const
299+
return useQuery({
300+
queryKey,
301+
queryFn: async () => id,
302+
})
303+
}
304+
`,
305+
},
249306
{
250307
name: 'should not fail if queryKey is having the whole object while queryFn uses some props of it',
251308
code: normalizeIndent`

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

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -65,25 +65,10 @@ export const rule = createRule({
6565
return
6666
}
6767

68-
let queryKeyNode = queryKey.value
69-
70-
if (
71-
queryKeyNode.type === AST_NODE_TYPES.TSAsExpression &&
72-
queryKeyNode.expression.type === AST_NODE_TYPES.ArrayExpression
73-
) {
74-
queryKeyNode = queryKeyNode.expression
75-
}
76-
77-
if (queryKeyNode.type === AST_NODE_TYPES.Identifier) {
78-
const expression = ASTUtils.getReferencedExpressionByIdentifier({
79-
context,
80-
node: queryKeyNode,
81-
})
82-
83-
if (expression?.type === AST_NODE_TYPES.ArrayExpression) {
84-
queryKeyNode = expression
85-
}
86-
}
68+
const queryKeyNode = dereferenceVariablesAndTypeAssertions(
69+
queryKey.value,
70+
context,
71+
)
8772

8873
const externalRefs = ASTUtils.getExternalRefs({
8974
scopeManager,
@@ -182,3 +167,38 @@ function getQueryFnRelevantNode(queryFn: TSESTree.Property) {
182167

183168
return queryFn.value.consequent
184169
}
170+
171+
function dereferenceVariablesAndTypeAssertions(
172+
queryKeyNode: TSESTree.Node,
173+
context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>,
174+
) {
175+
const visitedNodes = new Set<TSESTree.Node>()
176+
177+
for (let i = 0; i < 1 << 8; ++i) {
178+
if (visitedNodes.has(queryKeyNode)) {
179+
return queryKeyNode
180+
}
181+
visitedNodes.add(queryKeyNode)
182+
183+
switch (queryKeyNode.type) {
184+
case AST_NODE_TYPES.TSAsExpression:
185+
queryKeyNode = queryKeyNode.expression
186+
break
187+
case AST_NODE_TYPES.Identifier: {
188+
const expression = ASTUtils.getReferencedExpressionByIdentifier({
189+
context,
190+
node: queryKeyNode,
191+
})
192+
193+
if (expression == null) {
194+
return queryKeyNode
195+
}
196+
queryKeyNode = expression
197+
break
198+
}
199+
default:
200+
return queryKeyNode
201+
}
202+
}
203+
return queryKeyNode
204+
}

0 commit comments

Comments
 (0)