snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s

This commit is contained in:
upstream-mirror
2026-09-16 01:13:08 +05:00
commit 3a013ccdfe
3570 changed files with 490194 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
{
"ignoreRules": ["cjs-resolves-to-esm", "internal-resolution-error"]
}

View File

@@ -0,0 +1,557 @@
# @tanstack/svelte-query-persist-client
## 6.1.48
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.8
- @tanstack/svelte-query@6.1.48
## 6.1.47
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.7
- @tanstack/svelte-query@6.1.47
## 6.1.46
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.6
- @tanstack/svelte-query@6.1.46
## 6.1.45
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.5
- @tanstack/svelte-query@6.1.45
## 6.1.44
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.4
- @tanstack/svelte-query@6.1.44
## 6.1.43
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.3
- @tanstack/svelte-query@6.1.43
## 6.1.42
### Patch Changes
- Updated dependencies [[`cafd540`](https://github.com/TanStack/query/commit/cafd540c02f78be260198c4e84d054390c02c6b8), [`320ed25`](https://github.com/TanStack/query/commit/320ed25caca4e219b53f778c59cbb380543a21f4), [`250050d`](https://github.com/TanStack/query/commit/250050d863d33fbc881c6e342c104d510403a9e1)]:
- @tanstack/svelte-query@6.1.42
## 6.1.41
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.2
- @tanstack/svelte-query@6.1.41
## 6.1.40
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.102.1
- @tanstack/svelte-query@6.1.40
## 6.1.39
### Patch Changes
- Updated dependencies [[`6e3d521`](https://github.com/TanStack/query/commit/6e3d521fe54f78624e53c1c6f9cadd678504bee8), [`294d4e6`](https://github.com/TanStack/query/commit/294d4e62c4f7d674574a4903eef2a1bc3dd1413b), [`2215bb0`](https://github.com/TanStack/query/commit/2215bb031139cdc8a84751b37a485c38ca9d2b6e), [`1ef4208`](https://github.com/TanStack/query/commit/1ef42087c9a266c2137d2ef645cbcc662f60ac93)]:
- @tanstack/svelte-query@6.1.39
- @tanstack/query-persist-client-core@5.102.0
## 6.1.38
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.101.4
- @tanstack/svelte-query@6.1.38
## 6.1.37
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.101.3
- @tanstack/svelte-query@6.1.37
## 6.1.36
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.101.2
- @tanstack/svelte-query@6.1.36
## 6.1.35
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.101.1
- @tanstack/svelte-query@6.1.35
## 6.1.34
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.101.0
- @tanstack/svelte-query@6.1.34
## 6.1.33
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.14
- @tanstack/svelte-query@6.1.33
## 6.1.32
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.13
- @tanstack/svelte-query@6.1.32
## 6.1.31
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.12
- @tanstack/svelte-query@6.1.31
## 6.1.30
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.11
- @tanstack/svelte-query@6.1.30
## 6.1.29
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.10
- @tanstack/svelte-query@6.1.29
## 6.1.28
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.9
- @tanstack/svelte-query@6.1.28
## 6.1.27
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.8
- @tanstack/svelte-query@6.1.27
## 6.1.26
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.7
- @tanstack/svelte-query@6.1.26
## 6.1.25
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.6
- @tanstack/svelte-query@6.1.25
## 6.1.24
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.5
- @tanstack/svelte-query@6.1.24
## 6.1.23
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.4
- @tanstack/svelte-query@6.1.23
## 6.1.22
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.3
- @tanstack/svelte-query@6.1.22
## 6.1.21
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.2
- @tanstack/svelte-query@6.1.21
## 6.1.20
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.1
- @tanstack/svelte-query@6.1.20
## 6.1.19
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.100.0
- @tanstack/svelte-query@6.1.19
## 6.1.18
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.99.2
- @tanstack/svelte-query@6.1.18
## 6.1.17
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.99.1
- @tanstack/svelte-query@6.1.17
## 6.1.16
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.99.0
- @tanstack/svelte-query@6.1.16
## 6.1.15
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.98.0
- @tanstack/svelte-query@6.1.15
## 6.1.14
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.97.0
- @tanstack/svelte-query@6.1.14
## 6.1.13
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.96.2
- @tanstack/svelte-query@6.1.13
## 6.1.12
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.96.1
- @tanstack/svelte-query@6.1.12
## 6.1.11
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.96.0
- @tanstack/svelte-query@6.1.11
## 6.1.10
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.95.2
- @tanstack/svelte-query@6.1.10
## 6.1.9
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.95.1
- @tanstack/svelte-query@6.1.9
## 6.1.8
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.95.0
- @tanstack/svelte-query@6.1.8
## 6.1.7
### Patch Changes
- fix(\*): resolve issue about excluded build directory ([#10312](https://github.com/TanStack/query/pull/10312))
- Updated dependencies [[`4b6536d`](https://github.com/TanStack/query/commit/4b6536dfce99036f4e37f52943c6fed3ad0e0a18)]:
- @tanstack/query-persist-client-core@5.94.5
- @tanstack/svelte-query@6.1.7
## 6.1.6
### Patch Changes
- chore: fixed version ([#10064](https://github.com/TanStack/query/pull/10064))
- Updated dependencies [[`4c75210`](https://github.com/TanStack/query/commit/4c75210ce8235fe3d39b67e1029eff11278927cc)]:
- @tanstack/query-persist-client-core@5.94.4
- @tanstack/svelte-query@6.1.6
## 6.0.25
### Patch Changes
- fix(streamedQuery): maintain error state on reset refetch with initialData defined ([#10287](https://github.com/TanStack/query/pull/10287))
- Updated dependencies [[`248975e`](https://github.com/TanStack/query/commit/248975e896f585f6eaa505c796e73fcf7bfd1eec)]:
- @tanstack/query-persist-client-core@5.92.4
- @tanstack/svelte-query@6.1.3
## 6.0.24
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.92.3
- @tanstack/svelte-query@6.1.2
## 6.0.23
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.92.2
- @tanstack/svelte-query@6.1.1
## 6.0.22
### Patch Changes
- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:
- @tanstack/query-persist-client-core@5.92.1
## 6.0.21
### Patch Changes
- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:
- @tanstack/query-persist-client-core@5.92.0
## 6.0.20
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.19
- @tanstack/svelte-query@6.0.18
## 6.0.19
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.18
- @tanstack/svelte-query@6.0.17
## 6.0.18
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.17
- @tanstack/svelte-query@6.0.16
## 6.0.17
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.16
- @tanstack/svelte-query@6.0.15
## 6.0.16
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.15
- @tanstack/svelte-query@6.0.14
## 6.0.15
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.14
- @tanstack/svelte-query@6.0.13
## 6.0.14
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.13
- @tanstack/svelte-query@6.0.12
## 6.0.13
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.12
- @tanstack/svelte-query@6.0.11
## 6.0.12
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.11
- @tanstack/svelte-query@6.0.10
## 6.0.11
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.10
- @tanstack/svelte-query@6.0.9
## 6.0.10
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.9
- @tanstack/svelte-query@6.0.8
## 6.0.9
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.8
- @tanstack/svelte-query@6.0.7
## 6.0.8
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.7
- @tanstack/svelte-query@6.0.6
## 6.0.7
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.6
- @tanstack/svelte-query@6.0.5
## 6.0.6
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.5
- @tanstack/svelte-query@6.0.4
## 6.0.5
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.4
- @tanstack/svelte-query@6.0.3
## 6.0.4
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.3
- @tanstack/svelte-query@6.0.2
## 6.0.3
### Patch Changes
- Updated dependencies []:
- @tanstack/query-persist-client-core@5.91.2
- @tanstack/svelte-query@6.0.1
## 6.0.2
### Patch Changes
- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:
- @tanstack/query-persist-client-core@5.91.1
## 6.0.1
### Patch Changes
- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:
- @tanstack/query-persist-client-core@5.91.0
## 6.0.0
### Major Changes
- BREAKING: Migrate to svelte runes (signals). Requires [Svelte v5.25.0](https://github.com/sveltejs/svelte/releases/tag/svelte%405.25.0) or newer. Please see the [migration guide](https://tanstack.com/query/latest/docs/framework/svelte/migrate-from-v5-to-v6). ([#9694](https://github.com/TanStack/query/pull/9694))
### Patch Changes
- Updated dependencies [[`1056ba6`](https://github.com/TanStack/query/commit/1056ba63b30b9d9a66fa813c7d7fb1395e377c55)]:
- @tanstack/svelte-query@6.0.0

View File

@@ -0,0 +1,28 @@
// @ts-check
import tsParser from '@typescript-eslint/parser'
import pluginSvelte from 'eslint-plugin-svelte'
import rootConfig from './root.eslint.config.js'
import svelteConfig from './svelte.config.js'
export default [
...rootConfig,
...pluginSvelte.configs['recommended'],
{
files: ['**/*.svelte', '**/*.svelte.ts', '**/*.svelte.js'],
languageOptions: {
parserOptions: {
parser: tsParser,
extraFileExtensions: ['.svelte'],
svelteConfig,
},
},
},
{
rules: {
'svelte/block-lang': ['error', { script: ['ts'] }],
'svelte/no-svelte-internal': 'error',
'svelte/valid-compile': 'off',
},
},
]

View File

@@ -0,0 +1,70 @@
{
"name": "@tanstack/svelte-query-persist-client",
"version": "6.1.48",
"description": "Svelte bindings to work with persisters in TanStack/svelte-query",
"author": "Lachlan Collins",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/query.git",
"directory": "packages/svelte-query-persist-client"
},
"homepage": "https://tanstack.com/query",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"keywords": [
"tanstack",
"query",
"svelte"
],
"scripts": {
"clean": "premove ./dist ./coverage ./.svelte-kit ./dist-ts",
"compile": "tsc --project tsconfig.json",
"test:types": "svelte-check --tsconfig ./tsconfig.json",
"test:eslint": "eslint --concurrency=auto ./src ./tests",
"test:lib": "vitest",
"test:lib:dev": "pnpm run test:lib --watch",
"test:build": "publint --strict && attw --pack",
"build": "svelte-package --input ./src --output ./dist"
},
"type": "module",
"types": "dist/index.d.ts",
"module": "dist/index.js",
"svelte": "./dist/index.js",
"exports": {
".": {
"@tanstack/custom-condition": "./src/index.ts",
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js",
"import": "./dist/index.js"
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"dist",
"src",
"!src/__tests__"
],
"dependencies": {
"@tanstack/query-persist-client-core": "workspace:*"
},
"devDependencies": {
"@sveltejs/package": "^2.5.8",
"@sveltejs/vite-plugin-svelte": "^5.1.1",
"@tanstack/query-test-utils": "workspace:*",
"@tanstack/svelte-query": "workspace:*",
"@testing-library/svelte": "^5.2.8",
"@typescript-eslint/parser": "^8.48.0",
"eslint-plugin-svelte": "^3.11.0",
"svelte": "^5.39.3",
"svelte-check": "^4.4.5",
"typescript": "5.9.3"
},
"peerDependencies": {
"@tanstack/svelte-query": "workspace:^",
"svelte": "^5.25.0"
}
}

View File

@@ -0,0 +1 @@
../../eslint.config.js

View File

@@ -0,0 +1,56 @@
<script lang="ts">
import {
persistQueryClientRestore,
persistQueryClientSubscribe,
} from '@tanstack/query-persist-client-core'
import {
QueryClientProvider,
setIsRestoringContext,
} from '@tanstack/svelte-query'
import { box } from './utils.svelte.js'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type {
OmitKeyof,
QueryClientProviderProps,
} from '@tanstack/svelte-query'
type PersistQueryClientProviderProps = QueryClientProviderProps & {
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
onSuccess?: () => void
onError?: () => void
}
let {
client,
children,
persistOptions,
...props
}: PersistQueryClientProviderProps = $props()
let isRestoring = box(true)
setIsRestoringContext(isRestoring)
const options = $derived({
...persistOptions,
queryClient: client,
})
$effect(() => {
return isRestoring.current ? () => {} : persistQueryClientSubscribe(options)
})
$effect(() => {
isRestoring.current = true
persistQueryClientRestore(options)
.then(() => props.onSuccess?.())
.catch(() => props.onError?.())
.finally(() => {
isRestoring.current = false
})
})
</script>
<QueryClientProvider {client} {...props}>
{@render children()}
</QueryClientProvider>

View File

@@ -0,0 +1,3 @@
// Re-export core
export * from '@tanstack/query-persist-client-core'
export { default as PersistQueryClientProvider } from './PersistQueryClientProvider.svelte'

View File

@@ -0,0 +1,14 @@
type Box<T> = { current: T }
export function box<T>(initial: T): Box<T> {
let current = $state(initial)
return {
get current() {
return current
},
set current(newValue) {
current = newValue
},
}
}

View File

@@ -0,0 +1,10 @@
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
const config = {
preprocess: vitePreprocess(),
compilerOptions: {
runes: true,
},
}
export default config

View File

@@ -0,0 +1,20 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
import { StatelessRef } from '../utils.svelte.js'
let { states }: { states: StatelessRef<Array<string>> } = $props()
const query = createQuery(() => ({
queryKey: ['test'],
queryFn: async () => {
states.current.push('fetching')
await sleep(10)
states.current.push('fetched')
return 'fetched'
},
}))
</script>
<div>{query.data}</div>
<div>fetchStatus: {query.fetchStatus}</div>

View File

@@ -0,0 +1,20 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import AwaitOnSuccess from './AwaitOnSuccess.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import { StatelessRef } from '../utils.svelte'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
onSuccess: () => Promise<void>
states: StatelessRef<Array<string>>
}
let { queryClient, persistOptions, onSuccess, states }: Props = $props()
</script>
<PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>
<AwaitOnSuccess {states} />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
let {
states,
onFetch,
}: {
states: StatelessRef<Array<StatusResult<string>>>
onFetch: () => void
} = $props()
const query = createQuery(() => ({
queryKey: ['test'],
queryFn: async () => {
await sleep(10)
onFetch()
return 'fetched'
},
staleTime: Infinity,
}))
$effect(() => {
const snapshot = $state.snapshot(query)
states.current.push(snapshot)
})
</script>
<div>data: {query.data ?? 'null'}</div>
<div>fetchStatus: {query.fetchStatus}</div>

View File

@@ -0,0 +1,20 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import FreshData from './FreshData.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
states: StatelessRef<Array<StatusResult<string>>>
onFetch: () => void
}
let { queryClient, persistOptions, states, onFetch }: Props = $props()
</script>
<PersistQueryClientProvider client={queryClient} {persistOptions}>
<FreshData {states} {onFetch} />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,25 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =
$props()
const query = createQuery(() => ({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'fetched'),
initialData: 'initial',
// make sure that initial data is older than the hydration data
// otherwise initialData would be newer and takes precedence
initialDataUpdatedAt: 1,
}))
$effect(() => {
const snapshot = $state.snapshot(query)
states.current.push(snapshot)
})
</script>
<div>{query.data}</div>
<div>fetchStatus: {query.fetchStatus}</div>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import InitialData from './InitialData.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
states: StatelessRef<Array<StatusResult<string>>>
}
let { queryClient, persistOptions, states }: Props = $props()
</script>
<PersistQueryClientProvider client={queryClient} {persistOptions}>
<InitialData {states} />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
const query = createQuery(() => ({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'fetched'),
}))
</script>
<div>{query.data}</div>
<div>fetchStatus: {query.fetchStatus}</div>

View File

@@ -0,0 +1,18 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import OnSuccess from './OnSuccess.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
onSuccess: () => void
}
let { queryClient, persistOptions, onSuccess }: Props = $props()
</script>
<PersistQueryClientProvider client={queryClient} {persistOptions} {onSuccess}>
<OnSuccess />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,390 @@
import { render } from '@testing-library/svelte'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { QueryClient, noop } from '@tanstack/svelte-query'
import { persistQueryClientSave } from '@tanstack/query-persist-client-core'
import { sleep } from '@tanstack/query-test-utils'
import AwaitOnSuccess from './AwaitOnSuccess/Provider.svelte'
import FreshData from './FreshData/Provider.svelte'
import OnSuccess from './OnSuccess/Provider.svelte'
import InitialData from './InitialData/Provider.svelte'
import RemoveCache from './RemoveCache/Provider.svelte'
import RestoreCache from './RestoreCache/Provider.svelte'
import UseQueries from './UseQueries/Provider.svelte'
import { StatelessRef } from './utils.svelte.js'
import type {
PersistedClient,
Persister,
} from '@tanstack/query-persist-client-core'
import type { StatusResult } from './utils.svelte.js'
beforeEach(() => {
vi.useFakeTimers()
})
afterEach(() => {
vi.useRealTimers()
})
const createMockPersister = (): Persister => {
let storedState: PersistedClient | undefined
return {
persistClient(persistClient: PersistedClient) {
storedState = persistClient
},
async restoreClient() {
return sleep(10).then(() => storedState)
},
removeClient() {
storedState = undefined
},
}
}
const createMockErrorPersister = (
removeClient: Persister['removeClient'],
): [Error, Persister] => {
const error = new Error('restore failed')
return [
error,
{
async persistClient() {
// noop
},
async restoreClient() {
return sleep(10).then(() => Promise.reject(error))
},
removeClient,
},
]
}
describe('PersistQueryClientProvider', () => {
it('restores cache from persister', async () => {
const states = new StatelessRef<Array<StatusResult<string>>>([])
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
const rendered = render(RestoreCache, {
props: {
queryClient,
persistOptions: { persister },
states,
},
})
expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(states.current).toHaveLength(3)
expect(states.current[0]).toMatchObject({
status: 'pending',
fetchStatus: 'idle',
data: undefined,
})
expect(states.current[1]).toMatchObject({
status: 'success',
fetchStatus: 'fetching',
data: 'hydrated',
})
expect(states.current[2]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'fetched',
})
})
it('should also put useQueries into idle state', async () => {
const states = new StatelessRef<Array<StatusResult<string>>>([])
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
const rendered = render(UseQueries, {
props: {
queryClient,
persistOptions: { persister },
states,
},
})
expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(states.current).toHaveLength(3)
expect(states.current[0]).toMatchObject({
status: 'pending',
fetchStatus: 'idle',
data: undefined,
})
expect(states.current[1]).toMatchObject({
status: 'success',
fetchStatus: 'fetching',
data: 'hydrated',
})
expect(states.current[2]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'fetched',
})
})
it('should show initialData while restoring', async () => {
const states = new StatelessRef<Array<StatusResult<string>>>([])
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
const rendered = render(InitialData, {
props: {
queryClient,
persistOptions: { persister },
states,
},
})
expect(rendered.getByText('initial')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(states.current).toHaveLength(3)
expect(states.current[0]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'initial',
})
expect(states.current[1]).toMatchObject({
status: 'success',
fetchStatus: 'fetching',
data: 'hydrated',
})
expect(states.current[2]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'fetched',
})
})
it('should not refetch after restoring when data is fresh', async () => {
const states = new StatelessRef<Array<StatusResult<string>>>([])
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
let fetched = false
const rendered = render(FreshData, {
props: {
queryClient,
persistOptions: { persister },
states,
onFetch: () => {
fetched = true
},
},
})
expect(rendered.getByText('data: null')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('data: hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('data: hydrated')).toBeInTheDocument()
expect(states.current).toHaveLength(2)
expect(fetched).toBe(false)
expect(states.current[0]).toMatchObject({
status: 'pending',
fetchStatus: 'idle',
data: undefined,
})
expect(states.current[1]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'hydrated',
})
})
it('should call onSuccess after successful restoring', async () => {
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
const onSuccess = vi.fn()
const rendered = render(OnSuccess, {
props: {
queryClient,
persistOptions: { persister },
onSuccess,
},
})
expect(onSuccess).toHaveBeenCalledTimes(0)
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('hydrated')).toBeInTheDocument()
expect(onSuccess).toHaveBeenCalledTimes(1)
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('fetched')).toBeInTheDocument()
})
it('should await onSuccess after successful restoring', async () => {
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
const states = new StatelessRef<Array<string>>([])
const rendered = render(AwaitOnSuccess, {
props: {
queryClient,
persistOptions: { persister },
states,
onSuccess: async () => {
states.current.push('onSuccess')
await sleep(5)
states.current.push('onSuccess done')
},
},
})
await vi.advanceTimersByTimeAsync(15)
expect(rendered.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(states.current).toEqual([
'onSuccess',
'onSuccess done',
'fetching',
'fetched',
])
})
it('should remove cache after non-successful restoring', async () => {
const consoleMock = vi
.spyOn(console, 'error')
.mockImplementation(() => undefined)
const consoleWarn = vi
.spyOn(console, 'warn')
.mockImplementation(() => undefined)
const queryClient = new QueryClient()
const removeClient = vi.fn()
const onSuccess = vi.fn()
const onError = vi.fn()
const [error, persister] = createMockErrorPersister(removeClient)
const rendered = render(RemoveCache, {
props: { queryClient, persistOptions: { persister }, onError, onSuccess },
})
await vi.advanceTimersByTimeAsync(10)
await vi.advanceTimersByTimeAsync(10)
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(removeClient).toHaveBeenCalledTimes(1)
expect(onSuccess).toHaveBeenCalledTimes(0)
expect(onError).toHaveBeenCalledTimes(1)
expect(consoleMock).toHaveBeenCalledTimes(1)
expect(consoleMock).toHaveBeenNthCalledWith(1, error)
consoleMock.mockRestore()
consoleWarn.mockRestore()
})
})

View File

@@ -0,0 +1,24 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import RemoveCache from './RemoveCache.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
onSuccess: () => void
onError: () => void
}
let { queryClient, persistOptions, onError, onSuccess }: Props = $props()
</script>
<PersistQueryClientProvider
client={queryClient}
{persistOptions}
{onSuccess}
{onError}
>
<RemoveCache />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
const query = createQuery(() => ({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'fetched'),
}))
</script>
<div>{query.data}</div>
<div>fetchStatus: {query.fetchStatus}</div>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import RestoreCache from './RestoreCache.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
states: StatelessRef<Array<StatusResult<string>>>
}
let { queryClient, persistOptions, states }: Props = $props()
</script>
<PersistQueryClientProvider client={queryClient} {persistOptions}>
<RestoreCache {states} />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,21 @@
<script lang="ts">
import { createQuery } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =
$props()
const query = createQuery(() => ({
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'fetched'),
}))
$effect(() => {
const snapshot = $state.snapshot(query)
states.current.push(snapshot)
})
</script>
<div>{query.data}</div>
<div>fetchStatus: {query.fetchStatus}</div>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import PersistQueryClientProvider from '../../src/PersistQueryClientProvider.svelte'
import UseQueries from './UseQueries.svelte'
import type { OmitKeyof, QueryClient } from '@tanstack/svelte-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
interface Props {
queryClient: QueryClient
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
states: StatelessRef<Array<StatusResult<string>>>
}
let { queryClient, persistOptions, states }: Props = $props()
</script>
<PersistQueryClientProvider client={queryClient} {persistOptions}>
<UseQueries {states} />
</PersistQueryClientProvider>

View File

@@ -0,0 +1,25 @@
<script lang="ts">
import { createQueries } from '@tanstack/svelte-query'
import { sleep } from '@tanstack/query-test-utils'
import type { StatelessRef, StatusResult } from '../utils.svelte.js'
let { states }: { states: StatelessRef<Array<StatusResult<string>>> } =
$props()
const queries = createQueries(() => ({
queries: [
{
queryKey: ['test'],
queryFn: () => sleep(10).then(() => 'fetched'),
},
],
}))
$effect(() => {
const snapshot = $state.snapshot(queries[0])
states.current.push(snapshot)
})
</script>
<div>{queries[0].data}</div>
<div>fetchStatus: {queries[0].fetchStatus}</div>

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom/vitest'

View File

@@ -0,0 +1,12 @@
export type StatusResult<T = unknown> = {
status: string
fetchStatus: string
data: T | undefined
}
export class StatelessRef<T> {
current: T
constructor(value: T) {
this.current = value
}
}

View File

@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist-ts",
"rootDir": "."
},
"include": ["src", "tests", "*.config.ts", "*.config.js", "package.json"],
"references": [
{ "path": "../query-persist-client-core" },
{ "path": "../svelte-query" }
]
}

View File

@@ -0,0 +1,29 @@
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { defineConfig } from 'vitest/config'
import { svelteTesting } from '@testing-library/svelte/vite'
import packageJson from './package.json'
export default defineConfig({
plugins: [svelte(), svelteTesting()],
// fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660
resolve: {
conditions: ['@tanstack/custom-condition'],
},
environments: {
ssr: {
resolve: {
conditions: ['@tanstack/custom-condition'],
},
},
},
test: {
name: packageJson.name,
dir: './tests',
watch: false,
environment: 'jsdom',
setupFiles: ['./tests/test-setup.ts'],
typecheck: { enabled: true },
restoreMocks: true,
},
})