diff --git a/src/index.ts b/src/index.ts index ad01fed..345a2fa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,13 @@ type MigrationFile = { fullPath: string; } +type DBVersion = { + version: string, + notes: string, + creation_date: Date, + stable: boolean +} + /** * Carga de variables de entorno manual (para evitar dependencias como dotenv) * Busca el .env en el directorio actual (CWD) @@ -33,7 +40,7 @@ async function loadEnv(envpath?: string) { const [key, value] = line.split('='); if (key && value) process.env[key.trim()] = value.trim(); }); - console.log('ℹ️ Archivo .env cargado desde el directorio actual.'); + console.log('[i] Archivo .env cargado desde ' + envpath); } } @@ -48,24 +55,29 @@ function getArgs() { description: "Versión objetivo de la migracion", requiresArg: false }) - .parse() + .option("env", { + alias: "e", + type: 'string', + description: "Path del archivo .env con los datos de la BDD" + }) + .option("migrations", { + alias: "m", + type: "string", + description: "Path del directorio de migrations" + }) + .parse() as { + target: string, + env: string, + migrations: string + } console.log("args", argv) /* Antiguo */ - const args = process.argv.slice(2); - - const targetIdx = args.indexOf('--target') !== -1 ? args.indexOf('--target') : args.indexOf('-t'); - const envIdx = args.indexOf('--env') !== -1 ? args.indexOf('--env') : args.indexOf('-e'); - const migrtionsIdx = args.indexOf("") - - if (targetIdx === -1 || !args[targetIdx + 1]) { - console.error('❌ Error: Debes especificar una versión objetivo con --target o -t'); - process.exit(1); - } return { - target: args[targetIdx + 1], - env: args[envIdx + 1] + target: argv.target, + env: argv.env, + migrations: argv.migrations }; } @@ -99,34 +111,55 @@ function compareVersions(va: string, vb: string) { return 0 } +async function getCurrentVersion() { + try { + const lastVersion = await db.query(` + SELECT * form db_versions + ORDER BY creation_date DESC + LIMIT 1 + `) + return lastVersion.rows[0] + } catch (e) { + console.error(e) + } finally { + } +} + /** * Lógica principal de ejecución de migraciones * @param targetVersion Versión objetivo pasada por el usuario * @param currentVersion Versión actual obtenida de la DB */ -async function runMigrations(targetVersion: string, currentVersion: string, migrationDir: string) { +async function runMigrations(args: { + targetVersion: string, + currentVersion?: string, + migrationDir: string +}) { const dbClient = await db.connect() try { - const files = await fs.readdir(migrationDir); + // 1º La version explicita 2º La versión almacenada en BDD 3º 0.0.0 como version base + const currentVersion = args.currentVersion ?? (await getCurrentVersion())?.version ?? "0.0.0" + console.log("[i] Migrando desde la version " + currentVersion) + const files = await fs.readdir(args.migrationDir); const pendingMigrations: MigrationFile[] = files .map(f => ({ version: path.parse(f).name, fileName: f, - fullPath: path.join(migrationDir, f) + fullPath: path.join(args.migrationDir, f) })) // 1. Filtrar las migraciones > que la actual .filter(v => compareVersions(v.version, currentVersion) == -1) // 2. Filtra las migraciones <= que la objetivo - .filter(v => compareVersions(v.version, targetVersion) >= 0) + .filter(v => compareVersions(v.version, args.targetVersion) >= 0) .sort((a, b) => compareVersions(a.version, b.version)); if (pendingMigrations.length === 0) { - console.log("✅ La base de datos ya está actualizada."); + console.log("[o] La base de datos ya está actualizada."); return; } - console.log("Migraciones pendietes", pendingMigrations) - console.log(`🚀 Aplicando ${pendingMigrations.length} migraciones...`); + console.log("[i] Migraciones pendietes", pendingMigrations) + console.log(`[i] Aplicando ${pendingMigrations.length} migraciones...`); // Iniciamos Transacción (Ejemplo conceptual con un cliente genérico) // await db.query('BEGIN'); @@ -169,15 +202,15 @@ async function runMigrations(targetVersion: string, currentVersion: string, migr } } - /** * ******************************************************************* * ******************************************************************* */ async function main() { - const { target: targetVersion, env: envPath } = getArgs(); - await loadEnv(envPath) + const args = getArgs(); + await loadEnv(args.env); + runMigrations({ targetVersion: args.target, migrationDir: args.migrations }) } main().then(e => console.log(e)).catch(console.error)