@deinossrl/dgp-agent 1.4.43 → 1.4.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/index.mjs +212 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog - DGP Agent
|
|
2
2
|
|
|
3
|
+
## [1.4.45] - 2026-01-12
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Corregido error de file lock al extraer PostgreSQL binaries en Windows
|
|
7
|
+
- Agregado delay de 1 segundo después de cerrar archivo ZIP para que Windows libere el handle
|
|
8
|
+
- Resuelve el error "El proceso no puede obtener acceso al archivo... está siendo utilizado"
|
|
9
|
+
|
|
10
|
+
## [1.4.44] - 2026-01-12
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Búsqueda automática de pg_dump en ubicaciones comunes de Windows
|
|
14
|
+
- Descarga e instalación automática de PostgreSQL binaries si no se encuentra pg_dump
|
|
15
|
+
- Los binarios se guardan en ~/.dgp-agent/bin/ para reutilización
|
|
16
|
+
- Soporte para instalación portable sin requerir PostgreSQL completo
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- executePgDump ahora busca/instala pg_dump automáticamente antes de ejecutar
|
|
20
|
+
- Mejor experiencia de usuario: funciona sin configuración manual
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- Error "pg_dump not found" en Windows ahora se resuelve automáticamente
|
|
24
|
+
|
|
3
25
|
## [1.4.43] - 2026-01-12
|
|
4
26
|
|
|
5
27
|
### Fixed
|
package/index.mjs
CHANGED
|
@@ -44,6 +44,7 @@ const AGENT_VERSION = packageJson.version;
|
|
|
44
44
|
const CONFIG_DIR = join(homedir(), '.dgp-agent');
|
|
45
45
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
46
46
|
const PID_FILE = join(CONFIG_DIR, 'agent.pid');
|
|
47
|
+
const BIN_DIR = join(CONFIG_DIR, 'bin');
|
|
47
48
|
|
|
48
49
|
/**
|
|
49
50
|
* Mata al agente anterior si existe
|
|
@@ -1421,6 +1422,211 @@ async function executeDeploy(command) {
|
|
|
1421
1422
|
}
|
|
1422
1423
|
}
|
|
1423
1424
|
|
|
1425
|
+
/**
|
|
1426
|
+
* Busca pg_dump en el sistema o lo descarga automáticamente
|
|
1427
|
+
* @returns {Promise<string>} Ruta al ejecutable pg_dump
|
|
1428
|
+
*/
|
|
1429
|
+
async function findOrInstallPgDump() {
|
|
1430
|
+
const isWindows = process.platform === 'win32';
|
|
1431
|
+
const executableName = isWindows ? 'pg_dump.exe' : 'pg_dump';
|
|
1432
|
+
|
|
1433
|
+
// 1. Verificar si ya está en nuestro BIN_DIR
|
|
1434
|
+
const localPgDump = join(BIN_DIR, executableName);
|
|
1435
|
+
if (existsSync(localPgDump)) {
|
|
1436
|
+
return localPgDump;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
// 2. Buscar en PATH
|
|
1440
|
+
try {
|
|
1441
|
+
const checkCmd = isWindows ? 'where pg_dump' : 'which pg_dump';
|
|
1442
|
+
const output = execSync(checkCmd, { encoding: 'utf-8' }).trim();
|
|
1443
|
+
if (output) {
|
|
1444
|
+
logSuccess(`pg_dump encontrado en PATH: ${output}`);
|
|
1445
|
+
return output.split('\n')[0]; // Primera línea si hay múltiples
|
|
1446
|
+
}
|
|
1447
|
+
} catch (e) {
|
|
1448
|
+
// No está en PATH, continuar buscando
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// 3. Buscar en ubicaciones comunes de Windows
|
|
1452
|
+
if (isWindows) {
|
|
1453
|
+
const commonPaths = [
|
|
1454
|
+
'C:\\Program Files\\PostgreSQL',
|
|
1455
|
+
'C:\\Program Files (x86)\\PostgreSQL',
|
|
1456
|
+
];
|
|
1457
|
+
|
|
1458
|
+
for (const basePath of commonPaths) {
|
|
1459
|
+
if (existsSync(basePath)) {
|
|
1460
|
+
// Buscar en todas las versiones (16, 15, 14, etc.)
|
|
1461
|
+
try {
|
|
1462
|
+
const versions = execSync(`dir "${basePath}" /b`, { encoding: 'utf-8' })
|
|
1463
|
+
.trim()
|
|
1464
|
+
.split('\n')
|
|
1465
|
+
.filter(v => /^\d+$/.test(v.trim()))
|
|
1466
|
+
.sort((a, b) => parseInt(b) - parseInt(a)); // Mayor a menor
|
|
1467
|
+
|
|
1468
|
+
for (const version of versions) {
|
|
1469
|
+
const pgDumpPath = join(basePath, version.trim(), 'bin', 'pg_dump.exe');
|
|
1470
|
+
if (existsSync(pgDumpPath)) {
|
|
1471
|
+
logSuccess(`pg_dump encontrado: ${pgDumpPath}`);
|
|
1472
|
+
return pgDumpPath;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
} catch (e) {
|
|
1476
|
+
// Ignorar errores de dir
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
// 4. Si no se encontró, descargar binarios portables
|
|
1483
|
+
logInfo('pg_dump no encontrado. Descargando binarios de PostgreSQL...');
|
|
1484
|
+
|
|
1485
|
+
if (!existsSync(BIN_DIR)) {
|
|
1486
|
+
mkdirSync(BIN_DIR, { recursive: true });
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
const downloadPgDump = async () => {
|
|
1490
|
+
if (isWindows) {
|
|
1491
|
+
// Descargar binaries de PostgreSQL para Windows
|
|
1492
|
+
// Usamos la versión portable de PostgreSQL 16
|
|
1493
|
+
const zipUrl = 'https://get.enterprisedb.com/postgresql/postgresql-16.1-1-windows-x64-binaries.zip';
|
|
1494
|
+
const zipPath = join(BIN_DIR, 'postgresql-binaries.zip');
|
|
1495
|
+
|
|
1496
|
+
logInfo('Descargando PostgreSQL binaries...');
|
|
1497
|
+
logInfo('Esto puede tomar unos minutos (80 MB)...');
|
|
1498
|
+
|
|
1499
|
+
return new Promise((resolve, reject) => {
|
|
1500
|
+
const file = createWriteStream(zipPath);
|
|
1501
|
+
https.get(zipUrl, (response) => {
|
|
1502
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
1503
|
+
// Seguir redirect
|
|
1504
|
+
https.get(response.headers.location, (redirectResponse) => {
|
|
1505
|
+
redirectResponse.pipe(file);
|
|
1506
|
+
file.on('finish', () => {
|
|
1507
|
+
file.close();
|
|
1508
|
+
logInfo('Descarga completada. Extrayendo...');
|
|
1509
|
+
|
|
1510
|
+
// Dar tiempo a Windows para liberar el handle del archivo
|
|
1511
|
+
setTimeout(() => {
|
|
1512
|
+
// Extraer solo pg_dump.exe y sus DLLs necesarias
|
|
1513
|
+
try {
|
|
1514
|
+
// Usar PowerShell para extraer el zip
|
|
1515
|
+
const extractCmd = `powershell -command "Expand-Archive -Path '${zipPath}' -DestinationPath '${BIN_DIR}' -Force"`;
|
|
1516
|
+
execSync(extractCmd);
|
|
1517
|
+
|
|
1518
|
+
// Los binarios estarán en BIN_DIR/pgsql/bin/
|
|
1519
|
+
const extractedPgDump = join(BIN_DIR, 'pgsql', 'bin', 'pg_dump.exe');
|
|
1520
|
+
|
|
1521
|
+
if (existsSync(extractedPgDump)) {
|
|
1522
|
+
// Copiar pg_dump.exe y DLLs necesarias al BIN_DIR raíz
|
|
1523
|
+
const binSrcDir = join(BIN_DIR, 'pgsql', 'bin');
|
|
1524
|
+
const essentialFiles = [
|
|
1525
|
+
'pg_dump.exe',
|
|
1526
|
+
'libpq.dll',
|
|
1527
|
+
'libiconv-2.dll',
|
|
1528
|
+
'libintl-9.dll',
|
|
1529
|
+
'libssl-3-x64.dll',
|
|
1530
|
+
'libcrypto-3-x64.dll',
|
|
1531
|
+
'zlib1.dll',
|
|
1532
|
+
];
|
|
1533
|
+
|
|
1534
|
+
for (const file of essentialFiles) {
|
|
1535
|
+
const src = join(binSrcDir, file);
|
|
1536
|
+
const dest = join(BIN_DIR, file);
|
|
1537
|
+
if (existsSync(src)) {
|
|
1538
|
+
execSync(`copy "${src}" "${dest}"`, { shell: 'cmd.exe' });
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
// Limpiar archivos temporales
|
|
1543
|
+
unlinkSync(zipPath);
|
|
1544
|
+
// Opcional: eliminar carpeta pgsql si queremos ahorrar espacio
|
|
1545
|
+
// execSync(`rmdir /s /q "${join(BIN_DIR, 'pgsql')}"`, { shell: 'cmd.exe' });
|
|
1546
|
+
|
|
1547
|
+
logSuccess('pg_dump instalado correctamente');
|
|
1548
|
+
resolve(localPgDump);
|
|
1549
|
+
} else {
|
|
1550
|
+
reject(new Error('No se pudo extraer pg_dump del archivo'));
|
|
1551
|
+
}
|
|
1552
|
+
} catch (extractError) {
|
|
1553
|
+
reject(new Error(`Error al extraer: ${extractError.message}`));
|
|
1554
|
+
}
|
|
1555
|
+
}, 1000); // Esperar 1 segundo para que Windows libere el archivo
|
|
1556
|
+
});
|
|
1557
|
+
}).on('error', reject);
|
|
1558
|
+
} else {
|
|
1559
|
+
response.pipe(file);
|
|
1560
|
+
file.on('finish', () => {
|
|
1561
|
+
file.close();
|
|
1562
|
+
logInfo('Descarga completada. Extrayendo...');
|
|
1563
|
+
|
|
1564
|
+
// Dar tiempo a Windows para liberar el handle del archivo
|
|
1565
|
+
setTimeout(() => {
|
|
1566
|
+
try {
|
|
1567
|
+
const extractCmd = `powershell -command "Expand-Archive -Path '${zipPath}' -DestinationPath '${BIN_DIR}' -Force"`;
|
|
1568
|
+
execSync(extractCmd);
|
|
1569
|
+
|
|
1570
|
+
const extractedPgDump = join(BIN_DIR, 'pgsql', 'bin', 'pg_dump.exe');
|
|
1571
|
+
|
|
1572
|
+
if (existsSync(extractedPgDump)) {
|
|
1573
|
+
const binSrcDir = join(BIN_DIR, 'pgsql', 'bin');
|
|
1574
|
+
const essentialFiles = [
|
|
1575
|
+
'pg_dump.exe',
|
|
1576
|
+
'libpq.dll',
|
|
1577
|
+
'libiconv-2.dll',
|
|
1578
|
+
'libintl-9.dll',
|
|
1579
|
+
'libssl-3-x64.dll',
|
|
1580
|
+
'libcrypto-3-x64.dll',
|
|
1581
|
+
'zlib1.dll',
|
|
1582
|
+
];
|
|
1583
|
+
|
|
1584
|
+
for (const file of essentialFiles) {
|
|
1585
|
+
const src = join(binSrcDir, file);
|
|
1586
|
+
const dest = join(BIN_DIR, file);
|
|
1587
|
+
if (existsSync(src)) {
|
|
1588
|
+
execSync(`copy "${src}" "${dest}"`, { shell: 'cmd.exe' });
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
unlinkSync(zipPath);
|
|
1593
|
+
|
|
1594
|
+
logSuccess('pg_dump instalado correctamente');
|
|
1595
|
+
resolve(localPgDump);
|
|
1596
|
+
} else {
|
|
1597
|
+
reject(new Error('No se pudo extraer pg_dump del archivo'));
|
|
1598
|
+
}
|
|
1599
|
+
} catch (extractError) {
|
|
1600
|
+
reject(new Error(`Error al extraer: ${extractError.message}`));
|
|
1601
|
+
}
|
|
1602
|
+
}, 1000); // Esperar 1 segundo para que Windows libere el archivo
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
}).on('error', (err) => {
|
|
1606
|
+
unlinkSync(zipPath);
|
|
1607
|
+
reject(err);
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1610
|
+
file.on('error', (err) => {
|
|
1611
|
+
unlinkSync(zipPath);
|
|
1612
|
+
reject(err);
|
|
1613
|
+
});
|
|
1614
|
+
});
|
|
1615
|
+
} else {
|
|
1616
|
+
// En Linux/Mac, intentar instalar via package manager
|
|
1617
|
+
throw new Error('pg_dump no encontrado. Por favor instala PostgreSQL: sudo apt-get install postgresql-client (Debian/Ubuntu) o brew install postgresql (Mac)');
|
|
1618
|
+
}
|
|
1619
|
+
};
|
|
1620
|
+
|
|
1621
|
+
await downloadPgDump();
|
|
1622
|
+
|
|
1623
|
+
if (existsSync(localPgDump)) {
|
|
1624
|
+
return localPgDump;
|
|
1625
|
+
} else {
|
|
1626
|
+
throw new Error('No se pudo instalar pg_dump automáticamente');
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1424
1630
|
/**
|
|
1425
1631
|
* Ejecuta pg_dump para crear backup de PostgreSQL
|
|
1426
1632
|
*/
|
|
@@ -1459,8 +1665,12 @@ async function executePgDump(command) {
|
|
|
1459
1665
|
const fileName = `backup_${environmentId}_${timestamp}.${extension}`;
|
|
1460
1666
|
localFilePath = join(backupsDir, fileName);
|
|
1461
1667
|
|
|
1462
|
-
//
|
|
1463
|
-
|
|
1668
|
+
// Buscar o instalar pg_dump
|
|
1669
|
+
await addCommandLog('info', 'Buscando pg_dump...');
|
|
1670
|
+
const pgDumpCmd = await findOrInstallPgDump();
|
|
1671
|
+
await addCommandLog('success', `Usando pg_dump: ${pgDumpCmd}`);
|
|
1672
|
+
|
|
1673
|
+
// Construir argumentos
|
|
1464
1674
|
const pgDumpArgs = [];
|
|
1465
1675
|
|
|
1466
1676
|
// Configurar conexión según tipo
|