@deinossrl/dgp-agent 1.5.24 → 1.5.26

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 (2) hide show
  1. package/index.mjs +96 -7
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -2296,8 +2296,102 @@ async function executePgRestore(command) {
2296
2296
 
2297
2297
  // Opciones de restore
2298
2298
  if (clean_before_restore) {
2299
- pgRestoreArgs.push('--clean');
2300
- pgRestoreArgs.push('--if-exists'); // Solo borrar si existe (evita errores)
2299
+ logInfo('Modo Limpieza Profunda activado: Eliminando schemas antes de restaurar...');
2300
+
2301
+ // Lista de schemas protegidos que NUNCA se deben borrar
2302
+ const PROTECTED_SCHEMAS = [
2303
+ 'information_schema', 'pg_catalog', 'pg_toast',
2304
+ 'auth', 'storage', 'extensions', 'graphql', 'realtime',
2305
+ 'supabase_functions', 'vault', 'pg_sodium', 'pg_graphql',
2306
+ 'pg_stat_statements', 'graphql_public', 'pgbouncer', 'monitor'
2307
+ ];
2308
+
2309
+ try {
2310
+ // 1. Identificar schemas en el backup
2311
+ const listResult = spawnSync(pgRestorePath, ['--list', localFilePath], { encoding: 'utf-8' });
2312
+ if (listResult.status === 0) {
2313
+ const schemasToClean = new Set();
2314
+
2315
+ // Parse output to find "SCHEMA" entries
2316
+ // Format: "123; 1234 5678 SCHEMA - my_schema owner"
2317
+ const lines = listResult.stdout.split('\n');
2318
+ for (const line of lines) {
2319
+ if (line.includes(' SCHEMA ')) {
2320
+ const parts = line.split(' SCHEMA ');
2321
+ if (parts.length > 1) {
2322
+ // Usually: "- schema_name owner"
2323
+ const details = parts[1].trim().split(' ')[1]; // skip dash
2324
+ if (details) schemasToClean.add(details);
2325
+ }
2326
+ }
2327
+ }
2328
+
2329
+ // Fallback: If no schema found (often happens if just public), assume public
2330
+ if (schemasToClean.size === 0) schemasToClean.add('public');
2331
+
2332
+ // 2. Ejecutar limpieza por cada schema seguro
2333
+ for (const schema of schemasToClean) {
2334
+ if (PROTECTED_SCHEMAS.includes(schema) || schema.startsWith('pg_')) {
2335
+ logInfo(`Saltando limpieza de schema protegido: ${schema}`);
2336
+ continue;
2337
+ }
2338
+
2339
+ logInfo(`Limpiando schema "${schema}" (DROP CASCADE)...`);
2340
+ await addCommandLog('info', `Limpiando schema "${schema}"...`);
2341
+
2342
+ // Construir URI o usar psql args
2343
+ let psqlArgs = [];
2344
+ let env = { ...process.env };
2345
+
2346
+ if (target_environment.connection_type === 'supabase') {
2347
+ const projectRef = target_environment.supabase_project_ref;
2348
+ psqlArgs = [
2349
+ `--host=db.${projectRef}.supabase.co`,
2350
+ '--port=5432',
2351
+ '--username=postgres',
2352
+ '--dbname=postgres',
2353
+ '-c', `DROP SCHEMA IF EXISTS "${schema}" CASCADE; CREATE SCHEMA "${schema}";`
2354
+ ];
2355
+ if (params.password_encrypted) env.PGPASSWORD = params.password_encrypted;
2356
+ } else {
2357
+ psqlArgs = [
2358
+ `--host=${target_environment.db_host}`,
2359
+ `--port=${target_environment.db_port || 5432}`,
2360
+ `--username=${target_environment.db_user}`,
2361
+ `--dbname=${target_environment.db_name}`,
2362
+ '-c', `DROP SCHEMA IF EXISTS "${schema}" CASCADE; CREATE SCHEMA "${schema}";`
2363
+ ];
2364
+ if (params.password_encrypted) env.PGPASSWORD = params.password_encrypted;
2365
+ }
2366
+
2367
+ // Ejecutar PSQL
2368
+ // IMPORTANTE: psql debe estar en el path o usar la misma carpeta bin
2369
+ const psqlPath = 'psql'; // Asumimos que está disponible o usar path absoluto si es Windows
2370
+ // En Windows con Postgres instalado, suele estar. Si usa dgp-agent local, debería tener cliente.
2371
+ // Si falla psql, fallback a pg_restore standard?
2372
+
2373
+ try {
2374
+ const cleanResult = spawnSync(psqlPath, psqlArgs, { env });
2375
+ if (cleanResult.status !== 0) {
2376
+ logError(`Error limpiando schema ${schema}: ${cleanResult.stderr}`);
2377
+ } else {
2378
+ logInfo(`✓ Schema ${schema} recreado exitosamente.`);
2379
+ }
2380
+ } catch (psqlErr) {
2381
+ logError(`No se pudo ejecutar psql para limpiar: ${psqlErr.message}. Continuando con restore normal.`);
2382
+ }
2383
+ }
2384
+ }
2385
+ } catch (e) {
2386
+ logError(`Error en proceso de pre-limpieza: ${e.message}`);
2387
+ }
2388
+
2389
+ // Ya no necesitamos --clean ni --if-exists para pg_restore porque ya limpiamos manualmente
2390
+ // Pero lo dejamos por si acaso falló lo anterior? No, duplicaría errores.
2391
+ // Mejor NO agregar --clean si ya hicimos drop.
2392
+ } else {
2393
+ // Logic para cuando NO es clean restore
2394
+ pgRestoreArgs.push('--if-exists');
2301
2395
  }
2302
2396
 
2303
2397
  if (restore_type === 'schema_only') {
@@ -2306,11 +2400,6 @@ async function executePgRestore(command) {
2306
2400
  pgRestoreArgs.push('--data-only');
2307
2401
  }
2308
2402
 
2309
- // Siempre agregar --if-exists para evitar errores con DROP
2310
- if (!clean_before_restore) {
2311
- pgRestoreArgs.push('--if-exists');
2312
- }
2313
-
2314
2403
  // NO usar --exit-on-error por defecto - dejar que pg_restore continúe
2315
2404
  // Los errores de DROP son normales cuando el objeto no existe
2316
2405
  // pg_restore luego creará todo lo que necesita
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deinossrl/dgp-agent",
3
- "version": "1.5.24",
3
+ "version": "1.5.26",
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": {