@tanstack/query-persist-client-core 5.104.5 → 5.105.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/build/legacy/createPersister.cjs +18 -4
  2. package/build/legacy/createPersister.cjs.map +1 -1
  3. package/build/legacy/createPersister.d.cts +1 -3
  4. package/build/legacy/createPersister.d.cts.map +1 -1
  5. package/build/legacy/createPersister.d.ts +1 -3
  6. package/build/legacy/createPersister.d.ts.map +1 -1
  7. package/build/legacy/createPersister.js +18 -4
  8. package/build/legacy/createPersister.js.map +1 -1
  9. package/build/legacy/index.cjs +1 -2
  10. package/build/legacy/index.js +1 -2
  11. package/build/legacy/persist.cjs +11 -4
  12. package/build/legacy/persist.cjs.map +1 -1
  13. package/build/legacy/persist.d.cts +0 -2
  14. package/build/legacy/persist.d.cts.map +1 -1
  15. package/build/legacy/persist.d.ts +0 -2
  16. package/build/legacy/persist.d.ts.map +1 -1
  17. package/build/legacy/persist.js +11 -4
  18. package/build/legacy/persist.js.map +1 -1
  19. package/build/legacy/retryStrategies.cjs +1 -2
  20. package/build/legacy/retryStrategies.d.cts +0 -2
  21. package/build/legacy/retryStrategies.d.cts.map +1 -1
  22. package/build/legacy/retryStrategies.d.ts +0 -2
  23. package/build/legacy/retryStrategies.d.ts.map +1 -1
  24. package/build/legacy/retryStrategies.js +1 -2
  25. package/build/modern/createPersister.cjs +18 -4
  26. package/build/modern/createPersister.cjs.map +1 -1
  27. package/build/modern/createPersister.d.cts +1 -3
  28. package/build/modern/createPersister.d.cts.map +1 -1
  29. package/build/modern/createPersister.d.ts +1 -3
  30. package/build/modern/createPersister.d.ts.map +1 -1
  31. package/build/modern/createPersister.js +18 -4
  32. package/build/modern/createPersister.js.map +1 -1
  33. package/build/modern/index.cjs +1 -2
  34. package/build/modern/index.js +1 -2
  35. package/build/modern/persist.cjs +11 -4
  36. package/build/modern/persist.cjs.map +1 -1
  37. package/build/modern/persist.d.cts +0 -2
  38. package/build/modern/persist.d.cts.map +1 -1
  39. package/build/modern/persist.d.ts +0 -2
  40. package/build/modern/persist.d.ts.map +1 -1
  41. package/build/modern/persist.js +11 -4
  42. package/build/modern/persist.js.map +1 -1
  43. package/build/modern/retryStrategies.cjs +1 -2
  44. package/build/modern/retryStrategies.d.cts +0 -2
  45. package/build/modern/retryStrategies.d.cts.map +1 -1
  46. package/build/modern/retryStrategies.d.ts +0 -2
  47. package/build/modern/retryStrategies.d.ts.map +1 -1
  48. package/build/modern/retryStrategies.js +1 -2
  49. package/package.json +2 -2
  50. package/src/createPersister.ts +42 -3
  51. package/src/persist.ts +14 -3
