Zero-dependency TypeScript filtering library with MongoDB-style operators, geospatial queries, and framework integrations
Quick Start โข Features โข Documentation โข Playground โข Examples
npm install @mcabreradev/filter
# Using yarn
yarn add @mcabreradev/filter
# Using pnpm
pnpm add @mcabreradev/filter
# Optional: Install Zod for runtime validation (recommended for production)
npm install zodRequirements: Node.js >= 20, TypeScript 5.0+ (optional)
Note: Zod is now an optional peer dependency. Install it only if you need runtime validation features.
@mcabreradev/filter is optimized for minimal bundle impact with tree-shaking support:
import { filter } from '@mcabreradev/filter';
const users = [
{ 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 matching
filter(users, 'Berlin');
// โ [Alice, Charlie]
// MongoDB-style operators
filter(users, { age: { $gte: 30 }, active: true });
// โ [Alice, Charlie]
// Array OR syntax
filter(users, { city: ['Berlin', 'Paris'] });
// โ [Alice, Charlie]
// With options
filter(users, { age: { $gte: 30 } }, { orderBy: 'age', limit: 5 });- Zero Dependencies - Production-ready, 12KB gzipped
- Type-Safe - Full TypeScript support with intelligent autocomplete
- 30+ Operators - MongoDB-style queries (
$gte,$in,$regex, etc.) - Performance - 530x faster with optional caching
- Framework Ready - React, Vue, Svelte, Angular, SolidJS, Preact
- Geospatial Queries - Location-based filtering (
$near,$geoBox,$geoPolygon) - Temporal Operators - Date/time filtering (
$recent,$upcoming,$age) - Lazy Evaluation - Process millions of records efficiently
- Visual Debugging - Built-in expression tree visualization
- SQL-like Wildcards -
%and_pattern matching
| Import | Size | Tree-Shakeable |
|---|---|---|
| Full | 12 KB | โ |
| Core only | 8.4 KB | โ |
| React hooks | 9.2 KB | โ |
| Lazy evaluation | 5.4 KB | โ |
// String matching
filter(products, 'Laptop');
// Object matching
filter(products, { category: 'Electronics', price: { $lt: 1000 } });
// String operators
filter(users, { email: { $endsWith: '@company.com' } });filter(products, {
$and: [
{ inStock: true },
{ $or: [{ rating: { $gte: 4.5 } }, { price: { $lt: 50 } }] }
]
});filter(restaurants, {
location: {
$near: {
center: { lat: 52.52, lng: 13.405 },
maxDistanceMeters: 5000
}
},
rating: { $gte: 4.5 }
});filter(events, {
date: { $upcoming: { days: 7 } },
startTime: { $timeOfDay: { start: 9, end: 17 } }
});const results = filter(largeDataset, expression, {
enableCache: true,
orderBy: { field: 'price', direction: 'desc' },
limit: 100
});- ๐ Complete Guide
- ๐ฏ All Operators
- ๐ Geospatial Queries
- ๐ Date/Time Operators
- โก Performance Guide
- ๏ฟฝ Framework Integrations
- ๐ฎ Interactive Playground
Comparison: $gt, $gte, $lt, $lte, $eq, $ne
Array: $in, $nin, $contains, $size
String: $startsWith, $endsWith, $contains, $regex, $match
Logical: $and, $or, $not
Geospatial: $near, $geoBox, $geoPolygon
Date/Time: $recent, $upcoming, $dayOfWeek, $timeOfDay, $age, $isWeekday, $isWeekend
Full type safety with intelligent autocomplete:
interface Product {
name: string;
price: number;
tags: string[];
}
filter<Product>(products, {
price: { }, // Autocomplete: $gt, $gte, $lt, $lte, $eq, $ne, $in, $nin
name: { }, // Autocomplete: $startsWith, $endsWith, $contains, $regex, $match
tags: { } // Autocomplete: $in, $nin, $contains, $size
});- โ๏ธ React
- ๐ข Vue
- ๐ด Svelte
๐ ฐ๏ธ Angular- ๐ท SolidJS
- โก Preact
Contributions welcome! See CONTRIBUTING.md
MIT ยฉ Miguelรกngel Cabrera
993 tests โข 100% TypeScript โข Zero dependencies
import { useFilter, useDebouncedFilter } from '@mcabreradev/filter/react';
function UserList() {
const { filtered, isFiltering } = useFilter(users, { active: true });
return <div>{filtered.map(u => <User key={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>
}
`
})
export class UserListComponent {
filterService = inject(FilterService<User>);
}import { useFilter } from '@mcabreradev/filter/solidjs';
function UserList() {
const { filtered } = useFilter(
() => users,
() => ({ active: true })
);
return <For each={filtered()}>{(u) => <div>{u.name}</div>}</For>;
}import { useFilter } from '@mcabreradev/filter/preact';
function UserList() {
const { filtered } = useFilter(users, { active: true });
return <div>{filtered.map(u => <div key={u.id}>{u.name}</div>)}</div>;
}Features:
- โ Full TypeScript support with generics
- โ Debounced search hooks/services
- โ Pagination support
- โ SSR compatible
- โ 100% test coverage
๐ Complete Framework Guide โ
Filter by simple values across all object properties:
const products = [
{ id: 1, name: 'Laptop', price: 1200 },
{ id: 2, name: 'Mouse', price: 25 },
{ id: 3, name: 'Monitor', price: 450 }
];
// String search
filter(products, 'Laptop'); // โ [{ id: 1, ... }]
// Number search
filter(products, 25); // โ [{ id: 2, ... }]
// Boolean search
filter(tasks, true); // Finds all completed tasksSQL-like wildcards for flexible matching:
// % matches zero or more characters
filter(users, '%alice%'); // Contains 'alice'
filter(users, 'Al%'); // Starts with 'Al'
filter(users, '%son'); // Ends with 'son'
// _ matches exactly one character
filter(codes, 'A_'); // 'A1', 'A2', but not 'AB1'
filter(ids, 'user-10_'); // 'user-101', 'user-102'
// Negation with !
filter(users, '!admin'); // Exclude admin
filter(files, '!%.pdf'); // Exclude PDFsMatch by specific properties (AND logic):
// Single property
filter(products, { category: 'Electronics' });
// Multiple properties (all must match)
filter(products, {
category: 'Electronics',
price: 1200,
inStock: true
});
// Nested objects
filter(users, {
address: { city: 'Berlin' },
settings: { theme: 'dark' }
});Powerful operators for advanced filtering with intelligent autocomplete - TypeScript suggests only valid operators for each property type!
interface Product {
name: string;
price: number;
tags: string[];
inStock: boolean;
}
// TypeScript autocompletes operators based on property types
filter(products, {
price: {
// Suggests: $gt, $gte, $lt, $lte, $eq, $ne
$gte: 100,
$lte: 500
},
name: {
// Suggests: $startsWith, $endsWith, $contains, $regex, $match, $eq, $ne
$startsWith: 'Laptop'
},
tags: {
// Suggests: $in, $nin, $contains, $size
$contains: 'sale'
},
inStock: {
// Suggests: $eq, $ne
$eq: true
}
});๐ Learn more about autocomplete โ
// Greater than / Less than
filter(products, { price: { $gt: 100 } });
filter(products, { price: { $lte: 500 } });
// Range queries
filter(products, {
price: { $gte: 100, $lte: 500 }
});
// Date ranges
filter(orders, {
date: {
$gte: new Date('2025-01-01'),
$lte: new Date('2025-12-31')
}
});
// Not equal
filter(users, { role: { $ne: 'guest' } });Available: $gt, $gte, $lt, $lte, $eq, $ne
// In / Not in array
filter(products, {
category: { $in: ['Electronics', 'Books'] }
});
filter(products, {
status: { $nin: ['archived', 'deleted'] }
});
// Array contains value
filter(products, {
tags: { $contains: 'sale' }
});
// Array size
filter(products, {
images: { $size: 3 }
});Available: $in, $nin, $contains, $size
// Starts with / Ends with
filter(users, {
email: { $endsWith: '@company.com' }
});
filter(files, {
name: { $startsWith: 'report-' }
});
// Contains substring
filter(articles, {
title: { $contains: 'typescript' }
});
// Regular expressions
filter(users, {
email: { $regex: '^[a-z]+@example\\.com$' }
});
filter(users, {
phone: { $regex: /^\+1-\d{3}-\d{4}$/ }
});
// $match is an alias for $regex
filter(users, {
username: { $match: '^[a-z]+\\d+$' }
});Available: $startsWith, $endsWith, $contains, $regex, $match
Combine multiple conditions with logical operators:
// $and - All conditions must match
filter(products, {
$and: [
{ category: 'Electronics' },
{ inStock: true },
{ price: { $lt: 1000 } }
]
});
// $or - At least one condition must match
filter(products, {
$or: [
{ category: 'Electronics' },
{ category: 'Accessories' }
]
});
// $not - Negates the condition
filter(products, {
$not: { category: 'Furniture' }
});
// Complex nested queries
filter(products, {
$and: [
{ inStock: true },
{
$or: [
{ rating: { $gte: 4.5 } },
{ price: { $lt: 50 } }
]
},
{ $not: { category: 'Clearance' } }
]
});
// Combine with field-level conditions
filter(products, {
category: 'Electronics',
$and: [
{ price: { $gte: 100 } },
{ $or: [{ inStock: true }, { preOrder: true }] }
]
});Available: $and, $or, $not
// Multiple operators, multiple properties
filter(products, {
price: { $gte: 100, $lte: 500 },
category: { $in: ['Electronics', 'Accessories'] },
name: { $startsWith: 'Pro' },
inStock: { $eq: true }
});New in v5.5.0: Intuitive array-based OR filtering without explicit $in operator!
// Array syntax - clean and intuitive (OR logic)
filter(products, { category: ['Electronics', 'Books'] });
// Equivalent to: { category: { $in: ['Electronics', 'Books'] } }
// Multiple properties with array OR (independent OR conditions)
filter(products, {
category: ['Electronics', 'Accessories'],
price: [100, 200, 300]
});
// Logic: (category === 'Electronics' OR category === 'Accessories')
// AND (price === 100 OR price === 200 OR price === 300)
// Combining array OR with other conditions (AND logic)
filter(users, {
city: ['Berlin', 'Paris'],
age: 30,
role: ['admin', 'moderator']
});
// Logic: (city === 'Berlin' OR city === 'Paris')
// AND age === 30
// AND (role === 'admin' OR role === 'moderator')
// Works with wildcards
filter(users, { email: ['%@gmail.com', '%@yahoo.com'] });
// Matches emails ending with @gmail.com OR @yahoo.com
// Empty array matches nothing
filter(products, { category: [] });
// โ Returns empty arrayBenefits:
- โจ More intuitive than
$inoperator - ๐ Cleaner, more readable code
- ๐ 100% backward compatible
- ๐ฏ Works with strings, numbers, booleans
- ๐ Supports wildcard patterns
New in v5.6.0: Filter by geographic location with powerful spatial operators!
import { filter, type GeoPoint } from '@mcabreradev/filter';
interface Restaurant {
name: string;
location: GeoPoint;
rating: number;
}
const userLocation: GeoPoint = { lat: 52.52, lng: 13.405 };
// $near - Find points within radius
filter(restaurants, {
location: {
$near: {
center: userLocation,
maxDistanceMeters: 5000
}
}
});
// $geoBox - Bounding box queries
filter(stores, {
location: {
$geoBox: {
southwest: { lat: 52.5, lng: 13.3 },
northeast: { lat: 52.6, lng: 13.5 }
}
}
});
// $geoPolygon - Polygon containment
filter(properties, {
location: {
$geoPolygon: {
points: [
{ lat: 51.5074, lng: -0.1278 },
{ lat: 51.5100, lng: -0.1200 },
{ lat: 51.5050, lng: -0.1150 },
{ lat: 51.5020, lng: -0.1250 }
]
}
}
});
// Combine with other filters
filter(restaurants, {
location: {
$near: {
center: userLocation,
maxDistanceMeters: 3000
}
},
rating: { $gte: 4.5 },
isOpen: true
});Available: $near, $geoBox, $geoPolygon
Features:
- ๐ Location-based filtering
- ๐ Accurate distance calculation
- ๐บ๏ธ Bounding box and polygon support
- โก Fast spherical law of cosines
- ๐ Automatic coordinate validation
See Geospatial Operators Guide for complete documentation.
New in v5.6.0: Filter by relative time, days of week, time of day, and age calculations!
import { filter } from '@mcabreradev/filter';
interface Event {
name: string;
date: Date;
startTime: Date;
}
const events: Event[] = [...];
// Events in next 7 days
filter(events, {
date: { $upcoming: { days: 7 } }
});
// Recent events (last 24 hours)
filter(events, {
date: { $recent: { hours: 24 } }
});
// Weekday events only
filter(events, {
date: { $dayOfWeek: [1, 2, 3, 4, 5] }
});
// Business hours events (9 AM - 5 PM)
filter(events, {
startTime: { $timeOfDay: { start: 9, end: 17 } }
});
// Adult users (18+)
filter(users, {
birthDate: { $age: { min: 18 } }
});
// Weekend events
filter(events, {
date: { $isWeekend: true }
});
// Combine multiple datetime conditions
filter(events, {
date: {
$upcoming: { days: 7 },
$dayOfWeek: [1, 2, 3, 4, 5]
},
startTime: {
$timeOfDay: { start: 9, end: 17 }
}
});Available: $recent, $upcoming, $dayOfWeek, $timeOfDay, $age, $isWeekday, $isWeekend, $isBefore, $isAfter
Features:
- ๐ Relative time filtering (last/next N days/hours/minutes)
- ๐๏ธ Day of week filtering (0-6)
- โฐ Time of day filtering (0-23 hours)
- ๐ Age calculation (years/months/days)
- ๐ Weekday/weekend filtering
- ๐ Full TypeScript support with autocomplete
See Date/Time Operators Guide for complete documentation.
For complex custom logic:
// Simple predicate
filter(numbers, (n) => n > 5);
// Complex conditions
filter(products, (product) =>
product.price < 100 &&
product.inStock &&
product.rating >= 4.0
);
// Type-safe with TypeScript
filter<Product>(products, (p: Product): boolean =>
p.price > 100 && p.name.includes('Pro')
);Efficiently process large datasets with lazy evaluation:
import { filterLazy, filterFirst, filterExists, filterCount, toArray, take, map } from '@mcabreradev/filter';
// Lazy evaluation - process items on-demand
const filtered = filterLazy(millionRecords, { active: true });
for (const item of filtered) {
process(item);
if (shouldStop) break; // Early exit - stops processing immediately
}
// Find first N matches with early exit optimization
const first10 = filterFirst(users, { premium: true }, 10);
// Check existence without processing all items
const hasAdmin = filterExists(users, { role: 'admin' });
// Count matching items
const activeCount = filterCount(users, { active: true });
// Compose lazy operations for powerful pipelines
const result = toArray(
take(
map(filterLazy(users, { active: true }), u => u.name),
100
)
);
// Chunked processing for batch operations
for (const chunk of filterLazyChunked(largeDataset, { needsProcessing: true }, 1000)) {
await api.batchUpdate(chunk);
}Benefits:
- ๐ 500x faster for operations that don't need all results
- ๐พ 100,000x less memory for large datasets
- โก Early exit optimization for existence checks
- ๐ Streaming support for async data sources
- ๐ฆ Chunked processing for batch operations
See Lazy Evaluation Guide for complete documentation.
New in v5.2.0: Advanced multi-layer memoization strategy for maximum performance.
The library implements a sophisticated caching system with three layers:
- Result Cache - Caches complete filter results
- Predicate Cache - Memoizes compiled predicate functions
- Regex Cache - Caches compiled regex patterns
import { filter, clearFilterCache, getFilterCacheStats } from '@mcabreradev/filter';
const largeDataset = [...];
// First call - processes data
const results = filter(largeDataset, { age: { $gte: 18 } }, { enableCache: true });
// Second call - returns cached result instantly
const sameResults = filter(largeDataset, { age: { $gte: 18 } }, { enableCache: true });| 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 |
const products = await fetchProducts();
const electronics = filter(
products,
{
category: { $in: ['Electronics', 'Computers'] },
price: { $gte: 100, $lte: 2000 },
inStock: true,
rating: { $gte: 4.0 }
},
{ enableCache: true }
);
const electronicsAgain = filter(
products,
{
category: { $in: ['Electronics', 'Computers'] },
price: { $gte: 100, $lte: 2000 },
inStock: true,
rating: { $gte: 4.0 }
},
{ enableCache: true }
);// Get cache statistics
const stats = getFilterCacheStats();
console.log(stats);
// { hits: 150, misses: 10, size: 25, hitRate: 0.9375 }
// Clear cache when data changes
clearFilterCache();
// Memory management
let data = [/* large dataset */];
filter(data, query, { enableCache: true });
data = null; // Cache will be garbage collectedโ Enable for:
- Large datasets (>1,000 items)
- Repeated identical queries
- Complex expressions with regex
- Read-heavy workloads
- Dashboard/analytics views
โ Disable for:
- Frequently changing data
- One-time queries
- Memory-constrained environments
- Unique expressions every time
import { filter, clearFilterCache } from '@mcabreradev/filter';
class ProductDashboard {
private products: Product[];
constructor(products: Product[]) {
this.products = products;
}
getElectronics() {
return filter(
this.products,
{ category: 'Electronics' },
{ enableCache: true }
);
}
getHighRated() {
return filter(
this.products,
{ rating: { $gte: 4.5 } },
{ enableCache: true }
);
}
refreshData(newProducts: Product[]) {
this.products = newProducts;
clearFilterCache();
}
}
const dashboard = new ProductDashboard(products);
dashboard.getElectronics();
dashboard.getHighRated();
dashboard.getElectronics();
dashboard.getHighRated();See Memoization Guide for complete documentation.
New in v5.5.0: Built-in debug mode with expression tree visualization, performance metrics, and condition tracking!
Enable debug mode to see how your filter expressions are evaluated:
import { filter } from '@mcabreradev/filter';
// Enable debug mode with config option
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"// Verbose mode - detailed evaluation info
filter(users, { age: { $gte: 25 } }, {
debug: true,
verbose: true
});
// Show execution timings
filter(products, { premium: true }, {
debug: true,
showTimings: true
});
// Colorized output (ANSI colors)
filter(users, { city: 'Berlin' }, {
debug: true,
colorize: true
});
// All options combined
filter(users, {
age: { $gte: 25 },
city: 'Berlin'
}, {
debug: true,
verbose: true,
showTimings: true,
colorize: true
});Use filterDebug for programmatic access to debug information:
import { filterDebug } from '@mcabreradev/filter';
const result = filterDebug(users, { age: { $gte: 30 } });
console.log('Matched:', result.items.map(u => u.name));
console.log('Stats:', {
matched: result.stats.matched,
total: result.stats.total,
percentage: result.stats.percentage,
executionTime: result.stats.executionTime,
conditionsEvaluated: result.stats.conditionsEvaluated
});
// Access debug tree
console.log('Debug Tree:', result.debug.tree);Visualize complex nested expressions:
filter(products, {
$and: [
{ category: 'Electronics' },
{ inStock: true },
{
$or: [
{ rating: { $gte: 4.5 } },
{ price: { $lt: 50 } }
]
}
]
}, { debug: true, verbose: true });
// Console output shows tree structure:
// โโ Filter Debug Tree
// โ Expression: Complex nested query
// โ Matched: 5/10 (50.0%)
// โ Execution time: 1.23ms
// โโ AND
// โ โโ โ category = "Electronics"
// โ โโ โ inStock = true
// โ โโ OR
// โ โโ โ rating >= 4.5
// โ โโ โ price < 50
// โโ Conditions evaluated: 8Debug Options:
debug(boolean) - Enable debug modeverbose(boolean) - Show detailed evaluation infoshowTimings(boolean) - Display execution timingscolorize(boolean) - Use ANSI colors in output
Use Cases:
- ๐ Understanding complex filter logic
- โก Performance optimization
- ๐ Debugging unexpected results
- ๐ Analytics and monitoring
- ๐งช Testing and validation
Customize filter behavior with options:
import { filter } from '@mcabreradev/filter';
// Case-sensitive matching
filter(users, 'ALICE', { caseSensitive: true });
// Increase max depth for nested objects
filter(data, expression, { maxDepth: 5 });
// Enable caching for repeated queries
filter(largeDataset, expression, { enableCache: true });
// Enable debug mode (v5.5.0+)
filter(users, expression, { debug: true });
// Sort results by field(s)
filter(users, { age: { $gte: 18 } }, { orderBy: 'age' });
filter(users, { active: true }, {
orderBy: [
{ field: 'age', direction: 'desc' },
{ field: 'name', direction: 'asc' }
]
});
// Limit number of results
filter(users, { active: true }, { limit: 10 });
// Combine limit with sorting (limit is applied AFTER sorting)
filter(users, { active: true }, {
orderBy: { field: 'age', direction: 'desc' },
limit: 5
});
// Custom comparison logic
filter(data, expression, {
customComparator: (actual, expected) => actual === expected
});Available Options:
caseSensitive(boolean, default:false) - Case-sensitive string matchingmaxDepth(number, default:3, range: 1-10) - Max depth for nested objectsenableCache(boolean, default:false) - Enable result cachingdebug(boolean, default:false) - Enable debug mode with tree visualization (v5.5.0+)verbose(boolean, default:false) - Show detailed evaluation info in debug mode (v5.5.0+)showTimings(boolean, default:false) - Display execution timings in debug mode (v5.5.0+)colorize(boolean, default:false) - Use ANSI colors in debug output (v5.5.0+)orderBy(string | object | array, optional) - Sort filtered results by field(s) in ascending or descending order (v5.7.0+)limit(number, optional) - Limit the number of results returned (applied after filtering and sorting) (v5.7.0+)customComparator(function, optional) - Custom comparison function
Full TypeScript support with strict typing:
import { filter } from '@mcabreradev/filter';
import type {
Expression,
FilterOptions,
ComparisonOperators
} from '@mcabreradev/filter';
interface Product {
id: number;
name: string;
price: number;
category: string;
}
const products: Product[] = [...];
// Type-safe filtering
const result = filter<Product>(products, {
price: { $gte: 100 }
});
// result is Product[]
// Type-safe expressions
const priceFilter: ComparisonOperators = {
$gte: 100,
$lte: 500
};
filter<Product>(products, { price: priceFilter });interface Product {
id: number;
name: string;
price: number;
category: string;
brand: string;
rating: number;
inStock: boolean;
tags: string[];
createdAt: Date;
}
const products: Product[] = [...];
// E-commerce: Find affordable, highly-rated electronics in stock
const affordableElectronics = filter(products, {
category: 'Electronics',
price: { $lte: 1000 },
rating: { $gte: 4.5 },
inStock: { $eq: true }
});
// Search: Products matching keyword with filters
const searchResults = filter(products, {
name: { $contains: 'laptop' },
brand: { $in: ['Apple', 'Dell', 'HP'] },
price: { $gte: 500, $lte: 2000 }
});
// Analytics: Recent high-value orders
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const recentHighValue = filter(orders, {
createdAt: { $gte: thirtyDaysAgo },
amount: { $gte: 1000 },
status: { $in: ['completed', 'shipped'] }
});
// Sort results: Products sorted by price (ascending), then by rating (descending)
const sortedProducts = filter(products, {
category: 'Electronics',
inStock: true
}, {
orderBy: [
{ field: 'price', direction: 'asc' },
{ field: 'rating', direction: 'desc' }
]
});Filter is optimized for performance:
- Operators use early exit strategies for fast evaluation
- Regex patterns are compiled and cached
- Optional caching for repeated queries on large datasets (530x-1520x faster)
- Lazy evaluation for efficient large dataset processing (500x faster)
- Type guards for fast type checking
// โ
Fast: Operators with early exit
filter(data, { age: { $gte: 18 } });
// โ
Fast with caching for repeated queries
filter(largeData, expression, { enableCache: true });
// โ
Fast with lazy evaluation for large datasets
const result = filterFirst(millionRecords, { active: true }, 100);
// โ ๏ธ Slower: Complex predicates (but more flexible)
filter(data, (item) => complexCalculation(item));For performance optimization tips, see Performance Guide.
- Complete Wiki - Complete documentation with 150+ examples, API reference, TypeScript guide, real-world use cases, FAQ, and troubleshooting
- Framework Integrations - Complete guide for React, Vue, and Svelte integrations
- Operators Guide - Detailed guide for all 30+ MongoDB-style operators with examples and advanced regex patterns
- Geospatial Operators - Complete guide for location-based filtering with $near, $geoBox, $geoPolygon
- Date/Time Operators - Complete guide for temporal filtering with $recent, $upcoming, $dayOfWeek, $age
- Lazy Evaluation - Comprehensive guide to lazy evaluation for efficient large dataset processing
- Logical Operators - Advanced patterns and complex queries with $and, $or, $not
- Performance Benchmarks - Detailed performance metrics and optimization strategies
- Migration Guide - Migration guide from v3.x or native Array.filter()
- Examples - Real-world usage examples and code samples
- Installation & Setup
- Interactive Playground ๐ฎ NEW
- Framework Integrations โญ NEW
- Geospatial Operators ๐ NEW
- Date/Time Operators ๐ NEW
- All Operators Reference
- Regex Patterns Guide
- Logical Operators Guide
- Lazy Evaluation
- Memoization & Caching
- Performance Benchmarks
- TypeScript Integration
- Real-World Examples
- Performance Tips
- API Reference
- FAQ
- Troubleshooting
Good news: v5.x is 100% backward compatible! All v3.x code continues to work.
// โ
All v3.x syntax still works
filter(data, 'string');
filter(data, { prop: 'value' });
filter(data, (item) => true);
filter(data, '%pattern%');
// โ
New in v5.x
filter(data, { age: { $gte: 18 } });
filter(data, expression, { caseSensitive: true });
filter(data, expression, { enableCache: true });What's New in v5.x:
- v5.5.0: Array OR syntax, visual debugging, interactive playground
- v5.4.0: Framework integrations (React, Vue, Svelte)
- v5.3.0: Initial framework support
- v5.2.0: Enhanced memoization, logical operators ($and, $or, $not), regex operators
- v5.1.0: Lazy evaluation with generators
- v5.0.0: 18+ MongoDB-style operators, configuration API, runtime validation
See Migration Guide for detailed migration guide.
// Main filter function
filter<T>(array: T[], expression: Expression<T>, options?: FilterOptions): T[]
// Lazy evaluation functions
filterLazy<T>(array: T[], expression: Expression<T>, options?: FilterOptions): IterableIterator<T>
filterFirst<T>(array: T[], expression: Expression<T>, count: number, options?: FilterOptions): T[]
filterExists<T>(array: T[], expression: Expression<T>, options?: FilterOptions): boolean
filterCount<T>(array: T[], expression: Expression<T>, options?: FilterOptions): number
// Validation functions
validateExpression(expression: unknown): Expression<T>
validateOptions(options: unknown): FilterOptions
// Cache management
clearFilterCache(): void
getFilterCacheStats(): { hits: number; misses: number; size: number; hitRate: number }
// Configuration
mergeConfig(options?: FilterOptions): FilterConfig
createFilterConfig(options?: FilterOptions): FilterConfig
// Geospatial utilities
calculateDistance(p1: GeoPoint, p2: GeoPoint): number
isValidGeoPoint(point: unknown): point is GeoPoint
evaluateNear(point: GeoPoint, query: NearQuery): boolean
evaluateGeoBox(point: GeoPoint, box: BoundingBox): boolean
evaluateGeoPolygon(point: GeoPoint, query: PolygonQuery): boolean
// Framework integrations
useFilter<T>(data: T[], expression: Expression<T>, options?: FilterOptions) // React
useFilter<T>(data: Ref<T[]>, expression: Ref<Expression<T>>, options?: FilterOptions) // Vue
filterStore<T>(data: Writable<T[]>, expression: Writable<Expression<T>>, options?: FilterOptions) // SvelteFor complete API reference, see API Reference.
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
We welcome contributions! Please read our Contributing Guide for details on:
- Development setup and workflow
- Testing requirements
- Coding standards
- Pull request process
Ways to Contribute:
- Report bugs or request features via GitHub Issues
- Submit pull requests with bug fixes or new features
- Improve documentation
- Share your use cases and examples
For detailed guidelines, see CONTRIBUTING.md
# Run tests
pnpm test
# Watch mode
pnpm test:watch
# Coverage report
pnpm test:coverage
# Type checking
pnpm typecheckThe library has 994 tests with comprehensive coverage of all features.
- ๐จ New Framework Integrations: Angular, SolidJS, and Preact support
๐ ฐ๏ธ Angular: Services and Pipes with Signals support- ๐ท SolidJS: Signal-based reactive hooks with proper cleanup
- โก Preact: Lightweight hooks API compatible with React
- ๐ข Limit Option: New
limitconfiguration option to restrict result count - ๐ OrderBy Option: Sort filtered results by field(s) in ascending or descending order
- โ 33 new tests for limit functionality (994 total tests)
- ๐ Bug Fixes: Fixed
$containsoperator type detection for strings vs arrays - ๐ Complete documentation for all framework integrations
- ๐ Geospatial Operators: Location-based filtering with $near, $geoBox, $geoPolygon
- ๐ Distance Calculation: Spherical law of cosines for accurate distance measurement
- ๐บ๏ธ Spatial Queries: Proximity search, bounding box, and polygon containment
- ๐ Coordinate Validation: Automatic validation of lat/lng coordinates
- โก Performance Optimized: Fast algorithms for all geospatial operations
- ๐ Complete geospatial documentation and examples
- ๐ Date/Time Operators: Temporal filtering with $recent, $upcoming, $dayOfWeek, $timeOfDay, $age
- โฐ Relative Time Filtering: Filter by last/next N days/hours/minutes
- ๐๏ธ Day-of-Week Filtering: Filter by specific days (Monday-Sunday)
- ๐ Time-of-Day Filtering: Filter by hour ranges (0-23)
- ๐ Age Calculation: Calculate age in years/months/days with min/max ranges
- ๐ Weekday/Weekend Support: $isWeekday and $isWeekend operators
- ๐ Full TypeScript Support: Context-aware autocomplete for Date properties
- ๐ Zero Dependencies: Uses native Date API
- ๐ Complete datetime operators documentation and examples
- โ 90 new tests (994 total tests)
- ๐ Bug fixes and stability improvements
- ๐ Documentation updates
- ๐ง Build optimizations
- ๐จ Array OR Syntax: Intuitive array-based OR filtering (
{ city: ['Berlin', 'Paris'] }) - ๐ Visual Debugging: Built-in debug mode with expression tree visualization
- ๐ฎ Interactive Playground: New online playground for testing filters
- ๐ Debug Analytics: Performance metrics and condition evaluation tracking
- ๐จ Colorized Output: ANSI color support for debug tree visualization
- โก Performance improvements for array operations
- ๐จ Framework Integrations: React, Vue, and Svelte support
- ๐ช React Hooks:
useFilter,useFilteredState,useDebouncedFilter,usePaginatedFilter - ๐ Vue Composables: Full Composition API support with reactive refs
- ๐ฆ Svelte Stores: Reactive store-based filtering
- ๐ Comprehensive framework documentation
- โ 100% test coverage for all integrations
- ๐ TypeScript generics for type safety
- ๐ SSR compatibility (Next.js, Nuxt, SvelteKit)
- ๐จ Initial framework integration support
- ๐ช React hooks implementation
- ๐ Vue composables implementation
- ๐ฆ Svelte stores implementation
- ๐พ Enhanced Memoization: Multi-layer caching (530x faster)
- ๐ Logical Operators: $and, $or, $not for complex queries
- ๐ Regex Operators: $regex and $match for pattern matching
- ๐ Performance optimizations
- ๐จ Lazy Evaluation: filterLazy, filterFirst for efficient processing
- ๐ Generator-based filtering
- โก Early exit optimization
- โจ Added 18+ MongoDB-style operators
- โ๏ธ Configuration API with 4 options
- โ Runtime validation with Zod
- ๐ Performance optimizations
- ๐ Enhanced TypeScript support
- ๐งช 270+ tests
- ๐ Reorganized documentation into
/docsdirectory
See Migration Guide for detailed changelog and migration guide.
MIT License - see LICENSE.md for details.
Copyright (c) 2025 Miguelangel Cabrera
Author: Miguelรกngel Cabrera Repository: github.com/mcabreradev/filter
Inspired by MongoDB query syntax, SQL wildcards, and functional programming patterns.
- ๐ Complete Documentation
- ๐ฌ GitHub Discussions
- ๐ Issue Tracker
- โญ Star on GitHub
Made with โค๏ธ for the JavaScript/TypeScript community