HEX
Server: Apache/2.4.65 (Debian)
System: Linux kubikelcreative 5.10.0-35-amd64 #1 SMP Debian 5.10.237-1 (2025-05-19) x86_64
User: www-data (33)
PHP: 8.4.13
Disabled: NONE
Upload Files
File: /var/www/indoadvisory_new/web2/webapp/config/database.js
const { Pool } = require('pg');
require('dotenv').config();

// Database connection configuration for VPS PostgreSQL
const dbConfig = {
  host: process.env.DB_HOST || 'localhost',
  port: process.env.DB_PORT || 5432,
  database: process.env.DB_NAME || 'indo_advisory',
  user: process.env.DB_USER || 'indo_user',
  password: process.env.DB_PASSWORD,
  ssl: process.env.DB_SSL === 'true' ? {
    rejectUnauthorized: false // For self-signed certificates on VPS
  } : false,
  max: 20, // Maximum number of connections in the pool
  idleTimeoutMillis: 30000, // Close idle connections after 30 seconds
  connectionTimeoutMillis: 2000, // Return error if connection takes longer than 2 seconds
};

// Create connection pool for enterprise-grade performance
const pool = new Pool(dbConfig);

// Handle connection events
pool.on('connect', () => {
  console.log('✅ Connected to PostgreSQL database');
});

pool.on('error', (err) => {
  console.error('❌ PostgreSQL connection error:', err);
  process.exit(-1);
});

// Database utility functions
const db = {
  // Execute query with parameterized inputs (prevents SQL injection)
  query: async (text, params) => {
    const start = Date.now();
    try {
      const res = await pool.query(text, params);
      const duration = Date.now() - start;
      console.log('Executed query:', { text, duration, rows: res.rowCount });
      return res;
    } catch (err) {
      console.error('Database query error:', err);
      throw err;
    }
  },

  // Get a client from the pool for transactions
  getClient: async () => {
    return await pool.connect();
  },

  // Execute transaction
  transaction: async (callback) => {
    const client = await pool.connect();
    try {
      await client.query('BEGIN');
      const result = await callback(client);
      await client.query('COMMIT');
      return result;
    } catch (err) {
      await client.query('ROLLBACK');
      throw err;
    } finally {
      client.release();
    }
  },

  // Close all connections (for graceful shutdown)
  close: async () => {
    await pool.end();
    console.log('📦 Database connections closed');
  }
};

// Test database connection on startup
const testConnection = async () => {
  try {
    const client = await pool.connect();
    console.log('🔗 Database connection test successful');
    client.release();
  } catch (err) {
    console.error('❌ Database connection test failed:', err.message);
    
    // Provide helpful error messages for VPS setup
    if (err.code === 'ECONNREFUSED') {
      console.error('💡 Make sure PostgreSQL is running on your VPS');
      console.error('💡 Check if the database server is accepting connections');
    } else if (err.code === 'ENOTFOUND') {
      console.error('💡 Check your database host configuration');
    } else if (err.message.includes('authentication')) {
      console.error('💡 Check your database username and password');
    } else if (err.message.includes('database') && err.message.includes('does not exist')) {
      console.error('💡 Create the database first or check DB_NAME in .env');
    }
    
    throw err;
  }
};

module.exports = {
  db,
  pool,
  testConnection
};