89 lines
3.0 KiB
JavaScript
89 lines
3.0 KiB
JavaScript
const BASE = new URL('./', self.location.href).pathname;
|
|
importScripts(BASE + 'static/background-issue-sync.js');
|
|
const CACHE = 'stackchain-dashboard-shell-v12';
|
|
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
|
|
const SHELL = [
|
|
BASE,
|
|
BASE + 'manifest.webmanifest',
|
|
BASE + 'static/icons/stackchain-192.png',
|
|
BASE + 'static/icons/stackchain-512.png',
|
|
BASE + 'static/markdown.js',
|
|
BASE + 'static/commands.js',
|
|
BASE + 'static/search-preview.js',
|
|
BASE + 'static/widgets.js',
|
|
BASE + 'static/drafts.js',
|
|
BASE + 'static/outbox-coordinator.js',
|
|
BASE + 'static/issue-outbox.js',
|
|
BASE + 'static/authored-outbox.js',
|
|
BASE + 'static/offline-work.js',
|
|
BASE + 'static/my-work.js',
|
|
BASE + 'static/pick-work.js',
|
|
BASE + 'static/conversation.js',
|
|
BASE + 'static/issue-sheet.js',
|
|
BASE + 'static/create-issue-sheet.js',
|
|
BASE + 'static/pull-sheet.js',
|
|
BASE + 'static/review-sheet.js',
|
|
BASE + 'static/work-route.js',
|
|
BASE + 'static/context-poller.js',
|
|
BASE + 'static/mobile-task-dock.js',
|
|
BASE + 'static/background-issue-sync.js',
|
|
];
|
|
|
|
async function fetchJson(url, options) {
|
|
const response = await fetch(new URL(url, self.location.origin), options);
|
|
const payload = await response.json().catch(() => ({}));
|
|
if (!response.ok) {
|
|
const error = new Error(payload.error || payload.detail || 'Background issue delivery failed.');
|
|
error.status = response.status;
|
|
throw error;
|
|
}
|
|
return payload;
|
|
}
|
|
|
|
const issueSync = self.__issueSync || createBackgroundIssueSync({
|
|
store: createIssueSyncStore(), fetchJson, base: BASE,
|
|
});
|
|
|
|
self.addEventListener('install', event => {
|
|
event.waitUntil(caches.open(CACHE).then(cache => cache.addAll(SHELL)).then(() => self.skipWaiting()));
|
|
});
|
|
|
|
self.addEventListener('activate', event => {
|
|
event.waitUntil(caches.keys().then(keys => Promise.all(
|
|
keys.filter(key => key.startsWith('stackchain-dashboard-') && key !== CACHE)
|
|
.map(key => caches.delete(key))
|
|
)).then(() => self.clients.claim()));
|
|
});
|
|
|
|
self.addEventListener('sync', event => {
|
|
if (event.tag === 'stackchain-issue-outbox-v1') event.waitUntil(issueSync.flush());
|
|
});
|
|
|
|
self.addEventListener('fetch', event => {
|
|
const request = event.request;
|
|
if (request.method !== 'GET' || request.url.includes('/api/')) return;
|
|
const url = new URL(request.url);
|
|
if (url.origin !== self.location.origin || !url.pathname.startsWith(BASE)) return;
|
|
if (request.mode === 'navigate') {
|
|
event.respondWith(
|
|
fetch(request).then(async response => {
|
|
const cache = await caches.open(CACHE);
|
|
if (response.ok) {
|
|
await cache.put(BASE, response.clone());
|
|
} else if (OUTAGE_STATUSES.has(response.status)) {
|
|
const cached = await cache.match(BASE);
|
|
if (cached) return cached;
|
|
}
|
|
return response;
|
|
}).catch(async () => {
|
|
const cache = await caches.open(CACHE);
|
|
return cache.match(BASE);
|
|
})
|
|
);
|
|
return;
|
|
}
|
|
if (url.origin === self.location.origin && SHELL.includes(url.pathname)) {
|
|
event.respondWith(caches.match(request).then(cached => cached || fetch(request)));
|
|
}
|
|
});
|