@@ -1 +1 @@
1
- {"version":3,"file":"persist.cjs","names":["dehydrate"],"sources":["../../src/persist.ts"],"sourcesContent":["import { dehydrate, hydrate } from '@tanstack/query-core'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n NotifyEventType,\n QueryClient,\n} from '@tanstack/query-core'\n\n/**\n * A value, or a promise-like that resolves to it.\n */\nexport type Promisable<T> = T | PromiseLike<T>\n\n/**\n * Saves, restores, and removes a {@link PersistedClient} in a storage.\n */\nexport interface Persister {\n /**\n * Saves the persisted client to the storage.\n */\n persistClient: (persistClient: PersistedClient) => Promisable<void>\n /**\n * Reads the persisted client from the storage, or `undefined` if nothing was saved.\n */\n restoreClient: () => Promisable<PersistedClient | undefined>\n /**\n * Removes the persisted client from the storage.\n */\n removeClient: () => Promisable<void>\n}\n\n/**\n * The dehydrated state of a `QueryClient` as it is persisted, with the time it was saved and its\n * `buster`.\n */\nexport interface PersistedClient {\n /**\n * When the client was saved, in milliseconds since the epoch. Compared with `maxAge` on restore.\n */\n timestamp: number\n /**\n * The `buster` the client was saved with. A persisted client with a different `buster` is\n * discarded.\n */\n buster: string\n /**\n * The dehydrated cache of the `QueryClient`.\n */\n clientState: DehydratedState\n}\n\n/**\n * The options shared by restoring and saving a persisted `QueryClient`.\n */\nexport interface PersistQueryClientRootOptions {\n /** The QueryClient to persist */\n queryClient: QueryClient\n /**\n * The Persister interface for storing and restoring the cache\n * to/from a persisted location\n */\n persister: Persister\n /**\n * A unique string that can be used to forcefully\n * invalidate existing caches if they do not share the same buster string\n */\n buster?: string\n}\n\n/**\n * Options for restoring a persisted `QueryClient` with {@link persistQueryClientRestore}.\n */\nexport interface PersistedQueryClientRestoreOptions extends PersistQueryClientRootOptions {\n /**\n * The max-allowed age of the cache in milliseconds.\n * If a persisted cache is found that is older than this\n * time, it will be discarded\n */\n maxAge?: number\n /** The options passed to the hydrate function */\n hydrateOptions?: HydrateOptions\n}\n\n/**\n * Options for saving a `QueryClient` with {@link persistQueryClientSave}.\n */\nexport interface PersistedQueryClientSaveOptions extends PersistQueryClientRootOptions {\n /** The options passed to the dehydrate function */\n dehydrateOptions?: DehydrateOptions\n}\n\n/**\n * Options for {@link persistQueryClient}, which both restores and saves a `QueryClient`.\n */\nexport interface PersistQueryClientOptions\n extends\n PersistedQueryClientRestoreOptions,\n PersistedQueryClientSaveOptions,\n PersistQueryClientRootOptions {}\n\nconst cacheEventTypes: Array<NotifyEventType> = ['added', 'removed', 'updated']\n\n/**\n * Checks if emitted event is about cache change and not about observers.\n * Useful for persist, where we only want to trigger save when cache is changed.\n * @param eventType - The type of the emitted event.\n * @returns `true` if the event is `'added'`, `'removed'`, or `'updated'`.\n */\nfunction isCacheEventType(eventType: NotifyEventType) {\n return cacheEventTypes.includes(eventType)\n}\n\n/**\n * Restores persisted data to the QueryCache.\n * - data obtained from persister.restoreClient.\n * - data is hydrated using hydrateOptions.\n * If data is expired, busted, empty, or throws, it runs persister.removeClient.\n * @param options - The `queryClient` to restore into, the `persister`, and the `maxAge`, `buster`,\n * and `hydrateOptions` that decide whether and how the persisted data is restored.\n * @returns A promise that resolves once the data is restored or removed. If restoring throws, it\n * attempts to remove the persisted data and then rejects with the restore error, or with the removal\n * error if the removal fails too.\n */\nexport async function persistQueryClientRestore({\n queryClient,\n persister,\n maxAge = 1000 * 60 * 60 * 24,\n buster = '',\n hydrateOptions,\n}: PersistedQueryClientRestoreOptions) {\n try {\n const persistedClient = await persister.restoreClient()\n\n if (persistedClient) {\n if (persistedClient.timestamp) {\n const expired = Date.now() - persistedClient.timestamp > maxAge\n const busted = persistedClient.buster !== buster\n if (expired || busted) {\n return persister.removeClient()\n } else {\n hydrate(queryClient, persistedClient.clientState, hydrateOptions)\n }\n } else {\n return persister.removeClient()\n }\n }\n } catch (err) {\n if (process.env.NODE_ENV !== 'production') {\n console.error(err)\n console.warn(\n 'Encountered an error attempting to restore client cache from persisted location. As a precaution, the persisted cache will be discarded.',\n )\n }\n\n await persister.removeClient()\n\n throw err\n }\n}\n\n/**\n * Persists data from the QueryCache.\n * - data dehydrated using dehydrateOptions.\n * - data is persisted using persister.persistClient.\n * @param options - The `queryClient` to persist, the `persister`, the `buster`, and the\n * `dehydrateOptions`.\n */\nexport async function persistQueryClientSave({\n queryClient,\n persister,\n buster = '',\n dehydrateOptions,\n}: PersistedQueryClientSaveOptions) {\n const persistClient: PersistedClient = {\n buster,\n timestamp: Date.now(),\n clientState: dehydrate(queryClient, dehydrateOptions),\n }\n\n await persister.persistClient(persistClient)\n}\n\n/**\n * Subscribe to QueryCache and MutationCache updates (for persisting).\n * @param props - The `queryClient` to monitor, the `persister`, the `buster`, and the\n * `dehydrateOptions` used for each save.\n * @returns an unsubscribe function (to discontinue monitoring)\n */\nexport function persistQueryClientSubscribe(\n props: PersistedQueryClientSaveOptions,\n) {\n const unsubscribeQueryCache = props.queryClient\n .getQueryCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n persistQueryClientSave(props)\n }\n })\n\n const unsubscribeMutationCache = props.queryClient\n .getMutationCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n persistQueryClientSave(props)\n }\n })\n\n return () => {\n unsubscribeQueryCache()\n unsubscribeMutationCache()\n }\n}\n\n/**\n * Restores persisted data to QueryCache and persists further changes.\n * @param props - The options for both restoring and saving.\n * @returns A tuple of a function that stops persisting, and a promise that resolves once the\n * restore is done.\n */\nexport function persistQueryClient(\n props: PersistQueryClientOptions,\n): [() => void, Promise<void>] {\n let hasUnsubscribed = false\n let persistQueryClientUnsubscribe: (() => void) | undefined\n const unsubscribe = () => {\n hasUnsubscribed = true\n persistQueryClientUnsubscribe?.()\n }\n\n // Attempt restore\n const restorePromise = persistQueryClientRestore(props).then(() => {\n if (!hasUnsubscribed) {\n // Subscribe to changes in the query cache to trigger the save\n persistQueryClientUnsubscribe = persistQueryClientSubscribe(props)\n }\n })\n\n return [unsubscribe, restorePromise]\n}\n"],"mappings":";;;AAqGA,MAAM,kBAA0C;CAAC;CAAS;CAAW;AAAS;;;;;;;AAQ9E,SAAS,iBAAiB,WAA4B;CACpD,OAAO,gBAAgB,SAAS,SAAS;AAC3C;;;;;;;;;;;;AAaA,eAAsB,0BAA0B,EAC9C,aACA,WACA,SAAS,OACT,SAAS,IACT,kBACqC;CACrC,IAAI;EACF,MAAM,kBAAkB,MAAM,UAAU,cAAc;EAEtD,IAAI,iBAAiB;GACnB,IAAI,gBAAgB,WAAW;IAC7B,MAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB,YAAY;IACzD,MAAM,SAAS,gBAAgB,WAAW;IAC1C,IAAI,WAAW,QACb,OAAO,UAAU,aAAa;SAE9B,CAAA,GAAA,qBAAA,QAAA,CAAQ,aAAa,gBAAgB,aAAa,cAAc;GAEpE,OACE,OAAO,UAAU,aAAa;EAElC;CACF,SAAS,KAAK;EACZ,IAAI,QAAQ,IAAI,aAAa,cAAc;GACzC,QAAQ,MAAM,GAAG;GACjB,QAAQ,KACN,0IACF;EACF;EAEA,MAAM,UAAU,aAAa;EAE7B,MAAM;CACR;AACF;;;;;;;;AASA,eAAsB,uBAAuB,EAC3C,aACA,WACA,SAAS,IACT,oBACkC;CAClC,MAAM,gBAAiC;EACrC;EACA,WAAW,KAAK,IAAI;EACpB,cAAA,GAAaA,qBAAAA,UAAAA,CAAU,aAAa,gBAAgB;CACtD;CAEA,MAAM,UAAU,cAAc,aAAa;AAC7C;;;;;;;AAQA,SAAgB,4BACd,OACA;CACA,MAAM,wBAAwB,MAAM,YACjC,cAAc,CAAC,CACf,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,uBAAuB,KAAK;CAEhC,CAAC;CAEH,MAAM,2BAA2B,MAAM,YACpC,iBAAiB,CAAC,CAClB,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,uBAAuB,KAAK;CAEhC,CAAC;CAEH,aAAa;EACX,sBAAsB;EACtB,yBAAyB;CAC3B;AACF;;;;;;;AAQA,SAAgB,mBACd,OAC6B;CAC7B,IAAI,kBAAkB;CACtB,IAAI;CACJ,MAAM,oBAAoB;EACxB,kBAAkB;EAClB,gCAAgC;CAClC;CAUA,OAAO,CAAC,aAPe,0BAA0B,KAAK,CAAC,CAAC,WAAW;EACjE,IAAI,CAAC,iBAEH,gCAAgC,4BAA4B,KAAK;CAErE,CAEkC,CAAC;AACrC"}
1
+ {"version":3,"file":"persist.cjs","names":["dehydrate"],"sources":["../../src/persist.ts"],"sourcesContent":["import { dehydrate, hydrate } from '@tanstack/query-core'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n NotifyEventType,\n QueryClient,\n} from '@tanstack/query-core'\n\n/**\n * A value, or a promise-like that resolves to it.\n */\nexport type Promisable<T> = T | PromiseLike<T>\n\n/**\n * Saves, restores, and removes a {@link PersistedClient} in a storage.\n */\nexport interface Persister {\n /**\n * Saves the persisted client to the storage.\n */\n persistClient: (persistClient: PersistedClient) => Promisable<void>\n /**\n * Reads the persisted client from the storage, or `undefined` if nothing was saved.\n */\n restoreClient: () => Promisable<PersistedClient | undefined>\n /**\n * Removes the persisted client from the storage.\n */\n removeClient: () => Promisable<void>\n}\n\n/**\n * The dehydrated state of a `QueryClient` as it is persisted, with the time it was saved and its\n * `buster`.\n */\nexport interface PersistedClient {\n /**\n * When the client was saved, in milliseconds since the epoch. Compared with `maxAge` on restore.\n */\n timestamp: number\n /**\n * The `buster` the client was saved with. A persisted client with a different `buster` is\n * discarded.\n */\n buster: string\n /**\n * The dehydrated cache of the `QueryClient`.\n */\n clientState: DehydratedState\n}\n\n/**\n * The options shared by restoring and saving a persisted `QueryClient`.\n */\nexport interface PersistQueryClientRootOptions {\n /** The QueryClient to persist */\n queryClient: QueryClient\n /**\n * The Persister interface for storing and restoring the cache\n * to/from a persisted location\n */\n persister: Persister\n /**\n * A unique string that can be used to forcefully\n * invalidate existing caches if they do not share the same buster string\n */\n buster?: string\n}\n\n/**\n * Options for restoring a persisted `QueryClient` with {@link persistQueryClientRestore}.\n */\nexport interface PersistedQueryClientRestoreOptions extends PersistQueryClientRootOptions {\n /**\n * The max-allowed age of the cache in milliseconds.\n * If a persisted cache is found that is older than this\n * time, it will be discarded\n */\n maxAge?: number\n /** The options passed to the hydrate function */\n hydrateOptions?: HydrateOptions\n}\n\n/**\n * Options for saving a `QueryClient` with {@link persistQueryClientSave}.\n */\nexport interface PersistedQueryClientSaveOptions extends PersistQueryClientRootOptions {\n /** The options passed to the dehydrate function */\n dehydrateOptions?: DehydrateOptions\n}\n\n/**\n * Options for {@link persistQueryClient}, which both restores and saves a `QueryClient`.\n */\nexport interface PersistQueryClientOptions\n extends\n PersistedQueryClientRestoreOptions,\n PersistedQueryClientSaveOptions,\n PersistQueryClientRootOptions {}\n\nconst cacheEventTypes: Array<NotifyEventType> = ['added', 'removed', 'updated']\n\n/**\n * Checks if emitted event is about cache change and not about observers.\n * Useful for persist, where we only want to trigger save when cache is changed.\n * @param eventType - The type of the emitted event.\n * @returns `true` if the event is `'added'`, `'removed'`, or `'updated'`.\n */\nfunction isCacheEventType(eventType: NotifyEventType) {\n return cacheEventTypes.includes(eventType)\n}\n\n/**\n * Restores persisted data to the QueryCache.\n * - data obtained from persister.restoreClient.\n * - data is hydrated using hydrateOptions.\n * If data is expired, busted, empty, or throws, it runs persister.removeClient.\n * @param options - The `queryClient` to restore into, the `persister`, and the `maxAge`, `buster`,\n * and `hydrateOptions` that decide whether and how the persisted data is restored.\n * @returns A promise that resolves once the data is restored or removed. If restoring throws, it\n * attempts to remove the persisted data and then rejects with the restore error, or with the removal\n * error if the removal fails too.\n */\nexport async function persistQueryClientRestore({\n queryClient,\n persister,\n maxAge = 24 * 60 * 60 * 1000,\n buster = '',\n hydrateOptions,\n}: PersistedQueryClientRestoreOptions) {\n try {\n const persistedClient = await persister.restoreClient()\n\n if (persistedClient) {\n if (persistedClient.timestamp) {\n const expired = Date.now() - persistedClient.timestamp > maxAge\n const busted = persistedClient.buster !== buster\n if (expired || busted) {\n return persister.removeClient()\n } else {\n hydrate(queryClient, persistedClient.clientState, hydrateOptions)\n }\n } else {\n return persister.removeClient()\n }\n }\n } catch (err) {\n if (process.env.NODE_ENV !== 'production') {\n console.error(err)\n console.warn(\n 'Encountered an error attempting to restore client cache from persisted location. As a precaution, the persisted cache will be discarded.',\n )\n }\n\n await persister.removeClient()\n\n throw err\n }\n}\n\n/**\n * Persists data from the QueryCache.\n * - data dehydrated using dehydrateOptions.\n * - data is persisted using persister.persistClient.\n * @param options - The `queryClient` to persist, the `persister`, the `buster`, and the\n * `dehydrateOptions`.\n */\nexport async function persistQueryClientSave({\n queryClient,\n persister,\n buster = '',\n dehydrateOptions,\n}: PersistedQueryClientSaveOptions) {\n const persistClient: PersistedClient = {\n buster,\n timestamp: Date.now(),\n clientState: dehydrate(queryClient, dehydrateOptions),\n }\n\n await persister.persistClient(persistClient)\n}\n\n/**\n * Subscribe to QueryCache and MutationCache updates (for persisting).\n * @param props - The `queryClient` to monitor, the `persister`, the `buster`, and the\n * `dehydrateOptions` used for each save.\n * @returns an unsubscribe function (to discontinue monitoring)\n */\nexport function persistQueryClientSubscribe(\n props: PersistedQueryClientSaveOptions,\n) {\n const save = () => {\n persistQueryClientSave(props).catch((err) => {\n if (process.env.NODE_ENV !== 'production') {\n console.error(err)\n console.warn(\n 'Encountered an error attempting to persist client cache to persisted location.',\n )\n }\n })\n }\n\n const unsubscribeQueryCache = props.queryClient\n .getQueryCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n save()\n }\n })\n\n const unsubscribeMutationCache = props.queryClient\n .getMutationCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n save()\n }\n })\n\n return () => {\n unsubscribeQueryCache()\n unsubscribeMutationCache()\n }\n}\n\n/**\n * Restores persisted data to QueryCache and persists further changes.\n * @param props - The options for both restoring and saving.\n * @returns A tuple of a function that stops persisting, and a promise that resolves once the\n * restore is done.\n */\nexport function persistQueryClient(\n props: PersistQueryClientOptions,\n): [() => void, Promise<void>] {\n let hasUnsubscribed = false\n let persistQueryClientUnsubscribe: (() => void) | undefined\n const unsubscribe = () => {\n hasUnsubscribed = true\n persistQueryClientUnsubscribe?.()\n }\n\n // Attempt restore\n const restorePromise = persistQueryClientRestore(props).then(() => {\n if (!hasUnsubscribed) {\n // Subscribe to changes in the query cache to trigger the save\n persistQueryClientUnsubscribe = persistQueryClientSubscribe(props)\n }\n })\n\n return [unsubscribe, restorePromise]\n}\n"],"mappings":";;;AAqGA,MAAM,kBAA0C;CAAC;CAAS;CAAW;AAAS;;;;;;;AAQ9E,SAAS,iBAAiB,WAA4B;CACpD,OAAO,gBAAgB,SAAS,SAAS;AAC3C;;;;;;;;;;;;AAaA,eAAsB,0BAA0B,EAC9C,aACA,WACA,SAAS,OACT,SAAS,IACT,kBACqC;CACrC,IAAI;EACF,MAAM,kBAAkB,MAAM,UAAU,cAAc;EAEtD,IAAI,iBAAiB;GACnB,IAAI,gBAAgB,WAAW;IAC7B,MAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB,YAAY;IACzD,MAAM,SAAS,gBAAgB,WAAW;IAC1C,IAAI,WAAW,QACb,OAAO,UAAU,aAAa;SAE9B,CAAA,GAAA,qBAAA,QAAA,CAAQ,aAAa,gBAAgB,aAAa,cAAc;GAEpE,OACE,OAAO,UAAU,aAAa;EAElC;CACF,SAAS,KAAK;EACZ,IAAI,QAAQ,IAAI,aAAa,cAAc;GACzC,QAAQ,MAAM,GAAG;GACjB,QAAQ,KACN,0IACF;EACF;EAEA,MAAM,UAAU,aAAa;EAE7B,MAAM;CACR;AACF;;;;;;;;AASA,eAAsB,uBAAuB,EAC3C,aACA,WACA,SAAS,IACT,oBACkC;CAClC,MAAM,gBAAiC;EACrC;EACA,WAAW,KAAK,IAAI;EACpB,cAAA,GAAaA,qBAAAA,UAAAA,CAAU,aAAa,gBAAgB;CACtD;CAEA,MAAM,UAAU,cAAc,aAAa;AAC7C;;;;;;;AAQA,SAAgB,4BACd,OACA;CACA,MAAM,aAAa;EACjB,uBAAuB,KAAK,CAAC,CAAC,OAAO,QAAQ;GAC3C,IAAI,QAAQ,IAAI,aAAa,cAAc;IACzC,QAAQ,MAAM,GAAG;IACjB,QAAQ,KACN,gFACF;GACF;EACF,CAAC;CACH;CAEA,MAAM,wBAAwB,MAAM,YACjC,cAAc,CAAC,CACf,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,KAAK;CAET,CAAC;CAEH,MAAM,2BAA2B,MAAM,YACpC,iBAAiB,CAAC,CAClB,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,KAAK;CAET,CAAC;CAEH,aAAa;EACX,sBAAsB;EACtB,yBAAyB;CAC3B;AACF;;;;;;;AAQA,SAAgB,mBACd,OAC6B;CAC7B,IAAI,kBAAkB;CACtB,IAAI;CACJ,MAAM,oBAAoB;EACxB,kBAAkB;EAClB,gCAAgC;CAClC;CAUA,OAAO,CAAC,aAPe,0BAA0B,KAAK,CAAC,CAAC,WAAW;EACjE,IAAI,CAAC,iBAEH,gCAAgC,4BAA4B,KAAK;CAErE,CAEkC,CAAC;AACrC"}
@@ -1,5 +1,4 @@
1
1
  import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@tanstack/query-core";
