mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-04 23:44:41 +00:00
Persist only changed replica entities so steady-state writes scale with the update rather than the complete cached world. Restore remains an all-or-nothing validated boundary, with whole-host byte-budget eviction.
47 lines
1.8 KiB
TypeScript
47 lines
1.8 KiB
TypeScript
import type { ProjectIconCacheStorage } from "./icon-cache";
|
|
|
|
const DATABASE_NAME = "paseo-project-icon-cache";
|
|
const STORE_NAME = "key-value";
|
|
|
|
let databasePromise: Promise<IDBDatabase> | null = null;
|
|
|
|
function openDatabase(): Promise<IDBDatabase> {
|
|
databasePromise ??= new Promise((resolve, reject) => {
|
|
const request = indexedDB.open(DATABASE_NAME, 1);
|
|
request.addEventListener("upgradeneeded", () => {
|
|
if (!request.result.objectStoreNames.contains(STORE_NAME)) {
|
|
request.result.createObjectStore(STORE_NAME);
|
|
}
|
|
});
|
|
request.addEventListener("success", () => resolve(request.result));
|
|
request.addEventListener("error", () =>
|
|
reject(request.error ?? new Error("Failed to open project icon cache")),
|
|
);
|
|
});
|
|
return databasePromise;
|
|
}
|
|
|
|
async function getItem(key: string): Promise<string | null> {
|
|
const database = await openDatabase();
|
|
return new Promise((resolve, reject) => {
|
|
const request = database.transaction(STORE_NAME, "readonly").objectStore(STORE_NAME).get(key);
|
|
request.addEventListener("success", () =>
|
|
resolve(typeof request.result === "string" ? request.result : null),
|
|
);
|
|
request.addEventListener("error", () => reject(request.error));
|
|
});
|
|
}
|
|
|
|
async function setItem(key: string, value: string): Promise<void> {
|
|
const database = await openDatabase();
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = database.transaction(STORE_NAME, "readwrite");
|
|
transaction.objectStore(STORE_NAME).put(value, key);
|
|
transaction.addEventListener("complete", () => resolve());
|
|
transaction.addEventListener("error", () => reject(transaction.error));
|
|
transaction.addEventListener("abort", () => reject(transaction.error));
|
|
});
|
|
}
|
|
|
|
export const projectIconCacheStorage: ProjectIconCacheStorage = { getItem, setItem };
|