Files
MP-Server/web/service-worker.js
T

91 lines
2.8 KiB
JavaScript
Raw Normal View History

// MacroPad PWA Service Worker
const CACHE_NAME = 'macropad-v4';
const ASSETS_TO_CACHE = [
'/',
'/static/css/styles.css',
'/static/js/app.js',
'/static/icons/icon-192.png',
'/static/icons/icon-512.png',
'/manifest.json'
];
// Install event - pre-cache the app shell
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('Caching app assets');
return cache.addAll(ASSETS_TO_CACHE);
})
.then(() => self.skipWaiting())
);
});
// Activate event - clean old caches
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME)
.map((name) => caches.delete(name))
);
}).then(() => self.clients.claim())
);
});
// Network-first for navigations + app code so deployed fixes reach clients.
async function networkFirst(request) {
const cache = await caches.open(CACHE_NAME);
try {
const networkResponse = await fetch(request);
if (networkResponse && networkResponse.status === 200 && networkResponse.type === 'basic') {
cache.put(request, networkResponse.clone());
}
return networkResponse;
} catch (err) {
const cached = await cache.match(request);
if (cached) {
return cached;
}
// Offline fallback for navigations: serve the cached shell.
if (request.mode === 'navigate') {
const shell = await cache.match('/');
if (shell) {
return shell;
}
}
return new Response('Offline', {
status: 503,
statusText: 'Offline',
headers: { 'Content-Type': 'text/plain' }
});
}
}
self.addEventListener('fetch', (event) => {
const request = event.request;
// Only handle GET; let the browser deal with POST/PUT/DELETE directly.
if (request.method !== 'GET') {
return;
}
const url = new URL(request.url);
// API requests always go to the network; never serve stale data.
// Return a synthetic offline JSON response instead of an unhandled undefined.
if (url.pathname.startsWith('/api/')) {
event.respondWith(
fetch(request).catch(() => new Response(
JSON.stringify({ error: 'offline', detail: 'Network unavailable' }),
{ status: 503, headers: { 'Content-Type': 'application/json' } }
))
);
return;
}
// Navigations and static app assets: network-first with cache fallback.
event.respondWith(networkFirst(request));
});