export function useApi() { async function api(path: string, opts: RequestInit & { json?: unknown } = {}): Promise { const headers = new Headers(opts.headers); if (opts.json !== undefined) headers.set("Content-Type", "application/json"); const res = await fetch(path, { ...opts, headers, credentials: "include", body: opts.json !== undefined ? JSON.stringify(opts.json) : opts.body, }); if (!res.ok) { const err = await res.json().catch(() => ({ error: res.statusText })); throw Object.assign(new Error(err.error || "Error"), { status: res.status, data: err }); } const ct = res.headers.get("content-type") || ""; if (ct.includes("application/json")) return await res.json() as T; return (await res.blob()) as T; } async function download(path: string, filename: string) { const blob = await api(path); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = filename; a.rel = "noopener"; document.body.appendChild(a); a.click(); a.remove(); window.setTimeout(() => URL.revokeObjectURL(url), 2000); } return { api, download }; } export const useAuth = () => { const user = useState<{ id: number; username: string; display_name: string; company_id?: number | null; company_code?: string | null; company_name?: string | null; company_kind?: string | null; tenant_id?: number | null; role?: "platform_admin" | "tenant_admin" | "user"; realm?: "app" | "platform"; must_change_password?: boolean; } | null>("auth-user", () => null); const { api } = useApi(); async function fetchMe() { try { const r = await api<{ user: NonNullable }>("/v1/auth/me"); user.value = r.user; } catch { user.value = null; } } async function login(username: string, password: string) { const r = await api<{ user: NonNullable }>("/v1/auth/login", { method: "POST", json: { username, password }, }); user.value = r.user; } async function logout() { await api("/v1/auth/logout", { method: "POST" }); user.value = null; await navigateTo("/login"); } return { user, fetchMe, login, logout }; };