@tanstack/query-devtools 5.0.0-rc.1 → 5.0.0-rc.10
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 → 56YMBTAH.jsx} +286 -27
- package/build/Devtools/{HTDVDYMT.js → B5V4HXOX.js} +405 -105
- package/build/Devtools/{ALVY75L5.jsx → ECUC7UFN.jsx} +286 -27
- package/build/Devtools/{66PXWIOF.js → UZ6MTF6A.js} +405 -105
- package/build/dev.cjs +418 -114
- package/build/dev.js +1 -1
- package/build/dev.jsx +1 -1
- package/build/index.cjs +418 -114
- package/build/index.js +1 -1
- package/build/index.jsx +1 -1
- package/package.json +4 -4
- package/src/Devtools.tsx +2 -1
- package/src/Explorer.tsx +227 -19
- package/src/__tests__/utils.test.ts +725 -0
- package/src/icons/index.tsx +55 -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/UZ6MTF6A.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/ECUC7UFN.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.10",
|
|
4
4
|
"description": "Developer tools to interact with and visualize the TanStack Query cache",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"browser": {},
|
|
18
18
|
"exports": {
|
|
19
19
|
"solid": {
|
|
20
|
-
"development": "./build/
|
|
21
|
-
"import": "./build/index.
|
|
20
|
+
"development": "./build/index.js",
|
|
21
|
+
"import": "./build/index.js"
|
|
22
22
|
},
|
|
23
23
|
"development": {
|
|
24
24
|
"import": {
|
|
@@ -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.6"
|
|
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 { Check, 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,88 @@ 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
|
+
|
|
174
|
+
const ToggleValueButton = (props: {
|
|
175
|
+
dataPath: Array<string>
|
|
176
|
+
activeQuery: Query
|
|
177
|
+
value: boolean
|
|
178
|
+
}) => {
|
|
179
|
+
const styles = getStyles()
|
|
180
|
+
const queryClient = useQueryDevtoolsContext().client
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<button
|
|
184
|
+
class={cx(styles.actionButton)}
|
|
185
|
+
title={'Toggle value'}
|
|
186
|
+
aria-label={'Toggle value'}
|
|
187
|
+
onClick={() => {
|
|
188
|
+
const oldData = props.activeQuery.state.data
|
|
189
|
+
const newData = updateNestedDataByPath(
|
|
190
|
+
oldData,
|
|
191
|
+
props.dataPath,
|
|
192
|
+
!props.value,
|
|
193
|
+
)
|
|
194
|
+
queryClient.setQueryData(props.activeQuery.queryKey, newData)
|
|
195
|
+
}}
|
|
196
|
+
>
|
|
197
|
+
<Check checked={props.value} />
|
|
198
|
+
</button>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
121
202
|
type ExplorerProps = {
|
|
122
|
-
|
|
203
|
+
editable?: boolean
|
|
123
204
|
label: string
|
|
124
205
|
value: unknown
|
|
125
206
|
defaultExpanded?: Array<string>
|
|
207
|
+
dataPath?: Array<string>
|
|
208
|
+
activeQuery?: Query
|
|
209
|
+
itemsDeletable?: boolean
|
|
126
210
|
}
|
|
127
211
|
|
|
128
212
|
function isIterable(x: any): x is Iterable<unknown> {
|
|
@@ -131,6 +215,7 @@ function isIterable(x: any): x is Iterable<unknown> {
|
|
|
131
215
|
|
|
132
216
|
export default function Explorer(props: ExplorerProps) {
|
|
133
217
|
const styles = getStyles()
|
|
218
|
+
const queryClient = useQueryDevtoolsContext().client
|
|
134
219
|
|
|
135
220
|
const [expanded, setExpanded] = createSignal(
|
|
136
221
|
(props.defaultExpanded || []).includes(props.label),
|
|
@@ -187,6 +272,8 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
187
272
|
|
|
188
273
|
const subEntryPages = createMemo(() => chunkArray(subEntries(), 100))
|
|
189
274
|
|
|
275
|
+
const currentDataPath = props.dataPath ?? []
|
|
276
|
+
|
|
190
277
|
return (
|
|
191
278
|
<div class={styles.entry}>
|
|
192
279
|
<Show when={subEntryPages().length}>
|
|
@@ -201,8 +288,28 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
201
288
|
{subEntries().length} {subEntries().length > 1 ? `items` : `item`}
|
|
202
289
|
</span>
|
|
203
290
|
</button>
|
|
204
|
-
<Show when={props.
|
|
205
|
-
<
|
|
291
|
+
<Show when={props.editable}>
|
|
292
|
+
<div class={styles.actions}>
|
|
293
|
+
<CopyButton value={props.value} />
|
|
294
|
+
|
|
295
|
+
<Show
|
|
296
|
+
when={props.itemsDeletable && props.activeQuery !== undefined}
|
|
297
|
+
>
|
|
298
|
+
<DeleteItemButton
|
|
299
|
+
activeQuery={props.activeQuery!}
|
|
300
|
+
dataPath={currentDataPath}
|
|
301
|
+
/>
|
|
302
|
+
</Show>
|
|
303
|
+
|
|
304
|
+
<Show
|
|
305
|
+
when={type() === 'array' && props.activeQuery !== undefined}
|
|
306
|
+
>
|
|
307
|
+
<ClearArrayButton
|
|
308
|
+
activeQuery={props.activeQuery!}
|
|
309
|
+
dataPath={currentDataPath}
|
|
310
|
+
/>
|
|
311
|
+
</Show>
|
|
312
|
+
</div>
|
|
206
313
|
</Show>
|
|
207
314
|
</div>
|
|
208
315
|
<Show when={expanded()}>
|
|
@@ -215,7 +322,14 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
215
322
|
defaultExpanded={props.defaultExpanded}
|
|
216
323
|
label={entry().label}
|
|
217
324
|
value={entry().value}
|
|
218
|
-
|
|
325
|
+
editable={props.editable}
|
|
326
|
+
dataPath={[...currentDataPath, entry().label]}
|
|
327
|
+
activeQuery={props.activeQuery}
|
|
328
|
+
itemsDeletable={
|
|
329
|
+
type() === 'array' ||
|
|
330
|
+
type() === 'Iterable' ||
|
|
331
|
+
type() === 'object'
|
|
332
|
+
}
|
|
219
333
|
/>
|
|
220
334
|
)
|
|
221
335
|
}}
|
|
@@ -250,7 +364,9 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
250
364
|
defaultExpanded={props.defaultExpanded}
|
|
251
365
|
label={entry().label}
|
|
252
366
|
value={entry().value}
|
|
253
|
-
|
|
367
|
+
editable={props.editable}
|
|
368
|
+
dataPath={[...currentDataPath, entry().label]}
|
|
369
|
+
activeQuery={props.activeQuery}
|
|
254
370
|
/>
|
|
255
371
|
)}
|
|
256
372
|
</Key>
|
|
@@ -265,13 +381,73 @@ export default function Explorer(props: ExplorerProps) {
|
|
|
265
381
|
</Show>
|
|
266
382
|
</Show>
|
|
267
383
|
<Show when={subEntryPages().length === 0}>
|
|
268
|
-
<div
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
384
|
+
<div class={styles.row}>
|
|
385
|
+
<span class={styles.label}>{props.label}:</span>
|
|
386
|
+
<Show
|
|
387
|
+
when={
|
|
388
|
+
props.editable &&
|
|
389
|
+
props.activeQuery !== undefined &&
|
|
390
|
+
(type() === 'string' ||
|
|
391
|
+
type() === 'number' ||
|
|
392
|
+
type() === 'boolean')
|
|
393
|
+
}
|
|
394
|
+
fallback={
|
|
395
|
+
<span class={styles.value}>{displayValue(props.value)}</span>
|
|
396
|
+
}
|
|
397
|
+
>
|
|
398
|
+
<Show
|
|
399
|
+
when={
|
|
400
|
+
props.editable &&
|
|
401
|
+
props.activeQuery !== undefined &&
|
|
402
|
+
(type() === 'string' || type() === 'number')
|
|
403
|
+
}
|
|
404
|
+
>
|
|
405
|
+
<input
|
|
406
|
+
type={type() === 'number' ? 'number' : 'text'}
|
|
407
|
+
class={cx(styles.value, styles.editableInput)}
|
|
408
|
+
value={props.value as string | number}
|
|
409
|
+
onChange={(changeEvent) => {
|
|
410
|
+
const oldData = props.activeQuery!.state.data
|
|
411
|
+
|
|
412
|
+
const newData = updateNestedDataByPath(
|
|
413
|
+
oldData,
|
|
414
|
+
currentDataPath,
|
|
415
|
+
type() === 'number'
|
|
416
|
+
? changeEvent.target.valueAsNumber
|
|
417
|
+
: changeEvent.target.value,
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
queryClient.setQueryData(props.activeQuery!.queryKey, newData)
|
|
421
|
+
}}
|
|
422
|
+
/>
|
|
423
|
+
</Show>
|
|
424
|
+
|
|
425
|
+
<Show when={type() === 'boolean'}>
|
|
426
|
+
<span
|
|
427
|
+
class={cx(styles.value, styles.actions, styles.editableInput)}
|
|
428
|
+
>
|
|
429
|
+
<ToggleValueButton
|
|
430
|
+
activeQuery={props.activeQuery!}
|
|
431
|
+
dataPath={currentDataPath}
|
|
432
|
+
value={props.value as boolean}
|
|
433
|
+
/>
|
|
434
|
+
{displayValue(props.value)}
|
|
435
|
+
</span>
|
|
436
|
+
</Show>
|
|
437
|
+
</Show>
|
|
438
|
+
|
|
439
|
+
<Show
|
|
440
|
+
when={
|
|
441
|
+
props.editable &&
|
|
442
|
+
props.itemsDeletable &&
|
|
443
|
+
props.activeQuery !== undefined
|
|
444
|
+
}
|
|
445
|
+
>
|
|
446
|
+
<DeleteItemButton
|
|
447
|
+
activeQuery={props.activeQuery!}
|
|
448
|
+
dataPath={currentDataPath}
|
|
449
|
+
/>
|
|
450
|
+
</Show>
|
|
275
451
|
</div>
|
|
276
452
|
</Show>
|
|
277
453
|
</div>
|
|
@@ -315,6 +491,7 @@ const getStyles = () => {
|
|
|
315
491
|
align-items: center;
|
|
316
492
|
line-height: 1.125rem;
|
|
317
493
|
min-height: 1.125rem;
|
|
494
|
+
gap: ${size[2]};
|
|
318
495
|
`,
|
|
319
496
|
expanderButton: css`
|
|
320
497
|
cursor: pointer;
|
|
@@ -352,8 +529,32 @@ const getStyles = () => {
|
|
|
352
529
|
`,
|
|
353
530
|
value: css`
|
|
354
531
|
color: ${colors.purple[400]};
|
|
532
|
+
flex-grow: 1;
|
|
533
|
+
`,
|
|
534
|
+
actions: css`
|
|
535
|
+
display: inline-flex;
|
|
536
|
+
gap: ${size[2]};
|
|
537
|
+
align-items: center;
|
|
538
|
+
`,
|
|
539
|
+
row: css`
|
|
540
|
+
display: inline-flex;
|
|
541
|
+
gap: ${size[2]};
|
|
542
|
+
width: 100%;
|
|
543
|
+
margin-bottom: ${size[0.5]};
|
|
544
|
+
line-height: 1.125rem;
|
|
545
|
+
align-items: center;
|
|
355
546
|
`,
|
|
356
|
-
|
|
547
|
+
editableInput: css`
|
|
548
|
+
border: none;
|
|
549
|
+
padding: ${size[0.5]} ${size[1]};
|
|
550
|
+
flex-grow: 1;
|
|
551
|
+
background-color: ${colors.gray[900]};
|
|
552
|
+
|
|
553
|
+
&:hover {
|
|
554
|
+
background-color: ${colors.gray[800]};
|
|
555
|
+
}
|
|
556
|
+
`,
|
|
557
|
+
actionButton: css`
|
|
357
558
|
background-color: transparent;
|
|
358
559
|
border: none;
|
|
359
560
|
display: inline-flex;
|
|
@@ -364,11 +565,18 @@ const getStyles = () => {
|
|
|
364
565
|
width: ${size[3]};
|
|
365
566
|
height: ${size[3]};
|
|
366
567
|
position: relative;
|
|
367
|
-
left: ${size[2]};
|
|
368
568
|
z-index: 1;
|
|
369
569
|
|
|
370
|
-
&:hover svg
|
|
371
|
-
|
|
570
|
+
&:hover svg {
|
|
571
|
+
.copier,
|
|
572
|
+
.check,
|
|
573
|
+
.list {
|
|
574
|
+
stroke: ${colors.gray[500]} !important;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.list-item {
|
|
578
|
+
stroke: ${colors.gray[700]};
|
|
579
|
+
}
|
|
372
580
|
}
|
|
373
581
|
|
|
374
582
|
&:focus-visible {
|