Skip to content

Configuration ​

Filter provides flexible configuration options to customize behavior for your specific needs. Configure globally or per-filter call.

Overview ​

Available configuration options:

  • caseSensitive - Control case sensitivity for string matching
  • maxDepth - Set maximum depth for nested object traversal
  • enableCache - Enable performance caching
  • customComparator - Provide custom comparison logic
  • debug - Enable debug mode with visual tree output
  • verbose - Show additional debug details (requires debug: true)
  • showTimings - Display execution timings (requires debug: true)
  • colorize - Use ANSI colors in debug output (requires debug: true)
  • orderBy - Sort filtered results by field(s) (v5.7.0+)
  • limit - Limit the number of results returned (v5.7.0+)
  • enablePerformanceMonitoring - Collect and inspect filter execution timings (v5.7.0+)

Configuration Options ​

caseSensitive ​

Controls whether string comparisons are case-sensitive.

Type: booleanDefault: false

typescript
filter(users, 'alice');

filter(users, 'Alice', { caseSensitive: true });

Use Cases:

  • Case-insensitive search (default)
  • Exact case matching for codes/IDs
  • Case-sensitive email validation

Examples:

typescript
const users = [
  { name: 'Alice' },
  { name: 'alice' },
  { name: 'ALICE' },
];

filter(users, 'alice');

filter(users, 'alice', { caseSensitive: true });

maxDepth ​

Controls how deep the filter traverses nested objects.

Type: numberDefault: 3Range: 1-10 (recommended: 1-5) — 0 is invalid

typescript
filter(data, expression, { maxDepth: 5 });

Use Cases:

  • Limit traversal for performance
  • Control nested object filtering depth
  • Prevent excessive recursion

Examples:

typescript
interface DeepObject {
  level1: {
    level2: {
      level3: {
        value: string;
      };
    };
  };
}

filter(data, {
  level1: {
    level2: {
      level3: {
        value: 'test'
      }
    }
  }
}, { maxDepth: 3 });

Performance Impact:

  • Lower values = faster filtering
  • Higher values = more flexible but slower
  • Default (3) balances flexibility and performance

enableCache ​

Enables caching of filter predicates and regex patterns for improved performance.

Type: booleanDefault: false

typescript
filter(data, expression, { enableCache: true });

Use Cases:

  • Repeated filtering with same expression
  • High-frequency filtering operations
  • Performance-critical applications

Performance Gains:

  • Up to 530x faster for cached predicates
  • Significant improvement for regex patterns
  • Best for repeated identical queries

Examples:

typescript
const expression = { age: { $gte: 18 } };

filter(users, expression, { enableCache: true });
filter(users, expression, { enableCache: true });

Cache Management:

typescript
import { clearFilterCache, getFilterCacheStats } from '@mcabreradev/filter';

clearFilterCache();

const stats = getFilterCacheStats();
console.log(stats);

debug ​

Enable debug mode to visualize filter execution with tree output and statistics.

Type: booleanDefault: false

typescript
filter(users, { city: 'Berlin' }, { debug: true });

Use Cases:

  • Understanding complex filter logic
  • Debugging why items match or don't match
  • Performance analysis
  • Development and testing

Output:

Filter Debug Tree
└── city = "Berlin" (2/3 matched, 66.7%)

Statistics:
├── Matched: 2 / 3 items (66.7%)
├── Execution Time: 0.45ms
├── Cache Hit: No
└── Conditions Evaluated: 1

Examples:

typescript
filter(users, {
  $and: [
    { city: 'Berlin' },
    { age: { $gte: 25 } }
  ]
}, { debug: true });

Debug Options:

Combine with verbose, showTimings, and colorize for enhanced output:

typescript
filter(users, expression, {
  debug: true,
  verbose: true,
  showTimings: true,
  colorize: true
});

orderBy ​

Sort filtered results by one or more fields in ascending or descending order.

Type: string | { field: string; direction: 'asc' | 'desc' } | Array<string | { field: string; direction: 'asc' | 'desc' }>Default: undefined (no sorting)

typescript
filter(users, { age: { $gte: 18 } }, { orderBy: 'age' });

Use Cases:

  • Sort results by a single field
  • Multi-field sorting (primary, secondary, tertiary)
  • Sort by nested paths using dot notation
  • Combine filtering with sorting in one operation

Single Field Sorting:

typescript
const users = [
  { name: 'Charlie', age: 35 },
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
];

