@tanstack/query-devtools 5.56.1 → 5.59.19

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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createSignal, render, lazy, setupStyleSheet, createComponent, mergeProps } from './chunk/TU4XCPXB.js';
1
+ import { createSignal, render, lazy, setupStyleSheet, createComponent, mergeProps } from './chunk/BLREPECS.js';
2
2
 
3
3
  // src/TanstackQueryDevtools.tsx
4
4
  var TanstackQueryDevtools = class {
@@ -69,7 +69,7 @@ var TanstackQueryDevtools = class {
69
69
  if (this.#Component) {
70
70
  Devtools = this.#Component;
71
71
  } else {
72
- Devtools = lazy(() => import('./DevtoolsComponent/LU2ND2BF.js'));
72
+ Devtools = lazy(() => import('./DevtoolsComponent/BMGNQTAT.js'));
73
73
  this.#Component = Devtools;
74
74
  }
75
75
  setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget);
@@ -192,7 +192,7 @@ var TanstackQueryDevtoolsPanel = class {
192
192
  if (this.#Component) {
193
193
  Devtools = this.#Component;
194
194
  } else {
195
- Devtools = lazy(() => import('./DevtoolsPanelComponent/XJJMEBKY.js'));
195
+ Devtools = lazy(() => import('./DevtoolsPanelComponent/UODQIBEW.js'));
196
196
  this.#Component = Devtools;
197
197
  }
198
198
  setupStyleSheet(this.#styleNonce, this.#shadowDOMTarget);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/query-devtools",
3
- "version": "5.56.1",
3
+ "version": "5.59.19",
4
4
  "description": "Developer tools to interact with and visualize the TanStack Query cache",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -54,7 +54,7 @@
54
54
  "superjson": "^2.2.1",
55
55
  "tsup-preset-solid": "^2.2.0",
56
56
  "vite-plugin-solid": "^2.10.2",
57
- "@tanstack/query-core": "5.56.1"
57
+ "@tanstack/query-core": "5.59.17"
58
58
  },
59
59
  "scripts": {}
60
60
  }
package/src/Devtools.tsx CHANGED
@@ -1700,6 +1700,8 @@ const QueryDetails = () => {
1700
1700
  const queryClient = useQueryDevtoolsContext().client
1701
1701
 
1702
1702
  const [restoringLoading, setRestoringLoading] = createSignal(false)
1703
+ const [dataMode, setDataMode] = createSignal<'view' | 'edit'>('view')
1704
+ const [dataEditError, setDataEditError] = createSignal<boolean>(false)
1703
1705
 
1704
1706
  const errorTypes = createMemo(() => {
1705
1707
  return useQueryDevtoolsContext().errorTypes || []
@@ -1787,15 +1789,20 @@ const QueryDetails = () => {
1787
1789
  const restoreQueryAfterLoadingOrError = () => {
1788
1790
  const activeQueryVal = activeQuery()!
1789
1791
  const previousState = activeQueryVal.state
1790
- const previousOptions = (activeQueryVal.state.fetchMeta as any)
1791
- .__previousQueryOptions
1792
+ const previousOptions = activeQueryVal.state.fetchMeta
1793
+ ? (activeQueryVal.state.fetchMeta as any).__previousQueryOptions
1794
+ : null
1795
+
1792
1796
  activeQueryVal.cancel({ silent: true })
1793
1797
  activeQueryVal.setState({
1794
1798
  ...previousState,
1795
1799
  fetchStatus: 'idle',
1796
1800
  fetchMeta: null,
1797
1801
  })
1798
- activeQueryVal.fetch(previousOptions)
1802
+
1803
+ if (previousOptions) {
1804
+ activeQueryVal.fetch(previousOptions)
1805
+ }
1799
1806
  }
1800
1807
 
1801
1808
  createEffect(() => {
@@ -2047,22 +2054,85 @@ const QueryDetails = () => {
2047
2054
  </Show>
2048
2055
  </div>
2049
2056
  <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2050
- Data Explorer
2051
- </div>
2052
- <div
2053
- style={{
2054
- padding: tokens.size[2],
2055
- }}
2056
- class="tsqd-query-details-explorer-container tsqd-query-details-data-explorer"
2057
- >
2058
- <Explorer
2059
- label="Data"
2060
- defaultExpanded={['Data']}
2061
- value={activeQueryStateData()}
2062
- editable={true}
2063
- activeQuery={activeQuery()}
2064
- />
2057
+ Data {dataMode() === 'view' ? 'Explorer' : 'Editor'}
2065
2058
  </div>
2059
+ <Show when={dataMode() === 'view'}>
2060
+ <div
2061
+ style={{
2062
+ padding: tokens.size[2],
2063
+ }}
2064
+ class="tsqd-query-details-explorer-container tsqd-query-details-data-explorer"
2065
+ >
2066
+ <Explorer
2067
+ label="Data"
2068
+ defaultExpanded={['Data']}
2069
+ value={activeQueryStateData()}
2070
+ editable={true}
2071
+ onEdit={() => setDataMode('edit')}
2072
+ activeQuery={activeQuery()}
2073
+ />
2074
+ </div>
2075
+ </Show>
2076
+ <Show when={dataMode() === 'edit'}>
2077
+ <form
2078
+ class={cx(
2079
+ styles().devtoolsEditForm,
2080
+ 'tsqd-query-details-data-editor',
2081
+ )}
2082
+ onSubmit={(e) => {
2083
+ e.preventDefault()
2084
+ const formData = new FormData(e.currentTarget)
2085
+ const data = formData.get('data') as string
2086
+ try {
2087
+ const parsedData = JSON.parse(data)
2088
+ activeQuery()!.setState({
2089
+ ...activeQuery()!.state,
2090
+ data: parsedData,
2091
+ })
2092
+ setDataMode('view')
2093
+ } catch (error) {
2094
+ setDataEditError(true)
2095
+ }
2096
+ }}
2097
+ >
2098
+ <textarea
2099
+ name="data"
2100
+ class={styles().devtoolsEditTextarea}
2101
+ onFocus={() => setDataEditError(false)}
2102
+ data-error={dataEditError()}
2103
+ value={JSON.stringify(activeQueryStateData(), null, 2)}
2104
+ ></textarea>
2105
+ <div class={styles().devtoolsEditFormActions}>
2106
+ <span class={styles().devtoolsEditFormError}>
2107
+ {dataEditError() ? 'Invalid Value' : ''}
2108
+ </span>
2109
+ <div class={styles().devtoolsEditFormActionContainer}>
2110
+ <button
2111
+ class={cx(
2112
+ styles().devtoolsEditFormAction,
2113
+ css`
2114
+ color: ${t(colors.gray[600], colors.gray[300])};
2115
+ `,
2116
+ )}
2117
+ type="button"
2118
+ onClick={() => setDataMode('view')}
2119
+ >
2120
+ Cancel
2121
+ </button>
2122
+ <button
2123
+ class={cx(
2124
+ styles().devtoolsEditFormAction,
2125
+ css`
2126
+ color: ${t(colors.blue[600], colors.blue[400])};
2127
+ `,
2128
+ )}
2129
+ >
2130
+ Save
2131
+ </button>
2132
+ </div>
2133
+ </div>
2134
+ </form>
2135
+ </Show>
2066
2136
  <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2067
2137
  Query Explorer
2068
2138
  </div>
@@ -3318,6 +3388,74 @@ const stylesFactory = (
3318
3388
  }
3319
3389
  }
3320
3390
  `,
3391
+ devtoolsEditForm: css`
3392
+ padding: ${size[2]};
3393
+ & > [data-error='true'] {
3394
+ outline: 2px solid ${t(colors.red[200], colors.red[800])};
3395
+ outline-offset: 2px;
3396
+ border-radius: ${border.radius.xs};
3397
+ }
3398
+ `,
3399
+ devtoolsEditTextarea: css`
3400
+ width: 100%;
3401
+ max-height: 500px;
3402
+ font-family: 'Fira Code', monospace;
3403
+ font-size: ${font.size.xs};
3404
+ border-radius: ${border.radius.sm};
3405
+ field-sizing: content;
3406
+ padding: ${size[2]};
3407
+ background-color: ${t(colors.gray[100], colors.darkGray[800])};
3408
+ color: ${t(colors.gray[900], colors.gray[100])};
3409
+ border: 1px solid ${t(colors.gray[200], colors.gray[700])};
3410
+ resize: none;
3411
+ &:focus {
3412
+ outline-offset: 2px;
3413
+ border-radius: ${border.radius.xs};
3414
+ outline: 2px solid ${t(colors.blue[200], colors.blue[800])};
3415
+ }
3416
+ `,
3417
+ devtoolsEditFormActions: css`
3418
+ display: flex;
3419
+ justify-content: space-between;
3420
+ gap: ${size[2]};
3421
+ align-items: center;
3422
+ padding-top: ${size[1]};
3423
+ font-size: ${font.size.xs};
3424
+ `,
3425
+ devtoolsEditFormError: css`
3426
+ color: ${t(colors.red[700], colors.red[500])};
3427
+ `,
3428
+ devtoolsEditFormActionContainer: css`
3429
+ display: flex;
3430
+ gap: ${size[2]};
3431
+ `,
3432
+ devtoolsEditFormAction: css`
3433
+ font-family: ui-sans-serif, Inter, system-ui, sans-serif, sans-serif;
3434
+ font-size: ${font.size.xs};
3435
+ padding: ${size[1]} ${tokens.size[2]};
3436
+ display: flex;
3437
+ border-radius: ${border.radius.sm};
3438
+ background-color: ${t(colors.gray[100], colors.darkGray[600])};
3439
+ border: 1px solid ${t(colors.gray[300], colors.darkGray[400])};
3440
+ align-items: center;
3441
+ gap: ${size[2]};
3442
+ font-weight: ${font.weight.medium};
3443
+ line-height: ${font.lineHeight.xs};
3444
+ cursor: pointer;
3445
+ &:focus-visible {
3446
+ outline-offset: 2px;
3447
+ border-radius: ${border.radius.xs};
3448
+ outline: 2px solid ${colors.blue[800]};
3449
+ }
3450
+ &:hover {
3451
+ background-color: ${t(colors.gray[200], colors.darkGray[500])};
3452
+ }
3453
+
3454
+ &:disabled {
3455
+ opacity: 0.6;
3456
+ cursor: not-allowed;
3457
+ }
3458
+ `,
3321
3459
  }
3322
3460
  }
3323
3461
 
package/src/Explorer.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { stringify } from 'superjson'
1
+ import { serialize, stringify } from 'superjson'
2
2
  import { clsx as cx } from 'clsx'
3
3
  import { Index, Match, Show, Switch, createMemo, createSignal } from 'solid-js'
4
4
  import { Key } from '@solid-primitives/keyed'
@@ -9,7 +9,15 @@ import {
9
9
  displayValue,
10
10
  updateNestedDataByPath,
11
11
  } from './utils'
12
- import { Check, CopiedCopier, Copier, ErrorCopier, List, Trash } from './icons'
12
+ import {
13
+ Check,
14
+ CopiedCopier,
15
+ Copier,
16
+ ErrorCopier,
17
+ List,
18
+ Pencil,
19
+ Trash,
20
+ } from './icons'
13
21
  import { useQueryDevtoolsContext, useTheme } from './contexts'
14
22
  import type { Query } from '@tanstack/query-core'
15
23
 
@@ -243,6 +251,7 @@ type ExplorerProps = {
243
251
  dataPath?: Array<string>
244
252
  activeQuery?: Query
245
253
  itemsDeletable?: boolean
254
+ onEdit?: () => void
246
255
  }
247
256
 
248
257
  function isIterable(x: any): x is Iterable<unknown> {
@@ -351,6 +360,19 @@ export default function Explorer(props: ExplorerProps) {
351
360
  dataPath={currentDataPath}
352
361
  />
353
362
  </Show>
363
+
364
+ <Show when={!!props.onEdit && !serialize(props.value).meta}>
365
+ <button
366
+ class={styles().actionButton}
367
+ title={'Bulk Edit Data'}
368
+ aria-label={'Bulk Edit Data'}
369
+ onClick={() => {
370
+ props.onEdit?.()
371
+ }}
372
+ >
373
+ <Pencil />
374
+ </button>
375
+ </Show>
354
376
  </div>
355
377
  </Show>
356
378
  </div>
@@ -309,6 +309,26 @@ export function Copier() {
309
309
  )
310
310
  }
311
311
 
312
+ export function Pencil() {
313
+ return (
314
+ <svg
315
+ width="24"
316
+ height="24"
317
+ viewBox="0 0 24 24"
318
+ fill="none"
319
+ xmlns="http://www.w3.org/2000/svg"
320
+ >
321
+ <path
322
+ d="M2.5 21.4998L8.04927 19.3655C8.40421 19.229 8.58168 19.1607 8.74772 19.0716C8.8952 18.9924 9.0358 18.901 9.16804 18.7984C9.31692 18.6829 9.45137 18.5484 9.72028 18.2795L21 6.99982C22.1046 5.89525 22.1046 4.10438 21 2.99981C19.8955 1.89525 18.1046 1.89524 17 2.99981L5.72028 14.2795C5.45138 14.5484 5.31692 14.6829 5.20139 14.8318C5.09877 14.964 5.0074 15.1046 4.92823 15.2521C4.83911 15.4181 4.77085 15.5956 4.63433 15.9506L2.5 21.4998ZM2.5 21.4998L4.55812 16.1488C4.7054 15.7659 4.77903 15.5744 4.90534 15.4867C5.01572 15.4101 5.1523 15.3811 5.2843 15.4063C5.43533 15.4351 5.58038 15.5802 5.87048 15.8703L8.12957 18.1294C8.41967 18.4195 8.56472 18.5645 8.59356 18.7155C8.61877 18.8475 8.58979 18.9841 8.51314 19.0945C8.42545 19.2208 8.23399 19.2944 7.85107 19.4417L2.5 21.4998Z"
323
+ stroke="currentColor"
324
+ stroke-width="2"
325
+ stroke-linecap="round"
326
+ stroke-linejoin="round"
327
+ />
328
+ </svg>
329
+ )
330
+ }
331
+
312
332
  export function CopiedCopier(props: { theme: 'light' | 'dark' }) {
313
333
  return (
314
334
  <svg