/* Chat SPBoucher AI service worker — static assets only. API responses and pages carrying private data are NEVER cached. */ const VERSION = "csa-v1"; const STATIC = ["/offline", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"]; self.addEventListener("install", e => { e.waitUntil(caches.open(VERSION).then(c => c.addAll(STATIC)).then(() => self.skipWaiting())); }); self.addEventListener("activate", e => { e.waitUntil(caches.keys().then(ks => Promise.all(ks.filter(k => k !== VERSION).map(k => caches.delete(k)))).then(() => self.clients.claim())); }); self.addEventListener("message", e => { if (e.data === "logout") caches.keys().then(ks => ks.forEach(k => caches.delete(k))); }); self.addEventListener("fetch", e => { const url = new URL(e.request.url); if (e.request.method !== "GET" || url.origin !== location.origin) return; if (url.pathname.startsWith("/api/")) return; // never cache API if (url.pathname.startsWith("/_next/static/") || url.pathname.startsWith("/icons/")) { e.respondWith(caches.match(e.request).then(hit => hit || fetch(e.request).then(res => { const copy = res.clone(); caches.open(VERSION).then(c => c.put(e.request, copy)); return res; }))); return; } if (e.request.mode === "navigate") { e.respondWith(fetch(e.request).catch(() => caches.match("/offline"))); } });