filter(users, {}, { orderBy: 'name' });
filter(users, {}, { orderBy: { field: 'age', direction: 'desc' } });

Multiple Fields Sorting:

Sort by multiple fields with different directions:

typescript
filter(users, {}, {
  orderBy: [
    { field: 'age', direction: 'desc' },
    { field: 'name', direction: 'asc' }
  ]
});

Nested Paths:

Sort by nested object properties using dot notation:

typescript
const users = [
  { name: 'Alice', profile: { age: 30, address: { city: 'Berlin' } } },
  { name: 'Bob', profile: { age: 25, address: { city: 'London' } } },
];

filter(users, {}, { orderBy: 'profile.age' });
filter(users, {}, { orderBy: 'profile.address.city' });

Combining with Filtering:

Filter and sort in a single operation:

typescript
filter(users, { city: 'Berlin' }, { orderBy: 'age' });
filter(products, { category: 'Electronics' }, {
  orderBy: [
    { field: 'price', direction: 'asc' },
    { field: 'rating', direction: 'desc' }
  ]
});

Type Support:

  • Strings: Case-insensitive by default (respects caseSensitive option)
  • Numbers: Numeric comparison
  • Dates: Date comparison using getTime()
  • Booleans: Boolean comparison
  • Null/undefined: Placed at the end (nulls last)

Examples:

typescript
const products = [
  { name: 'Laptop', price: 1200, rating: 4.5 },
  { name: 'Mouse', price: 25, rating: 4.8 },
  { name: 'Monitor', price: 450, rating: 4.2 },
];

filter(products, { price: { $lte: 1000 } }, { orderBy: 'price' });

filter(products, {}, {
  orderBy: [
    { field: 'rating', direction: 'desc' },
    { field: 'price', direction: 'asc' }
  ]
});

Performance Impact:

  • Sorting is O(n log n) operation
  • Applied only when orderBy is specified
  • No performance impact when orderBy is not used
  • Works efficiently with caching (different orderBy = different cache entry)

See Debug Mode Guide for complete documentation.

limit ​

Limit the number of results returned by the filter. The limit is applied after filtering and sorting, so you get the top N results after all processing.

Type: numberDefault: undefined (no limit)

typescript
filter(users, { active: true }, { limit: 10 });

Use Cases:

  • Pagination and result limiting
  • "Top N" queries (e.g., top 10 products)
  • Performance optimization for large datasets
  • Preview/sample data display
  • Rate limiting and quotas

Basic Usage:

typescript
const users = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 },
  { name: 'David', age: 28 },
  { name: 'Eve', age: 32 },
];

filter(users, { age: { $gte: 25 } }, { limit: 3 });

Combining with Sorting:

Get the top N results by combining limit with orderBy:

typescript
filter(products, { category: 'Electronics' }, {
  orderBy: { field: 'price', direction: 'desc' },
  limit: 5
});

filter(users, { active: true }, {
  orderBy: [
    { field: 'score', direction: 'desc' },
    { field: 'createdAt', direction: 'asc' }
  ],
  limit: 10
});

Special Values:

  • undefined or omitted: No limit (returns all matching results)
  • Positive integers: Returns at most N results
  • 0, negative values, or non-integers: rejected by validation — throws a ConfigurationError (added in v5.8.2)

Examples:

typescript
// Invalid — throws ConfigurationError (limit must be a positive integer)
// filter(users, { active: true }, { limit: 0 });
// filter(users, { active: true }, { limit: -5 });

// Valid
filter(users, { active: true });

filter(users, { active: true }, { limit: 100 });

Top N Queries:

Get top performers, highest scores, most recent items, etc.:

typescript
filter(students, {}, {
  orderBy: { field: 'grade', direction: 'desc' },
  limit: 10
});

filter(posts, { published: true }, {
  orderBy: { field: 'createdAt', direction: 'desc' },
  limit: 20
});

filter(products, { category: 'Electronics', inStock: true }, {
  orderBy: [
    { field: 'rating', direction: 'desc' },
    { field: 'price', direction: 'asc' }
  ],
  limit: 5
});

Pagination Pattern:

While limit doesn't support offset directly, you can implement pagination by filtering in chunks:

typescript
const pageSize = 10;

const allResults = filter(users, { active: true }, {
  orderBy: 'createdAt'
});

const page1 = allResults.slice(0, pageSize);
const page2 = allResults.slice(pageSize, pageSize * 2);
const page3 = allResults.slice(pageSize * 2, pageSize * 3);

