Edoruin's picture
fix: force PWA update and cache busting with v4
9557c6b
/**
* Service Worker for PWA
* Handles offline functionality and caching
*/
const CACHE_NAME = 'mipesca-v2';
const STATIC_CACHE = [
'./',
'index.html',
'css/styles.css',
'js/app.js',
'js/db.js',
'js/geolocation.js',
'js/api.js',
'js/sync.js',
'js/components/home.js',
'js/components/species-selector.js',
'js/components/capture-form.js',
'js/components/confirmation.js',
'js/components/history.js',
'js/components/info.js',
'manifest.json',
'https://unpkg.com/dexie@3.2.4/dist/dexie.min.js'
];
// Install event - cache static assets
self.addEventListener('install', (event) => {
console.log('Service Worker installing...');
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('Caching static assets');
return cache.addAll(STATIC_CACHE);
})
.then(() => self.skipWaiting())
);
});
// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
console.log('Service Worker activating...');
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
console.log('Deleting old cache:', cacheName);
return caches.delete(cacheName);
}
})
);
}).then(() => self.clients.claim())
);
});
// Fetch event - serve from cache, fallback to network
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);
// API requests - network first, then cache
if (url.pathname.startsWith('/api/')) {
event.respondWith(
fetch(request)
.then((response) => {
// Clone response to cache it
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseClone);
});
return response;
})
.catch(() => {
// If network fails, try cache
return caches.match(request);
})
);
return;
}
// Static assets - cache first, then network
event.respondWith(
caches.match(request)
.then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(request)
.then((response) => {
// Don't cache non-successful responses
if (!response || response.status !== 200 || response.type === 'error') {
return response;
}
// Clone response to cache it
const responseClone = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseClone);
});
return response;
});
})
.catch(() => {
// Return offline page if available
if (request.mode === 'navigate') {
return caches.match('/index.html');
}
})
);
});
// Background sync for captures
self.addEventListener('sync', (event) => {
if (event.tag === 'sync-captures') {
console.log('Background sync triggered');
event.waitUntil(
// Notify clients to sync
self.clients.matchAll().then((clients) => {
clients.forEach((client) => {
client.postMessage({
type: 'BACKGROUND_SYNC',
action: 'sync-captures'
});
});
})
);
}
});