- 11 archivos corregidos: agente-ia, alta-clientes, cobranza, cotizador, dashboards, mi-dia, landing (auth.ts, api.ts, mi-dia.ts, reportes.ts, push.ts, notas.ts, recordatorios.ts, reporte-mi-tablero.ts) - ?? solo cubre null/undefined, || cubre string vacío - 7 apps reconstruidas
51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
// Cliente HTTP del API Gateway de FRASA (Express + Prisma)
|
|
const API_URL = import.meta.env.VITE_API_URL || '/api'
|
|
// TODO produccion: '/api' same-origin detras de NGINX
|
|
|
|
import { conAuth, manejar401 } from './auth'
|
|
|
|
/**
|
|
* Error HTTP del API (respuesta con status >= 400, p. ej. validación o 404).
|
|
* NO amerita fallback offline: el servidor respondió y su respuesta manda.
|
|
*/
|
|
export class ErrorApi extends Error {
|
|
constructor(
|
|
public readonly status: number,
|
|
message: string,
|
|
) {
|
|
super(message)
|
|
this.name = 'ErrorApi'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* fetch solo rechaza (TypeError) cuando falla la red; una respuesta HTTP de
|
|
* error resuelve normalmente. El fallback offline solo aplica al primer caso.
|
|
*/
|
|
export function esErrorDeRed(err: unknown): boolean {
|
|
return err instanceof TypeError
|
|
}
|
|
|
|
/** Llama al API Gateway; lanza ErrorApi con el mensaje del servidor si el status no es 2xx */
|
|
export async function request<T>(ruta: string, init?: RequestInit): Promise<T> {
|
|
const res = await fetch(
|
|
`${API_URL}${ruta}`,
|
|
conAuth({
|
|
headers: { 'Content-Type': 'application/json' },
|
|
...init,
|
|
}),
|
|
)
|
|
manejar401(res)
|
|
if (!res.ok) {
|
|
let mensaje = `Error ${res.status} al llamar ${ruta}`
|
|
try {
|
|
const cuerpo = (await res.json()) as { error?: string }
|
|
if (typeof cuerpo.error === 'string') mensaje = cuerpo.error
|
|
} catch {
|
|
// cuerpo no JSON: se queda el mensaje genérico
|
|
}
|
|
throw new ErrorApi(res.status, mensaje)
|
|
}
|
|
return (await res.json()) as T
|
|
}
|