// Cuentas de cliente reales conectadas a Medusa (Store API), mismo patron // que medusa-cart.ts -- server-side, nunca cacheado (auth es estado // mutable por sesion, no catalogo). // // Flujo verificado en vivo (2026-08-29) antes de escribir este archivo, // no asumido contra documentacion: registro (auth/customer/emailpass/ // register) da un token de registro; ese token crea el customer real // (POST /store/customers); pero ese token de registro NO sirve como // sesion del customer -- hay que loguear de nuevo para obtener el token // de sesion real. Mensajes de error exactos confirmados: registro con // correo repetido -> 401 "Identity with email already exists"; login con // credenciales invalidas -> 401 "Invalid email or password". export interface CustomerSummary { token: string; id: string; email: string; firstName: string | null; lastName: string | null; } function backendUrl(): string { const value = process.env.MEDUSA_BACKEND_URL; if (!value) { throw new Error("MEDUSA_BACKEND_URL no está configurado."); } return value.replace(/\/$/, ""); } async function medusaAuthFetch( path: string, init?: { method?: string; body?: unknown; token?: string }, ): Promise> { const publishableKey = process.env.MEDUSA_PUBLISHABLE_KEY; const response = await fetch(`${backendUrl()}${path}`, { method: init?.method ?? "GET", headers: { "Content-Type": "application/json", ...(publishableKey ? { "x-publishable-api-key": publishableKey } : {}), ...(init?.token ? { Authorization: `Bearer ${init.token}` } : {}), }, body: init?.body ? JSON.stringify(init.body) : undefined, cache: "no-store", }); const data = await response.json().catch(() => ({})); if (!response.ok) { const message = typeof data.message === "string" ? data.message : `Error ${response.status}`; throw new Error(message); } return data; } type MedusaCustomer = { id: string; email: string; first_name?: string | null; last_name?: string | null; }; export async function getCurrentCustomer(token: string): Promise { const data = await medusaAuthFetch("/store/customers/me", { token }); const customer = data.customer as MedusaCustomer; return { token, id: customer.id, email: customer.email, firstName: customer.first_name ?? null, lastName: customer.last_name ?? null, }; } export async function loginCustomer(email: string, password: string): Promise { let data: Record; try { data = await medusaAuthFetch("/auth/customer/emailpass", { method: "POST", body: { email, password }, }); } catch (error) { if ((error as Error).message === "Invalid email or password") { throw new Error("Correo o contraseña incorrectos."); } throw error; } return getCurrentCustomer(data.token as string); } export async function registerCustomer( email: string, password: string, firstName: string, lastName: string, ): Promise { let data: Record; try { data = await medusaAuthFetch("/auth/customer/emailpass/register", { method: "POST", body: { email, password }, }); } catch (error) { if ((error as Error).message === "Identity with email already exists") { throw new Error("Ese correo ya está registrado — inicia sesión en vez de crear una cuenta nueva."); } throw error; } await medusaAuthFetch("/store/customers", { method: "POST", token: data.token as string, body: { email, first_name: firstName, last_name: lastName }, }); // El token de registro crea el customer pero no queda como sesion real // -- se loguea de nuevo para obtener el token de sesion (confirmado en // vivo, no documentado explicitamente). return loginCustomer(email, password); }