58 lines
1.6 KiB
JavaScript
58 lines
1.6 KiB
JavaScript
import Database from 'better-sqlite3';
|
|
import { mkdirSync, readdirSync, readFileSync } from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { getPaths } from './config.mjs';
|
|
|
|
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
|
export function migrate(databasePath = getPaths().database) {
|
|
mkdirSync(path.dirname(databasePath), { recursive: true });
|
|
mkdirSync(getPaths().uploads, { recursive: true });
|
|
|
|
const database = new Database(databasePath);
|
|
database.pragma('foreign_keys = ON');
|
|
database.exec(`
|
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
name TEXT PRIMARY KEY,
|
|
applied_at_utc TEXT NOT NULL
|
|
)
|
|
`);
|
|
|
|
const applied = new Set(
|
|
database
|
|
.prepare('SELECT name FROM schema_migrations')
|
|
.all()
|
|
.map((row) => row.name)
|
|
);
|
|
const migrations = readdirSync(path.join(projectRoot, 'migrations'))
|
|
.filter((name) => /^\d+.+\.sql$/.test(name))
|
|
.sort();
|
|
|
|
for (const name of migrations) {
|
|
if (applied.has(name)) continue;
|
|
|
|
const sql = readFileSync(path.join(projectRoot, 'migrations', name), 'utf8');
|
|
database.exec('BEGIN IMMEDIATE');
|
|
try {
|
|
database.exec(sql);
|
|
database
|
|
.prepare('INSERT INTO schema_migrations (name, applied_at_utc) VALUES (?, ?)')
|
|
.run(name, new Date().toISOString());
|
|
database.exec('COMMIT');
|
|
console.log(`Migration applied: ${name}`);
|
|
} catch (error) {
|
|
database.exec('ROLLBACK');
|
|
database.close();
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
database.close();
|
|
console.log(`Database ready: ${databasePath}`);
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
migrate();
|
|
}
|