espace-paie-odentas/lib/fetcher.ts

83 lines
3.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export async function api<T>(path: string, init: RequestInit = {}, clientInfo?: { id: string; name: string; api_name?: string } | null): Promise<T> {
const headers = new Headers(init.headers || {});
// Helper: UTF-8 → base64 (ASCII safe for HTTP headers)
const toBase64 = (s: string) => {
try {
// browser-safe utf8 → b64
return btoa(unescape(encodeURIComponent(s)));
} catch {
// Node or unexpected env best effort fallback
if (typeof Buffer !== "undefined") return Buffer.from(s, "utf-8").toString("base64");
return s;
}
};
// Priorité 1: Utiliser clientInfo passé en paramètre (server-side)
if (clientInfo) {
const company = clientInfo.name || "";
const activeOrg = clientInfo.id || "";
if (company) {
headers.set("x-company-name", company);
headers.set("x-company-name-b64", toBase64(company));
}
if (activeOrg) {
headers.set("x-active-org-id", activeOrg);
}
} else {
// Fallback: localStorage (client-side seulement si pas de clientInfo)
let company = "";
let activeOrg = "";
if (typeof window !== "undefined") {
company = localStorage.getItem("company_name") || "";
activeOrg = localStorage.getItem("active_org_id") || "";
}
if (company) {
headers.set("x-company-name", company);
headers.set("x-company-name-b64", toBase64(company));
}
if (activeOrg && !headers.has("x-active-org-id")) {
headers.set("x-active-org-id", activeOrg);
}
}
console.log("📦 headers envoyés :", [...headers.entries()]);
// Content negotiation
headers.set("Accept", "application/json");
// Only set Content-Type automatically if a body is present and header not already set
const hasBody = !!(init as RequestInit).body;
if (hasBody && !headers.has("Content-Type")) headers.set("Content-Type", "application/json");
// Route interne pour certaines ressources gérées par Next.js (évite l'upstream AWS)
// Prefixes served by Next.js API (internal) instead of upstream
const INTERNAL_PREFIXES = [
"/access",
"/salaries", // all salaries endpoints are internal (Supabase)
"/spectacles", // all spectacles endpoints are internal (Supabase)
"/informations", // Vos informations: lire depuis Supabase (organization_details)
"/facturation", // Facturation: lire depuis Supabase (invoices)
"/cotisations", // Cotisations: lire depuis Supabase (monthly_contributions)
"/contrats", // Ajouté : toutes les requêtes contrats passent par l'API interne
"/staff", // Toutes les API staff (staff/facturation, staff/organizations, etc.)
];
const isInternal = INTERNAL_PREFIXES.some((p) => path.startsWith(p));
const base = process.env.NEXT_PUBLIC_API_BASE as string;
const url = isInternal ? `/api${path}` : `${base}${path}`;
console.log("🔗 api() -> URL ciblée :", url);
const res = await fetch(url, {
...init,
credentials: "include", // cookie httpOnly (supabase / session)
headers,
cache: "no-store",
});
if (!res.ok) {
// Try to surface text body for easier debugging
const text = await res.text().catch(() => "");
throw new Error(text || `API error ${res.status}`);
}
return res.json();
}