56 lines
2.2 KiB
JavaScript
56 lines
2.2 KiB
JavaScript
const fs = require('fs').promises;
|
|
const path = require('path');
|
|
const util = require('util');
|
|
const colors = require('colors');
|
|
|
|
module.exports = (db) => {
|
|
const run = util.promisify(db.run.bind(db));
|
|
const get = util.promisify(db.get.bind(db));
|
|
const exec = util.promisify(db.exec.bind(db));
|
|
return new Promise((resolve, reject) => {
|
|
(async () => {
|
|
try {
|
|
await run(`CREATE TABLE IF NOT EXISTS migrations (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);`);
|
|
|
|
const migrationsDir = path.join(__dirname, 'migrations');
|
|
let files;
|
|
try {
|
|
files = await fs.readdir(migrationsDir);
|
|
} catch (e) {
|
|
if (e.code === 'ENOENT') return resolve(); // no migrations directory
|
|
throw e;
|
|
}
|
|
|
|
files = files.filter(f => path.extname(f).toLowerCase() === '.sql').sort();
|
|
|
|
for (const file of files) {
|
|
const name = file;
|
|
const already = await get('SELECT 1 FROM migrations WHERE name = ?', [name]);
|
|
if (already) continue;
|
|
|
|
const sql = await fs.readFile(path.join(migrationsDir, file), 'utf8');
|
|
|
|
await exec('BEGIN');
|
|
try {
|
|
await exec(sql);
|
|
console.log(`${colors.yellow('[MIGRATION]')} Applied migration: ${name}`);
|
|
await run('INSERT INTO migrations (name) VALUES (?)', [name]);
|
|
await exec('COMMIT');
|
|
} catch (e) {
|
|
console.error(`${colors.red('[MIGRATION]')} Failed migration: ${name}`);
|
|
await exec('ROLLBACK');
|
|
throw e;
|
|
}
|
|
}
|
|
console.log(`${colors.green('[MIGRATION]')} All migrations applied.`);
|
|
resolve();
|
|
} catch (err) {
|
|
reject(err);
|
|
}
|
|
})();
|
|
});
|
|
} |