Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,31 @@
"to": "framework/vue/plugins/createPersister"
}
]
},
{
"label": "preact",
"children": [
{
"label": "persistQueryClient",
"to": "framework/preact/plugins/persistQueryClient"
},
{
"label": "createSyncStoragePersister",
"to": "framework/preact/plugins/createSyncStoragePersister"
},
{
"label": "createAsyncStoragePersister",
"to": "framework/preact/plugins/createAsyncStoragePersister"
},
{
"label": "broadcastQueryClient (Experimental)",
"to": "framework/preact/plugins/broadcastQueryClient"
},
{
"label": "createPersister (Experimental)",
"to": "framework/preact/plugins/createPersister"
}
]
}
]
}
Expand Down
6 changes: 6 additions & 0 deletions docs/framework/preact/plugins/createAsyncStoragePersister.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: createAsyncStoragePersister
title: createAsyncStoragePersister
ref: docs/framework/react/plugins/createAsyncStoragePersister.md
replace: { 'react-query': 'preact-query' }
---
6 changes: 6 additions & 0 deletions docs/framework/preact/plugins/createPersister.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: createPersister
title: experimental_createPersister
ref: docs/framework/react/plugins/createPersister.md
replace: { 'react-query': 'preact-query' }
---
6 changes: 6 additions & 0 deletions docs/framework/preact/plugins/createSyncStoragePersister.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
id: createSyncStoragePersister
title: createSyncStoragePersister
ref: docs/framework/react/plugins/createSyncStoragePersister.md
replace: { 'react-query': 'preact-query' }
---
38 changes: 38 additions & 0 deletions packages/preact-query-persist-client/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// @ts-check
// @ts-ignore: no types for eslint-config-preact
import preact from 'eslint-config-preact'
// eslint-config-preact uses typescript-eslint under the hood
import tseslint from 'typescript-eslint'

import rootConfig from './root.eslint.config.js'

