31 lines
1008 B
TypeScript
31 lines
1008 B
TypeScript
import Database from 'better-sqlite3';
|
|||
|
|
import { mkdirSync } from 'node:fs';
|
||
|
|
import { dirname } from 'node:path';
|
||
|
|
import { migrations } from './migrations.js';
|
||
|
|
|
||
|
|
export type DB = Database.Database;
|
||
|
|
|
||
|
|
export function openDatabase(path: string): DB {
|
||
|
|
if (path !== ':memory:') mkdirSync(dirname(path), { recursive: true });
|
||
|
|
const db = new Database(path);
|
||
|
|
db.pragma('journal_mode = WAL');
|
||
|
|
db.pragma('foreign_keys = ON');
|
||
|
|
migrate(db);
|
||
|
|
return db;
|
||
|
|
}
|
||
|
|
|
||
|
|
function migrate(db: DB): void {
|
||
|
|
db.exec('CREATE TABLE IF NOT EXISTS schema_migrations (id INTEGER PRIMARY KEY, applied_at INTEGER NOT NULL)');
|
||
|
|
const applied = new Set(
|
||
|
|
db.prepare('SELECT id FROM schema_migrations').all().map((r) => (r as { id: number }).id),
|
||
|
|
);
|
||
|
|
const record = db.prepare('INSERT INTO schema_migrations (id, applied_at) VALUES (?, ?)');
|
||
|
|
for (const m of migrations) {
|
||
|
|
if (applied.has(m.id)) continue;
|
||
|
|
db.transaction(() => {
|
||
|
|
db.exec(m.sql);
|
||
|
|
record.run(m.id, Math.floor(Date.now() / 1000));
|
||
|
|
})();
|
||
|
|
}
|
||
|
|
}
|