diff --git a/docs/eslint/eslint-plugin-query.md b/docs/eslint/eslint-plugin-query.md index 661943b8b9..d54006654e 100644 --- a/docs/eslint/eslint-plugin-query.md +++ b/docs/eslint/eslint-plugin-query.md @@ -19,34 +19,68 @@ $ yarn add -D @tanstack/eslint-plugin-query $ bun add -D @tanstack/eslint-plugin-query ``` -## Usage +## Flat Config (`eslint.config.js`) -To enable all of the recommended rules for our plugin, add `plugin:@tanstack/eslint-plugin-query/recommended` in extends: +### Recommended setup -```json -{ - "extends": ["plugin:@tanstack/eslint-plugin-query/recommended"] -} +To enable all of the recommended rules for our plugin, add the following config: + +```js +import pluginQuery from '@tanstack/eslint-plugin-query' + +export default [ + ...pluginQuery.configs['flat/recommended'], + // Any other config... +] +``` + +### Custom setup + +Alternatively, you can load the plugin and configure only the rules you want to use: + +```js +import pluginQuery from '@tanstack/eslint-plugin-query' + +export default [ + { + plugins: { + '@tanstack/query': pluginQuery, + }, + rules: { + '@tanstack/query/exhaustive-deps': 'error', + }, + }, + // Any other config... +] ``` -### Alternative config +## Legacy Config (`.eslintrc`) -Alternatively, add `@tanstack/eslint-plugin-query` to the plugins section of your `.eslintrc` configuration file: +### Recommended setup + +To enable all of the recommended rules for our plugin, add `plugin:@tanstack/eslint-plugin-query/recommended` in extends: ```json { - "plugins": ["@tanstack/query"] + "extends": ["plugin:@tanstack/eslint-plugin-query/recommended"] } ``` -Then configure the rules you want to use under the rules section: +### Custom setup + +Alternatively, add `@tanstack/eslint-plugin-query` to the plugins section, and configure the rules you want to use: ```json { + "plugins": ["@tanstack/query"], "rules": { - "@tanstack/query/exhaustive-deps": "error", - "@tanstack/query/no-rest-destructuring": "warn", - "@tanstack/query/stable-query-client": "error" + "@tanstack/query/exhaustive-deps": "error" } } ``` + +## Rules + +- [@tanstack/query/exhaustive-deps](../exhaustive-deps) +- [@tanstack/query/no-rest-destructuring](../exhaustive-deps) +- [@tanstack/query/stable-query-client](../exhaustive-deps) diff --git a/examples/react/basic-graphql-request/src/index.jsx b/examples/react/basic-graphql-request/src/index.jsx index b484d73a23..10aad56931 100644 --- a/examples/react/basic-graphql-request/src/index.jsx +++ b/examples/react/basic-graphql-request/src/index.jsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react' import ReactDOM from 'react-dom/client' import { diff --git a/examples/react/basic-typescript/.eslintrc b/examples/react/basic-typescript/.eslintrc deleted file mode 100644 index 270fbc9ac0..0000000000 --- a/examples/react/basic-typescript/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": [ - "plugin:react/jsx-runtime", - "plugin:react-hooks/recommended", - "plugin:@tanstack/eslint-plugin-query/recommended" - ] -} diff --git a/examples/react/basic-typescript/eslint.config.js b/examples/react/basic-typescript/eslint.config.js new file mode 100644 index 0000000000..dee0fcc96c --- /dev/null +++ b/examples/react/basic-typescript/eslint.config.js @@ -0,0 +1,19 @@ +import { tanstackConfig } from '@tanstack/config/eslint' +import pluginQuery from '@tanstack/eslint-plugin-query' +import pluginReact from '@eslint-react/eslint-plugin' +import pluginReactHooks from 'eslint-plugin-react-hooks' + +export default [ + ...tanstackConfig, + ...pluginQuery.configs['flat/recommended'], + pluginReact.configs.recommended, + { + plugins: { + 'react-hooks': pluginReactHooks, + }, + rules: { + 'react-hooks/exhaustive-deps': 'error', + 'react-hooks/rules-of-hooks': 'error', + }, + }, +] diff --git a/examples/react/basic-typescript/src/index.tsx b/examples/react/basic-typescript/src/index.tsx index 09d700c7c1..d6aace092c 100644 --- a/examples/react/basic-typescript/src/index.tsx +++ b/examples/react/basic-typescript/src/index.tsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import * as React from 'react' import ReactDOM from 'react-dom/client' import axios from 'axios' diff --git a/examples/react/basic-typescript/tsconfig.json b/examples/react/basic-typescript/tsconfig.json index 7c962d9747..23a8707ef4 100644 --- a/examples/react/basic-typescript/tsconfig.json +++ b/examples/react/basic-typescript/tsconfig.json @@ -20,5 +20,5 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src"] + "include": ["src", "eslint.config.js"] } diff --git a/examples/react/basic/src/index.jsx b/examples/react/basic/src/index.jsx index e038ea9b33..3ee4ac23a8 100644 --- a/examples/react/basic/src/index.jsx +++ b/examples/react/basic/src/index.jsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react' import ReactDOM from 'react-dom/client' import axios from 'axios' diff --git a/examples/react/default-query-function/src/index.jsx b/examples/react/default-query-function/src/index.jsx index 5b494df68e..6a10ce9155 100644 --- a/examples/react/default-query-function/src/index.jsx +++ b/examples/react/default-query-function/src/index.jsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react' import ReactDOM from 'react-dom/client' import axios from 'axios' diff --git a/examples/react/simple/src/index.jsx b/examples/react/simple/src/index.jsx index 5aa4579fe7..fa7f86a58a 100644 --- a/examples/react/simple/src/index.jsx +++ b/examples/react/simple/src/index.jsx @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ import React from 'react' import ReactDOM from 'react-dom/client' import { diff --git a/package.json b/package.json index 0de7e54ea3..bf098199a9 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "namespace": "@tanstack", "devDependencies": { - "@arethetypeswrong/cli": "^0.15.3", + "@arethetypeswrong/cli": "^0.16.0", "@cspell/eslint-plugin": "^8.9.1", "@eslint-react/eslint-plugin": "^1.5.16", "@solidjs/testing-library": "^0.8.8", diff --git a/packages/eslint-plugin-query/.attw.json b/packages/eslint-plugin-query/.attw.json new file mode 100644 index 0000000000..329bfe8343 --- /dev/null +++ b/packages/eslint-plugin-query/.attw.json @@ -0,0 +1,3 @@ +{ + "ignoreRules": ["false-export-default"] +} diff --git a/packages/eslint-plugin-query/src/__tests__/configs.test.ts b/packages/eslint-plugin-query/src/__tests__/configs.test.ts deleted file mode 100644 index ee73289f90..0000000000 --- a/packages/eslint-plugin-query/src/__tests__/configs.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { configs } from '../configs' - -describe('configs', () => { - it('should match snapshot', () => { - expect(configs).toMatchInlineSnapshot(` - { - "recommended": { - "plugins": [ - "@tanstack/eslint-plugin-query", - ], - "rules": { - "@tanstack/query/exhaustive-deps": "error", - "@tanstack/query/no-rest-destructuring": "warn", - "@tanstack/query/stable-query-client": "error", - }, - }, - } - `) - }) -}) diff --git a/packages/eslint-plugin-query/src/configs.ts b/packages/eslint-plugin-query/src/configs.ts deleted file mode 100644 index 12d23f0d5b..0000000000 --- a/packages/eslint-plugin-query/src/configs.ts +++ /dev/null @@ -1,34 +0,0 @@ -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, - ExtraRuleDocs, - ESLintUtils.RuleListener - > - >, -) { - return Object.entries(allRules).reduce( - (memo, [name, rule]) => { - const { recommended } = rule.meta.docs || {} - - return { - ...memo, - ...(recommended ? { [`@tanstack/query/${name}`]: recommended } : {}), - } - }, - {} as Record, - ) -} - -export const configs = { - recommended: { - plugins: ['@tanstack/eslint-plugin-query'], - rules: generateRecommendedConfig(rules), - }, -} diff --git a/packages/eslint-plugin-query/src/index.ts b/packages/eslint-plugin-query/src/index.ts index eef4c020b5..9a8e387b20 100644 --- a/packages/eslint-plugin-query/src/index.ts +++ b/packages/eslint-plugin-query/src/index.ts @@ -1,2 +1,47 @@ -export { configs } from './configs' -export { rules } from './rules' +import { rules } from './rules' +import type { ESLint, Linter } from 'eslint' +import type { RuleModule } from '@typescript-eslint/utils/ts-eslint' + +type RuleKey = keyof typeof rules + +interface Plugin extends Omit { + rules: Record> + configs: Record< + string, + ESLint.ConfigData | Linter.FlatConfig | Array + > +} + +const plugin: Plugin = { + meta: { + name: '@tanstack/eslint-plugin-query', + }, + configs: {}, + rules, +} + +// Assign configs here so we can reference `plugin` +Object.assign(plugin.configs, { + recommended: { + plugins: ['@tanstack/eslint-plugin-query'], + rules: { + '@tanstack/query/exhaustive-deps': 'error', + '@tanstack/query/no-rest-destructuring': 'warn', + '@tanstack/query/stable-query-client': 'error', + }, + }, + 'flat/recommended': [ + { + plugins: { + '@tanstack/query': plugin, + }, + rules: { + '@tanstack/query/exhaustive-deps': 'error', + '@tanstack/query/no-rest-destructuring': 'warn', + '@tanstack/query/stable-query-client': 'error', + }, + }, + ], +}) + +export default plugin diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f9efa7436..f12e7a998c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,8 +14,8 @@ importers: .: devDependencies: '@arethetypeswrong/cli': - specifier: ^0.15.3 - version: 0.15.3 + specifier: ^0.16.0 + version: 0.16.0 '@cspell/eslint-plugin': specifier: ^8.9.1 version: 8.9.1(eslint@8.57.0) @@ -2546,8 +2546,8 @@ packages: peerDependencies: ajv: '>=8' - '@arethetypeswrong/cli@0.15.3': - resolution: {integrity: sha512-sIMA9ZJBWDEg1+xt5RkAEflZuf8+PO8SdKj17x6PtETuUho+qlZJg4DgmKc3q+QwQ9zOB5VLK6jVRbFdNLdUIA==} + '@arethetypeswrong/cli@0.16.0': + resolution: {integrity: sha512-Vn3ihwlhueIvyJ6V3PKS8zwll9TId5Radvl3GS58ITimafJNoYRribKCoymYFiFS3jH6TspM30KhhiMvnMGvNQ==} engines: {node: '>=18'} hasBin: true @@ -19053,7 +19053,7 @@ snapshots: jsonpointer: 5.0.1 leven: 3.1.0 - '@arethetypeswrong/cli@0.15.3': + '@arethetypeswrong/cli@0.16.0': dependencies: '@arethetypeswrong/core': 0.15.1 chalk: 4.1.2 @@ -19062,6 +19062,7 @@ snapshots: marked: 9.1.6 marked-terminal: 6.2.0(marked@9.1.6) semver: 7.6.2 + which-pm-runs: 1.1.0 '@arethetypeswrong/core@0.15.1': dependencies: