Files
crowd-funder-for-time-pwa/public/sw.js
T

69 lines
2.1 KiB
JavaScript

/* eslint-env serviceworker */
/**
* Service worker for the web build.
*
* Its only job is the Web Share Target: the manifest's share_target POSTs a
* photo to /share-target, which no static server can accept. This worker
* stashes the photo in Cache Storage and redirects to /shared-photo, where
* src/libs/webShareTarget.ts picks it up. Every other request goes straight to
* the network (no fetch handler response, no precaching).
*
* It also replaces the Workbox worker that older builds registered at this
* same URL, and deletes that worker's precaches, which otherwise keep serving
* a stale index.html that points at JavaScript files no longer deployed.
*/
const SHARE_TARGET_CACHE = "share-target";
// Keep in sync with src/libs/webShareTarget.ts
const SHARED_PHOTO_KEY = "/share-target/photo";
const FILE_NAME_HEADER = "X-File-Name";
self.addEventListener("install", () => {
self.skipWaiting();
});
self.addEventListener("activate", (event) => {
event.waitUntil(
(async () => {
const names = await caches.keys();
await Promise.all(
names
.filter((name) => name !== SHARE_TARGET_CACHE)
.map((name) => caches.delete(name)),
);
await self.clients.claim();
})(),
);
});
self.addEventListener("fetch", (event) => {
const url = new URL(event.request.url);
if (
event.request.method !== "POST" ||
url.origin !== self.location.origin ||
url.pathname !== "/share-target"
) {
return;
}
event.respondWith(
(async () => {
const formData = await event.request.formData();
const photo = formData.get("photo");
if (photo instanceof File) {
const cache = await caches.open(SHARE_TARGET_CACHE);
await cache.put(
SHARED_PHOTO_KEY,
new Response(photo, {
headers: {
"Content-Type": photo.type || "application/octet-stream",
[FILE_NAME_HEADER]: encodeURIComponent(photo.name || ""),
},
}),
);
}
return Response.redirect("/shared-photo?source=share-target", 303);
})(),
);
});