d2l-ui / lib /sync.ts
Berkkirik's picture
feat: persist chat history to backend (debounced PUT, hydrate on mount)
e6ed1f4
/**
* Backend persistence for chat history.
*
* Single shared store at /data/conversations.json on the backend Space.
* Frontend hydrates on mount and writes back on changes (debounced).
* Last-write-wins; no auth beyond the Space-level Bearer.
*/
import type { Conversation } from "./chatStore";
const PROXY = "/api/proxy/conversations";
export type RemoteConversationsPayload = {
conversations: Record<string, Conversation>;
activeId: string | null;
updatedAt?: number;
version?: number;
};
export async function loadConversations(): Promise<RemoteConversationsPayload | null> {
try {
const res = await fetch(PROXY, {
method: "GET",
headers: { "Content-Type": "application/json" },
});
if (!res.ok) {
console.warn("[sync] load failed", res.status);
return null;
}
const data = (await res.json()) as RemoteConversationsPayload;
return data;
} catch (err) {
console.warn("[sync] load error", err);
return null;
}
}
export async function saveConversations(
payload: RemoteConversationsPayload,
signal?: AbortSignal
): Promise<boolean> {
try {
const res = await fetch(PROXY, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
signal,
});
if (!res.ok) {
console.warn("[sync] save failed", res.status);
return false;
}
return true;
} catch (err) {
if ((err as { name?: string })?.name === "AbortError") return false;
console.warn("[sync] save error", err);
return false;
}
}