UNPKG

@bee.js/node

Version:

A JavaScript framework for making Node.js API´s

360 lines (302 loc) 9.42 kB
const mysql = require("mysql2/promise"); //https://evertpot.com/executing-a-mysql-query-in-nodejs/ const beeTools = require("../../tools/beeTools"); const parseArray = function (param) { switch (typeof param) { case "string": return param.split(",").map((a) => a.trim()); case "object": return Object.values(param); default: return param || []; } }; const quote = function (word, type = this.configs.databases.default.type) { let escape; switch (type) { case "mysql": escape = "``"; break; case "mssql": escape = "[]"; break; default: escape = type + type; break; } return escape[0] + word + escape[1]; }; const stringBind = function (_string, params = {}) { for (let param of Object.keys(params)) _string = _string.replace(":" + param, `'${params[param]}'`); // TODO fazer replace global (Expressao regular) quando a palavra a ser substituida for iniciada com o caractere : return _string; }; const modelSqlSelectFields = function (model, onlyFields = []) { let fields = []; model.fields ? (fields = parseArray(model.fields)) : Object.keys(model.schema).map((field) => { if ( model.schema[field].out === false || (onlyFields.length && !onlyFields.includes(field)) ) return; switch (model.schema[field].type) { case "uuid": case "guid": fields.push(`BIN_TO_UUID(${model.table}.${field}) as ${field}`); break; default: fields.push(`${model.table}.${field}`); } }); return fields; }; const modelSqlWhere = function ( model, vals, middlewareParams, callsWhere = [] ) { const q = quote; const keys = parseArray(model.indexes?.keys || ""); let SQL = ""; let gWhere = model.globalWhere ? q(model.globalWhere, "()") : ""; gWhere = gWhere && middlewareParams ? stringBind(gWhere, middlewareParams) : ""; if (typeof vals !== "object") vals = [vals]; vals.map((val, i) => keys.map((k) => { switch ( model.schema[k].type //TODO encapsule ) { case "guid": case "uuid": vals[i] = `UUID_TO_BIN('${val}')`; break; default: vals[i] = `'${val}'`; } }) ); switch (vals.length) { case 0: SQL += gWhere ? ` WHERE ${gWhere}` : ""; break; case 1: SQL += ` WHERE ${model.table}.${keys[0]} = ${vals[0]} ${ gWhere ? "AND " + gWhere : "" }`; break; default: SQL += typeof vals == "object" ? ` WHERE ${model.table}.${keys[0]} IN('${vals.join("','")}') ${ gWhere ? "AND " + gWhere : "" }` : ` WHERE ${model.table}.${keys[0]} IN(${vals}) ${ gWhere ? "AND " + gWhere : "" }`; } if (callsWhere.length) SQL += `WHERE ${callsWhere.join(" AND ")}`; return SQL; }; module.exports = { escape, quote, stringBind, parseArray, modelSqlWhere, modelSqlSelectFields, createPool: function (configs) { // TODO criar aviso de error para falta de configs.db. Criar no hive().create // TODO pegar dinamicamnete database utilizada let db = configs.databases.default; let pool; switch (db.type) { case "mssql": // TODO implementar na versao >=1.2 return false; case "mongo": // TODO implementar na versao >=1.2 return false; default: pool = mysql.createPool({ acquireTimeout: 10000, // Tempo limite para tentar adquirir uma nova conexão connectTimeout: 10000, // Tempo limite para conectar ao banco de dados idleTimeout: 60000, // Tempo que uma conexão pode ficar inativa antes de ser fechada reconnect: true, enableKeepAlive: true, ...db, host: db.host, user: db.user, password: db.pass, database: db.name, waitForConnections: db.waitForConnections || true, connectionLimit: db.connectionLimit || 10, queueLimit: db.queueLimit || 0, }); if (db.ping) setInterval(async () => { console.log("ping db"); try { const connection = await pool.getConnection(); await connection.ping(); connection.release(); } catch (error) { console.error("MySQL ping error:", { error }); } }, db.ping); return pool; } }, sqlSelect: function (model, ids = [], params = {}) { //console.log(ids) let SQL = []; let vals = Array.isArray(ids) ? ids : ids.toString().split(","); let where = modelSqlWhere( model, vals, params.middlewareParams, params.where ); let joins = params.joins && params.joins.length ? joins.join(" ") : ""; let order = params.orderBy && params.orderBy.length ? ` ORDER BY ${params.orderBy}` : ""; let limit = params.limit && params.limit.length ? ` LIMIT ${params.limit}` : ""; let fields = modelSqlSelectFields(model, params.fields); SQL.push(`SELECT ${fields.join(", ")} `); SQL.push(`FROM ${quote(model.table)} `); SQL.push(joins); SQL.push(where); SQL.push(order); SQL.push(limit); return SQL; }, sqlInsertUpdate(model, data, onlyFields = [], statement = "INSERT") { const q = quote; let result = {}; let fields = []; let values = []; let binds = []; let insertValues = []; data = data[0] ? data : [data]; const sanitizeString = (val) => { return typeof val === "string" ? val.replace(/\0/g, "") : val; }; const normalizeDate = (val) => { if (!val || val === "" || isNaN(new Date(val).getTime())) return null; return val; }; Object.keys(data).map((key) => { for (let field in model.schema) { field = { ...model.schema[field], name: field }; if (field.dbControl) continue; if (!field.ai && onlyFields.length && !onlyFields.includes(field.name)) continue; let value = data[key][field.name]; let type = model.schema[field.name].type; if (statement == "INSERT" && field.ai) switch (type) { case "guid": case "uuid": value = beeTools.guid().toString(); result.insertBin = beeTools.guidToBin(value); result.insertUUID = value; break; } if (value === undefined) continue; switch (type) { case "guid": case "uuid": binds.push(value); value = `UUID_TO_BIN(?)`; break; case "date": case "datetime": binds.push(normalizeDate(value)); value = "?"; break; default: binds.push(value); value = "?"; } if (field.onInput) value = `${field.onInput}(${value})`; //example md5() if (statement === "INSERT") { if (key == 0) fields.push(q(field.name)); values.push(value); } else { values.push(q(field.name) + "=" + value); } } if (statement === "INSERT") { insertValues.push(values.join(",")); values = []; } }); let SQL = statement === "INSERT" ? `INSERT INTO ${model.table} (${fields.join( "," )}) VALUES (${insertValues.join("),(")})` : `UPDATE ${model.table} SET ${values.join(",")}`; return { result, SQL, binds }; }, save: (model, key = null) => { //TODO, tirar daqui. var fields = Object.keys(model.schema); var body = []; //key = 1 //test for (let i = 0; i <= req.body.length - 1; i++) { var values = []; for (field of fields) { let out = model.schema[field].out || a; let value = (req.body[i] || req.body)[out]; //TODO inserir validacoes value = ["guid", "binary"].includes(model.schema[field].type) ? value : q(value, "''"); values.push({ field: field, out: out, value: value }); } body.push(values); } if (key !== null) { body = body[0] .filter((a) => a.value) .map((a) => (a = a.field + `=${a.value}`)) .join(); db.query( `UPDATE ${model.table} SET ${body} WHERE ${model.fieldKey} = ${key}` ); } else { body = body.map((a) => a.map((a) => `${a.value}`)).join("),("); db.query( `INSERT INTO ${model.table} (${Object.keys( model.schema )}) VALUES(${body})` ); } }, sqlUpdate: (model, keys) => { //TODO return db.query( `UPDATE ${model.table} SET TODO WHERE ${table.fieldKey} = (${key})` ); }, sqlDelete: (model, keys) => { //TODO return db.query( `DELETE FROM ${model.table} WHERE ${table.fieldKey} = (${key})` ); }, forceData(data, req = {}) { // TODO coocar funcao para pegar apenas campos do middlaware marcados para INSERT e UPDATE. // Se nao campos do tipo IDUser_Profile poderá ser forçado pelo middleware invés do post form. return Object.assign({}, data, req.token || {}, req.middleware || {}); }, formatOut(data, model) { //TODO if (!model) return data; return data; }, };