winofy-front/src/lib/api/gooyal-accounts.ts
2026-09-02 15:14:43 +03:30

65 lines
No EOL
1.9 KiB
TypeScript

import "server-only";
import { getValidSession } from "@/lib/auth/session";
import { ApiError, type WinofyErrorDetails } from "./errors";
import { logApiRequest, logApiResponse } from "./dev-logger";
const BASE_URL = process.env.GOOYAL_ACCOUNTS_BASE_URL!;
interface GooyalFetchOptions extends Omit<RequestInit, "body"> {
auth?: boolean;
params?: Record<string, string | number | boolean | undefined>;
body?: unknown;
}
export async function gooyalFetch<T>(path: string, options: GooyalFetchOptions = {}): Promise<T> {
const { auth = true, params, headers, body, ...rest } = options;
const method = rest.method ?? "GET";
const url = new URL(BASE_URL.replace(/\/$/, "") + path);
if (params) {
for (const [key, value] of Object.entries(params)) {
if (value !== undefined) url.searchParams.set(key, String(value));
}
}
const finalHeaders = new Headers(headers);
const hasBody = body !== undefined;
if (hasBody && !finalHeaders.has("Content-Type")) {
finalHeaders.set("Content-Type", "application/json");
}
if (auth) {
const session = await getValidSession();
if (session) {
finalHeaders.set("Authorization", `Bearer ${session.accessToken}`);
}
}
logApiRequest("gooyal", method, url.toString(), body);
const res = await fetch(url.toString(), {
...rest,
headers: finalHeaders,
body: hasBody ? JSON.stringify(body) : undefined,
cache: "no-store",
});
if (res.status === 204) {
logApiResponse("gooyal", method, url.toString(), res.status, null);
return undefined as T;
}
const data = await res.json().catch(() => null);
logApiResponse("gooyal", method, url.toString(), res.status, data);
if (!res.ok) {
const envelope = data as { status_message?: string; details?: WinofyErrorDetails } | null;
throw new ApiError(
res.status,
envelope?.status_message ?? res.statusText,
envelope?.details ?? null,
);
}
return data as T;
}