mirror of https://github.com/Fabio286/antares.git
292 lines
7.4 KiB
JavaScript
292 lines
7.4 KiB
JavaScript
'use strict';
|
|
import mysql from 'mysql';
|
|
import mssql from 'mssql';
|
|
// import pg from 'pg'; TODO: PostgreSQL
|
|
|
|
/**
|
|
* As Simple As Possible Query Builder
|
|
*
|
|
* @export
|
|
* @class AntaresConnector
|
|
*/
|
|
export class AntaresConnector {
|
|
/**
|
|
*Creates an instance of AntaresConnector.
|
|
* @param {Object} args connection params
|
|
* @memberof AntaresConnector
|
|
*/
|
|
constructor (args) {
|
|
this._client = args.client;
|
|
this._params = args.params;
|
|
this._poolSize = args.poolSize || false;
|
|
this._connection = null;
|
|
this._logger = args.logger || console.log;
|
|
|
|
this._queryDefaults = {
|
|
schema: '',
|
|
select: [],
|
|
from: '',
|
|
where: [],
|
|
groupBy: [],
|
|
orderBy: [],
|
|
limit: [],
|
|
join: [],
|
|
update: [],
|
|
insert: [],
|
|
delete: false
|
|
};
|
|
this._query = Object.assign({}, this._queryDefaults);
|
|
}
|
|
|
|
_reducer (acc, curr) {
|
|
const type = typeof curr;
|
|
|
|
switch (type) {
|
|
case 'number':
|
|
case 'string':
|
|
return [...acc, curr];
|
|
case 'object':
|
|
if (Array.isArray(curr))
|
|
return [...acc, ...curr];
|
|
else {
|
|
const clausoles = [];
|
|
for (const key in curr)
|
|
clausoles.push(`${key} ${curr[key]}`);
|
|
|
|
return clausoles;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resets the query object after a query
|
|
*
|
|
* @memberof AntaresConnector
|
|
*/
|
|
_resetQuery () {
|
|
this._query = Object.assign({}, this._queryDefaults);
|
|
}
|
|
|
|
/**
|
|
* @memberof AntaresConnector
|
|
*/
|
|
async connect () {
|
|
switch (this._client) {
|
|
case 'maria':
|
|
case 'mysql':
|
|
if (!this._poolSize)
|
|
this._connection = mysql.createConnection(this._params);
|
|
else
|
|
this._connection = mysql.createPool({ ...this._params, connectionLimit: this._poolSize });
|
|
break;
|
|
case 'mssql': {
|
|
const mssqlParams = {
|
|
user: this._params.user,
|
|
password: this._params.password,
|
|
server: this._params.host
|
|
};
|
|
this._connection = await mssql.connect(mssqlParams);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
schema (schema) {
|
|
this._query.schema = schema;
|
|
return this;
|
|
}
|
|
|
|
select (...args) {
|
|
this._query.select = [...this._query.select, ...args];
|
|
return this;
|
|
}
|
|
|
|
from (table) {
|
|
this._query.from = table;
|
|
return this;
|
|
}
|
|
|
|
delete (table) {
|
|
this._query.delete = true;
|
|
this.from(table);
|
|
return this;
|
|
}
|
|
|
|
where (...args) {
|
|
this._query.where = [...this._query.where, ...args];
|
|
return this;
|
|
}
|
|
|
|
groupBy (...args) {
|
|
this._query.groupBy = [...this._query.groupBy, ...args];
|
|
return this;
|
|
}
|
|
|
|
orderBy (...args) {
|
|
this._query.orderBy = [...this._query.orderBy, ...args];
|
|
return this;
|
|
}
|
|
|
|
limit (...args) {
|
|
this._query.limit = args;
|
|
return this;
|
|
}
|
|
|
|
use (schema) {
|
|
let sql;
|
|
|
|
switch (this._client) {
|
|
case 'maria':
|
|
case 'mysql':
|
|
sql = `USE \`${schema}\``;
|
|
break;
|
|
case 'mssql':
|
|
sql = `USE "${schema}"`;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return this.raw(sql);
|
|
}
|
|
|
|
/**
|
|
* @param {String | Array} args field = value
|
|
* @returns
|
|
* @memberof AntaresConnector
|
|
*/
|
|
update (...args) {
|
|
this._query.update = [...this._query.update, ...args];
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @returns {string} SQL string
|
|
* @memberof AntaresConnector
|
|
*/
|
|
getSQL () {
|
|
// SELECT
|
|
const selectArray = this._query.select.reduce(this._reducer, []);
|
|
let selectRaw = '';
|
|
if (selectArray.length) {
|
|
switch (this._client) {
|
|
case 'maria':
|
|
case 'mysql':
|
|
selectRaw = selectArray.length ? `SELECT ${selectArray.join(', ')} ` : 'SELECT * ';
|
|
break;
|
|
case 'mssql': {
|
|
const topRaw = this._query.limit.length ? ` TOP (${this._query.limit[0]}) ` : '';
|
|
selectRaw = selectArray.length ? `SELECT${topRaw} ${selectArray.join(', ')} ` : 'SELECT * ';
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// FROM
|
|
let fromRaw = '';
|
|
if (!this._query.update.length && !!this._query.from)
|
|
fromRaw = 'FROM';
|
|
|
|
switch (this._client) {
|
|
case 'maria':
|
|
case 'mysql':
|
|
fromRaw += this._query.from ? ` ${this._query.schema ? `\`${this._query.schema}\`.` : ''}\`${this._query.from}\` ` : '';
|
|
break;
|
|
case 'mssql':
|
|
fromRaw += this._query.from ? ` ${this._query.schema ? `${this._query.schema}.` : ''}${this._query.from} ` : '';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
const whereArray = this._query.where.reduce(this._reducer, []);
|
|
const whereRaw = whereArray.length ? `WHERE ${whereArray.join(' AND ')} ` : '';
|
|
|
|
const updateArray = this._query.update.reduce(this._reducer, []);
|
|
const updateRaw = updateArray.length ? `SET ${updateArray.join(', ')} ` : '';
|
|
|
|
const groupByArray = this._query.groupBy.reduce(this._reducer, []);
|
|
const groupByRaw = groupByArray.length ? `GROUP BY ${groupByArray.join(', ')} ` : '';
|
|
|
|
const orderByArray = this._query.orderBy.reduce(this._reducer, []);
|
|
const orderByRaw = orderByArray.length ? `ORDER BY ${orderByArray.join(', ')} ` : '';
|
|
|
|
// LIMIT
|
|
let limitRaw;
|
|
switch (this._client) {
|
|
case 'maria':
|
|
case 'mysql':
|
|
limitRaw = this._query.limit.length ? `LIMIT ${this._query.limit.join(', ')} ` : '';
|
|
break;
|
|
case 'mssql':
|
|
limitRaw = '';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return `${selectRaw}${updateRaw ? 'UPDATE' : ''}${this._query.delete ? 'DELETE ' : ''}${fromRaw}${updateRaw}${whereRaw}${groupByRaw}${orderByRaw}${limitRaw}`;
|
|
}
|
|
|
|
/**
|
|
* @returns {Promise}
|
|
* @memberof AntaresConnector
|
|
*/
|
|
async run () {
|
|
const rawQuery = this.getSQL();
|
|
this._resetQuery();
|
|
return this.raw(rawQuery);
|
|
}
|
|
|
|
/**
|
|
* @param {string} sql raw SQL query
|
|
* @returns {Promise}
|
|
* @memberof AntaresConnector
|
|
*/
|
|
async raw (sql) {
|
|
if (process.env.NODE_ENV === 'development') this._logger(sql);
|
|
|
|
switch (this._client) { // TODO: uniform fields with every client type, needed table name and fields array
|
|
case 'maria':
|
|
case 'mysql': {
|
|
const { rows, fields } = await new Promise((resolve, reject) => {
|
|
this._connection.query(sql, (err, rows, fields) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve({ rows, fields });
|
|
});
|
|
});
|
|
return { rows, fields };
|
|
}
|
|
case 'mssql': {
|
|
const results = await this._connection.request().query(sql);
|
|
return { rows: results.recordsets[0] };// TODO: fields
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @memberof AntaresConnector
|
|
*/
|
|
destroy () {
|
|
switch (this._client) {
|
|
case 'maria':
|
|
case 'mysql':
|
|
this._connection.end();
|
|
break;
|
|
case 'mssql':
|
|
this._connection.close();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|