const mysql = require("mysql2/promise"); const { Client } = require("ssh2"); const { Pool } = require('pg'); const dotenv = require("dotenv"); const path = require("path"); // Helper function to setup SSH tunnel async function setupSshTunnel(sshConfig) { return new Promise((resolve, reject) => { const ssh = new Client(); ssh.on('error', (err) => { console.error('SSH connection error:', err); }); ssh.on('end', () => { console.log('SSH connection ended normally'); }); ssh.on('close', () => { console.log('SSH connection closed'); }); ssh .on("ready", () => { ssh.forwardOut( "127.0.0.1", 0, sshConfig.prodDbConfig.host, sshConfig.prodDbConfig.port, async (err, stream) => { if (err) reject(err); resolve({ ssh, stream }); } ); }) .connect(sshConfig.ssh); }); } // Helper function to setup database connections async function setupConnections(sshConfig) { const tunnel = await setupSshTunnel(sshConfig); // Setup MySQL connection for production const prodConnection = await mysql.createConnection({ ...sshConfig.prodDbConfig, stream: tunnel.stream, }); // Setup PostgreSQL connection pool for local const localPool = new Pool(sshConfig.localDbConfig); // Test the PostgreSQL connection try { const client = await localPool.connect(); await client.query('SELECT NOW()'); client.release(); console.log('PostgreSQL connection successful'); } catch (err) { console.error('PostgreSQL connection error:', err); throw err; } // Create a wrapper for the PostgreSQL pool to match MySQL interface const localConnection = { query: async (text, params) => { const client = await localPool.connect(); try { const result = await client.query(text, params); return [result]; } finally { client.release(); } }, end: async () => { await localPool.end(); } }; return { ssh: tunnel.ssh, prodConnection, localConnection }; } // Helper function to close connections async function closeConnections(connections) { const { ssh, prodConnection, localConnection } = connections; try { if (prodConnection) await prodConnection.end(); if (localConnection) await localConnection.end(); // Wait a bit for any pending data to be written before closing SSH await new Promise(resolve => setTimeout(resolve, 100)); if (ssh) { ssh.on('close', () => { console.log('SSH connection closed cleanly'); }); ssh.end(); } } catch (err) { console.error('Error during cleanup:', err); } } module.exports = { setupConnections, closeConnections };