diff --git a/src/lib/pwa/__tests__/query-persister.test.ts b/src/lib/pwa/__tests__/query-persister.test.ts index b4da283be..a68f1edf0 100644 --- a/src/lib/pwa/__tests__/query-persister.test.ts +++ b/src/lib/pwa/__tests__/query-persister.test.ts @@ -98,7 +98,7 @@ describe("session-end CacheStorage cleanup", () => { } }); - it("deletes current and legacy HealthLog static/page/data caches only", async () => { + it("deletes current and legacy HealthLog page and data caches only", async () => { const cacheNames = [ "healthlog-static-v1.34.0", "healthlog-static-v1.15.20", @@ -124,9 +124,11 @@ describe("session-end CacheStorage cleanup", () => { .soft(deleted.sort()) .toEqual( cacheNames - .filter((name) => /^healthlog-(?:static|pages|data)-/.test(name)) + .filter((name) => /^healthlog-(?:pages|data)-/.test(name)) .sort(), ); + // The static cache holds catalogs and icons, nothing of an account. + expect(deleted).not.toContain("healthlog-static-v1.34.0"); expect(deleted).not.toContain("unrelated-app-static-v7"); expect(deleted).not.toContain("workbox-precache-healthlog"); }); diff --git a/src/lib/pwa/query-persister.ts b/src/lib/pwa/query-persister.ts index 4555e4aa6..eee75a8ed 100644 --- a/src/lib/pwa/query-persister.ts +++ b/src/lib/pwa/query-persister.ts @@ -36,10 +36,7 @@ import { import { trackBackgroundTask } from "@/lib/logging/background-tasks"; import { queryKeys } from "@/lib/query-keys"; import { isReadingSharedRecord } from "@/lib/query-keys/record-scope"; -// Session-end cleanup removes every current/legacy HealthLog cache family -// while leaving unrelated CacheStorage namespaces on the same origin -// untouched; the name contract is shared with `public/sw.js`. -import { HEALTHLOG_CACHE_NAME_RE } from "@/lib/pwa/sw-cache-policy"; +import { ACCOUNT_CACHE_NAME_RE } from "@/lib/pwa/sw-cache-policy"; const DB_NAME = "healthlog-query-cache"; const STORE = "kv"; @@ -335,9 +332,11 @@ export async function clearPersistedQueryCache(): Promise { /** * Wipe every client-side cache that can hold one account's data: the - * IndexedDB query snapshot and the worker's caches, including the API caches - * older releases left behind. The single call for a session END (logout or - * 401 / expiry redirect). Best-effort across the board. + * IndexedDB query snapshot, the worker's page cache and the API caches older + * releases left behind, current and legacy versions alike. The static cache + * (catalogs, icons) holds nothing of an account and stays, so a sign-in does + * not download the locale catalog again. The single call for a session END + * (logout or 401 / expiry redirect) and at sign-in. Best-effort. */ export async function clearOfflineCachesForSessionEnd(): Promise { await clearPersistedQueryCache(); @@ -346,7 +345,7 @@ export async function clearOfflineCachesForSessionEnd(): Promise { const keys = await caches.keys(); await Promise.all( keys - .filter((k) => HEALTHLOG_CACHE_NAME_RE.test(k)) + .filter((k) => ACCOUNT_CACHE_NAME_RE.test(k)) .map((k) => caches.delete(k)), ); } catch { diff --git a/src/lib/pwa/sw-cache-policy.ts b/src/lib/pwa/sw-cache-policy.ts index b379b849d..b4890eea3 100644 --- a/src/lib/pwa/sw-cache-policy.ts +++ b/src/lib/pwa/sw-cache-policy.ts @@ -1,9 +1,15 @@ /** * The worker's own cache names: `healthlog-{static,pages,data}-`. - * Everything the app deletes from CacheStorage (session end, the "new - * version" reload) matches against this and nothing else, so another app's - * caches on the same origin are left alone. `data` names the API cache older - * releases kept; it stays so those caches are still deleted. Same pattern as + * Everything the app deletes from CacheStorage matches one of the two + * patterns below and nothing else, so another app's caches on the same + * origin are left alone. `data` names the API cache older releases kept; it + * stays so those caches are still deleted. Same pattern as * `HEALTHLOG_CACHE_NAME_RE` in `public/sw.js`. */ export const HEALTHLOG_CACHE_NAME_RE = /^healthlog-(?:static|pages|data)-/; + +/** + * The caches that can hold something of one account: cached pages and the + * old API answers. The session wipe deletes these and keeps the static cache. + */ +export const ACCOUNT_CACHE_NAME_RE = /^healthlog-(?:pages|data)-/;