Or use lazy evaluation for memory efficiency:

typescript
import { filterLazy, take, toArray } from '@mcabreradev/filter';

const resultsIterator = filterLazy(users, { active: true });
const limitedResults = toArray(take(resultsIterator, 10));

Performance Impact:

  • limit is applied after filtering and sorting
  • Reduces memory usage when only subset of results needed
  • No performance gain for filtering itself (all items still evaluated)
  • Fastest when combined with lazy evaluation for early exit

Combining with Caching:

Limit works with caching - different limits create different cache entries:

typescript
filter(users, { active: true }, {
  limit: 10,
  enableCache: true
});

filter(users, { active: true }, {
  limit: 20,
  enableCache: true
});

Order of Operations:

Understanding how limit interacts with other options:

  1. Filtering - Apply expression to all items
  2. Sorting - Apply orderBy if specified
  3. Limiting - Apply limit to get top N results
typescript
const result = filter(products, { category: 'Electronics' }, {
  orderBy: { field: 'price', direction: 'desc' },
  limit: 5
});

Best Practices:

typescript
filter(users, { active: true }, {
  orderBy: 'name',
  limit: 100
});

filter(users, { active: true }, { limit: 0 });

import { filterLazy, take } from '@mcabreradev/filter';
const result = take(filterLazy(hugeDataset, expression), 1000);

const pageSize = 20;
filter(users, expression, {
  orderBy: 'createdAt',
  limit: pageSize,
  enableCache: true
});

verbose ​

Show additional details in debug output (only works with debug: true).

Type: booleanDefault: false

typescript
filter(users, expression, {
  debug: true,
  verbose: true
});

showTimings ​

Display execution time for each node in debug tree (only works with debug: true).

Type: booleanDefault: false

typescript
filter(users, expression, {
  debug: true,
  showTimings: true
});

colorize ​

Use ANSI colors in debug output for better readability (only works with debug: true).

Type: booleanDefault: false

typescript
filter(users, expression, {
  debug: true,
  colorize: true
});

customComparator ​

Provide custom comparison logic for string matching.

Type: (actual: unknown, expected: unknown) => booleanDefault: Case-insensitive substring matching

typescript
filter(data, expression, {
  customComparator: (actual, expected) => {
    return String(actual) === String(expected);
  }
});

Use Cases:

  • Custom string comparison logic
  • Locale-specific comparisons
  • Special matching rules
  • Domain-specific equality

Examples:

typescript
filter(users, 'alice', {
  customComparator: (actual, expected) => {
    return String(actual).toLowerCase() === String(expected).toLowerCase();
  }
});

Advanced Comparator:

typescript
filter(products, 'widget', {
  customComparator: (actual, expected) => {
    const actualStr = String(actual).toLowerCase().trim();
    const expectedStr = String(expected).toLowerCase().trim();

    return actualStr.includes(expectedStr) ||
           expectedStr.includes(actualStr);
  }
});

Configuration Methods ​

Per-Filter Configuration ​

Pass options to individual filter calls:

typescript
filter(users, expression, {
  caseSensitive: true,
  maxDepth: 5,
  enableCache: true
});

Configuration Builder ​

Use the configuration builder for reusable configs:

typescript
import { createFilterConfig } from '@mcabreradev/filter';

const config = createFilterConfig({
  caseSensitive: true,
  enableCache: true,
  maxDepth: 4
});

filter(users, expression, config);

Merging Configurations ​

Merge multiple configurations:

typescript
import { mergeConfig } from '@mcabreradev/filter';

const baseConfig = { caseSensitive: true };
const cacheConfig = { enableCache: true };

const merged = mergeConfig(baseConfig, cacheConfig);

Real-World Examples ​

Case-Sensitive Code Matching ​

typescript
const products = [
  { sku: 'PRD-001' },
  { sku: 'prd-001' },
];

filter(products, { sku: 'PRD-001' }, {
  caseSensitive: true
});

Deep Object Filtering ​

typescript
interface Organization {
  department: {
    team: {
      lead: {
        name: string;
      };
    };
  };
}

filter(orgs, {
  department: {
    team: {
      lead: {
        name: 'Alice'
      }
    }
  }
}, {
  maxDepth: 4
});

High-Performance Dashboard ​

typescript
const dashboardConfig = {
  enableCache: true,
  caseSensitive: false,
  maxDepth: 3
};

const activeUsers = filter(users, { status: 'active' }, dashboardConfig);
const premiumUsers = filter(users, { premium: true }, dashboardConfig);

