-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsw.js
More file actions
157 lines (140 loc) · 4.29 KB
/
sw.js
File metadata and controls
157 lines (140 loc) · 4.29 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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Service Worker for ESP32Tool PWA
const CACHE_NAME = 'esp32tool-v1.6.3';
const RUNTIME_CACHE = 'esp32tool-runtime';
// Core files to cache on install (relative paths work for any deployment path)
// This ensures the app works completely offline after installation
const CORE_ASSETS = [
// App shell
'./',
'./index.html',
'./install-android.html',
// Stylesheets
'./css/style.css',
'./css/light.css',
'./css/dark.css',
// JavaScript
'./js/script.js',
'./js/hex-editor.js',
'./js/nvs-editor.js',
'./js/utilities.js',
'./js/webusb-serial.js',
'./js/modules/esptool.js',
// PWA manifest
'./manifest.json',
// Icons (all sizes referenced in manifest)
'./icons/icon-72.png',
'./icons/icon-96.png',
'./icons/icon-128.png',
'./icons/icon-144.png',
'./icons/icon-152.png',
'./icons/icon-192.png',
'./icons/icon-384.png',
'./icons/icon-512.png',
'./apple-touch-icon.png',
'./favicon.ico',
// WASM modules (required for filesystem operations)
'./src/wasm/littlefs/index.js',
'./src/wasm/littlefs/littlefs.js',
'./src/wasm/littlefs/littlefs.wasm',
'./src/wasm/fatfs/index.js',
'./src/wasm/fatfs/fatfs.wasm'
];
// Install event - cache core assets
self.addEventListener('install', (event) => {
console.log('[SW] Installing service worker...');
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => {
console.log('[SW] Caching core assets');
return cache.addAll(CORE_ASSETS);
})
.then(() => {
console.log('[SW] Skipping waiting - activating immediately');
return self.skipWaiting();
})
);
});
// Activate event - clean up old caches
self.addEventListener('activate', (event) => {
console.log('[SW] Activating service worker...');
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames
.filter((name) => name !== CACHE_NAME && name !== RUNTIME_CACHE)
.map((name) => {
console.log('[SW] Deleting old cache:', name);
return caches.delete(name);
})
);
}).then(() => self.clients.claim())
);
});
// Fetch event - network first, fallback to cache
self.addEventListener('fetch', (event) => {
const { request } = event;
const url = new URL(request.url);
// Skip non-GET requests
if (request.method !== 'GET') {
return;
}
// Skip chrome-extension and other non-http(s) requests
if (!url.protocol.startsWith('http')) {
return;
}
// Network first strategy for HTML and API calls
if (request.headers.get('accept')?.includes('text/html')) {
event.respondWith(
fetch(request)
.then((response) => {
// Only cache successful responses
if (response && response.ok) {
// Clone and cache the response
const responseClone = response.clone();
caches.open(RUNTIME_CACHE).then((cache) => {
cache.put(request, responseClone);
});
}
return response;
})
.catch(() => {
// Fallback to cache
return caches.match(request);
})
);
return;
}
// Cache first strategy for static assets
event.respondWith(
caches.match(request)
.then((cachedResponse) => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(request).then((response) => {
// Don't cache non-successful responses
if (!response || response.status !== 200 || response.type === 'error') {
return response;
}
// Clone and cache the response
const responseClone = response.clone();
caches.open(RUNTIME_CACHE).then((cache) => {
cache.put(request, responseClone);
});
// CRITICAL: Return the response after caching
return response;
}).catch(() => {
// Network failed and not in cache - return a basic error response
// or optionally return an offline fallback
console.warn('[SW] Network request failed for:', request.url);
return new Response('Network unavailable', { status: 503 });
});
})
);
});
// Handle messages from clients
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});