Repository navigation
Expand file tree
/
Copy pathsw.js
More file actions
113 lines (107 loc) · 3.75 KB
/
Copy pathsw.js
File metadata and controls
113 lines (107 loc) · 3.75 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
// web/sw.js — offline app shell (network-first, cache fallback).
//
// The SPA is a client-code trust root, so the relay serves everything
// Cache-Control: no-store — freshness over stale trusted-code delivery. This
// worker preserves that property: every request goes to the NETWORK FIRST and
// the cache is rewritten from each fresh response; the cache is only READ when
// the relay is unreachable. While the relay is up you always run exactly the
// code it serves; while it is down the installed app still opens and the
// reconnect loop dials until signaling returns.
//
// Recovery is not pinnable by a stale/compromised worker: browsers fetch sw.js
// update checks from the origin (this worker cannot intercept them), and the
// relay serves sw.js no-store — so a new deploy replaces this worker on the
// next online load.
const CACHE = 'mir-shell-v6';
// Everything the app needs to boot. test/sw.test.js fails if this list drifts
// from the files on disk — add new modules here when you add them to src/.
const SHELL = [
'/',
'/manifest.json',
'/icons/apple-touch-icon.png',
'/icons/icon-192.png',
'/icons/icon-512.png',
'/icons/icon-maskable-512.png',
'/src/app.js',
'/src/guest.js',
'/src/join.js',
'/src/boot.js',
'/src/identity.js',
'/src/identity/auth.js',
'/src/identity/binding.js',
'/src/identity/grant.js',
'/src/identity/owner.js',
'/src/identity/registry.js',
'/src/identity/signer.js',
'/src/net/backoff.js',
'/src/net/disconnect-grace.js',
'/src/net/ice-state.js',
'/src/net/pool.js',
'/src/net/reconnect.js',
'/src/net/ws-open.js',
'/src/noise/frame.js',
'/src/noise/noise-kk.js',
'/src/pair.js',
'/src/pairing/code.js',
'/src/pairing/confirm.js',
'/src/pairing/nnpsk0.js',
'/src/pairing/sas.js',
'/src/registry.js',
'/src/revocations.js',
'/src/rp.js',
'/src/store.js',
'/src/ui/keybar.js',
'/src/wallet/base58.js',
'/src/wallet/bip39.js',
'/src/wallet/wordlist.js',
'/vendor/jsqr.js',
'/vendor/noble-ciphers-chacha.js',
'/vendor/noble-curves-ed25519.js',
'/vendor/noble-hashes-hkdf.js',
'/vendor/noble-hashes-hmac.js',
'/vendor/noble-hashes-sha2.js',
'/vendor/noble-hashes-utils.js',
'/vendor/xterm-addon-fit.js',
'/vendor/xterm.css',
'/vendor/xterm.js',
];
// Live conversations with the relay — never cached, never intercepted.
// (WebSocket upgrades bypass the fetch handler anyway; this covers the plain
// HTTP ones like /turn-credentials and keeps the list in one place.)
const SIGNALING = ['/agent/signal', '/attach', '/pair', '/turn-credentials', '/healthz', '/registry', '/revocations'];
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE).then((cache) => cache.addAll(SHELL)).then(() => self.skipWaiting()),
);
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys()
.then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k))))
.then(() => self.clients.claim()),
);
});
self.addEventListener('fetch', (event) => {
const req = event.request;
if (req.method !== 'GET') return;
const url = new URL(req.url);
if (url.origin !== self.location.origin) return;
if (SIGNALING.includes(url.pathname)) return;
// Any navigation serves the SPA entry, matching the server's routing.
const key = req.mode === 'navigate' ? '/' : url.pathname;
event.respondWith(
fetch(req)
.then((res) => {
if (res.ok) {
const copy = res.clone();
caches.open(CACHE).then((cache) => cache.put(key, copy)).catch(() => {});
}
return res;
})
.catch(() =>
caches.match(key).then(
(hit) => hit || new Response('offline', { status: 503, headers: { 'Content-Type': 'text/plain' } }),
),
),
);
});