Files
fusion/packages/dashboard/app/swUpdate.ts
Fusion 7a11a32aa0 feat(FN-3730): add action-gate reload endpoint for reloadable exempt-tools
Adds a reload endpoint for action-gate exempt tools in the engine, wiring it into the dashboard routing system and documenting the behavior in the agents guide, with a changeset for the published CLI package.

Fusion-Task-Id: FN-3730
2026-05-08 07:38:50 -07:00

52 lines
1.7 KiB
TypeScript

import { reloadOnce } from "./versionCheck";
function promptUpdate(worker: ServiceWorker): void {
worker.postMessage({ type: "SKIP_WAITING" });
}
function watchInstalling(installing: ServiceWorker): void {
installing.addEventListener("statechange", () => {
if (installing.state === "installed" && navigator.serviceWorker.controller) {
promptUpdate(installing);
}
});
}
export function installSwUpdate(): void {
if (!import.meta.env.PROD || !("serviceWorker" in navigator)) return;
// controllerchange fires on first install too (sw.js calls clients.claim()),
// but there's no prior version to swap out — reloading there races with the
// in-flight chunk loads and strands the page on a blank shell. Only reload
// when an existing controller is being replaced by a new one.
const wasControlled = !!navigator.serviceWorker.controller;
let reloading = false;
navigator.serviceWorker.addEventListener("controllerchange", () => {
if (reloading || !wasControlled) return;
reloading = true;
reloadOnce("service worker activated new version");
});
navigator.serviceWorker
.register("/sw.js")
.then((registration) => {
console.log("SW registered:", registration.scope);
if (registration.waiting && navigator.serviceWorker.controller) {
promptUpdate(registration.waiting);
}
if (registration.installing) {
watchInstalling(registration.installing);
}
registration.addEventListener("updatefound", () => {
const installing = registration.installing;
if (installing) watchInstalling(installing);
});
})
.catch((error) => {
console.log("SW registration failed:", error);
});
}