Skip to content
Snippets Groups Projects
Commit 8063657d authored by Vytor Calixto's avatar Vytor Calixto :space_invader:
Browse files

Added a "query builder" middleware for fields

It uses a object to set the url fields accepted and it's values, parse the
fields and build the query with the values automagically
parent 07215e9e
No related branches found
No related tags found
2 merge requests!116Release v1.0.0,!29Feature param query builder
const libs = `${process.cwd()}/libs`;
const log = require(`${libs}/log`)(module);
const parseParams = require(`${libs}/middlewares/parseParams`);
const _ = require('lodash');
class ReqQueryFields {
constructor(fields = {}, fieldValues = {}) {
// Parâmetros no campo query da requisição.
// Exemplo de field:
// {
// name: 'dims',
// field: true,
// where: false
// }
this.fields = fields;
this.fieldValues = fieldValues;
}
addField(field) {
// Parâmetro no campo query da requisição.
// Exemplo de field:
// {
// name: 'dims',
// field: true,
// where: false,
// fieldValues: {}
// }
if(typeof this.fields[field.name] === 'undefined') {
this.fields[field.name] = field;
}
return this;
}
addValue(fieldValue) {
// Array de valores aceitos pelo campo
// Exemplo de valor:
// {
// name: 'location',
// table: 'localizacao',
// tableField: 'descricao'
// resultField: 'location_name',
// where: {
// relation: '=',
// type: 'integer',
// field: 'id_localizacao',
// table: 'turma'
// },
// join: {
// primary: 'pk_localizacao_id',
// foreign: 'id_localizacao',
// foreignTable: 'turma'
// }
// }
if(typeof this.fieldValues[fieldValue.name] === 'undefined') {
this.fieldValues[fieldValue.name] = fieldValue;
}
return this;
}
parse() {
return (req, res, next) => {
Object.keys(this.fields).map((key, index) => {
let params = [];
let f = this.fields[key];
log.debug('f');
log.debug(f);
Object.keys(this.fieldValues).map((k, i) => {
let value = this.fieldValues[k];
log.debug('value');
log.debug(value);
params.push(value.name);
});
let queryField = f.name;
let arrayOfParams = params;
req[queryField] = {};
if (req.query[queryField]) {
const params = req.query[queryField].split(',');
// Temporary object to hold the params and it's values
const obj = {};
for (const param of params) {
// Get the key and the value - state:41 is key 'state' whith value 41.
// kv is then an array [key, value] or [key] if there is no value
const kv = param.split(':');
// Check if there is a value. If there isn't, assign true
obj[kv[0]] = (typeof kv[1] === 'undefined') ? true : kv[1];
// obj is now an object {kv[0]: kv[1]} ou {kv[0]: true}
}
// If the array exists and is not empty we intersect
if (typeof arrayOfParams !== 'undefined' && arrayOfParams.length > 0) {
// Intersect the keys of the obj with the array arrayOfParams
// The intersection array is assigned with the keys
const intersection = _.intersection(arrayOfParams, Object.keys(obj));
// This is a bit tricky...
// For each key in the intersection array we get it's value in the obj
// and assign it to the custom attribute in the req obj.
// For example: instersection => ["state"] so
// obj[intersection[i]] (with i=0) is obj["state"], that is 41
// and req[queryField]["state"] = 41
for (let i = 0; i < intersection.length; ++i) {
req[queryField][intersection[i]] = obj[intersection[i]];
}
req[queryField].size = intersection.length;
} else {
req[queryField] = obj;
req[queryField].size = Object.keys(obj).length;
}
}
});
next();
};
}
build() {
return (req, res, next) => {
Object.keys(this.fields).map((key, index) => {
let field = this.fields[key];
log.debug(field);
let param = req[field.name];
log.debug(param);
Object.keys(param).map((k, i) => {
let values = this.fieldValues;
log.debug(k);
if(typeof values[k] !== 'undefined') {
// Clonamos para não alterar
let value = _.clone(values[k]);
log.debug(value);
// Checa se não fizemos o join para este valor e se é necessário fazer
if(!value.hasJoined && typeof value.join !== 'undefined') {
let foreignTable = '';
if(value.join.foreignTable) foreignTable = value.join.foreignTable+'.';
// Fazemos o join
req.sql.join(value.table, null, foreignTable+value.join.foreign+'='+value.table+'.'+value.join.primary);
// Marcamos o join como feito para não ter problemas
value.hasJoined = true;
}
// Se o valor é um campo a ser incluído no SELECT
if(typeof field.field !== 'undefined' && field.field) {
log.debug('SELECT');
req.sql.field(value.table+'.'+value.tableField, value.resultField || value.tableField)
.group(value.table+'.'+value.tableField)
.order(value.table+'.'+value.tableField);
}
// Se o valor é um campo para ser usado no WHERE
if(typeof field.where !== 'undefined' && field.where) {
log.debug('WHERE');
// Valor do where
let whereValue = param[k];
// Valor sempre vem como string, necessário fazer parse para o banco
if(value.where.type === 'integer') whereValue = parseInt(whereValue, 10);
if(value.where.type === 'double') whereValue = parseFloat(whereValue);
let tbl = value.where.table || value.table;
req.sql.where(tbl+'.'+value.where.field+' '+value.where.relation+' ?', whereValue);
}
}
});
});
next();
};
}
}
module.exports = ReqQueryFields;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment