const mysql = require('mysql2'); const config = require('./config.js'); const fs = require('fs-extra'); const PoolConnection = mysql.PoolConnection; module.exports = { init() { if (!this.pool) { const datasources = config.datasources; const pool = mysql.createPoolCluster(); for (let datasource of datasources) pool.add(datasource.name, datasource.options); this.pool = pool; } return this.pool; }, /** * Retuns a pool connection from specific cluster node * @param {String} name - The cluster name * * @return {Object} - Pool connection */ getConnection(name) { let pool = this.pool; return new Promise((resolve, reject) => { pool.getConnection(name, function(error, connection) { if (error) return reject(error); resolve(connection); }); }); }, /** * Makes a query from a raw sql * @param {String} query - The raw SQL query * @param {Object} params - Parameterized values * @param {Object} connection - Optional pool connection * * @return {Object} - Result promise */ rawSql(query, params, connection) { let pool = this.pool; if (params instanceof PoolConnection) connection = params; if (connection) pool = connection; return new Promise((resolve, reject) => { if (!connection) { pool.getConnection('default', function(error, conn) { if (error) return reject(error); conn.query(query, params, (error, rows) => { if (error) return reject(error); conn.release(); resolve(rows); }); }); } else { connection.query(query, params, (error, rows) => { if (error) return reject(error); resolve(rows); }); } }); }, /** * Makes a query from a SQL file * @param {String} queryName - The SQL file name * @param {Object} params - Parameterized values * @param {Object} connection - Optional pool connection * * @return {Object} - Result promise */ rawSqlFromDef(queryName, params, connection) { const query = fs.readFileSync(`${queryName}.sql`, 'utf8'); return this.rawSql(query, params, connection); }, /** * Returns the first row from a given raw sql * @param {String} query - The raw SQL query * @param {Object} params - Parameterized values * * @return {Object} - Result promise */ findOne(query, params) { return this.rawSql(query, params).then(([row]) => row); }, /** * Returns the first row from a given SQL file * @param {String} queryName - The SQL file name * @param {Object} params - Parameterized values * * @return {Object} - Result promise */ findOneFromDef(queryName, params) { return this.rawSqlFromDef(queryName, params) .then(([row]) => row); }, /** * Returns the first property from a given raw sql * @param {String} query - The raw SQL query * @param {Object} params - Parameterized values * * @return {Object} - Result promise */ findValue(query, params) { return this.findOne(query, params).then(row => { return Object.values(row)[0]; }); }, /** * Returns the first property from a given SQL file * @param {String} queryName - The SQL file name * @param {Object} params - Parameterized values * * @return {Object} - Result promise */ findValueFromDef(queryName, params) { return this.findOneFromDef(queryName, params).then(row => { return Object.values(row)[0]; }); }, /** * Returns the content of a SQL file * @param {String} queryName - The SQL file name * * @return {Object} - SQL */ getSqlFromDef(queryName) { return fs.readFileSync(`${queryName}.sql`, 'utf8'); }, /** * Merges two SQL strings * * @param {String} query - Input SQL * @param {String} sql - String to merge * * @return {String} - Merged SQL string */ merge(query, sql) { return query += `\r\n ${sql}`; }, /** * Builds where string * * @param {Object} args - Query params * @param {Function} callback - Callback * * @return {String} - Where Sql string */ buildWhere(args, callback) { let sql = ''; for (let prop in args) { const value = args[prop]; if (!value) continue; const sanitizedValue = mysql.escape(value); const conditional = callback(prop, sanitizedValue); if (!conditional) continue; if (sql) sql += ' AND '; sql += conditional; } let where = ''; if (sql) where = `WHERE ${sql}`; return where; } };