Skip to content

feat: ESLint v9 Support #7543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/eslint-plugin-query/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@
"src"
],
"dependencies": {
"@typescript-eslint/utils": "^6.20.0"
"@typescript-eslint/utils": "8.0.0-alpha.28"
},
"devDependencies": {
"@typescript-eslint/rule-tester": "^6.20.0",
"eslint": "^8.56.0"
"@typescript-eslint/rule-tester": "8.0.0-alpha.28",
"eslint": "^9.4.0"
},
"peerDependencies": {
"eslint": "^8.0.0"
"eslint": "^8.0.0 | ^9.0.0"
}
}
27 changes: 0 additions & 27 deletions packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,33 +679,6 @@ ruleTester.run('exhaustive-deps', rule, {
},
],
},
{
name: 'should fail when a queryKey is a reference of an array expression with a missing dep',
code: normalizeIndent`
const x = 5;
const queryKey = ['foo']
useQuery({ queryKey, queryFn: () => x })
`,
errors: [
{
messageId: 'missingDeps',
data: { deps: 'x' },
suggestions: [
{
messageId: 'fixTo',
data: {
result: "['foo', x]",
},
output: normalizeIndent`
const x = 5;
const queryKey = ['foo', x]
useQuery({ queryKey, queryFn: () => x })
`,
},
],
},
],
},
{
name: 'should fail when queryKey is a queryKeyFactory while having missing dep',
code: normalizeIndent`
Expand Down
5 changes: 3 additions & 2 deletions packages/eslint-plugin-query/src/configs.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { rules } from './rules'
import type { ESLintUtils } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from './types'

function generateRecommendedConfig(
allRules: Record<
string,
ESLintUtils.RuleModule<
string,
ReadonlyArray<unknown>,
ExtraRuleDocs,
ESLintUtils.RuleListener
>
>,
) {
return Object.entries(allRules).reduce(
// @ts-expect-error
(memo, [name, rule]) => {
const { recommended } = rule.meta.docs || {}

Expand All @@ -21,7 +22,7 @@ function generateRecommendedConfig(
...(recommended ? { [`@tanstack/query/${name}`]: recommended } : {}),
}
},
{} as Record<string, 'strict' | 'error' | 'warn'>,
{} as Record<string, ExtraRuleDocs['recommended']>,
)
}

Expand Down
2 changes: 2 additions & 0 deletions packages/eslint-plugin-query/src/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import * as exhaustiveDeps from './rules/exhaustive-deps/exhaustive-deps.rule'
import * as stableQueryClient from './rules/stable-query-client/stable-query-client.rule'
import * as noRestDestructuring from './rules/no-rest-destructuring/no-rest-destructuring.rule'
import type { ESLintUtils } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from './types'

export const rules: Record<
string,
ESLintUtils.RuleModule<
string,
ReadonlyArray<unknown>,
ExtraRuleDocs,
ESLintUtils.RuleListener
>
> = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,22 @@ import { uniqueBy } from '../../utils/unique-by'
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
import { ExhaustiveDepsUtils } from './exhaustive-deps.utils'
import type { TSESLint } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from '../../types'

const QUERY_KEY = 'queryKey'
const QUERY_FN = 'queryFn'

export const name = 'exhaustive-deps'

const createRule = ESLintUtils.RuleCreator(getDocsUrl)
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)

export const rule = createRule({
name,
meta: {
type: 'problem',
docs: {
description: 'Exhaustive deps rule for useQuery',
recommended: 'error' as any,
recommended: 'error',
},
messages: {
missingDeps: `The following dependencies are missing in your queryKey: {{deps}}`,
Expand Down Expand Up @@ -92,9 +93,10 @@ export const rule = createRule({

const relevantRefs = externalRefs.filter((reference) =>
ExhaustiveDepsUtils.isRelevantReference({
context,
sourceCode: context.sourceCode,
reference,
scopeManager,
node: queryFn.value,
}),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import type { TSESLint, TSESTree } from '@typescript-eslint/utils'

export const ExhaustiveDepsUtils = {
isRelevantReference(params: {
context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>
sourceCode: Readonly<TSESLint.SourceCode>
reference: TSESLint.Scope.Reference
scopeManager: TSESLint.Scope.ScopeManager
node: TSESTree.Node
}) {
const { reference, scopeManager, context } = params
const component = ASTUtils.getFunctionAncestor(context)
const { sourceCode, reference, scopeManager, node } = params
const component = ASTUtils.getFunctionAncestor(sourceCode, node)

if (
component !== undefined &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ import { getDocsUrl } from '../../utils/get-docs-url'
import { ASTUtils } from '../../utils/ast-utils'
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
import { NoRestDestructuringUtils } from './no-rest-destructuring.utils'
import type { ExtraRuleDocs } from '../../types'

export const name = 'no-rest-destructuring'

const queryHooks = ['useQuery', 'useQueries', 'useInfiniteQuery']

const createRule = ESLintUtils.RuleCreator(getDocsUrl)
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)

export const rule = createRule({
name,
meta: {
type: 'problem',
docs: {
description: 'Disallows rest destructuring in queries',
recommended: 'warn' as any,
recommended: 'warn',
},
messages: {
objectRestDestructure: `Object rest destructuring on a query will observe all changes to the query, leading to excessive re-renders.`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ import { ASTUtils } from '../../utils/ast-utils'
import { getDocsUrl } from '../../utils/get-docs-url'
import { detectTanstackQueryImports } from '../../utils/detect-react-query-imports'
import type { TSESLint } from '@typescript-eslint/utils'
import type { ExtraRuleDocs } from '../../types'

export const name = 'stable-query-client'

const createRule = ESLintUtils.RuleCreator(getDocsUrl)
const createRule = ESLintUtils.RuleCreator<ExtraRuleDocs>(getDocsUrl)

export const rule = createRule({
name,
meta: {
type: 'problem',
docs: {
description: 'Makes sure that QueryClient is stable',
recommended: 'error' as any,
recommended: 'error',
},
messages: {
unstable: [
Expand Down Expand Up @@ -44,7 +45,10 @@ export const rule = createRule({
return
}

const fnAncestor = ASTUtils.getFunctionAncestor(context)
const fnAncestor = ASTUtils.getFunctionAncestor(
context.sourceCode,
node,
)
const isReactServerComponent = fnAncestor?.async === true

if (
Expand Down
3 changes: 3 additions & 0 deletions packages/eslint-plugin-query/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type ExtraRuleDocs = {
recommended: 'strict' | 'error' | 'warn'
}
5 changes: 3 additions & 2 deletions packages/eslint-plugin-query/src/utils/ast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,10 @@ export const ASTUtils = {
)
},
getFunctionAncestor(
context: Readonly<TSESLint.RuleContext<string, ReadonlyArray<unknown>>>,
sourceCode: Readonly<TSESLint.SourceCode>,
node: TSESTree.Node,
) {
for (const ancestor of context.getAncestors()) {
for (const ancestor of sourceCode.getAncestors(node)) {
if (ancestor.type === AST_NODE_TYPES.FunctionDeclaration) {
return ancestor
}
Expand Down
Loading