// backend/server/src/db.
js
// ESM module (import syntax). Uses mysql2/promise.
// Reads DB config from [Link] (no [Link] required).
import mysql from 'mysql2/promise';
/**
* Helper: parse boolean-ish env vars
*/
function envBool(name, defaultValue = false) {
const v = [Link][name];
if (v === undefined || v === null) return defaultValue;
return ['1', 'true', 'yes', 'on'].includes(String(v).toLowerCase());
}
/**
* Convert Date or ISO-like string to MySQL DATETIME (YYYY-MM-DD HH:MM:SS)
* - If param is a Date, convert and truncate milliseconds.
* - If param is a ISO datetime string like "2025-08-15T[Link].266Z", convert and
drop fractional & Z.
* - Otherwise return param as-is.
*/
export function toMySQLDateTime(value) {
if (value instanceof Date) {
return [Link]().slice(0, 19).replace('T', ' ');
}
if (typeof value === 'string') {
// Match ISO-like strings: YYYY-MM-DD[T ]HH:MM:SS(.sss)?Z?
const m = [Link](/^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}:\d{2})(?:\.\d+)?Z?
$/);
if (m) {
return `${m[1]} ${m[2]}`;
}
}
return value;
}
/**
* Build mysql2 connection options using [Link].
* If DATABASE_URL is provided, mysql2 accepts a connection string directly.
* Otherwise we assemble options from individual env vars.
*/
function buildPoolOptions() {
const dbUrl = [Link].DATABASE_URL && [Link].DATABASE_URL.trim();
const useSsl = envBool('DB_SSL', false);
if (dbUrl) {
// If DB_SSL is requested and mysql2 requires ssl object, we convert it below
by passing options object.
if (!useSsl) {
// simple: use connection string
return dbUrl;
}
// If SSL is required, parse connection string into object and add ssl options.
// We will let mysql2 parse the connection string by using URL class.
try {
const u = new URL(dbUrl);
const [user, password] = ([Link] || '') ? [[Link], [Link]] :
[undefined, undefined];
const host = [Link];
const port = [Link] ? Number([Link]) : 3306;
const database = [Link] ? [Link](/^\//, '') : undefined;
const ssl = {
// allow controlling rejecting unauthorized via env
rejectUnauthorized: envBool('DB_SSL_REJECT_UNAUTHORIZED', true),
};
return {
host,
port,
user,
password,
database,
waitForConnections: true,
connectionLimit: Number([Link].DB_CONN_LIMIT || 10),
queueLimit: 0,
ssl,
};
} catch (err) {
// fallback to passing the string
return dbUrl;
}
}
// Otherwise read individual environment variables (fallback)
return {
host: [Link].DB_HOST || '[Link]',
port: Number([Link].DB_PORT || 3306),
user: [Link].DB_USER || [Link].DATABASE_USER || 'root',
password: [Link].DB_PASS || [Link].DATABASE_PASSWORD || '',
database: [Link].DB_NAME || [Link].DATABASE_NAME || 'nurvio_hub',
waitForConnections: true,
connectionLimit: Number([Link].DB_CONN_LIMIT || 10),
queueLimit: 0,
ssl: useSsl ? { rejectUnauthorized: envBool('DB_SSL_REJECT_UNAUTHORIZED', true)
} : undefined,
};
}
/**
* Create pool (mysql2/promise supports either an options object or connection
string)
*/
const poolOptions = buildPoolOptions();
export const pool = typeof poolOptions === 'string'
? [Link](poolOptions)
: [Link](poolOptions);
/**
* Graceful close
*/
export async function closePool() {
try {
await [Link]();
} catch (err) {
// ignore or log
// [Link]('Error closing DB pool', err);
}
}
/**
* Normalizes params: convert Date and ISO-string datetimes to MySQL-friendly
format.
* Returns a new array.
*/
function normalizeParams(params) {
if (!params || ) return params;
return [Link]((p) => toMySQLDateTime(p));
}
/**
* run(sql, params) -> executes a query and returns rows
* Preserves previous behaviour; only normalizes date-like params.
*/
export async function run(sql, params = []) {
const normalized = normalizeParams(params);
const [rows] = await [Link](sql, normalized);
return rows;
}
/**
* [Link] convenience object to stay compatible with previous code
* Example usage: await [Link]('SELECT * FROM users WHERE id = ?', [id]);
*/
export const db = {
query: async (sql, params = []) => {
const normalized = normalizeParams(params);
const [rows] = await [Link](sql, normalized);
return rows;
},
// expose execute if needed
execute: async (sql, params = []) => {
const normalized = normalizeParams(params);
const [result] = await [Link](sql, normalized);
return result;
},
};
/**
* Optional small helper to test DB connectivity quickly (used in readiness probes)
*/
export async function ping() {
try {
const [rows] = await [Link]('SELECT 1');
return true;
} catch (err) {
return false;
}
}