You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
2.2 KiB
TypeScript

// frontend/lib/settings/api.ts — 설정: 시스템 스냅샷 + LLM(조회/저장/테스트) + 프로필/토큰/내보내기
import type {
LlmConfig,
LlmTestResult,
LlmUpdate,
Me,
SystemConfig,
TokenCreated,
TokenInfo,
} from "@/lib/types";
async function ok<T>(r: Response): Promise<T> {
if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
return r.json() as Promise<T>;
}
// 인증 켜짐일 때 세션 쿠키가 함께 가도록 항상 credentials 포함(데모/off 에선 무해).
const CREDS: RequestInit = { credentials: "include" };
export const settingsApi = {
system: () => fetch("/api/settings/system", { cache: "no-store" }).then((r) => ok<SystemConfig>(r)),
getLlm: () => fetch("/api/settings/llm", { cache: "no-store" }).then((r) => ok<LlmConfig>(r)),
updateLlm: (body: LlmUpdate) =>
fetch("/api/settings/llm", {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
}).then((r) => ok<LlmConfig>(r)),
testLlm: (body: { provider?: string; host?: string; model?: string }) =>
fetch("/api/settings/llm/test", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
}).then((r) => ok<LlmTestResult>(r)),
me: () => fetch("/api/me", { cache: "no-store", ...CREDS }).then((r) => ok<Me>(r)),
updateProfile: (body: { name?: string; role?: string }) =>
fetch("/api/me", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
...CREDS,
body: JSON.stringify(body),
}).then((r) => ok<Me>(r)),
listTokens: () =>
fetch("/api/me/tokens", { cache: "no-store", ...CREDS }).then((r) => ok<TokenInfo[]>(r)),
createToken: (name: string) =>
fetch(`/api/me/tokens?name=${encodeURIComponent(name)}`, { method: "POST", ...CREDS }).then(
(r) => ok<TokenCreated>(r),
),
revokeToken: (id: string) =>
fetch(`/api/me/tokens/${id}`, { method: "DELETE", ...CREDS }).then((r) =>
ok<{ ok: boolean }>(r),
),
exportData: () =>
fetch("/api/me/export", CREDS).then((r) => {
if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
return r.blob();
}),
};