Custom Fuzzy Matching ​

typescript
filter(products, 'laptop', {
  customComparator: (actual, expected) => {
    const actualStr = String(actual).toLowerCase();
    const expectedStr = String(expected).toLowerCase();

    const distance = levenshteinDistance(actualStr, expectedStr);
    return distance <= 2;
  }
});

Configuration Patterns ​

Development vs Production ​

typescript
const config = {
  enableCache: process.env.NODE_ENV === 'production',
  caseSensitive: false,
  maxDepth: 3
};

filter(data, expression, config);

Feature Flags ​

typescript
const config = {
  enableCache: featureFlags.caching,
  caseSensitive: featureFlags.strictMatching,
  maxDepth: featureFlags.deepSearch ? 5 : 3
};

User Preferences ​

typescript
const getUserConfig = (preferences) => ({
  caseSensitive: preferences.exactMatch,
  enableCache: preferences.performanceMode,
  maxDepth: preferences.searchDepth || 3
});

filter(data, expression, getUserConfig(userPreferences));

Performance Guidelines ​

When to Enable Caching ​

Enable caching when:

  • Filtering the same data repeatedly
  • Using identical expressions multiple times
  • Performance is critical
  • Working with large datasets

Don't enable caching when:

  • Expressions change frequently
  • Memory is constrained
  • Filtering small datasets
  • One-time queries

Optimal maxDepth ​

Use CaseRecommended maxDepth
Flat objects1
Simple nesting2-3 (default)
Complex structures4-5
Very deep nesting6+ (use sparingly)

caseSensitive Impact ​

  • Case-insensitive (default): Slightly slower but more flexible
  • Case-sensitive: Faster but stricter matching

Best Practices ​

1. Use Sensible Defaults ​

typescript
const defaultConfig = {
  caseSensitive: false,
  maxDepth: 3,
  enableCache: false
};

2. Enable Caching for Repeated Queries ​

typescript
const config = { enableCache: true };

setInterval(() => {
  const active = filter(users, { status: 'active' }, config);
  updateDashboard(active);
}, 1000);

3. Adjust maxDepth Based on Data ​

typescript
const shallowConfig = { maxDepth: 2 };
const deepConfig = { maxDepth: 5 };

filter(simpleData, expression, shallowConfig);
filter(complexData, expression, deepConfig);

4. Document Custom Comparators ​

typescript
const fuzzyComparator = (actual, expected) => {
  return similarity(actual, expected) > 0.8;
};

filter(data, expression, {
  customComparator: fuzzyComparator
});

5. Clear Cache Periodically ​

typescript
import { clearFilterCache } from '@mcabreradev/filter';

setInterval(() => {
  clearFilterCache();
}, 60000);

TypeScript Support ​

Full type safety for configuration:

typescript
import type { FilterOptions } from '@mcabreradev/filter';

const config: FilterOptions = {
  caseSensitive: true,
  maxDepth: 4,
  enableCache: true,
  customComparator: (a, b) => String(a) === String(b)
};

filter(users, expression, config);

Troubleshooting ​

Nested Properties Not Matching ​

Increase maxDepth:

typescript
filter(data, expression, { maxDepth: 5 });

Case Sensitivity Issues ​

Check caseSensitive setting:

typescript
filter(users, 'Alice', { caseSensitive: false });

Performance Problems ​

Enable caching:

typescript
filter(data, expression, { enableCache: true });

Custom Comparator Not Working ​

Verify comparator signature:

typescript
const comparator = (actual: unknown, expected: unknown): boolean => {
  return String(actual) === String(expected);
};

filter(data, expression, { customComparator: comparator });

Advanced Configuration ​

Combining All Options ​

typescript
const advancedConfig = {
  caseSensitive: true,
  maxDepth: 5,
  enableCache: true,
  customComparator: (actual, expected) => {
    if (typeof actual === 'string' && typeof expected === 'string') {
      return actual.localeCompare(expected, 'en', { sensitivity: 'base' }) === 0;
    }
    return actual === expected;
  }
};

filter(data, expression, advancedConfig);

Environment-Based Configuration ​

typescript
const getConfig = (): FilterOptions => {
  const env = process.env.NODE_ENV;

  return {
    caseSensitive: env === 'production',
    maxDepth: env === 'development' ? 5 : 3,
    enableCache: env === 'production',
  };
};

filter(data, expression, getConfig());

See Also ​

Released under the MIT License.