/* Slim Uiltjies AfterCare — Service Worker Offline-first caching for the entire app shell + vendor libs. */ const CACHE = 'slimuiltjies-v11'; const PRECACHE = [ './', './index.html', './manifest.webmanifest', './css/styles.css', './js/app.js', './js/db.js', './js/seed.js', './js/icons.js', './js/invoice.js', './js/pdf.js', './js/share.js', './js/views.js', './vendor/jspdf.umd.min.js', './vendor/html2canvas.min.js', './icons/icon.svg', './icons/icon-192.png', './icons/icon-512.png', './icons/apple-touch-icon.png', './icons/favicon-32.png' ]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE).then((cache) => cache.addAll(PRECACHE)).then(() => self.skipWaiting()) ); }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))) ).then(() => self.clients.claim()) ); }); self.addEventListener('fetch', (event) => { const req = event.request; // Only handle GET if (req.method !== 'GET') return; const url = new URL(req.url); // Same-origin only if (url.origin !== self.location.origin) return; event.respondWith( caches.match(req).then((cached) => { const networkFetch = fetch(req).then((res) => { // Cache successful basic responses for next time if (res && res.status === 200 && res.type === 'basic') { const copy = res.clone(); caches.open(CACHE).then((c) => c.put(req, copy)); } return res; }).catch(() => cached); // Cache-first with network fallback return cached || networkFetch; }) ); });