All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m5s
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.
107 lines
3.8 KiB
TypeScript
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 },
|
|
})
|
|
}
|
|
})
|