114 lines
No EOL
3.1 KiB
JavaScript
114 lines
No EOL
3.1 KiB
JavaScript
import mysql from 'mysql2';
|
|
import fs from 'fs/promises';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import config from './config.js';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
// Create database connection
|
|
const connection = mysql.createConnection(config.connection);
|
|
|
|
// Ensure migrations table exists
|
|
function ensureMigrationsTable() {
|
|
const createTableQuery = `
|
|
CREATE TABLE IF NOT EXISTS ${config.tableName} (
|
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
`;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
connection.execute(createTableQuery, (err) => {
|
|
if (err) reject(err);
|
|
else resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
// Get list of already executed migrations
|
|
function getExecutedMigrations() {
|
|
const query = `SELECT name FROM ${config.tableName} ORDER BY executed_at`;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
connection.execute(query, (err, results) => {
|
|
if (err) reject(err);
|
|
else resolve(results.map(row => row.name));
|
|
});
|
|
});
|
|
}
|
|
|
|
// Execute a migration file
|
|
function executeMigration(migrationName, sqlContent) {
|
|
return new Promise((resolve, reject) => {
|
|
connection.execute(sqlContent, (err) => {
|
|
if (err) reject(err);
|
|
else {
|
|
// Log the execution in migrations table
|
|
const logQuery = `INSERT INTO ${config.tableName} (name) VALUES (?)`;
|
|
connection.execute(logQuery, [migrationName], (logErr) => {
|
|
if (logErr) reject(logErr);
|
|
else resolve();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Get all migration files
|
|
async function getMigrationFiles() {
|
|
try {
|
|
const files = await fs.readdir(config.migrationsDir);
|
|
return files
|
|
.filter(file => file.endsWith('.sql'))
|
|
.sort((a, b) => a.localeCompare(b));
|
|
} catch (err) {
|
|
if (err.code === 'ENOENT') {
|
|
// Directory doesn't exist, create it
|
|
await fs.mkdir(config.migrationsDir, { recursive: true });
|
|
return [];
|
|
}
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// Run migrations
|
|
async function runMigrations() {
|
|
try {
|
|
await ensureMigrationsTable();
|
|
const executed = await getExecutedMigrations();
|
|
const allMigrations = await getMigrationFiles();
|
|
|
|
const pending = allMigrations.filter(name => !executed.includes(name));
|
|
|
|
if (pending.length === 0) {
|
|
console.log('No pending migrations');
|
|
return;
|
|
}
|
|
|
|
console.log(`Running ${pending.length} migrations...`);
|
|
|
|
for (const migrationName of pending) {
|
|
console.log(`Executing ${migrationName}`);
|
|
const filePath = path.join(config.migrationsDir, migrationName);
|
|
const sqlContent = await fs.readFile(filePath, 'utf8');
|
|
await executeMigration(migrationName, sqlContent);
|
|
}
|
|
|
|
console.log('All migrations executed successfully');
|
|
} catch (err) {
|
|
console.error('Error running migrations:', err);
|
|
throw err;
|
|
} finally {
|
|
connection.end();
|
|
}
|
|
}
|
|
|
|
// Run the migrations
|
|
if (process.argv.includes('--run')) {
|
|
runMigrations().catch(console.error);
|
|
}
|
|
|
|
export { runMigrations }; |