zenith-frontend / service-worker.js
teoat's picture
Upload folder using huggingface_hub
7ee531a verified
// Service Worker for Zenith Fraud Detection Platform
// Provides offline capability and performance optimization
const CACHE_VERSION = 'v1.0.0';
const CACHE_NAME = `zenith-cache-${CACHE_VERSION}`;
const OFFLINE_URL = '/offline.html';
// Assets to cache on install
const STATIC_ASSETS = [
'/',
'/offline.html',
'/index.html',
'/manifest.json',
'/favicon.ico',
];
// Install event - cache static assets
self.addEventListener('install', (event) => {
console.log('[Service Worker] Installing...');
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[Service Worker] Caching static assets');
return cache.addAll(STATIC_ASSETS);
})
.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('[Service Worker] Deleting old cache:', cacheName);
return caches.delete(cacheName);
}
})
);
})
.then(() => self.clients.claim())
);
});
// Fetch event - network first, fallback to cache
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);
// Skip cross-origin requests
if (url.origin !== location.origin) {
return;
}
// API requests - network only (no cache)
if (url.pathname.startsWith('/api/')) {
event.respondWith(
fetch(request).catch(() => {
return new Response(
JSON.stringify({ error: 'Offline - API unavailable' }),
{
status: 503,
headers: { 'Content-Type': 'application/json' }
}
);
})
);
return;
}
// Static assets - cache first, fallback to network
if (request.destination === 'script' ||
request.destination === 'style' ||
request.destination === 'font' ||
request.destination === 'image') {
event.respondWith(
caches.match(request)
.then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(request).then((response) => {
// Cache successful responses
if (response.status === 200) {
const responseToCache = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseToCache);
});
}
return response;
});
})
);
return;
}
// HTML pages - network first, fallback to cache, then offline page
event.respondWith(
fetch(request)
.then((response) => {
// Cache successful HTML responses
if (response.status === 200 && request.destination === 'document') {
const responseToCache = response.clone();
caches.open(CACHE_NAME).then((cache) => {
cache.put(request, responseToCache);
});
}
return response;
})
.catch(() => {
return caches.match(request)
.then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
// Return offline page for navigation requests
if (request.destination === 'document') {
return caches.match(OFFLINE_URL);
}
});
})
);
});
// Background sync for offline actions
self.addEventListener('sync', (event) => {
console.log('[Service Worker] Background sync:', event.tag);
if (event.tag === 'sync-offline-actions') {
event.waitUntil(syncOfflineActions());
}
});
async function syncOfflineActions() {
// Get offline actions from IndexedDB (handled by main app)
// This is a placeholder - actual implementation in useOfflineQueue
console.log('[Service Worker] Syncing offline actions...');
}
// Push notifications (future enhancement)
self.addEventListener('push', (event) => {
const data = event.data ? event.data.json() : {};
const options = {
body: data.body || 'New fraud alert detected',
icon: '/icon-192.png',
badge: '/badge-72.png',
vibrate: [200, 100, 200],
data: data,
actions: [
{ action: 'view', title: 'View Alert' },
{ action: 'dismiss', title: 'Dismiss' }
]
};
event.waitUntil(
self.registration.showNotification(data.title || 'Zenith Alert', options)
);
});
// Notification click handler
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'view') {
event.waitUntil(
clients.openWindow(event.notification.data.url || '/')
);
}
});
// Message handler for cache updates
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
if (event.data && event.data.type === 'CACHE_URLS') {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(event.data.urls);
})
);
}
});
console.log('[Service Worker] Loaded successfully');