template-saas-frontend-v2/public/sw.js
rckrdmrd eb95d0e276 Initial commit - Frontend de template-saas migrado desde monorepo
Migración desde workspace-v2/projects/template-saas/apps/frontend
Este repositorio es parte del estándar multi-repo v2

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:07:16 -06:00

157 lines
4.0 KiB
JavaScript

// Service Worker for Push Notifications
// Template SaaS v2.0
const CACHE_NAME = 'template-saas-v1';
// Install event
self.addEventListener('install', (event) => {
console.log('[SW] Installing service worker...');
self.skipWaiting();
});
// Activate event
self.addEventListener('activate', (event) => {
console.log('[SW] Service worker activated');
event.waitUntil(self.clients.claim());
});
// Push notification received
self.addEventListener('push', (event) => {
console.log('[SW] Push notification received');
let data = {
title: 'Nueva notificacion',
body: 'Tienes una nueva notificacion',
icon: '/icon-192.png',
badge: '/badge-72.png',
url: '/',
data: {},
};
if (event.data) {
try {
data = { ...data, ...event.data.json() };
} catch (e) {
console.error('[SW] Error parsing push data:', e);
}
}
const options = {
body: data.body,
icon: data.icon || '/icon-192.png',
badge: data.badge || '/badge-72.png',
vibrate: [100, 50, 100],
tag: data.notificationId || 'default',
renotify: true,
requireInteraction: data.requireInteraction || false,
data: {
url: data.url || '/',
notificationId: data.notificationId,
...data.data,
},
actions: data.actions || [
{ action: 'view', title: 'Ver' },
{ action: 'dismiss', title: 'Descartar' },
],
};
event.waitUntil(
self.registration.showNotification(data.title, options)
);
});
// Notification click handler
self.addEventListener('notificationclick', (event) => {
console.log('[SW] Notification clicked:', event.action);
event.notification.close();
if (event.action === 'dismiss') {
return;
}
const url = event.notification.data?.url || '/';
event.waitUntil(
self.clients
.matchAll({ type: 'window', includeUncontrolled: true })
.then((clientList) => {
// Try to find an existing window and navigate
for (const client of clientList) {
if (client.url.includes(self.location.origin) && 'focus' in client) {
return client.focus().then((focusedClient) => {
if (focusedClient && 'navigate' in focusedClient) {
return focusedClient.navigate(url);
}
});
}
}
// If no window found, open a new one
if (self.clients.openWindow) {
return self.clients.openWindow(url);
}
})
);
});
// Notification close handler
self.addEventListener('notificationclose', (event) => {
console.log('[SW] Notification closed');
// Optionally track notification dismissals
const notificationId = event.notification.data?.notificationId;
if (notificationId) {
// Could send analytics here
}
});
// Push subscription change handler
self.addEventListener('pushsubscriptionchange', (event) => {
console.log('[SW] Push subscription changed');
event.waitUntil(
self.registration.pushManager
.subscribe({
userVisibleOnly: true,
applicationServerKey: event.oldSubscription?.options?.applicationServerKey,
})
.then((subscription) => {
// Notify the app about the new subscription
return self.clients.matchAll().then((clients) => {
clients.forEach((client) => {
client.postMessage({
type: 'PUSH_SUBSCRIPTION_CHANGED',
subscription: JSON.stringify(subscription),
});
});
});
})
);
});
// Message handler (for app communication)
self.addEventListener('message', (event) => {
console.log('[SW] Message received:', event.data);
if (event.data?.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Background sync (for offline notifications)
self.addEventListener('sync', (event) => {
console.log('[SW] Background sync:', event.tag);
if (event.tag === 'sync-notifications') {
event.waitUntil(syncNotifications());
}
});
async function syncNotifications() {
// This would sync any pending notification actions
console.log('[SW] Syncing notifications...');
}
console.log('[SW] Service worker loaded');