-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsw.js
More file actions
128 lines (111 loc) · 4.28 KB
/
Copy pathsw.js
File metadata and controls
128 lines (111 loc) · 4.28 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
/* ═══════════════════════════════════════════════════════════════
Alpha Toolkit — sw.js (Service Worker)
Strategy:
· HTML pages → Network-first, cache fallback
· Static assets (CSS/JS/fonts/images) → Cache-first, network fallback
Update cycle: bump CACHE_VERSION to evict old caches on next visit.
═══════════════════════════════════════════════════════════════ */
'use strict';
const CACHE_VERSION = 'v3';
const CACHE_NAME = `alpha-toolkit-${CACHE_VERSION}`;
/* Core assets to precache on install */
const PRECACHE_ASSETS = [
'index.html',
'404.html',
'style.css',
'assets/images/favicon.svg',
'assets/images/favicon-192.svg',
'assets/images/favicon-512.svg',
'manifest.json',
/* Core JS */
'assets/js/core/utils.js',
'assets/js/core/nav.js',
'assets/js/core/tools-data.js',
'assets/js/pages/home.js',
/* Self-hosted fonts */
'assets/fonts/SpaceGrotesk.ttf',
'assets/fonts/JetBrainsMono.ttf',
'assets/fonts/JetBrainsMono-Italic.ttf',
/* Vendor libraries (QR tools) */
'assets/js/vendor/qrcode.min.js',
'assets/js/vendor/jsQR.min.js',
'assets/js/vendor/qrious.min.js',
];
/* ─── Install ────────────────────────────────────────────────── */
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(PRECACHE_ASSETS))
.then(() => self.skipWaiting())
);
});
/* ─── Activate ───────────────────────────────────────────────── */
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys()
.then((keys) =>
Promise.all(
keys
.filter((key) => key !== CACHE_NAME)
.map((key) => caches.delete(key))
)
)
.then(() => self.clients.claim())
);
});
/* ─── Fetch ──────────────────────────────────────────────────── */
self.addEventListener('fetch', (event) => {
const { request } = event;
/* Only handle GET requests */
if (request.method !== 'GET') return;
const url = new URL(request.url);
/* Skip non-http(s) schemes (chrome-extension etc.) */
if (!url.protocol.startsWith('http')) return;
/* Only handle same-origin requests (fonts are now local) */
if (url.origin !== self.location.origin) return;
const isHTML = request.headers.get('accept')?.includes('text/html');
/* ── HTML → Network-first ── */
if (isHTML) {
event.respondWith(networkFirst(request));
return;
}
/* ── All other same-origin assets → Cache-first ── */
event.respondWith(cacheFirst(request));
});
/* ─── Strategies ─────────────────────────────────────────────── */
/**
* Network-first: try the network, cache the response, fall back to cache.
* Falls back to 404.html when completely offline and no cache exists.
*/
async function networkFirst(request) {
try {
const response = await fetch(request);
if (response.ok) {
const cache = await caches.open(CACHE_NAME);
cache.put(request, response.clone());
}
return response;
} catch {
const cached = await caches.match(request);
if (cached) return cached;
return caches.match('404.html');
}
}
/**
* Cache-first: serve from cache if available, otherwise fetch, cache,
* and return. Silently ignores non-OK responses (e.g. 404).
*/
async function cacheFirst(request) {
const cached = await caches.match(request);
if (cached) return cached;
try {
const response = await fetch(request);
if (response.ok) {
const cache = await caches.open(CACHE_NAME);
cache.put(request, response.clone());
}
return response;
} catch {
return new Response('', { status: 503, statusText: 'Service Unavailable' });
}
}