snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import pluginQuery from '@tanstack/eslint-plugin-query'
import tseslint from 'typescript-eslint'
export default [
...tseslint.configs.recommended,
...pluginQuery.configs['flat/recommended-strict'],
{
files: ['src/**/*.ts', 'src/**/*.tsx'],
rules: {
'@tanstack/query/exhaustive-deps': [
'error',
{
allowlist: {
variables: ['api'],
types: ['AnalyticsClient'],
},
},
],
},
},
]

View File

@@ -0,0 +1,27 @@
{
"name": "@tanstack/query-example-eslint-plugin-demo",
"private": true,
"type": "module",
"scripts": {
"test:eslint": "eslint ./src"
},
"dependencies": {
"@tanstack/react-query": "^5.102.8",
"react": "^19.0.0"
},
"devDependencies": {
"@tanstack/eslint-plugin-query": "^5.102.8",
"eslint": "^9.39.0",
"typescript": "5.8.3",
"typescript-eslint": "^8.48.0"
},
"nx": {
"targets": {
"test:eslint": {
"dependsOn": [
"^build"
]
}
}
}
}

View File

@@ -0,0 +1,55 @@
import { queryOptions } from '@tanstack/react-query'
export function todosOptions(userId: string) {
const api = useApiClient()
return queryOptions({
// ✅ passes: 'api' is in allowlist.variables
queryKey: ['todos', userId],
queryFn: () => api.fetchTodos(userId),
})
}
export function todosByApiOptions(userId: string) {
const todoApi = useApiClient()
// ❌ fails: 'api' is in allowlist.variables, but this variable is named 'todoApi'
// eslint-disable-next-line @tanstack/query/exhaustive-deps -- The following dependencies are missing in your queryKey: todoApi
return queryOptions({
queryKey: ['todos', userId],
queryFn: () => todoApi.fetchTodos(userId),
})
}
export function todosWithTrackingOptions(
tracker: AnalyticsClient,
userId: string,
) {
return queryOptions({
// ✅ passes: AnalyticsClient is in allowlist.types
queryKey: ['todos', userId],
queryFn: async () => {
tracker.track('todos')
return fetch(`/api/todos?userId=${userId}`).then((r) => r.json())
},
})
}
export function todosWithClientOptions(client: ApiClient, userId: string) {
// ❌ fails: AnalyticsClient is in allowlist.types, but this param is typed as ApiClient
// eslint-disable-next-line @tanstack/query/exhaustive-deps -- The following dependencies are missing in your queryKey: client
return queryOptions({
queryKey: ['todos', userId],
queryFn: () => client.fetchTodos(userId),
})
}
interface ApiClient {
fetchTodos: (userId: string) => Promise<Array<{ id: string }>>
}
interface AnalyticsClient {
track: (event: string) => Promise<void>
}
function useApiClient(): ApiClient {
throw new Error('not implemented')
}

View File

@@ -0,0 +1,49 @@
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { todoOptions, todosOptions } from './queries'
// ✅ passes: consuming imported queryOptions result directly
export function Todos() {
const query = useQuery(todosOptions)
return query.data
}
// ✅ passes: spreading imported queryOptions result with additional options
export function Todo({ id }: { id: string }) {
const query = useQuery({
...todoOptions(id),
select: (data) => data.title,
})
return query.data
}
// ✅ passes: referencing queryKey from imported queryOptions result
export function invalidateTodos() {
const queryClient = useQueryClient()
queryClient.invalidateQueries({ queryKey: todosOptions.queryKey })
}
// ❌ fails: inline queryKey + queryFn should use queryOptions()
export function TodosBad() {
const query = useQuery(
// eslint-disable-next-line @tanstack/query/prefer-query-options -- Prefer using queryOptions() or infiniteQueryOptions() to co-locate queryKey and queryFn.
{
queryKey: ['todos'],
queryFn: () => fetch('/api/todos').then((r) => r.json()),
},
)
return query.data
}
// ❌ fails: inline queryKey should reference queryOptions result
export function InvalidateTodosBad() {
const queryClient = useQueryClient()
// eslint-disable-next-line @tanstack/query/prefer-query-options -- Prefer referencing a queryKey from a queryOptions() result instead of typing it manually.
queryClient.invalidateQueries({ queryKey: ['todos'] })
}
// ❌ fails: inline queryKey as direct parameter
export function GetTodosDataBad() {
const queryClient = useQueryClient()
// eslint-disable-next-line @tanstack/query/prefer-query-options -- Prefer referencing a queryKey from a queryOptions() result instead of typing it manually.
return queryClient.getQueryData(['todos'])
}

View File

@@ -0,0 +1,23 @@
import { queryOptions } from '@tanstack/react-query'
// ✅ passes: queryKey and queryFn are co-located via queryOptions()
export const todosOptions = queryOptions({
queryKey: ['todos'],
queryFn: () => fetchTodos(),
})
// ✅ passes: factory function wrapping queryOptions()
export const todoOptions = (id: string) =>
queryOptions({
queryKey: ['todo', id],
queryFn: () => fetchTodo(id),
})
function fetchTodos(): Promise<Array<{ id: string; title: string }>> {
throw new Error('not implemented')
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function fetchTodo(id: string): Promise<{ id: string; title: string }> {
throw new Error('not implemented')
}

View File

@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "Bundler",
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"strict": true
},
"include": ["src", "eslint.config.js"]
}