const ROOT = new URL(self.registration.scope).pathname; const appPath = path => `${ROOT}${String(path).replace(/^\/+/, '')}`; const CACHE_NAMESPACE = `timmy-shell:${ROOT}:`; const CACHE = `${CACHE_NAMESPACE}v5`; const ASSETS = [ '', 'index.html', 'styles.css', 'app.js', 'src/domain.js', 'src/analysis.js', 'manifest.webmanifest', 'assets/timmy.svg', 'assets/icon-192.svg', 'assets/icon-512.svg', ].map(appPath); self.addEventListener('install', event => event.waitUntil( caches.open(CACHE).then(cache => cache.addAll(ASSETS)).then(() => self.skipWaiting()), )); self.addEventListener('activate', event => event.waitUntil( caches.keys() .then(keys => Promise.all(keys.filter(key => key.startsWith(CACHE_NAMESPACE) && key !== CACHE).map(key => caches.delete(key)))) .then(() => self.clients.claim()), )); self.addEventListener('fetch', event => { if (event.request.method !== 'GET' || !new URL(event.request.url).pathname.startsWith(ROOT)) return; event.respondWith( fetch(event.request) .then(response => { const copy = response.clone(); caches.open(CACHE).then(cache => cache.put(event.request, copy)); return response; }) .catch(() => caches.match(event.request).then(hit => hit || caches.match(appPath('index.html')))), ); });