Refactor database integration to use bun:sqlite instead of better-sqlite3

- Updated import statements across multiple files to use bun:sqlite.
- Changed database query methods from `prepare` to `query` for consistency.
- Removed dependency on better-sqlite3 from package.json and adjusted package.json to specify bun as the engine.
- Modified hook installation process to eliminate unnecessary dependency installation.
- Updated migration scripts to align with bun:sqlite's API.
This commit is contained in:
Alex Newman
2025-10-15 15:03:43 -04:00
parent b5bfc029c3
commit 2663121d9f
14 changed files with 351 additions and 364 deletions
+31 -32
View File
@@ -1,22 +1,25 @@
import Database from 'better-sqlite3';
import { Database as BunDatabase } from 'bun:sqlite';
import path from 'path';
import fs from 'fs';
import { PathDiscovery } from '../path-discovery.js';
// Type alias for better-sqlite3 compatibility
type Database = BunDatabase;
export interface Migration {
version: number;
up: (db: Database.Database) => void;
down?: (db: Database.Database) => void;
up: (db: Database) => void;
down?: (db: Database) => void;
}
let dbInstance: Database.Database | null = null;
let dbInstance: Database | null = null;
/**
* SQLite Database singleton with migration support and optimized settings
*/
export class DatabaseManager {
private static instance: DatabaseManager;
private db: Database.Database | null = null;
private db: Database | null = null;
private migrations: Migration[] = [];
static getInstance(): DatabaseManager {
@@ -38,7 +41,7 @@ export class DatabaseManager {
/**
* Initialize database connection with optimized settings
*/
async initialize(): Promise<Database.Database> {
async initialize(): Promise<Database> {
if (this.db) {
return this.db;
}
@@ -48,15 +51,15 @@ export class DatabaseManager {
fs.mkdirSync(dataDir, { recursive: true });
const dbPath = path.join(dataDir, 'claude-mem.db');
this.db = new Database(dbPath);
this.db = new BunDatabase(dbPath, { create: true, readwrite: true });
// Apply optimized SQLite settings
this.db.pragma('journal_mode = WAL');
this.db.pragma('synchronous = NORMAL');
this.db.pragma('foreign_keys = ON');
this.db.pragma('temp_store = memory');
this.db.pragma('mmap_size = 268435456'); // 256MB
this.db.pragma('cache_size = 10000');
this.db.run('PRAGMA journal_mode = WAL');
this.db.run('PRAGMA synchronous = NORMAL');
this.db.run('PRAGMA foreign_keys = ON');
this.db.run('PRAGMA temp_store = memory');
this.db.run('PRAGMA mmap_size = 268435456'); // 256MB
this.db.run('PRAGMA cache_size = 10000');
// Initialize schema_versions table
this.initializeSchemaVersions();
@@ -71,7 +74,7 @@ export class DatabaseManager {
/**
* Get the current database connection
*/
getConnection(): Database.Database {
getConnection(): Database {
if (!this.db) {
throw new Error('Database not initialized. Call initialize() first.');
}
@@ -81,7 +84,7 @@ export class DatabaseManager {
/**
* Execute a function within a transaction
*/
withTransaction<T>(fn: (db: Database.Database) => T): T {
withTransaction<T>(fn: (db: Database) => T): T {
const db = this.getConnection();
const transaction = db.transaction(fn);
return transaction(db);
@@ -104,7 +107,7 @@ export class DatabaseManager {
private initializeSchemaVersions(): void {
if (!this.db) return;
this.db.exec(`
this.db.run(`
CREATE TABLE IF NOT EXISTS schema_versions (
id INTEGER PRIMARY KEY,
version INTEGER UNIQUE NOT NULL,
@@ -119,23 +122,20 @@ export class DatabaseManager {
private async runMigrations(): Promise<void> {
if (!this.db) return;
const appliedVersions = this.db
.prepare('SELECT version FROM schema_versions ORDER BY version')
.all()
.map((row: any) => row.version);
const query = this.db.query('SELECT version FROM schema_versions ORDER BY version');
const appliedVersions = query.all().map((row: any) => row.version);
const maxApplied = appliedVersions.length > 0 ? Math.max(...appliedVersions) : 0;
for (const migration of this.migrations) {
if (migration.version > maxApplied) {
console.log(`Applying migration ${migration.version}...`);
const transaction = this.db.transaction(() => {
migration.up(this.db!);
this.db!
.prepare('INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)')
.run(migration.version, new Date().toISOString());
const insertQuery = this.db!.query('INSERT INTO schema_versions (version, applied_at) VALUES (?, ?)');
insertQuery.run(migration.version, new Date().toISOString());
});
transaction();
@@ -150,9 +150,8 @@ export class DatabaseManager {
getCurrentVersion(): number {
if (!this.db) return 0;
const result = this.db
.prepare('SELECT MAX(version) as version FROM schema_versions')
.get() as { version: number } | undefined;
const query = this.db.query('SELECT MAX(version) as version FROM schema_versions');
const result = query.get() as { version: number } | undefined;
return result?.version || 0;
}
@@ -161,7 +160,7 @@ export class DatabaseManager {
/**
* Get the global database instance (for compatibility)
*/
export function getDatabase(): Database.Database {
export function getDatabase(): Database {
if (!dbInstance) {
throw new Error('Database not initialized. Call DatabaseManager.getInstance().initialize() first.');
}
@@ -171,9 +170,9 @@ export function getDatabase(): Database.Database {
/**
* Initialize and get database manager
*/
export async function initializeDatabase(): Promise<Database.Database> {
export async function initializeDatabase(): Promise<Database> {
const manager = DatabaseManager.getInstance();
return await manager.initialize();
}
export { Database };
export { BunDatabase as Database };