PageSourceSearch

https://spreka.ai/sw.js

js spreka.ai collected 2026-10-05 15:19:13 UTC 3,284 bytes, 103 lines download raw bytes

1// Spreka AI — Service Worker
2const CACHE_VERSION = 'spreka-v3';
3const OFFLINE_URL = '/offline.html';
4
5// Assets to pre-cache on install
6const PRECACHE_ASSETS = [
7    OFFLINE_URL,
8    '/favicon.ico',
9    '/favicon-96x96.png',
10    '/apple-touch-icon.png',
11    '/pwa-icon-192.png',
12    '/pwa-icon-512.png',
13];
14
15// Install: pre-cache offline page + core assets
16self.addEventListener('install', (event) => {
17    event.waitUntil(
18        caches.open(CACHE_VERSION).then((cache) => {
19            return cache.addAll(PRECACHE_ASSETS);
20        })
21    );
22    // Activate new SW immediately
23    self.skipWaiting();
24});
25
26// Activate: clean up old caches
27self.addEventListener('activate', (event) => {
28    event.waitUntil(
29        caches.keys().then((cacheNames) => {
30            return Promise.all(
31                cacheNames
32                    .filter((name) => name !== CACHE_VERSION)
33                    .map((name) => caches.delete(name))
34            );
35        })
36    );
37    // Take control of all clients immediately
38    self.clients.claim();
39});
40
41// Fetch: Network-first for navigation, Cache-first for static assets
42self.addEventListener('fetch', (event) => {
43    const { request } = event;
44
45    // Only handle GET requests
46    if (request.method !== 'GET') return;
47
48    // Skip cross-origin requests
49    if (!request.url.startsWith(self.location.origin)) return;
50
51    // Skip Livewire/API requests
52    if (request.url.includes('/livewire/') || request.url.includes('/api/')) return;
53
54    // Navigation requests (HTML pages): Network-first with offline fallback
55    if (request.mode === 'navigate') {
56        event.respondWith(
57            fetch(request)
58                .then((response) => {
59                    // Cache successful navigation responses
60                    if (response.ok) {
61                        const responseClone = response.clone();
62                        caches.open(CACHE_VERSION).then((cache) => {
63                            cache.put(request, responseClone);
64                        });
65                    }
66                    return response;
67                })
68                .catch(() => {
69                    // Try cache first, then offline page
70                    return caches.match(request).then((cached) => {
71                        return cached || caches.match(OFFLINE_URL);
72                    });
73                })
74        );
75        return;
76    }
77
78    // Static assets (CSS, JS, images, fonts): Cache-first with network fallback
79    if (
80        request.destination === 'style' ||
81        request.destination === 'script' ||
82        request.destination === 'image' ||
83        request.destination === 'font' ||
84        request.url.includes('/build/')
85    ) {
86        event.respondWith(
87            caches.match(request).then((cached) => {
88                if (cached) return cached;
89
90                return fetch(request).then((response) => {
91                    if (response.ok) {
92                        const responseClone = response.clone();
93                        caches.open(CACHE_VERSION).then((cache) => {
94                            cache.put(request, responseClone);
95                        });
96                    }
97                    return response;
98                });
99            })
100        );
101        return;
102    }
103});

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.