AeThex-Connect/packages/web/public/service-worker.ts
2026-01-10 08:00:59 +00:00

171 lines
4.5 KiB
TypeScript

import { precacheAndRoute } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { NetworkFirst, CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { BackgroundSyncPlugin } from 'workbox-background-sync';
import { ExpirationPlugin } from 'workbox-expiration';
declare const self: ServiceWorkerGlobalScope;
// Precache all build assets
precacheAndRoute(self.__WB_MANIFEST);
// API requests - Network first, cache fallback
registerRoute(
({ url }) => url.pathname.startsWith('/api/'),
new NetworkFirst({
cacheName: 'api-cache',
plugins: [
new ExpirationPlugin({
maxEntries: 50,
maxAgeSeconds: 5 * 60, // 5 minutes
}),
],
})
);
// Images - Cache first
registerRoute(
({ request }) => request.destination === 'image',
new CacheFirst({
cacheName: 'images',
plugins: [
new ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
}),
],
})
);
// Fonts - Cache first
registerRoute(
({ request }) => request.destination === 'font',
new CacheFirst({
cacheName: 'fonts',
plugins: [
new ExpirationPlugin({
maxEntries: 20,
maxAgeSeconds: 365 * 24 * 60 * 60, // 1 year
}),
],
})
);
// Background sync for failed POST requests
const bgSyncPlugin = new BackgroundSyncPlugin('message-queue', {
maxRetentionTime: 24 * 60, // Retry for 24 hours
});
registerRoute(
({ url }) => url.pathname.startsWith('/api/messages'),
new NetworkFirst({
plugins: [bgSyncPlugin],
}),
'POST'
);
// Push notifications
self.addEventListener('push', (event) => {
const data = event.data?.json() || {};
const options: NotificationOptions = {
body: data.body || 'You have a new message',
icon: data.icon || '/icon-192.png',
badge: '/badge-96.png',
tag: data.tag || 'notification',
data: data.data || {},
actions: data.actions || [
{ action: 'open', title: 'Open' },
{ action: 'dismiss', title: 'Dismiss' },
],
vibrate: [200, 100, 200],
requireInteraction: data.requireInteraction || false,
};
event.waitUntil(
self.registration.showNotification(data.title || 'AeThex Connect', options)
);
});
// Notification click handler
self.addEventListener('notificationclick', (event) => {
event.notification.close();
if (event.action === 'open' || !event.action) {
const urlToOpen = event.notification.data?.url || '/';
event.waitUntil(
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
// Check if there's already a window open
for (const client of clientList) {
if (client.url === urlToOpen && 'focus' in client) {
return client.focus();
}
}
// Open new window if none exists
if (self.clients.openWindow) {
return self.clients.openWindow(urlToOpen);
}
})
);
}
});
// Handle notification actions (reply, etc.)
self.addEventListener('notificationclick', (event) => {
if (event.action === 'reply' && event.reply) {
// Send reply via background sync
event.waitUntil(
fetch('/api/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
conversationId: event.notification.data.conversationId,
content: event.reply,
contentType: 'text',
}),
})
);
}
});
// Periodic background sync (for checking new messages when offline)
self.addEventListener('periodicsync', (event: any) => {
if (event.tag === 'check-messages') {
event.waitUntil(checkForNewMessages());
}
});
async function checkForNewMessages() {
try {
const response = await fetch('/api/messages/unread');
const data = await response.json();
if (data.count > 0) {
self.registration.showNotification('New Messages', {
body: `You have ${data.count} unread messages`,
icon: '/icon-192.png',
badge: '/badge-96.png',
tag: 'unread-messages',
});
}
} catch (error) {
console.error('Error checking messages:', error);
}
}
// Skip waiting and claim clients immediately
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim());
});
// Log service worker version
console.log('AeThex Connect Service Worker v1.0.0');