typecql
Version:
ORM for CQL databases.
177 lines (176 loc) • 8.67 kB
JavaScript
;
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