export default [
...rootConfig,
...preact,
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: true,
},
},
plugins: {
'typescript-eslint': tseslint.plugin,
},
rules: {
// Disable base rule to prevent overload false positives
'no-redeclare': 'off',
'no-duplicate-imports': 'off',
'no-unused-vars': 'off',
'import/order': 'off',
'sort-imports': 'off',
'no-import-assign': 'off',
// TS-aware version handles overloads correctly
'@typescript-eslint/no-redeclare': 'error',
'@typescript-eslint/array-type': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'@typescript-eslint/no-unnecessary-condition': 'off',
},
},
]
77 changes: 77 additions & 0 deletions packages/preact-query-persist-client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"name": "@tanstack/preact-query-persist-client",
"version": "5.91.0",
"description": "Preact bindings to work with persisters in TanStack/preact-query",
"author": "tannerlinsley",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/query.git",
"directory": "packages/preact-query-persist-client"
},
"homepage": "https://tanstack.com/query",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"scripts": {
"clean": "premove ./build ./coverage ./dist-ts",
"compile": "tsc --build",
"test:eslint": "eslint --concurrency=auto ./src",
"test:types": "npm-run-all --serial test:types:*",
"test:types:ts50": "node ../../node_modules/typescript50/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts51": "node ../../node_modules/typescript51/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts52": "node ../../node_modules/typescript52/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --build tsconfig.legacy.json",
"test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --build tsconfig.legacy.json",
"test:types:tscurrent": "tsc --build",
"test:lib": "vitest --retry=3",
"test:lib:dev": "pnpm run test:lib --watch",
"test:build": "publint --strict && attw --pack",
"build": "tsup --tsconfig tsconfig.prod.json"
},
"type": "module",
"types": "build/legacy/index.d.ts",
"main": "build/legacy/index.cjs",
"module": "build/legacy/index.js",
"exports": {
".": {
"@tanstack/custom-condition": "./src/index.ts",
"import": {
"types": "./build/modern/index.d.ts",
"default": "./build/modern/index.js"
},
"require": {
"types": "./build/modern/index.d.cts",
"default": "./build/modern/index.cjs"
}
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"build",
"src",
"!src/__tests__"
],
"dependencies": {
"@tanstack/query-persist-client-core": "workspace:*"
},
"devDependencies": {
"@preact/preset-vite": "^2.10.2",
"@tanstack/preact-query": "workspace:*",
"@tanstack/query-test-utils": "workspace:*",
"@testing-library/preact": "^3.2.4",
"eslint-config-preact": "^2.0.0",
"npm-run-all2": "^5.0.0",
"preact": "^10.28.0",
"typescript-eslint": "^8.54.0"
},
"peerDependencies": {
"@tanstack/preact-query": "workspace:^",
"preact": "^10.0.0"
}
}
1 change: 1 addition & 0 deletions packages/preact-query-persist-client/root.eslint.config.js
1 change: 1 addition & 0 deletions packages/preact-query-persist-client/root.tsup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useEffect, useRef, useState } from 'preact/hooks'
import type { VNode } from 'preact'
Comment on lines +1 to +2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix import order: type import from preact should follow @tanstack/* imports.

ESLint reports that the preact type import on Line 2 should occur after the @tanstack/preact-query import.

🔧 Proposed fix
 import { useEffect, useRef, useState } from 'preact/hooks'
-import type { VNode } from 'preact'
 
 import {
   persistQueryClientRestore,
   persistQueryClientSubscribe,
 } from '@tanstack/query-persist-client-core'
 import { IsRestoringProvider, QueryClientProvider } from '@tanstack/preact-query'
 import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
 import type { OmitKeyof, QueryClientProviderProps } from '@tanstack/preact-query'
+import type { VNode } from 'preact'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { useEffect, useRef, useState } from 'preact/hooks'
import type { VNode } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks'
import {
persistQueryClientRestore,
persistQueryClientSubscribe,
} from '@tanstack/query-persist-client-core'
import { IsRestoringProvider, QueryClientProvider } from '@tanstack/preact-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type { OmitKeyof, QueryClientProviderProps } from '@tanstack/preact-query'
import type { VNode } from 'preact'
🧰 Tools
🪛 ESLint

[error] 2-2: preact type import should occur after import of @tanstack/preact-query

(import/order)

🤖 Prompt for AI Agents
In `@packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx`
around lines 1 - 2, The import order is incorrect: move the type import "import
type { VNode } from 'preact'" so it appears after the package imports from
"@tanstack/*" (specifically after any import from "@tanstack/preact-query") to
satisfy ESLint ordering; update the top of PersistQueryClientProvider.tsx so
non-type `@tanstack` imports come first and the "VNode" type import follows them.


import {
persistQueryClientRestore,
persistQueryClientSubscribe,
} from '@tanstack/query-persist-client-core'
import { IsRestoringProvider, QueryClientProvider } from '@tanstack/preact-query'
import type { PersistQueryClientOptions } from '@tanstack/query-persist-client-core'
import type { OmitKeyof, QueryClientProviderProps } from '@tanstack/preact-query'

export type PersistQueryClientProviderProps = QueryClientProviderProps & {
persistOptions: OmitKeyof<PersistQueryClientOptions, 'queryClient'>
onSuccess?: () => Promise<unknown> | unknown
onError?: () => Promise<unknown> | unknown
}

export const PersistQueryClientProvider = ({
children,
persistOptions,
onSuccess,
onError,
...props
}: PersistQueryClientProviderProps): VNode => {
const [isRestoring, setIsRestoring] = useState(true)
const refs = useRef({ persistOptions, onSuccess, onError })
const didRestore = useRef(false)

useEffect(() => {
refs.current = { persistOptions, onSuccess, onError }
})

useEffect(() => {
const options = {
...refs.current.persistOptions,
queryClient: props.client,
}
if (!didRestore.current) {
didRestore.current = true
persistQueryClientRestore(options)
.then(() => refs.current.onSuccess?.())
.catch(() => refs.current.onError?.())
.finally(() => {
setIsRestoring(false)
})
}
return isRestoring ? undefined : persistQueryClientSubscribe(options)
}, [props.client, isRestoring])
Comment on lines +33 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd . && find . -type f -name "*PersistQueryClientProvider*" | head -20

Repository: TanStack/query

Length of output: 617


🏁 Script executed:

ls -la packages/

Repository: TanStack/query

Length of output: 1931


🏁 Script executed:

find . -name "PersistQueryClientProvider.tsx" -type f

Repository: TanStack/query

Length of output: 277


🏁 Script executed:

git ls-files | grep "PersistQueryClientProvider"

Repository: TanStack/query

Length of output: 603


🏁 Script executed:

git ls-files "**/*PersistQueryClientProvider*"

