// poolSingleton.mjs // Conexión Singleton a base de datos (pg/Pool) para CORE y TENANTS. // Cambios mínimos respecto a tu versión original. import { Pool } from 'pg'; // Utilidad mínima para booleans const isTrue = (v) => String(v).toLowerCase() === 'true'; // --------------------- CORE --------------------- class DatabaseCore { static instance = null; constructor() { if (DatabaseCore.instance) { return DatabaseCore.instance; // <-- corrección: antes devolvía Database.instance } const host = process.env.CORE_DB_HOST; const user = process.env.CORE_DB_USER; const password = process.env.CORE_DB_PASS; const database = process.env.CORE_DB_NAME; const port = process.env.CORE_DB_PORT; const ssl = isTrue(process.env.CORE_PGSSL ?? process.env.PGSSL) ? { rejectUnauthorized: false } : undefined; const config = { host, user, password, database, port: port ? Number(port) : undefined, ssl, }; this.host = host; this.dbName = database; this.connection = new Pool(config); DatabaseCore.instance = this; } async query(sql, params) { return this.connection.query(sql, params); } async connect() { // idempotente a nivel de pool; retorna un client return this.connection.connect(); } async getClient() { // alias simple, conserva tu API return this.connection.connect(); } async release() { // cierra TODO el pool (uso excepcional) await this.connection.end(); } } // --------------------- TENANTS --------------------- class DatabaseTenants { static instance = null; constructor() { if (DatabaseTenants.instance) { return DatabaseTenants.instance; // <-- corrección: antes devolvía Database.instance } const host = process.env.TENANTS_DB_HOST; const user = process.env.TENANTS_DB_USER; const password = process.env.TENANTS_DB_PASS; const database = process.env.TENANTS_DB_NAME; const port = process.env.TENANTS_DB_PORT; const ssl = isTrue(process.env.TENANTS_PGSSL ?? process.env.PGSSL) ? { rejectUnauthorized: false } : undefined; const config = { host, user, password, database, port: port ? Number(port) : undefined, ssl, }; this.host = host; this.dbName = database; this.connection = new Pool(config); DatabaseTenants.instance = this; } async query(sql, params) { return this.connection.query(sql, params); } async connect() { // idempotente a nivel de pool; retorna un client return this.connection.connect(); } async getClient() { // alias simple, conserva tu API return this.connection.connect(); } async release() { // cierra TODO el pool (uso excepcional) await this.connection.end(); } } // Instancias únicas por el cache de módulos de Node/ESM + guardas estáticas const poolCore = new DatabaseCore(); const poolTenants = new DatabaseTenants(); // --------------------- Healthchecks aquí dentro --------------------- async function verificarConexionCore() { try { console.log(`[ PG ] Comprobando accesibilidad a la db ${poolCore.dbName} del host ${poolCore.host} ...`); const client = await poolCore.getClient(); const { rows } = await client.query('SELECT NOW() AS ahora'); console.log(`[ PG ] Conexión con ${poolCore.dbName} OK. Hora DB:`, rows[0].ahora); client.release(); } catch (error) { console.error('[ PG ] Error al conectar con la base de datos al iniciar:', error.message); console.error('[ PG ] Revisar credenciales, accesos de red y firewall.'); } } async function verificarConexionTenants() { try { console.log(`[ PG ] Comprobando accesibilidad a la db ${poolTenants.dbName} del host ${poolTenants.host} ...`); const client = await poolTenants.getClient(); const { rows } = await client.query('SELECT NOW() AS ahora'); console.log(`[ PG ] Conexión con ${poolTenants.dbName} OK. Hora DB:`, rows[0].ahora); client.release(); } catch (error) { console.error('[ PG ] Error al conectar con la base de datos al iniciar:', error.message); console.error('[ PG ] Revisar credenciales, accesos de red y firewall.'); } } // Exports (mantengo tu patrón) export default { poolCore, poolTenants, verificarConexionCore, verificarConexionTenants }; export { poolCore, poolTenants, verificarConexionCore, verificarConexionTenants }; // export { DatabaseCore, DatabaseTenants }; // si lo necesitás para tests