web-terminal-server
Version:
Professional web-based terminal server with persistent sessions, live sharing, smart port detection, Cloudflare tunnels, and full CLI support
95 lines (84 loc) • 2.36 kB
JavaScript
// Service Worker for Terminal Grid PWA
const CACHE_NAME = 'terminal-grid-v1.5.1';
const urlsToCache = [
'/',
'/index.html',
'/ports',
'/ports.html',
'/monitor',
'/monitor.html',
'/manifest.json',
'/icons/icon.svg'
];
// Install event - cache resources
self.addEventListener('install', (event) => {
console.log('[SW] Installing...');
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[SW] Caching app shell');
return cache.addAll(urlsToCache);
})
.then(() => self.skipWaiting())
);
});
// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
console.log('[SW] Activating...');
event.waitUntil(
caches.keys()
.then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
console.log('[SW] Deleting old cache:', cacheName);
return caches.delete(cacheName);
}
})
);
})
.then(() => self.clients.claim())
);
});
// Fetch event - serve from cache, fallback to network
self.addEventListener('fetch', (event) => {
// Skip WebSocket and API calls
if (event.request.url.includes('/socket.io/') ||
event.request.url.includes('/api/')) {
return;
}
event.respondWith(
caches.match(event.request)
.then((response) => {
// Cache hit - return response
if (response) {
return response;
}
// Clone the request
const fetchRequest = event.request.clone();
return fetch(fetchRequest).then((response) => {
// Check if valid response
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// Clone the response
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then((cache) => {
cache.put(event.request, responseToCache);
});
return response;
});
})
.catch(() => {
// Return offline page if available
return caches.match('/');
})
);
});
// Handle messages from clients
self.addEventListener('message', (event) => {
if (event.data.action === 'skipWaiting') {
self.skipWaiting();
}
});