Papure/src/service-worker.ts
2026-09-26 19:13:02 +02:00

61 lines
1.6 KiB
TypeScript

/// <reference types="@sveltejs/kit" />
/// <reference no-default-lib="true"/>
/// <reference lib="esnext" />
/// <reference lib="webworker" />
// Offline-first: the app shell and static assets are cached on install.
// GitHub API calls are never cached (sync needs live data).
import { build, files, version } from '$service-worker';
const sw = self as unknown as ServiceWorkerGlobalScope;
const CACHE = `papure-${version}`;
const ASSETS = [...build, ...files, '/'];
sw.addEventListener('install', (event) => {
event.waitUntil(
caches
.open(CACHE)
.then((c) => c.addAll(ASSETS))
.then(() => sw.skipWaiting())
);
});
sw.addEventListener('activate', (event) => {
event.waitUntil(
caches
.keys()
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
.then(() => sw.clients.claim())
);
});
sw.addEventListener('fetch', (event) => {
const req = event.request;
if (req.method !== 'GET') return;
const url = new URL(req.url);
if (url.origin !== sw.location.origin) return;
// Navigations: network first, fall back to the cached shell (SPA).
if (req.mode === 'navigate') {
event.respondWith(
fetch(req).catch(async () => (await caches.match('/')) ?? Response.error())
);
return;
}
// Assets: cache first (they're versioned or fixed).
event.respondWith(
caches.match(req).then(
(hit) =>
hit ??
fetch(req).then((res) => {
if (res.ok && ASSETS.includes(url.pathname)) {
const copy = res.clone();
void caches.open(CACHE).then((c) => c.put(req, copy));
}
return res;
})
)
);
});