L7 Offline & PWA: Outbox-Kern, IndexedDB-Store, Sync-Engine und Bundle-Logik

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 17:19:43 +02:00
co-authored by Claude Opus 5
parent d5c1221ab5
commit 9f73cdae49
13 changed files with 2081 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
import { getOfflineStore } from "./db";
import { getOfflineState, whenReady } from "./outbox";
import { ctxKeyOf } from "./types";
/**
* Form drafts in IndexedDB (lane L7, Spec §22 "automatische Zwischenspeicherung"): note text,
* report draft … Stored per tenant+user context, deleted with the local data on logout.
* `key` is a stable form id, e.g. `note:<workOrderId>` or `report:<workOrderId>:daily`.
*/
const metaKey = (key: string) => `draft:${key}`;
export async function loadDraft<T>(key: string): Promise<T | null> {
if (!(await whenReady())) return null;
const ctx = getOfflineState().ctx;
if (!ctx) return null;
try {
return await (await getOfflineStore()).getMeta<T>(ctxKeyOf(ctx), metaKey(key));
} catch {
return null;
}
}
export async function saveDraft(key: string, value: unknown): Promise<void> {
const ctx = getOfflineState().ctx;
if (!ctx) return;
try {
await (await getOfflineStore()).setMeta(ctxKeyOf(ctx), metaKey(key), value);
} catch {
// quota / private mode — the form keeps working without a draft
}
}
export async function clearDraft(key: string): Promise<void> {
const ctx = getOfflineState().ctx;
if (!ctx) return;
try {
await (await getOfflineStore()).deleteMeta(ctxKeyOf(ctx), metaKey(key));
} catch {
/* ignore */
}
}