@tanstack/react-query-devtools 5.0.0-alpha.1 → 5.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/lib/Explorer.esm.js +2 -1
- package/build/lib/Explorer.esm.js.map +1 -1
- package/build/lib/Explorer.js +2 -1
- package/build/lib/Explorer.js.map +1 -1
- package/build/lib/Explorer.mjs +1 -0
- package/build/lib/Explorer.mjs.map +1 -1
- package/build/lib/devtools.d.ts +20 -2
- package/build/lib/devtools.esm.js +162 -34
- package/build/lib/devtools.esm.js.map +1 -1
- package/build/lib/devtools.js +161 -34
- package/build/lib/devtools.js.map +1 -1
- package/build/lib/devtools.mjs +106 -9
- package/build/lib/devtools.mjs.map +1 -1
- package/build/lib/index.esm.js +1 -0
- package/build/lib/index.esm.js.map +1 -1
- package/build/lib/index.js +1 -0
- package/build/lib/index.js.map +1 -1
- package/build/lib/index.mjs +1 -0
- package/build/lib/index.mjs.map +1 -1
- package/build/lib/index.prod.esm.js +165 -36
- package/build/lib/index.prod.esm.js.map +1 -1
- package/build/lib/index.prod.js +164 -36
- package/build/lib/index.prod.js.map +1 -1
- package/build/lib/index.prod.mjs +108 -10
- package/build/lib/index.prod.mjs.map +1 -1
- package/build/lib/styledComponents.d.ts +0 -1
- package/build/lib/styledComponents.esm.js +3 -1
- package/build/lib/styledComponents.esm.js.map +1 -1
- package/build/lib/styledComponents.js +3 -1
- package/build/lib/styledComponents.js.map +1 -1
- package/build/lib/styledComponents.mjs +3 -1
- package/build/lib/styledComponents.mjs.map +1 -1
- package/build/lib/theme.esm.js +1 -0
- package/build/lib/theme.esm.js.map +1 -1
- package/build/lib/theme.js +1 -0
- package/build/lib/theme.js.map +1 -1
- package/build/lib/theme.mjs +1 -0
- package/build/lib/theme.mjs.map +1 -1
- package/build/umd/index.development.js +107 -10
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/Explorer.test.tsx +3 -2
- package/src/__tests__/devtools.test.tsx +183 -9
- package/src/devtools.tsx +151 -3
- package/src/index.ts +2 -0
- package/src/styledComponents.ts +3 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.production.js","sources":["../../src/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.production.js","sources":["../../src/index.ts"],"sourcesContent":["'use client'\n\nimport * as devtools from './devtools'\n\nexport const ReactQueryDevtools: (typeof devtools)['ReactQueryDevtools'] =\n process.env.NODE_ENV !== 'development'\n ? function () {\n return null\n }\n : devtools.ReactQueryDevtools\n\nexport const ReactQueryDevtoolsPanel: (typeof devtools)['ReactQueryDevtoolsPanel'] =\n process.env.NODE_ENV !== 'development'\n ? (function () {\n return null\n } as any)\n : devtools.ReactQueryDevtoolsPanel\n"],"names":[],"mappings":"+QAMM,WACE,OAAO,IACT,4BAKC,WACC,OAAO,IACT"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-query-devtools",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.11",
|
|
4
4
|
"description": "Developer tools to interact with and visualize the TanStack/react-query cache",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"react": "^18.2.0",
|
|
44
44
|
"react-dom": "^18.2.0",
|
|
45
45
|
"react-error-boundary": "^3.1.4",
|
|
46
|
-
"@tanstack/react-query": "5.0.0-alpha.
|
|
46
|
+
"@tanstack/react-query": "5.0.0-alpha.10"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@tanstack/match-sorter-utils": "^8.7.0",
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": "^18.0.0",
|
|
54
54
|
"react-dom": "^18.0.0",
|
|
55
|
-
"@tanstack/react-query": "5.0.0-alpha.
|
|
55
|
+
"@tanstack/react-query": "5.0.0-alpha.10"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"clean": "rimraf ./build",
|
|
59
59
|
"test:eslint": "eslint --ext .ts,.tsx ./src",
|
|
60
60
|
"test:types": "tsc",
|
|
61
|
-
"test:lib": "
|
|
61
|
+
"test:lib": "vitest run --coverage",
|
|
62
62
|
"test:lib:dev": "pnpm run test:lib --watch",
|
|
63
63
|
"build:types": "tsc --build && cp build/lib/index.d.ts build/lib/index.prod.d.ts"
|
|
64
64
|
}
|
|
@@ -3,6 +3,7 @@ import * as React from 'react'
|
|
|
3
3
|
|
|
4
4
|
import { chunkArray, CopyButton, DefaultRenderer } from '../Explorer'
|
|
5
5
|
import { displayValue } from '../utils'
|
|
6
|
+
import { vi } from 'vitest'
|
|
6
7
|
|
|
7
8
|
describe('Explorer', () => {
|
|
8
9
|
describe('chunkArray', () => {
|
|
@@ -30,7 +31,7 @@ describe('Explorer', () => {
|
|
|
30
31
|
|
|
31
32
|
describe('DefaultRenderer', () => {
|
|
32
33
|
it('when the entry label is clicked, toggle expanded', async () => {
|
|
33
|
-
const toggleExpanded =
|
|
34
|
+
const toggleExpanded = vi.fn()
|
|
34
35
|
|
|
35
36
|
render(
|
|
36
37
|
<DefaultRenderer
|
|
@@ -90,7 +91,7 @@ describe('Explorer', () => {
|
|
|
90
91
|
})
|
|
91
92
|
|
|
92
93
|
it('when the copy button is clicked but there is an error, show error state', async () => {
|
|
93
|
-
const consoleMock =
|
|
94
|
+
const consoleMock = vi.spyOn(console, 'error')
|
|
94
95
|
consoleMock.mockImplementation(() => undefined)
|
|
95
96
|
|
|
96
97
|
// Mock clipboard with error state
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import { fireEvent, screen, waitFor, act } from '@testing-library/react'
|
|
3
3
|
import '@testing-library/jest-dom'
|
|
4
|
-
import { useQuery } from '@tanstack/react-query'
|
|
4
|
+
import { useQuery, onlineManager } from '@tanstack/react-query'
|
|
5
5
|
import { defaultPanelSize, sortFns } from '../utils'
|
|
6
6
|
import {
|
|
7
7
|
getByTextContent,
|
|
@@ -9,18 +9,27 @@ import {
|
|
|
9
9
|
sleep,
|
|
10
10
|
createQueryClient,
|
|
11
11
|
} from './utils'
|
|
12
|
+
import { vi } from 'vitest'
|
|
13
|
+
import UserEvent from '@testing-library/user-event'
|
|
14
|
+
|
|
15
|
+
class CustomError extends Error {
|
|
16
|
+
constructor(message: string) {
|
|
17
|
+
super(message)
|
|
18
|
+
this.name = 'CustomError'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
12
21
|
|
|
13
22
|
Object.defineProperty(window, 'matchMedia', {
|
|
14
23
|
writable: true,
|
|
15
|
-
value:
|
|
24
|
+
value: vi.fn().mockImplementation((query: string) => ({
|
|
16
25
|
matches: false,
|
|
17
26
|
media: query,
|
|
18
27
|
onchange: null,
|
|
19
|
-
addListener:
|
|
20
|
-
removeListener:
|
|
21
|
-
addEventListener:
|
|
22
|
-
removeEventListener:
|
|
23
|
-
dispatchEvent:
|
|
28
|
+
addListener: vi.fn(), // deprecated
|
|
29
|
+
removeListener: vi.fn(), // deprecated
|
|
30
|
+
addEventListener: vi.fn(),
|
|
31
|
+
removeEventListener: vi.fn(),
|
|
32
|
+
dispatchEvent: vi.fn(),
|
|
24
33
|
})),
|
|
25
34
|
})
|
|
26
35
|
|
|
@@ -31,8 +40,8 @@ describe('ReactQueryDevtools', () => {
|
|
|
31
40
|
})
|
|
32
41
|
it('should be able to open and close devtools', async () => {
|
|
33
42
|
const { queryClient } = createQueryClient()
|
|
34
|
-
const onCloseClick =
|
|
35
|
-
const onToggleClick =
|
|
43
|
+
const onCloseClick = vi.fn()
|
|
44
|
+
const onToggleClick = vi.fn()
|
|
36
45
|
|
|
37
46
|
function Page() {
|
|
38
47
|
const { data = 'default' } = useQuery({
|
|
@@ -469,6 +478,31 @@ describe('ReactQueryDevtools', () => {
|
|
|
469
478
|
expect(count).toBe(2)
|
|
470
479
|
})
|
|
471
480
|
|
|
481
|
+
it('should inform onlineManager when offline mode is simulated', () => {
|
|
482
|
+
const { queryClient } = createQueryClient()
|
|
483
|
+
const online: Array<boolean> = []
|
|
484
|
+
|
|
485
|
+
const unsubscribe = onlineManager.subscribe(() => {
|
|
486
|
+
online.push(onlineManager.isOnline())
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
renderWithClient(queryClient, <div />, {
|
|
490
|
+
initialIsOpen: true,
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
fireEvent.click(
|
|
494
|
+
screen.getByRole('button', { name: /mock offline behavior/i }),
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
fireEvent.click(
|
|
498
|
+
screen.getByRole('button', { name: /restore offline mock/i }),
|
|
499
|
+
)
|
|
500
|
+
|
|
501
|
+
expect(online).toStrictEqual([false, true])
|
|
502
|
+
|
|
503
|
+
unsubscribe()
|
|
504
|
+
})
|
|
505
|
+
|
|
472
506
|
it('should sort the queries according to the sorting filter', async () => {
|
|
473
507
|
const { queryClient, queryCache } = createQueryClient()
|
|
474
508
|
|
|
@@ -861,4 +895,144 @@ describe('ReactQueryDevtools', () => {
|
|
|
861
895
|
fireEvent.click(screen.getByRole('button', { name: /^close$/i }))
|
|
862
896
|
expect(parentElement).toHaveStyle(parentPaddings)
|
|
863
897
|
})
|
|
898
|
+
|
|
899
|
+
it('should simulate loading state', async () => {
|
|
900
|
+
const { queryClient } = createQueryClient()
|
|
901
|
+
let count = 0
|
|
902
|
+
function App() {
|
|
903
|
+
const { data, fetchStatus } = useQuery({
|
|
904
|
+
queryKey: ['key'],
|
|
905
|
+
queryFn: () => {
|
|
906
|
+
count++
|
|
907
|
+
return Promise.resolve('test')
|
|
908
|
+
},
|
|
909
|
+
})
|
|
910
|
+
|
|
911
|
+
return (
|
|
912
|
+
<div>
|
|
913
|
+
<h1>
|
|
914
|
+
{data ?? 'No data'}, {fetchStatus}
|
|
915
|
+
</h1>
|
|
916
|
+
</div>
|
|
917
|
+
)
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
renderWithClient(queryClient, <App />, {
|
|
921
|
+
initialIsOpen: true,
|
|
922
|
+
})
|
|
923
|
+
|
|
924
|
+
await screen.findByRole('heading', { name: /test/i })
|
|
925
|
+
|
|
926
|
+
const loadingButton = await screen.findByRole('button', {
|
|
927
|
+
name: 'Trigger loading',
|
|
928
|
+
})
|
|
929
|
+
fireEvent.click(loadingButton)
|
|
930
|
+
|
|
931
|
+
await waitFor(() => {
|
|
932
|
+
expect(screen.getByText('Restore loading')).toBeInTheDocument()
|
|
933
|
+
})
|
|
934
|
+
|
|
935
|
+
await waitFor(() => {
|
|
936
|
+
expect(screen.getByText('No data, fetching')).toBeInTheDocument()
|
|
937
|
+
})
|
|
938
|
+
|
|
939
|
+
fireEvent.click(screen.getByRole('button', { name: /restore loading/i }))
|
|
940
|
+
|
|
941
|
+
await waitFor(() => {
|
|
942
|
+
expect(screen.getByText('test, idle')).toBeInTheDocument()
|
|
943
|
+
})
|
|
944
|
+
|
|
945
|
+
expect(count).toBe(2)
|
|
946
|
+
})
|
|
947
|
+
|
|
948
|
+
it('should simulate error state', async () => {
|
|
949
|
+
const { queryClient } = createQueryClient()
|
|
950
|
+
function App() {
|
|
951
|
+
const { status, error } = useQuery({
|
|
952
|
+
queryKey: ['key'],
|
|
953
|
+
queryFn: () => {
|
|
954
|
+
return Promise.resolve('test')
|
|
955
|
+
},
|
|
956
|
+
})
|
|
957
|
+
|
|
958
|
+
return (
|
|
959
|
+
<div>
|
|
960
|
+
<h1>
|
|
961
|
+
{!!error ? 'Some error' : 'No error'}, {status}
|
|
962
|
+
</h1>
|
|
963
|
+
</div>
|
|
964
|
+
)
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
renderWithClient(queryClient, <App />, {
|
|
968
|
+
initialIsOpen: true,
|
|
969
|
+
})
|
|
970
|
+
|
|
971
|
+
const errorButton = await screen.findByRole('button', {
|
|
972
|
+
name: 'Trigger error',
|
|
973
|
+
})
|
|
974
|
+
fireEvent.click(errorButton)
|
|
975
|
+
|
|
976
|
+
await waitFor(() => {
|
|
977
|
+
expect(screen.getByText('Restore error')).toBeInTheDocument()
|
|
978
|
+
})
|
|
979
|
+
|
|
980
|
+
await waitFor(() => {
|
|
981
|
+
expect(screen.getByText('Some error, error')).toBeInTheDocument()
|
|
982
|
+
})
|
|
983
|
+
|
|
984
|
+
fireEvent.click(screen.getByRole('button', { name: /Restore error/i }))
|
|
985
|
+
|
|
986
|
+
await waitFor(() => {
|
|
987
|
+
expect(screen.getByText('No error, success')).toBeInTheDocument()
|
|
988
|
+
})
|
|
989
|
+
})
|
|
990
|
+
|
|
991
|
+
it('should can simulate a specific error', async () => {
|
|
992
|
+
const { queryClient } = createQueryClient()
|
|
993
|
+
|
|
994
|
+
function App() {
|
|
995
|
+
const { status, error } = useQuery({
|
|
996
|
+
queryKey: ['key'],
|
|
997
|
+
queryFn: () => {
|
|
998
|
+
return Promise.resolve('test')
|
|
999
|
+
},
|
|
1000
|
+
})
|
|
1001
|
+
|
|
1002
|
+
return (
|
|
1003
|
+
<div data-testid="test">
|
|
1004
|
+
<h1>
|
|
1005
|
+
{error instanceof CustomError
|
|
1006
|
+
? error.message.toString()
|
|
1007
|
+
: 'No error'}
|
|
1008
|
+
, {status}
|
|
1009
|
+
</h1>
|
|
1010
|
+
</div>
|
|
1011
|
+
)
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
renderWithClient(queryClient, <App />, {
|
|
1015
|
+
initialIsOpen: true,
|
|
1016
|
+
errorTypes: [
|
|
1017
|
+
{
|
|
1018
|
+
name: 'error1',
|
|
1019
|
+
initializer: () => new CustomError('error1'),
|
|
1020
|
+
},
|
|
1021
|
+
],
|
|
1022
|
+
})
|
|
1023
|
+
|
|
1024
|
+
const errorOption = await screen.findByLabelText('Trigger error:')
|
|
1025
|
+
|
|
1026
|
+
UserEvent.selectOptions(errorOption, 'error1')
|
|
1027
|
+
|
|
1028
|
+
await waitFor(() => {
|
|
1029
|
+
expect(screen.getByText('error1, error')).toBeInTheDocument()
|
|
1030
|
+
})
|
|
1031
|
+
|
|
1032
|
+
fireEvent.click(screen.getByRole('button', { name: /Restore error/i }))
|
|
1033
|
+
|
|
1034
|
+
await waitFor(() => {
|
|
1035
|
+
expect(screen.getByText('No error, success')).toBeInTheDocument()
|
|
1036
|
+
})
|
|
1037
|
+
})
|
|
864
1038
|
})
|
package/src/devtools.tsx
CHANGED
|
@@ -4,6 +4,8 @@ import type {
|
|
|
4
4
|
QueryCache,
|
|
5
5
|
QueryClient,
|
|
6
6
|
QueryKey as QueryKeyType,
|
|
7
|
+
Query,
|
|
8
|
+
DefaultError,
|
|
7
9
|
} from '@tanstack/react-query'
|
|
8
10
|
import {
|
|
9
11
|
useQueryClient,
|
|
@@ -39,6 +41,18 @@ import { ThemeProvider, defaultTheme as theme } from './theme'
|
|
|
39
41
|
import { getQueryStatusLabel, getQueryStatusColor } from './utils'
|
|
40
42
|
import Explorer from './Explorer'
|
|
41
43
|
import Logo from './Logo'
|
|
44
|
+
import { useMemo } from 'react'
|
|
45
|
+
|
|
46
|
+
export interface DevToolsErrorType {
|
|
47
|
+
/**
|
|
48
|
+
* The name of the error.
|
|
49
|
+
*/
|
|
50
|
+
name: string
|
|
51
|
+
/**
|
|
52
|
+
* How the error is initialized.
|
|
53
|
+
*/
|
|
54
|
+
initializer: (query: Query) => DefaultError
|
|
55
|
+
}
|
|
42
56
|
|
|
43
57
|
export interface DevtoolsOptions {
|
|
44
58
|
/**
|
|
@@ -81,6 +95,10 @@ export interface DevtoolsOptions {
|
|
|
81
95
|
* Custom instance of QueryClient
|
|
82
96
|
*/
|
|
83
97
|
queryClient?: QueryClient
|
|
98
|
+
/**
|
|
99
|
+
* Use this so you can define custom errors that can be shown in the devtools.
|
|
100
|
+
*/
|
|
101
|
+
errorTypes?: DevToolsErrorType[]
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
interface DevtoolsPanelOptions {
|
|
@@ -129,6 +147,10 @@ interface DevtoolsPanelOptions {
|
|
|
129
147
|
* Custom instance of QueryClient
|
|
130
148
|
*/
|
|
131
149
|
queryClient?: QueryClient
|
|
150
|
+
/**
|
|
151
|
+
* Use this so you can define custom errors that can be shown in the devtools.
|
|
152
|
+
*/
|
|
153
|
+
errorTypes?: DevToolsErrorType[]
|
|
132
154
|
}
|
|
133
155
|
|
|
134
156
|
export function ReactQueryDevtools({
|
|
@@ -141,6 +163,7 @@ export function ReactQueryDevtools({
|
|
|
141
163
|
queryClient,
|
|
142
164
|
styleNonce,
|
|
143
165
|
panelPosition: initialPanelPosition = 'bottom',
|
|
166
|
+
errorTypes = [],
|
|
144
167
|
}: DevtoolsOptions): React.ReactElement | null {
|
|
145
168
|
const rootRef = React.useRef<HTMLDivElement>(null)
|
|
146
169
|
const panelRef = React.useRef<HTMLDivElement>(null)
|
|
@@ -349,6 +372,7 @@ export function ReactQueryDevtools({
|
|
|
349
372
|
isOpen={isResolvedOpen}
|
|
350
373
|
setIsOpen={setIsOpen}
|
|
351
374
|
onDragStart={(e) => handleDragStart(panelRef.current, e)}
|
|
375
|
+
errorTypes={errorTypes}
|
|
352
376
|
/>
|
|
353
377
|
</ThemeProvider>
|
|
354
378
|
{!isResolvedOpen ? (
|
|
@@ -439,6 +463,7 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
|
|
|
439
463
|
showCloseButton,
|
|
440
464
|
position,
|
|
441
465
|
closeButtonProps = {},
|
|
466
|
+
errorTypes = [],
|
|
442
467
|
...panelProps
|
|
443
468
|
} = props
|
|
444
469
|
|
|
@@ -611,6 +636,8 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
|
|
|
611
636
|
style={{
|
|
612
637
|
display: 'flex',
|
|
613
638
|
alignItems: 'center',
|
|
639
|
+
flexWrap: 'wrap',
|
|
640
|
+
gap: '0.5em',
|
|
614
641
|
}}
|
|
615
642
|
>
|
|
616
643
|
<Input
|
|
@@ -623,7 +650,6 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
|
|
|
623
650
|
}}
|
|
624
651
|
style={{
|
|
625
652
|
flex: '1',
|
|
626
|
-
marginRight: '.5em',
|
|
627
653
|
width: '100%',
|
|
628
654
|
}}
|
|
629
655
|
/>
|
|
@@ -663,6 +689,7 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
|
|
|
663
689
|
} else {
|
|
664
690
|
onlineManager.setOnline(false)
|
|
665
691
|
setMockOffline(true)
|
|
692
|
+
window.dispatchEvent(new Event('offline'))
|
|
666
693
|
}
|
|
667
694
|
}}
|
|
668
695
|
aria-label={
|
|
@@ -744,6 +771,7 @@ export const ReactQueryDevtoolsPanel = React.forwardRef<
|
|
|
744
771
|
activeQueryHash={activeQueryHash}
|
|
745
772
|
queryCache={queryCache}
|
|
746
773
|
queryClient={client}
|
|
774
|
+
errorTypes={errorTypes}
|
|
747
775
|
/>
|
|
748
776
|
) : null}
|
|
749
777
|
|
|
@@ -779,10 +807,12 @@ const ActiveQuery = ({
|
|
|
779
807
|
queryCache,
|
|
780
808
|
activeQueryHash,
|
|
781
809
|
queryClient,
|
|
810
|
+
errorTypes,
|
|
782
811
|
}: {
|
|
783
812
|
queryCache: QueryCache
|
|
784
813
|
activeQueryHash: string
|
|
785
814
|
queryClient: QueryClient
|
|
815
|
+
errorTypes: DevToolsErrorType[]
|
|
786
816
|
}) => {
|
|
787
817
|
const activeQuery = useSubscribeToQueryCache(queryCache, () =>
|
|
788
818
|
queryCache.getAll().find((query) => query.queryHash === activeQueryHash),
|
|
@@ -816,10 +846,50 @@ const ActiveQuery = ({
|
|
|
816
846
|
promise?.catch(noop)
|
|
817
847
|
}
|
|
818
848
|
|
|
849
|
+
const currentErrorTypeName = useMemo(() => {
|
|
850
|
+
if (activeQuery && activeQueryState?.error) {
|
|
851
|
+
const errorType = errorTypes.find(
|
|
852
|
+
(type) =>
|
|
853
|
+
type.initializer(activeQuery).toString() ===
|
|
854
|
+
activeQueryState.error?.toString(),
|
|
855
|
+
)
|
|
856
|
+
return errorType?.name
|
|
857
|
+
}
|
|
858
|
+
return undefined
|
|
859
|
+
}, [activeQuery, activeQueryState?.error, errorTypes])
|
|
860
|
+
|
|
819
861
|
if (!activeQuery || !activeQueryState) {
|
|
820
862
|
return null
|
|
821
863
|
}
|
|
822
864
|
|
|
865
|
+
const triggerError = (errorType?: DevToolsErrorType) => {
|
|
866
|
+
const error =
|
|
867
|
+
errorType?.initializer(activeQuery) ??
|
|
868
|
+
new Error('Unknown error from devtools')
|
|
869
|
+
|
|
870
|
+
const __previousQueryOptions = activeQuery.options
|
|
871
|
+
|
|
872
|
+
activeQuery.setState({
|
|
873
|
+
status: 'error',
|
|
874
|
+
error,
|
|
875
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
876
|
+
fetchMeta: {
|
|
877
|
+
...activeQuery.state.fetchMeta,
|
|
878
|
+
__previousQueryOptions,
|
|
879
|
+
} as any,
|
|
880
|
+
})
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
const restoreQueryAfterLoadingOrError = () => {
|
|
884
|
+
activeQuery.fetch(
|
|
885
|
+
(activeQuery.state.fetchMeta as any).__previousQueryOptions,
|
|
886
|
+
{
|
|
887
|
+
// Make sure this fetch will cancel the previous one
|
|
888
|
+
cancelRefetch: true,
|
|
889
|
+
},
|
|
890
|
+
)
|
|
891
|
+
}
|
|
892
|
+
|
|
823
893
|
return (
|
|
824
894
|
<ActiveQueryPanel>
|
|
825
895
|
<div
|
|
@@ -842,7 +912,7 @@ const ActiveQuery = ({
|
|
|
842
912
|
style={{
|
|
843
913
|
marginBottom: '.5em',
|
|
844
914
|
display: 'flex',
|
|
845
|
-
alignItems: '
|
|
915
|
+
alignItems: 'flex-start',
|
|
846
916
|
justifyContent: 'space-between',
|
|
847
917
|
}}
|
|
848
918
|
>
|
|
@@ -916,6 +986,10 @@ const ActiveQuery = ({
|
|
|
916
986
|
<div
|
|
917
987
|
style={{
|
|
918
988
|
padding: '0.5em',
|
|
989
|
+
display: 'flex',
|
|
990
|
+
flexWrap: 'wrap',
|
|
991
|
+
gap: '0.5em',
|
|
992
|
+
alignItems: 'flex-end',
|
|
919
993
|
}}
|
|
920
994
|
>
|
|
921
995
|
<Button
|
|
@@ -955,7 +1029,81 @@ const ActiveQuery = ({
|
|
|
955
1029
|
}}
|
|
956
1030
|
>
|
|
957
1031
|
Remove
|
|
958
|
-
</Button>
|
|
1032
|
+
</Button>{' '}
|
|
1033
|
+
<Button
|
|
1034
|
+
type="button"
|
|
1035
|
+
onClick={() => {
|
|
1036
|
+
if (activeQuery.state.data === undefined) {
|
|
1037
|
+
restoreQueryAfterLoadingOrError()
|
|
1038
|
+
} else {
|
|
1039
|
+
const __previousQueryOptions = activeQuery.options
|
|
1040
|
+
// Trigger a fetch in order to trigger suspense as well.
|
|
1041
|
+
activeQuery.fetch({
|
|
1042
|
+
...__previousQueryOptions,
|
|
1043
|
+
queryFn: () => {
|
|
1044
|
+
return new Promise(() => {
|
|
1045
|
+
// Never resolve
|
|
1046
|
+
})
|
|
1047
|
+
},
|
|
1048
|
+
gcTime: -1,
|
|
1049
|
+
})
|
|
1050
|
+
activeQuery.setState({
|
|
1051
|
+
data: undefined,
|
|
1052
|
+
status: 'pending',
|
|
1053
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
|
1054
|
+
fetchMeta: {
|
|
1055
|
+
...activeQuery.state.fetchMeta,
|
|
1056
|
+
__previousQueryOptions,
|
|
1057
|
+
} as any,
|
|
1058
|
+
})
|
|
1059
|
+
}
|
|
1060
|
+
}}
|
|
1061
|
+
style={{
|
|
1062
|
+
background: theme.paused,
|
|
1063
|
+
}}
|
|
1064
|
+
>
|
|
1065
|
+
{activeQuery.state.status === 'pending' ? 'Restore' : 'Trigger'}{' '}
|
|
1066
|
+
loading
|
|
1067
|
+
</Button>{' '}
|
|
1068
|
+
{errorTypes.length === 0 || activeQuery.state.status === 'error' ? (
|
|
1069
|
+
<Button
|
|
1070
|
+
type="button"
|
|
1071
|
+
onClick={() => {
|
|
1072
|
+
if (!activeQuery.state.error) {
|
|
1073
|
+
triggerError()
|
|
1074
|
+
} else {
|
|
1075
|
+
queryClient.resetQueries(activeQuery)
|
|
1076
|
+
}
|
|
1077
|
+
}}
|
|
1078
|
+
style={{
|
|
1079
|
+
background: theme.danger,
|
|
1080
|
+
}}
|
|
1081
|
+
>
|
|
1082
|
+
{activeQuery.state.status === 'error' ? 'Restore' : 'Trigger'} error
|
|
1083
|
+
</Button>
|
|
1084
|
+
) : (
|
|
1085
|
+
<label>
|
|
1086
|
+
Trigger error:
|
|
1087
|
+
<Select
|
|
1088
|
+
value={currentErrorTypeName ?? ''}
|
|
1089
|
+
style={{ marginInlineStart: '.5em' }}
|
|
1090
|
+
onChange={(e) => {
|
|
1091
|
+
const errorType = errorTypes.find(
|
|
1092
|
+
(t) => t.name === e.target.value,
|
|
1093
|
+
)
|
|
1094
|
+
|
|
1095
|
+
triggerError(errorType)
|
|
1096
|
+
}}
|
|
1097
|
+
>
|
|
1098
|
+
<option key="" value="" />
|
|
1099
|
+
{errorTypes.map((errorType) => (
|
|
1100
|
+
<option key={errorType.name} value={errorType.name}>
|
|
1101
|
+
{errorType.name}
|
|
1102
|
+
</option>
|
|
1103
|
+
))}
|
|
1104
|
+
</Select>
|
|
1105
|
+
</label>
|
|
1106
|
+
)}
|
|
959
1107
|
</div>
|
|
960
1108
|
<div
|
|
961
1109
|
style={{
|
package/src/index.ts
CHANGED
package/src/styledComponents.ts
CHANGED