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,250 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createSignal } from 'solid-js'
import { render } from '@solidjs/testing-library'
import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
import { TanstackQueryDevtools } from '@tanstack/query-devtools'
import SolidQueryDevtools from '../devtools'
import type {
DevtoolsButtonPosition,
DevtoolsErrorType,
DevtoolsPosition,
Theme,
} from '@tanstack/query-devtools'
describe('SolidQueryDevtools', () => {
let queryClient: QueryClient
beforeEach(() => {
queryClient = new QueryClient()
})
afterEach(() => {
vi.restoreAllMocks()
})
it('should throw an error if no query client has been set', () => {
expect(() => render(() => <SolidQueryDevtools />)).toThrow(
'No QueryClient set, use QueryClientProvider to set one',
)
})
it('should not throw an error if query client is provided via context', () => {
expect(() =>
render(() => (
<QueryClientProvider client={queryClient}>
<SolidQueryDevtools />
</QueryClientProvider>
)),
).not.toThrow()
})
it('should not throw an error if query client is provided via props', () => {
expect(() =>
render(() => <SolidQueryDevtools client={queryClient} />),
).not.toThrow()
})
it('should forward "buttonPosition" to the devtools instance', () => {
const setButtonPosition = vi.spyOn(
TanstackQueryDevtools.prototype,
'setButtonPosition',
)
render(() => (
<SolidQueryDevtools client={queryClient} buttonPosition="top-left" />
))
expect(setButtonPosition).toHaveBeenCalledWith('top-left')
})
it('should forward "position" to the devtools instance', () => {
const setPosition = vi.spyOn(TanstackQueryDevtools.prototype, 'setPosition')
render(() => <SolidQueryDevtools client={queryClient} position="left" />)
expect(setPosition).toHaveBeenCalledWith('left')
})
it('should forward "initialIsOpen" to the devtools instance', () => {
const setInitialIsOpen = vi.spyOn(
TanstackQueryDevtools.prototype,
'setInitialIsOpen',
)
render(() => (
<SolidQueryDevtools client={queryClient} initialIsOpen={true} />
))
expect(setInitialIsOpen).toHaveBeenCalledWith(true)
})
it('should default "initialIsOpen" to "false" when the prop is omitted', () => {
const setInitialIsOpen = vi.spyOn(
TanstackQueryDevtools.prototype,
'setInitialIsOpen',
)
render(() => <SolidQueryDevtools client={queryClient} />)
expect(setInitialIsOpen).toHaveBeenCalledWith(false)
})
it('should forward "errorTypes" to the devtools instance', () => {
const setErrorTypes = vi.spyOn(
TanstackQueryDevtools.prototype,
'setErrorTypes',
)
const errorTypes = [
{ name: 'Network', initializer: () => new Error('Network') },
]
render(() => (
<SolidQueryDevtools client={queryClient} errorTypes={errorTypes} />
))
expect(setErrorTypes).toHaveBeenCalledWith(errorTypes)
})
it('should default "errorTypes" to an empty array when the prop is omitted', () => {
const setErrorTypes = vi.spyOn(
TanstackQueryDevtools.prototype,
'setErrorTypes',
)
render(() => <SolidQueryDevtools client={queryClient} />)
expect(setErrorTypes).toHaveBeenCalledWith([])
})
it('should forward "theme" to the devtools instance', () => {
const setTheme = vi.spyOn(TanstackQueryDevtools.prototype, 'setTheme')
render(() => <SolidQueryDevtools client={queryClient} theme="dark" />)
expect(setTheme).toHaveBeenCalledWith('dark')
})
it('should default "theme" to "system" when the prop is omitted', () => {
const setTheme = vi.spyOn(TanstackQueryDevtools.prototype, 'setTheme')
render(() => <SolidQueryDevtools client={queryClient} />)
expect(setTheme).toHaveBeenCalledWith('system')
})
it('should forward the resolved "QueryClient" via "setClient"', () => {
const setClient = vi.spyOn(TanstackQueryDevtools.prototype, 'setClient')
render(() => <SolidQueryDevtools client={queryClient} />)
expect(setClient).toHaveBeenCalledWith(queryClient)
})
it('should forward a "buttonPosition" change to the devtools instance after mount', () => {
const setButtonPosition = vi.spyOn(
TanstackQueryDevtools.prototype,
'setButtonPosition',
)
const [buttonPosition, setButtonPositionSignal] =
createSignal<DevtoolsButtonPosition>('bottom-right')
render(() => (
<SolidQueryDevtools
client={queryClient}
buttonPosition={buttonPosition()}
/>
))
setButtonPosition.mockClear()
setButtonPositionSignal('top-left')
expect(setButtonPosition).toHaveBeenCalledWith('top-left')
})
it('should forward a "position" change to the devtools instance after mount', () => {
const setPosition = vi.spyOn(TanstackQueryDevtools.prototype, 'setPosition')
const [position, setPositionSignal] =
createSignal<DevtoolsPosition>('bottom')
render(() => (
<SolidQueryDevtools client={queryClient} position={position()} />
))
setPosition.mockClear()
setPositionSignal('top')
expect(setPosition).toHaveBeenCalledWith('top')
})
it('should forward an "initialIsOpen" change to the devtools instance after mount', () => {
const setInitialIsOpen = vi.spyOn(
TanstackQueryDevtools.prototype,
'setInitialIsOpen',
)
const [initialIsOpen, setInitialIsOpenSignal] = createSignal(false)
render(() => (
<SolidQueryDevtools
client={queryClient}
initialIsOpen={initialIsOpen()}
/>
))
setInitialIsOpen.mockClear()
setInitialIsOpenSignal(true)
expect(setInitialIsOpen).toHaveBeenCalledWith(true)
})
it('should forward an "errorTypes" change to the devtools instance after mount', () => {
const setErrorTypes = vi.spyOn(
TanstackQueryDevtools.prototype,
'setErrorTypes',
)
const [errorTypes, setErrorTypesSignal] = createSignal<
Array<DevtoolsErrorType>
>([])
render(() => (
<SolidQueryDevtools client={queryClient} errorTypes={errorTypes()} />
))
setErrorTypes.mockClear()
const nextErrorTypes = [
{ name: 'Network', initializer: () => new Error('Network') },
]
setErrorTypesSignal(nextErrorTypes)
expect(setErrorTypes).toHaveBeenCalledWith(nextErrorTypes)
})
it('should forward a "theme" change to the devtools instance after mount', () => {
const setTheme = vi.spyOn(TanstackQueryDevtools.prototype, 'setTheme')
const [theme, setThemeSignal] = createSignal<Theme>('light')
render(() => <SolidQueryDevtools client={queryClient} theme={theme()} />)
setTheme.mockClear()
setThemeSignal('dark')
expect(setTheme).toHaveBeenCalledWith('dark')
})
it('should call "unmount" on the devtools instance when the component unmounts', () => {
const unmount = vi.spyOn(TanstackQueryDevtools.prototype, 'unmount')
const { unmount: unmountComponent } = render(() => (
<SolidQueryDevtools client={queryClient} />
))
unmountComponent()
expect(unmount).toHaveBeenCalled()
})
it('should return null in non-development environments', async () => {
vi.doMock('solid-js/web', async (importOriginal) => {
const actual = await importOriginal()
return Object.assign({}, actual, { isDev: false })
})
vi.resetModules()
try {
const { SolidQueryDevtools: ProductionDevtools } = await import('..')
expect(ProductionDevtools({})).toBeNull()
} finally {
vi.doUnmock('solid-js/web')
vi.resetModules()
}
})
})

