โ– humdrum codex / soft
2.1 KB raw
 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(),
  });
}