Newer
Older
const libs = `${process.cwd()}/libs`;
const log = require(`${libs}/log`)(module);
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') {
log.debug("added field "+field.name);
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;
log.debug("added value "+fieldValue.name);
}
return this;
}
addValueToField(fieldValue, field) {
if(typeof this.fields[field] === 'undefined') {
throw 'No field with name ' +field+ ' defined';
}
if(typeof this.fields[field].values === 'undefined') {
this.fields[field].values = {};
}
if(typeof this.fields[field].values[fieldValue.name] === 'undefined') {
this.fields[field].values[fieldValue.name] = fieldValue;
log.debug("added value "+fieldValue.name+ ' to field ' + field);
}
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);
// Unimos os valores aceitos globalmente com os aceitos apenas pelo parâmetro
let values = _.merge(this.fieldValues, f.values);
Object.keys(values).map((k, i) => {
let value = values[k];
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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 = _.merge(this.fieldValues, field.values);
log.debug('ValueS');
log.debug(values);
log.debug('k');
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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);
if(value.where.type === 'string') whereValue = '%'+whereValue+'%';
let tbl = value.where.table || value.table;
let whereField = (value.where.type === 'string')? 'LOWER('+tbl+'.'+value.where.field+')' : tbl+'.'+value.where.field;
let lower = (value.where.type === 'string') ? ' LOWER(?) ' : ' ? ';
req.sql.where(whereField + ' ' + value.where.relation + lower, whereValue);