PageSourceSearch

https://whisper-chat-gpt.lovable.app/service-worker.js

js whisper-chat-gpt.lovable.app collected 2026-10-03 03:46:10 UTC 4,113 bytes, 150 lines download raw bytes

1
2// Service Worker for Whisper Chat
3const CACHE_NAME = 'whisper-chat-v1.2'; // Updated version
4const RUNTIME = 'runtime';
5const SECURITY_HEADERS = {
6  'Content-Security-Policy': "default-src 'self'",
7  'X-Content-Type-Options': 'nosniff',
8  'X-Frame-Options': 'DENY',
9  'Referrer-Policy': 'no-referrer'
10};
11
12const urlsToCache = [
13  '/',
14  '/index.html',
15  '/manifest.json',
16  '/favicon.ico'
17];
18
19// Force HTTPS for all requests in production
20const secureRequest = (request) => {
21  // Skip localhost for development
22  if (self.location.hostname === 'localhost') {
23    return request;
24  }
25  
26  // Check if the URL is HTTP and not HTTPS
27  const url = new URL(request.url);
28  if (url.protocol === 'http:' && url.hostname !== 'localhost') {
29    // Replace with HTTPS version of the same URL
30    url.protocol = 'https:';
31    return new Request(url.toString(), request);
32  }
33  
34  return request;
35};
36
37// Install event - cache basic resources
38self.addEventListener('install', event => {
39  // Skip waiting to avoid blocking the app
40  self.skipWaiting();
41  
42  event.waitUntil(
43    caches.open(CACHE_NAME)
44      .then(cache => {
45        console.log('Cache opened');
46        return cache.addAll(urlsToCache);
47      })
48      .catch(error => {
49        console.error('Error during service worker install:', error);
50      })
51  );
52});
53
54// Activate event - clean up old caches and take control
55self.addEventListener('activate', event => {
56  // Take control immediately
57  event.waitUntil(self.clients.claim());
58  
59  // Clean up old caches
60  event.waitUntil(
61    caches.keys().then(cacheNames => {
62      return Promise.all(
63        cacheNames.map(cacheName => {
64          if (cacheName !== CACHE_NAME) {
65            console.log('Deleting old cache:', cacheName);
66            return caches.delete(cacheName);
67          }
68        })
69      );
70    })
71  );
72});
73
74// Helper function to add security headers to response
75const addSecurityHeaders = (response) => {
76  if (!response || !response.headers) {
77    return response;
78  }
79  
80  // Clone the response to make it mutable
81  const responseWithHeaders = response.clone();
82  const headers = new Headers(responseWithHeaders.headers);
83  
84  // Add security headers
85  Object.keys(SECURITY_HEADERS).forEach(key => {
86    headers.set(key, SECURITY_HEADERS[key]);
87  });
88  
89  // Create new Response with the enhanced headers
90  return new Response(responseWithHeaders.body, {
91    status: responseWithHeaders.status,
92    statusText: responseWithHeaders.statusText,
93    headers: headers
94  });
95};
96
97// Simplified fetch event handler to prevent blocking app loading
98self.addEventListener('fetch', event => {
99  // Only handle GET requests
100  if (event.request.method !== 'GET') {
101    return;
102  }
103
104  // Try to serve from cache first, fallback to network
105  event.respondWith(
106    caches.match(event.request)
107      .then(response => {
108        if (response) {
109          return response;
110        }
111        
112        // Try network and cache result
113        return fetch(event.request)
114          .then(networkResponse => {
115            if (!networkResponse || networkResponse.status !== 200) {
116              return networkResponse;
117            }
118            
119            // Cache a copy of the response
120            const responseToCache = networkResponse.clone();
121            
122            caches.open(RUNTIME)
123              .then(cache => {
124                cache.put(event.request, responseToCache);
125              })
126              .catch(() => {
127                // Fail silently if cache put fails
128              });
129            
130            return networkResponse;
131          })
132          .catch(() => {
133            // Fallback for navigation requests
134            if (event.request.mode === 'navigate') {
135              return caches.match('/index.html');
136            }
137            
138            // Let the error bubble up for other requests
139            return new Response('Network error', { status: 408 });
140          });
141      })
142  );
143});
144
145// Add event listener for messages from clients
146self.addEventListener('message', event => {
147  if (event.data && event.data.type === 'SKIP_WAITING') {
148    self.skipWaiting();
149  }
150});

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.