import { QueryClient } from '@tanstack/react-query'; import { persistQueryClient } from '@tanstack/query-persist-client-core'; import { get, set, del } from 'idb-keyval'; import LZString from 'lz-string'; const CACHE_KEY = 'khollise-cache'; // Key for IndexedDB storage // Check if we're in a browser environment with IndexedDB support const isIndexedDBAvailable = () => { return typeof window !== 'undefined' && typeof window.indexedDB !== 'undefined' && window.indexedDB !== null; }; // Custom IndexedDB persister with LZ-string compression const createIDBPersister = () => { // Return a no-op persister if IndexedDB is not available if (!isIndexedDBAvailable()) { console.warn('IndexedDB not available - cache persistence disabled'); return { persistClient: async () => { }, restoreClient: async () => undefined, removeClient: async () => { }, }; } return { persistClient: async (client: any) => { try { // Double-check IndexedDB availability before operation if (!isIndexedDBAvailable()) { console.warn('IndexedDB not available during persist operation'); return; } // Serialize the client data const serializedClient = JSON.stringify(client); // Compress the serialized data const compressedData = LZString.compress(serializedClient); // Store compressed data in IndexedDB await set(CACHE_KEY, compressedData); } catch (error) { console.error('Failed to persist client cache:', error); } }, restoreClient: async () => { try { // Double-check IndexedDB availability before operation if (!isIndexedDBAvailable()) { console.warn('IndexedDB not available during restore operation'); return undefined; } // Get compressed data from IndexedDB const compressedData = await get(CACHE_KEY); if (!compressedData) { console.log('No cached data found in IndexedDB'); return undefined; } // Decompress the data const decompressedData = LZString.decompress(compressedData); if (!decompressedData) { console.warn('Failed to decompress cached data'); return undefined; } // Parse and return the client data const client = JSON.parse(decompressedData); console.log('Cache restored from IndexedDB'); return client; } catch (error) { console.error('Failed to restore client cache:', error); // Clear corrupted cache if IndexedDB is available if (isIndexedDBAvailable()) { try { await del(CACHE_KEY); } catch (delError) { console.error('Failed to clear corrupted cache:', delError); } } return undefined; } }, removeClient: async () => { try { // Double-check IndexedDB availability before operation if (!isIndexedDBAvailable()) { console.warn('IndexedDB not available during remove operation'); return; } await del(CACHE_KEY); console.log('Cache cleared from IndexedDB'); } catch (error) { console.error('Failed to remove client cache:', error); } }, }; }; // Create QueryClient with persistence const createQueryClient = () => { const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 1000 * 60 * 5, // 5 minutes gcTime: 1000 * 60 * 60 * 24, // 24 hours (formerly cacheTime) refetchOnWindowFocus: false, retry: 2, }, }, }); // Only set up persistence if IndexedDB is available if (isIndexedDBAvailable()) { persistQueryClient({ queryClient, persister: createIDBPersister(), maxAge: 1000 * 60 * 60 * 24, // 24 hours buster: 'v1', // Change this to invalidate cache }) } else { console.warn('Cache persistence disabled - IndexedDB not available'); } return queryClient; }; const queryClient = createQueryClient(); export default queryClient;