Files
seguidorDeLotes/nuxt4/server/api/debug/export-database.post.ts
josedario87 730d2ce299
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m5s
Mejorar compatibilidad de backups SQL
Resuelve problemas de compatibilidad entre versiones de PostgreSQL
al exportar e importar backups.

Cambios en export-database.post.ts:
- Agregar flags adicionales a pg_dump para mayor portabilidad:
  --no-tablespaces: evita referencias a tablespaces
  --no-security-labels: evita security labels
  --no-synchronized-snapshots: evita snapshots sincronizados
- Esto genera SQL más compatible entre diferentes instalaciones

Cambios en import-database.post.ts:
- Limpiar SQL antes de importar, removiendo comandos incompatibles:
  * SET transaction_timeout (no existe en todas las versiones)
  * SET idle_in_transaction_session_timeout
  * SET lock_timeout
  * \unrestrict (comando no reconocido)
- Agregar -q y -v ON_ERROR_STOP=1 a psql
- Mejorar detección de errores: solo fallar en ERROR/FATAL reales
- Reportar tamaño original y limpio del archivo

Con estos cambios, los backups exportados desde cualquier versión
de PostgreSQL se pueden importar correctamente sin errores de
compatibilidad.
2025-11-22 04:30:55 -06:00

107 lines
3.8 KiB
TypeScript

/**
* ⚠️ ⚠️ ⚠️ ENDPOINT DE DEBUG - TEMPORAL ⚠️ ⚠️ ⚠️
*
* POST /api/debug/export-database
*
* EXPORTA TODA LA BASE DE DATOS A UN ARCHIVO SQL (pg_dump)
*
* ⚠️ NO ELIMINAR SIN CONSULTAR A DARIO/DRAGANEL/NUCLEO000 ⚠️
*
* Este endpoint fue creado para desarrollo y debugging.
* Antes de eliminarlo, preguntar si todavía es necesario.
*/
import { exec } from 'child_process'
import { promisify } from 'util'
const execAsync = promisify(exec)
export default defineEventHandler(async (event) => {
try {
console.log('💾 EXPORT DATABASE - Generando backup con pg_dump...')
// Obtener credenciales de la base de datos
const config = useRuntimeConfig()
let host: string
let port: string
let database: string
let user: string
let password: string
if (config.postgresUrl) {
// Parsear la URL de conexión
const url = new URL(config.postgresUrl)
host = url.hostname
port = url.port || '5432'
database = url.pathname.slice(1)
user = url.username
password = url.password
} else {
// Fallback a variables de entorno
const defaultHost = process.env.APP_NAME ? `${process.env.APP_NAME}-postgres` : 'postgres'
host = process.env.POSTGRES_HOST || defaultHost
port = process.env.POSTGRES_PORT || '5432'
database = process.env.POSTGRES_DB || 'seguidor_lotes'
user = process.env.POSTGRES_USER || 'seguidor'
password = process.env.POSTGRES_PASSWORD || 'seguidor_password'
}
console.log(` - Host: ${host}`)
console.log(` - Puerto: ${port}`)
console.log(` - Base de datos: ${database}`)
console.log(` - Usuario: ${user}`)
// Generar timestamp para el nombre del archivo
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5)
const filename = `backup-seguidordelotes-${timestamp}.sql`
// Ejecutar pg_dump con opciones para máxima compatibilidad
// --clean: incluir DROP antes de CREATE
// --if-exists: usar IF EXISTS en los DROP
// --no-owner: no incluir comandos de ownership
// --no-acl: no incluir permisos
// --no-tablespaces: no incluir tablespaces
// --no-security-labels: no incluir security labels
// --no-synchronized-snapshots: no usar snapshots sincronizados
const command = `PGPASSWORD="${password}" pg_dump -h ${host} -p ${port} -U ${user} -d ${database} --clean --if-exists --no-owner --no-acl --no-tablespaces --no-security-labels --no-synchronized-snapshots`
console.log(' - Ejecutando pg_dump...')
const { stdout, stderr } = await execAsync(command, {
maxBuffer: 50 * 1024 * 1024, // 50MB buffer para backups grandes
})
if (stderr && !stderr.includes('NOTICE')) {
console.warn('⚠️ Advertencias de pg_dump:', stderr)
}
console.log('✅ Backup generado exitosamente')
console.log(` - Tamaño: ${(stdout.length / 1024).toFixed(2)} KB`)
// Establecer headers para descarga
setResponseHeader(event, 'Content-Type', 'application/sql')
setResponseHeader(event, 'Content-Disposition', `attachment; filename="${filename}"`)
setResponseHeader(event, 'Content-Length', stdout.length.toString())
return stdout
} catch (error: any) {
console.error('❌ Error exportando base de datos:', error)
// Si el error es porque pg_dump no está disponible
if (error.message?.includes('pg_dump') && error.message?.includes('not found')) {
throw createError({
statusCode: 500,
statusMessage: 'pg_dump no está disponible',
data: {
message: 'El comando pg_dump no está disponible en el servidor. Asegúrate de que PostgreSQL client tools estén instalados.',
},
})
}
throw createError({
statusCode: 500,
statusMessage: 'Error exportando base de datos',
data: { message: error.message },
})
}
})