@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.
Files changed (3) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/index.mjs +212 -2
  3. 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
- // Construir comando pg_dump
1463
- let pgDumpCmd = 'pg_dump';
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deinossrl/dgp-agent",
3
- "version": "1.4.43",
3
+ "version": "1.4.45",
4
4
  "description": "Agente local para Despliegue-GPT - Reporta el estado del repositorio Git a la plataforma TenMinute IA",
5
5
  "main": "index.mjs",
6
6
  "bin": {