- Notifications
You must be signed in to change notification settings - Fork1
A powerful, zero-dependency filtering library that brings MongoDB-style operators, SQL wildcards, and intelligent autocomplete to TypeScript arrays. Think of it as Array.filter() on steroids! 💪
License
mcabreradev/filter
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Filter arrays like a pro. A powerful, SQL-like array filtering library for TypeScript with advanced pattern matching, MongoDB-style operators, deep object comparison, geospatial queries, and zero dependencies.
Quick Start •Why You'll Love It •Examples •Playground •Documentation
- @mcabreradev/filter
Tired of writing complex filter logic? Stop wrestling with nestedArray.filter() chains and verbose conditionals. Write clean, declarative filters that read like queries.
Before:
constresults=data.filter(item=>item.age>=18&&item.status==='active'&&(item.role==='admin'||item.role==='moderator')&&item.email.endsWith('@company.com')&&item.createdAt>=thirtyDaysAgo);
After:
constresults=filter(data,{age:{$gte:18},status:'active',role:['admin','moderator'],email:{$endsWith:'@company.com'},createdAt:{$gte:thirtyDaysAgo}});
Same result. 70% less code. 100% more readable.
npm install @mcabreradev/filter# orpnpm add @mcabreradev/filter# oryarn add @mcabreradev/filter
Requirements: Node.js >= 20, TypeScript 5.0+ (optional)
import{filter}from'@mcabreradev/filter';constusers=[{name:'Alice',age:30,city:'Berlin',active:true},{name:'Bob',age:25,city:'London',active:false},{name:'Charlie',age:35,city:'Berlin',active:true}];// Simple string searchconstberlinUsers=filter(users,'Berlin');// → [{ name: 'Alice', ... }, { name: 'Charlie', ... }]// Object-based filteringconstactiveBerlinUsers=filter(users,{city:'Berlin',active:true});// → [{ name: 'Alice', ... }]// MongoDB-style operatorsconstadults=filter(users,{age:{$gte:18}});// → All users (all are 18+)// That's it! You're filtering like a pro.
- 530x faster with optional caching
- 500x faster with lazy evaluation for large datasets
- Optimized for production workloads
- Intuitive API that feels natural
- SQL-like syntax you already know
- Full TypeScript support with intelligent autocomplete
- Multiple filtering strategies (strings, objects, operators, predicates)
- Works with any data structure
- Combine approaches seamlessly
- 993+ tests ensuring reliability
- Zero dependencies (12KB gzipped)
- Used in production by companies worldwide
- MIT licensed
- Truly zero dependencies!
- Tiny 12KB bundle
- Optional Zod for validation
- No bloat, just pure filtering power
- Built with strict TypeScript
- Catch errors at compile time
- Full IntelliSense and autocomplete support
- Works everywhere: React, Vue, Svelte, Angular, SolidJS, Preact
- First-class hooks and composables included
- SSR compatible (Next.js, Nuxt, SvelteKit)
- Process millions of records efficiently
- Lazy evaluation for memory optimization
- Built for scale
// String matching - searches all propertiesfilter(products,'Laptop');// Object matching - AND logicfilter(products,{category:'Electronics',price:{$lt:1000}});// Wildcard patterns (SQL-like)filter(users,'%alice%');// Contains 'alice'filter(users,'Al%');// Starts with 'Al'filter(users,'%son');// Ends with 'son'
// Comparison operatorsfilter(products,{price:{$gte:100,$lte:500}});// Array operatorsfilter(products,{category:{$in:['Electronics','Books']},tags:{$contains:'sale'}});// String operatorsfilter(users,{email:{$endsWith:'@company.com'},name:{$startsWith:'John'}});// Logical operatorsfilter(products,{$and:[{inStock:true},{$or:[{rating:{$gte:4.5}},{price:{$lt:50}}]}]});
// Clean array syntax - no $in needed!filter(products,{category:['Electronics','Books']});// Equivalent to: { category: { $in: ['Electronics', 'Books'] }}// Multiple propertiesfilter(users,{city:['Berlin','Paris'],role:['admin','moderator']});
import{filter,typeGeoPoint}from'@mcabreradev/filter';constuserLocation:GeoPoint={lat:52.52,lng:13.405};// Find restaurants within 5kmfilter(restaurants,{location:{$near:{center:userLocation,maxDistanceMeters:5000}},rating:{$gte:4.5}});
// Events in next 7 daysfilter(events,{date:{$upcoming:{days:7}}});// Recent events (last 24 hours)filter(events,{date:{$recent:{hours:24}}});// Weekday events during business hoursfilter(events,{date:{$dayOfWeek:[1,2,3,4,5]},startTime:{$timeOfDay:{start:9,end:17}}});// Users who logged in recently (last 7 days)filter(users,{lastLogin:{$recent:{days:7}}});// Upcoming meetings in next 2 hoursfilter(meetings,{startTime:{$upcoming:{hours:2}}});// Weekend events onlyfilter(events,{date:{$isWeekend:true}});// Calculate age (users over 18)filter(users,{birthDate:{$age:{$gte:18}}});// Events before a specific datefilter(events,{date:{$isBefore:newDate('2025-12-31')}});
// Enable caching for repeated queriesconstresults=filter(largeDataset,expression,{enableCache:true,orderBy:{field:'price',direction:'desc'},limit:100});// Lazy evaluation for large datasetsimport{filterFirst}from'@mcabreradev/filter';constfirst10=filterFirst(users,{premium:true},10);
interfaceProduct{id:number;name:string;price:number;category:string;brand:string;rating:number;inStock:boolean;tags:string[];}constproducts:Product[]=[...];// Find affordable, highly-rated electronics in stockconstaffordableElectronics=filter(products,{category:'Electronics',price:{$lte:1000},rating:{$gte:4.5},inStock:true});// Search with multiple filtersconstsearchResults=filter(products,{name:{$contains:'laptop'},brand:{$in:['Apple','Dell','HP']},price:{$gte:500,$lte:2000}});// Sort resultsconstsortedProducts=filter(products,{category:'Electronics',inStock:true},{orderBy:[{field:'price',direction:'asc'},{field:'rating',direction:'desc'}],limit:20});
Works seamlessly with your favorite framework:
import{useFilter}from'@mcabreradev/filter/react';functionUserList(){const{ filtered, isFiltering}=useFilter(users,{active:true});return<div>{filtered.map(u=><Userkey={u.id}{...u}/>)}</div>;}
<script setup>import {useFilter }from'@mcabreradev/filter/vue';const {filtered }=useFilter(users, { active:true });</script>
<script>import {useFilter }from'@mcabreradev/filter/svelte';const {filtered }=useFilter(users,writable({ active:true }));</script>
import{FilterService}from'@mcabreradev/filter/angular';@Component({providers:[FilterService],template:` @for (user of filterService.filtered(); track user.id) { <div>{{ user.name }}</div> } `})exportclassUserListComponent{filterService=inject(FilterService<User>);}
import{useFilter}from'@mcabreradev/filter/solidjs';functionUserList(){const{ filtered}=useFilter(()=>users,()=>({active:true}));return<Foreach={filtered()}>{(u)=><div>{u.name}</div>}</For>;}
import{useFilter}from'@mcabreradev/filter/preact';functionUserList(){const{ filtered}=useFilter(users,{active:true});return<div>{filtered.map(u=><divkey={u.id}>{u.name}</div>)}</div>;}
Features:
- ✅ Full TypeScript support with generics
- ✅ Debounced search hooks/services
- ✅ Pagination support
- ✅ SSR compatible
- ✅ 100% test coverage
Comparison:$gt,$gte,$lt,$lte,$eq,$neArray:$in,$nin,$contains,$sizeString:$startsWith,$endsWith,$contains,$regex,$matchLogical:$and,$or,$notGeospatial:$near,$geoBox,$geoPolygonDatetime:$recent,$upcoming,$dayOfWeek,$timeOfDay,$age,$isWeekday,$isWeekend,$isBefore,$isAfter
Full type safety with intelligent autocomplete:
interfaceProduct{name:string;price:number;tags:string[];}filter<Product>(products,{price:{},// Autocomplete: $gt, $gte, $lt, $lte, $eq, $nename:{},// Autocomplete: $startsWith, $endsWith, $contains, $regextags:{}// Autocomplete: $in, $nin, $contains, $size});
filter(data,expression,{caseSensitive:false,// Case-sensitive string matchingmaxDepth:3,// Max depth for nested objectsenableCache:true,// Enable result caching (530x faster)orderBy:'price',// Sort resultslimit:10,// Limit number of resultsdebug:true// Visual debugging mode});
Efficiently process large datasets with lazy evaluation:
import{filterLazy,filterFirst,filterExists,filterCount}from'@mcabreradev/filter';// Process items on-demandconstfiltered=filterLazy(millionRecords,{active:true});for(constitemoffiltered){process(item);if(shouldStop)break;// Early exit}// Find first N matchesconstfirst10=filterFirst(users,{premium:true},10);// Check existence without processing all itemsconsthasAdmin=filterExists(users,{role:'admin'});// Count matchesconstactiveCount=filterCount(users,{active:true});
Benefits:
- 🚀500x faster for operations that don't need all results
- 💾100,000x less memory for large datasets
- ⚡Early exit optimization
530x faster with optional caching:
// First call - processes dataconstresults=filter(largeDataset,{age:{$gte:18}},{enableCache:true});// Second call - returns cached result instantlyconstsameResults=filter(largeDataset,{age:{$gte:18}},{enableCache:true});
Performance Gains:
| Scenario | Without Cache | With Cache | Speedup |
|---|---|---|---|
| Simple query (10K items) | 5.3ms | 0.01ms | 530x |
| Regex pattern | 12.1ms | 0.02ms | 605x |
| Complex nested | 15.2ms | 0.01ms | 1520x |
Built-in debug mode with expression tree visualization:
filter(users,{city:'Berlin'},{debug:true});// Console output:// ┌─ Filter Debug Tree// │ Expression: {"city":"Berlin"}// │ Matched: 3/10 (30.0%)// │ Execution time: 0.42ms// └─ ✓ city = "Berlin"
- Getting Started - Installation and first steps
- All Operators - Complete operator reference
- Geospatial Queries - Location-based filtering
- Datetime Operators - Temporal filtering
- Framework Integrations - React, Vue, Svelte, Angular, SolidJS, Preact
- Lazy Evaluation - Efficient large dataset processing
- Memoization & Caching - Performance optimization
- Visual Debugging - Debug mode and tree visualization
Filter is optimized for performance:
- Operators use early exit strategies for fast evaluation
- Regex patterns are compiled and cached
- Optional caching for repeated queries (530x-1520x faster)
- Lazy evaluation for efficient large dataset processing (500x faster)
- Type guards for fast type checking
// ✅ Fast: Operators with early exitfilter(data,{age:{$gte:18}});// ✅ Fast with caching for repeated queriesfilter(largeData,expression,{enableCache:true});// ✅ Fast with lazy evaluation for large datasetsconstresult=filterFirst(millionRecords,{active:true},100);
| Import | Size (gzipped) | Tree-Shakeable |
|---|---|---|
| Full | 12 KB | ✅ |
| Core only | 8.4 KB | ✅ |
| React hooks | 9.2 KB | ✅ |
| Lazy evaluation | 5.4 KB | ✅ |
Works in all modern browsers and Node.js:
- Node.js: >= 20
- Browsers: Chrome, Firefox, Safari, Edge (latest versions)
- TypeScript: >= 5.0
- Module Systems: ESM, CommonJS
Good news: v5.x is100% backward compatible! All v3.x code continues to work.
// ✅ All v3.x syntax still worksfilter(data,'string');filter(data,{prop:'value'});filter(data,(item)=>true);filter(data,'%pattern%');// ✅ New in v5.xfilter(data,{age:{$gte:18}});filter(data,expression,{enableCache:true});
- 🐛Bug Fix: Fixed critical issue where
limitoption was ignored in cache key - ⚡Performance: Replaced unbounded caches with LRU strategy to prevent memory leaks
- 🔒Stability: Improved memory management for long-running applications
- 🎨New Framework Integrations: Angular, SolidJS, and Preact support
- 🔢Limit Option: New
limitconfiguration option to restrict result count - 📊OrderBy Option: New
OrderByconfiguration option to sort filtered results by field(s) in ascending or descending order - ✅ 993+ tests with comprehensive coverage
🅰️ Angular: Services and Pipes with Signals support- 🔷SolidJS: Signal-based reactive hooks
- ⚡Preact: Lightweight hooks API
- 🌍Geospatial Operators: Location-based filtering with $near, $geoBox, $geoPolygon
- 📅Datetime Operators: Temporal filtering with $recent, $upcoming, $dayOfWeek, $age
- 🎨Array OR Syntax: Intuitive array-based OR filtering
- 🐛Visual Debugging: Built-in debug mode with expression tree visualization
- 🎮Interactive Playground: Online playground for testing filters
We welcome contributions! Please read ourContributing Guide for details.
Ways to Contribute:
- Report bugs or request features viaGitHub Issues
- Submit pull requests with bug fixes or new features
- Improve documentation
- Share your use cases and examples
MIT License - seeLICENSE.md for details.
Copyright (c) 2025 Miguelangel Cabrera
Made with ❤️ for the JavaScript/TypeScript community
About
A powerful, zero-dependency filtering library that brings MongoDB-style operators, SQL wildcards, and intelligent autocomplete to TypeScript arrays. Think of it as Array.filter() on steroids! 💪
Topics
Resources
License
Contributing
Security policy
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.
Contributors5
Uh oh!
There was an error while loading.Please reload this page.