// Generated by render_books.py -- do not edit by hand. // // STRATEGY decides what a same-origin GET does: // // network-first ask the network, fall back to the cache when it fails. // Offline, fetch rejects immediately, so the fallback is // effectively instant -- the only cost is one round trip // while online, and you never see a stale page. // cache-first answer from the cache the moment there is a hit. Fastest // possible load, but a rebuild needs two reloads to appear. // // Either way every response that arrives is written back to the cache, so the // offline copy stays current, and a new build changes VERSION, dropping the // caches belonging to older builds. const STRATEGY = 'network-first'; const NETWORK_TIMEOUT_MS = 3000; const VERSION = 'c5d29c3cdf15'; const CACHE = 'bible-' + VERSION; const ASSETS = [ "./", "./1CH.html", "./1CO.html", "./1ES.html", "./1JN.html", "./1KI.html", "./1MA.html", "./1PE.html", "./1SA.html", "./1TH.html", "./1TI.html", "./2CH.html", "./2CO.html", "./2ES.html", "./2JN.html", "./2KI.html", "./2MA.html", "./2PE.html", "./2SA.html", "./2TH.html", "./2TI.html", "./3JN.html", "./3MA.html", "./4MA.html", "./ACT.html", "./AMO.html", "./BAR.html", "./COL.html", "./DAG.html", "./DAN.html", "./DEU.html", "./ECC.html", "./EPH.html", "./ESG.html", "./EST.html", "./EXO.html", "./EZK.html", "./EZR.html", "./FRT.html", "./GAL.html", "./GEN.html", "./GLO.html", "./HAB.html", "./HAG.html", "./HEB.html", "./HOS.html", "./ISA.html", "./JAS.html", "./JDG.html", "./JDT.html", "./JER.html", "./JHN.html", "./JOB.html", "./JOL.html", "./JON.html", "./JOS.html", "./JUD.html", "./LAM.html", "./LEV.html", "./LUK.html", "./MAL.html", "./MAN.html", "./MAT.html", "./MIC.html", "./MRK.html", "./NAM.html", "./NEH.html", "./NUM.html", "./OBA.html", "./PHM.html", "./PHP.html", "./PRO.html", "./PS2.html", "./PSA.html", "./REV.html", "./ROM.html", "./RUT.html", "./SIR.html", "./SNG.html", "./TIT.html", "./TOB.html", "./WIS.html", "./ZEC.html", "./ZEP.html", "./app.js", "./bible.css", "./icons/apple-touch-icon.png", "./icons/icon-192.png", "./icons/icon-512.png", "./index.html", "./manifest.webmanifest" ]; self.addEventListener('install', (event) => { event.waitUntil((async () => { const cache = await caches.open(CACHE); // Added one at a time rather than addAll(): addAll is atomic, so a single // failed asset would leave the app with no offline copy at all. let failed = 0; await Promise.all(ASSETS.map((url) => cache.add(new Request(url, { cache: 'reload' })).catch(() => { failed++; }))); if (failed) console.warn('precache: ' + failed + ' of ' + ASSETS.length + ' failed'); await self.skipWaiting(); })()); }); self.addEventListener('activate', (event) => { event.waitUntil((async () => { const keys = await caches.keys(); await Promise.all(keys .filter((k) => k.startsWith('bible-') && k !== CACHE) .map((k) => caches.delete(k))); await self.clients.claim(); })()); }); self.addEventListener('fetch', (event) => { const req = event.request; if (req.method !== 'GET') return; if (new URL(req.url).origin !== location.origin) return; event.respondWith(respond(event)); }); // Aborted rather than raced, so a hung request is actually torn down instead // of leaking while the cache answers. async function fromNetwork(req) { const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), NETWORK_TIMEOUT_MS); try { return await fetch(req, { signal: controller.signal }); } finally { clearTimeout(timer); } } function cached(req) { return caches.match(req, { ignoreSearch: true }); } async function respond(event) { const req = event.request; if (STRATEGY === 'cache-first') { const hit = await cached(req); if (hit) return hit; } try { const res = await fromNetwork(req); if (res && res.ok && res.type === 'basic') { const copy = res.clone(); // Not awaited: the response should not wait on the cache write. event.waitUntil(caches.open(CACHE).then((c) => c.put(req, copy))); } return res; } catch (err) { const hit = await cached(req); if (hit) return hit; // Offline and never cached. Navigations get the index rather than the // browser's error page; anything else genuinely fails. if (req.mode === 'navigate') { const index = await cached('./index.html'); if (index) return index; } throw err; } }