All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m7s
El import ahora funciona correctamente gracias a la limpieza de SQL que remueve comandos incompatibles. Los flags adicionales de pg_dump no son necesarios y pueden causar problemas. Cambios: - Revertir pg_dump a su forma original con solo: --clean --if-exists --no-owner --no-acl - Mantener todas las mejoras en import-database.post.ts El ciclo funciona así: 1. Export genera SQL estándar con pg_dump 2. Import limpia automáticamente comandos incompatibles 3. Import ejecuta con psql correctamente
101 lines
3.4 KiB
TypeScript
101 lines
3.4 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
|
|
// Usar PGPASSWORD en la variable de entorno para evitar prompt de contraseña
|
|
const command = `PGPASSWORD="${password}" pg_dump -h ${host} -p ${port} -U ${user} -d ${database} --clean --if-exists --no-owner --no-acl`
|
|
|
|
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 },
|
|
})
|
|
}
|
|
})
|