Files
EJClaw/src/db/bootstrap.ts

59 lines
1.7 KiB
TypeScript

import { Database } from 'bun:sqlite';
import fs from 'fs';
import path from 'path';
import { ASSISTANT_NAME, STORE_DIR } from '../config.js';
import { applyBaseSchema } from './base-schema.js';
import { applySchemaMigrations } from './schema.js';
function setForeignKeys(database: Database, enabled: boolean): void {
database.exec(`PRAGMA foreign_keys = ${enabled ? 'ON' : 'OFF'}`);
}
function assertNoForeignKeyViolations(database: Database): void {
const violations = database
.prepare('PRAGMA foreign_key_check')
.all() as Array<{
table: string;
rowid: number;
parent: string;
fkid: number;
}>;
if (violations.length === 0) {
return;
}
const violation = violations[0]!;
throw new Error(
`Foreign key integrity check failed for ${violation.table}(rowid=${violation.rowid}) referencing ${violation.parent} [fk=${violation.fkid}]`,
);
}
export function initializeDatabaseSchema(database: Database): void {
setForeignKeys(database, false);
applyBaseSchema(database);
applySchemaMigrations(database, {
assistantName: ASSISTANT_NAME,
});
setForeignKeys(database, true);
assertNoForeignKeyViolations(database);
}
export function openPersistentDatabase(): Database {
const dbPath = path.join(STORE_DIR, 'messages.db');
fs.mkdirSync(path.dirname(dbPath), { recursive: true });
const database = new Database(dbPath);
database.exec('PRAGMA journal_mode = WAL');
database.exec('PRAGMA busy_timeout = 5000');
return database;
}
export function openInMemoryDatabase(): Database {
return new Database(':memory:');
}
export function openDatabaseFromFile(dbPath: string): Database {
return new Database(dbPath);
}