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"]
}

View File

@@ -0,0 +1,539 @@
# @tanstack/angular-query-persist-client
## 5.102.8
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.8
- @tanstack/query-persist-client-core@5.102.8
## 5.102.7
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.7
- @tanstack/query-persist-client-core@5.102.7
## 5.102.6
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.6
- @tanstack/query-persist-client-core@5.102.6
## 5.102.5
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.5
- @tanstack/query-persist-client-core@5.102.5
## 5.102.4
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.4
- @tanstack/query-persist-client-core@5.102.4
## 5.102.3
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.3
- @tanstack/query-persist-client-core@5.102.3
## 5.102.2
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.2
- @tanstack/query-persist-client-core@5.102.2
## 5.102.1
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.102.1
- @tanstack/query-persist-client-core@5.102.1
## 5.102.0
### Patch Changes
- Updated dependencies [[`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/angular-query-experimental@5.102.0
- @tanstack/query-persist-client-core@5.102.0
## 5.101.4
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.101.4
- @tanstack/query-persist-client-core@5.101.4
## 5.101.3
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.101.3
- @tanstack/query-persist-client-core@5.101.3
## 5.101.2
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.101.2
- @tanstack/query-persist-client-core@5.101.2
## 5.101.1
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.101.1
- @tanstack/query-persist-client-core@5.101.1
## 5.101.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.101.0
- @tanstack/query-persist-client-core@5.101.0
## 5.100.14
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.14
- @tanstack/query-persist-client-core@5.100.14
## 5.100.13
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.13
- @tanstack/query-persist-client-core@5.100.13
## 5.100.12
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.12
- @tanstack/query-persist-client-core@5.100.12
## 5.100.11
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.11
- @tanstack/query-persist-client-core@5.100.11
## 5.100.10
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.10
- @tanstack/query-persist-client-core@5.100.10
## 5.100.9
### Patch Changes
- Updated dependencies [[`bf902df`](https://github.com/TanStack/query/commit/bf902df59dcc3196cbc4a379c43ee55200c75a0a)]:
- @tanstack/angular-query-experimental@5.100.9
- @tanstack/query-persist-client-core@5.100.9
## 5.100.8
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.8
- @tanstack/query-persist-client-core@5.100.8
## 5.100.7
### Patch Changes
- Updated dependencies [[`868577d`](https://github.com/TanStack/query/commit/868577d5daa6de7dc7698f8b41ad5cf225606d05)]:
- @tanstack/angular-query-experimental@5.100.7
- @tanstack/query-persist-client-core@5.100.7
## 5.100.6
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.6
- @tanstack/query-persist-client-core@5.100.6
## 5.100.5
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.5
- @tanstack/query-persist-client-core@5.100.5
## 5.100.4
### Patch Changes
- Updated dependencies [[`3d1a62e`](https://github.com/TanStack/query/commit/3d1a62e63bd864359e369bb21356fa80d043f2ba)]:
- @tanstack/angular-query-experimental@5.100.4
- @tanstack/query-persist-client-core@5.100.4
## 5.100.3
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.3
- @tanstack/query-persist-client-core@5.100.3
## 5.100.2
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.2
- @tanstack/query-persist-client-core@5.100.2
## 5.100.1
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.1
- @tanstack/query-persist-client-core@5.100.1
## 5.100.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.100.0
- @tanstack/query-persist-client-core@5.100.0
## 5.99.2
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.99.2
- @tanstack/query-persist-client-core@5.99.2
## 5.99.1
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.99.1
- @tanstack/query-persist-client-core@5.99.1
## 5.99.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.99.0
- @tanstack/query-persist-client-core@5.99.0
## 5.98.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.98.0
- @tanstack/query-persist-client-core@5.98.0
## 5.97.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.97.0
- @tanstack/query-persist-client-core@5.97.0
## 5.96.2
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.96.2
- @tanstack/query-persist-client-core@5.96.2
## 5.96.1
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.96.1
- @tanstack/query-persist-client-core@5.96.1
## 5.96.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.96.0
- @tanstack/query-persist-client-core@5.96.0
## 5.95.2
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.95.2
- @tanstack/query-persist-client-core@5.95.2
## 5.95.1
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.95.1
- @tanstack/query-persist-client-core@5.95.1
## 5.95.0
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.95.0
- @tanstack/query-persist-client-core@5.95.0
## 5.94.5
### 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/angular-query-experimental@5.94.5
- @tanstack/query-persist-client-core@5.94.5
## 5.94.4
### Patch Changes
- chore: fixed version ([#10064](https://github.com/TanStack/query/pull/10064))
- Updated dependencies [[`4c75210`](https://github.com/TanStack/query/commit/4c75210ce8235fe3d39b67e1029eff11278927cc)]:
- @tanstack/angular-query-experimental@5.94.4
- @tanstack/query-persist-client-core@5.94.4
## 5.62.32
### 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/angular-query-experimental@5.90.28
- @tanstack/query-persist-client-core@5.92.4
## 5.62.31
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.27
- @tanstack/query-persist-client-core@5.92.3
## 5.62.30
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.26
- @tanstack/query-persist-client-core@5.92.2
## 5.62.29
### Patch Changes
- Updated dependencies [[`e505568`](https://github.com/TanStack/query/commit/e505568f4d51c8281d38e9687091094b7d32a405)]:
- @tanstack/query-persist-client-core@5.92.1
## 5.62.28
### Patch Changes
- Updated dependencies [[`978fc52`](https://github.com/TanStack/query/commit/978fc52728a8b9eb33f0a82f4ddf42a95815bd7f)]:
- @tanstack/query-persist-client-core@5.92.0
## 5.62.27
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.24
- @tanstack/query-persist-client-core@5.91.19
## 5.62.26
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.23
- @tanstack/query-persist-client-core@5.91.18
## 5.62.25
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.22
- @tanstack/query-persist-client-core@5.91.17
## 5.62.24
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.21
- @tanstack/query-persist-client-core@5.91.16
## 5.62.23
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.20
- @tanstack/query-persist-client-core@5.91.15
## 5.62.22
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.19
- @tanstack/query-persist-client-core@5.91.14
## 5.62.21
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.18
- @tanstack/query-persist-client-core@5.91.13
## 5.62.20
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.17
- @tanstack/query-persist-client-core@5.91.12
## 5.62.19
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.16
- @tanstack/query-persist-client-core@5.91.11
## 5.62.18
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.15
- @tanstack/query-persist-client-core@5.91.10
## 5.62.17
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.12
- @tanstack/query-persist-client-core@5.91.9
## 5.62.16
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.11
- @tanstack/query-persist-client-core@5.91.8
## 5.62.15
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.10
- @tanstack/query-persist-client-core@5.91.7
## 5.62.14
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.9
- @tanstack/query-persist-client-core@5.91.6
## 5.62.13
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.8
- @tanstack/query-persist-client-core@5.91.5
## 5.62.12
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.5
- @tanstack/query-persist-client-core@5.91.4
## 5.62.11
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.4
- @tanstack/query-persist-client-core@5.91.3
## 5.62.10
### Patch Changes
- Updated dependencies []:
- @tanstack/angular-query-experimental@5.90.3
- @tanstack/query-persist-client-core@5.91.2
## 5.62.9
### Patch Changes
- Updated dependencies [[`846d53d`](https://github.com/TanStack/query/commit/846d53d98992d50606c40634efa43dea9965b787)]:
- @tanstack/query-persist-client-core@5.91.1
## 5.62.8
### Patch Changes
- Updated dependencies [[`5cd86c6`](https://github.com/TanStack/query/commit/5cd86c6ef1720b87b13e1ab70ee823616f1f029a)]:
- @tanstack/query-persist-client-core@5.91.0

View File

@@ -0,0 +1,31 @@
// @ts-check
import pluginJsdoc from 'eslint-plugin-jsdoc'
import rootConfig from './root.eslint.config.js'
export default [
...rootConfig,
pluginJsdoc.configs['flat/recommended-typescript'],
{
rules: {
'cspell/spellchecker': [
'warn',
{
cspell: {
ignoreRegExpList: ['\\ɵ.+'],
},
},
],
'jsdoc/require-hyphen-before-param-description': 1,
'jsdoc/sort-tags': 1,
'jsdoc/require-throws': 1,
'jsdoc/check-tag-names': [
'warn',
{
// Not compatible with Api Extractor @public
typed: false,
},
],
},
},
]

View File

@@ -0,0 +1,74 @@
{
"name": "@tanstack/angular-query-persist-client",
"private": true,
"version": "5.102.8",
"description": "Angular bindings to work with persisters in TanStack/angular-query",
"author": "Omer Gronich",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/query.git",
"directory": "packages/angular-query-persist-client"
},
"homepage": "https://tanstack.com/query",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"scripts": {
"clean": "premove ./build ./coverage ./dist-ts ./.cache/test-types",
"compile": "tsc --project tsconfig.json",
"test:eslint": "eslint --concurrency=auto ./src",
"test:types": "npm-run-all --serial test:types:*",
"test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts56 --tsBuildInfoFile .cache/test-types/ts56.tsbuildinfo",
"test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts57 --tsBuildInfoFile .cache/test-types/ts57.tsbuildinfo",
"test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts58 --tsBuildInfoFile .cache/test-types/ts58.tsbuildinfo",
"test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts59 --tsBuildInfoFile .cache/test-types/ts59.tsbuildinfo",
"test:types:tscurrent": "tsc --project tsconfig.json --outDir .cache/test-types/tscurrent --tsBuildInfoFile .cache/test-types/tscurrent.tsbuildinfo",
"test:types:ts70": "node ../../node_modules/typescript70/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts70 --tsBuildInfoFile .cache/test-types/ts70.tsbuildinfo",
"test:lib": "vitest",
"test:lib:dev": "pnpm run test:lib --watch",
"test:build": "publint --strict && attw --pack",
"build": "pnpm build:tsdown",
"build:tsdown": "tsdown --tsconfig tsconfig.prod.json"
},
"type": "module",
"types": "build/index.d.ts",
"module": "build/index.mjs",
"exports": {
".": {
"types": "./build/index.d.ts",
"default": "./build/index.mjs"
},
"./package.json": {
"default": "./package.json"
}
},
"sideEffects": false,
"files": [
"build",
"src",
"!src/__tests__"
],
"dependencies": {
"@tanstack/query-persist-client-core": "workspace:*"
},
"devDependencies": {
"@angular/animations": "^20.0.0",
"@angular/common": "^20.0.0",
"@angular/compiler": "^20.0.0",
"@angular/core": "^20.0.0",
"@angular/platform-browser": "^20.0.0",
"@tanstack/angular-query-experimental": "workspace:*",
"@tanstack/query-test-utils": "workspace:*",
"@testing-library/angular": "^18.0.0",
"@testing-library/dom": "^10.4.0",
"eslint-plugin-jsdoc": "^50.5.0",
"npm-run-all2": "^5.0.0"
},
"peerDependencies": {
"@angular/common": ">=16.0.0",
"@angular/core": ">=16.0.0",
"@tanstack/angular-query-experimental": "workspace:^"
}
}

View File

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

View File

@@ -0,0 +1,452 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
QueryClient,
injectQuery,
noop,
provideTanStackQuery,
} from '@tanstack/angular-query-experimental'
import { persistQueryClientSave } from '@tanstack/query-persist-client-core'
import {
Component,
effect,
provideZonelessChangeDetection,
} from '@angular/core'
import { render } from '@testing-library/angular'
import { queryKey, sleep } from '@tanstack/query-test-utils'
import { withPersistQueryClient } from '../with-persist-query-client'
import type {
PersistedClient,
Persister,
} from '@tanstack/query-persist-client-core'
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() {
await sleep(10)
throw error
},
removeClient,
},
]
}
describe('withPersistQueryClient', () => {
beforeEach(() => {
vi.useFakeTimers()
})
afterEach(() => {
vi.useRealTimers()
})
it('should restore cache from persister', async () => {
const key = queryKey()
const states: Array<{
status: string
fetchStatus: string
data: string | undefined
}> = []
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: key,
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
@Component({
template: `
<div>
<h1>{{ state.data() }}</h1>
<h2>fetchStatus: {{ state.fetchStatus() }}</h2>
</div>
`,
})
class Page {
state = injectQuery(() => ({
queryKey: key,
queryFn: () => sleep(10).then(() => 'fetched'),
}))
constructor() {
effect(() => {
states.push({
status: this.state.status(),
fetchStatus: this.state.fetchStatus(),
data: this.state.data(),
})
})
}
}
const rendered = await render(Page, {
providers: [
provideZonelessChangeDetection(),
provideTanStackQuery(
queryClient,
withPersistQueryClient({ persistOptions: { persister } }),
),
],
})
expect(rendered.getByText('fetchStatus: idle')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
rendered.fixture.detectChanges()
expect(rendered.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(11)
rendered.fixture.detectChanges()
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(states).toHaveLength(3)
expect(states[0]).toMatchObject({
status: 'pending',
fetchStatus: 'idle',
data: undefined,
})
expect(states[1]).toMatchObject({
status: 'success',
fetchStatus: 'fetching',
data: 'hydrated',
})
expect(states[2]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'fetched',
})
})
it.todo(
'(Once injectQueries is functional) verify that injectQueries transitions to an idle state',
)
it('should show initialData while restoring', async () => {
const key = queryKey()
const states: Array<{
status: string
fetchStatus: string
data: string | undefined
}> = []
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: key,
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
@Component({
template: `
<div>
<h1>{{ state.data() }}</h1>
<h2>fetchStatus: {{ state.fetchStatus() }}</h2>
</div>
`,
})
class Page {
state = injectQuery(() => ({
queryKey: key,
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,
}))
constructor() {
effect(() => {
states.push({
status: this.state.status(),
fetchStatus: this.state.fetchStatus(),
data: this.state.data(),
})
})
}
}
const rendered = await render(Page, {
providers: [
provideZonelessChangeDetection(),
provideTanStackQuery(
queryClient,
withPersistQueryClient({ persistOptions: { persister } }),
),
],
})
expect(rendered.getByText('initial')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
rendered.fixture.detectChanges()
expect(rendered.getByText('hydrated')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(11)
rendered.fixture.detectChanges()
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(states).toHaveLength(3)
expect(states[0]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'initial',
})
expect(states[1]).toMatchObject({
status: 'success',
fetchStatus: 'fetching',
data: 'hydrated',
})
expect(states[2]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'fetched',
})
})
it('should not refetch after restoring when data is fresh', async () => {
const key = queryKey()
const states: Array<{
status: string
fetchStatus: string
data: string | undefined
}> = []
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: key,
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
@Component({
template: `
<div>
<h1>data: {{ state.data() ?? 'null' }}</h1>
<h2>fetchStatus: {{ state.fetchStatus() }}</h2>
</div>
`,
})
class Page {
state = injectQuery(() => ({
queryKey: key,
queryFn: () =>
sleep(10).then(() => {
fetched = true
return 'fetched'
}),
staleTime: Infinity,
}))
constructor() {
effect(() => {
states.push({
status: this.state.status(),
fetchStatus: this.state.fetchStatus(),
data: this.state.data(),
})
})
}
}
const rendered = await render(Page, {
providers: [
provideZonelessChangeDetection(),
provideTanStackQuery(
queryClient,
withPersistQueryClient({ persistOptions: { persister } }),
),
],
})
expect(rendered.getByText('data: null')).toBeInTheDocument()
await vi.advanceTimersByTimeAsync(10)
rendered.fixture.detectChanges()
expect(rendered.getByText('data: hydrated')).toBeInTheDocument()
expect(states).toHaveLength(2)
expect(fetched).toBe(false)
expect(states[0]).toMatchObject({
status: 'pending',
fetchStatus: 'idle',
data: undefined,
})
expect(states[1]).toMatchObject({
status: 'success',
fetchStatus: 'idle',
data: 'hydrated',
})
})
it('should call onSuccess after successful restoring', async () => {
const key = queryKey()
const queryClient = new QueryClient()
void queryClient
.query({
queryKey: key,
queryFn: () => sleep(10).then(() => 'hydrated'),
})
.catch(noop)
await vi.advanceTimersByTimeAsync(10)
const persister = createMockPersister()
persistQueryClientSave({ queryClient, persister })
await vi.advanceTimersByTimeAsync(0)
queryClient.clear()
@Component({
template: `
<div>
<h1>{{ state.data() }}</h1>
<h2>fetchStatus: {{ state.fetchStatus() }}</h2>
</div>
`,
})
class Page {
state = injectQuery(() => ({
queryKey: key,
queryFn: () => sleep(10).then(() => 'fetched'),
}))
}
const onSuccess = vi.fn()
const rendered = await render(Page, {
providers: [
provideZonelessChangeDetection(),
provideTanStackQuery(
queryClient,
withPersistQueryClient({
persistOptions: { persister },
onSuccess,
}),
),
],
})
expect(onSuccess).toHaveBeenCalledTimes(0)
await vi.advanceTimersByTimeAsync(10)
rendered.fixture.detectChanges()
expect(rendered.getByText('hydrated')).toBeInTheDocument()
expect(onSuccess).toHaveBeenCalledTimes(1)
await vi.advanceTimersByTimeAsync(11)
rendered.fixture.detectChanges()
expect(rendered.getByText('fetched')).toBeInTheDocument()
})
it('should remove cache after non-successful restoring', async () => {
const key = queryKey()
const onErrorMock = vi
.spyOn(console, 'error')
.mockImplementation(() => undefined)
const queryClient = new QueryClient()
const removeClient = vi.fn()
const [error, persister] = createMockErrorPersister(removeClient)
const onSuccess = vi.fn()
const onError = vi.fn()
@Component({
template: `
<div>
<h1>{{ state.data() }}</h1>
<h2>fetchStatus: {{ state.fetchStatus() }}</h2>
</div>
`,
})
class Page {
state = injectQuery(() => ({
queryKey: key,
queryFn: () => sleep(10).then(() => 'fetched'),
}))
}
const rendered = await render(Page, {
providers: [
provideZonelessChangeDetection(),
provideTanStackQuery(
queryClient,
withPersistQueryClient({
persistOptions: { persister },
onSuccess,
onError,
}),
),
],
})
await vi.advanceTimersByTimeAsync(10)
rendered.fixture.detectChanges()
expect(removeClient).toHaveBeenCalledTimes(1)
expect(onSuccess).toHaveBeenCalledTimes(0)
expect(onError).toHaveBeenCalledTimes(1)
await vi.advanceTimersByTimeAsync(11)
rendered.fixture.detectChanges()
expect(rendered.getByText('fetched')).toBeInTheDocument()
expect(onErrorMock).toHaveBeenCalledTimes(1)
expect(onErrorMock).toHaveBeenNthCalledWith(1, error)
onErrorMock.mockRestore()
})
})

View File

@@ -0,0 +1,4 @@
// Re-export core
export * from '@tanstack/query-persist-client-core'
export * from './with-persist-query-client'

View File

@@ -0,0 +1,88 @@
import {
QueryClient,
provideIsRestoring,
queryFeature,
} from '@tanstack/angular-query-experimental'
import {
DestroyRef,
ENVIRONMENT_INITIALIZER,
PLATFORM_ID,
inject,
signal,
} from '@angular/core'
import { isPlatformBrowser } from '@angular/common'
import {
persistQueryClientRestore,
persistQueryClientSubscribe,
} from '@tanstack/query-persist-client-core'
import type { PersistQueryClientOptions as PersistQueryClientOptionsCore } from '@tanstack/query-persist-client-core'
import type { PersistQueryClientFeature } from '@tanstack/angular-query-experimental'
type PersistQueryClientOptions = {
persistOptions: Omit<PersistQueryClientOptionsCore, 'queryClient'>
onSuccess?: () => Promise<unknown> | unknown
onError?: () => Promise<unknown> | unknown
}
/**
* Enables persistence.
*
* **Example**
*
* ```ts
* const localStoragePersister = createAsyncStoragePersister({
* storage: window.localStorage,
* })
*
* export const appConfig: ApplicationConfig = {
* providers: [
* provideTanStackQuery(
* new QueryClient(),
* withPersistQueryClient({
* persistOptions: {
* persister: localStoragePersister,
* },
* onSuccess: () => console.log('Restoration completed successfully.'),
* })
* ),
* ],
* };
* ```
* @param persistQueryClientOptions - persistence options and optional onSuccess and onError callbacks which get called when the restoration process is complete.
* @returns A set of providers for use with `provideTanStackQuery`.
* @public
*/
export function withPersistQueryClient(
persistQueryClientOptions: PersistQueryClientOptions,
): PersistQueryClientFeature {
const isRestoring = signal(true)
const providers = [
provideIsRestoring(isRestoring.asReadonly()),
{
// Do not use provideEnvironmentInitializer while Angular < v19 is supported
provide: ENVIRONMENT_INITIALIZER,
multi: true,
useValue: () => {
if (!isPlatformBrowser(inject(PLATFORM_ID))) return
const destroyRef = inject(DestroyRef)
const queryClient = inject(QueryClient)
const { onSuccess, onError, persistOptions } = persistQueryClientOptions
const options = { queryClient, ...persistOptions }
persistQueryClientRestore(options)
.then(() => {
onSuccess?.()
})
.catch(() => {
onError?.()
})
.finally(() => {
isRestoring.set(false)
const cleanup = persistQueryClientSubscribe(options)
destroyRef.onDestroy(cleanup)
})
},
},
]
return queryFeature('PersistQueryClient', providers)
}

View File

@@ -0,0 +1,8 @@
import '@testing-library/jest-dom/vitest'
import { getTestBed } from '@angular/core/testing'
import {
BrowserTestingModule,
platformBrowserTesting,
} from '@angular/platform-browser/testing'
getTestBed().initTestEnvironment(BrowserTestingModule, platformBrowserTesting())

View File

@@ -0,0 +1,21 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist-ts",
"rootDir": ".",
"noFallthroughCasesInSwitch": true,
"useDefineForClassFields": false,
"target": "ES2022"
},
"include": [
"src",
"test-setup.ts",
"*.config.ts",
"*.config.js",
"package.json"
],
"references": [
{ "path": "../angular-query-experimental" },
{ "path": "../query-persist-client-core" }
]
}

View File

@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"incremental": false,
"composite": false,
"rootDir": "../../"
},
"include": ["src"],
"exclude": ["src/__tests__"]
}

View File

@@ -0,0 +1,14 @@
import { defineConfig } from 'tsdown'
export default defineConfig({
entry: ['src/index.ts'],
sourcemap: true,
clean: true,
format: ['esm'],
dts: true,
fixedExtension: false,
outDir: 'build',
outExtensions({ format }) {
return format === 'es' ? { js: '.mjs', dts: '.d.ts' } : { js: '.js' }
},
})

View File

@@ -0,0 +1,33 @@
import { defineConfig } from 'vitest/config'
import packageJson from './package.json'
export default defineConfig({
// 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: './src',
watch: false,
environment: 'jsdom',
setupFiles: ['test-setup.ts'],
coverage: {
enabled: !!process.env.CI,
provider: 'istanbul',
include: ['src/**/*'],
exclude: ['src/__tests__/**'],
},
typecheck: { enabled: true },
globals: true,
restoreMocks: true,
},
})