UNPKG

typecql

Version:

ORM for CQL databases.

177 lines (176 loc) 8.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runMigrations = runMigrations; const fs = require("fs"); const path = require("path"); const cassandra_driver_1 = require("cassandra-driver"); const execute_1 = require("./execute"); const logo = ` ______ __________ __ /_ __/_ ______ ___ / ____/ __ \\ / / / / / / / / __ \\/ _ \\/ / / / / / / / / / / /_/ / /_/ / __/ /___/ /_/ / / /___ /_/ \\__, / .___/\\___/\\____/\\___\\_\\/_____/ /____/_/ `; function findConfigFile(directory) { function searchDirectory(dir) { const files = fs.readdirSync(dir); for (const file of files) { const filePath = path.join(dir, file); const stats = fs.statSync(filePath); if (stats.isDirectory()) { const result = searchDirectory(filePath); // Рекурсивно ищем в подпапках if (result) { return result; } } else if (file === 'typecql.config.ts' || file === 'typecql.config.js') { // eslint-disable-next-line @typescript-eslint/no-var-requires const configFile = require(filePath); if (configFile && configFile.config) { return configFile.config; } } } return null; } return searchDirectory(directory); } function findMigrationFiles(directory) { const migrationFiles = []; let migrationPath = ''; function searchDirectory(dir) { const files = fs.readdirSync(dir); for (const file of files) { const filePath = path.join(dir, file); if (filePath.includes('node_modules')) { continue; } const stats = fs.statSync(filePath); if (filePath.endsWith('migrations')) { migrationPath = filePath; } if (stats.isDirectory()) { searchDirectory(filePath); } } } function findMigrationClasses(filePath) { const files = fs.readdirSync(filePath); for (const file of files) { const stats = fs.statSync(filePath + '/' + file); if (stats.isDirectory()) { findMigrationClasses(filePath + '/' + file); } if (!file.endsWith('js')) { continue; } const fileContent = fs.readFileSync(filePath + '/' + file, 'utf-8'); const classNameMatch = fileContent.match(/class (.*) extends .*\.TypeCQLMigration/); if (classNameMatch) { const className = classNameMatch[1]; migrationFiles.push({ filePath: filePath + '/' + file, className }); } } } searchDirectory(directory); findMigrationClasses(migrationPath); return migrationFiles; } async function executeMigrations(client, migrationFiles, direction, counter) { // Сортировка файлов по числовой части в имени класса migrationFiles.sort((a, b) => { const numA = parseInt(a.className.match(/\d+/)[0], 10); const numB = parseInt(b.className.match(/\d+/)[0], 10); return direction === 'up' ? numA - numB : numB - numA; }); for (const { filePath, className } of migrationFiles) { const timestamp = parseInt(className.match(/\d+/)[0], 10); const findMigration = await client.execute(`SELECT * FROM migrations WHERE migration_time = ${timestamp}`); if (direction === 'down') { if (!findMigration?.rows?.length) { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - \x1b[43m${className}\x1b[0m was \x1b[33m\x1b[4malready downed or not migrated\x1b[0m.`); counter.exists++; continue; } try { const MigrationClass = require(filePath)[className]; const migrationInstance = new MigrationClass(client); if (typeof migrationInstance[direction] === 'function') { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - Executing \x1b[4m${className}\x1b[0m...`); const executions = new execute_1.MigrationExecuter([]); await migrationInstance[direction](executions); for (const execution of executions.queries) { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - Executing \x1b[4m${execution.query}\x1b[0m...`); await client.execute(execution.query, execution.params); } if (executions?.queries?.length === 0) { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - No queries found.`); } await client.execute(`DELETE FROM migrations WHERE "migration_time" = ${timestamp};`); counter.executed++; console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - Executing \x1b[42m${className}\x1b[0m \x1b[32m\x1b[4msucceded\x1b[0m.\n`); } } catch (e) { console.error(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - \x1b[41mError\x1b[0m while executing \x1b[41m${className}\x1b[0m: \x1b[31m\x1b[4m${e.message}\x1b[0m.`); counter.failed++; } } else { if (findMigration?.rows?.length) { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - \x1b[43m${className}\x1b[0m was \x1b[33m\x1b[4malready executed\x1b[0m.`); counter.exists++; continue; } try { const MigrationClass = require(filePath)[className]; const migrationInstance = new MigrationClass(client); if (typeof migrationInstance[direction] === 'function') { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - Executing \x1b[4m${className}\x1b[0m...`); const executions = new execute_1.MigrationExecuter([]); await migrationInstance[direction](executions); for (const execution of executions.queries) { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - Executing \x1b[4m${execution.query}\x1b[0m...`); await client.execute(execution.query, execution.params); } if (executions?.queries?.length === 0) { console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - No queries found.`); } await client.execute(`INSERT INTO migrations (migration_time, migration_name) VALUES (${timestamp}, '${className}')`); counter.executed++; console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - Executing \x1b[42m${className}\x1b[0m \x1b[32m\x1b[4msucceded\x1b[0m.\n`); } } catch (e) { console.error(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - \x1b[41mError\x1b[0m while executing \x1b[41m${className}\x1b[0m: \x1b[31m\x1b[4m${e.message}\x1b[0m.`); counter.failed++; } } } } // Пример использования async function runMigrations(dir) { console.log(logo); const directoryPath = path.join(__dirname, '..', '..', '..', '..', '..'); const configFile = findConfigFile(directoryPath); if (!configFile) { throw new Error('\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m - \x1b[41mFile typecql.config.js not found!\x1b[0m'); } const client = new cassandra_driver_1.Client(configFile); await client.connect(); await client.execute(`CREATE TABLE IF NOT EXISTS migrations ( migration_name text, migration_time int PRIMARY KEY )`); const migrationFiles = findMigrationFiles(path.join(directoryPath, 'dist')); const counter = { executed: 0, exists: 0, failed: 0 }; await executeMigrations(client, migrationFiles, dir, counter); await client.shutdown(); console.log(`\x1b[97m\x1b[4m[TYPECQL] | [Migration]\x1b[0m Migration results: \x1b[32m\x1b[4mExecuted\x1b[0m - \x1b[42m${counter.executed}\x1b[0m \x1b[33m\x1b[4mExists\x1b[0m - \x1b[43m${counter.exists}\x1b[0m \x1b[31m\x1b[4mFailed\x1b[0m - \x1b[41m${counter.failed}\x1b[0m `); } //# sourceMappingURL=migrate-base.js.map