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 { auth?: boolean; params?: Record; body?: unknown; } export async function gooyalFetch(path: string, options: GooyalFetchOptions = {}): Promise { 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; }