109 أسطر
2.9 KiB
TypeScript
109 أسطر
2.9 KiB
TypeScript
import { apiEndpoints } from "@/lib/api/endpoints";
|
|
import type { LoginResponse } from "@/types/api";
|
|
|
|
const API_PREFIX = "/api/proxy";
|
|
|
|
function isHardAuthFailure(error: unknown) {
|
|
const message = String(error);
|
|
return message.includes("400") || message.includes("401");
|
|
}
|
|
|
|
function extractErrorMessage(payload: unknown): string | null {
|
|
if (!payload || typeof payload !== "object") {
|
|
return null;
|
|
}
|
|
|
|
const candidate = payload as { message?: unknown; error?: unknown };
|
|
if (Array.isArray(candidate.message)) {
|
|
return candidate.message.map((item) => String(item)).join(", ");
|
|
}
|
|
if (typeof candidate.message === "string" && candidate.message.trim()) {
|
|
return candidate.message.trim();
|
|
}
|
|
if (typeof candidate.error === "string" && candidate.error.trim()) {
|
|
return candidate.error.trim();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
|
const isFormDataRequest =
|
|
typeof FormData !== "undefined" && init?.body instanceof FormData;
|
|
|
|
const res = await fetch(`${API_PREFIX}${path}`, {
|
|
...init,
|
|
credentials: "include",
|
|
headers: {
|
|
...(isFormDataRequest ? {} : { "Content-Type": "application/json" }),
|
|
...(init?.headers ?? {}),
|
|
},
|
|
});
|
|
|
|
if (!res.ok) {
|
|
const contentType = res.headers.get("content-type") ?? "";
|
|
let detail = "";
|
|
|
|
if (contentType.includes("application/json")) {
|
|
const payload = (await res.json()) as unknown;
|
|
const message = extractErrorMessage(payload);
|
|
detail = message ? ` - ${message}` : ` - ${JSON.stringify(payload)}`;
|
|
} else {
|
|
const text = await res.text();
|
|
detail = text ? ` - ${text}` : "";
|
|
}
|
|
|
|
throw new Error(`Request failed: ${res.status}${detail}`);
|
|
}
|
|
|
|
if (res.status === 204) {
|
|
return undefined as T;
|
|
}
|
|
|
|
return res.json() as Promise<T>;
|
|
}
|
|
|
|
export async function loginSuperAdmin(email: string, password: string): Promise<void> {
|
|
await request<LoginResponse>(apiEndpoints.auth.superAdminLogin, {
|
|
method: "POST",
|
|
body: JSON.stringify({ email, password }),
|
|
});
|
|
}
|
|
|
|
export async function refreshSuperAdmin(): Promise<boolean> {
|
|
try {
|
|
await request<LoginResponse>(apiEndpoints.auth.superAdminRefresh, {
|
|
method: "POST",
|
|
body: JSON.stringify({}),
|
|
});
|
|
return true;
|
|
} catch (error) {
|
|
if (isHardAuthFailure(error)) {
|
|
return false;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
export async function logoutSuperAdmin(): Promise<void> {
|
|
await request<void>(apiEndpoints.auth.superAdminLogout, {
|
|
method: "POST",
|
|
body: JSON.stringify({}),
|
|
});
|
|
}
|
|
|
|
export async function fetchWithAuth<T>(path: string, init?: RequestInit): Promise<T> {
|
|
const makeRequest = async () => request<T>(path, init);
|
|
|
|
try {
|
|
return await makeRequest();
|
|
} catch (error) {
|
|
if (String(error).includes("401")) {
|
|
const refreshed = await refreshSuperAdmin();
|
|
if (refreshed) {
|
|
return makeRequest();
|
|
}
|
|
}
|
|
throw error;
|
|
}
|
|
}
|