1// GENERATED by packages/service-worker/typescript. Do not edit this file: edit the 2// source there and run `bun run --filter=@bomdisoft/service-worker generate`. 3// 4// Native service worker: runtime caching only, no precache manifest. Next.js's static assets 5// under /_next/static/ are content-hashed in production (immutable URLs), so there is no need 6// for Workbox-style install-time precaching with revisioned cache invalidation: everything 7// caches progressively as it's requested. 8const CACHE_NAME = 'bomdisoft-v2'; 9 10self.addEventListener('install', () => { 11 self.skipWaiting(); 12}); 13 14self.addEventListener('activate', event => { 15 event.waitUntil( 16 (async () => { 17 const keys = await caches.keys(); 18 await Promise.all(keys.filter(key => key !== CACHE_NAME).map(key => caches.delete(key))); 19 await self.clients.claim(); 20 })(), 21 ); 22}); 23 24// Content-hashing is a PRODUCTION property. A dev server serves mutable chunks under this same 25// prefix, so caching them first pins whatever was there: a prod build run once on a dev port 26// left the worker answering that origin's dev chunks from the prod bundle, and the page ran new 27// code against an old module until the worker was unregistered by hand (2026-08-30). 28// 29// Reads through an absent `self.location`, because clepit's suite evaluates this file in a fake 30// scope that has none and an unguarded read threw there on every test in it. 31const devHost = (self.location && self.location.hostname) || ''; 32const isDevOrigin = devHost === 'localhost' || devHost === '127.0.0.1' || devHost.endsWith('.localhost'); 33 34const isImmutableAsset = url => !isDevOrigin && url.pathname.startsWith('/_next/static/'); 35const isImage = url => /\.(png|jpe?g|gif|webp|avif|svg|ico)$/.test(url.pathname); 36 37async function cacheFirst(request) { 38 const cache = await caches.open(CACHE_NAME); 39 const cached = await cache.match(request); 40 if (cached) return cached; 41 const response = await fetch(request); 42 if (response.ok) cache.put(request, response.clone()); 43 return response; 44} 45 46async function networkFirst(request) { 47 const cache = await caches.open(CACHE_NAME); 48 try { 49 const response = await fetch(request); 50 if (response.ok) cache.put(request, response.clone()); 51 return response; 52 } catch (error) { 53 const cached = await cache.match(request); 54 if (cached) return cached; 55 throw error; 56 } 57} 58 59async function staleWhileRevalidate(request) { 60 const cache = await caches.open(CACHE_NAME); 61 const cached = await cache.match(request); 62 const fetchPromise = fetch(request).then(response => { 63 if (response.ok) cache.put(request, response.clone()); 64 return response; 65 }); 66 return cached || fetchPromise; 67} 68 69self.addEventListener('fetch', event => { 70 const { request } = event; 71 if (request.method !== 'GET') return; 72 73 const url = new URL(request.url); 74 if (url.origin !== self.location.origin) return; 75 76 if (request.mode === 'navigate') { 77 event.respondWith(networkFirst(request)); 78 return; 79 } 80 81 if (isImmutableAsset(url)) { 82 event.respondWith(cacheFirst(request)); 83 return; 84 } 85 86 if (isImage(url)) { 87 event.respondWith(staleWhileRevalidate(request)); 88 } 89});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.