111 lines
3.3 KiB
JavaScript
111 lines
3.3 KiB
JavaScript
const mysql = require('mysql2/promise');
|
||
require('dotenv').config();
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
// Create connection pool for better performance
|
||
const getSSLConfig = () => {
|
||
const useSSL = String(process.env.DB_SSL || '').toLowerCase() === 'true';
|
||
const caPath = process.env.DB_SSL_CA_PATH;
|
||
if (!useSSL) return undefined;
|
||
|
||
try {
|
||
if (caPath) {
|
||
const resolved = path.resolve(caPath);
|
||
if (fs.existsSync(resolved)) {
|
||
console.log('🔐 Loading DB CA certificate from:', resolved);
|
||
return {
|
||
ca: fs.readFileSync(resolved),
|
||
rejectUnauthorized: false // Allow self-signed / custom CA
|
||
};
|
||
} else {
|
||
console.warn('⚠️ CA file not found at path:', resolved, '- proceeding with rejectUnauthorized:false');
|
||
}
|
||
} else {
|
||
console.warn('⚠️ DB_SSL_CA_PATH not set - proceeding with empty CA and rejectUnauthorized:false');
|
||
}
|
||
} catch (e) {
|
||
console.warn('⚠️ Failed to load CA file:', e.message, '- proceeding with empty CA and rejectUnauthorized:false');
|
||
}
|
||
|
||
// Fallback: still provide object so mysql2 enables TLS
|
||
return {
|
||
rejectUnauthorized: false
|
||
};
|
||
};
|
||
|
||
const NODE_ENV = process.env.NODE_ENV || 'development';
|
||
|
||
let dbConfig;
|
||
if (NODE_ENV === 'development') {
|
||
dbConfig = {
|
||
host: process.env.DEV_DB_HOST || 'localhost',
|
||
port: Number(process.env.DEV_DB_PORT) || 3306,
|
||
user: process.env.DEV_DB_USER || 'root',
|
||
password: process.env.DEV_DB_PASSWORD || '', // XAMPP default: no password
|
||
database: process.env.DEV_DB_NAME || 'profitplanet_centralserver',
|
||
// Do NOT use SSL for development/XAMPP
|
||
ssl: undefined
|
||
};
|
||
} else {
|
||
dbConfig = {
|
||
host: process.env.DB_HOST,
|
||
port: Number(process.env.DB_PORT) || 3306,
|
||
user: process.env.DB_USER,
|
||
password: process.env.DB_PASSWORD,
|
||
database: process.env.DB_NAME,
|
||
ssl: getSSLConfig()
|
||
};
|
||
}
|
||
|
||
const pool = mysql.createPool({
|
||
...dbConfig,
|
||
waitForConnections: true,
|
||
connectionLimit: 10,
|
||
queueLimit: 0
|
||
});
|
||
|
||
console.log('📊 MySQL connection pool created (SSL:', !!process.env.DB_SSL, ')');
|
||
|
||
module.exports = {
|
||
// Execute query with parameters
|
||
async execute(query, params = []) {
|
||
try {
|
||
const [rows] = await pool.execute(query, params);
|
||
return rows;
|
||
} catch (error) {
|
||
console.error('💥 Database query error:', error.message);
|
||
throw error;
|
||
}
|
||
},
|
||
// Non-prepared query – avoids server-side prepared-statement issues
|
||
// (e.g. "Incorrect arguments to mysqld_stmt_execute" with dynamic SQL)
|
||
async query(query, params = []) {
|
||
return await pool.query(query, params);
|
||
},
|
||
// Get single row
|
||
async get(query, params = []) {
|
||
const rows = await this.execute(query, params);
|
||
return rows[0] || null;
|
||
},
|
||
// Get all rows
|
||
async all(query, params = []) {
|
||
return await this.execute(query, params);
|
||
},
|
||
// Close pool
|
||
async close() {
|
||
await pool.end();
|
||
console.log('📊 MySQL connection pool closed');
|
||
},
|
||
// Get a connection from the pool
|
||
async getConnection() {
|
||
return await pool.getConnection();
|
||
},
|
||
// Get a dedicated connection that allows multiple statements (for SQL dumps)
|
||
async getMultiStatementConnection() {
|
||
return await mysql.createConnection({
|
||
...dbConfig,
|
||
multipleStatements: true
|
||
});
|
||
}
|
||
}; |