/// // Claude Chat PWA — Service Worker // Cache-First fuer statische Assets, Network-First fuer API-Calls declare const self: ServiceWorkerGlobalScope; const CACHE_NAME = 'claude-chat-v1'; // Statische Assets die gecacht werden sollen const STATIC_ASSETS = [ '/', '/favicon.png', '/manifest.json', ]; // ============ Install — Statische Assets vorladen ============ self.addEventListener('install', (event: ExtendableEvent) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { return cache.addAll(STATIC_ASSETS); }) ); // Sofort aktivieren, nicht auf alte Tabs warten self.skipWaiting(); }); // ============ Activate — Alte Caches loeschen ============ self.addEventListener('activate', (event: ExtendableEvent) => { event.waitUntil( caches.keys().then((names) => { return Promise.all( names .filter((name) => name !== CACHE_NAME) .map((name) => caches.delete(name)) ); }) ); // Sofort alle Clients uebernehmen self.clients.claim(); }); // ============ Fetch — Caching-Strategie ============ self.addEventListener('fetch', (event: FetchEvent) => { const url = new URL(event.request.url); // WebSocket-Requests ignorieren if (url.protocol === 'ws:' || url.protocol === 'wss:') { return; } // API-Calls: Network-First mit Cache-Fallback if (url.pathname.startsWith('/api/')) { event.respondWith(networkFirst(event.request)); return; } // Statische Assets: Cache-First mit Network-Fallback event.respondWith(cacheFirst(event.request)); }); /** Cache-First: Zuerst im Cache suchen, dann Netzwerk */ async function cacheFirst(request: Request): Promise { const cached = await caches.match(request); if (cached) return cached; try { const response = await fetch(request); // Erfolgreiche Responses cachen if (response.ok) { const cache = await caches.open(CACHE_NAME); cache.put(request, response.clone()); } return response; } catch { // Offline-Fallback fuer HTML-Seiten if (request.headers.get('accept')?.includes('text/html')) { const cached = await caches.match('/'); if (cached) return cached; } return new Response('Offline', { status: 503 }); } } /** Network-First: Zuerst Netzwerk versuchen, dann Cache */ async function networkFirst(request: Request): Promise { try { const response = await fetch(request); // Erfolgreiche GET-Responses cachen if (response.ok && request.method === 'GET') { const cache = await caches.open(CACHE_NAME); cache.put(request, response.clone()); } return response; } catch { const cached = await caches.match(request); if (cached) return cached; return new Response(JSON.stringify({ error: 'Offline' }), { status: 503, headers: { 'Content-Type': 'application/json' }, }); } } export {};