Skip to content
Open
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
28 changes: 26 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
// @ts-check

// @ts-ignore Needed due to moduleResolution Node vs Bundler
import { tanstackConfig } from '@tanstack/eslint-config'
import pluginCspell from '@cspell/eslint-plugin'
import unusedImports from 'eslint-plugin-unused-imports'
import vitest from '@vitest/eslint-plugin'
import oxlint from 'eslint-plugin-oxlint'
import { createJiti } from 'jiti'

export default [
const jiti = createJiti(import.meta.url)
const oxlintConfig = /** @type {*} */ (await jiti.import('./oxlint.config.ts'))
.default

/** @type {import('eslint').Linter.Config[]} */
const config = [
...tanstackConfig,
{
name: 'tanstack/temp',
plugins: {
cspell: pluginCspell,
'unused-imports': unusedImports,
},
rules: {
'cspell/spellchecker': [
Expand Down Expand Up @@ -44,7 +52,19 @@ export default [
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-unsafe-function-type': 'off',
'no-case-declarations': 'off',
'no-shadow': 'off',
'pnpm/enforce-catalog': 'off',
'pnpm/json-enforce-catalog': 'off',
'prefer-const': 'off',
'unused-imports/no-unused-imports': 'warn',
},
},
{
name: 'tanstack/linter-options',
linterOptions: {
// eslint-disable comments are shared with oxlint β€” don't warn
// about directives ESLint considers unused
reportUnusedDisableDirectives: 'off',
},
},
{
Expand All @@ -61,4 +81,8 @@ export default [
},
settings: { vitest: { typecheck: true } },
},
// Must be last β€” disables ESLint rules that oxlint already covers
...oxlint.buildFromOxlintConfig(oxlintConfig),
]

export default config
5 changes: 4 additions & 1 deletion examples/react/algolia/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { tanstackConfig } from '@tanstack/eslint-config'
import pluginQuery from '@tanstack/eslint-plugin-query'
import pluginReact from '@eslint-react/eslint-plugin'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...tanstackConfig,
...pluginQuery.configs['flat/recommended'],
pluginReact.configs.recommended,
]

export default config
5 changes: 4 additions & 1 deletion examples/react/basic-graphql-request/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { tanstackConfig } from '@tanstack/eslint-config'
import pluginQuery from '@tanstack/eslint-plugin-query'
import pluginReact from '@eslint-react/eslint-plugin'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...tanstackConfig,
...pluginQuery.configs['flat/recommended'],
pluginReact.configs.recommended,
]

export default config
5 changes: 4 additions & 1 deletion examples/react/basic/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { tanstackConfig } from '@tanstack/eslint-config'
import pluginQuery from '@tanstack/eslint-plugin-query'
import pluginReact from '@eslint-react/eslint-plugin'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...tanstackConfig,
...pluginQuery.configs['flat/recommended'],
pluginReact.configs.recommended,
]

export default config
5 changes: 4 additions & 1 deletion examples/react/eslint-plugin-demo/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import pluginQuery from '@tanstack/eslint-plugin-query'
import tseslint from 'typescript-eslint'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...tseslint.configs.recommended,
...pluginQuery.configs['flat/recommended'],
{
Expand All @@ -19,3 +20,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion examples/react/shadow-dom/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { tanstackConfig } from '@tanstack/eslint-config'
import pluginQuery from '@tanstack/eslint-plugin-query'
import pluginReact from '@eslint-react/eslint-plugin'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...tanstackConfig,
...pluginQuery.configs['flat/recommended'],
pluginReact.configs.recommended,
]

export default config
124 changes: 124 additions & 0 deletions oxlint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { defineConfig } from 'oxlint'

