PageSourceSearch

https://www.fedacash.com/sw.js

js fedacash.com collected 2026-10-02 01:30:29 UTC 5,041 bytes, 181 lines download raw bytes

1// Service Worker for FedaCash PWA
2const CACHE_NAME = 'fedacash-v1';
3const RUNTIME_CACHE = 'fedacash-runtime-v1';
4
5// Assets to cache on install
6const PRECACHE_ASSETS = [
7  '/',
8  '/favicon.ico',
9  '/logo-light.png',
10  '/logo-dark.png',
11  '/favicon/android-chrome-192x192.png',
12  '/favicon/android-chrome-512x512.png',
13  '/images/empty-state.png',
14];
15
16// Install event - cache critical assets
17self.addEventListener('install', (event) => {
18  console.log('[Service Worker] Installing...');
19  event.waitUntil(
20    caches.open(CACHE_NAME).then((cache) => {
21      console.log('[Service Worker] Precaching assets');
22      return cache.addAll(PRECACHE_ASSETS);
23    }).then(() => {
24      console.log('[Service Worker] Skip waiting');
25      return self.skipWaiting();
26    })
27  );
28});
29
30// Activate event - clean up old caches
31self.addEventListener('activate', (event) => {
32  console.log('[Service Worker] Activating...');
33  event.waitUntil(
34    caches.keys().then((cacheNames) => {
35      return Promise.all(
36        cacheNames.map((cacheName) => {
37          if (cacheName !== CACHE_NAME && cacheName !== RUNTIME_CACHE) {
38            console.log('[Service Worker] Deleting old cache:', cacheName);
39            return caches.delete(cacheName);
40          }
41        })
42      );
43    }).then(() => {
44      console.log('[Service Worker] Claiming clients');
45      return self.clients.claim();
46    })
47  );
48});
49
50// Fetch event - network first, fallback to cache
51self.addEventListener('fetch', (event) => {
52  const { request } = event;
53  const url = new URL(request.url);
54
55  // Skip cross-origin requests
56  if (url.origin !== location.origin) {
57    return;
58  }
59
60  // Skip POST, PUT, DELETE requests
61  if (request.method !== 'GET') {
62    return;
63  }
64
65  // API requests and Remix loader/action data requests - network only (don't cache).
66  // Remix's single-fetch mode requests data via "*.data" URLs on every client-side
67  // navigation; caching these caused stale data (e.g. previous user's name) to
68  // flash on login until a hard refresh.
69  if (
70    url.pathname.startsWith('/api/') ||
71    url.pathname.endsWith('.data') ||
72    url.searchParams.has('_data')
73  ) {
74    event.respondWith(fetch(request));
75    return;
76  }
77
78  // For navigation requests (HTML pages) - network first
79  if (request.mode === 'navigate') {
80    event.respondWith(
81      fetch(request)
82        .then((response) => {
83          // Cache successful responses
84          if (response.status === 200) {
85            const responseClone = response.clone();
86            caches.open(RUNTIME_CACHE).then((cache) => {
87              cache.put(request, responseClone);
88            });
89          }
90          return response;
91        })
92        .catch(() => {
93          // Fallback to cache if network fails
94          return caches.match(request).then((cached) => {
95            return cached || caches.match('/');
96          });
97        })
98    );
99    return;
100  }
101
102  // For other requests - cache first, fallback to network
103  event.respondWith(
104    caches.match(request).then((cached) => {
105      if (cached) {
106        // Return cached version and update cache in background
107        fetch(request).then((response) => {
108          if (response.status === 200) {
109            caches.open(RUNTIME_CACHE).then((cache) => {
110              cache.put(request, response.clone());
111            });
112          }
113        });
114        return cached;
115      }
116
117      // Not in cache, fetch from network
118      return fetch(request).then((response) => {
119        if (response.status === 200) {
120          const responseClone = response.clone();
121          caches.open(RUNTIME_CACHE).then((cache) => {
122            cache.put(request, responseClone);
123          });
124        }
125        return response;
126      });
127    })
128  );
129});
130
131// Handle messages from clients
132self.addEventListener('message', (event) => {
133  if (event.data && event.data.type === 'SKIP_WAITING') {
134    self.skipWaiting();
135  }
136  
137  if (event.data && event.data.type === 'CLEAR_CACHE') {
138    event.waitUntil(
139      caches.keys().then((cacheNames) => {
140        return Promise.all(
141          cacheNames.map((cacheName) => caches.delete(cacheName))
142        );
143      })
144    );
145  }
146});
147
148// Periodic background sync (if supported)
149self.addEventListener('sync', (event) => {
150  if (event.tag === 'sync-data') {
151    event.waitUntil(syncData());
152  }
153});
154
155async function syncData() {
156  // Implement background sync logic here
157  console.log('[Service Worker] Background sync');
158}
159
160// Push notifications (if needed in future)
161self.addEventListener('push', (event) => {
162  const options = {
163    body: event.data ? event.data.text() : 'New notification',
164    icon: '/favicon/android-chrome-192x192.png',
165    badge: '/favicon/android-chrome-192x192.png',
166    vibrate: [200, 100, 200],
167    tag: 'fedacash-notification',
168    requireInteraction: false,
169  };
170
171  event.waitUntil(
172    self.registration.showNotification('FedaCash', options)
173  );
174});
175
176self.addEventListener('notificationclick', (event) => {
177  event.notification.close();
178  event.waitUntil(
179    clients.openWindow('/')
180  );
181});

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.