diff --git a/docs/react/devtools.md b/docs/react/devtools.md index 171dff4caf9..df95fe49ad0 100644 --- a/docs/react/devtools.md +++ b/docs/react/devtools.md @@ -22,6 +22,7 @@ $ pnpm add @tanstack/react-query-devtools # or $ yarn add @tanstack/react-query-devtools ``` + For Next 13+ App Dir you must install it as a dev dependency for it to work. You can import the devtools like this: @@ -32,7 +33,6 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' By default, React Query Devtools are only included in bundles when `process.env.NODE_ENV === 'development'`, so you don't need to worry about excluding them during a production build. - ## Floating Mode Floating Mode will mount the devtools as a fixed, floating element in your app and provide a toggle in the corner of the screen to show and hide the devtools. This toggle state will be stored and remembered in localStorage across reloads. @@ -66,6 +66,8 @@ function App() { - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used. - `errorTypes?: { name: string; initializer: (query: Query) => TError}` - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error. +- `styleNonce?: string` + - 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. ## Devtools in production diff --git a/docs/solid/devtools.md b/docs/solid/devtools.md index 4f6ada51e45..3d14b17cc50 100644 --- a/docs/solid/devtools.md +++ b/docs/solid/devtools.md @@ -62,3 +62,5 @@ function App() { - Use this to use a custom QueryClient. Otherwise, the one from the nearest context will be used. - `errorTypes?: { name: string; initializer: (query: Query) => TError}` - Use this to predefine some errors that can be triggered on your queries. Initializer will be called (with the specific query) when that error is toggled on from the UI. It must return an Error. +- `styleNonce?: string` + - 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. diff --git a/packages/query-devtools/src/index.tsx b/packages/query-devtools/src/index.tsx index 39527376470..52436d9498e 100644 --- a/packages/query-devtools/src/index.tsx +++ b/packages/query-devtools/src/index.tsx @@ -1,5 +1,6 @@ import { render } from 'solid-js/web' import { createSignal, lazy } from 'solid-js' +import { setupStyleSheet } from './utils' import type { QueryClient, onlineManager as TonlineManager, @@ -14,7 +15,9 @@ import type { import type { Signal } from 'solid-js' export type { DevtoolsButtonPosition, DevtoolsPosition, DevToolsErrorType } -export interface TanstackQueryDevtoolsConfig extends QueryDevtoolsProps {} +export interface TanstackQueryDevtoolsConfig extends QueryDevtoolsProps { + styleNonce?: string +} class TanstackQueryDevtools { #client: Signal @@ -22,6 +25,7 @@ class TanstackQueryDevtools { #queryFlavor: string #version: string #isMounted = false + #styleNonce?: string #buttonPosition: Signal #position: Signal #initialIsOpen: Signal @@ -39,11 +43,13 @@ class TanstackQueryDevtools { position, initialIsOpen, errorTypes, + styleNonce, } = config this.#client = createSignal(client) this.#queryFlavor = queryFlavor this.#version = version this.#onlineManager = onlineManager + this.#styleNonce = styleNonce this.#buttonPosition = createSignal(buttonPosition) this.#position = createSignal(position) this.#initialIsOpen = createSignal(initialIsOpen) @@ -80,7 +86,6 @@ class TanstackQueryDevtools { const [isOpen] = this.#initialIsOpen const [errors] = this.#errorTypes const [queryClient] = this.#client - let Devtools: typeof DevtoolsComponent if (this.#Component) { @@ -90,6 +95,7 @@ class TanstackQueryDevtools { this.#Component = Devtools } + setupStyleSheet(this.#styleNonce) return ( { + if (!nonce) return + const styleExists = document.querySelector('#_goober') + if (styleExists) return + const styleTag = document.createElement('style') + const textNode = document.createTextNode('') + styleTag.appendChild(textNode) + styleTag.id = '_goober' + styleTag.setAttribute('nonce', nonce) + document.head.appendChild(styleTag) +} diff --git a/packages/react-query-devtools/src/devtools.tsx b/packages/react-query-devtools/src/devtools.tsx index 8befb8a58b1..b3dc0bccf14 100644 --- a/packages/react-query-devtools/src/devtools.tsx +++ b/packages/react-query-devtools/src/devtools.tsx @@ -35,6 +35,10 @@ export interface DevtoolsOptions { * Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array + /** + * 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 } export function ReactQueryDevtools( @@ -43,7 +47,8 @@ export function ReactQueryDevtools( const queryClient = useQueryClient() const client = props.client || queryClient const ref = useRef(null) - const { buttonPosition, position, initialIsOpen, errorTypes } = props + const { buttonPosition, position, initialIsOpen, errorTypes, styleNonce } = + props const [devtools] = useState( new TanstackQueryDevtools({ client: client, @@ -54,6 +59,7 @@ export function ReactQueryDevtools( position, initialIsOpen, errorTypes, + styleNonce, }), ) diff --git a/packages/solid-query-devtools/src/devtools.tsx b/packages/solid-query-devtools/src/devtools.tsx index 5d138cc97d0..d900608a780 100644 --- a/packages/solid-query-devtools/src/devtools.tsx +++ b/packages/solid-query-devtools/src/devtools.tsx @@ -44,6 +44,10 @@ export interface DevtoolsOptions { * Use this so you can define custom errors that can be shown in the devtools. */ errorTypes?: Array + /** + * 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 } export default function SolidQueryDevtools(props: DevtoolsOptions) { @@ -59,6 +63,7 @@ export default function SolidQueryDevtools(props: DevtoolsOptions) { position: props.position, initialIsOpen: props.initialIsOpen, errorTypes: props.errorTypes, + styleNonce: props.styleNonce, }) createEffect(() => { diff --git a/packages/svelte-query-devtools/src/Devtools.svelte b/packages/svelte-query-devtools/src/Devtools.svelte index 3eb2d6ad2ac..1a3df967b61 100644 --- a/packages/svelte-query-devtools/src/Devtools.svelte +++ b/packages/svelte-query-devtools/src/Devtools.svelte @@ -15,6 +15,7 @@ export let position: DevtoolsPosition = 'bottom' export let client: QueryClient = useQueryClient() export let errorTypes: Array = [] + export let styleNonce: string | undefined let ref: HTMLDivElement let devtools: TanstackQueryDevtools | undefined @@ -33,6 +34,7 @@ position, initialIsOpen, errorTypes, + styleNonce, }) devtools.mount(ref)