1const CORE_CACHE = "rect-run-core-v3";2const RUNTIME_CACHE = "rect-run-runtime-v3";3const CORE_PATHS = [4 "/",5 "/d",6 "/site.webmanifest",7 "/icon.svg",8 "/icon-192.png",9 "/icon-512.png",10 "/apple-touch-icon.png",11 "/fonts/GeistPixel-Square.woff2",12 "/register-sw.js",13 "/sw.js",14];1516self.addEventListener("install", (event) => {17 event.waitUntil(18 caches.open(CORE_CACHE).then((cache) => cache.addAll(CORE_PATHS)).then(19 () => {20 self.skipWaiting();21 },22 ),23 );24});2526self.addEventListener("activate", (event) => {27 event.waitUntil((async () => {28 const names = await caches.keys();29 await Promise.all(30 names.filter((name) => name !== CORE_CACHE && name !== RUNTIME_CACHE).map(31 (name) => caches.delete(name),32 ),33 );34 await self.clients.claim();35 })());36});3738self.addEventListener("fetch", (event) => {39 const { request } = event;40 if (request.method !== "GET") return;4142 const url = new URL(request.url);43 if (url.origin !== self.location.origin) return;4445 if (request.mode === "navigate") {46 event.respondWith(handleNavigation(request));47 return;48 }4950 if (url.pathname.startsWith("/api/puzzles/")) {51 event.respondWith(networkFirst(request));52 return;53 }5455 event.respondWith(staleWhileRevalidate(request));56});5758async function handleNavigation(request) {59 try {60 const response = await fetch(request);61 const cache = await caches.open(RUNTIME_CACHE);62 cache.put(request, response.clone());63 return response;64 } catch {65 const cached = await caches.match(request);66 if (cached) return cached;67 return caches.match("/");68 }69}7071async function networkFirst(request) {72 const cache = await caches.open(RUNTIME_CACHE);73 try {74 const response = await fetch(request);75 cache.put(request, response.clone());76 return response;77 } catch {78 const cached = await cache.match(request);79 if (cached) return cached;80 throw errorResponse();81 }82}8384async function staleWhileRevalidate(request) {85 const cache = await caches.open(RUNTIME_CACHE);86 const cached = await cache.match(request);87 const networkPromise = fetch(request).then((response) => {88 cache.put(request, response.clone());89 return response;90 }).catch(() => null);9192 return cached ?? await networkPromise ?? errorResponse();93}9495function errorResponse() {96 return new Response("Offline", {97 status: 503,98 statusText: "Offline",99 headers: { "content-type": "text/plain; charset=utf-8" },100 });101}