From a1fe95ac8e2c46c769533942a416d893fe6b92f2 Mon Sep 17 00:00:00 2001 From: Riva Junior Date: Tue, 27 Aug 2024 12:35:01 -0300 Subject: [PATCH 1/4] feat(eslint-plugin-query): use @typescript-eslint/utils stable v8 --- packages/eslint-plugin-query/package.json | 8 +- pnpm-lock.yaml | 101 ++++++++++++++-------- 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/packages/eslint-plugin-query/package.json b/packages/eslint-plugin-query/package.json index ed8f033fb1..ba21d91aa4 100644 --- a/packages/eslint-plugin-query/package.json +++ b/packages/eslint-plugin-query/package.json @@ -50,13 +50,13 @@ "src" ], "dependencies": { - "@typescript-eslint/utils": "8.0.0-alpha.30" + "@typescript-eslint/utils": "^8.3.0" }, "devDependencies": { - "@typescript-eslint/rule-tester": "8.0.0-alpha.30", - "eslint": "^9.5.0" + "@typescript-eslint/rule-tester": "^8.3.0", + "eslint": "^9.9.1" }, "peerDependencies": { - "eslint": "^8 || ^9" + "eslint": "^8.57.0 || ^9.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 850d145dde..38bd825778 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,7 +53,7 @@ importers: version: 2.0.5(vitest@2.0.5(@types/node@20.14.13)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)) '@vitest/eslint-plugin': specifier: ^1.0.2 - version: 1.0.2(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)) + version: 1.0.2(@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)) cpy-cli: specifier: ^5.0.0 version: 5.0.0 @@ -1927,12 +1927,12 @@ importers: packages/eslint-plugin-query: dependencies: '@typescript-eslint/utils': - specifier: 8.0.0-alpha.30 - version: 8.0.0-alpha.30(eslint@8.57.0)(typescript@5.4.2) + specifier: ^8.3.0 + version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) devDependencies: '@typescript-eslint/rule-tester': - specifier: 8.0.0-alpha.30 - version: 8.0.0-alpha.30(@eslint/eslintrc@2.1.4)(eslint@8.57.0)(typescript@5.4.2) + specifier: ^8.3.0 + version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) eslint: specifier: ^8.57.0 version: 8.57.0 @@ -6351,19 +6351,18 @@ packages: typescript: optional: true - '@typescript-eslint/rule-tester@8.0.0-alpha.30': - resolution: {integrity: sha512-mqGc88a7uCoEMhdertGKaeLy8QrvqA5pKBchFosa+RX7EGU6ngJAmMj+ZRZka/r6hmTyDRbd44H3Z0ChOPgl+Q==} + '@typescript-eslint/rule-tester@8.3.0': + resolution: {integrity: sha512-ITX1PUjIUZcj0sVpReC41YLNd+BfSEfcWRI4siYAAbjUdTRT5FpT54Uir6ezqS3RGKd5T8D5Yz3I3G80COa56w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@eslint/eslintrc': '>=2' eslint: ^8.57.0 '@typescript-eslint/scope-manager@7.18.0': resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/scope-manager@8.0.0-alpha.30': - resolution: {integrity: sha512-FGW/iPWGyPFamAVZ60oCAthMqQrqafUGebF8UKuq/ha+e9SVG6YhJoRzurlQXOVf8dHfOhJ0ADMXyFnMc53clg==} + '@typescript-eslint/scope-manager@8.3.0': + resolution: {integrity: sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/type-utils@7.18.0': @@ -6380,8 +6379,8 @@ packages: resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/types@8.0.0-alpha.30': - resolution: {integrity: sha512-4WzLlw27SO9pK9UFj/Hu7WGo8WveT0SEiIpFVsV2WwtQmLps6kouwtVCB8GJPZKJyurhZhcqCoQVQFmpv441Vg==} + '@typescript-eslint/types@8.3.0': + resolution: {integrity: sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript-eslint/typescript-estree@7.18.0': @@ -6393,8 +6392,8 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@8.0.0-alpha.30': - resolution: {integrity: sha512-WSXbc9ZcXI+7yC+6q95u77i8FXz6HOLsw3ST+vMUlFy1lFbXyFL/3e6HDKQCm2Clt0krnoCPiTGvIn+GkYPn4Q==} + '@typescript-eslint/typescript-estree@8.3.0': + resolution: {integrity: sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -6408,8 +6407,8 @@ packages: peerDependencies: eslint: ^8.57.0 - '@typescript-eslint/utils@8.0.0-alpha.30': - resolution: {integrity: sha512-rfhqfLqFyXhHNDwMnHiVGxl/Z2q/3guQ1jLlGQ0hi9Rb7inmwz42crM+NnLPR+2vEnwyw1P/g7fnQgQ3qvFx4g==} + '@typescript-eslint/utils@8.3.0': + resolution: {integrity: sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 @@ -6418,8 +6417,8 @@ packages: resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/visitor-keys@8.0.0-alpha.30': - resolution: {integrity: sha512-XZuNurZxBqmr6ZIRIwWFq7j5RZd6ZlkId/HZEWyfciK+CWoyOxSF9Pv2VXH9Rlu2ZG2PfbhLz2Veszl4Pfn7yA==} + '@typescript-eslint/visitor-keys@8.3.0': + resolution: {integrity: sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.2.0': @@ -22900,11 +22899,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/rule-tester@8.0.0-alpha.30(@eslint/eslintrc@2.1.4)(eslint@8.57.0)(typescript@5.4.2)': + '@typescript-eslint/rule-tester@8.3.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: - '@eslint/eslintrc': 2.1.4 - '@typescript-eslint/typescript-estree': 8.0.0-alpha.30(typescript@5.4.2) - '@typescript-eslint/utils': 8.0.0-alpha.30(eslint@8.57.0)(typescript@5.4.2) + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.4.2) + '@typescript-eslint/utils': 8.3.0(eslint@8.57.0)(typescript@5.4.2) ajv: 6.12.6 eslint: 8.57.0 json-stable-stringify-without-jsonify: 1.0.1 @@ -22919,10 +22917,10 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/scope-manager@8.0.0-alpha.30': + '@typescript-eslint/scope-manager@8.3.0': dependencies: - '@typescript-eslint/types': 8.0.0-alpha.30 - '@typescript-eslint/visitor-keys': 8.0.0-alpha.30 + '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/visitor-keys': 8.3.0 '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.3.3)': dependencies: @@ -22938,7 +22936,7 @@ snapshots: '@typescript-eslint/types@7.18.0': {} - '@typescript-eslint/types@8.0.0-alpha.30': {} + '@typescript-eslint/types@8.3.0': {} '@typescript-eslint/typescript-estree@7.18.0(typescript@5.3.3)': dependencies: @@ -22955,12 +22953,28 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.0.0-alpha.30(typescript@5.4.2)': + '@typescript-eslint/typescript-estree@8.3.0(typescript@5.3.3)': dependencies: - '@typescript-eslint/types': 8.0.0-alpha.30 - '@typescript-eslint/visitor-keys': 8.0.0-alpha.30 + '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/visitor-keys': 8.3.0 debug: 4.3.6(supports-color@6.1.0) - globby: 11.1.0 + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.3.3) + optionalDependencies: + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + optional: true + + '@typescript-eslint/typescript-estree@8.3.0(typescript@5.4.2)': + dependencies: + '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/visitor-keys': 8.3.0 + debug: 4.3.6(supports-color@6.1.0) + fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 @@ -22981,12 +22995,24 @@ snapshots: - supports-color - typescript - '@typescript-eslint/utils@8.0.0-alpha.30(eslint@8.57.0)(typescript@5.4.2)': + '@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.3.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 8.3.0 + '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.3.3) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + optional: true + + '@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 8.0.0-alpha.30 - '@typescript-eslint/types': 8.0.0-alpha.30 - '@typescript-eslint/typescript-estree': 8.0.0-alpha.30(typescript@5.4.2) + '@typescript-eslint/scope-manager': 8.3.0 + '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.4.2) eslint: 8.57.0 transitivePeerDependencies: - supports-color @@ -22997,9 +23023,9 @@ snapshots: '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 - '@typescript-eslint/visitor-keys@8.0.0-alpha.30': + '@typescript-eslint/visitor-keys@8.3.0': dependencies: - '@typescript-eslint/types': 8.0.0-alpha.30 + '@typescript-eslint/types': 8.3.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -23159,10 +23185,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.0.2(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))': + '@vitest/eslint-plugin@1.0.2(@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))': dependencies: eslint: 8.57.0 optionalDependencies: + '@typescript-eslint/utils': 8.3.0(eslint@8.57.0)(typescript@5.3.3) typescript: 5.3.3 vitest: 2.0.5(@types/node@20.14.13)(jsdom@24.1.1)(less@4.2.0)(sass@1.77.8)(terser@5.31.3) From e1c48bb5756a7224a3cb9bb518fbc51f9d01cb69 Mon Sep 17 00:00:00 2001 From: Riva Junior Date: Tue, 27 Aug 2024 13:52:01 -0300 Subject: [PATCH 2/4] test(eslint-plugin-query): fix missing parser --- packages/eslint-plugin-query/package.json | 1 + .../src/__tests__/exhaustive-deps.test.ts | 72 +++++++++++++++---- .../__tests__/no-rest-destructuring.test.ts | 6 +- .../src/__tests__/no-unstable-deps.test.ts | 12 ++-- .../src/__tests__/stable-query-client.test.ts | 10 +-- pnpm-lock.yaml | 26 +++++++ 6 files changed, 103 insertions(+), 24 deletions(-) diff --git a/packages/eslint-plugin-query/package.json b/packages/eslint-plugin-query/package.json index ba21d91aa4..8b72309b22 100644 --- a/packages/eslint-plugin-query/package.json +++ b/packages/eslint-plugin-query/package.json @@ -53,6 +53,7 @@ "@typescript-eslint/utils": "^8.3.0" }, "devDependencies": { + "@typescript-eslint/parser": "^8.3.0", "@typescript-eslint/rule-tester": "^8.3.0", "eslint": "^9.9.1" }, diff --git a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts index e33bdb30b1..e413af42dc 100644 --- a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts @@ -1,10 +1,12 @@ import { RuleTester } from '@typescript-eslint/rule-tester' +import * as parser from '@typescript-eslint/parser' import { rule } from '../rules/exhaustive-deps/exhaustive-deps.rule' import { normalizeIndent } from './test-utils' const ruleTester = new RuleTester({ - parser: '@typescript-eslint/parser', - settings: {}, + settings: { + parser, + }, }) ruleTester.run('exhaustive-deps', rule, { @@ -146,7 +148,7 @@ ruleTester.run('exhaustive-deps', rule, { foo: () => ['foo'] as const, num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const, } - + const useFoo = (num: number) => useQuery({ queryKey: fooQueryKeyFactory.foo(num), @@ -161,7 +163,7 @@ ruleTester.run('exhaustive-deps', rule, { foo: () => ['foo'] as const, num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const, } - + const useFoo = (num: number) => useQuery({ queryKey: fooQueryKeyFactory.foo({ x: num }), @@ -176,7 +178,7 @@ ruleTester.run('exhaustive-deps', rule, { foo: () => ['foo'] as const, num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const, } - + const useFoo = (num: number) => useQuery({ queryKey: fooQueryKeyFactory.foo({ num }), @@ -191,7 +193,7 @@ ruleTester.run('exhaustive-deps', rule, { foo: () => ['foo'] as const, num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const, } - + const useFoo = (num: number) => useQuery({ queryKey: fooQueryKeyFactory.foo([num]), @@ -206,7 +208,7 @@ ruleTester.run('exhaustive-deps', rule, { foo: () => ['foo'] as const, num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const, } - + const useFoo = (num: number) => useQuery({ queryKey: fooQueryKeyFactory.foo(1, num), @@ -221,7 +223,7 @@ ruleTester.run('exhaustive-deps', rule, { foo: () => ['foo'] as const, num: (num: number) => [...fooQueryKeyFactory.foo(), num] as const, } - + const useFoo = (obj: { num: number }) => useQuery({ queryKey: fooQueryKeyFactory.foo(obj.num), @@ -253,7 +255,7 @@ ruleTester.run('exhaustive-deps', rule, { name: 'should not fail if queryKey is having the whole object while queryFn uses some props of it', code: normalizeIndent` const state = { foo: 'foo', bar: 'bar' } - + useQuery({ queryKey: ['state', state], queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar }) @@ -407,7 +409,7 @@ ruleTester.run('exhaustive-deps', rule, { code: normalizeIndent` import { useQuery, skipToken } from "@tanstack/react-query"; const fetch = true - + function Component({ id }) { useQuery({ queryKey: [id], @@ -715,7 +717,7 @@ ruleTester.run('exhaustive-deps', rule, { name: 'should fail if queryFn is using multiple object props when only one of them is in the queryKey', code: normalizeIndent` const state = { foo: 'foo', bar: 'bar' } - + useQuery({ queryKey: ['state', state.foo], queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar }) @@ -723,6 +725,19 @@ ruleTester.run('exhaustive-deps', rule, { `, errors: [ { + suggestions: [ + { + messageId: 'fixTo', + output: normalizeIndent` + const state = { foo: 'foo', bar: 'bar' } + + useQuery({ + queryKey: ['state', state.foo, state.bar], + queryFn: () => Promise.resolve({ foo: state.foo, bar: state.bar }) + }) + `, + }, + ], messageId: 'missingDeps', data: { deps: 'state.bar' }, }, @@ -732,7 +747,7 @@ ruleTester.run('exhaustive-deps', rule, { name: 'should fail if queryFn is invalid while using FunctionExpression syntax', code: normalizeIndent` const id = 1; - + useQuery({ queryKey: [], queryFn() { @@ -742,6 +757,21 @@ ruleTester.run('exhaustive-deps', rule, { `, errors: [ { + suggestions: [ + { + messageId: 'fixTo', + output: normalizeIndent` + const id = 1; + + useQuery({ + queryKey: [, id], + queryFn() { + Promise.resolve(id) + } + }) + `, + }, + ], messageId: 'missingDeps', data: { deps: 'id' }, }, @@ -752,7 +782,7 @@ ruleTester.run('exhaustive-deps', rule, { code: normalizeIndent` import { useQuery, skipToken } from "@tanstack/react-query"; const fetch = true - + function Component({ id }) { useQuery({ queryKey: [], @@ -762,6 +792,22 @@ ruleTester.run('exhaustive-deps', rule, { `, errors: [ { + suggestions: [ + { + messageId: 'fixTo', + output: normalizeIndent` + import { useQuery, skipToken } from "@tanstack/react-query"; + const fetch = true + + function Component({ id }) { + useQuery({ + queryKey: [, id], + queryFn: fetch ? () => Promise.resolve(id) : skipToken + }) + } + `, + }, + ], messageId: 'missingDeps', data: { deps: 'id' }, }, diff --git a/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts b/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts index ec9e798fa7..59f0851290 100644 --- a/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts @@ -1,10 +1,12 @@ import { RuleTester } from '@typescript-eslint/rule-tester' +import * as parser from '@typescript-eslint/parser' import { rule } from '../rules/no-rest-destructuring/no-rest-destructuring.rule' import { normalizeIndent } from './test-utils' const ruleTester = new RuleTester({ - parser: '@typescript-eslint/parser', - settings: {}, + settings: { + parser, + }, }) ruleTester.run('no-rest-destructuring', rule, { diff --git a/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts index 31b0fc8ef7..aff5eb4d0e 100644 --- a/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts @@ -1,4 +1,5 @@ import { RuleTester } from '@typescript-eslint/rule-tester' +import * as parser from '@typescript-eslint/parser' import { reactHookNames, rule, @@ -6,8 +7,9 @@ import { } from '../rules/no-unstable-deps/no-unstable-deps.rule' const ruleTester = new RuleTester({ - parser: '@typescript-eslint/parser', - settings: {}, + settings: { + parser, + }, }) interface TestCase { @@ -37,7 +39,7 @@ const baseTestCases = { code: ` ${reactHookImport} import { ${queryHook} } from "@tanstack/react-query"; - + function Component() { const { refetch } = ${queryHook}({ queryFn: (value: string) => value }); const callback = ${reactHookInvocation}(() => { query.refetch() }, [refetch]); @@ -57,7 +59,7 @@ const baseTestCases = { code: ` ${reactHookImport} import { useMutation } from "@tanstack/react-query"; - + function Component() { const mutation = useMutation({ mutationFn: (value: string) => value }); const callback = ${reactHookInvocation}(() => { mutation.mutate('hello') }, [mutation]); @@ -77,7 +79,7 @@ const baseTestCases = { code: ` ${reactHookImport} import { ${queryHook} } from "@tanstack/react-query"; - + function Component() { const query = ${queryHook}({ queryFn: (value: string) => value }); const callback = ${reactHookInvocation}(() => { query.refetch() }, [query]); diff --git a/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts b/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts index ef64fa1c4d..dd88f1cfe9 100644 --- a/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts @@ -1,10 +1,12 @@ import { RuleTester } from '@typescript-eslint/rule-tester' +import * as parser from '@typescript-eslint/parser' import { rule } from '../rules/stable-query-client/stable-query-client.rule' import { normalizeIndent } from './test-utils' const ruleTester = new RuleTester({ - parser: '@typescript-eslint/parser', - settings: {}, + settings: { + parser, + }, }) ruleTester.run('stable-query-client', rule, { @@ -35,7 +37,7 @@ ruleTester.run('stable-query-client', rule, { name: 'QueryClient is stable when wrapped in React.useMemo', code: normalizeIndent` import { QueryClient } from "@tanstack/react-query"; - + function Component() { const [queryClient] = React.useMemo(() => new QueryClient(), []); return; @@ -46,7 +48,7 @@ ruleTester.run('stable-query-client', rule, { name: 'QueryClient is stable when wrapped in useAnything', code: normalizeIndent` import { QueryClient } from "@tanstack/react-query"; - + function Component() { const [queryClient] = useAnything(() => new QueryClient()); return; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38bd825778..7cfa1c8a6f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1930,6 +1930,9 @@ importers: specifier: ^8.3.0 version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) devDependencies: + '@typescript-eslint/parser': + specifier: ^8.3.0 + version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) '@typescript-eslint/rule-tester': specifier: ^8.3.0 version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) @@ -6351,6 +6354,16 @@ packages: typescript: optional: true + '@typescript-eslint/parser@8.3.0': + resolution: {integrity: sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/rule-tester@8.3.0': resolution: {integrity: sha512-ITX1PUjIUZcj0sVpReC41YLNd+BfSEfcWRI4siYAAbjUdTRT5FpT54Uir6ezqS3RGKd5T8D5Yz3I3G80COa56w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -22899,6 +22912,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.3.0(eslint@8.57.0)(typescript@5.4.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.3.0 + '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.4.2) + '@typescript-eslint/visitor-keys': 8.3.0 + debug: 4.3.6(supports-color@6.1.0) + eslint: 8.57.0 + optionalDependencies: + typescript: 5.4.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/rule-tester@8.3.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.4.2) From 0417d6b468e372a16e0a6383c75f5c5d50916b72 Mon Sep 17 00:00:00 2001 From: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:55:51 +1000 Subject: [PATCH 3/4] Remove @typescript-eslint/parser --- packages/eslint-plugin-query/package.json | 1 - .../src/__tests__/exhaustive-deps.test.ts | 7 +-- .../__tests__/no-rest-destructuring.test.ts | 7 +-- .../src/__tests__/no-unstable-deps.test.ts | 7 +-- .../src/__tests__/stable-query-client.test.ts | 7 +-- pnpm-lock.yaml | 50 ++++++------------- 6 files changed, 19 insertions(+), 60 deletions(-) diff --git a/packages/eslint-plugin-query/package.json b/packages/eslint-plugin-query/package.json index ecb0ca4cf2..db28822391 100644 --- a/packages/eslint-plugin-query/package.json +++ b/packages/eslint-plugin-query/package.json @@ -53,7 +53,6 @@ "@typescript-eslint/utils": "^8.3.0" }, "devDependencies": { - "@typescript-eslint/parser": "^8.3.0", "@typescript-eslint/rule-tester": "^8.3.0", "eslint": "^9.9.1" }, diff --git a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts index e413af42dc..c5d5c2a04c 100644 --- a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts @@ -1,13 +1,8 @@ import { RuleTester } from '@typescript-eslint/rule-tester' -import * as parser from '@typescript-eslint/parser' import { rule } from '../rules/exhaustive-deps/exhaustive-deps.rule' import { normalizeIndent } from './test-utils' -const ruleTester = new RuleTester({ - settings: { - parser, - }, -}) +const ruleTester = new RuleTester() ruleTester.run('exhaustive-deps', rule, { valid: [ diff --git a/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts b/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts index 59f0851290..b3ec633b70 100644 --- a/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/no-rest-destructuring.test.ts @@ -1,13 +1,8 @@ import { RuleTester } from '@typescript-eslint/rule-tester' -import * as parser from '@typescript-eslint/parser' import { rule } from '../rules/no-rest-destructuring/no-rest-destructuring.rule' import { normalizeIndent } from './test-utils' -const ruleTester = new RuleTester({ - settings: { - parser, - }, -}) +const ruleTester = new RuleTester() ruleTester.run('no-rest-destructuring', rule, { valid: [ diff --git a/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts index aff5eb4d0e..32cbf542d7 100644 --- a/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts @@ -1,16 +1,11 @@ import { RuleTester } from '@typescript-eslint/rule-tester' -import * as parser from '@typescript-eslint/parser' import { reactHookNames, rule, useQueryHookNames, } from '../rules/no-unstable-deps/no-unstable-deps.rule' -const ruleTester = new RuleTester({ - settings: { - parser, - }, -}) +const ruleTester = new RuleTester() interface TestCase { reactHookImport: string diff --git a/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts b/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts index dd88f1cfe9..0ceda63523 100644 --- a/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/stable-query-client.test.ts @@ -1,13 +1,8 @@ import { RuleTester } from '@typescript-eslint/rule-tester' -import * as parser from '@typescript-eslint/parser' import { rule } from '../rules/stable-query-client/stable-query-client.rule' import { normalizeIndent } from './test-utils' -const ruleTester = new RuleTester({ - settings: { - parser, - }, -}) +const ruleTester = new RuleTester() ruleTester.run('stable-query-client', rule, { valid: [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5434d8eb9e..3f4b5b6700 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,7 +53,7 @@ importers: version: 2.0.5(vitest@2.0.5(@types/node@20.14.13)(jsdom@25.0.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)) '@vitest/eslint-plugin': specifier: ^1.0.2 - version: 1.0.2(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@25.0.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)) + version: 1.0.2(@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@25.0.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)) cpy-cli: specifier: ^5.0.0 version: 5.0.0 @@ -1118,7 +1118,7 @@ importers: version: 5.1.0(astro@4.12.3(@types/node@22.0.2)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)(typescript@5.3.3))(tailwindcss@3.4.7) '@astrojs/vercel': specifier: ^7.7.2 - version: 7.7.2(astro@4.12.3(@types/node@22.0.2)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)(typescript@5.3.3))(encoding@0.1.13)(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522))(react@18.3.1)(sass@1.77.8))(react@18.3.1) + version: 7.7.2(astro@4.12.3(@types/node@22.0.2)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)(typescript@5.3.3))(encoding@0.1.13)(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react@18.3.1) '@tanstack/solid-query': specifier: ^5.52.3 version: link:../../../packages/solid-query @@ -1924,9 +1924,6 @@ importers: specifier: ^8.3.0 version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) devDependencies: - '@typescript-eslint/parser': - specifier: ^8.3.0 - version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) '@typescript-eslint/rule-tester': specifier: ^8.3.0 version: 8.3.0(eslint@8.57.0)(typescript@5.4.2) @@ -6322,16 +6319,6 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.3.0': - resolution: {integrity: sha512-h53RhVyLu6AtpUzVCYLPhZGL5jzTD9fZL+SYf/+hYOx2bDkyQXztXSc4tbvKYHzfMXExMLiL9CWqJmVz6+78IQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@typescript-eslint/rule-tester@8.3.0': resolution: {integrity: sha512-ITX1PUjIUZcj0sVpReC41YLNd+BfSEfcWRI4siYAAbjUdTRT5FpT54Uir6ezqS3RGKd5T8D5Yz3I3G80COa56w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -17588,10 +17575,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/vercel@7.7.2(astro@4.12.3(@types/node@22.0.2)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)(typescript@5.3.3))(encoding@0.1.13)(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522))(react@18.3.1)(sass@1.77.8))(react@18.3.1)': + '@astrojs/vercel@7.7.2(astro@4.12.3(@types/node@22.0.2)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)(typescript@5.3.3))(encoding@0.1.13)(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react@18.3.1)': dependencies: '@astrojs/internal-helpers': 0.4.1 - '@vercel/analytics': 1.3.1(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522))(react@18.3.1)(sass@1.77.8))(react@18.3.1) + '@vercel/analytics': 1.3.1(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react@18.3.1) '@vercel/edge': 1.1.2 '@vercel/nft': 0.27.3(encoding@0.1.13) astro: 4.12.3(@types/node@22.0.2)(less@4.2.0)(sass@1.77.8)(terser@5.31.3)(typescript@5.3.3) @@ -22818,19 +22805,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.3.0(eslint@8.57.0)(typescript@5.4.2)': - dependencies: - '@typescript-eslint/scope-manager': 8.3.0 - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.4.2) - '@typescript-eslint/visitor-keys': 8.3.0 - debug: 4.3.6(supports-color@6.1.0) - eslint: 8.57.0 - optionalDependencies: - typescript: 5.4.2 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/rule-tester@8.3.0(eslint@8.57.0)(typescript@5.4.2)': dependencies: '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.4.2) @@ -22974,11 +22948,11 @@ snapshots: graphql: 15.8.0 wonka: 4.0.15 - '@vercel/analytics@1.3.1(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522))(react@18.3.1)(sass@1.77.8))(react@18.3.1)': + '@vercel/analytics@1.3.1(next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1))(react@18.3.1)(sass@1.77.8))(react@18.3.1)': dependencies: server-only: 0.0.1 optionalDependencies: - next: 14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522))(react@18.3.1)(sass@1.77.8) + next: 14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1))(react@18.3.1)(sass@1.77.8) react: 18.3.1 '@vercel/edge@1.1.2': {} @@ -23117,7 +23091,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.0.2(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@25.0.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))': + '@vitest/eslint-plugin@1.0.2(@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3)(vitest@2.0.5(@types/node@20.14.13)(jsdom@25.0.0)(less@4.2.0)(sass@1.77.8)(terser@5.31.3))': dependencies: eslint: 8.57.0 optionalDependencies: @@ -30078,7 +30052,7 @@ snapshots: next-tick@1.1.0: {} - next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522))(react@18.3.1)(sass@1.77.8): + next@14.2.5(@babel/core@7.25.2)(react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1))(react@18.3.1)(sass@1.77.8): dependencies: '@next/env': 14.2.5 '@swc/helpers': 0.5.5 @@ -30087,7 +30061,7 @@ snapshots: graceful-fs: 4.2.11 postcss: 8.4.31 react: 18.3.1 - react-dom: 19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522) + react-dom: 19.0.0-rc-4c2e457c7c-20240522(react@18.3.1) styled-jsx: 5.1.1(@babel/core@7.25.2)(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.2.5 @@ -32385,6 +32359,12 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 + react-dom@19.0.0-rc-4c2e457c7c-20240522(react@18.3.1): + dependencies: + react: 18.3.1 + scheduler: 0.25.0-rc-4c2e457c7c-20240522 + optional: true + react-dom@19.0.0-rc-4c2e457c7c-20240522(react@19.0.0-rc-4c2e457c7c-20240522): dependencies: react: 19.0.0-rc-4c2e457c7c-20240522 From 8390136a5385d3ca2038f511b4413f6c1533d246 Mon Sep 17 00:00:00 2001 From: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Date: Fri, 30 Aug 2024 17:02:10 +1000 Subject: [PATCH 4/4] Fix suggestion for empty queryKey array --- .../src/__tests__/exhaustive-deps.test.ts | 4 ++-- .../rules/exhaustive-deps/exhaustive-deps.rule.ts | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts index c5d5c2a04c..74426d7193 100644 --- a/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts +++ b/packages/eslint-plugin-query/src/__tests__/exhaustive-deps.test.ts @@ -759,7 +759,7 @@ ruleTester.run('exhaustive-deps', rule, { const id = 1; useQuery({ - queryKey: [, id], + queryKey: [id], queryFn() { Promise.resolve(id) } @@ -796,7 +796,7 @@ ruleTester.run('exhaustive-deps', rule, { function Component({ id }) { useQuery({ - queryKey: [, id], + queryKey: [id], queryFn: fetch ? () => Promise.resolve(id) : skipToken }) } diff --git a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts index 472a341bdd..3cc4610df0 100644 --- a/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts +++ b/packages/eslint-plugin-query/src/rules/exhaustive-deps/exhaustive-deps.rule.ts @@ -85,7 +85,6 @@ export const rule = createRule({ } } - const queryKeyValue = queryKeyNode const externalRefs = ASTUtils.getExternalRefs({ scopeManager, sourceCode: context.sourceCode, @@ -101,7 +100,7 @@ export const rule = createRule({ }), ) - const existingKeys = ASTUtils.getNestedIdentifiers(queryKeyValue).map( + const existingKeys = ASTUtils.getNestedIdentifiers(queryKeyNode).map( (identifier) => ASTUtils.mapKeyNodeToText(identifier, context.sourceCode), ) @@ -133,9 +132,12 @@ export const rule = createRule({ ) .join(', ') - const existingWithMissing = context.sourceCode - .getText(queryKeyValue) - .replace(/\]$/, `, ${missingAsText}]`) + const queryKeyValue = context.sourceCode.getText(queryKeyNode) + + const existingWithMissing = + queryKeyValue === '[]' + ? `[${missingAsText}]` + : queryKeyValue.replace(/\]$/, `, ${missingAsText}]`) const suggestions: TSESLint.ReportSuggestionArray = [] @@ -144,7 +146,7 @@ export const rule = createRule({ messageId: 'fixTo', data: { result: existingWithMissing }, fix(fixer) { - return fixer.replaceText(queryKeyValue, existingWithMissing) + return fixer.replaceText(queryKeyNode, existingWithMissing) }, }) }