add more to the inital migration, and refactor the locations of types

This commit is contained in:
2025-05-25 17:55:04 -06:00
parent da35b225cd
commit 83771caee1
6 changed files with 207 additions and 85 deletions

97
src/services/database.ts Normal file
View File

@@ -0,0 +1,97 @@
// Add type declarations for external modules
declare module '@jlongster/sql.js';
declare module 'absurd-sql';
declare module 'absurd-sql/dist/indexeddb-backend';
import initSqlJs from '@jlongster/sql.js';
import { SQLiteFS } from 'absurd-sql';
import IndexedDBBackend from 'absurd-sql/dist/indexeddb-backend';
import { runMigrations } from '../db-sql/migration';
import { QueryExecResult } from './migrationService';
interface SQLDatabase {
exec: (sql: string, params?: any[]) => Promise<QueryExecResult[]>;
run: (sql: string, params?: any[]) => Promise<{ changes: number; lastId?: number }>;
}
class DatabaseService {
private db: SQLDatabase | null;
private initialized: boolean;
constructor() {
this.db = null;
this.initialized = false;
}
async initialize(): Promise<void> {
if (this.initialized) return;
const SQL = await initSqlJs({
locateFile: (file: string) => {
return new URL(`/node_modules/@jlongster/sql.js/dist/${file}`, import.meta.url).href;
}
});
let sqlFS = new SQLiteFS(SQL.FS, new IndexedDBBackend());
SQL.register_for_idb(sqlFS);
SQL.FS.mkdir('/sql');
SQL.FS.mount(sqlFS, {}, '/sql');
const path = '/sql/db.sqlite';
if (typeof SharedArrayBuffer === 'undefined') {
let stream = SQL.FS.open(path, 'a+');
await stream.node.contents.readIfFallback();
SQL.FS.close(stream);
}
this.db = new SQL.Database(path, { filename: true });
if (!this.db) {
throw new Error('Failed to initialize database');
}
await this.db.exec(`
PRAGMA journal_mode=MEMORY;
`);
const sqlExec = this.db.exec.bind(this.db);
// Run migrations
await runMigrations(sqlExec);
this.initialized = true;
}
private ensureInitialized(): void {
if (!this.initialized || !this.db) {
throw new Error('Database not initialized');
}
}
// Used for inserts, updates, and deletes
async run(sql: string, params: any[] = []): Promise<{ changes: number; lastId?: number }> {
this.ensureInitialized();
return this.db!.run(sql, params);
}
async query(sql: string, params: any[] = []): Promise<QueryExecResult[]> {
this.ensureInitialized();
return this.db!.exec(sql, params);
}
async get(sql: string, params: any[] = []): Promise<any[] | undefined> {
this.ensureInitialized();
const result = await this.db!.exec(sql, params);
return result[0]?.values[0];
}
async all(sql: string, params: any[] = []): Promise<any[][]> {
this.ensureInitialized();
const result = await this.db!.exec(sql, params);
return result[0]?.values || [];
}
}
// Create a singleton instance
const databaseService = new DatabaseService();
export default databaseService;