Repository: TanStack/query

Length of output: 603


🏁 Script executed:

find packages -type f -name "*.tsx" | grep -i provider

Repository: TanStack/query

Length of output: 855


🏁 Script executed:

find . -type f -name "*.tsx" -o -name "*.ts" | xargs grep -l "PersistQueryClientProvider" 2>/dev/null

Repository: TanStack/query

Length of output: 953


🏁 Script executed:

tree -L 3 -d 2>/dev/null || find . -maxdepth 3 -type d | head -30

Repository: TanStack/query

Length of output: 6546


🏁 Script executed:

pwd && ls -la

Repository: TanStack/query

Length of output: 2437


🏁 Script executed:

find . -path "*/preact-query-persist-client/*" -type f

Repository: TanStack/query

Length of output: 623


🏁 Script executed:

rg "didRestore.current" -t tsx -t ts

Repository: TanStack/query

Length of output: 85


🏁 Script executed:

git ls-files | wc -l && git ls-files | grep -i provider

Repository: TanStack/query

Length of output: 2578


🏁 Script executed:

git ls-files | grep "\.tsx$"

Repository: TanStack/query

Length of output: 17194


🏁 Script executed:

git log --oneline --all | head -5

Repository: TanStack/query

Length of output: 340


🏁 Script executed:

git ls-files --full-name | sort

Repository: TanStack/query

Length of output: 50371


🏁 Script executed:

git ls-files --full-name | grep -i persist

Repository: TanStack/query

Length of output: 9283


🏁 Script executed:

find . -type f -name "*.tsx" | wc -l

Repository: TanStack/query

Length of output: 61


🏁 Script executed:

rg "useEffect" --type tsx --type ts | grep -i "persistquery\|restore" -A 5

Repository: TanStack/query

Length of output: 85


🏁 Script executed:

rg "persistQueryClientRestore"

Repository: TanStack/query

Length of output: 2830


🏁 Script executed:

git ls-files | head -100

Repository: TanStack/query

Length of output: 4804


🏁 Script executed:

cat /dev/null && pwd

Repository: TanStack/query

Length of output: 76


🏁 Script executed:

git remote -v 2>/dev/null || echo "No git remote found"

Repository: TanStack/query

Length of output: 174


🏁 Script executed:

git rev-parse --show-toplevel 2>/dev/null || echo "Not a git repo"

Repository: TanStack/query

Length of output: 76


🏁 Script executed:

test -f packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx && echo "File exists" || echo "File not found"

Repository: TanStack/query

Length of output: 69


🏁 Script executed:

find . -iname "*react*query*persist*" -o -iname "*preact*query*persist*" 2>/dev/null

Repository: TanStack/query

Length of output: 134


🌐 Web query:

TanStack query persist client PersistQueryClientProvider restore unmount

💡 Result:

In TanStack Query (v5), restoration/persistence works like this:

  • persistQueryClient({ ... }) does two things: (1) async restore of the persisted cache, then (2) subscribes to cache changes and returns an unsubscribe function. If you call it outside React, you can’t reliably unsubscribe and you can also get restore-vs-fetch race conditions. [1]
  • PersistQueryClientProvider exists specifically to solve those lifecycle issues: it subscribes/unsubscribes with the React component lifecycle, and it also prevents queries from starting network fetching while restore is in progress (queries render, but are held in fetchingState: 'idle' until restore completes). [1]
  • onSuccess is called when the initial restore finishes; if it returns a Promise, the provider will keep “restoring” true until that Promise resolves (useful for resumePausedMutations). [1]

What happens on unmount/remount?

  • If PersistQueryClientProvider unmounts, it will unsubscribe from persistence syncing (that’s the point of using it). [1]
  • If it mounts again, it will run the restore again and re-subscribe. (So in most apps, you want this provider mounted once at the app root.)

Manual pattern (if you’re not using PersistQueryClientProvider)

Use explicit restore + subscribe in an effect, and cleanup on unmount:

