@jackiemacklein/nettz-utils
Version:
Serviços de imagem, e-mail, códigos de barras, utilitários numéricos e componentes React para apps Node.js com TypeScript
207 lines (206 loc) • 8.17 kB
JavaScript
;
/**
* @author Jackiê Macklein
* @company Onside tecnologia/Nettz
* @copyright Todos direitos reservados.
* @description Utilitários para construção de filtros SQL
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildWhereConditions = buildWhereConditions;
exports.buildCustomOperatorCondition = buildCustomOperatorCondition;
/**
* Constrói condições WHERE para consultas SQL
*
* @example
* const whereConditions = buildWhereConditions(
* {
* age: { value: 18, operator: ">" },
* status: { value: ["ACTIVE", "PENDING"], operator: "in" },
* name: "João"
* },
* {
* mainTable: "users",
* useUnaccent: true,
* customConditions: []
* }
* );
*/
function buildWhereConditions(filter, options = {}) {
const { mainTable = "", useUnaccent = true, customConditions = [] } = options;
const where = [...customConditions];
if (!filter || typeof filter !== "object") {
return where;
}
Object.entries(filter).forEach(([key, value]) => {
// Ignora valores vazios
if (!value || (typeof value === "string" && value.trim() === "")) {
return;
}
const tableName = key.includes(".") ? key.split(".")[0] : mainTable;
const fieldName = key.includes(".") ? key.split(".")[1] : key;
const fullFieldName = tableName ? `${tableName}.${fieldName}` : fieldName;
// Verifica se o valor é um objeto com operador customizado
if (typeof value === "object" &&
!Array.isArray(value) &&
"value" in value) {
const filterValue = value;
if (filterValue.customQuery) {
// Permite inserir uma query SQL customizada
where.push(filterValue.customQuery);
return;
}
switch (filterValue.operator) {
case "=":
where.push(`${fullFieldName} = '${filterValue.value}'`);
break;
case "!=":
where.push(`${fullFieldName} != '${filterValue.value}'`);
break;
case ">":
where.push(`${fullFieldName} > ${filterValue.value}`);
break;
case ">=":
where.push(`${fullFieldName} >= ${filterValue.value}`);
break;
case "<":
where.push(`${fullFieldName} < ${filterValue.value}`);
break;
case "<=":
where.push(`${fullFieldName} <= ${filterValue.value}`);
break;
case "like":
where.push(`${fullFieldName} like '%${filterValue.value}%'`);
break;
case "ilike":
where.push(`${fullFieldName} ilike '%${filterValue.value}%'`);
break;
case "in":
const inValues = Array.isArray(filterValue.value)
? filterValue.value
: [filterValue.value];
where.push(`${fullFieldName} = ANY(ARRAY[${inValues.join(",")}])`);
break;
case "not in":
const notInValues = Array.isArray(filterValue.value)
? filterValue.value
: [filterValue.value];
where.push(`${fullFieldName} != ALL(ARRAY[${notInValues.join(",")}])`);
break;
case "between":
if (Array.isArray(filterValue.value) &&
filterValue.value.length === 2) {
const startValue = filterValue.value[0];
const endValue = filterValue.value[1];
// Tratamento para datas
if (isDateOrDateTime(startValue) && isDateOrDateTime(endValue)) {
where.push(`${fullFieldName} BETWEEN '${startValue}' AND '${endValue}'`);
}
// Tratamento para números
else if (isNumber(startValue) && isNumber(endValue)) {
where.push(`${fullFieldName} BETWEEN ${startValue} AND ${endValue}`);
}
// Tratamento para texto (padrão)
else {
where.push(`${fullFieldName} BETWEEN '${startValue}' AND '${endValue}'`);
}
}
break;
default:
// Tratamento padrão caso não tenha operador específico
handleDefaultValue(fullFieldName, filterValue.value, where, useUnaccent);
}
return;
}
// Tratamento padrão para valores simples
handleDefaultValue(fullFieldName, value, where, useUnaccent);
});
return where;
}
function handleDefaultValue(fullFieldName, value, where, useUnaccent) {
// Tratamento para números
if (isNumber(value)) {
where.push(`${fullFieldName} = ${value}`);
return;
}
// Tratamento para datas
if (isDateOrDateTime(value)) {
where.push(`DATE(${fullFieldName}) = DATE('${value}')`);
return;
}
// Tratamento para booleanos
if (typeof value === "boolean" || value === "true" || value === "false") {
where.push(`${fullFieldName} = ${value === true || value === "true"}`);
return;
}
// Tratamento para arrays
if (Array.isArray(value)) {
where.push(`${fullFieldName} = ANY(ARRAY[${value.join(",")}])`);
return;
}
// Tratamento para texto
if (useUnaccent) {
where.push(`unaccent(${fullFieldName}) ilike unaccent('%${value.trim()}%')`);
}
else {
where.push(`${fullFieldName} ilike '%${value.trim()}%'`);
}
}
/**
* Constrói condições customizadas para operadores específicos
*/
function buildCustomOperatorCondition(field, operator, value, options = {}) {
const { mainTable = "" } = options;
const fullFieldName = mainTable ? `${mainTable}.${field}` : field;
switch (operator) {
case "eq":
return `${fullFieldName} = '${value}'`;
case "neq":
return `${fullFieldName} != '${value}'`;
case "gt":
return `${fullFieldName} > ${value}`;
case "gte":
return `${fullFieldName} >= ${value}`;
case "lt":
return `${fullFieldName} < ${value}`;
case "lte":
return `${fullFieldName} <= ${value}`;
case "in":
return `${fullFieldName} = ANY(ARRAY[${value}])`;
case "nin":
return `${fullFieldName} != ANY(ARRAY[${value}])`;
case "like":
return `${fullFieldName} ilike '%${value}%'`;
case "between":
if (Array.isArray(value) && value.length === 2) {
const startValue = value[0];
const endValue = value[1];
// Tratamento para datas
if (isDateOrDateTime(startValue) && isDateOrDateTime(endValue)) {
return `${fullFieldName} BETWEEN '${startValue}' AND '${endValue}'`;
}
// Tratamento para números
else if (isNumber(startValue) && isNumber(endValue)) {
return `${fullFieldName} BETWEEN ${startValue} AND ${endValue}`;
}
// Tratamento para texto (padrão)
else {
return `${fullFieldName} BETWEEN '${startValue}' AND '${endValue}'`;
}
}
return "";
default:
return "";
}
}
// Função auxiliar para verificar se é data
function isDateOrDateTime(value) {
if (typeof value === "string") {
const dateRegex = /^\d{4}-\d{2}-\d{2}/;
return dateRegex.test(value);
}
return value instanceof Date;
}
// Função auxiliar para verificar se é número
function isNumber(value) {
return !isNaN(Number(value));
}