File size: 3,382 Bytes
bf81892
 
34b260a
 
 
bf81892
34b260a
bf81892
 
 
 
 
34b260a
1dc6a03
 
bf81892
 
 
 
1dc6a03
 
 
 
bf81892
 
 
 
 
 
 
 
 
1dc6a03
 
 
bf81892
34b260a
bf81892
 
34b260a
bf81892
1dc6a03
bf81892
 
 
 
 
 
 
 
 
 
 
 
 
 
1dc6a03
 
 
bf81892
1dc6a03
bf81892
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1dc6a03
 
 
bf81892
 
 
34b260a
bf81892
 
 
 
 
 
 
 
 
 
 
 
1dc6a03
 
 
bf81892
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1dc6a03
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
const STATIC_CACHE = 'static-v3';
const DYNAMIC_CACHE = 'dynamic-v3';

const isHttpGet = (req) => {
  try {
    if (!req || req.method !== 'GET') return false;
    const u = new URL(req.url);
    return (u.protocol === 'http:' || u.protocol === 'https:');
  } catch { return false; }
};
const isSameOrigin = (req) => {
  try { return new URL(req.url).origin === self.location.origin; } catch { return false; }
};

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(STATIC_CACHE);
    await cache.addAll(['/','/index.html','/vite.svg']);
  })());
  self.skipWaiting();
});

self.addEventListener('activate', (event) => {
  event.waitUntil((async () => {
    // If you enabled navigationPreload in page code, either keep it:
    // await self.registration.navigationPreload.enable();
    // or disable to remove the warning:
    try { await self.registration.navigationPreload.disable(); } catch {}
    const names = await caches.keys();
    await Promise.all(names.map((n) => (n === STATIC_CACHE || n === DYNAMIC_CACHE) ? null : caches.delete(n)));
    await self.clients.claim();
  })());
});

self.addEventListener('fetch', (event) => {
  const req = event.request;

  // Ignore non-http(s) or non-GET (extensions, blob:, data:, etc.)
  if (!isHttpGet(req)) return;

  const url = new URL(req.url);

  // Handle navigations (SPA shell) + optional preload
  if (req.mode === 'navigate') {
    event.respondWith((async () => {
      // If preload is enabled, prefer it
      const pre = await event.preloadResponse;
      if (pre) return pre;
      try {
        const net = await fetch(req);
        return net;
      } catch {
        const cached = await caches.match('/index.html');
        return cached || Response.error();
      }
    })());
    return;
  }

  // API: network-first, cache successful same-origin GETs
  if (url.pathname.startsWith('/api/')) {
    event.respondWith((async () => {
      try {
        const resp = await fetch(req);
        if (resp.ok && isSameOrigin(req)) {
          try {
            const c = await caches.open(DYNAMIC_CACHE);
            await c.put(req, resp.clone());
          } catch {}
        }
        return resp;
      } catch {
        const cached = await caches.match(req);
        return cached || Response.error();
      }
    })());
    return;
  }

  // Assets (script/style/image/font): cache-first
  const dest = req.destination;
  const isAsset = dest === 'script' || dest === 'style' || dest === 'image' || dest === 'font';
  if (isAsset) {
    event.respondWith((async () => {
      const hit = await caches.match(req);
      if (hit) return hit;
      const resp = await fetch(req);
      if (resp.ok && isSameOrigin(req)) {
        try {
          const c = await caches.open(STATIC_CACHE);
          await c.put(req, resp.clone());
        } catch {}
      }
      return resp;
    })());
    return;
  }

  // Default: network-first with safe cache
  event.respondWith((async () => {
    try {
      const resp = await fetch(req);
      if (resp.ok && isSameOrigin(req)) {
        try {
          const c = await caches.open(DYNAMIC_CACHE);
          await c.put(req, resp.clone());
        } catch {}
      }
      return resp;
    } catch {
      const cached = await caches.match(req);
      return cached || Response.error();
    }
  })());
});