|
|
|
|
@ -60,54 +60,81 @@ async function openDb(filename: string = 'tasks.db'): Promise<any> {
|
|
|
|
|
const instance = new DatabaseCtor(absolutePath);
|
|
|
|
|
applyDefaultPragmas(instance);
|
|
|
|
|
|
|
|
|
|
// Auto-inicialización y seed sólo en desarrollo y primer arranque
|
|
|
|
|
if (firstCreate && isDev() && DEV_AUTOSEED_DB) {
|
|
|
|
|
// Detectar entorno Bun vs Node (Vite dev)
|
|
|
|
|
const isBun = typeof (globalThis as any).Bun !== 'undefined';
|
|
|
|
|
// Auto-inicialización de esquema en desarrollo si falta y seed opcional
|
|
|
|
|
if (isDev()) {
|
|
|
|
|
// ¿Existe la tabla principal?
|
|
|
|
|
let hasTasksTable = false;
|
|
|
|
|
try {
|
|
|
|
|
instance.prepare(`SELECT 1 FROM tasks LIMIT 1`).get();
|
|
|
|
|
hasTasksTable = true;
|
|
|
|
|
} catch {}
|
|
|
|
|
|
|
|
|
|
if (isBun) {
|
|
|
|
|
// En Bun podemos reutilizar initializeDatabase del repo principal
|
|
|
|
|
try {
|
|
|
|
|
const dbModule = await import('../../../../../src/db');
|
|
|
|
|
if (typeof (dbModule as any).initializeDatabase === 'function') {
|
|
|
|
|
(dbModule as any).initializeDatabase(instance);
|
|
|
|
|
// Si no existe el esquema, aplicar inicialización/migraciones
|
|
|
|
|
if (!hasTasksTable) {
|
|
|
|
|
const isBun = typeof (globalThis as any).Bun !== 'undefined';
|
|
|
|
|
|
|
|
|
|
if (isBun) {
|
|
|
|
|
// En Bun podemos reutilizar initializeDatabase del repo principal
|
|
|
|
|
try {
|
|
|
|
|
const dbModule = await import('../../../../../src/db');
|
|
|
|
|
if (typeof (dbModule as any).initializeDatabase === 'function') {
|
|
|
|
|
(dbModule as any).initializeDatabase(instance);
|
|
|
|
|
hasTasksTable = true;
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] No se pudo ejecutar initializeDatabase en dev (Bun):', e);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// En SSR Node: aplicar migraciones directamente con compat para .query
|
|
|
|
|
try {
|
|
|
|
|
const mod = await import('../../../../../src/db/migrations/index.ts');
|
|
|
|
|
const list = (mod as any).migrations as any[];
|
|
|
|
|
const compat: any = instance;
|
|
|
|
|
if (typeof compat.query !== 'function') {
|
|
|
|
|
compat.query = (sql: string) => ({
|
|
|
|
|
all: () => compat.prepare(sql).all(),
|
|
|
|
|
get: () => compat.prepare(sql).get()
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
try { compat.exec?.(`PRAGMA foreign_keys = ON;`); } catch {}
|
|
|
|
|
for (const m of list) {
|
|
|
|
|
try {
|
|
|
|
|
await (m.up as any)(compat);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] Error aplicando migración en dev (Node):', (m as any)?.name ?? '(sin nombre)', e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Verificar de nuevo
|
|
|
|
|
try {
|
|
|
|
|
compat.prepare(`SELECT 1 FROM tasks LIMIT 1`).get();
|
|
|
|
|
hasTasksTable = true;
|
|
|
|
|
} catch {}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] No se pudieron aplicar migraciones en dev (Node):', e);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] No se pudo ejecutar initializeDatabase en dev (Bun):', e);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// En SSR Node: aplicar migraciones directamente con compat para .query
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Seed de datos de demo si está habilitado y la tabla está vacía
|
|
|
|
|
if (DEV_AUTOSEED_DB) {
|
|
|
|
|
try {
|
|
|
|
|
const mod = await import('../../../../../src/db/migrations/index.ts');
|
|
|
|
|
const list = (mod as any).migrations as any[];
|
|
|
|
|
const compat: any = instance;
|
|
|
|
|
if (typeof compat.query !== 'function') {
|
|
|
|
|
compat.query = (sql: string) => ({
|
|
|
|
|
all: () => compat.prepare(sql).all(),
|
|
|
|
|
get: () => compat.prepare(sql).get()
|
|
|
|
|
});
|
|
|
|
|
let count = 0;
|
|
|
|
|
try {
|
|
|
|
|
const row = instance.prepare(`SELECT COUNT(1) AS c FROM tasks`).get() as any;
|
|
|
|
|
count = Number(row?.c ?? 0);
|
|
|
|
|
} catch {
|
|
|
|
|
// Si aún no existe la tabla, no seedear
|
|
|
|
|
count = 0;
|
|
|
|
|
}
|
|
|
|
|
try { compat.exec?.(`PRAGMA foreign_keys = ON;`); } catch {}
|
|
|
|
|
for (const m of list) {
|
|
|
|
|
try {
|
|
|
|
|
await (m.up as any)(compat);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] Error aplicando migración en dev (Node):', (m as any)?.name ?? '(sin nombre)', e);
|
|
|
|
|
if (count === 0) {
|
|
|
|
|
const seed = await import('./dev-seed');
|
|
|
|
|
if (typeof (seed as any).seedDev === 'function') {
|
|
|
|
|
await (seed as any).seedDev(instance, DEV_DEFAULT_USER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] No se pudieron aplicar migraciones en dev (Node):', e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Seed de datos de demo
|
|
|
|
|
try {
|
|
|
|
|
const seed = await import('./dev-seed');
|
|
|
|
|
if (typeof (seed as any).seedDev === 'function') {
|
|
|
|
|
await (seed as any).seedDev(instance, DEV_DEFAULT_USER);
|
|
|
|
|
console.warn('[web/db] No se pudo realizar el seed de datos de demo:', e);
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.warn('[web/db] No se pudo realizar el seed de datos de demo:', e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|