@tanstack/query-devtools 5.0.0-rc.1 → 5.0.0-rc.5
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/Devtools/{H2EROWFU.jsx → 336SHOD5.jsx} +220 -27
- package/build/Devtools/{ALVY75L5.jsx → 5OOWR6BQ.jsx} +220 -27
- package/build/Devtools/{66PXWIOF.js → CIR3WCBJ.js} +338 -99
- package/build/Devtools/{HTDVDYMT.js → XXDYGLB2.js} +338 -99
- package/build/dev.cjs +349 -108
- package/build/dev.js +1 -1
- package/build/dev.jsx +1 -1
- package/build/index.cjs +349 -108
- package/build/index.js +1 -1
- package/build/index.jsx +1 -1
- package/package.json +2 -2
- package/src/Devtools.tsx +2 -1
- package/src/Explorer.tsx +173 -19
- package/src/__tests__/utils.test.ts +725 -0
- package/src/icons/index.tsx +19 -0
- package/src/utils.tsx +137 -0
package/build/index.js
CHANGED
|
@@ -52,7 +52,7 @@ var TanstackQueryDevtools = class {
|
|
|
52
52
|
if (this.Component) {
|
|
53
53
|
Devtools = this.Component;
|
|
54
54
|
} else {
|
|
55
|
-
Devtools = lazy(() => import('./Devtools/
|
|
55
|
+
Devtools = lazy(() => import('./Devtools/CIR3WCBJ.js'));
|
|
56
56
|
this.Component = Devtools;
|
|
57
57
|
}
|
|
58
58
|
const _self$ = this;
|
package/build/index.jsx
CHANGED
|
@@ -56,7 +56,7 @@ var TanstackQueryDevtools = class {
|
|
|
56
56
|
if (this.Component) {
|
|
57
57
|
Devtools = this.Component;
|
|
58
58
|
} else {
|
|
59
|
-
Devtools = lazy(() => import("./Devtools/
|
|
59
|
+
Devtools = lazy(() => import("./Devtools/5OOWR6BQ.jsx"));
|
|
60
60
|
this.Component = Devtools;
|
|
61
61
|
}
|
|
62
62
|
return <Devtools
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/query-devtools",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.5",
|
|
4
4
|
"description": "Developer tools to interact with and visualize the TanStack Query cache",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"superjson": "^1.12.4",
|
|
51
51
|
"tsup-preset-solid": "^2.0.1",
|
|
52
52
|
"vite-plugin-solid": "^2.7.0",
|
|
53
|
-
"@tanstack/query-core": "5.0.0-rc.
|
|
53
|
+
"@tanstack/query-core": "5.0.0-rc.5"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"clean": "rimraf ./build && rimraf ./coverage",
|
package/src/Devtools.tsx
CHANGED
|
@@ -1273,7 +1273,8 @@ const QueryDetails = () => {
|
|
|
1273
1273
|
label="Data"
|
|
1274
1274
|
defaultExpanded={['Data']}
|
|
1275
1275
|
value={activeQueryStateData()}
|
|
1276
|
-
|
|
1276
|
+
editable={true}
|
|
1277
|
+
activeQuery={activeQuery()}
|
|
1277
1278
|
/>
|
|
1278
1279
|
</div>
|
|
1279
1280
|
<div class={cx(styles.detailsHeader, 'tsqd-query-details-header')}>
|
package/src/Explorer.tsx
CHANGED
|
@@ -4,8 +4,14 @@ import { clsx as cx } from 'clsx'
|
|
|
4
4
|
import { Index, Match, Show, Switch, createMemo, createSignal } from 'solid-js'
|
|
5
5
|
import { Key } from '@solid-primitives/keyed'
|
|
6
6
|
import { tokens } from './theme'
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
deleteNestedDataByPath,
|
|
9
|
+
displayValue,
|
|
10
|
+
updateNestedDataByPath,
|
|
11
|
+
} from './utils'
|
|
12
|
+
import { CopiedCopier, Copier, ErrorCopier, List, Trash } from './icons'
|
|
13
|
+
import { useQueryDevtoolsContext } from './Context'
|
|
14
|
+
import type { Query } from '@tanstack/query-core'
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* Chunk elements in the array by size
|
|
@@ -73,7 +79,8 @@ const CopyButton = (props: { value: unknown }) => {
|
|
|
73
79
|
|
|
74
80
|
return (
|
|
75
81
|
<button
|
|
76
|
-
class={styles.
|
|
82
|
+
class={styles.actionButton}
|
|
83
|
+
title="Copy object to clipboard"
|
|
77
84
|
aria-label={`${
|
|
78
85
|
copyState() === 'NoCopy'
|
|
79
86
|
? 'Copy object to clipboard'
|
|
@@ -118,11 +125,60 @@ const CopyButton = (props: { value: unknown }) => {
|
|
|
118
125
|
)
|
|
119
126
|
}
|
|
120
127
|
|
|
128
|
+
const ClearArrayButton = (props: {
|
|
129
|
+
dataPath: Array<string>
|
|
130
|
+
activeQuery: Query
|
|
131
|
+
}) => {
|
|
132
|
+
const styles = getStyles()
|
|
133
|
+
const queryClient = useQueryDevtoolsContext().client
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<button
|
|
137
|
+
class={styles.actionButton}
|
|
138
|
+
title={'Remove all items'}
|
|
139
|
+
aria-label={'Remove all items'}
|
|
140
|
+
onClick={() => {
|
|
141
|
+
const oldData = props.activeQuery.state.data
|
|
142
|
+
const newData = updateNestedDataByPath(oldData, props.dataPath, [])
|
|
143
|
+
queryClient.setQueryData(props.activeQuery.queryKey, newData)
|
|
144
|
+
}}
|
|
145
|
+
>
|
|
146
|
+
<List />
|
|
147
|
+
</button>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const DeleteItemButton = (props: {
|
|
152
|
+
dataPath: Array<string>
|
|
153
|
+
activeQuery: Query
|
|
154
|
+
}) => {
|
|
155
|
+
const styles = getStyles()
|
|
156
|
+
const queryClient = useQueryDevtoolsContext().client
|
|
157
|
+
|
|
158
|
+
return (
|
|
159
|
+
<button
|
|
160
|
+
class={cx(styles.actionButton)}
|
|
161
|
+
title={'Delete item'}
|
|
162
|
+
aria-label={'Delete item'}
|
|
163
|
+
onClick={() => {
|
|
164
|
+
const oldData = props.activeQuery.state.data
|
|
165
|
+
const newData = deleteNestedDataByPath(oldData, props.dataPath)
|
|
166
|
+
queryClient.setQueryData(props.activeQuery.queryKey, newData)
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
<Trash />
|
|
170
|
+
</button>
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
121
174
|
type ExplorerProps = {
|
|
122
|
-
|
|
175
|
+
editable?: boolean
|
|
123
176
|
label: string
|
|
124
177
|
value: unknown
|
|
125
178
|
defaultExpanded?: Array<string>
|
|
179
|
+
dataPath?: Array<string>
|
|
180
|
+
activeQuery?: Query
|
|
181
|
+
itemsDeletable?: boolean
|
|
126
182
|
}
|
|
127
183
|
|
|
128
184
|
function isIterable(x: any): x is Iterable<unknown> {
|
|
@@ -131,6 +187,7 @@ function isIterable(x: any): x is Iterable<unknown> {
|
|
|
131
187
|
|
|
132
188
|
export default function Explorer(props: ExplorerProps) {
|
|
133
189
|
const styles = getStyles()
|
|
190
|
+
const queryClient = useQueryDevtoolsContext().client
|
|
134
191
|
|
|
135
192
|
const [expanded, setExpanded] = createSignal(
|
|
136
193
|
(props.defaultExpanded || []).includes(props.label),
|
|
@@ -187,6 +244,8 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
187
244
|
|
|
188
245
|
const subEntryPages = createMemo(() => chunkArray(subEntries(), 100))
|
|
189
246
|
|
|
247
|
+
const currentDataPath = props.dataPath ?? []
|
|
248
|
+
|
|
190
249
|
return (
|
|
191
250
|
<div class={styles.entry}>
|
|
192
251
|
<Show when={subEntryPages().length}>
|
|
@@ -201,8 +260,28 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
201
260
|
{subEntries().length} {subEntries().length > 1 ? `items` : `item`}
|
|
202
261
|
</span>
|
|
203
262
|
</button>
|
|
204
|
-
<Show when={props.
|
|
205
|
-
<
|
|
263
|
+
<Show when={props.editable}>
|
|
264
|
+
<div class={styles.actions}>
|
|
265
|
+
<CopyButton value={props.value} />
|
|
266
|
+
|
|
267
|
+
<Show
|
|
268
|
+
when={props.itemsDeletable && props.activeQuery !== undefined}
|
|
269
|
+
>
|
|
270
|
+
<DeleteItemButton
|
|
271
|
+
activeQuery={props.activeQuery!}
|
|
272
|
+
dataPath={currentDataPath}
|
|
273
|
+
/>
|
|
274
|
+
</Show>
|
|
275
|
+
|
|
276
|
+
<Show
|
|
277
|
+
when={type() === 'array' && props.activeQuery !== undefined}
|
|
278
|
+
>
|
|
279
|
+
<ClearArrayButton
|
|
280
|
+
activeQuery={props.activeQuery!}
|
|
281
|
+
dataPath={currentDataPath}
|
|
282
|
+
/>
|
|
283
|
+
</Show>
|
|
284
|
+
</div>
|
|
206
285
|
</Show>
|
|
207
286
|
</div>
|
|
208
287
|
<Show when={expanded()}>
|
|
@@ -215,7 +294,14 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
215
294
|
defaultExpanded={props.defaultExpanded}
|
|
216
295
|
label={entry().label}
|
|
217
296
|
value={entry().value}
|
|
218
|
-
|
|
297
|
+
editable={props.editable}
|
|
298
|
+
dataPath={[...currentDataPath, entry().label]}
|
|
299
|
+
activeQuery={props.activeQuery}
|
|
300
|
+
itemsDeletable={
|
|
301
|
+
type() === 'array' ||
|
|
302
|
+
type() === 'Iterable' ||
|
|
303
|
+
type() === 'object'
|
|
304
|
+
}
|
|
219
305
|
/>
|
|
220
306
|
)
|
|
221
307
|
}}
|
|
@@ -250,7 +336,9 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
250
336
|
defaultExpanded={props.defaultExpanded}
|
|
251
337
|
label={entry().label}
|
|
252
338
|
value={entry().value}
|
|
253
|
-
|
|
339
|
+
editable={props.editable}
|
|
340
|
+
dataPath={[...currentDataPath, entry().label]}
|
|
341
|
+
activeQuery={props.activeQuery}
|
|
254
342
|
/>
|
|
255
343
|
)}
|
|
256
344
|
</Key>
|
|
@@ -265,13 +353,50 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
265
353
|
</Show>
|
|
266
354
|
</Show>
|
|
267
355
|
<Show when={subEntryPages().length === 0}>
|
|
268
|
-
<div
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
356
|
+
<div class={styles.row}>
|
|
357
|
+
<span class={styles.label}>{props.label}:</span>
|
|
358
|
+
<Show
|
|
359
|
+
when={
|
|
360
|
+
props.editable &&
|
|
361
|
+
props.activeQuery !== undefined &&
|
|
362
|
+
(type() === 'string' || type() === 'number')
|
|
363
|
+
}
|
|
364
|
+
fallback={
|
|
365
|
+
<span class={styles.value}>{displayValue(props.value)}</span>
|
|
366
|
+
}
|
|
367
|
+
>
|
|
368
|
+
<input
|
|
369
|
+
type={type() === 'number' ? 'number' : 'text'}
|
|
370
|
+
class={cx(styles.value, styles.editableInput)}
|
|
371
|
+
value={props.value as string | number}
|
|
372
|
+
onChange={(changeEvent) => {
|
|
373
|
+
const oldData = props.activeQuery!.state.data
|
|
374
|
+
|
|
375
|
+
const newData = updateNestedDataByPath(
|
|
376
|
+
oldData,
|
|
377
|
+
currentDataPath,
|
|
378
|
+
type() === 'number'
|
|
379
|
+
? changeEvent.target.valueAsNumber
|
|
380
|
+
: changeEvent.target.value,
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
queryClient.setQueryData(props.activeQuery!.queryKey, newData)
|
|
384
|
+
}}
|
|
385
|
+
/>
|
|
386
|
+
</Show>
|
|
387
|
+
|
|
388
|
+
<Show
|
|
389
|
+
when={
|
|
390
|
+
props.editable &&
|
|
391
|
+
props.itemsDeletable &&
|
|
392
|
+
props.activeQuery !== undefined
|
|
393
|
+
}
|
|
394
|
+
>
|
|
395
|
+
<DeleteItemButton
|
|
396
|
+
activeQuery={props.activeQuery!}
|
|
397
|
+
dataPath={currentDataPath}
|
|
398
|
+
/>
|
|
399
|
+
</Show>
|
|
275
400
|
</div>
|
|
276
401
|
</Show>
|
|
277
402
|
</div>
|
|
@@ -315,6 +440,7 @@ const getStyles = () => {
|
|
|
315
440
|
align-items: center;
|
|
316
441
|
line-height: 1.125rem;
|
|
317
442
|
min-height: 1.125rem;
|
|
443
|
+
gap: ${size[2]};
|
|
318
444
|
`,
|
|
319
445
|
expanderButton: css`
|
|
320
446
|
cursor: pointer;
|
|
@@ -352,8 +478,30 @@ const getStyles = () => {
|
|
|
352
478
|
`,
|
|
353
479
|
value: css`
|
|
354
480
|
color: ${colors.purple[400]};
|
|
481
|
+
flex-grow: 1;
|
|
355
482
|
`,
|
|
356
|
-
|
|
483
|
+
actions: css`
|
|
484
|
+
display: inline-flex;
|
|
485
|
+
gap: ${size[2]};
|
|
486
|
+
`,
|
|
487
|
+
row: css`
|
|
488
|
+
display: inline-flex;
|
|
489
|
+
gap: ${size[2]};
|
|
490
|
+
width: 100%;
|
|
491
|
+
margin-bottom: ${size[0.5]};
|
|
492
|
+
line-height: 1.125rem;
|
|
493
|
+
`,
|
|
494
|
+
editableInput: css`
|
|
495
|
+
border: none;
|
|
496
|
+
padding: 0px ${size[1]};
|
|
497
|
+
flex-grow: 1;
|
|
498
|
+
background-color: ${colors.gray[900]};
|
|
499
|
+
|
|
500
|
+
&:hover {
|
|
501
|
+
background-color: ${colors.gray[800]};
|
|
502
|
+
}
|
|
503
|
+
`,
|
|
504
|
+
actionButton: css`
|
|
357
505
|
background-color: transparent;
|
|
358
506
|
border: none;
|
|
359
507
|
display: inline-flex;
|
|
@@ -364,11 +512,17 @@ const getStyles = () => {
|
|
|
364
512
|
width: ${size[3]};
|
|
365
513
|
height: ${size[3]};
|
|
366
514
|
position: relative;
|
|
367
|
-
left: ${size[2]};
|
|
368
515
|
z-index: 1;
|
|
369
516
|
|
|
370
|
-
&:hover svg
|
|
371
|
-
|
|
517
|
+
&:hover svg {
|
|
518
|
+
.copier,
|
|
519
|
+
.list {
|
|
520
|
+
stroke: ${colors.gray[500]} !important;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.list-item {
|
|
524
|
+
stroke: ${colors.gray[700]};
|
|
525
|
+
}
|
|
372
526
|
}
|
|
373
527
|
|
|
374
528
|
&:focus-visible {
|