Refactor invoice edit flow: enhance error handling, load reference data, and improve token management

This commit is contained in:
AlexeerCT
2025-12-29 12:53:06 -06:00
parent b939526302
commit 8d0a895c8d
6 changed files with 421 additions and 93 deletions

View File

@@ -134,48 +134,63 @@ export async function authenticatedFetch(
fetch: typeof globalThis.fetch,
redirectUrl?: string
): Promise<Response> {
const baseUrl = getServerApiUrl();
let { accessToken } = getAuthTokens(cookies);
try {
const baseUrl = getServerApiUrl();
let { accessToken } = getAuthTokens(cookies);
// Si no hay token, redirigir o lanzar error
if (!accessToken) {
if (redirectUrl) {
throw redirect(303, redirectUrl);
}
throw new Error('No access token available');
}
// Construir URL completa
const url = endpoint.startsWith('http') ? endpoint : `${baseUrl}${endpoint}`;
// Realizar la petición inicial
const headers = createAuthHeaders(accessToken, options.headers as Record<string, string>);
let response = await fetch(url, {
...options,
headers
});
// Si es 401, intentar refrescar el token
if (response.status === 401) {
const newToken = await refreshAccessToken(cookies, fetch);
if (newToken) {
// Reintentar la petición con el nuevo token
const newHeaders = createAuthHeaders(newToken, options.headers as Record<string, string>);
response = await fetch(url, {
...options,
headers: newHeaders
});
} else {
// No se pudo refrescar, limpiar y redirigir
clearAuthTokens(cookies);
// Si no hay token, redirigir o lanzar error
if (!accessToken) {
if (redirectUrl) {
throw redirect(303, redirectUrl);
}
throw new Error('No access token available');
}
}
return response;
// Construir URL completa
const url = endpoint.startsWith('http') ? endpoint : `${baseUrl}${endpoint}`;
// Realizar la petición inicial
const headers = createAuthHeaders(accessToken, options.headers as Record<string, string>);
let response = await fetch(url, {
...options,
headers
});
// Si es 401, intentar refrescar el token
if (response.status === 401) {
const newToken = await refreshAccessToken(cookies, fetch);
if (newToken) {
// Reintentar la petición con el nuevo token
const newHeaders = createAuthHeaders(newToken, options.headers as Record<string, string>);
response = await fetch(url, {
...options,
headers: newHeaders
});
} else {
// No se pudo refrescar, limpiar y redirigir
clearAuthTokens(cookies);
if (redirectUrl) {
throw redirect(303, redirectUrl);
}
}
}
return response;
} catch (error) {
// Si es un redirect, re-lanzarlo
if (error && typeof error === 'object' && 'status' in error && 'location' in error) {
throw error;
}
console.error('🔴 [API] Error en authenticatedFetch:', endpoint, error);
// Retornar una respuesta de error simulada en lugar de lanzar
return new Response(JSON.stringify({ error: 'Network error', details: String(error) }), {
status: 500,
headers: { 'Content-Type': 'application/json' }
});
}
}
/**