UNPKG

@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
"use strict"; /** * @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)); }