@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.
- package/index.mjs +96 -7
- 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
|
-
|
|
2300
|
-
|
|
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
|