import { useEffect } from 'react'
import {
  persistQueryClientRestore,
  persistQueryClientSubscribe,
} from '@tanstack/react-query-persist-client'

function usePersistedQueryClient({ queryClient, persister, buster, maxAge }: any) {
  useEffect(() => {
    let unsub: (() => void) | undefined

    ;(async () => {
      await persistQueryClientRestore({ queryClient, persister, buster, maxAge })
      unsub = persistQueryClientSubscribe({ queryClient, persister, buster })
    })()

    return () => {
      unsub?.()
    }
  }, [queryClient, persister, buster, maxAge])
}

This mirrors what the provider is designed to manage for you. [1]

Source
[1] TanStack Query docs: persistQueryClient / PersistQueryClientProvider lifecycle + restoring behavior (tanstack.dev)

Citations:


🏁 Script executed:

find . -type f \( -name "*.tsx" -o -name "*.ts" \) 2>/dev/null

Repository: TanStack/query

Length of output: 50371


🏁 Script executed:

file $(git ls-files | head -1) 2>/dev/null

Repository: TanStack/query

Length of output: 42


🏁 Script executed:

git diff-tree --no-commit-id --name-only -r HEAD 2>/dev/null | head -20

Repository: TanStack/query

Length of output: 40


🌐 Web query:

TanStack query persist client PersistQueryClientProvider.tsx github

💡 Result:

The source for PersistQueryClientProvider lives in the TanStack Query monorepo here (GitHub):

https://github.com/TanStack/query/blob/main/packages/react-query-persist-client/src/PersistQueryClientProvider.tsx

This component is part of @tanstack/react-query-persist-client and is the recommended React wrapper around persistQueryClient so restore/subscribe/unsubscribe happens in the React lifecycle and queries don’t race-fetch while the cache is restoring. [1][2]

Sources: [1], [2]


🏁 Script executed:

git ls-files packages/ 2>/dev/null || echo "Checking without git"; ls -la packages/ 2>/dev/null || echo "No packages dir"

Repository: TanStack/query

Length of output: 44438


🏁 Script executed:

rg "useEffect.*didRestore"

Repository: TanStack/query

Length of output: 40


🌐 Web query:

TanStack "PersistQueryClientProvider" preact implementation

💡 Result:

There’s no special TanStack Query “preact” build for PersistQueryClientProvider—you use the normal React packages, and run them through Preact’s React-compat layer (preact/compat).

1) Make react resolve to preact/compat

One simple approach is a package alias so anything importing react gets @preact/compat instead (works in Node tooling too): (bret.io)

// package.json
{
  "dependencies": {
    "preact": "^10.0.0",
    "@tanstack/react-query": "^5.0.0",
    "@tanstack/react-query-persist-client": "^5.0.0",
    "@tanstack/query-sync-storage-persister": "^5.0.0",

    "react": "npm:`@preact/compat`@^18.0.0"
  }
}

(Alternatively, you can do a bundler alias to map react -> preact/compat.)

2) Use PersistQueryClientProvider exactly like in React

PersistQueryClientProvider is provided by @tanstack/react-query-persist-client and is designed to manage restore + subscribe/unsubscribe via the component lifecycle. (tanstack.dev)

localStorage (sync) example (Preact entry)

// main.tsx (or similar)
import { render } from 'preact'
import { QueryClient } from '@tanstack/react-query'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'

import { App } from './app'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      gcTime: 1000 * 60 * 60 * 24, // 24h
    },
  },
})

const persister = createSyncStoragePersister({
  storage: typeof window !== 'undefined' ? window.localStorage : undefined,
})

render(
  <PersistQueryClientProvider
    client={queryClient}
    persistOptions={{ persister }}
  >
    <App />
  </PersistQueryClientProvider>,
  document.getElementById('app')!,
)

createSyncStoragePersister is the official helper for localStorage/sessionStorage. (tanstack.com)

Citations:


🏁 Script executed:

git config --local remote.origin.url 2>/dev/null || git config --global user.name 2>/dev/null || echo "Git config unavailable"

Repository: TanStack/query

Length of output: 95


🏁 Script executed:

rg "\.finally\(\(" -t tsx -A 2

Repository: TanStack/query

Length of output: 85


