@tanstack/query-core 5.27.4 → 5.28.0

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.
Files changed (79) hide show
  1. package/build/legacy/hydration.d.cts +1 -1
  2. package/build/legacy/hydration.d.ts +1 -1
  3. package/build/legacy/index.d.cts +1 -1
  4. package/build/legacy/index.d.ts +1 -1
  5. package/build/legacy/infiniteQueryBehavior.d.cts +1 -1
  6. package/build/legacy/infiniteQueryBehavior.d.ts +1 -1
  7. package/build/legacy/infiniteQueryObserver.d.cts +1 -1
  8. package/build/legacy/infiniteQueryObserver.d.ts +1 -1
  9. package/build/legacy/mutation.d.cts +1 -1
  10. package/build/legacy/mutation.d.ts +1 -1
  11. package/build/legacy/mutationCache.d.cts +1 -1
  12. package/build/legacy/mutationCache.d.ts +1 -1
  13. package/build/legacy/mutationObserver.d.cts +1 -1
  14. package/build/legacy/mutationObserver.d.ts +1 -1
  15. package/build/legacy/queriesObserver.d.cts +1 -1
  16. package/build/legacy/queriesObserver.d.ts +1 -1
  17. package/build/legacy/query.d.cts +1 -1
  18. package/build/legacy/query.d.ts +1 -1
  19. package/build/legacy/queryCache.d.cts +1 -1
  20. package/build/legacy/queryCache.d.ts +1 -1
  21. package/build/legacy/{queryClient-WUwa1bEQ.d.ts → queryClient-UWB6EkqM.d.ts} +5 -2
  22. package/build/legacy/{queryClient-8vXd-6hw.d.cts → queryClient-WxLAyIG_.d.cts} +5 -2
  23. package/build/legacy/queryClient.cjs +14 -5
  24. package/build/legacy/queryClient.cjs.map +1 -1
  25. package/build/legacy/queryClient.d.cts +1 -1
  26. package/build/legacy/queryClient.d.ts +1 -1
  27. package/build/legacy/queryClient.js +14 -5
  28. package/build/legacy/queryClient.js.map +1 -1
  29. package/build/legacy/queryObserver.d.cts +1 -1
  30. package/build/legacy/queryObserver.d.ts +1 -1
  31. package/build/legacy/retryer.d.cts +1 -1
  32. package/build/legacy/retryer.d.ts +1 -1
  33. package/build/legacy/types.cjs.map +1 -1
  34. package/build/legacy/types.d.cts +1 -1
  35. package/build/legacy/types.d.ts +1 -1
  36. package/build/legacy/utils.d.cts +1 -1
  37. package/build/legacy/utils.d.ts +1 -1
  38. package/build/modern/hydration.d.cts +1 -1
  39. package/build/modern/hydration.d.ts +1 -1
  40. package/build/modern/index.d.cts +1 -1
  41. package/build/modern/index.d.ts +1 -1
  42. package/build/modern/infiniteQueryBehavior.d.cts +1 -1
  43. package/build/modern/infiniteQueryBehavior.d.ts +1 -1
  44. package/build/modern/infiniteQueryObserver.d.cts +1 -1
  45. package/build/modern/infiniteQueryObserver.d.ts +1 -1
  46. package/build/modern/mutation.d.cts +1 -1
  47. package/build/modern/mutation.d.ts +1 -1
  48. package/build/modern/mutationCache.d.cts +1 -1
  49. package/build/modern/mutationCache.d.ts +1 -1
  50. package/build/modern/mutationObserver.d.cts +1 -1
  51. package/build/modern/mutationObserver.d.ts +1 -1
  52. package/build/modern/queriesObserver.d.cts +1 -1
  53. package/build/modern/queriesObserver.d.ts +1 -1
  54. package/build/modern/query.d.cts +1 -1
  55. package/build/modern/query.d.ts +1 -1
  56. package/build/modern/queryCache.d.cts +1 -1
  57. package/build/modern/queryCache.d.ts +1 -1
  58. package/build/modern/{queryClient-WUwa1bEQ.d.ts → queryClient-UWB6EkqM.d.ts} +5 -2
  59. package/build/modern/{queryClient-8vXd-6hw.d.cts → queryClient-WxLAyIG_.d.cts} +5 -2
  60. package/build/modern/queryClient.cjs +14 -5
  61. package/build/modern/queryClient.cjs.map +1 -1
  62. package/build/modern/queryClient.d.cts +1 -1
  63. package/build/modern/queryClient.d.ts +1 -1
  64. package/build/modern/queryClient.js +14 -5
  65. package/build/modern/queryClient.js.map +1 -1
  66. package/build/modern/queryObserver.d.cts +1 -1
  67. package/build/modern/queryObserver.d.ts +1 -1
  68. package/build/modern/retryer.d.cts +1 -1
  69. package/build/modern/retryer.d.ts +1 -1
  70. package/build/modern/types.cjs.map +1 -1
  71. package/build/modern/types.d.cts +1 -1
  72. package/build/modern/types.d.ts +1 -1
  73. package/build/modern/utils.d.cts +1 -1
  74. package/build/modern/utils.d.ts +1 -1
  75. package/package.json +1 -1
  76. package/src/queryClient.ts +20 -8
  77. package/src/tests/queryClient.test.tsx +88 -8
  78. package/src/tests/utils.ts +3 -3
  79. package/src/types.ts +16 -0
