fix(api): Rename route.ts to route.tsx for safe JSX processing in next/og and expose specific error details

This commit is contained in:
AI Bot 2026-08-23 17:06:31 -05:00
parent 58025866be
commit 0685fcfe59

View File

@ -117,45 +117,44 @@ export async function GET(request: Request) {
const plainTextResumen = (post.resumen_redes || post.contenido || '').replace(/<[^>]*>?/gm, ' ').replace(/\s+/g, ' ').trim();
const safeResumen = plainTextResumen.length > 120 ? plainTextResumen.substring(0, 120) + '...' : plainTextResumen;
// WAIT! This file is route.ts, JSX is not supported in .ts unless it's .tsx!
// Let's use react.createElement
const React = require('react');
const cardNode = React.createElement('div', {
style: {
display: 'flex', flexDirection: 'column', width: 600, height: 600,
backgroundColor: '#0f172a', borderRadius: 24,
overflow: 'hidden', border: '1px solid rgba(255,255,255,0.1)', fontFamily: 'sans-serif'
}
},
React.createElement('div', {
style: { display: 'flex', width: 600, height: 337, backgroundColor: '#1e293b', position: 'relative' }
},
imageUrl
? React.createElement('img', { src: imageUrl, style: { width: 600, height: 337, objectFit: 'cover' } })
: React.createElement('div', { style: { width: 600, height: 337, display: 'flex', alignItems: 'center', justifyContent: 'center' } },
React.createElement('span', { style: { color: '#475569', fontSize: 24, fontWeight: 900, textTransform: 'uppercase', letterSpacing: 4 } }, 'Almeira Web')
),
React.createElement('div', { style: { position: 'absolute', top: 16, left: 16, display: 'flex' } },
React.createElement('span', {
style: { padding: '6px 12px', borderRadius: 9999, fontSize: 12, fontWeight: 'bold', letterSpacing: 1, backgroundColor: 'rgba(0,0,0,0.6)', color: '#67e8f9', border: '1px solid rgba(255,255,255,0.2)' }
}, 'NOTICIA')
)
// Use native JSX now that the file is renamed to route.tsx
const cardImage = new ImageResponse(
(
<div style={{
display: 'flex', flexDirection: 'column', width: 600, height: 600,
backgroundColor: '#0f172a', borderRadius: 24,
overflow: 'hidden', border: '1px solid rgba(255,255,255,0.1)', fontFamily: 'sans-serif'
}}>
<div style={{ display: 'flex', width: 600, height: 337, backgroundColor: '#1e293b', position: 'relative' }}>
{imageUrl ? (
<img src={imageUrl} style={{ width: 600, height: 337, objectFit: 'cover' }} />
) : (
<div style={{ width: 600, height: 337, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<span style={{ color: '#475569', fontSize: 24, fontWeight: 900, textTransform: 'uppercase', letterSpacing: 4 }}>Almeira Web</span>
</div>
)}
<div style={{ position: 'absolute', top: 16, left: 16, display: 'flex' }}>
<span style={{ padding: '6px 12px', borderRadius: 9999, fontSize: 12, fontWeight: 'bold', letterSpacing: 1, backgroundColor: 'rgba(0,0,0,0.6)', color: '#67e8f9', border: '1px solid rgba(255,255,255,0.2)' }}>
NOTICIA
</span>
</div>
</div>
<div style={{ display: 'flex', flexDirection: 'column', padding: 32, flexGrow: 1 }}>
<h3 style={{ fontSize: 26, fontWeight: 'bold', margin: '0 0 16px 0', lineHeight: 1.3, color: 'white' }}>{post.titulo || 'Sin título'}</h3>
<p style={{ fontSize: 16, color: '#94a3b8', margin: '0 0 32px 0', lineHeight: 1.6 }}>{safeResumen}</p>
<div style={{ marginTop: 'auto', paddingTop: 20, borderTop: '1px solid rgba(255,255,255,0.1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<span style={{ color: '#06b6d4', fontSize: 13, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1, marginRight: 8 }}>ESTADO:</span>
<span style={{ color: '#94a3b8', fontSize: 13, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 }}>{post.estado || 'Borrador'}</span>
</div>
<span style={{ color: '#06b6d4', fontSize: 13, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 }}>{fechaFormat}</span>
</div>
</div>
</div>
),
React.createElement('div', { style: { display: 'flex', flexDirection: 'column', padding: 32, flexGrow: 1 } },
React.createElement('h3', { style: { fontSize: 26, fontWeight: 'bold', margin: '0 0 16px 0', lineHeight: 1.3, color: 'white' } }, post.titulo || 'Sin título'),
React.createElement('p', { style: { fontSize: 16, color: '#94a3b8', margin: '0 0 32px 0', lineHeight: 1.6 } }, safeResumen),
React.createElement('div', { style: { marginTop: 'auto', paddingTop: 20, borderTop: '1px solid rgba(255,255,255,0.1)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' } },
React.createElement('div', { style: { display: 'flex', alignItems: 'center' } },
React.createElement('span', { style: { color: '#06b6d4', fontSize: 13, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1, marginRight: 8 } }, 'ESTADO:'),
React.createElement('span', { style: { color: '#94a3b8', fontSize: 13, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 } }, post.estado || 'Borrador')
),
React.createElement('span', { style: { color: '#06b6d4', fontSize: 13, fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 } }, fechaFormat)
)
)
{ width: 600, height: 600 }
);
const cardImage = new ImageResponse(cardNode, { width: 600, height: 600 });
const imgBuffer = await cardImage.arrayBuffer();
docChildren.push(
new Paragraph({
@ -228,8 +227,8 @@ export async function GET(request: Request) {
'Content-Disposition': `attachment; filename=reporte_publicaciones_${new Date().toISOString().split('T')[0]}.docx`,
},
});
} catch (error) {
} catch (error: any) {
console.error('General error Word API:', error);
return NextResponse.json({ error: 'Error al generar el documento' }, { status: 500 });
return NextResponse.json({ error: 'Error al generar el documento', details: error?.message || 'Error desconocido' }, { status: 500 });
}
}