From fe2b8f5131f96d3f61845bae52ca4fa33b79e108 Mon Sep 17 00:00:00 2001 From: Hanzo_dev <2002samudiojohan@gmail.com> Date: Tue, 31 Mar 2026 18:58:38 -0500 Subject: [PATCH] fix: pgvector format, robust error handling & 5-minute API timeout --- backend/server.js | 63 ++++++++++++++++++++++++++++++++--------- frontend/src/lib/api.js | 17 +++++++++-- frontend/vite.config.js | 2 ++ 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/backend/server.js b/backend/server.js index bb7dbbc..a5d395d 100644 --- a/backend/server.js +++ b/backend/server.js @@ -146,24 +146,43 @@ app.post('/api/analizar', async (req, res) => { console.log(`[5/5] Generando embedding y guardando...`) const vector = await generarEmbedding(transcript, analisis) + paso = 'guardado' + console.log(`[5/5] Guardando en la base de datos...`) + + const payload = { + cliente_id, niche, sub_niche, mercado_objetivo, idioma, + proyecto_nombre, competidor_referente, + url_origen: url, plataforma, duracion_segundos: duracion, + vistas: vistas ? Number(vistas) : null, + likes: likes ? Number(likes) : null, + compartidos: compartidos ? Number(compartidos) : null, + fecha_publicacion, + contexto_video: contexto_video || null, + ...analisis, + transcript, + embedding_vector: vector, // Use native array + procesado_ok: true, + version_prompt: 'v1.0', + } + const { data: guion, error: errorSupabase } = await supabase .from('guiones') - .insert({ - cliente_id, niche, sub_niche, mercado_objetivo, idioma, - proyecto_nombre, competidor_referente, - url_origen: url, plataforma, duracion_segundos: duracion, - vistas, likes, compartidos, fecha_publicacion, - contexto_video: contexto_video || null, - ...analisis, - transcript, - embedding_vector: `[${vector.join(',')}]`, - procesado_ok: true, - version_prompt: 'v1.0', - }) + .insert(payload) .select('id, niche, score_virabilidad, resumen_patron') .single() - if (errorSupabase) throw new Error(`Supabase: ${errorSupabase.message}`) + if (errorSupabase) { + console.error('[Supabase] Error al insertar guion:') + console.error(' Código:', errorSupabase.code) + console.error(' Mensaje:', errorSupabase.message) + console.error(' Detalle:', errorSupabase.details) + console.error(' Pista:', errorSupabase.hint) + + // Log simple del objeto para detectar campos inválidos en la consola del backend + console.error('Payload enviado (resumido):', Object.keys(payload).join(', ')) + + throw new Error(`Supabase [${errorSupabase.code}]: ${errorSupabase.message}`) + } const segundos = ((Date.now() - inicio) / 1000).toFixed(1) console.log(`✓ Completado en ${segundos}s — ID: ${guion.id}`) @@ -322,3 +341,21 @@ app.get('/api/generados/:id', async (req, res) => { }) app.listen(PORT, () => console.log(`Backend local corriendo en http://localhost:${PORT}`)) + +// ── Middleware global de manejo de errores ─────────────────── +// Captura cualquier error no manejado en los routes de Express +app.use((err, req, res, _next) => { + console.error('[Express] Error no manejado:', err.stack || err.message) + if (!res.headersSent) { + res.status(500).json({ ok: false, error: err.message || 'Error interno del servidor' }) + } +}) + +// ── Prevenir Crash por Promesas Rechazadas ─────────────────── +process.on('unhandledRejection', (reason) => { + console.error('[Node] unhandledRejection:', reason) +}) +process.on('uncaughtException', (err) => { + console.error('[Node] uncaughtException:', err.stack || err.message) +}) + diff --git a/frontend/src/lib/api.js b/frontend/src/lib/api.js index 135e946..7fe7b0c 100644 --- a/frontend/src/lib/api.js +++ b/frontend/src/lib/api.js @@ -5,8 +5,21 @@ async function request(path, options = {}) { headers: { 'Content-Type': 'application/json' }, ...options, }) - const data = await res.json() - if (!res.ok) throw new Error(data.error || `Error ${res.status}`) + + // Protección: el servidor puede devolver texto/HTML en errores graves + let data + const contentType = res.headers.get('content-type') || '' + if (contentType.includes('application/json')) { + data = await res.json() + } else { + const text = await res.text() + data = { error: text || `Error del servidor (${res.status})` } + } + + if (!res.ok) { + const msg = data.error || data.message || `Error ${res.status}` + throw new Error(data.paso ? `[${data.paso}] ${msg}` : msg) + } return data } diff --git a/frontend/vite.config.js b/frontend/vite.config.js index 6cad1a3..d1dbc57 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -9,6 +9,8 @@ export default defineConfig({ '/api': { target: 'http://localhost:3001', changeOrigin: true, + timeout: 300000, + proxyTimeout: 300000, } } }