Disable frontend serviceworker registration and clear stale caches
This commit is contained in:
@@ -77,6 +77,6 @@
|
|||||||
- The frontend sharp runtime patch makes icon generation non-fatal on FreeBSD when `sharp` cannot load, preventing startup crashes in asset controller imports.
|
- The frontend sharp runtime patch makes icon generation non-fatal on FreeBSD when `sharp` cannot load, preventing startup crashes in asset controller imports.
|
||||||
- The files upload route patch fixes browser multi-upload by posting to `/files/upload` (session-authenticated) instead of direct `/media` calls without bearer token.
|
- The files upload route patch fixes browser multi-upload by posting to `/files/upload` (session-authenticated) instead of direct `/media` calls without bearer token.
|
||||||
- The files upload locale patch adds missing `files.upload.dropText`/`files.upload.browse`/`files.upload.submitMultiple` labels in endpoint locale files so UI text does not render raw translation keys.
|
- The files upload locale patch adds missing `files.upload.dropText`/`files.upload.browse`/`files.upload.submitMultiple` labels in endpoint locale files so UI text does not render raw translation keys.
|
||||||
- The frontend serviceworker patch ensures `@indiekit/frontend/lib/serviceworker.js` exists at runtime, and forces network-only handling for `/auth` and `/session` pages to avoid stale cached login/consent screens.
|
- The frontend serviceworker patch ensures `@indiekit/frontend/lib/serviceworker.js` exists at runtime, forces network-only handling for `/auth` and `/session` pages, and patches frontend layout templates to unregister stale service workers and clear caches on load.
|
||||||
- The conversations guard patch prevents `Cannot read properties of undefined (reading 'find')` when the `conversation_items` collection is temporarily unavailable.
|
- The conversations guard patch prevents `Cannot read properties of undefined (reading 'find')` when the `conversation_items` collection is temporarily unavailable.
|
||||||
- The indieauth dev-mode guard patch prevents accidental production auth bypass by requiring explicit `INDIEKIT_ALLOW_DEV_AUTH=1` to enable dev auto-login.
|
- The indieauth dev-mode guard patch prevents accidental production auth bypass by requiring explicit `INDIEKIT_ALLOW_DEV_AUTH=1` to enable dev auto-login.
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ const candidates = [
|
|||||||
"node_modules/@rmdes/indiekit-endpoint-webmention-io/node_modules/@indiekit/frontend/lib/serviceworker.js",
|
"node_modules/@rmdes/indiekit-endpoint-webmention-io/node_modules/@indiekit/frontend/lib/serviceworker.js",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const layoutCandidates = [
|
||||||
|
"node_modules/@indiekit/frontend/layouts/default.njk",
|
||||||
|
"node_modules/@rmdes/indiekit-frontend/layouts/default.njk",
|
||||||
|
"node_modules/@indiekit/indiekit/node_modules/@indiekit/frontend/layouts/default.njk",
|
||||||
|
"node_modules/@indiekit/endpoint-posts/node_modules/@indiekit/frontend/layouts/default.njk",
|
||||||
|
"node_modules/@rmdes/indiekit-endpoint-conversations/node_modules/@indiekit/frontend/layouts/default.njk",
|
||||||
|
"node_modules/@rmdes/indiekit-endpoint-webmention-io/node_modules/@indiekit/frontend/layouts/default.njk",
|
||||||
|
];
|
||||||
|
|
||||||
const fallback = `const APP_VERSION = "APP_VERSION";
|
const fallback = `const APP_VERSION = "APP_VERSION";
|
||||||
|
|
||||||
self.addEventListener("install", (event) => {
|
self.addEventListener("install", (event) => {
|
||||||
@@ -68,6 +77,30 @@ const activateNew = ` await clearOldCaches();
|
|||||||
await clearAuthSessionEntries();
|
await clearAuthSessionEntries();
|
||||||
await clients.claim();`;
|
await clients.claim();`;
|
||||||
|
|
||||||
|
const registrationScriptRegex =
|
||||||
|
/<script type="module">\n\s*if \(navigator\.serviceWorker\) \{\n[\s\S]*?<\/script>/m;
|
||||||
|
|
||||||
|
const registrationDisableMarker = "disable stale service-worker caches";
|
||||||
|
const registrationDisableScript = `<script type="module">
|
||||||
|
if ("serviceWorker" in navigator) {
|
||||||
|
window.addEventListener("load", async () => {
|
||||||
|
try {
|
||||||
|
const registrations = await navigator.serviceWorker.getRegistrations();
|
||||||
|
await Promise.all(
|
||||||
|
registrations.map((registration) => registration.unregister()),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ("caches" in window) {
|
||||||
|
const keys = await caches.keys();
|
||||||
|
await Promise.all(keys.map((key) => caches.delete(key)));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to disable stale service-worker caches", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>`;
|
||||||
|
|
||||||
async function exists(filePath) {
|
async function exists(filePath) {
|
||||||
try {
|
try {
|
||||||
await access(filePath);
|
await access(filePath);
|
||||||
@@ -101,6 +134,19 @@ function patchServiceworker(content) {
|
|||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function patchLayout(content) {
|
||||||
|
let updated = content;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!updated.includes(registrationDisableMarker) &&
|
||||||
|
registrationScriptRegex.test(updated)
|
||||||
|
) {
|
||||||
|
updated = updated.replace(registrationScriptRegex, registrationDisableScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
return updated;
|
||||||
|
}
|
||||||
|
|
||||||
let restored = false;
|
let restored = false;
|
||||||
|
|
||||||
if (!(await exists(expected))) {
|
if (!(await exists(expected))) {
|
||||||
@@ -129,9 +175,36 @@ if (!(await exists(expected))) {
|
|||||||
const source = await readFile(expected, "utf8");
|
const source = await readFile(expected, "utf8");
|
||||||
const updated = patchServiceworker(source);
|
const updated = patchServiceworker(source);
|
||||||
|
|
||||||
|
let serviceworkerPatched = false;
|
||||||
if (updated !== source) {
|
if (updated !== source) {
|
||||||
await writeFile(expected, updated, "utf8");
|
await writeFile(expected, updated, "utf8");
|
||||||
|
serviceworkerPatched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let layoutPatched = 0;
|
||||||
|
for (const layoutPath of layoutCandidates) {
|
||||||
|
if (!(await exists(layoutPath))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const layoutSource = await readFile(layoutPath, "utf8");
|
||||||
|
const layoutUpdated = patchLayout(layoutSource);
|
||||||
|
if (layoutUpdated !== layoutSource) {
|
||||||
|
await writeFile(layoutPath, layoutUpdated, "utf8");
|
||||||
|
layoutPatched += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serviceworkerPatched) {
|
||||||
console.log("[postinstall] Patched frontend serviceworker auth/session cache bypass");
|
console.log("[postinstall] Patched frontend serviceworker auth/session cache bypass");
|
||||||
} else if (!restored) {
|
}
|
||||||
|
|
||||||
|
if (layoutPatched > 0) {
|
||||||
|
console.log(
|
||||||
|
`[postinstall] Patched frontend layout serviceworker unregister in ${layoutPatched} file(s)`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!restored && !serviceworkerPatched && layoutPatched === 0) {
|
||||||
console.log("[postinstall] frontend serviceworker already present");
|
console.log("[postinstall] frontend serviceworker already present");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user