// Install-only service worker. // // Its sole job today is to satisfy Chromium's PWA installability requirement (a registered // service worker with a fetch handler) so the web app can be installed to the home screen / // desktop — notably on Android, where the manifest alone is not enough. It deliberately does // NOT cache assets or the Connect-RPC stream: only top-level navigations are handled, // network-first with a cached-shell fallback, so the live app, its immutable hashed assets and // the live event stream are never served stale. // // This is the single designated growth point for the planned offline mode (a Settings toggle, // default online — see docs/ARCHITECTURE.md). Extend the fetch router here; keep the same // /app/ scope; gate any real caching behind the toggle and coordinate updates with the boot // version guard. const SHELL = 'scrabble-shell-v1'; // bump only when the SW strategy itself changes. self.addEventListener('install', () => { // No cached content to migrate carefully, so activate the new worker immediately. self.skipWaiting(); }); self.addEventListener('activate', (event) => { event.waitUntil( (async () => { const keys = await caches.keys(); await Promise.all(keys.filter((k) => k !== SHELL).map((k) => caches.delete(k))); await self.clients.claim(); })(), ); }); self.addEventListener('fetch', (event) => { const req = event.request; // Only top-level navigations are handled. Hashed assets and the Connect-RPC requests are // left untouched (no respondWith -> the browser performs its default fetch), so the worker // can never break the live stream or serve a stale immutable asset. if (req.mode !== 'navigate') return; event.respondWith( (async () => { try { const res = await fetch(req); const cache = await caches.open(SHELL); // One shell entry regardless of the deep-link path: the hash router resolves the route // client-side, so any offline navigation can be served the same cached shell. cache.put('shell', res.clone()); return res; } catch { const cache = await caches.open(SHELL); const cached = await cache.match('shell'); return cached ?? Response.error(); } })(), ); });