{"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":[]}