abinazebinoy's picture
fix(sw.js): bump CACHE version to force clients off the poisoned cache
f4791ec
Raw
History Blame Contribute Delete
3.08 kB
// BharatGraph Service Worker v5
// BUG-28 FIX: API responses were cached indefinitely
// NEW-A5 FIX: host === "hf.space" never matches -- HF uses *.hf.space subdomains
// SW-01 FIX: use relative paths so caching works on GitHub Pages
const CACHE = "bharatgraph-v6";
const STATIC = [
"./",
"./index.html",
"./css/design-system.css",
"./css/components.css",
"./js/router.js",
"./js/api.js",
"./js/components.js",
"./js/graph.js",
"./js/timeline.js",
"./js/evidence_panel.js",
"./js/app.js"
];
self.addEventListener("install", e => {
e.waitUntil(
caches.open(CACHE)
.then(c => c.addAll(STATIC))
.catch(() => {}) // never block install on cache failure
);
self.skipWaiting();
});
self.addEventListener("activate", e => {
e.waitUntil(
caches.keys()
.then(keys => Promise.all(
keys.filter(k => k !== CACHE).map(k => caches.delete(k))
))
.then(() => self.clients.claim())
);
});
self.addEventListener("fetch", e => {
const reqUrl = new URL(e.request.url);
const host = reqUrl.hostname;
const path = reqUrl.pathname;
// NEW-A5 FIX: HuggingFace Spaces run on *.hf.space subdomains.
// The previous check `host === "hf.space"` never matched because the actual
// hostname is e.g. "abinazebinoly-bharatgraph.hf.space" -- use endsWith().
// BUG-28 FIX: all API paths must be network-first, never cached.
const isHfSpace = host.endsWith(".hf.space") || host === "hf.space";
const isApiPath = path.startsWith("/search") ||
path.startsWith("/profile") ||
path.startsWith("/risk") ||
path.startsWith("/graph") ||
path.startsWith("/biography") ||
path.startsWith("/investigate") ||
path.startsWith("/admin") ||
path.startsWith("/stats") ||
path.startsWith("/health") ||
path.startsWith("/ws/") ||
path.startsWith("/runtime") ||
path.startsWith("/multilingual") ||
path.startsWith("/export");
const isLocalApi = host === "localhost" || host === "127.0.0.1";
const isApi = isHfSpace || (isLocalApi && isApiPath);
if (isApi) {
// Network-first: always go to network, fall back to error JSON
e.respondWith(
fetch(e.request).catch(() =>
new Response(
JSON.stringify({ error: "API temporarily unavailable" }),
{ status: 503, headers: { "Content-Type": "application/json" } }
)
)
);
return;
}
// Static assets: cache-first
e.respondWith(
caches.match(e.request).then(cached => {
if (cached) return cached;
return fetch(e.request).then(response => {
if (!response || response.status !== 200 || response.type !== "basic") {
return response;
}
const clone = response.clone();
caches.open(CACHE).then(c => c.put(e.request, clone));
return response;
});
})
);
});