Projeto bot pontos
This commit is contained in:
68
web/lib/client-api.ts
Normal file
68
web/lib/client-api.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
"use client";
|
||||
|
||||
// Chamadas feitas pelo navegador. Vão para /api/v1 na mesma origem; o Next
|
||||
// repassa para a API Go. Toda mutação envia o token CSRF (double submit).
|
||||
import type { Problem } from "./types";
|
||||
|
||||
export class ApiError extends Error {
|
||||
status: number;
|
||||
problem: Problem | null;
|
||||
|
||||
constructor(status: number, problem: Problem | null) {
|
||||
super(problem?.title ?? `Erro ${status}`);
|
||||
this.status = status;
|
||||
this.problem = problem;
|
||||
}
|
||||
|
||||
/** Mensagem com os erros de campo, se houver. */
|
||||
details(): string {
|
||||
const fields = this.problem?.errors ?? [];
|
||||
if (fields.length === 0) return this.message;
|
||||
return `${this.message}: ${fields.map((e) => `${e.field} — ${e.message}`).join("; ")}`;
|
||||
}
|
||||
}
|
||||
|
||||
function readCookie(name: string): string {
|
||||
const match = document.cookie.split("; ").find((c) => c.startsWith(`${name}=`));
|
||||
return match ? decodeURIComponent(match.slice(name.length + 1)) : "";
|
||||
}
|
||||
|
||||
export async function apiFetch<T = unknown>(
|
||||
path: string,
|
||||
options: { method?: string; body?: unknown } = {},
|
||||
): Promise<T> {
|
||||
const method = options.method ?? "GET";
|
||||
const headers: Record<string, string> = { accept: "application/json" };
|
||||
if (method !== "GET") {
|
||||
headers["X-CSRF-Token"] = readCookie("bp_csrf");
|
||||
}
|
||||
if (options.body !== undefined) {
|
||||
headers["content-type"] = "application/json";
|
||||
}
|
||||
|
||||
const res = await fetch(`/api/v1${path}`, {
|
||||
method,
|
||||
headers,
|
||||
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
||||
credentials: "same-origin",
|
||||
});
|
||||
|
||||
if (res.status === 401 && path !== "/auth/login") {
|
||||
window.location.href = "/login";
|
||||
throw new ApiError(401, null);
|
||||
}
|
||||
if (!res.ok) {
|
||||
const problem = (await res.json().catch(() => null)) as Problem | null;
|
||||
throw new ApiError(res.status, problem);
|
||||
}
|
||||
if (res.status === 204) {
|
||||
return undefined as T;
|
||||
}
|
||||
return (await res.json()) as T;
|
||||
}
|
||||
|
||||
export function errorMessage(err: unknown): string {
|
||||
if (err instanceof ApiError) return err.details();
|
||||
if (err instanceof Error) return err.message;
|
||||
return "Erro inesperado";
|
||||
}
|
||||
Reference in New Issue
Block a user