@tanstack/eslint-plugin-query 5.53.0 → 5.57.0
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/index.cjs +4 -2
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +0 -1
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.rule.d.cts +0 -1
- package/dist/cjs/rules/exhaustive-deps/exhaustive-deps.utils.d.cts +0 -1
- package/dist/cjs/rules/infinite-query-property-order/constants.cjs +15 -0
- package/dist/cjs/rules/infinite-query-property-order/constants.cjs.map +1 -0
- package/dist/cjs/rules/infinite-query-property-order/constants.d.cts +3 -0
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.rule.cjs +99 -0
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.rule.cjs.map +1 -0
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.rule.d.cts +4 -0
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.utils.cjs +28 -0
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.utils.cjs.map +1 -0
- package/dist/cjs/rules/infinite-query-property-order/infinite-query-property-order.utils.d.cts +1 -0
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.rule.d.cts +0 -1
- package/dist/cjs/rules/no-rest-destructuring/no-rest-destructuring.utils.d.cts +0 -1
- package/dist/cjs/rules/no-unstable-deps/no-unstable-deps.rule.cjs +1 -1
- package/dist/cjs/rules/no-unstable-deps/no-unstable-deps.rule.cjs.map +1 -1
- package/dist/cjs/rules/no-unstable-deps/no-unstable-deps.rule.d.cts +0 -1
- package/dist/cjs/rules/stable-query-client/stable-query-client.rule.d.cts +0 -1
- package/dist/cjs/rules.cjs +3 -1
- package/dist/cjs/rules.cjs.map +1 -1
- package/dist/cjs/rules.d.cts +0 -1
- package/dist/cjs/utils/ast-utils.d.cts +0 -1
- package/dist/cjs/utils/detect-react-query-imports.d.cts +0 -1
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.js +4 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.rule.d.ts +0 -1
- package/dist/esm/rules/exhaustive-deps/exhaustive-deps.utils.d.ts +0 -1
- package/dist/esm/rules/infinite-query-property-order/constants.d.ts +3 -0
- package/dist/esm/rules/infinite-query-property-order/constants.js +15 -0
- package/dist/esm/rules/infinite-query-property-order/constants.js.map +1 -0
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.d.ts +4 -0
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.js +99 -0
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.rule.js.map +1 -0
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.d.ts +1 -0
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.js +28 -0
- package/dist/esm/rules/infinite-query-property-order/infinite-query-property-order.utils.js.map +1 -0
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.rule.d.ts +0 -1
- package/dist/esm/rules/no-rest-destructuring/no-rest-destructuring.utils.d.ts +0 -1
- package/dist/esm/rules/no-unstable-deps/no-unstable-deps.rule.d.ts +0 -1
- package/dist/esm/rules/no-unstable-deps/no-unstable-deps.rule.js +1 -1
- package/dist/esm/rules/no-unstable-deps/no-unstable-deps.rule.js.map +1 -1
- package/dist/esm/rules/stable-query-client/stable-query-client.rule.d.ts +0 -1
- package/dist/esm/rules.d.ts +0 -1
- package/dist/esm/rules.js +3 -1
- package/dist/esm/rules.js.map +1 -1
- package/dist/esm/utils/ast-utils.d.ts +0 -1
- package/dist/esm/utils/detect-react-query-imports.d.ts +0 -1
- package/package.json +2 -1
- package/src/__tests__/infinite-query-property-order.rule.test.ts +140 -0
- package/src/__tests__/infinite-query-property-order.utils.test.ts +58 -0
- package/src/__tests__/test-utils.test.ts +104 -0
- package/src/__tests__/test-utils.ts +103 -0
- package/src/index.ts +2 -0
- package/src/rules/infinite-query-property-order/constants.ts +13 -0
- package/src/rules/infinite-query-property-order/infinite-query-property-order.rule.ts +114 -0
- package/src/rules/infinite-query-property-order/infinite-query-property-order.utils.ts +38 -0
- package/src/rules/no-unstable-deps/no-unstable-deps.rule.ts +1 -1
- package/src/rules.ts +2 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { AST_NODE_TYPES, ESLintUtils } from '@typescript-eslint/utils'
|
|
2
|
+
|
|
3
|
+
import { getDocsUrl } from '../../utils/get-docs-url'
|
|
4
|
+
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
|
|
5
|
+
import { sortDataByOrder } from './infinite-query-property-order.utils'
|
|
6
|
+
import { checkedProperties, infiniteQueryFunctions } from './constants'
|
|
7
|
+
import type { InfiniteQueryFunctions } from './constants'
|
|
8
|
+
import type { ExtraRuleDocs } from '../../types'
|
|
9
|
+
|
|
10
|
+
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)
|
|
11
|
+
|
|
12
|
+
const infiniteQueryFunctionsSet = new Set(infiniteQueryFunctions)
|
|
13
|
+
function isInfiniteQueryFunction(node: any): node is InfiniteQueryFunctions {
|
|
14
|
+
return infiniteQueryFunctionsSet.has(node)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const name = 'infinite-query-property-order'
|
|
18
|
+
|
|
19
|
+
export const rule = createRule({
|
|
20
|
+
name,
|
|
21
|
+
meta: {
|
|
22
|
+
type: 'problem',
|
|
23
|
+
docs: {
|
|
24
|
+
description:
|
|
25
|
+
'Ensure correct order of inference sensitive properties for infinite queries',
|
|
26
|
+
recommended: 'error',
|
|
27
|
+
},
|
|
28
|
+
messages: {
|
|
29
|
+
invalidOrder: 'Invalid order of properties for `{{function}}`.',
|
|
30
|
+
},
|
|
31
|
+
schema: [],
|
|
32
|
+
hasSuggestions: true,
|
|
33
|
+
fixable: 'code',
|
|
34
|
+
},
|
|
35
|
+
defaultOptions: [],
|
|
36
|
+
|
|
37
|
+
create: detectTanstackQueryImports((context) => {
|
|
38
|
+
return {
|
|
39
|
+
CallExpression(node) {
|
|
40
|
+
if (node.callee.type !== AST_NODE_TYPES.Identifier) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
const infiniteQueryFunction = node.callee.name
|
|
44
|
+
if (!isInfiniteQueryFunction(infiniteQueryFunction)) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
const argument = node.arguments[0]
|
|
48
|
+
if (argument === undefined || argument.type !== 'ObjectExpression') {
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const allProperties = argument.properties
|
|
53
|
+
if (allProperties.length < 2) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const properties = allProperties.flatMap((p) => {
|
|
58
|
+
if (
|
|
59
|
+
p.type === AST_NODE_TYPES.Property &&
|
|
60
|
+
p.key.type === AST_NODE_TYPES.Identifier
|
|
61
|
+
) {
|
|
62
|
+
return { name: p.key.name, property: p }
|
|
63
|
+
} else if (p.type === AST_NODE_TYPES.SpreadElement) {
|
|
64
|
+
if (p.argument.type === AST_NODE_TYPES.Identifier) {
|
|
65
|
+
return { name: p.argument.name, property: p }
|
|
66
|
+
} else {
|
|
67
|
+
throw new Error('Unsupported spread element')
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return []
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const sortedProperties = sortDataByOrder(
|
|
74
|
+
properties,
|
|
75
|
+
checkedProperties,
|
|
76
|
+
'name',
|
|
77
|
+
)
|
|
78
|
+
if (sortedProperties === null) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
context.report({
|
|
82
|
+
node: argument,
|
|
83
|
+
data: { function: node.callee.name },
|
|
84
|
+
messageId: 'invalidOrder',
|
|
85
|
+
fix(fixer) {
|
|
86
|
+
const sourceCode = context.sourceCode
|
|
87
|
+
|
|
88
|
+
const text = sortedProperties.reduce(
|
|
89
|
+
(sourceText, specifier, index) => {
|
|
90
|
+
let text = ''
|
|
91
|
+
if (index < allProperties.length - 1) {
|
|
92
|
+
text = sourceCode
|
|
93
|
+
.getText()
|
|
94
|
+
.slice(
|
|
95
|
+
allProperties[index]!.range[1],
|
|
96
|
+
allProperties[index + 1]!.range[0],
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
return (
|
|
100
|
+
sourceText + sourceCode.getText(specifier.property) + text
|
|
101
|
+
)
|
|
102
|
+
},
|
|
103
|
+
'',
|
|
104
|
+
)
|
|
105
|
+
return fixer.replaceTextRange(
|
|
106
|
+
[allProperties[0]!.range[0], allProperties.at(-1)!.range[1]],
|
|
107
|
+
text,
|
|
108
|
+
)
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
}),
|
|
114
|
+
})
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export function sortDataByOrder<T, TKey extends keyof T>(
|
|
2
|
+
data: Array<T> | ReadonlyArray<T>,
|
|
3
|
+
orderArray: Array<T[TKey]> | ReadonlyArray<T[TKey]>,
|
|
4
|
+
key: TKey,
|
|
5
|
+
): Array<T> | null {
|
|
6
|
+
const orderMap = new Map(orderArray.map((item, index) => [item, index]))
|
|
7
|
+
|
|
8
|
+
// Separate items that are in orderArray from those that are not
|
|
9
|
+
const inOrderArray = data
|
|
10
|
+
.filter((item) => orderMap.has(item[key]))
|
|
11
|
+
.sort((a, b) => {
|
|
12
|
+
const indexA = orderMap.get(a[key])!
|
|
13
|
+
const indexB = orderMap.get(b[key])!
|
|
14
|
+
|
|
15
|
+
return indexA - indexB
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const inOrderIterator = inOrderArray.values()
|
|
19
|
+
|
|
20
|
+
// `as boolean` is needed to avoid TS incorrectly inferring that wasResorted is always `true`
|
|
21
|
+
let wasResorted = false as boolean
|
|
22
|
+
|
|
23
|
+
const result = data.map((item) => {
|
|
24
|
+
if (orderMap.has(item[key])) {
|
|
25
|
+
const sortedItem = inOrderIterator.next().value!
|
|
26
|
+
if (sortedItem[key] !== item[key]) {
|
|
27
|
+
wasResorted = true
|
|
28
|
+
}
|
|
29
|
+
return sortedItem
|
|
30
|
+
}
|
|
31
|
+
return item
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
if (!wasResorted) {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
return result
|
|
38
|
+
}
|
|
@@ -24,7 +24,7 @@ export const rule = createRule({
|
|
|
24
24
|
type: 'problem',
|
|
25
25
|
docs: {
|
|
26
26
|
description:
|
|
27
|
-
'Disallow putting the result of
|
|
27
|
+
'Disallow putting the result of query hooks directly in a React hook dependency array',
|
|
28
28
|
recommended: 'error',
|
|
29
29
|
},
|
|
30
30
|
messages: {
|
package/src/rules.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as exhaustiveDeps from './rules/exhaustive-deps/exhaustive-deps.rule'
|
|
|
2
2
|
import * as stableQueryClient from './rules/stable-query-client/stable-query-client.rule'
|
|
3
3
|
import * as noRestDestructuring from './rules/no-rest-destructuring/no-rest-destructuring.rule'
|
|
4
4
|
import * as noUnstableDeps from './rules/no-unstable-deps/no-unstable-deps.rule'
|
|
5
|
+
import * as infiniteQueryPropertyOrder from './rules/infinite-query-property-order/infinite-query-property-order.rule'
|
|
5
6
|
import type { ESLintUtils } from '@typescript-eslint/utils'
|
|
6
7
|
import type { ExtraRuleDocs } from './types'
|
|
7
8
|
|
|
@@ -18,4 +19,5 @@ export const rules: Record<
|
|
|
18
19
|
[stableQueryClient.name]: stableQueryClient.rule,
|
|
19
20
|
[noRestDestructuring.name]: noRestDestructuring.rule,
|
|
20
21
|
[noUnstableDeps.name]: noUnstableDeps.rule,
|
|
22
|
+
[infiniteQueryPropertyOrder.name]: infiniteQueryPropertyOrder.rule,
|
|
21
23
|
}
|