View File

@@ -0,0 +1,170 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { render } from '@solidjs/testing-library'
import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'
import { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'
import SolidQueryDevtoolsPanel from '../devtoolsPanel'
describe('SolidQueryDevtoolsPanel', () => {
let queryClient: QueryClient
beforeEach(() => {
queryClient = new QueryClient()
})
afterEach(() => {
vi.restoreAllMocks()
})
it('should throw an error if no query client has been set', () => {
expect(() => render(() => <SolidQueryDevtoolsPanel />)).toThrow(
'No QueryClient set, use QueryClientProvider to set one',
)
})
it('should not throw an error if query client is provided via context', () => {
expect(() =>
render(() => (
<QueryClientProvider client={queryClient}>
<SolidQueryDevtoolsPanel />
</QueryClientProvider>
)),
).not.toThrow()
})
it('should not throw an error if query client is provided via props', () => {
expect(() =>
render(() => <SolidQueryDevtoolsPanel client={queryClient} />),
).not.toThrow()
})
it('should forward "onClose" to the devtools instance', () => {
const setOnClose = vi.spyOn(
TanstackQueryDevtoolsPanel.prototype,
'setOnClose',
)
const onClose = vi.fn()
render(() => (
<SolidQueryDevtoolsPanel client={queryClient} onClose={onClose} />
))
expect(setOnClose).toHaveBeenCalledWith(onClose)
})
it('should default "onClose" to a no-op function when the prop is omitted', () => {
const setOnClose = vi.spyOn(
TanstackQueryDevtoolsPanel.prototype,
'setOnClose',
)
render(() => <SolidQueryDevtoolsPanel client={queryClient} />)
const forwarded = setOnClose.mock.calls[0]![0]
expect(forwarded).toBeInstanceOf(Function)
expect(forwarded()).toBeUndefined()
})
it('should forward "errorTypes" to the devtools instance', () => {
const setErrorTypes = vi.spyOn(
TanstackQueryDevtoolsPanel.prototype,
'setErrorTypes',
)
const errorTypes = [
{ name: 'Network', initializer: () => new Error('Network') },
]
render(() => (
<SolidQueryDevtoolsPanel client={queryClient} errorTypes={errorTypes} />
))
expect(setErrorTypes).toHaveBeenCalledWith(errorTypes)
})
it('should default "errorTypes" to an empty array when the prop is omitted', () => {
const setErrorTypes = vi.spyOn(
TanstackQueryDevtoolsPanel.prototype,
'setErrorTypes',
)
render(() => <SolidQueryDevtoolsPanel client={queryClient} />)
expect(setErrorTypes).toHaveBeenCalledWith([])
})
it('should forward "theme" to the devtools instance', () => {
const setTheme = vi.spyOn(TanstackQueryDevtoolsPanel.prototype, 'setTheme')
render(() => <SolidQueryDevtoolsPanel client={queryClient} theme="dark" />)
expect(setTheme).toHaveBeenCalledWith('dark')
})
it('should default "theme" to "system" when the prop is omitted', () => {
const setTheme = vi.spyOn(TanstackQueryDevtoolsPanel.prototype, 'setTheme')
render(() => <SolidQueryDevtoolsPanel client={queryClient} />)
expect(setTheme).toHaveBeenCalledWith('system')
})
it('should forward the resolved "QueryClient" via "setClient"', () => {
const setClient = vi.spyOn(
TanstackQueryDevtoolsPanel.prototype,
'setClient',
)
render(() => <SolidQueryDevtoolsPanel client={queryClient} />)
expect(setClient).toHaveBeenCalledWith(queryClient)
})
it('should preserve the default container height when "style" omits "height"', () => {
const { container } = render(() => (
<SolidQueryDevtoolsPanel
client={queryClient}
style={{ width: '300px' }}
/>
))
expect(container.querySelector('.tsqd-parent-container')).toHaveStyle({
height: '500px',
width: '300px',
})
})
it('should let "style" override the default container height on the rendered element', () => {
const { container } = render(() => (
<SolidQueryDevtoolsPanel
client={queryClient}
style={{ width: '300px', height: '300px' }}
/>
))
expect(container.querySelector('.tsqd-parent-container')).toHaveStyle({
height: '300px',
width: '300px',
})
})
it('should call "unmount" on the devtools instance when the component unmounts', () => {
const unmount = vi.spyOn(TanstackQueryDevtoolsPanel.prototype, 'unmount')
const { unmount: unmountComponent } = render(() => (
<SolidQueryDevtoolsPanel client={queryClient} />
))
unmountComponent()
expect(unmount).toHaveBeenCalled()
})
it('should return null in non-development environments', async () => {
vi.doMock('solid-js/web', async (importOriginal) => {
const actual = await importOriginal()
return Object.assign({}, actual, { isDev: false })
})
vi.resetModules()
try {
const { SolidQueryDevtoolsPanel: ProductionDevtoolsPanel } =
await import('..')
expect(ProductionDevtoolsPanel({})).toBeNull()
} finally {
vi.doUnmock('solid-js/web')
vi.resetModules()
}
})
})

View File

@@ -0,0 +1,43 @@
import {
createMemo,
createSignal,
onMount,
sharedConfig,
splitProps,
untrack,
} from 'solid-js'
import { isServer } from 'solid-js/web'
import type { Component, ComponentProps, JSX } from 'solid-js'
/*
This function has been taken from solid-start's codebase
This allows the devtools to be loaded only on the client and bypasses any server side rendering
https://github.com/solidjs/solid-start/blob/2967fc2db3f0df826f061020231dbdafdfa0746b/packages/start/islands/clientOnly.tsx
*/
export default function clientOnly<T extends Component<any>>(
fn: () => Promise<{
default: T
}>,
) {
if (isServer)
return (props: ComponentProps<T> & { fallback?: JSX.Element }) =>
props.fallback
const [comp, setComp] = createSignal<T>()
fn().then((m) => setComp(() => m.default))
return (props: ComponentProps<T>) => {
let Comp: T | undefined
let m: boolean
const [, rest] = splitProps(props, ['fallback'])
if ((Comp = comp()) && !sharedConfig.context) return Comp(rest)
const [mounted, setMounted] = createSignal(!sharedConfig.context)
onMount(() => setMounted(true))
return createMemo(
() => (
(Comp = comp()),
(m = mounted()),
untrack(() => (Comp && m ? Comp(rest) : props.fallback))
),
)
}
}

View File

@@ -0,0 +1,111 @@
import { createEffect, createMemo, onCleanup, onMount } from 'solid-js'
import { onlineManager, useQueryClient } from '@tanstack/solid-query'
import { TanstackQueryDevtools } from '@tanstack/query-devtools'
import type {
DevtoolsButtonPosition,
DevtoolsErrorType,
DevtoolsPosition,
Theme,
} from '@tanstack/query-devtools'
import type { QueryClient } from '@tanstack/solid-query'
interface DevtoolsOptions {
/**
* Set this true if you want the dev tools to default to being open
*/
initialIsOpen?: boolean
/**
* The position of the TanStack logo to open and close the devtools panel.
* 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'relative'
* Defaults to 'bottom-right'.
*/
buttonPosition?: DevtoolsButtonPosition
/**
* The position of the Solid Query devtools panel.
* 'top' | 'bottom' | 'left' | 'right'
* Defaults to 'bottom'.
*/
position?: DevtoolsPosition
/**
* Custom instance of QueryClient
*/
client?: QueryClient
/**
* Use this so you can define custom errors that can be shown in the devtools.
*/
errorTypes?: Array<DevtoolsErrorType>
/**
* Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
*/
styleNonce?: string
/**
* Use this so you can attach the devtool's styles to specific element in the DOM.
*/
shadowDOMTarget?: ShadowRoot
/**
* Set this to true to hide disabled queries from the devtools panel.
*/
hideDisabledQueries?: boolean
/**
* Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.
* Defaults to 'system'.
*/
theme?: Theme
}
export default function SolidQueryDevtools(props: DevtoolsOptions) {
const queryClient = useQueryClient(props.client)
const client = createMemo(() => queryClient)
let ref!: HTMLDivElement
const devtools = new TanstackQueryDevtools({
client: client(),
queryFlavor: 'Solid Query',
version: '5',
onlineManager,
buttonPosition: props.buttonPosition,
position: props.position,
initialIsOpen: props.initialIsOpen,
errorTypes: props.errorTypes,
styleNonce: props.styleNonce,
shadowDOMTarget: props.shadowDOMTarget,
hideDisabledQueries: props.hideDisabledQueries,
theme: props.theme,
})
createEffect(() => {
devtools.setClient(client())
})
createEffect(() => {
const buttonPos = props.buttonPosition
if (buttonPos) {
devtools.setButtonPosition(buttonPos)
}
})
createEffect(() => {
const pos = props.position
if (pos) {
devtools.setPosition(pos)
}
})
createEffect(() => {
devtools.setInitialIsOpen(props.initialIsOpen || false)
})
createEffect(() => {
devtools.setErrorTypes(props.errorTypes || [])
})
createEffect(() => {
devtools.setTheme(props.theme || 'system')
})
onMount(() => {
devtools.mount(ref)
onCleanup(() => devtools.unmount())
})
return <div class="tsqd-parent-container" ref={ref}></div>
}

View File

@@ -0,0 +1,96 @@
import { createEffect, createMemo, onCleanup, onMount } from 'solid-js'
import { onlineManager, useQueryClient } from '@tanstack/solid-query'
import { TanstackQueryDevtoolsPanel } from '@tanstack/query-devtools'
import type { DevtoolsErrorType, Theme } from '@tanstack/query-devtools'
import type { QueryClient } from '@tanstack/solid-query'
import type { JSX } from 'solid-js'
export interface DevtoolsPanelOptions {
/**
* Custom instance of QueryClient
*/
client?: QueryClient
/**
* Use this so you can define custom errors that can be shown in the devtools.
*/
errorTypes?: Array<DevtoolsErrorType>
/**
* Use this to pass a nonce to the style tag that is added to the document head. This is useful if you are using a Content Security Policy (CSP) nonce to allow inline styles.
*/
styleNonce?: string
/**
* Use this so you can attach the devtool's styles to specific element in the DOM.
*/
shadowDOMTarget?: ShadowRoot
/**
* Custom styles for the devtools panel
* @default { height: '500px' }
* @example { height: '100%' }
* @example { height: '100%', width: '100%' }
*/
style?: JSX.CSSProperties
/**
* Callback function that is called when the devtools panel is closed
*/
onClose?: () => void
/**
* Set this to true to hide disabled queries from the devtools panel.
*/
hideDisabledQueries?: boolean
/**
* Set this to 'light', 'dark', or 'system' to change the theme of the devtools panel.
* Defaults to 'system'.
*/
theme?: Theme
}
export default function SolidQueryDevtoolsPanel(props: DevtoolsPanelOptions) {
const queryClient = useQueryClient(props.client)
const client = createMemo(() => queryClient)
let ref!: HTMLDivElement
const { errorTypes, styleNonce, shadowDOMTarget, hideDisabledQueries } = props
const devtools = new TanstackQueryDevtoolsPanel({
client: client(),
queryFlavor: 'Solid Query',
version: '5',
onlineManager,
buttonPosition: 'bottom-left',
position: 'bottom',
initialIsOpen: true,
errorTypes,
styleNonce,
shadowDOMTarget,
onClose: props.onClose,
hideDisabledQueries,
theme: props.theme,
})
createEffect(() => {
devtools.setClient(client())
})
createEffect(() => {
devtools.setOnClose(props.onClose ?? (() => {}))
})
createEffect(() => {
devtools.setErrorTypes(props.errorTypes || [])
})
createEffect(() => {
devtools.setTheme(props.theme || 'system')
})
onMount(() => {
devtools.mount(ref)
onCleanup(() => devtools.unmount())
})
return (
<div
style={{ height: '500px', ...props.style }}
class="tsqd-parent-container"
ref={ref}
/>
)
}

View File

@@ -0,0 +1,18 @@
import { isDev } from 'solid-js/web'
import clientOnly from './clientOnly'
import type SolidQueryDevtoolsComp from './devtools'
import type SolidQueryDevtoolsCompPanel from './devtoolsPanel'
export const SolidQueryDevtools: typeof SolidQueryDevtoolsComp = isDev
? clientOnly(() => import('./devtools'))
: function () {
return null
}
export const SolidQueryDevtoolsPanel: typeof SolidQueryDevtoolsCompPanel = isDev
? clientOnly(() => import('./devtoolsPanel'))
: function () {
return null
}
export type { DevtoolsPanelOptions } from './devtoolsPanel'