PageSourceSearch

https://bruch-hasadeh.vercel.app/sw.js

js bruch-hasadeh.vercel.app collected 2026-10-03 06:19:09 UTC 2,702 bytes, 85 lines download raw bytes

1/* Service worker for the ברוח השטח PWA.
2 *
3 * Strategy (kept deliberately conservative so it can never serve stale authed
4 * content or interfere with the API):
5 *   - Only same-origin GET requests are handled.
6 *   - /api/* is never intercepted — always hits the network.
7 *   - Navigations: network-first, falling back to a cached offline page only
8 *     when the network is unavailable (authed pages stay fresh online).
9 *   - Static assets (_next/static, icons, images, fonts, css, js): cache-first
10 *     with a background refresh (stale-while-revalidate).
11 */
12const CACHE = "broach-hasadeh-v2";
13const OFFLINE_URL = "/offline.html";
14const PRECACHE = [
15  OFFLINE_URL,
16  "/manifest.webmanifest",
17  "/icons/icon-192.png",
18  "/icons/icon-512.png",
19];
20
21self.addEventListener("install", (event) => {
22  event.waitUntil(
23    caches
24      .open(CACHE)
25      .then((cache) => Promise.allSettled(PRECACHE.map((url) => cache.add(url))))
26      .then(() => self.skipWaiting())
27  );
28});
29
30self.addEventListener("activate", (event) => {
31  event.waitUntil(
32    caches
33      .keys()
34      .then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
35      .then(() => self.clients.claim())
36  );
37});
38
39function isStaticAsset(url) {
40  return (
41    url.pathname.startsWith("/_next/static/") ||
42    url.pathname.startsWith("/icons/") ||
43    url.pathname === "/manifest.webmanifest" ||
44    /\.(?:png|jpe?g|svg|gif|webp|ico|woff2?|ttf|otf|css|js)$/i.test(url.pathname)
45  );
46}
47
48self.addEventListener("fetch", (event) => {
49  const req = event.request;
50  if (req.method !== "GET") return;
51
52  const url = new URL(req.url);
53  if (url.origin !== self.location.origin) return; // never touch cross-origin
54  if (url.pathname.startsWith("/api/")) return; // never cache API/auth
55
56  // Navigations — network-first with an offline fallback.
57  if (req.mode === "navigate") {
58    event.respondWith(
59      fetch(req).catch(() =>
60        caches.match(OFFLINE_URL).then(
61          (cached) => cached || new Response("אין חיבור", { status: 503, headers: { "Content-Type": "text/plain; charset=utf-8" } })
62        )
63      )
64    );
65    return;
66  }
67
68  // Static assets — cache-first, refresh in the background.
69  if (isStaticAsset(url)) {
70    event.respondWith(
71      caches.match(req).then((cached) => {
72        const network = fetch(req)
73          .then((res) => {
74            if (res && res.status === 200 && res.type === "basic") {
75              const copy = res.clone();
76              caches.open(CACHE).then((cache) => cache.put(req, copy));
77            }
78            return res;
79          })
80          .catch(() => cached);
81        return cached || network;
82      })
83    );
84  }
85});

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.