const CACHE_NAME = 'credittracker-v47'; const ASSETS = [ './index.html', './manifest.json', './icon.svg', './icon-maskable.svg' ]; // Install: pre-cache all app shell files self.addEventListener('install', event => { event.waitUntil( caches.open(CACHE_NAME).then(cache => cache.addAll(ASSETS)) ); self.skipWaiting(); }); // Activate: clean up old caches self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(keys => Promise.all(keys.filter(k => k !== CACHE_NAME).map(k => caches.delete(k))) ) ); self.clients.claim(); }); // Lets the page ask "what version are you actually running" (Settings screen indicator) self.addEventListener('message', event => { if (event.data && event.data.type === 'GET_VERSION') { event.source.postMessage({ type: 'VERSION', version: CACHE_NAME }); } }); // Fetch: network-first for the app shell (so edits show up without a version bump), // cache-first for everything else (icons, manifest, external libs) self.addEventListener('fetch', event => { if (event.request.method !== 'GET') return; const reqUrl = new URL(event.request.url); const isSameOrigin = reqUrl.origin === self.location.origin; const isAppShell = isSameOrigin && (event.request.mode === 'navigate' || reqUrl.pathname.endsWith('/index.html')); if (isAppShell) { event.respondWith( fetch(event.request).then(response => { if (response.ok) { const clone = response.clone(); caches.open(CACHE_NAME).then(cache => cache.put(event.request, clone)); } return response; }).catch(() => caches.match(event.request).then(cached => cached || caches.match('./index.html'))) ); return; } event.respondWith( caches.match(event.request).then(cached => { if (cached) return cached; return fetch(event.request).then(response => { if (response.ok && isSameOrigin) { const clone = response.clone(); caches.open(CACHE_NAME).then(cache => cache.put(event.request, clone)); } return response; }); }).catch(() => { // Offline fallback only for external CDN fetches: fail loudly instead of masking with app HTML if (isSameOrigin) return caches.match('./index.html'); return Response.error(); }) ); });