// posimai-sc SW — same-origin の静的資産のみキャッシュ(CDN は対象外) const CACHE = 'posimai-sc-v8'; const STATIC = [ '/', '/index.html', '/manifest.json', '/logo.png', '/js/app.js', '/js/data/drills.js', '/js/data/categories.js' ]; self.addEventListener('install', e => { e.waitUntil( Promise.all([ caches.open(CACHE).then(c => c.addAll( STATIC.filter(u => { try { new URL(u, self.location.origin); return true; } catch { return false; } }) ) ), self.skipWaiting() ]) ); }); self.addEventListener('activate', e => { e.waitUntil( caches .keys() .then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))) .then(() => self.clients.claim()) ); }); self.addEventListener('fetch', e => { if (e.request.method !== 'GET') return; if (!e.request.url.startsWith(self.location.origin)) return; e.respondWith( caches.open(CACHE).then(cache => cache.match(e.request).then(cached => { const network = fetch(e.request) .then(res => { // type:'basic' = same-origin only; CORS レスポンスはキャッシュしない if (res.ok && res.type === 'basic') { cache.put(e.request, res.clone()).catch(err => { console.warn('[sc-sw] cache.put failed (quota?):', err); }); } return res; }) .catch(() => cached || new Response('Offline', { status: 503, statusText: 'Service Unavailable' })); return cached || network; }) ) ); });