@@ -450,6 +450,33 @@ describe('queryClient', () => {
450
450
  queryClient.ensureQueryData({ queryKey: [key], queryFn }),
451
451
  ).resolves.toEqual('data')
452
452
  })
453
+
454
+ test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {
455
+ const TIMEOUT = 10
456
+ const key = queryKey()
457
+ queryClient.setQueryData([key, 'id'], 'old')
458
+
459
+ const queryFn = () =>
460
+ new Promise((resolve) => {
461
+ setTimeout(() => resolve('new'), TIMEOUT)
462
+ })
463
+
464
+ await expect(
465
+ queryClient.ensureQueryData({
466
+ queryKey: [key, 'id'],
467
+ queryFn,
468
+ revalidateIfStale: true,
469
+ }),
470
+ ).resolves.toEqual('old')
471
+ await sleep(TIMEOUT + 10)
472
+ await expect(
473
+ queryClient.ensureQueryData({
474
+ queryKey: [key, 'id'],
475
+ queryFn,
476
+ revalidateIfStale: true,
477
+ }),
478
+ ).resolves.toEqual('new')
479
+ })
453
480
  })
454
481
 
455
482
  describe('getQueriesData', () => {
@@ -1389,6 +1416,10 @@ describe('queryClient', () => {
1389
1416
  })
1390
1417
 
1391
1418
  describe('focusManager and onlineManager', () => {
1419
+ afterEach(() => {
1420
+ onlineManager.setOnline(true)
1421
+ focusManager.setFocused(undefined)
1422
+ })
1392
1423
  test('should notify queryCache and mutationCache if focused', async () => {
1393
1424
  const testClient = createQueryClient()
1394
1425
  testClient.mount()
@@ -1411,7 +1442,7 @@ describe('queryClient', () => {
1411
1442
  expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()
1412
1443
 
1413
1444
  focusManager.setFocused(true)
1414
- expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1)
1445
+ await waitFor(() => expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1))
1415
1446
  expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)
1416
1447
 
1417
1448
  expect(queryCacheOnOnlineSpy).not.toHaveBeenCalled()
@@ -1419,7 +1450,6 @@ describe('queryClient', () => {
1419
1450
  queryCacheOnFocusSpy.mockRestore()
1420
1451
  mutationCacheResumePausedMutationsSpy.mockRestore()
1421
1452
  queryCacheOnOnlineSpy.mockRestore()
1422
- focusManager.setFocused(undefined)
1423
1453
  })
1424
1454
 
1425
1455
  test('should notify queryCache and mutationCache if online', async () => {
@@ -1444,7 +1474,10 @@ describe('queryClient', () => {
1444
1474
  expect(mutationCacheResumePausedMutationsSpy).not.toHaveBeenCalled()
1445
1475
 
1446
1476
  onlineManager.setOnline(true)
1447
- expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1)
1477
+ await waitFor(() =>
1478
+ expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1),
1479
+ )
1480
+
1448
1481
  expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)
1449
1482
 
1450
1483
  expect(queryCacheOnFocusSpy).not.toHaveBeenCalled()
@@ -1452,7 +1485,6 @@ describe('queryClient', () => {
1452
1485
  queryCacheOnFocusSpy.mockRestore()
1453
1486
  queryCacheOnOnlineSpy.mockRestore()
1454
1487
  mutationCacheResumePausedMutationsSpy.mockRestore()
1455
- onlineManager.setOnline(true)
1456
1488
  })
1457
1489
 
1458
1490
  test('should resume paused mutations when coming online', async () => {
@@ -1481,8 +1513,6 @@ describe('queryClient', () => {
1481
1513
  expect(observer1.getCurrentResult().status).toBe('success')
1482
1514
  expect(observer1.getCurrentResult().status).toBe('success')
1483
1515
  })
1484
-
1485
- onlineManager.setOnline(true)
1486
1516
  })
1487
1517
 
1488
1518
  test('should resume paused mutations one after the other when invoked manually at the same time', async () => {
@@ -1600,6 +1630,54 @@ describe('queryClient', () => {
1600
1630
  newQueryClient.unmount()
1601
1631
  })
1602
1632
 
1633
+ test('should notify queryCache after resumePausedMutations has finished when coming online', async () => {
1634
+ const key = queryKey()
1635
+
1636
+ let count = 0
1637
+ const results: Array<string> = []
1638
+
1639
+ const queryObserver = new QueryObserver(queryClient, {
1640
+ queryKey: key,
1641
+ queryFn: async () => {
1642
+ count++
1643
+ results.push('data' + count)
1644
+ await sleep(10)
1645
+ return 'data' + count
1646
+ },
1647
+ })
1648
+
1649
+ const unsubscribe = queryObserver.subscribe(() => undefined)
1650
+
1651
+ await waitFor(() => {
1652
+ expect(queryClient.getQueryData(key)).toBe('data1')
1653
+ })
1654
+
1655
+ onlineManager.setOnline(false)
1656
+
1657
+ const observer = new MutationObserver(queryClient, {
1658
+ mutationFn: async () => {
1659
+ results.push('mutation')
1660
+ await sleep(50)
1661
+ return 1
1662
+ },
1663
+ })
1664
+
1665
+ void observer.mutate()
1666
+
1667
+ expect(observer.getCurrentResult().isPaused).toBeTruthy()
1668
+
1669
+ onlineManager.setOnline(true)
1670
+
1671
+ await waitFor(() => {
1672
+ expect(queryClient.getQueryData(key)).toBe('data2')
1673
+ })
1674
+
1675
+ // refetch from coming online should happen after mutations have finished
1676
+ expect(results).toStrictEqual(['data1', 'mutation', 'data2'])
1677
+
1678
+ unsubscribe()
1679
+ })
1680
+
1603
1681
  test('should notify queryCache and mutationCache after multiple mounts and single unmount', async () => {
1604
1682
  const testClient = createQueryClient()
1605
1683
  testClient.mount()
@@ -1621,11 +1699,13 @@ describe('queryClient', () => {
1621
1699
 
1622
1700
  onlineManager.setOnline(false)
1623
1701
  onlineManager.setOnline(true)
1624
- expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1)
1702
+ await waitFor(() =>
1703
+ expect(queryCacheOnOnlineSpy).toHaveBeenCalledTimes(1),
1704
+ )
1625
1705
  expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(1)
1626
1706
 
1627
1707
  focusManager.setFocused(true)
1628
- expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1)
1708
+ await waitFor(() => expect(queryCacheOnFocusSpy).toHaveBeenCalledTimes(1))
1629
1709
  expect(mutationCacheResumePausedMutationsSpy).toHaveBeenCalledTimes(2)
1630
1710
 
1631
1711
  queryCacheOnFocusSpy.mockRestore()
@@ -1,7 +1,7 @@
1
1
  import { vi } from 'vitest'
2
2
  import { QueryClient, onlineManager } from '..'
3
3
  import * as utils from '../utils'
4
- import type { SpyInstance } from 'vitest'
4
+ import type { MockInstance } from 'vitest'
5
5
  import type { MutationOptions, QueryClientConfig } from '..'
6
6
 
7
7
  export function createQueryClient(config?: QueryClientConfig): QueryClient {
@@ -10,13 +10,13 @@ export function createQueryClient(config?: QueryClientConfig): QueryClient {
10
10
 
11
11
  export function mockVisibilityState(
12
12
  value: DocumentVisibilityState,
13
- ): SpyInstance<[], DocumentVisibilityState> {
13
+ ): MockInstance<[], DocumentVisibilityState> {
14
14
  return vi.spyOn(document, 'visibilityState', 'get').mockReturnValue(value)
15
15
  }
16
16
 
17
17
  export function mockOnlineManagerIsOnline(
18
18
  value: boolean,
19
- ): SpyInstance<[], boolean> {
19
+ ): MockInstance<[], boolean> {
20
20
  return vi.spyOn(onlineManager, 'isOnline').mockReturnValue(value)
21
21
  }
22
22
 
package/src/types.ts CHANGED
@@ -407,6 +407,22 @@ export interface FetchQueryOptions<
407
407
  staleTime?: number
408
408
  }
409
409
 
410
+ export interface EnsureQueryDataOptions<
411
+ TQueryFnData = unknown,
412
+ TError = DefaultError,
413
+ TData = TQueryFnData,
414
+ TQueryKey extends QueryKey = QueryKey,
415
+ TPageParam = never,
416
+ > extends FetchQueryOptions<
417
+ TQueryFnData,
418
+ TError,
419
+ TData,
420
+ TQueryKey,
421
+ TPageParam
422
+ > {
423
+ revalidateIfStale?: boolean
424
+ }
425
+
410
426
  type FetchInfiniteQueryPages<TQueryFnData = unknown, TPageParam = unknown> =
411
427
  | { pages?: never }
412
428
  | {