UNPKG

@mcabreradev/filter

Version:

A powerful, SQL-like array filtering library for TypeScript and JavaScript with advanced pattern matching, MongoDB-style operators, deep object comparison, and zero dependencies

76 lines (75 loc) 3.17 kB
import { OPERATORS } from '../../constants'; import { hasWildcard, createWildcardRegex, hasNegation, removeNegation, isString, isObject, isOperatorExpression, } from '../../utils'; import { processOperators } from '../../operators'; import { applyLogicalOperators } from '../../operators/logical/logical.operators'; const isLogicalOperator = (key) => { return key === OPERATORS.AND || key === OPERATORS.OR || key === OPERATORS.NOT; }; export function createObjectPredicate(expression, config) { return function (item) { for (const key in expression) { if (isLogicalOperator(key)) { const logicalExpr = expression; const operatorValue = logicalExpr[key]; if (operatorValue !== undefined && !applyLogicalOperators(item, key, operatorValue, config)) { return false; } continue; } let expr = expression[key]; const itemValue = item[key]; if (isObject(expr) && isOperatorExpression(expr)) { if (!processOperators(itemValue, expr, config, item)) { return false; } continue; } if (isObject(expr) && !isOperatorExpression(expr) && isObject(itemValue)) { const nestedPredicate = createObjectPredicate(expr, config); if (!nestedPredicate(itemValue)) { return false; } continue; } let shouldNegate = false; if (isString(expr) && hasNegation(expr)) { expr = removeNegation(expr); shouldNegate = true; } if (Array.isArray(expr)) { const matchesAny = expr.some((value) => { if (isString(value) && hasWildcard(value)) { const regex = createWildcardRegex(value, config.caseSensitive); return typeof itemValue === 'string' && regex.test(itemValue); } return itemValue === value; }); if (shouldNegate ? matchesAny : !matchesAny) { return false; } continue; } if (isString(expr) && hasWildcard(expr)) { const regex = createWildcardRegex(expr, config.caseSensitive); const matches = typeof itemValue === 'string' && regex.test(itemValue); if (shouldNegate ? matches : !matches) { return false; } } else { let matches; if (!config.caseSensitive && typeof itemValue === 'string' && typeof expr === 'string') { matches = itemValue.toLowerCase() === expr.toLowerCase(); } else { matches = itemValue === expr; } if (shouldNegate ? matches : !matches) { return false; } } } return true; }; }