49 lines
1.5 KiB
TypeScript
49 lines
1.5 KiB
TypeScript
|
|
const BASE = "/api/v1";
|
||
|
|
|
||
|
|
function getToken(): string | null {
|
||
|
|
return localStorage.getItem("accessToken");
|
||
|
|
}
|
||
|
|
|
||
|
|
export function setTokens(accessToken: string, refreshToken: string) {
|
||
|
|
localStorage.setItem("accessToken", accessToken);
|
||
|
|
localStorage.setItem("refreshToken", refreshToken);
|
||
|
|
}
|
||
|
|
|
||
|
|
export function clearTokens() {
|
||
|
|
localStorage.removeItem("accessToken");
|
||
|
|
localStorage.removeItem("refreshToken");
|
||
|
|
}
|
||
|
|
|
||
|
|
async function request<T>(
|
||
|
|
path: string,
|
||
|
|
options: RequestInit = {}
|
||
|
|
): Promise<T> {
|
||
|
|
const token = getToken();
|
||
|
|
const headers: Record<string, string> = {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
...(options.headers as Record<string, string>),
|
||
|
|
};
|
||
|
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
||
|
|
|
||
|
|
const res = await fetch(`${BASE}${path}`, { ...options, headers });
|
||
|
|
|
||
|
|
if (!res.ok) {
|
||
|
|
const body = await res.json().catch(() => ({}));
|
||
|
|
const message = body?.error?.message ?? `HTTP ${res.status}`;
|
||
|
|
throw new Error(message);
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.json() as Promise<T>;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const api = {
|
||
|
|
get: <T>(path: string) => request<T>(path),
|
||
|
|
post: <T>(path: string, body: unknown) =>
|
||
|
|
request<T>(path, { method: "POST", body: JSON.stringify(body) }),
|
||
|
|
put: <T>(path: string, body: unknown) =>
|
||
|
|
request<T>(path, { method: "PUT", body: JSON.stringify(body) }),
|
||
|
|
patch: <T>(path: string, body: unknown) =>
|
||
|
|
request<T>(path, { method: "PATCH", body: JSON.stringify(body) }),
|
||
|
|
delete: <T>(path: string) => request<T>(path, { method: "DELETE" }),
|
||
|
|
};
|