UNPKG

@tanstack/query-persist-client-core

Version:

Set of utilities for interacting with persisters, which can save your queryClient for later use

1 lines 6.95 kB
{"version":3,"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\nexport type Promisable<T> = T | PromiseLike<T>\n\nexport interface Persister {\n persistClient: (persistClient: PersistedClient) => Promisable<void>\n restoreClient: () => Promisable<PersistedClient | undefined>\n removeClient: () => Promisable<void>\n}\n\nexport interface PersistedClient {\n timestamp: number\n buster: string\n clientState: DehydratedState\n}\n\nexport interface PersistQueryClientRootOptions {\n /** The QueryClient to persist */\n queryClient: QueryClient\n /** The Persister interface for storing and restoring the cache\n * to/from a persisted location */\n persister: Persister\n /** A unique string that can be used to forcefully\n * invalidate existing caches if they do not share the same buster string */\n buster?: string\n}\n\nexport interface PersistedQueryClientRestoreOptions\n extends PersistQueryClientRootOptions {\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 maxAge?: number\n /** The options passed to the hydrate function */\n hydrateOptions?: HydrateOptions\n}\n\nexport interface PersistedQueryClientSaveOptions\n extends PersistQueryClientRootOptions {\n /** The options passed to the dehydrate function */\n dehydrateOptions?: DehydrateOptions\n}\n\nexport interface PersistQueryClientOptions\n extends PersistedQueryClientRestoreOptions,\n PersistedQueryClientSaveOptions,\n PersistQueryClientRootOptions {}\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 */\nconst cacheEventTypes: Array<NotifyEventType> = ['added', 'removed', '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 */\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 */\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 * @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 */\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAmC;AA2DnC,IAAM,kBAA0C,CAAC,SAAS,WAAW,SAAS;AAE9E,SAAS,iBAAiB,WAA4B;AACpD,SAAO,gBAAgB,SAAS,SAAS;AAC3C;AAQA,eAAsB,0BAA0B;AAAA,EAC9C;AAAA,EACA;AAAA,EACA,SAAS,MAAO,KAAK,KAAK;AAAA,EAC1B,SAAS;AAAA,EACT;AACF,GAAuC;AACrC,MAAI;AACF,UAAM,kBAAkB,MAAM,UAAU,cAAc;AAEtD,QAAI,iBAAiB;AACnB,UAAI,gBAAgB,WAAW;AAC7B,cAAM,UAAU,KAAK,IAAI,IAAI,gBAAgB,YAAY;AACzD,cAAM,SAAS,gBAAgB,WAAW;AAC1C,YAAI,WAAW,QAAQ;AACrB,iBAAO,UAAU,aAAa;AAAA,QAChC,OAAO;AACL,yCAAQ,aAAa,gBAAgB,aAAa,cAAc;AAAA,QAClE;AAAA,MACF,OAAO;AACL,eAAO,UAAU,aAAa;AAAA,MAChC;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAQ,MAAM,GAAG;AACjB,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,aAAa;AAE7B,UAAM;AAAA,EACR;AACF;AAOA,eAAsB,uBAAuB;AAAA,EAC3C;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT;AACF,GAAoC;AAClC,QAAM,gBAAiC;AAAA,IACrC;AAAA,IACA,WAAW,KAAK,IAAI;AAAA,IACpB,iBAAa,6BAAU,aAAa,gBAAgB;AAAA,EACtD;AAEA,QAAM,UAAU,cAAc,aAAa;AAC7C;AAMO,SAAS,4BACd,OACA;AACA,QAAM,wBAAwB,MAAM,YACjC,cAAc,EACd,UAAU,CAAC,UAAU;AACpB,QAAI,iBAAiB,MAAM,IAAI,GAAG;AAChC,6BAAuB,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC;AAEH,QAAM,2BAA2B,MAAM,YACpC,iBAAiB,EACjB,UAAU,CAAC,UAAU;AACpB,QAAI,iBAAiB,MAAM,IAAI,GAAG;AAChC,6BAAuB,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC;AAEH,SAAO,MAAM;AACX,0BAAsB;AACtB,6BAAyB;AAAA,EAC3B;AACF;AAKO,SAAS,mBACd,OAC6B;AAC7B,MAAI,kBAAkB;AACtB,MAAI;AACJ,QAAM,cAAc,MAAM;AACxB,sBAAkB;AAClB;AAAA,EACF;AAGA,QAAM,iBAAiB,0BAA0B,KAAK,EAAE,KAAK,MAAM;AACjE,QAAI,CAAC,iBAAiB;AAEpB,sCAAgC,4BAA4B,KAAK;AAAA,IACnE;AAAA,EACF,CAAC;AAED,SAAO,CAAC,aAAa,cAAc;AACrC;","names":[]}