Files
administracionHospital/server/db.js
T
snlavaise e887d66411 Fix: solucionar error SQLITE_BUSY y mejorar backend
- Migrar de sqlite3 a better-sqlite3 con conexión persistente
- Configurar WAL mode, busy_timeout y PRAGMAs optimizados
- Implementar transacciones para operaciones bulk
- Corregir error initialLoadComplete en useHospitalStore.ts
- Agregar tablas usuarios y kv faltantes
- Actualizar .gitignore para archivos WAL de SQLite
2026-04-24 02:06:21 -03:00

213 lines
6.4 KiB
JavaScript

import Database from 'better-sqlite3';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import bcrypt from 'bcryptjs';
import { existsSync, mkdirSync } from 'fs';
const __dirname = dirname(fileURLToPath(import.meta.url));
const DB_PATH = __dirname + '/data/hospital.db';
// Ensure data directory exists
if (!existsSync(__dirname + '/data')) {
mkdirSync(__dirname + '/data', { recursive: true });
}
// Create persistent database connection with WAL mode and proper settings
const db = new Database(DB_PATH);
// Enable WAL mode for better concurrency
db.pragma('journal_mode = WAL');
// Set busy timeout to 5000ms (5 seconds)
db.pragma('busy_timeout = 5000');
// Additional performance and concurrency settings
db.pragma('synchronous = NORMAL');
db.pragma('cache_size = 1000');
db.pragma('temp_store = MEMORY');
db.pragma('mmap_size = 268435456'); // 256MB
export function getDb() {
return db;
}
function rowToObj(row) {
if (!row) return row;
const obj = {};
for (const key in row) {
const val = row[key];
try {
obj[key] = typeof val === 'string' && (val.startsWith('[') || val.startsWith('{')) ? JSON.parse(val) : val;
} catch {
obj[key] = val;
}
}
return obj;
}
export function getValue(key) {
const row = db.prepare('SELECT value FROM kv WHERE key = ?').get(key);
return row?.value ?? null;
}
export function setValue(key, value) {
const stmt = db.prepare('INSERT INTO kv (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value=excluded.value');
stmt.run(key, value);
}
export function getUsuarioByDni(dni) {
const row = db.prepare('SELECT * FROM usuarios WHERE dni = ?').get(dni);
return row || null;
}
export function getUsuarioById(id) {
const row = db.prepare('SELECT * FROM usuarios WHERE id = ?').get(id);
return row || null;
}
export function getAllUsuarios() {
const rows = db.prepare('SELECT * FROM usuarios ORDER BY apellido, nombre').all();
return rows;
}
export function createUsuario(usuario) {
const stmt = db.prepare(`INSERT INTO usuarios (id, apellido, nombre, dni, fechaNacimiento, email, rol, matriculaProfesional, passwordHash, areaId, fechaCreacion)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
stmt.run(
usuario.id,
usuario.apellido,
usuario.nombre,
usuario.dni,
usuario.fechaNacimiento,
usuario.email,
usuario.rol,
usuario.matriculaProfesional || null,
usuario.passwordHash,
usuario.areaId || null,
usuario.fechaCreacion
);
}
export function updateUsuario(id, datos) {
const fields = [];
const values = [];
if (datos.apellido !== undefined) { fields.push('apellido = ?'); values.push(datos.apellido); }
if (datos.nombre !== undefined) { fields.push('nombre = ?'); values.push(datos.nombre); }
if (datos.fechaNacimiento !== undefined) { fields.push('fechaNacimiento = ?'); values.push(datos.fechaNacimiento); }
if (datos.email !== undefined) { fields.push('email = ?'); values.push(datos.email); }
if (datos.rol !== undefined) { fields.push('rol = ?'); values.push(datos.rol); }
if (datos.matriculaProfesional !== undefined) { fields.push('matriculaProfesional = ?'); values.push(datos.matriculaProfesional); }
if (datos.passwordHash !== undefined) { fields.push('passwordHash = ?'); values.push(datos.passwordHash); }
if (datos.areaId !== undefined) { fields.push('areaId = ?'); values.push(datos.areaId); }
if (fields.length > 0) {
values.push(id);
db.prepare(`UPDATE usuarios SET ${fields.join(', ')} WHERE id = ?`).run(values);
}
}
export function deleteUsuario(id) {
db.prepare('DELETE FROM usuarios WHERE id = ?').run(id);
}
export function verifyPassword(dni, password) {
const row = db.prepare('SELECT passwordHash FROM usuarios WHERE dni = ?').get(dni);
if (!row) return false;
return bcrypt.compareSync(password, row.passwordHash);
}
export function hashPassword(password) {
return bcrypt.hashSync(password, 10);
}
export function getAllPacientes() {
const rows = db.prepare('SELECT * FROM pacientes').all();
return rows;
}
export function getAllAreas() {
const rows = db.prepare('SELECT * FROM areas').all();
return rows;
}
export function getAllCamas() {
const rows = db.prepare('SELECT * FROM camas').all();
return rows;
}
export function updateCama(id, updates) {
const fields = [];
const values = [];
if (updates.estado !== undefined) {
fields.push('estado = ?');
values.push(updates.estado);
}
if (updates.pacienteId !== undefined) {
fields.push('pacienteId = ?');
values.push(updates.pacienteId);
}
if (updates.internacionId !== undefined) {
fields.push('internacionId = ?');
values.push(updates.internacionId);
}
if (fields.length > 0) {
values.push(id);
db.prepare(`UPDATE camas SET ${fields.join(', ')} WHERE id = ?`).run(values);
}
}
export function getAllInternaciones() {
const rows = db.prepare('SELECT * FROM internaciones').all();
return rows.map(i => ({ ...i, activa: !!i.activa }));
}
export function getAllEvoluciones() {
const rows = db.prepare('SELECT * FROM evoluciones').all();
return rows.map(e => ({
...e,
signosVitales: typeof e.signosVitales === 'string' ? JSON.parse(e.signosVitales) : e.signosVitales,
examenFisico: typeof e.examenFisico === 'string' ? JSON.parse(e.examenFisico) : e.examenFisico
}));
}
export function getAllLaboratorios() {
const rows = db.prepare('SELECT * FROM laboratorios').all();
return rows.map(l => ({ ...l, resultados: typeof l.resultados === 'string' ? JSON.parse(l.resultados) : l.resultados }));
}
export function getAllAcidosBase() {
const rows = db.prepare('SELECT * FROM acidosbase').all();
return rows;
}
export function getAllCultivos() {
const rows = db.prepare('SELECT * FROM cultivos').all();
return rows;
}
export function getAllEstudiosComplementarios() {
const rows = db.prepare('SELECT * FROM estudiosComplementarios').all();
return rows;
}
export function getAllInterconsultas() {
const rows = db.prepare('SELECT * FROM interconsultas').all();
return rows.map(ic => ({ ...ic, realizada: !!ic.realizada }));
}
export function getAllAtb() {
const rows = db.prepare('SELECT * FROM atb').all();
return rows;
}
export function getAllIndicaciones() {
const rows = db.prepare('SELECT * FROM indicaciones').all();
return rows;
}
export function getAllMovimientosIndicaciones() {
const rows = db.prepare('SELECT * FROM movimientos_indicaciones').all();
return rows;
}