mirror of https://github.com/VERT-sh/VERT.git
				
				
				
			
		
			
				
	
	
		
			192 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
const CACHE_NAME = "vert-wasm-cache-v1";
 | 
						|
 | 
						|
const WASM_FILES = [
 | 
						|
	"/pandoc.wasm",
 | 
						|
	"https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm/ffmpeg-core.js",
 | 
						|
	"https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm/ffmpeg-core.wasm",
 | 
						|
];
 | 
						|
 | 
						|
const WASM_URL_PATTERNS = [
 | 
						|
	/\/src\/lib\/workers\/.*\.js$/, // dev mode worker files
 | 
						|
	/\/assets\/.*worker.*\.js$/, // prod worker files
 | 
						|
	/magick.*\.wasm$/, // magick-wasm (unneeded?)
 | 
						|
];
 | 
						|
 | 
						|
function shouldCacheUrl(url) {
 | 
						|
	const urlObj = new URL(url);
 | 
						|
 | 
						|
	if (WASM_FILES.includes(urlObj.pathname) || WASM_FILES.includes(url)) {
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return WASM_URL_PATTERNS.some(
 | 
						|
		(pattern) => pattern.test(urlObj.pathname) || pattern.test(url),
 | 
						|
	);
 | 
						|
}
 | 
						|
 | 
						|
self.addEventListener("install", (event) => {
 | 
						|
	console.log("[SW] installing service worker");
 | 
						|
 | 
						|
	event.waitUntil(
 | 
						|
		caches.open(CACHE_NAME).then((cache) => {
 | 
						|
			const staticFiles = WASM_FILES.filter((file) =>
 | 
						|
				file.startsWith("/"),
 | 
						|
			);
 | 
						|
			if (staticFiles.length > 0) {
 | 
						|
				console.log("[SW] pre-caching static files:", staticFiles);
 | 
						|
				return cache.addAll(staticFiles).catch((err) => {
 | 
						|
					console.warn("[SW] failed to pre-cache some files:", err);
 | 
						|
				});
 | 
						|
			}
 | 
						|
		}),
 | 
						|
	);
 | 
						|
 | 
						|
	self.skipWaiting();
 | 
						|
});
 | 
						|
 | 
						|
self.addEventListener("activate", (event) => {
 | 
						|
	event.waitUntil(
 | 
						|
		caches
 | 
						|
			.keys()
 | 
						|
			.then((cacheNames) => {
 | 
						|
				return Promise.all(
 | 
						|
					cacheNames.map((cacheName) => {
 | 
						|
						if (
 | 
						|
							cacheName !== CACHE_NAME &&
 | 
						|
							cacheName.startsWith("vert-wasm-cache")
 | 
						|
						) {
 | 
						|
							console.log("[SW] deleting old cache:", cacheName);
 | 
						|
							return caches.delete(cacheName);
 | 
						|
						}
 | 
						|
					}),
 | 
						|
				);
 | 
						|
			})
 | 
						|
			.then(() => {
 | 
						|
				return self.clients.claim();
 | 
						|
			}),
 | 
						|
	);
 | 
						|
});
 | 
						|
 | 
						|
self.addEventListener("fetch", (event) => {
 | 
						|
	const request = event.request;
 | 
						|
 | 
						|
	if (!shouldCacheUrl(request.url)) {
 | 
						|
		return; // Let the request go through normally if not a target URL
 | 
						|
	}
 | 
						|
 | 
						|
    // else intercept request
 | 
						|
	event.respondWith(
 | 
						|
		caches.match(request).then((cachedResponse) => {
 | 
						|
			if (cachedResponse) {
 | 
						|
				console.log("[SW] serving from cache:", request.url);
 | 
						|
				return cachedResponse;
 | 
						|
			}
 | 
						|
 | 
						|
			console.log("[SW] fetching and caching:", request.url);
 | 
						|
			return fetch(request)
 | 
						|
				.then((response) => {
 | 
						|
					if (!response.ok) {
 | 
						|
						console.warn(
 | 
						|
							"[SW] not caching failed response:",
 | 
						|
							response.status,
 | 
						|
							request.url,
 | 
						|
						);
 | 
						|
						return response;
 | 
						|
					}
 | 
						|
 | 
						|
					const responseToCache = response.clone();
 | 
						|
					caches.open(CACHE_NAME).then((cache) => {
 | 
						|
						cache
 | 
						|
							.put(request, responseToCache)
 | 
						|
							.then(() => {
 | 
						|
								console.log(
 | 
						|
									"[SW] cached successfully:",
 | 
						|
									request.url,
 | 
						|
								);
 | 
						|
							})
 | 
						|
							.catch((err) => {
 | 
						|
								console.warn(
 | 
						|
									"[SW] failed to cache:",
 | 
						|
									request.url,
 | 
						|
									err,
 | 
						|
								);
 | 
						|
							});
 | 
						|
					});
 | 
						|
 | 
						|
					return response;
 | 
						|
				})
 | 
						|
				.catch((err) => {
 | 
						|
					console.error("[SW] fetch failed for:", request.url, err);
 | 
						|
					throw err;
 | 
						|
				});
 | 
						|
		}),
 | 
						|
	);
 | 
						|
});
 | 
						|
 | 
						|
self.addEventListener("message", (event) => {
 | 
						|
    if (!event.data) return;
 | 
						|
    const type = event.data.type;
 | 
						|
 | 
						|
	if (type === "GET_CACHE_INFO") {
 | 
						|
		event.waitUntil(
 | 
						|
			caches.open(CACHE_NAME).then(async (cache) => {
 | 
						|
				const keys = await cache.keys();
 | 
						|
				let totalSize = 0;
 | 
						|
				const files = [];
 | 
						|
 | 
						|
				for (const request of keys) {
 | 
						|
					try {
 | 
						|
						const response = await cache.match(request);
 | 
						|
						if (response) {
 | 
						|
							const blob = await response.blob();
 | 
						|
							const size = blob.size;
 | 
						|
							totalSize += size;
 | 
						|
 | 
						|
							files.push({
 | 
						|
								url: request.url,
 | 
						|
								size: size,
 | 
						|
								type:
 | 
						|
									response.headers.get("content-type") ||
 | 
						|
									"unknown",
 | 
						|
							});
 | 
						|
						}
 | 
						|
					} catch (err) {
 | 
						|
						console.warn(
 | 
						|
							"[SW] failed to get info for cached file:",
 | 
						|
							request.url,
 | 
						|
							err,
 | 
						|
						);
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				event.ports[0].postMessage({
 | 
						|
					totalSize,
 | 
						|
					fileCount: files.length,
 | 
						|
					files,
 | 
						|
				});
 | 
						|
			}),
 | 
						|
		);
 | 
						|
	}
 | 
						|
 | 
						|
	if (type === "CLEAR_CACHE") {
 | 
						|
		event.waitUntil(
 | 
						|
			caches
 | 
						|
				.delete(CACHE_NAME)
 | 
						|
				.then(() => {
 | 
						|
					console.log("[SW] cache cleared");
 | 
						|
					return caches.open(CACHE_NAME);
 | 
						|
				})
 | 
						|
				.then(() => {
 | 
						|
					event.ports[0].postMessage({ success: true });
 | 
						|
				})
 | 
						|
				.catch((err) => {
 | 
						|
					console.error("[SW] failed to clear cache:", err);
 | 
						|
					event.ports[0].postMessage({
 | 
						|
						success: false,
 | 
						|
						error: err.message,
 | 
						|
					});
 | 
						|
				}),
 | 
						|
		);
 | 
						|
	}
 | 
						|
});
 |