2
- //#region src/persist.d.ts
3
2
  /**
4
3
  * A value, or a promise-like that resolves to it.
5
4
  */
@@ -115,5 +114,4 @@ export declare function persistQueryClientSubscribe(props: PersistedQueryClientS
115
114
  * restore is done.
116
115
  */
117
116
  export declare function persistQueryClient(props: PersistQueryClientOptions): [() => void, Promise<void>];
118
- //#endregion
119
117
  //# sourceMappingURL=persist.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persist.d.cts","names":[],"sources":["../../src/persist.ts"],"mappings":";;;;;YAYY,WAAW,KAAK,IAAI,YAAY;;;;iBAK3B;;;;EAIf,gBAAgB,eAAe,oBAAoB;;;;EAInD,qBAAqB,WAAW;;;;EAIhC,oBAAoB;;;;;;iBAOL;;;;EAIf;;;;;EAKA;;;;EAIA,aAAa;;;;;iBAME;;EAEf,aAAa;;;;;EAKb,WAAW;;;;;EAKX;;;;;iBAMe,2CAA2C;;;;;;EAM1D;;EAEA,iBAAiB;;;;;iBAMF,wCAAwC;;EAEvD,mBAAmB;;;;;iBAMJ,kCAEb,oCACA,iCACA;;;;;;;;;;;;wBAyBkB,4BACpB,aACA,WACA,QACA,QACA,kBACC,qCAAkC;;;;;;;;wBAsCf,yBACpB,aACA,WACA,QACA,oBACC,kCAA+B;;;;;;;wBAgBlB,4BACd,OAAO;;;;;;;wBA8BO,mBACd,OAAO,yCACO"}
1
+ {"version":3,"file":"persist.d.cts","names":[],"sources":["../../src/persist.ts"],"mappings":";;;;YAYY,WAAW,KAAK,IAAI,YAAY;;;;iBAK3B;;;;EAIf,gBAAgB,eAAe,oBAAoB;;;;EAInD,qBAAqB,WAAW;;;;EAIhC,oBAAoB;;;;;;iBAOL;;;;EAIf;;;;;EAKA;;;;EAIA,aAAa;;;;;iBAME;;EAEf,aAAa;;;;;EAKb,WAAW;;;;;EAKX;;;;;iBAMe,2CAA2C;;;;;;EAM1D;;EAEA,iBAAiB;;;;;iBAMF,wCAAwC;;EAEvD,mBAAmB;;;;;iBAMJ,kCAEb,oCACA,iCACA;;;;;;;;;;;;wBAyBkB,4BACpB,aACA,WACA,QACA,QACA,kBACC,qCAAkC;;;;;;;;wBAsCf,yBACpB,aACA,WACA,QACA,oBACC,kCAA+B;;;;;;;wBAgBlB,4BACd,OAAO;;;;;;;wBAyCO,mBACd,OAAO,yCACO"}
@@ -1,5 +1,4 @@
1
1
  import { DehydrateOptions, DehydratedState, HydrateOptions, QueryClient } from "@tanstack/query-core";
2
- //#region src/persist.d.ts
3
2
  /**
4
3
  * A value, or a promise-like that resolves to it.
5
4
  */
@@ -115,5 +114,4 @@ export declare function persistQueryClientSubscribe(props: PersistedQueryClientS
115
114
  * restore is done.
116
115
  */
117
116
  export declare function persistQueryClient(props: PersistQueryClientOptions): [() => void, Promise<void>];
118
- //#endregion
119
117
  //# sourceMappingURL=persist.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persist.d.ts","names":[],"sources":["../../src/persist.ts"],"mappings":";;;;;YAYY,WAAW,KAAK,IAAI,YAAY;;;;iBAK3B;;;;EAIf,gBAAgB,eAAe,oBAAoB;;;;EAInD,qBAAqB,WAAW;;;;EAIhC,oBAAoB;;;;;;iBAOL;;;;EAIf;;;;;EAKA;;;;EAIA,aAAa;;;;;iBAME;;EAEf,aAAa;;;;;EAKb,WAAW;;;;;EAKX;;;;;iBAMe,2CAA2C;;;;;;EAM1D;;EAEA,iBAAiB;;;;;iBAMF,wCAAwC;;EAEvD,mBAAmB;;;;;iBAMJ,kCAEb,oCACA,iCACA;;;;;;;;;;;;wBAyBkB,4BACpB,aACA,WACA,QACA,QACA,kBACC,qCAAkC;;;;;;;;wBAsCf,yBACpB,aACA,WACA,QACA,oBACC,kCAA+B;;;;;;;wBAgBlB,4BACd,OAAO;;;;;;;wBA8BO,mBACd,OAAO,yCACO"}
1
+ {"version":3,"file":"persist.d.ts","names":[],"sources":["../../src/persist.ts"],"mappings":";;;;YAYY,WAAW,KAAK,IAAI,YAAY;;;;iBAK3B;;;;EAIf,gBAAgB,eAAe,oBAAoB;;;;EAInD,qBAAqB,WAAW;;;;EAIhC,oBAAoB;;;;;;iBAOL;;;;EAIf;;;;;EAKA;;;;EAIA,aAAa;;;;;iBAME;;EAEf,aAAa;;;;;EAKb,WAAW;;;;;EAKX;;;;;iBAMe,2CAA2C;;;;;;EAM1D;;EAEA,iBAAiB;;;;;iBAMF,wCAAwC;;EAEvD,mBAAmB;;;;;iBAMJ,kCAEb,oCACA,iCACA;;;;;;;;;;;;wBAyBkB,4BACpB,aACA,WACA,QACA,QACA,kBACC,qCAAkC;;;;;;;;wBAsCf,yBACpB,aACA,WACA,QACA,oBACC,kCAA+B;;;;;;;wBAgBlB,4BACd,OAAO;;;;;;;wBAyCO,mBACd,OAAO,yCACO"}
@@ -1,5 +1,5 @@
1
1
  import { dehydrate, hydrate } from "@tanstack/query-core";
2
- //#region src/persist.ts
2
+ // src/persist.ts
3
3
  const cacheEventTypes = [
4
4
  "added",
5
5
  "removed",
@@ -67,11 +67,19 @@ async function persistQueryClientSave({ queryClient, persister, buster = "", deh
67
67
  * @returns an unsubscribe function (to discontinue monitoring)
68
68
  */
69
69
  function persistQueryClientSubscribe(props) {
70
+ const save = () => {
71
+ persistQueryClientSave(props).catch((err) => {
72
+ if (process.env.NODE_ENV !== "production") {
73
+ console.error(err);
74
+ console.warn("Encountered an error attempting to persist client cache to persisted location.");
75
+ }
76
+ });
77
+ };
70
78
  const unsubscribeQueryCache = props.queryClient.getQueryCache().subscribe((event) => {
71
- if (isCacheEventType(event.type)) persistQueryClientSave(props);
79
+ if (isCacheEventType(event.type)) save();
72
80
  });
73
81
  const unsubscribeMutationCache = props.queryClient.getMutationCache().subscribe((event) => {
74
- if (isCacheEventType(event.type)) persistQueryClientSave(props);
82
+ if (isCacheEventType(event.type)) save();
75
83
  });
76
84
  return () => {
77
85
  unsubscribeQueryCache();
@@ -95,7 +103,6 @@ function persistQueryClient(props) {
95
103
  if (!hasUnsubscribed) persistQueryClientUnsubscribe = persistQueryClientSubscribe(props);
96
104
  })];
97
105
  }
98
- //#endregion
99
106
  export { persistQueryClient, persistQueryClientRestore, persistQueryClientSave, persistQueryClientSubscribe };
100
107
 
101
108
  //# sourceMappingURL=persist.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"persist.js","names":[],"sources":["../../src/persist.ts"],"sourcesContent":["import { dehydrate, hydrate } from '@tanstack/query-core'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n NotifyEventType,\n QueryClient,\n} from '@tanstack/query-core'\n\n/**\n * A value, or a promise-like that resolves to it.\n */\nexport type Promisable<T> = T | PromiseLike<T>\n\n/**\n * Saves, restores, and removes a {@link PersistedClient} in a storage.\n */\nexport interface Persister {\n /**\n * Saves the persisted client to the storage.\n */\n persistClient: (persistClient: PersistedClient) => Promisable<void>\n /**\n * Reads the persisted client from the storage, or `undefined` if nothing was saved.\n */\n restoreClient: () => Promisable<PersistedClient | undefined>\n /**\n * Removes the persisted client from the storage.\n */\n removeClient: () => Promisable<void>\n}\n\n/**\n * The dehydrated state of a `QueryClient` as it is persisted, with the time it was saved and its\n * `buster`.\n */\nexport interface PersistedClient {\n /**\n * When the client was saved, in milliseconds since the epoch. Compared with `maxAge` on restore.\n */\n timestamp: number\n /**\n * The `buster` the client was saved with. A persisted client with a different `buster` is\n * discarded.\n */\n buster: string\n /**\n * The dehydrated cache of the `QueryClient`.\n */\n clientState: DehydratedState\n}\n\n/**\n * The options shared by restoring and saving a persisted `QueryClient`.\n */\nexport interface PersistQueryClientRootOptions {\n /** The QueryClient to persist */\n queryClient: QueryClient\n /**\n * The Persister interface for storing and restoring the cache\n * to/from a persisted location\n */\n persister: Persister\n /**\n * A unique string that can be used to forcefully\n * invalidate existing caches if they do not share the same buster string\n */\n buster?: string\n}\n\n/**\n * Options for restoring a persisted `QueryClient` with {@link persistQueryClientRestore}.\n */\nexport interface PersistedQueryClientRestoreOptions extends PersistQueryClientRootOptions {\n /**\n * The max-allowed age of the cache in milliseconds.\n * If a persisted cache is found that is older than this\n * time, it will be discarded\n */\n maxAge?: number\n /** The options passed to the hydrate function */\n hydrateOptions?: HydrateOptions\n}\n\n/**\n * Options for saving a `QueryClient` with {@link persistQueryClientSave}.\n */\nexport interface PersistedQueryClientSaveOptions extends PersistQueryClientRootOptions {\n /** The options passed to the dehydrate function */\n dehydrateOptions?: DehydrateOptions\n}\n\n/**\n * Options for {@link persistQueryClient}, which both restores and saves a `QueryClient`.\n */\nexport interface PersistQueryClientOptions\n extends\n PersistedQueryClientRestoreOptions,\n PersistedQueryClientSaveOptions,\n PersistQueryClientRootOptions {}\n\nconst cacheEventTypes: Array<NotifyEventType> = ['added', 'removed', 'updated']\n\n/**\n * Checks if emitted event is about cache change and not about observers.\n * Useful for persist, where we only want to trigger save when cache is changed.\n * @param eventType - The type of the emitted event.\n * @returns `true` if the event is `'added'`, `'removed'`, or `'updated'`.\n */\nfunction isCacheEventType(eventType: NotifyEventType) {\n return cacheEventTypes.includes(eventType)\n}\n\n/**\n * Restores persisted data to the QueryCache.\n * - data obtained from persister.restoreClient.\n * - data is hydrated using hydrateOptions.\n * If data is expired, busted, empty, or throws, it runs persister.removeClient.\n * @param options - The `queryClient` to restore into, the `persister`, and the `maxAge`, `buster`,\n * and `hydrateOptions` that decide whether and how the persisted data is restored.\n * @returns A promise that resolves once the data is restored or removed. If restoring throws, it\n * attempts to remove the persisted data and then rejects with the restore error, or with the removal\n * error if the removal fails too.\n */\nexport async function persistQueryClientRestore({\n queryClient,\n persister,\n maxAge = 1000 * 60 * 60 * 24,\n buster = '',\n hydrateOptions,\n}: PersistedQueryClientRestoreOptions) {\n try {\n const persistedClient = await persister.restoreClient()\n\n if (persistedClient) {\n if (persistedClient.timestamp) {\n const expired = Date.now() - persistedClient.timestamp > maxAge\n const busted = persistedClient.buster !== buster\n if (expired || busted) {\n return persister.removeClient()\n } else {\n hydrate(queryClient, persistedClient.clientState, hydrateOptions)\n }\n } else {\n return persister.removeClient()\n }\n }\n } catch (err) {\n if (process.env.NODE_ENV !== 'production') {\n console.error(err)\n console.warn(\n 'Encountered an error attempting to restore client cache from persisted location. As a precaution, the persisted cache will be discarded.',\n )\n }\n\n await persister.removeClient()\n\n throw err\n }\n}\n\n/**\n * Persists data from the QueryCache.\n * - data dehydrated using dehydrateOptions.\n * - data is persisted using persister.persistClient.\n * @param options - The `queryClient` to persist, the `persister`, the `buster`, and the\n * `dehydrateOptions`.\n */\nexport async function persistQueryClientSave({\n queryClient,\n persister,\n buster = '',\n dehydrateOptions,\n}: PersistedQueryClientSaveOptions) {\n const persistClient: PersistedClient = {\n buster,\n timestamp: Date.now(),\n clientState: dehydrate(queryClient, dehydrateOptions),\n }\n\n await persister.persistClient(persistClient)\n}\n\n/**\n * Subscribe to QueryCache and MutationCache updates (for persisting).\n * @param props - The `queryClient` to monitor, the `persister`, the `buster`, and the\n * `dehydrateOptions` used for each save.\n * @returns an unsubscribe function (to discontinue monitoring)\n */\nexport function persistQueryClientSubscribe(\n props: PersistedQueryClientSaveOptions,\n) {\n const unsubscribeQueryCache = props.queryClient\n .getQueryCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n persistQueryClientSave(props)\n }\n })\n\n const unsubscribeMutationCache = props.queryClient\n .getMutationCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n persistQueryClientSave(props)\n }\n })\n\n return () => {\n unsubscribeQueryCache()\n unsubscribeMutationCache()\n }\n}\n\n/**\n * Restores persisted data to QueryCache and persists further changes.\n * @param props - The options for both restoring and saving.\n * @returns A tuple of a function that stops persisting, and a promise that resolves once the\n * restore is done.\n */\nexport function persistQueryClient(\n props: PersistQueryClientOptions,\n): [() => void, Promise<void>] {\n let hasUnsubscribed = false\n let persistQueryClientUnsubscribe: (() => void) | undefined\n const unsubscribe = () => {\n hasUnsubscribed = true\n persistQueryClientUnsubscribe?.()\n }\n\n // Attempt restore\n const restorePromise = persistQueryClientRestore(props).then(() => {\n if (!hasUnsubscribed) {\n // Subscribe to changes in the query cache to trigger the save\n persistQueryClientUnsubscribe = persistQueryClientSubscribe(props)\n }\n })\n\n return [unsubscribe, restorePromise]\n}\n"],"mappings":";;AAqGA,MAAM,kBAA0C;CAAC;CAAS;CAAW;AAAS;;;;;;;AAQ9E,SAAS,iBAAiB,WAA4B;CACpD,OAAO,gBAAgB,SAAS,SAAS;AAC3C;;;;;;;;;;;;AAaA,eAAsB,0BAA0B,EAC9C,aACA,WACA,SAAS,OACT,SAAS,IACT,kBACqC;CACrC,IAAI;EACF,MAAM,kBAAkB,MAAM,UAAU,cAAc;EAEtD,IAAI,iBAAiB;GACnB,IAAI,gBAAgB,WAAW;IAC7B,MAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB,YAAY;IACzD,MAAM,SAAS,gBAAgB,WAAW;IAC1C,IAAI,WAAW,QACb,OAAO,UAAU,aAAa;SAE9B,QAAQ,aAAa,gBAAgB,aAAa,cAAc;GAEpE,OACE,OAAO,UAAU,aAAa;EAElC;CACF,SAAS,KAAK;EACZ,IAAI,QAAQ,IAAI,aAAa,cAAc;GACzC,QAAQ,MAAM,GAAG;GACjB,QAAQ,KACN,0IACF;EACF;EAEA,MAAM,UAAU,aAAa;EAE7B,MAAM;CACR;AACF;;;;;;;;AASA,eAAsB,uBAAuB,EAC3C,aACA,WACA,SAAS,IACT,oBACkC;CAClC,MAAM,gBAAiC;EACrC;EACA,WAAW,KAAK,IAAI;EACpB,aAAa,UAAU,aAAa,gBAAgB;CACtD;CAEA,MAAM,UAAU,cAAc,aAAa;AAC7C;;;;;;;AAQA,SAAgB,4BACd,OACA;CACA,MAAM,wBAAwB,MAAM,YACjC,cAAc,CAAC,CACf,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,uBAAuB,KAAK;CAEhC,CAAC;CAEH,MAAM,2BAA2B,MAAM,YACpC,iBAAiB,CAAC,CAClB,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,uBAAuB,KAAK;CAEhC,CAAC;CAEH,aAAa;EACX,sBAAsB;EACtB,yBAAyB;CAC3B;AACF;;;;;;;AAQA,SAAgB,mBACd,OAC6B;CAC7B,IAAI,kBAAkB;CACtB,IAAI;CACJ,MAAM,oBAAoB;EACxB,kBAAkB;EAClB,gCAAgC;CAClC;CAUA,OAAO,CAAC,aAPe,0BAA0B,KAAK,CAAC,CAAC,WAAW;EACjE,IAAI,CAAC,iBAEH,gCAAgC,4BAA4B,KAAK;CAErE,CAEkC,CAAC;AACrC"}
1
+ {"version":3,"file":"persist.js","names":[],"sources":["../../src/persist.ts"],"sourcesContent":["import { dehydrate, hydrate } from '@tanstack/query-core'\nimport type {\n DehydrateOptions,\n DehydratedState,\n HydrateOptions,\n NotifyEventType,\n QueryClient,\n} from '@tanstack/query-core'\n\n/**\n * A value, or a promise-like that resolves to it.\n */\nexport type Promisable<T> = T | PromiseLike<T>\n\n/**\n * Saves, restores, and removes a {@link PersistedClient} in a storage.\n */\nexport interface Persister {\n /**\n * Saves the persisted client to the storage.\n */\n persistClient: (persistClient: PersistedClient) => Promisable<void>\n /**\n * Reads the persisted client from the storage, or `undefined` if nothing was saved.\n */\n restoreClient: () => Promisable<PersistedClient | undefined>\n /**\n * Removes the persisted client from the storage.\n */\n removeClient: () => Promisable<void>\n}\n\n/**\n * The dehydrated state of a `QueryClient` as it is persisted, with the time it was saved and its\n * `buster`.\n */\nexport interface PersistedClient {\n /**\n * When the client was saved, in milliseconds since the epoch. Compared with `maxAge` on restore.\n */\n timestamp: number\n /**\n * The `buster` the client was saved with. A persisted client with a different `buster` is\n * discarded.\n */\n buster: string\n /**\n * The dehydrated cache of the `QueryClient`.\n */\n clientState: DehydratedState\n}\n\n/**\n * The options shared by restoring and saving a persisted `QueryClient`.\n */\nexport interface PersistQueryClientRootOptions {\n /** The QueryClient to persist */\n queryClient: QueryClient\n /**\n * The Persister interface for storing and restoring the cache\n * to/from a persisted location\n */\n persister: Persister\n /**\n * A unique string that can be used to forcefully\n * invalidate existing caches if they do not share the same buster string\n */\n buster?: string\n}\n\n/**\n * Options for restoring a persisted `QueryClient` with {@link persistQueryClientRestore}.\n */\nexport interface PersistedQueryClientRestoreOptions extends PersistQueryClientRootOptions {\n /**\n * The max-allowed age of the cache in milliseconds.\n * If a persisted cache is found that is older than this\n * time, it will be discarded\n */\n maxAge?: number\n /** The options passed to the hydrate function */\n hydrateOptions?: HydrateOptions\n}\n\n/**\n * Options for saving a `QueryClient` with {@link persistQueryClientSave}.\n */\nexport interface PersistedQueryClientSaveOptions extends PersistQueryClientRootOptions {\n /** The options passed to the dehydrate function */\n dehydrateOptions?: DehydrateOptions\n}\n\n/**\n * Options for {@link persistQueryClient}, which both restores and saves a `QueryClient`.\n */\nexport interface PersistQueryClientOptions\n extends\n PersistedQueryClientRestoreOptions,\n PersistedQueryClientSaveOptions,\n PersistQueryClientRootOptions {}\n\nconst cacheEventTypes: Array<NotifyEventType> = ['added', 'removed', 'updated']\n\n/**\n * Checks if emitted event is about cache change and not about observers.\n * Useful for persist, where we only want to trigger save when cache is changed.\n * @param eventType - The type of the emitted event.\n * @returns `true` if the event is `'added'`, `'removed'`, or `'updated'`.\n */\nfunction isCacheEventType(eventType: NotifyEventType) {\n return cacheEventTypes.includes(eventType)\n}\n\n/**\n * Restores persisted data to the QueryCache.\n * - data obtained from persister.restoreClient.\n * - data is hydrated using hydrateOptions.\n * If data is expired, busted, empty, or throws, it runs persister.removeClient.\n * @param options - The `queryClient` to restore into, the `persister`, and the `maxAge`, `buster`,\n * and `hydrateOptions` that decide whether and how the persisted data is restored.\n * @returns A promise that resolves once the data is restored or removed. If restoring throws, it\n * attempts to remove the persisted data and then rejects with the restore error, or with the removal\n * error if the removal fails too.\n */\nexport async function persistQueryClientRestore({\n queryClient,\n persister,\n maxAge = 24 * 60 * 60 * 1000,\n buster = '',\n hydrateOptions,\n}: PersistedQueryClientRestoreOptions) {\n try {\n const persistedClient = await persister.restoreClient()\n\n if (persistedClient) {\n if (persistedClient.timestamp) {\n const expired = Date.now() - persistedClient.timestamp > maxAge\n const busted = persistedClient.buster !== buster\n if (expired || busted) {\n return persister.removeClient()\n } else {\n hydrate(queryClient, persistedClient.clientState, hydrateOptions)\n }\n } else {\n return persister.removeClient()\n }\n }\n } catch (err) {\n if (process.env.NODE_ENV !== 'production') {\n console.error(err)\n console.warn(\n 'Encountered an error attempting to restore client cache from persisted location. As a precaution, the persisted cache will be discarded.',\n )\n }\n\n await persister.removeClient()\n\n throw err\n }\n}\n\n/**\n * Persists data from the QueryCache.\n * - data dehydrated using dehydrateOptions.\n * - data is persisted using persister.persistClient.\n * @param options - The `queryClient` to persist, the `persister`, the `buster`, and the\n * `dehydrateOptions`.\n */\nexport async function persistQueryClientSave({\n queryClient,\n persister,\n buster = '',\n dehydrateOptions,\n}: PersistedQueryClientSaveOptions) {\n const persistClient: PersistedClient = {\n buster,\n timestamp: Date.now(),\n clientState: dehydrate(queryClient, dehydrateOptions),\n }\n\n await persister.persistClient(persistClient)\n}\n\n/**\n * Subscribe to QueryCache and MutationCache updates (for persisting).\n * @param props - The `queryClient` to monitor, the `persister`, the `buster`, and the\n * `dehydrateOptions` used for each save.\n * @returns an unsubscribe function (to discontinue monitoring)\n */\nexport function persistQueryClientSubscribe(\n props: PersistedQueryClientSaveOptions,\n) {\n const save = () => {\n persistQueryClientSave(props).catch((err) => {\n if (process.env.NODE_ENV !== 'production') {\n console.error(err)\n console.warn(\n 'Encountered an error attempting to persist client cache to persisted location.',\n )\n }\n })\n }\n\n const unsubscribeQueryCache = props.queryClient\n .getQueryCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n save()\n }\n })\n\n const unsubscribeMutationCache = props.queryClient\n .getMutationCache()\n .subscribe((event) => {\n if (isCacheEventType(event.type)) {\n save()\n }\n })\n\n return () => {\n unsubscribeQueryCache()\n unsubscribeMutationCache()\n }\n}\n\n/**\n * Restores persisted data to QueryCache and persists further changes.\n * @param props - The options for both restoring and saving.\n * @returns A tuple of a function that stops persisting, and a promise that resolves once the\n * restore is done.\n */\nexport function persistQueryClient(\n props: PersistQueryClientOptions,\n): [() => void, Promise<void>] {\n let hasUnsubscribed = false\n let persistQueryClientUnsubscribe: (() => void) | undefined\n const unsubscribe = () => {\n hasUnsubscribed = true\n persistQueryClientUnsubscribe?.()\n }\n\n // Attempt restore\n const restorePromise = persistQueryClientRestore(props).then(() => {\n if (!hasUnsubscribed) {\n // Subscribe to changes in the query cache to trigger the save\n persistQueryClientUnsubscribe = persistQueryClientSubscribe(props)\n }\n })\n\n return [unsubscribe, restorePromise]\n}\n"],"mappings":";;AAqGA,MAAM,kBAA0C;CAAC;CAAS;CAAW;AAAS;;;;;;;AAQ9E,SAAS,iBAAiB,WAA4B;CACpD,OAAO,gBAAgB,SAAS,SAAS;AAC3C;;;;;;;;;;;;AAaA,eAAsB,0BAA0B,EAC9C,aACA,WACA,SAAS,OACT,SAAS,IACT,kBACqC;CACrC,IAAI;EACF,MAAM,kBAAkB,MAAM,UAAU,cAAc;EAEtD,IAAI,iBAAiB;GACnB,IAAI,gBAAgB,WAAW;IAC7B,MAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB,YAAY;IACzD,MAAM,SAAS,gBAAgB,WAAW;IAC1C,IAAI,WAAW,QACb,OAAO,UAAU,aAAa;SAE9B,QAAQ,aAAa,gBAAgB,aAAa,cAAc;GAEpE,OACE,OAAO,UAAU,aAAa;EAElC;CACF,SAAS,KAAK;EACZ,IAAI,QAAQ,IAAI,aAAa,cAAc;GACzC,QAAQ,MAAM,GAAG;GACjB,QAAQ,KACN,0IACF;EACF;EAEA,MAAM,UAAU,aAAa;EAE7B,MAAM;CACR;AACF;;;;;;;;AASA,eAAsB,uBAAuB,EAC3C,aACA,WACA,SAAS,IACT,oBACkC;CAClC,MAAM,gBAAiC;EACrC;EACA,WAAW,KAAK,IAAI;EACpB,aAAa,UAAU,aAAa,gBAAgB;CACtD;CAEA,MAAM,UAAU,cAAc,aAAa;AAC7C;;;;;;;AAQA,SAAgB,4BACd,OACA;CACA,MAAM,aAAa;EACjB,uBAAuB,KAAK,CAAC,CAAC,OAAO,QAAQ;GAC3C,IAAI,QAAQ,IAAI,aAAa,cAAc;IACzC,QAAQ,MAAM,GAAG;IACjB,QAAQ,KACN,gFACF;GACF;EACF,CAAC;CACH;CAEA,MAAM,wBAAwB,MAAM,YACjC,cAAc,CAAC,CACf,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,KAAK;CAET,CAAC;CAEH,MAAM,2BAA2B,MAAM,YACpC,iBAAiB,CAAC,CAClB,WAAW,UAAU;EACpB,IAAI,iBAAiB,MAAM,IAAI,GAC7B,KAAK;CAET,CAAC;CAEH,aAAa;EACX,sBAAsB;EACtB,yBAAyB;CAC3B;AACF;;;;;;;AAQA,SAAgB,mBACd,OAC6B;CAC7B,IAAI,kBAAkB;CACtB,IAAI;CACJ,MAAM,oBAAoB;EACxB,kBAAkB;EAClB,gCAAgC;CAClC;CAUA,OAAO,CAAC,aAPe,0BAA0B,KAAK,CAAC,CAAC,WAAW;EACjE,IAAI,CAAC,iBAEH,gCAAgC,4BAA4B,KAAK;CAErE,CAEkC,CAAC;AACrC"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region src/retryStrategies.ts
2
+ // src/retryStrategies.ts
3
3
  /**
4
4
  * A {@link PersistRetryer} that drops the query with the oldest `dataUpdatedAt` and tries again, until
5
5
  * no queries are left.
@@ -23,7 +23,6 @@ const removeOldestQuery = ({ persistedClient }) => {
23
23
  return client;
24
24
  }
25
25
  };
26
- //#endregion
27
26
  exports.removeOldestQuery = removeOldestQuery;
28
27
 
29
28
  //# sourceMappingURL=retryStrategies.cjs.map
@@ -1,5 +1,4 @@
1
1
  import { PersistedClient } from "./persist.cjs";
2
- //#region src/retryStrategies.d.ts
3
2
  /**
4
3
  * Called when saving the persisted client fails. Returns a smaller client to try saving again, or
5
4
  * `undefined` to give up.
@@ -16,5 +15,4 @@ export type PersistRetryer = (props: {
16
15
  * @returns A copy of the client without its oldest query, or `undefined` if it has no queries.
17
16
  */
18
17
  export declare const removeOldestQuery: PersistRetryer;
19
- //#endregion
20
18
  //# sourceMappingURL=retryStrategies.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"retryStrategies.d.cts","names":[],"sources":["../../src/retryStrategies.ts"],"mappings":";;;;;;YAMY,kBAAkB;EAC5B,iBAAiB;EACjB,OAAO;EACP;MACI;;;;;;;qBAQO,mBAAmB"}
1
+ {"version":3,"file":"retryStrategies.d.cts","names":[],"sources":["../../src/retryStrategies.ts"],"mappings":";;;;;YAMY,kBAAkB;EAC5B,iBAAiB;EACjB,OAAO;EACP;MACI;;;;;;;qBAQO,mBAAmB"}
@@ -1,5 +1,4 @@
1
1
  import { PersistedClient } from "./persist.js";
2
- //#region src/retryStrategies.d.ts
3
2
  /**
4
3
  * Called when saving the persisted client fails. Returns a smaller client to try saving again, or
5
4
  * `undefined` to give up.
@@ -16,5 +15,4 @@ export type PersistRetryer = (props: {
16
15
  * @returns A copy of the client without its oldest query, or `undefined` if it has no queries.
17
16
  */
18
17
  export declare const removeOldestQuery: PersistRetryer;
19
- //#endregion
20
18
  //# sourceMappingURL=retryStrategies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"retryStrategies.d.ts","names":[],"sources":["../../src/retryStrategies.ts"],"mappings":";;;;;;YAMY,kBAAkB;EAC5B,iBAAiB;EACjB,OAAO;EACP;MACI;;;;;;;qBAQO,mBAAmB"}
1
+ {"version":3,"file":"retryStrategies.d.ts","names":[],"sources":["../../src/retryStrategies.ts"],"mappings":";;;;;YAMY,kBAAkB;EAC5B,iBAAiB;EACjB,OAAO;EACP;MACI;;;;;;;qBAQO,mBAAmB"}
@@ -1,4 +1,4 @@
1
- //#region src/retryStrategies.ts
1
+ // src/retryStrategies.ts
2
2
  /**
3
3
  * A {@link PersistRetryer} that drops the query with the oldest `dataUpdatedAt` and tries again, until
4
4
  * no queries are left.
@@ -22,7 +22,6 @@ const removeOldestQuery = ({ persistedClient }) => {
22
22
  return client;
23
23
  }
24
24
  };
25
- //#endregion
26
25
  export { removeOldestQuery };
27
26
 
28
27
  //# sourceMappingURL=retryStrategies.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/query-persist-client-core",
3
- "version": "5.104.5",
3
+ "version": "5.105.1",
4
4
  "description": "Set of utilities for interacting with persisters, which can save your queryClient for later use",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@
40
40
  "!src/__tests__"
41
41
  ],
42
42
  "dependencies": {
43
- "@tanstack/query-core": "5.104.5"
43
+ "@tanstack/query-core": "5.105.1"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@tanstack/query-test-utils": "0.0.0",
@@ -137,7 +137,7 @@ export const PERSISTER_KEY_PREFIX = 'tanstack-query'
137
137
  export function experimental_createQueryPersister<TStorageValue = string>({
138
138
  storage,
139
139
  buster = '',
140
- maxAge = 1000 * 60 * 60 * 24,
140
+ maxAge = 24 * 60 * 60 * 1000,
141
141
  serialize = JSON.stringify as Required<
142
142
  StoragePersisterOptions<TStorageValue>
143
143
  >['serialize'],
@@ -146,8 +146,33 @@ export function experimental_createQueryPersister<TStorageValue = string>({
146
146
  >['deserialize'],
147
147
  prefix = PERSISTER_KEY_PREFIX,
148
148
  refetchOnRestore = true,
149
- filters,
149
+ filters: persistFilters,
150
150
  }: StoragePersisterOptions<TStorageValue>) {
151
+ /**
152
+ * Checks the fields used to filter, expire, and restore a deserialized query.
153
+ * @param value - The deserialized value to check.
154
+ * @returns `true` if the value can be processed as a persisted query.
155
+ */
156
+ function isValidPersistedQuery(value: unknown) {
157
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
158
+ return false
159
+ }
160
+
161
+ const persistedQuery = value as Partial<Omit<PersistedQuery, 'state'>> & {
162
+ state?: Partial<QueryState> | null
163
+ }
164
+ const state = persistedQuery.state
165
+
166
+ return (
167
+ typeof persistedQuery.queryHash === 'string' &&
168
+ Array.isArray(persistedQuery.queryKey) &&
169
+ typeof state === 'object' &&
170
+ state !== null &&
171
+ !Array.isArray(state) &&
172
+ Number.isFinite(state.dataUpdatedAt)
173
+ )
174
+ }
175
+
151
176
  /**
152
177
  * Checks whether a persisted query should be discarded.
153
178
  * @param persistedQuery - The persisted query to check.
@@ -190,6 +215,9 @@ export function experimental_createQueryPersister<TStorageValue = string>({
190
215
  let persistedQuery: PersistedQuery
191
216
  try {
192
217
  persistedQuery = await deserialize(storedData)
218
+ if (!isValidPersistedQuery(persistedQuery)) {
219
+ throw new Error('Invalid persisted query')
220
+ }
193
221
  } catch {
194
222
  await storage.removeItem(storageKey)
195
223
  return
@@ -280,7 +308,9 @@ export function experimental_createQueryPersister<TStorageValue = string>({
280
308
  ctx: QueryFunctionContext<TQueryKey>,
281
309
  query: Query,
282
310
  ) {
283
- const matchesFilter = filters ? matchQuery(filters, query) : true
311
+ const matchesFilter = persistFilters
312
+ ? matchQuery(persistFilters, query)
313
+ : true
284
314
 
285
315
  // Try to restore only if we do not have any data in the cache and we have persister defined
286
316
  if (matchesFilter && query.state.data === undefined && storage != null) {
@@ -334,6 +364,9 @@ export function experimental_createQueryPersister<TStorageValue = string>({
334
364
  let persistedQuery: PersistedQuery
335
365
  try {
336
366
  persistedQuery = await deserialize(value)
367
+ if (!isValidPersistedQuery(persistedQuery)) {
368
+ throw new Error('Invalid persisted query')
369
+ }
337
370
  } catch {
338
371
  await storage.removeItem(key)
339
372
  continue
@@ -372,6 +405,9 @@ export function experimental_createQueryPersister<TStorageValue = string>({
372
405
  let persistedQuery: PersistedQuery
373
406
  try {
374
407
  persistedQuery = await deserialize(value)
408
+ if (!isValidPersistedQuery(persistedQuery)) {
409
+ throw new Error('Invalid persisted query')
410
+ }
375
411
  } catch {
376
412
  await storage.removeItem(key)
377
413
  continue
@@ -432,6 +468,9 @@ export function experimental_createQueryPersister<TStorageValue = string>({
432
468
  let persistedQuery: PersistedQuery
433
469
  try {
434
470
  persistedQuery = await deserialize(value)
471
+ if (!isValidPersistedQuery(persistedQuery)) {
472
+ throw new Error('Invalid persisted query')
473
+ }
435
474
  } catch {
436
475
  await storage.removeItem(key)
437
476
  continue
package/src/persist.ts CHANGED
@@ -125,7 +125,7 @@ function isCacheEventType(eventType: NotifyEventType) {
125
125
  export async function persistQueryClientRestore({
126
126
  queryClient,
127
127
  persister,
128
- maxAge = 1000 * 60 * 60 * 24,
128
+ maxAge = 24 * 60 * 60 * 1000,
129
129
  buster = '',
130
130
  hydrateOptions,
131
131
  }: PersistedQueryClientRestoreOptions) {
@@ -190,11 +190,22 @@ export async function persistQueryClientSave({
190
190
  export function persistQueryClientSubscribe(
191
191
  props: PersistedQueryClientSaveOptions,
192
192
  ) {
193
+ const save = () => {
194
+ persistQueryClientSave(props).catch((err) => {
195
+ if (process.env.NODE_ENV !== 'production') {
196
+ console.error(err)
197
+ console.warn(
198
+ 'Encountered an error attempting to persist client cache to persisted location.',
199
+ )
200
+ }
201
+ })
202
+ }
203
+
193
204
  const unsubscribeQueryCache = props.queryClient
194
205
  .getQueryCache()
195
206
  .subscribe((event) => {
196
207
  if (isCacheEventType(event.type)) {
197
- persistQueryClientSave(props)
208
+ save()
198
209
  }
199
210
  })
200
211
 
@@ -202,7 +213,7 @@ export function persistQueryClientSubscribe(
202
213
  .getMutationCache()
203
214
  .subscribe((event) => {
204
215
  if (isCacheEventType(event.type)) {
205
- persistQueryClientSave(props)
216
+ save()
206
217
  }
207
218
  })
208
219