blob: 89680e98a0d9e4d88ae0905bd1a3840188e8bbe4 [file]
// Service Worker to intercept and serve cached share assets on-demand
const pendingRequests = new Map();
let requestIdCounter = 0;
self.addEventListener('install', (event) => {
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
// Intercept requests matching /share/<32-char-hex-hash>/...
const match = url.pathname.match(/\/share\/([a-f0-9]{32})\/(.*)/);
if (match) {
const hash = match[1];
const filePath = match[2] || 'index.html';
event.respondWith(
caches.open(`share-${hash}`).then((cache) => {
return cache.match(event.request).then((cachedResponse) => {
if (cachedResponse && filePath !== 'index.html' && filePath !== '') {
return cachedResponse;
}
// Request the file from the client window on-demand
return new Promise((resolve, reject) => {
const requestId = ++requestIdCounter;
pendingRequests.set(requestId, { resolve, reject, cache, request: event.request });
// Send message to all matching clients
self.clients.matchAll().then((clients) => {
if (clients.length === 0) {
reject(new Error('No active client window found to fetch file'));
pendingRequests.delete(requestId);
return;
}
clients.forEach((client) => {
client.postMessage({
type: 'FETCH_FILE',
requestId: requestId,
hash: hash,
path: filePath
});
});
});
});
});
})
);
}
});
self.addEventListener('message', (event) => {
if (event.data.type === 'FETCH_FILE_RESPONSE') {
const pending = pendingRequests.get(event.data.requestId);
if (pending) {
pendingRequests.delete(event.data.requestId);
if (event.data.error) {
pending.reject(new Error(event.data.error));
} else {
const mimeType = event.data.mimeType || 'application/octet-stream';
const headers = new Headers({
'content-type': mimeType,
'access-control-allow-origin': '*'
});
const response = new Response(event.data.bytes, { headers });
// Store in cache for next time
pending.cache.put(pending.request, response.clone());
pending.resolve(response);
}
}
}
});