diff --git a/src/db/locator.ts b/src/db/locator.ts new file mode 100644 index 0000000..9dcac53 --- /dev/null +++ b/src/db/locator.ts @@ -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(fn: (db: Database) => T | Promise): T | Promise { + const db = getDb(); + return fn(db); +} diff --git a/tests/unit/db/locator.test.ts b/tests/unit/db/locator.test.ts new file mode 100644 index 0000000..6d73758 --- /dev/null +++ b/tests/unit/db/locator.test.ts @@ -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 {} + }); +});