🌐 Web query:

TanStack query repository persist client PersistQueryClientProvider

💡 Result:

PersistQueryClientProvider lives in the TanStack Query monorepo under packages/react-query-persist-client (source: packages/react-query-persist-client/src/PersistQueryClientProvider.tsx). [3]

What it does

Use PersistQueryClientProvider (from @tanstack/react-query-persist-client) instead of QueryClientProvider so that:

  • the persisted cache is restored asynchronously before queries start fetching (avoids restore/fetch race conditions)
  • the persist “subscription” is correctly subscribed/unsubscribed with the React lifecycle. [1]

Install (typical)

  • @tanstack/react-query-persist-client
  • a persister, e.g. @tanstack/query-sync-storage-persister (web localStorage) or @tanstack/query-async-storage-persister (AsyncStorage / async). [1][2]

Minimal example (web localStorage)

import { QueryClient } from '@tanstack/react-query'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      gcTime: 1000 * 60 * 60 * 24, // important for persistence/hydration
    },
  },
})

const persister = createSyncStoragePersister({
  storage: window.localStorage,
})

export function Root() {
  return (
    <PersistQueryClientProvider
      client={queryClient}
      persistOptions={{ persister }}
      // optional:
      // onSuccess={() => queryClient.resumePausedMutations()}
    >
      <App />
    </PersistQueryClientProvider>
  )
}

PersistQueryClientProvider props:

  • everything QueryClientProvider supports, plus:
    • persistOptions (same options as persistQueryClient minus the queryClient)
    • onSuccess / onError callbacks for the initial restore. [1]

If you tell me your target (web vs React Native) and TanStack Query major version (v4 vs v5), I can tailor the exact packages/imports.


🌐 Web query:

site:github.com "persistQueryClientRestore" preact

💡 Result:

Your GitHub query (site:github.com "persistQueryClientRestore" preact) doesn’t surface any Preact-specific usage/examples of persistQueryClientRestore. Instead, persistQueryClientRestore is a TanStack Query persistence utility (it restores/hydrates a previously persisted cache into a QueryClient) and is not inherently tied to React/Preact at the function level. [1]

If you’re looking for “Preact + TanStack Query” support, TanStack Query has an open “Feat: Preact Adapter” PR (#9935), which is the most directly relevant GitHub hit connecting Preact to the TanStack Query ecosystem. [2]

Sources: [1], [2]


🏁 Script executed:

find . -type f 2>/dev/null | wc -l && find . -type f 2>/dev/null | head -50

Repository: TanStack/query

Length of output: 3459


🏁 Script executed:

wc -l packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx

Repository: TanStack/query

Length of output: 132


🏁 Script executed:

cat packages/react-query-persist-client/src/PersistQueryClientProvider.tsx

Repository: TanStack/query

Length of output: 1803


🏁 Script executed:

# Let's check for any unmount handling or cleanup in both files
rg "return.*=>|useEffect.*cleanup" packages/react-query-persist-client/src/PersistQueryClientProvider.tsx packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx

Repository: TanStack/query

Length of output: 40


🏁 Script executed:

grep -A 10 "unmount\|cleanup\|cancel" packages/react-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx

Repository: TanStack/query

Length of output: 40


Guard setIsRestoring(false) against state updates after unmount.

The persistQueryClientRestore promise chain executes its finally block and calls setIsRestoring(false) even if the component unmounts before the restore settles. This causes a React "Cannot update an unmounted component" warning. Add a mounted flag to the cleanup function:

♻️ Suggested fix
   React.useEffect(() => {
+    let isMounted = true
     const options = {
       ...refs.current.persistOptions,
       queryClient: props.client,
     }
     if (!didRestore.current) {
       didRestore.current = true
       persistQueryClientRestore(options)
         .then(() => refs.current.onSuccess?.())
         .catch(() => refs.current.onError?.())
         .finally(() => {
+          if (isMounted) {
             setIsRestoring(false)
+          }
         })
     }
-    return isRestoring ? undefined : persistQueryClientSubscribe(options)
+    return () => {
+      isMounted = false
+      return isRestoring ? undefined : persistQueryClientSubscribe(options)
+    }
   }, [props.client, isRestoring])
🤖 Prompt for AI Agents
In `@packages/preact-query-persist-client/src/PersistQueryClientProvider.tsx`
around lines 33 - 48, The finally handler calls setIsRestoring(false) even after
unmount, causing state updates on unmounted component; inside the useEffect that
references didRestore, refs.current, persistQueryClientRestore, isRestoring and
persistQueryClientSubscribe, add a mounted flag (e.g., let mounted = true) and
set mounted = false in the cleanup, then only call setIsRestoring(false) in the
persistQueryClientRestore promise chain if mounted is true; ensure the cleanup
still returns persistQueryClientSubscribe(options) when not restoring and the
mounted flag prevents setIsRestoring from running after unmount.


return (
<QueryClientProvider {...props}>
<IsRestoringProvider value={isRestoring}>{children}</IsRestoringProvider>
</QueryClientProvider>
)
}
4 changes: 4 additions & 0 deletions packages/preact-query-persist-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Re-export core
export * from '@tanstack/query-persist-client-core'

export * from './PersistQueryClientProvider'
14 changes: 14 additions & 0 deletions packages/preact-query-persist-client/test-setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import '@testing-library/jest-dom/vitest'
import { act, cleanup as cleanupRTL } from '@testing-library/preact'
import { afterEach } from 'vitest'
import { notifyManager } from '@tanstack/preact-query'

// https://testing-library.com/docs/preact-testing-library/api#cleanup
afterEach(() => {
cleanupRTL()
})

// Wrap notifications with act to make sure Preact knows about Query updates
notifyManager.setNotifyFunction((fn) => {
act(fn)
})
14 changes: 14 additions & 0 deletions packages/preact-query-persist-client/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist-ts",
"rootDir": ".",
"jsx": "react-jsx",
"jsxImportSource": "preact"
},
"include": ["src", "test-setup.ts", "*.config.*", "package.json"],
"references": [
{ "path": "../query-persist-client-core" },
{ "path": "../preact-query" }
]
}
14 changes: 14 additions & 0 deletions packages/preact-query-persist-client/tsconfig.legacy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "preact",
"outDir": "./dist-ts/legacy"
},
"include": ["src"],
"exclude": ["src/__tests__"],
"references": [
{ "path": "../query-persist-client-core" },
{ "path": "../preact-query" }
]
}
8 changes: 8 additions & 0 deletions packages/preact-query-persist-client/tsconfig.prod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"incremental": false,
"composite": false,
"rootDir": "../../"
}
}
7 changes: 7 additions & 0 deletions packages/preact-query-persist-client/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'tsup'
import { legacyConfig, modernConfig } from './root.tsup.config.js'

export default defineConfig([
modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),
legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),
])
35 changes: 35 additions & 0 deletions packages/preact-query-persist-client/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import preact from '@preact/preset-vite'
import { defineConfig } from 'vitest/config'
import type { UserConfig as ViteUserConfig } from 'vite'

import packageJson from './package.json'
Comment on lines +3 to +5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix import order: ./package.json should be imported before the type import from vite.

ESLint flags this as an import/order violation.

Proposed fix
-import { defineConfig } from 'vitest/config'
-import type { UserConfig as ViteUserConfig } from 'vite'
-
-import packageJson from './package.json'
+import { defineConfig } from 'vitest/config'
+import packageJson from './package.json'
+import type { UserConfig as ViteUserConfig } from 'vite'
🧰 Tools
🪛 ESLint

[error] 5-5: ./package.json import should occur before type import of vite

(import/order)

🤖 Prompt for AI Agents
In `@packages/preact-query-persist-client/vite.config.ts` around lines 3 - 5,
Reorder the imports so the package JSON import appears before the Vite type
import to satisfy import/order; move "import packageJson from './package.json'"
above "import type { UserConfig as ViteUserConfig } from 'vite'"; ensure symbols
packageJson and ViteUserConfig remain unchanged and that no other code is
affected by the swap.


export default defineConfig({
plugins: [preact() as ViteUserConfig['plugins']],
// 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: true,
provider: 'istanbul',
include: ['src/**/*'],
exclude: ['src/__tests__/**'],
},
typecheck: { enabled: true },
restoreMocks: true,
},
})
31 changes: 31 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.