export default defineConfig({
plugins: ['typescript', 'vitest', 'import', 'react'],
categories: {
correctness: 'warn',
},
env: {
builtin: true,
browser: true,
node: true,
es2024: true,
},
rules: {
// Suppress tsconfig resolution noise in monorepo
'typescript/tsconfig-error': 'allow',
},
ignorePatterns: [
'**/dist',
'**/build',
'**/node_modules',
'**/coverage',
'**/examples',
'**/integrations',
],
overrides: [
{
files: [
'**/*.ts',
'**/*.tsx',
'**/*.js',
'**/*.jsx',
'**/*.cjs',
'**/*.mjs',
],
rules: {
// ── JavaScript rules (from @tanstack/eslint-config) ──
'for-direction': 'error',
'no-async-promise-executor': 'error',
'no-compare-neg-zero': 'error',
'no-cond-assign': 'error',
'no-constant-binary-expression': 'error',
'no-constant-condition': 'error',
'no-control-regex': 'error',
'no-debugger': 'error',
'no-delete-var': 'error',
'no-dupe-else-if': 'error',
'no-duplicate-case': 'error',
'no-empty-character-class': 'error',
'no-empty-pattern': 'error',
'no-empty-static-block': 'error',
'no-ex-assign': 'error',
'no-extra-boolean-cast': 'error',
'no-fallthrough': 'error',
'no-global-assign': 'error',
'no-invalid-regexp': 'error',
'no-irregular-whitespace': 'error',
'no-loss-of-precision': 'error',
'no-misleading-character-class': 'error',
'no-nonoctal-decimal-escape': 'error',
'no-regex-spaces': 'error',
'no-self-assign': 'error',
'no-shadow': 'allow',
'no-shadow-restricted-names': 'error',
'no-sparse-arrays': 'error',
'no-unsafe-finally': 'error',
'no-unsafe-optional-chaining': 'error',
'no-unused-labels': 'error',
'no-unused-private-class-members': 'error',
'no-useless-backreference': 'error',
'no-useless-catch': 'error',
'no-useless-escape': 'error',
'no-var': 'error',
'require-yield': 'error',
'use-isnan': 'error',
'valid-typeof': 'error',

// Overridden to 'off' in eslint.config.js
'no-case-declarations': 'allow',
'prefer-const': 'allow',

// ── TypeScript rules (from @tanstack/eslint-config) ──
// ban-ts-comment: warn because oxlint doesn't support the granular
// options that allow @ts-expect-error without description β€” ESLint
// still enforces the exact policy at error level
'@typescript-eslint/ban-ts-comment': 'warn',
'@typescript-eslint/no-duplicate-enum-values': 'error',
'@typescript-eslint/no-extra-non-null-assertion': 'error',
// no-inferrable-types: warn because oxlint doesn't support
// ignoreParameters option β€” ESLint handles the precise config
'@typescript-eslint/no-inferrable-types': 'warn',
'@typescript-eslint/no-misused-new': 'error',
'@typescript-eslint/no-namespace': 'error',
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error',
'@typescript-eslint/prefer-as-const': 'error',
'@typescript-eslint/no-wrapper-object-types': 'error',
'@typescript-eslint/triple-slash-reference': 'error',

// Overridden to 'off' in eslint.config.js
'@typescript-eslint/no-empty-function': 'allow',
'@typescript-eslint/no-unsafe-function-type': 'allow',
},
},
{
files: ['**/*.spec.ts*', '**/*.test.ts*', '**/*.test-d.ts*'],
rules: {
// ── Vitest rules (from @vitest/eslint-plugin recommended) ──
// expect-expect & no-standalone-expect: warn because oxlint doesn't
// support additionalTestBlockFunctions β€” ESLint handles the full config
'vitest/expect-expect': 'warn',
'vitest/no-conditional-expect': 'error',
'vitest/no-focused-tests': 'error',
'vitest/no-identical-title': 'error',
'vitest/no-import-node-test': 'error',
'vitest/no-standalone-expect': 'warn',
'vitest/valid-describe-callback': 'error',
'vitest/valid-expect': 'error',
'vitest/valid-title': 'error',
'vitest/no-commented-out-tests': 'error',
'vitest/no-disabled-tests': 'warn',
},
},
],
})
12 changes: 9 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
"scripts": {
"clean": "pnpm --filter \"./packages/**\" run clean",
"test": "pnpm run test:ci",
"test:pr": "nx affected --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build",
"test:ci": "nx run-many --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build",
"test:pr": "nx affected --targets=test:sherif,test:knip,test:docs,test:oxlint,test:eslint,test:lib,test:types,test:build,build",
"test:ci": "nx run-many --targets=test:sherif,test:knip,test:docs,test:oxlint,test:eslint,test:lib,test:types,test:build,build",
"test:oxlint": "oxlint -c oxlint.config.ts --quiet .",
"test:eslint": "nx affected --target=test:eslint",
"test:sherif": "sherif -i typescript -p \"./integrations/*\" -p \"./examples/*\"",
"test:size": "size-limit",
Expand All @@ -35,6 +36,7 @@
"includedScripts": [
"test:docs",
"test:knip",
"test:oxlint",
"test:sherif",
"test:size"
]
Expand All @@ -46,7 +48,7 @@
"@eslint-react/eslint-plugin": "^2.0.1",
"@size-limit/preset-small-lib": "^12.0.0",
"@svitejs/changesets-changelog-github-compact": "^1.2.0",
"@tanstack/eslint-config": "0.3.2",
"@tanstack/eslint-config": "0.4.0",
"@tanstack/typedoc-config": "0.3.1",
"@tanstack/vite-config": "0.4.3",
"@testing-library/jest-dom": "^6.8.0",
Expand All @@ -57,11 +59,15 @@
"@vitest/eslint-plugin": "^1.4.0",
"esbuild-plugin-file-path-extensions": "^2.1.4",
"eslint": "^9.36.0",
"eslint-plugin-oxlint": "^1.57.0",
"eslint-plugin-react-hooks": "^6.1.1",
"eslint-plugin-unused-imports": "^4.4.1",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need eslint-plugin-unused-imports? As far as I know, TypeScript will flag unused imports just fine

"jiti": "^2.6.1",
"jsdom": "^27.0.0",
"knip": "^6.0.2",
"markdown-link-extractor": "^4.0.2",
"nx": "22.1.3",
"oxlint": "^1.57.0",
"premove": "^4.0.0",
"prettier": "^3.7.4",
"prettier-plugin-svelte": "^3.4.0",
Expand Down
5 changes: 4 additions & 1 deletion packages/angular-query-experimental/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import vitest from '@vitest/eslint-plugin'
import rootConfig from './root.eslint.config.js'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...rootConfig,
{
plugins: { vitest },
Expand All @@ -22,3 +23,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion packages/angular-query-persist-client/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import pluginJsdoc from 'eslint-plugin-jsdoc'
import rootConfig from './root.eslint.config.js'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...rootConfig,
pluginJsdoc.configs['flat/recommended-typescript'],
{
Expand All @@ -29,3 +30,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion packages/eslint-plugin-query/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import vitest from '@vitest/eslint-plugin'
import rootConfig from './root.eslint.config.js'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...rootConfig,
{
plugins: { vitest },
Expand All @@ -18,3 +19,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion packages/preact-query-devtools/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import tseslint from 'typescript-eslint'

import rootConfig from './root.eslint.config.js'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...rootConfig,
...preact,
{
Expand Down Expand Up @@ -36,3 +37,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion packages/preact-query-persist-client/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import tseslint from 'typescript-eslint'

import rootConfig from './root.eslint.config.js'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...rootConfig,
...preact,
{
Expand Down Expand Up @@ -36,3 +37,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion packages/preact-query/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import tseslint from 'typescript-eslint'

import rootConfig from './root.eslint.config.js'

export default [
/** @type {import('eslint').Linter.Config[]} */
const config = [
...rootConfig,
...preact,
{
Expand Down Expand Up @@ -36,3 +37,5 @@ export default [
},
},
]

export default config
5 changes: 4 additions & 1 deletion packages/query-async-storage-persister/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@

import rootConfig from './root.eslint.config.js'

export default [...rootConfig]
/** @type {import('eslint').Linter.Config[]} */
const config = [...rootConfig]

export default config
Loading
Loading