/* ! /database/commands.js ? The command library for mariadb */ // % imports import pools from './pools.js'; // functions "add(this)", "remove(this.name)", "status(name)" // = command manager class export default class Commands { constructor(name, db, protocol = 'read', address = process.env.DB_CONN_IP) { this.name = name; // persistent identifier this.address = address; // database adress (host) this.database = db; // database name this.protocol = protocol; // user protocol this.pool = null; // pool reference this.connStat = false; // connection status } // $ add a connection to the pool manager async connect() { console.log(`[Database] Connecting command instance "${this.name}" to database "${this.database}"...`); const result = await pools.add(this); this.connStat = result.connStat; this.pool = result.pool; console.log(`[Database] Connection status for "${this.name}": ${this.connStat ? 'SUCCESS' : 'FAILED'}`); } // $ remove a connection from the pool manager async disconnect() { if (this.connStat) { console.log(`[Database] Disconnecting instance "${this.name}"...`); const result = await pools.remove(this.name); this.connStat = result?.connStat ?? false; this.pool = null; console.log(`[Database] Instance "${this.name}" successfully disconnected.`); } } // $ get the status of a connection from the pool manager async status() { if (this.connStat) { console.log(`[Database] Checking status for instance "${this.name}"...`); const result = await pools.status(this.name); this.connStat = result?.connStat ?? false; this.pool = result?.pool ?? null; console.log(`[Database] Status for "${this.name}": Active = ${this.connStat}`); return result; } else { console.log(`[Database] Status check skipped for "${this.name}" (currently not connected).`); } } // $ execute an sql query async query(query, params = []) { // ~ check if connection is established if (!this.connStat || !this.pool) { console.error(`[Database Error] Tried to execute query on disconnected instance "${this.name}".`); throw new Error(`Database connection '${this.name}' is not established.`); } // ~ connection reference let conn; // ~ try executing the query try { conn = await this.pool.getConnection(); const rows = await conn.query(query, params); console.log(`[Database Query] [${this.name}] Executed successfully (${duration}ms):`, { query, params }); return rows; // ~ throw error if failed } catch(e) { console.error(`[Database Error] Query failed in "${this.name}":`, e.message); console.error(`[Failed Query]:`, query, params); throw e; // ~ release the connection back to the pool } finally { if (conn) conn.release(); } } // $ insert a record into a table async insert(table, data) { if (Object.keys(data).length === 0) return null; const keys = Object.keys(data); const values = Object.values(data); const placeholders = keys.map(() => '?').join(', '); const columns = keys.join(', '); const query = `INSERT INTO ${table} (${columns}) VALUES (${placeholders})`; return await this.query(query, values); } // $ update a record in a table async update(table, data, where, whereParams = []) { if (Object.keys(data).length === 0) return null; const keys = Object.keys(data); const values = Object.values(data); const setClause = keys.map(key => `${key} = ?`).join(', '); const query = `UPDATE ${table} SET ${setClause} WHERE ${where}`; return await this.query(query, [...values, ...whereParams]); } // $ select records from a table async select(table, columns = '*', where = '', params = []) { let query = `SELECT ${Array.isArray(columns) ? columns.join(', ') : columns} FROM ${table}`; if (where) { query += ` WHERE ${where}`; } return await this.query(query, params); } // $ delete records from a table async delete(table, where, params = []) { const query = `DELETE FROM ${table} WHERE ${where}`; return await this.query(query, params); } // $ create a new table async createTable(table, columns = 'id INT AUTO_INCREMENT PRIMARY KEY') { const query = `CREATE TABLE IF NOT EXISTS ${table} (${columns}) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci`; return await this.query(query); } // $ alter an existing table async alterTable(table, modificationClause) { const query = `ALTER TABLE ${table} ${modificationClause}`; return await this.query(query); } };