@tanstack/eslint-plugin-query 5.59.7 → 5.60.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.rule.cjs +9 -2
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.rule.cjs.map +1 -1
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.rule.js +9 -2
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.rule.js.map +1 -1
- package/package.json +3 -2
- package/src/rules/no-rest-destructuring/no-rest-destructuring.rule.ts +12 -2
- package/src/__tests__/exhaustive-deps.test.ts +0 -859
- package/src/__tests__/infinite-query-property-order.rule.test.ts +0 -222
- package/src/__tests__/infinite-query-property-order.utils.test.ts +0 -79
- package/src/__tests__/no-rest-destructuring.test.ts +0 -192
- package/src/__tests__/no-unstable-deps.test.ts +0 -129
- package/src/__tests__/stable-query-client.test.ts +0 -192
- package/src/__tests__/test-utils.test.ts +0 -104
- package/src/__tests__/test-utils.ts +0 -108
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import { RuleTester } from '@typescript-eslint/rule-tester'
|
|
2
|
-
import combinate from 'combinate'
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
checkedProperties,
|
|
6
|
-
infiniteQueryFunctions,
|
|
7
|
-
} from '../rules/infinite-query-property-order/constants'
|
|
8
|
-
import {
|
|
9
|
-
name,
|
|
10
|
-
rule,
|
|
11
|
-
} from '../rules/infinite-query-property-order/infinite-query-property-order.rule'
|
|
12
|
-
import {
|
|
13
|
-
generateInterleavedCombinations,
|
|
14
|
-
generatePartialCombinations,
|
|
15
|
-
generatePermutations,
|
|
16
|
-
normalizeIndent,
|
|
17
|
-
} from './test-utils'
|
|
18
|
-
import type { InfiniteQueryFunctions } from '../rules/infinite-query-property-order/constants'
|
|
19
|
-
|
|
20
|
-
const ruleTester = new RuleTester()
|
|
21
|
-
|
|
22
|
-
type CheckedProperties = (typeof checkedProperties)[number]
|
|
23
|
-
const orderIndependentProps = [
|
|
24
|
-
'queryKey',
|
|
25
|
-
'...objectExpressionSpread',
|
|
26
|
-
'...callExpressionSpread',
|
|
27
|
-
'...memberCallExpressionSpread',
|
|
28
|
-
] as const
|
|
29
|
-
type OrderIndependentProps = (typeof orderIndependentProps)[number]
|
|
30
|
-
|
|
31
|
-
interface TestCase {
|
|
32
|
-
infiniteQueryFunction: InfiniteQueryFunctions
|
|
33
|
-
properties: Array<CheckedProperties | OrderIndependentProps>
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const validTestMatrix = combinate({
|
|
37
|
-
infiniteQueryFunction: [...infiniteQueryFunctions],
|
|
38
|
-
properties: generatePartialCombinations(checkedProperties, 2),
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
export function generateInvalidPermutations(
|
|
42
|
-
arr: ReadonlyArray<CheckedProperties>,
|
|
43
|
-
): Array<{
|
|
44
|
-
invalid: Array<CheckedProperties>
|
|
45
|
-
valid: Array<CheckedProperties>
|
|
46
|
-
}> {
|
|
47
|
-
const combinations = generatePartialCombinations(arr, 2)
|
|
48
|
-
const allPermutations: Array<{
|
|
49
|
-
invalid: Array<CheckedProperties>
|
|
50
|
-
valid: Array<CheckedProperties>
|
|
51
|
-
}> = []
|
|
52
|
-
|
|
53
|
-
for (const combination of combinations) {
|
|
54
|
-
const permutations = generatePermutations(combination)
|
|
55
|
-
// skip the first permutation as it matches the original combination
|
|
56
|
-
const invalidPermutations = permutations.slice(1)
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
combination.includes('getNextPageParam') &&
|
|
60
|
-
combination.includes('getPreviousPageParam')
|
|
61
|
-
) {
|
|
62
|
-
if (
|
|
63
|
-
combination.indexOf('getNextPageParam') <
|
|
64
|
-
combination.indexOf('getPreviousPageParam')
|
|
65
|
-
) {
|
|
66
|
-
// since we ignore the relative order of 'getPreviousPageParam' and 'getNextPageParam', we skip this combination (but keep the other one where `getPreviousPageParam` is before `getNextPageParam`)
|
|
67
|
-
|
|
68
|
-
continue
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
allPermutations.push(
|
|
73
|
-
...invalidPermutations
|
|
74
|
-
.map((p) => {
|
|
75
|
-
// ignore the relative order of 'getPreviousPageParam' and 'getNextPageParam'
|
|
76
|
-
const correctedValid = [...combination].sort((a, b) => {
|
|
77
|
-
if (
|
|
78
|
-
(a === 'getNextPageParam' && b === 'getPreviousPageParam') ||
|
|
79
|
-
(a === 'getPreviousPageParam' && b === 'getNextPageParam')
|
|
80
|
-
) {
|
|
81
|
-
return p.indexOf(a) - p.indexOf(b)
|
|
82
|
-
}
|
|
83
|
-
return checkedProperties.indexOf(a) - checkedProperties.indexOf(b)
|
|
84
|
-
})
|
|
85
|
-
return { invalid: p, valid: correctedValid }
|
|
86
|
-
})
|
|
87
|
-
.filter(
|
|
88
|
-
({ invalid }) =>
|
|
89
|
-
// if `getPreviousPageParam` and `getNextPageParam` are next to each other and `queryFn` is not present, we skip this invalid permutation
|
|
90
|
-
Math.abs(
|
|
91
|
-
invalid.indexOf('getNextPageParam') -
|
|
92
|
-
invalid.indexOf('getPreviousPageParam'),
|
|
93
|
-
) !== 1,
|
|
94
|
-
),
|
|
95
|
-
)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return allPermutations
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const invalidPermutations = generateInvalidPermutations(checkedProperties)
|
|
102
|
-
|
|
103
|
-
type Interleaved = CheckedProperties | OrderIndependentProps
|
|
104
|
-
const interleavedInvalidPermutations: Array<{
|
|
105
|
-
invalid: Array<Interleaved>
|
|
106
|
-
valid: Array<Interleaved>
|
|
107
|
-
}> = []
|
|
108
|
-
for (const invalidPermutation of invalidPermutations) {
|
|
109
|
-
const invalid = generateInterleavedCombinations(
|
|
110
|
-
invalidPermutation.invalid,
|
|
111
|
-
orderIndependentProps,
|
|
112
|
-
)
|
|
113
|
-
const valid = generateInterleavedCombinations(
|
|
114
|
-
invalidPermutation.valid,
|
|
115
|
-
orderIndependentProps,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
for (let i = 0; i < invalid.length; i++) {
|
|
119
|
-
interleavedInvalidPermutations.push({
|
|
120
|
-
invalid: invalid[i]!,
|
|
121
|
-
valid: valid[i]!,
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const invalidTestMatrix = combinate({
|
|
127
|
-
infiniteQueryFunction: [...infiniteQueryFunctions],
|
|
128
|
-
properties: interleavedInvalidPermutations,
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
const callExpressionSpread = normalizeIndent`
|
|
132
|
-
...communitiesQuery({
|
|
133
|
-
filters: {
|
|
134
|
-
...fieldValues,
|
|
135
|
-
placementFormats: [],
|
|
136
|
-
},
|
|
137
|
-
})`
|
|
138
|
-
|
|
139
|
-
function getCode({
|
|
140
|
-
infiniteQueryFunction: infiniteQueryFunction,
|
|
141
|
-
properties,
|
|
142
|
-
}: TestCase) {
|
|
143
|
-
function getPropertyCode(
|
|
144
|
-
property: CheckedProperties | OrderIndependentProps,
|
|
145
|
-
) {
|
|
146
|
-
switch (property) {
|
|
147
|
-
case '...objectExpressionSpread':
|
|
148
|
-
return `...objectExpressionSpread`
|
|
149
|
-
case '...callExpressionSpread':
|
|
150
|
-
return callExpressionSpread
|
|
151
|
-
case '...memberCallExpressionSpread':
|
|
152
|
-
return '...myOptions.infiniteQueryOptions()'
|
|
153
|
-
case 'queryKey':
|
|
154
|
-
return `queryKey: ['projects']`
|
|
155
|
-
case 'queryFn':
|
|
156
|
-
return 'queryFn: async ({ pageParam }) => { \n await fetch(`/api/projects?cursor=${pageParam}`) \n return await response.json() \n }'
|
|
157
|
-
case 'getPreviousPageParam':
|
|
158
|
-
return 'getPreviousPageParam: (firstPage) => firstPage.previousId ?? undefined'
|
|
159
|
-
case 'getNextPageParam':
|
|
160
|
-
return 'getNextPageParam: (lastPage) => lastPage.nextId ?? undefined'
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return `
|
|
164
|
-
import { ${infiniteQueryFunction} } from '@tanstack/react-query'
|
|
165
|
-
|
|
166
|
-
${infiniteQueryFunction}({
|
|
167
|
-
${properties.map(getPropertyCode).join(',\n ')}
|
|
168
|
-
})
|
|
169
|
-
`
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const validTestCases = validTestMatrix.map(
|
|
173
|
-
({ infiniteQueryFunction, properties }) => ({
|
|
174
|
-
name: `should pass when order is correct for ${infiniteQueryFunction} with order: ${properties.join(', ')}`,
|
|
175
|
-
code: getCode({ infiniteQueryFunction, properties }),
|
|
176
|
-
}),
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
const invalidTestCases = invalidTestMatrix.map(
|
|
180
|
-
({ infiniteQueryFunction, properties }) => ({
|
|
181
|
-
name: `incorrect property order is detected for ${infiniteQueryFunction} with invalid order: ${properties.invalid.join(', ')}, valid order: ${properties.valid.join(', ')}`,
|
|
182
|
-
code: getCode({
|
|
183
|
-
infiniteQueryFunction: infiniteQueryFunction,
|
|
184
|
-
properties: properties.invalid,
|
|
185
|
-
}),
|
|
186
|
-
errors: [{ messageId: 'invalidOrder' }],
|
|
187
|
-
output: getCode({
|
|
188
|
-
infiniteQueryFunction: infiniteQueryFunction,
|
|
189
|
-
properties: properties.valid,
|
|
190
|
-
}),
|
|
191
|
-
}),
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
ruleTester.run(name, rule, {
|
|
195
|
-
valid: validTestCases,
|
|
196
|
-
invalid: invalidTestCases,
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
// regression tests
|
|
200
|
-
|
|
201
|
-
const regressionTestCases = {
|
|
202
|
-
valid: [
|
|
203
|
-
{
|
|
204
|
-
name: 'should pass with call expression spread',
|
|
205
|
-
code: normalizeIndent`
|
|
206
|
-
import { useInfiniteQuery } from '@tanstack/react-query'
|
|
207
|
-
const { data, isFetching, isLoading, hasNextPage, fetchNextPage } =
|
|
208
|
-
useInfiniteQuery({
|
|
209
|
-
...communitiesQuery({
|
|
210
|
-
filters: {
|
|
211
|
-
...fieldValues,
|
|
212
|
-
placementFormats: [],
|
|
213
|
-
},
|
|
214
|
-
}),
|
|
215
|
-
refetchOnMount: false,
|
|
216
|
-
})`,
|
|
217
|
-
},
|
|
218
|
-
],
|
|
219
|
-
invalid: [],
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
ruleTester.run(name, rule, regressionTestCases)
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from 'vitest'
|
|
2
|
-
import { sortDataByOrder } from '../rules/infinite-query-property-order/infinite-query-property-order.utils'
|
|
3
|
-
|
|
4
|
-
describe('create-route-property-order utils', () => {
|
|
5
|
-
describe('sortDataByOrder', () => {
|
|
6
|
-
const testCases = [
|
|
7
|
-
{
|
|
8
|
-
data: [{ key: 'a' }, { key: 'c' }, { key: 'b' }],
|
|
9
|
-
orderArray: [
|
|
10
|
-
[['a'], ['b']],
|
|
11
|
-
[['b'], ['c']],
|
|
12
|
-
],
|
|
13
|
-
key: 'key',
|
|
14
|
-
expected: [{ key: 'a' }, { key: 'b' }, { key: 'c' }],
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
data: [{ key: 'b' }, { key: 'a' }, { key: 'c' }],
|
|
18
|
-
orderArray: [
|
|
19
|
-
[['a'], ['b']],
|
|
20
|
-
[['b'], ['c']],
|
|
21
|
-
],
|
|
22
|
-
key: 'key',
|
|
23
|
-
expected: [{ key: 'a' }, { key: 'b' }, { key: 'c' }],
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
data: [{ key: 'a' }, { key: 'b' }, { key: 'c' }],
|
|
27
|
-
orderArray: [
|
|
28
|
-
[['a'], ['b']],
|
|
29
|
-
[['b'], ['c']],
|
|
30
|
-
],
|
|
31
|
-
key: 'key',
|
|
32
|
-
expected: null,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
data: [{ key: 'a' }, { key: 'b' }, { key: 'c' }, { key: 'd' }],
|
|
36
|
-
orderArray: [
|
|
37
|
-
[['a'], ['b']],
|
|
38
|
-
[['b'], ['c']],
|
|
39
|
-
],
|
|
40
|
-
key: 'key',
|
|
41
|
-
expected: null,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
data: [{ key: 'a' }, { key: 'b' }, { key: 'd' }, { key: 'c' }],
|
|
45
|
-
orderArray: [
|
|
46
|
-
[['a'], ['b']],
|
|
47
|
-
[['b'], ['c']],
|
|
48
|
-
],
|
|
49
|
-
key: 'key',
|
|
50
|
-
expected: null,
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
data: [{ key: 'd' }, { key: 'a' }, { key: 'b' }, { key: 'c' }],
|
|
54
|
-
orderArray: [
|
|
55
|
-
[['a'], ['b']],
|
|
56
|
-
[['b'], ['c']],
|
|
57
|
-
],
|
|
58
|
-
key: 'key',
|
|
59
|
-
expected: null,
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
data: [{ key: 'd' }, { key: 'b' }, { key: 'a' }, { key: 'c' }],
|
|
63
|
-
orderArray: [
|
|
64
|
-
[['a'], ['b']],
|
|
65
|
-
[['b'], ['c']],
|
|
66
|
-
],
|
|
67
|
-
key: 'key',
|
|
68
|
-
expected: [{ key: 'd' }, { key: 'a' }, { key: 'b' }, { key: 'c' }],
|
|
69
|
-
},
|
|
70
|
-
] as const
|
|
71
|
-
test.each(testCases)(
|
|
72
|
-
'$data $orderArray $key $expected',
|
|
73
|
-
({ data, orderArray, key, expected }) => {
|
|
74
|
-
const sortedData = sortDataByOrder(data, orderArray, key)
|
|
75
|
-
expect(sortedData).toEqual(expected)
|
|
76
|
-
},
|
|
77
|
-
)
|
|
78
|
-
})
|
|
79
|
-
})
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { RuleTester } from '@typescript-eslint/rule-tester'
|
|
2
|
-
import { rule } from '../rules/no-rest-destructuring/no-rest-destructuring.rule'
|
|
3
|
-
import { normalizeIndent } from './test-utils'
|
|
4
|
-
|
|
5
|
-
const ruleTester = new RuleTester()
|
|
6
|
-
|
|
7
|
-
ruleTester.run('no-rest-destructuring', rule, {
|
|
8
|
-
valid: [
|
|
9
|
-
{
|
|
10
|
-
name: 'useQuery is not captured',
|
|
11
|
-
code: normalizeIndent`
|
|
12
|
-
import { useQuery } from '@tanstack/react-query'
|
|
13
|
-
|
|
14
|
-
function Component() {
|
|
15
|
-
useQuery()
|
|
16
|
-
return
|
|
17
|
-
}
|
|
18
|
-
`,
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
name: 'useQuery is not destructured',
|
|
22
|
-
code: normalizeIndent`
|
|
23
|
-
import { useQuery } from '@tanstack/react-query'
|
|
24
|
-
|
|
25
|
-
function Component() {
|
|
26
|
-
const query = useQuery()
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
`,
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
name: 'useQuery is destructured without rest',
|
|
33
|
-
code: normalizeIndent`
|
|
34
|
-
import { useQuery } from '@tanstack/react-query'
|
|
35
|
-
|
|
36
|
-
function Component() {
|
|
37
|
-
const { data, isLoading, isError } = useQuery()
|
|
38
|
-
return
|
|
39
|
-
}
|
|
40
|
-
`,
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: 'useInfiniteQuery is not captured',
|
|
44
|
-
code: normalizeIndent`
|
|
45
|
-
import { useInfiniteQuery } from '@tanstack/react-query'
|
|
46
|
-
|
|
47
|
-
function Component() {
|
|
48
|
-
useInfiniteQuery()
|
|
49
|
-
return
|
|
50
|
-
}
|
|
51
|
-
`,
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: 'useInfiniteQuery is not destructured',
|
|
55
|
-
code: normalizeIndent`
|
|
56
|
-
import { useInfiniteQuery } from '@tanstack/react-query'
|
|
57
|
-
|
|
58
|
-
function Component() {
|
|
59
|
-
const query = useInfiniteQuery()
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
`,
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'useInfiniteQuery is destructured without rest',
|
|
66
|
-
code: normalizeIndent`
|
|
67
|
-
import { useInfiniteQuery } from '@tanstack/react-query'
|
|
68
|
-
|
|
69
|
-
function Component() {
|
|
70
|
-
const { data, isLoading, isError } = useInfiniteQuery()
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
`,
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: 'useQueries is not captured',
|
|
77
|
-
code: normalizeIndent`
|
|
78
|
-
import { useQueries } from '@tanstack/react-query'
|
|
79
|
-
|
|
80
|
-
function Component() {
|
|
81
|
-
useQueries([])
|
|
82
|
-
return
|
|
83
|
-
}
|
|
84
|
-
`,
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
name: 'useQueries is not destructured',
|
|
88
|
-
code: normalizeIndent`
|
|
89
|
-
import { useQueries } from '@tanstack/react-query'
|
|
90
|
-
|
|
91
|
-
function Component() {
|
|
92
|
-
const queries = useQueries([])
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
`,
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
name: 'useQueries array has no rest destructured element',
|
|
99
|
-
code: normalizeIndent`
|
|
100
|
-
import { useQueries } from '@tanstack/react-query'
|
|
101
|
-
|
|
102
|
-
function Component() {
|
|
103
|
-
const [query1, { data, isLoading },, ...others] = useQueries([
|
|
104
|
-
{ queryKey: ['key1'], queryFn: () => {} },
|
|
105
|
-
{ queryKey: ['key2'], queryFn: () => {} },
|
|
106
|
-
{ queryKey: ['key3'], queryFn: () => {} },
|
|
107
|
-
{ queryKey: ['key4'], queryFn: () => {} },
|
|
108
|
-
{ queryKey: ['key5'], queryFn: () => {} },
|
|
109
|
-
])
|
|
110
|
-
return
|
|
111
|
-
}
|
|
112
|
-
`,
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
name: 'useQuery is destructured with rest but not from tanstack query',
|
|
116
|
-
code: normalizeIndent`
|
|
117
|
-
import { useQuery } from 'other-package'
|
|
118
|
-
|
|
119
|
-
function Component() {
|
|
120
|
-
const { data, ...rest } = useQuery()
|
|
121
|
-
return
|
|
122
|
-
}
|
|
123
|
-
`,
|
|
124
|
-
},
|
|
125
|
-
{
|
|
126
|
-
name: 'useInfiniteQuery is destructured with rest but not from tanstack query',
|
|
127
|
-
code: normalizeIndent`
|
|
128
|
-
import { useInfiniteQuery } from 'other-package'
|
|
129
|
-
|
|
130
|
-
function Component() {
|
|
131
|
-
const { data, ...rest } = useInfiniteQuery()
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
`,
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
name: 'useQueries array has rest destructured element but not from tanstack query',
|
|
138
|
-
code: normalizeIndent`
|
|
139
|
-
import { useQueries } from 'other-package'
|
|
140
|
-
|
|
141
|
-
function Component() {
|
|
142
|
-
const [query1, { data, ...rest }] = useQueries([
|
|
143
|
-
{ queryKey: ['key1'], queryFn: () => {} },
|
|
144
|
-
{ queryKey: ['key2'], queryFn: () => {} },
|
|
145
|
-
])
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
`,
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
invalid: [
|
|
152
|
-
{
|
|
153
|
-
name: 'useQuery is destructured with rest',
|
|
154
|
-
code: normalizeIndent`
|
|
155
|
-
import { useQuery } from '@tanstack/react-query'
|
|
156
|
-
|
|
157
|
-
function Component() {
|
|
158
|
-
const { data, ...rest } = useQuery()
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
`,
|
|
162
|
-
errors: [{ messageId: 'objectRestDestructure' }],
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
name: 'useInfiniteQuery is destructured with rest',
|
|
166
|
-
code: normalizeIndent`
|
|
167
|
-
import { useInfiniteQuery } from '@tanstack/react-query'
|
|
168
|
-
|
|
169
|
-
function Component() {
|
|
170
|
-
const { data, ...rest } = useInfiniteQuery()
|
|
171
|
-
return
|
|
172
|
-
}
|
|
173
|
-
`,
|
|
174
|
-
errors: [{ messageId: 'objectRestDestructure' }],
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
name: 'useQueries array has rest destructured element',
|
|
178
|
-
code: normalizeIndent`
|
|
179
|
-
import { useQueries } from '@tanstack/react-query'
|
|
180
|
-
|
|
181
|
-
function Component() {
|
|
182
|
-
const [query1, { data, ...rest }] = useQueries([
|
|
183
|
-
{ queryKey: ['key1'], queryFn: () => {} },
|
|
184
|
-
{ queryKey: ['key2'], queryFn: () => {} },
|
|
185
|
-
])
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
`,
|
|
189
|
-
errors: [{ messageId: 'objectRestDestructure' }],
|
|
190
|
-
},
|
|
191
|
-
],
|
|
192
|
-
})
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { RuleTester } from '@typescript-eslint/rule-tester'
|
|
2
|
-
import {
|
|
3
|
-
reactHookNames,
|
|
4
|
-
rule,
|
|
5
|
-
useQueryHookNames,
|
|
6
|
-
} from '../rules/no-unstable-deps/no-unstable-deps.rule'
|
|
7
|
-
|
|
8
|
-
const ruleTester = new RuleTester()
|
|
9
|
-
|
|
10
|
-
interface TestCase {
|
|
11
|
-
reactHookImport: string
|
|
12
|
-
reactHookInvocation: string
|
|
13
|
-
reactHookAlias: string
|
|
14
|
-
}
|
|
15
|
-
const baseTestCases = {
|
|
16
|
-
valid: ({ reactHookImport, reactHookInvocation, reactHookAlias }: TestCase) =>
|
|
17
|
-
[
|
|
18
|
-
{
|
|
19
|
-
name: `should pass when destructured mutate is passed to ${reactHookAlias} as dependency`,
|
|
20
|
-
code: `
|
|
21
|
-
${reactHookImport}
|
|
22
|
-
import { useMutation } from "@tanstack/react-query";
|
|
23
|
-
|
|
24
|
-
function Component() {
|
|
25
|
-
const { mutate } = useMutation({ mutationFn: (value: string) => value });
|
|
26
|
-
const callback = ${reactHookInvocation}(() => { mutate('hello') }, [mutate]);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
`,
|
|
30
|
-
},
|
|
31
|
-
].concat(
|
|
32
|
-
useQueryHookNames.map((queryHook) => ({
|
|
33
|
-
name: `should pass result of ${queryHook} is passed to ${reactHookInvocation} as dependency`,
|
|
34
|
-
code: `
|
|
35
|
-
${reactHookImport}
|
|
36
|
-
import { ${queryHook} } from "@tanstack/react-query";
|
|
37
|
-
|
|
38
|
-
function Component() {
|
|
39
|
-
const { refetch } = ${queryHook}({ queryFn: (value: string) => value });
|
|
40
|
-
const callback = ${reactHookInvocation}(() => { query.refetch() }, [refetch]);
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
`,
|
|
44
|
-
})),
|
|
45
|
-
),
|
|
46
|
-
invalid: ({
|
|
47
|
-
reactHookImport,
|
|
48
|
-
reactHookInvocation,
|
|
49
|
-
reactHookAlias,
|
|
50
|
-
}: TestCase) =>
|
|
51
|
-
[
|
|
52
|
-
{
|
|
53
|
-
name: `result of useMutation is passed to ${reactHookInvocation} as dependency `,
|
|
54
|
-
code: `
|
|
55
|
-
${reactHookImport}
|
|
56
|
-
import { useMutation } from "@tanstack/react-query";
|
|
57
|
-
|
|
58
|
-
function Component() {
|
|
59
|
-
const mutation = useMutation({ mutationFn: (value: string) => value });
|
|
60
|
-
const callback = ${reactHookInvocation}(() => { mutation.mutate('hello') }, [mutation]);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
`,
|
|
64
|
-
errors: [
|
|
65
|
-
{
|
|
66
|
-
messageId: 'noUnstableDeps',
|
|
67
|
-
data: { reactHook: reactHookAlias, queryHook: 'useMutation' },
|
|
68
|
-
},
|
|
69
|
-
],
|
|
70
|
-
},
|
|
71
|
-
].concat(
|
|
72
|
-
useQueryHookNames.map((queryHook) => ({
|
|
73
|
-
name: `result of ${queryHook} is passed to ${reactHookInvocation} as dependency`,
|
|
74
|
-
code: `
|
|
75
|
-
${reactHookImport}
|
|
76
|
-
import { ${queryHook} } from "@tanstack/react-query";
|
|
77
|
-
|
|
78
|
-
function Component() {
|
|
79
|
-
const query = ${queryHook}({ queryFn: (value: string) => value });
|
|
80
|
-
const callback = ${reactHookInvocation}(() => { query.refetch() }, [query]);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
`,
|
|
84
|
-
errors: [
|
|
85
|
-
{
|
|
86
|
-
messageId: 'noUnstableDeps',
|
|
87
|
-
data: { reactHook: reactHookAlias, queryHook },
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
})),
|
|
91
|
-
),
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const testCases = (reactHookName: string) => [
|
|
95
|
-
{
|
|
96
|
-
reactHookImport: 'import * as React from "React";',
|
|
97
|
-
reactHookInvocation: `React.${reactHookName}`,
|
|
98
|
-
reactHookAlias: reactHookName,
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
reactHookImport: `import { ${reactHookName} } from "React";`,
|
|
102
|
-
reactHookInvocation: reactHookName,
|
|
103
|
-
reactHookAlias: reactHookName,
|
|
104
|
-
},
|
|
105
|
-
{
|
|
106
|
-
reactHookImport: `import { ${reactHookName} as useAlias } from "React";`,
|
|
107
|
-
reactHookInvocation: 'useAlias',
|
|
108
|
-
reactHookAlias: 'useAlias',
|
|
109
|
-
},
|
|
110
|
-
]
|
|
111
|
-
|
|
112
|
-
reactHookNames.forEach((reactHookName) => {
|
|
113
|
-
testCases(reactHookName).forEach(
|
|
114
|
-
({ reactHookInvocation, reactHookAlias, reactHookImport }) => {
|
|
115
|
-
ruleTester.run('no-unstable-deps', rule, {
|
|
116
|
-
valid: baseTestCases.valid({
|
|
117
|
-
reactHookImport,
|
|
118
|
-
reactHookInvocation,
|
|
119
|
-
reactHookAlias,
|
|
120
|
-
}),
|
|
121
|
-
invalid: baseTestCases.invalid({
|
|
122
|
-
reactHookImport,
|
|
123
|
-
reactHookInvocation,
|
|
124
|
-
reactHookAlias,
|
|
125
|
-
}),
|
|
126
|
-
})
|
|
127
|
-
},
|
|
128
|
-
)
|
|
129
|
-
})
|