1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
"use client";
import { openDB, type IDBPDatabase } from "idb";
const DB_NAME = "app-cache";
const DB_VERSION = 1;
export interface CachedDoc {
id: string;
payload: unknown;
cachedAt: number;
}
export interface PendingWrite {
id: string;
op: "create" | "update" | "delete";
endpoint: string;
body: unknown;
createdAt: number;
}
let dbPromise: Promise<IDBPDatabase> | null = null;
function getDB(): Promise<IDBPDatabase> {
if (!dbPromise) {
dbPromise = openDB(DB_NAME, DB_VERSION, {
upgrade(db) {
if (!db.objectStoreNames.contains("docs")) {
db.createObjectStore("docs", { keyPath: "id" });
}
if (!db.objectStoreNames.contains("pending")) {
db.createObjectStore("pending", { keyPath: "id" });
}
},
});
}
return dbPromise;
}
export async function getCached(id: string): Promise<CachedDoc | undefined> {
return (await getDB()).get("docs", id) as Promise<CachedDoc | undefined>;
}
export async function setCached(doc: CachedDoc): Promise<void> {
await (await getDB()).put("docs", doc);
}
export async function deleteCached(id: string): Promise<void> {
await (await getDB()).delete("docs", id);
}
export async function getAllCached(): Promise<CachedDoc[]> {
return (await getDB()).getAll("docs") as Promise<CachedDoc[]>;
}
export async function enqueueWrite(w: PendingWrite): Promise<void> {
await (await getDB()).put("pending", w);
}
export async function getPendingWrites(): Promise<PendingWrite[]> {
return (await getDB()).getAll("pending") as Promise<PendingWrite[]>;
}
export async function clearPendingWrite(id: string): Promise<void> {
await (await getDB()).delete("pending", id);
}
// Optimistic write helper โ update cache and enqueue remote sync.
export async function optimisticWrite<T extends { id: string }>(
doc: T,
endpoint: string,
op: PendingWrite["op"] = "update",
): Promise<void> {
await setCached({ id: doc.id, payload: doc, cachedAt: Date.now() });
await enqueueWrite({
id: `${doc.id}-${Date.now()}`,
op,
endpoint,
body: doc,
createdAt: Date.now(),
});
}
|