feat: añadir locator de DB con setDb/getDb/withDb y tests
Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>main
parent
02331790df
commit
9222242eda
@ -0,0 +1,37 @@
|
|||||||
|
import type { Database } from 'bun:sqlite';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error específico cuando se intenta acceder a la DB sin haberla configurado.
|
||||||
|
*/
|
||||||
|
export class DbNotConfiguredError extends Error {
|
||||||
|
constructor(message: string = 'Database has not been configured. Call setDb(db) before using getDb().') {
|
||||||
|
super(message);
|
||||||
|
this.name = 'DbNotConfiguredError';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentDb: Database | null = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establece la instancia global de DB.
|
||||||
|
* Se permite sobrescribir (útil en tests).
|
||||||
|
*/
|
||||||
|
export function setDb(db: Database): void {
|
||||||
|
currentDb = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtiene la instancia global de DB o lanza si no está configurada.
|
||||||
|
*/
|
||||||
|
export function getDb(): Database {
|
||||||
|
if (currentDb) return currentDb;
|
||||||
|
throw new DbNotConfiguredError('Database has not been configured. Call setDb(db) before using getDb().');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ejecuta una función con la DB actual (sync o async) y devuelve su resultado.
|
||||||
|
*/
|
||||||
|
export function withDb<T>(fn: (db: Database) => T | Promise<T>): T | Promise<T> {
|
||||||
|
const db = getDb();
|
||||||
|
return fn(db);
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
import Database from 'bun:sqlite';
|
||||||
|
import { describe, it, expect } from 'bun:test';
|
||||||
|
import { getDb, setDb, withDb, DbNotConfiguredError } from '../../../src/db/locator';
|
||||||
|
|
||||||
|
describe('db/locator', () => {
|
||||||
|
it('getDb lanza si no está configurada', () => {
|
||||||
|
expect(() => getDb()).toThrow(DbNotConfiguredError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('setDb y getDb devuelven la misma instancia', () => {
|
||||||
|
const db = new Database(':memory:');
|
||||||
|
setDb(db);
|
||||||
|
expect(getDb()).toBe(db);
|
||||||
|
try { db.close(); } catch {}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('withDb soporta callback síncrono', () => {
|
||||||
|
const db = new Database(':memory:');
|
||||||
|
setDb(db);
|
||||||
|
const result = withDb(d => {
|
||||||
|
expect(d).toBe(db);
|
||||||
|
return 42;
|
||||||
|
});
|
||||||
|
expect(result).toBe(42);
|
||||||
|
try { db.close(); } catch {}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('withDb soporta callback asíncrono', async () => {
|
||||||
|
const db = new Database(':memory:');
|
||||||
|
setDb(db);
|
||||||
|
const result = await withDb(async d => {
|
||||||
|
expect(d).toBe(db);
|
||||||
|
await Promise.resolve();
|
||||||
|
return 'ok';
|
||||||
|
});
|
||||||
|
expect(result).toBe('ok');
|
||||||
|
try { db.close(); } catch {}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('permitir sobrescritura de setDb', () => {
|
||||||
|
const db1 = new Database(':memory:');
|
||||||
|
const db2 = new Database(':memory:');
|
||||||
|
setDb(db1);
|
||||||
|
setDb(db2);
|
||||||
|
const got = getDb();
|
||||||
|
expect(got).toBe(db2);
|
||||||
|
try { db1.close(); } catch {}
|
||||||
|
try { db2.close(); } catch {}
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue