import { Pool, PoolClient, QueryResult, QueryResultRow } from 'pg'; import config from './index'; import logger from '../utils/logger'; const pool = new Pool({ host: config.database.host, port: config.database.port, user: config.database.user, password: config.database.password, database: config.database.database, ssl: config.database.ssl ? { rejectUnauthorized: false } : false, max: config.database.maxConnections, idleTimeoutMillis: config.database.idleTimeoutMs, connectionTimeoutMillis: config.database.connectionTimeoutMs, }); pool.on('connect', () => { logger.debug('New client connected to the database pool'); }); pool.on('error', (err: Error) => { logger.error('Unexpected error on idle database client', err); }); pool.on('remove', () => { logger.debug('Client removed from the database pool'); }); /** * Execute a query on the database pool * @param text - SQL query string * @param params - Query parameters * @returns Query result */ export const query = async ( text: string, params?: unknown[] ): Promise> => { const start = Date.now(); try { const result = await pool.query(text, params); const duration = Date.now() - start; logger.debug(`Query executed in ${duration}ms`, { query: text, rows: result.rowCount, }); return result; } catch (error) { logger.error('Database query error', { query: text, error: error instanceof Error ? error.message : 'Unknown error', }); throw error; } }; /** * Get a client from the pool for transactions * @returns Pool client */ export const getClient = async (): Promise => { try { const client = await pool.connect(); logger.debug('Database client acquired from pool'); return client; } catch (error) { logger.error('Failed to get database client', { error: error instanceof Error ? error.message : 'Unknown error', }); throw error; } }; /** * Test database connectivity * @returns True if connection is successful, false otherwise */ export const testConnection = async (): Promise => { try { const result = await pool.query('SELECT NOW()'); logger.info('Database connection successful', { serverTime: result.rows[0]?.now, }); return true; } catch (error) { logger.error('Database connection failed', { error: error instanceof Error ? error.message : 'Unknown error', }); return false; } }; /** * Close all pool connections (for graceful shutdown) */ export const closePool = async (): Promise => { try { await pool.end(); logger.info('Database pool closed'); } catch (error) { logger.error('Error closing database pool', { error: error instanceof Error ? error.message : 'Unknown error', }); throw error; } }; export { pool }; export default pool;