1// PWA Service Worker 2// Version: v1.0.0-1790863654 3const CACHE_NAME = 'v1.0.0-1790863654'; 4const OFFLINE_PAGE = 'https://utesinternationallounge.com/pwa-offline.html'; 5const HOME_URL = 'https://utesinternationallounge.com/'; 6 7// URLs to precache 8const PRECACHE_URLS = ["https:\/\/utesinternationallounge.com\/","https:\/\/utesinternationallounge.com\/pwa-offline.html"]; 9 10// Cache timeout in ms 11const CACHE_TIMEOUT = 3000; 12 13// Install event - precache essential files 14self.addEventListener('install', event => { 15 console.log('[PWA] Service Worker installing...'); 16 17 event.waitUntil( 18 caches.open(CACHE_NAME) 19 .then(cache => { 20 console.log('[PWA] Precaching files'); 21 return cache.addAll(PRECACHE_URLS); 22 }) 23 .then(() => self.skipWaiting()) 24 .catch(error => { 25 console.error('[PWA] Precaching failed:', error); 26 }) 27 ); 28}); 29 30// Activate event - clean up old caches 31self.addEventListener('activate', event => { 32 console.log('[PWA] Service Worker activating...'); 33 34 event.waitUntil( 35 caches.keys() 36 .then(cacheNames => { 37 return Promise.all( 38 cacheNames 39 .filter(cacheName => cacheName !== CACHE_NAME) 40 .map(cacheName => { 41 console.log('[PWA] Deleting old cache:', cacheName); 42 return caches.delete(cacheName); 43 }) 44 ); 45 }) 46 .then(() => self.clients.claim()) 47 ); 48}); 49 50// Fetch event - handle requests with different strategies 51self.addEventListener('fetch', event => { 52 const { request } = event; 53 const url = new URL(request.url); 54 55 // Skip non-GET requests 56 if (request.method !== 'GET') { 57 return; 58 } 59 60 // Skip cross-origin requests 61 if (url.origin !== location.origin) { 62 return; 63 } 64 65 // Skip admin, login, and API requests 66 if ( 67 url.pathname.startsWith('/wp-admin/') || 68 url.pathname.startsWith('/wp-login.php') || 69 url.pathname.startsWith('/wp-json/') || 70 url.searchParams.has('rest_route') 71 ) { 72 return; 73 } 74 75 // Determine cache strategy based on resource type 76 if (isImage(url)) { 77 event.respondWith(cacheFirstStrategy(request)); 78 } else if (isStaticAsset(url)) { 79 event.respondWith(cacheFirstStrategy(request)); 80 } else if (isNavigationRequest(request)) { 81 event.respondWith(networkFirstStrategy(request)); 82 } else { 83 event.respondWith(networkFirstStrategy(request)); 84 } 85}); 86 87// Check if request is for an image 88function isImage(url) { 89 return /\.(jpg|jpeg|png|gif|webp|svg|ico)$/i.test(url.pathname); 90} 91 92// Check if request is for a static asset 93function isStaticAsset(url) { 94 return /\.(css|js|woff|woff2|ttf|eot)$/i.test(url.pathname); 95} 96 97// Check if request is a navigation request 98function isNavigationRequest(request) { 99 return request.mode === 'navigate' || 100 (request.method === 'GET' && request.headers.get('accept').includes('text/html')); 101} 102 103// Network First Strategy - Try network, fallback to cache 104async function networkFirstStrategy(request) { 105 try { 106 // Try to fetch from network with timeout 107 const networkResponse = await fetchWithTimeout(request, CACHE_TIMEOUT); 108 109 // Cache successful response 110 if (networkResponse && networkResponse.ok) { 111 const cache = await caches.open(CACHE_NAME); 112 cache.put(request, networkResponse.clone()); 113 } 114 115 return networkResponse; 116 } catch (error) { 117 console.log('[PWA] Network first failed, trying cache:', error); 118 119 // Try to get from cache 120 const cachedResponse = await caches.match(request); 121 122 if (cachedResponse) { 123 return cachedResponse; 124 } 125 126 // If it's a navigation request and we have nothing, show offline page 127 if (isNavigationRequest(request)) { 128 const offlineResponse = await caches.match(OFFLINE_PAGE); 129 if (offlineResponse) { 130 return offlineResponse; 131 } 132 } 133 134 // Return a basic offline response 135 return new Response('Offline - No cached version available', { 136 status: 503, 137 statusText: 'Service Unavailable', 138 headers: new Headers({ 139 'Content-Type': 'text/plain' 140 }) 141 }); 142 } 143} 144 145// Cache First Strategy - Try cache, fallback to network 146async function cacheFirstStrategy(request) { 147 const cachedResponse = await caches.match(request); 148 149 if (cachedResponse) { 150 // Update cache in background 151 fetchAndCache(request); 152 return cachedResponse; 153 } 154 155 try { 156 const networkResponse = await fetch(request); 157 158 if (networkResponse && networkResponse.ok) { 159 const cache = await caches.open(CACHE_NAME); 160 cache.put(request, networkResponse.clone()); 161 } 162 163 return networkResponse; 164 } catch (error) { 165 console.log('[PWA] Cache first network fallback failed:', error); 166 167 // Return offline page for navigation requests 168 if (isNavigationRequest(request)) { 169 const offlineResponse = await caches.match(OFFLINE_PAGE); 170 if (offlineResponse) { 171 return offlineResponse; 172 } 173 } 174 175 return new Response('Offline', { status: 503 }); 176 } 177} 178 179// Fetch with timeout 180function fetchWithTimeout(request, timeout) { 181 return Promise.race([ 182 fetch(request), 183 new Promise((_, reject) => 184 setTimeout(() => reject(new Error('Network timeout')), timeout) 185 ) 186 ]); 187} 188 189// Fetch and cache in background 190async function fetchAndCache(request) { 191 try { 192 const response = await fetch(request); 193 194 if (response && response.ok) { 195 const cache = await caches.open(CACHE_NAME); 196 cache.put(request, response.clone()); 197 } 198 } catch (error) {
199 console.log('[PWA] Background fetch failed:', error); 200 } 201} 202 203// Handle messages from clients 204self.addEventListener('message', event => { 205 if (event.data && event.data.type === 'SKIP_WAITING') { 206 self.skipWaiting(); 207 } 208 209 if (event.data && event.data.type === 'CACHE_URLS') { 210 event.waitUntil( 211 caches.open(CACHE_NAME) 212 .then(cache => cache.addAll(event.data.urls)) 213 ); 214 } 215 216 if (event.data && event.data.type === 'CLEAR_CACHE') { 217 event.waitUntil( 218 caches.keys() 219 .then(cacheNames => Promise.all( 220 cacheNames.map(cacheName => caches.delete(cacheName)) 221 )) 222 ); 223 } 224}); 225 226// Background sync for WooCommerce 227self.addEventListener('sync', event => { 228 if (event.tag === 'sync-cart') { 229 event.waitUntil(syncCart()); 230 } 231 232 if (event.tag === 'sync-orders') { 233 event.waitUntil(syncOrders()); 234 } 235}); 236 237// Sync cart data 238async function syncCart() { 239 try { 240 const cartData = await getCartFromIndexedDB(); 241 if (cartData) { 242 await fetch(HOME_URL + 'wp-json/wc/store/cart', { 243 method: 'POST', 244 headers: { 'Content-Type': 'application/json' }, 245 body: JSON.stringify(cartData) 246 }); 247 } 248 } catch (error) { 249 console.error('[PWA] Cart sync failed:', error); 250 } 251} 252 253// Sync orders 254async function syncOrders() { 255 // Implement order sync if needed 256 console.log('[PWA] Syncing orders...'); 257} 258 259// IndexedDB helper (simplified) 260async function getCartFromIndexedDB() { 261 // This would interface with your IndexedDB implementation 262 return null; 263} 264 265// Push notification event 266self.addEventListener('push', event => { 267 const options = { 268 body: event.data ? event.data.text() : 'New notification', 269 icon: '', 270 badge: '', 271 vibrate: [200, 100, 200], 272 data: { 273 dateOfArrival: Date.now(), 274 primaryKey: 1 275 } 276 }; 277 278 event.waitUntil( 279 self.registration.showNotification('Ute\'s International Lounge & Academy', options) 280 ); 281}); 282 283// Notification click event 284self.addEventListener('notificationclick', event => { 285 event.notification.close(); 286 287 event.waitUntil( 288 clients.openWindow(HOME_URL) 289 ); 290}); 291 292console.log('[PWA] Service Worker loaded successfully');
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.