This directory contains practical examples demonstrating how to use @sfast/pattern-emitter-ts in real-world applications.
# From the root directory
npm install
npm run build# Basic usage
npx ts-node example/01-basic.ts
# API routing patterns
npx ts-node example/02-api-routing.ts
# Real-world e-commerce app
npx ts-node example/03-real-world-app.ts
# Advanced features
npx ts-node example/04-advanced-features.ts
# Namespace-based events
npx ts-node example/05-namespace-events.ts
# Performance benchmarks
npx ts-node example/06-benchmarks.tsWhat it demonstrates:
- String event listeners (exact match)
- Regex pattern listeners (match multiple events)
- How multiple patterns can match the same event
- Listener introspection (
listenerCount,eventNames,eventPatterns)
Key concept: Understanding the difference between exact string events and flexible regex patterns.
Run it:
npx ts-node example/01-basic.tsWhat it demonstrates:
- Using PatternEmitter for API-style event routing
- Combining exact endpoints with pattern-based middleware
- Request logging, authentication, and analytics patterns
- Real-world routing statistics
Key concept: How to build a flexible routing system using string + regex patterns.
Use case: REST API handlers, middleware chains, request logging
Run it:
npx ts-node example/02-api-routing.tsExample pattern:
// Exact endpoint
router.on('request:users:list', () => { /* handler */ });
// Pattern for all user endpoints
router.on(/^request:users:/, () => { /* middleware */ });
// Pattern for all create operations
router.on(/:create$/, () => { /* analytics */ });What it demonstrates:
- E-commerce order processing system
- Multiple systems listening to same events:
- Order processing
- Analytics tracking
- Email notifications
- Error handling
- Comprehensive logging
- Asynchronous event-driven architecture
Key concept: Building a complete application with multiple subsystems communicating via events.
Use case: E-commerce, order management, event-driven microservices
Run it:
npx ts-node example/03-real-world-app.tsWhat it demonstrates:
once()- Single execution listeners- Execution order preservation
- Dynamic handler registration/removal
- Listener introspection APIs
allListenersgetter for complete view- Bulk cleanup with
removeAllListeners - Max listeners configuration (memory leak prevention)
Key concept: Advanced PatternEmitter APIs for production applications.
Run it:
npx ts-node example/04-advanced-features.tsWhat it demonstrates:
- Hierarchical event namespaces (colon-separated)
- Multi-level pattern matching
- Microservices communication patterns
- Namespace best practices
Key concept: Organizing events using namespaces for clean, scalable architecture.
Use case: Large applications, microservices, domain-driven design
Run it:
npx ts-node example/05-namespace-events.tsExample namespaces:
// Hierarchical organization
events.on('app:user:profile:update', handler);
events.on(/^app:user:/, middleware);
events.on(/^app:/, globalLogger);
// Service-oriented
events.on('service:auth:login', handler);
events.on('service:payment:success', handler);What it demonstrates:
- Head-to-head comparison: EventEmitter vs PatternEmitter
- String event performance (apples to apples)
- Pattern matching overhead
- Scaling with many patterns
- Cache performance
- Listener registration costs
Key concept: Understanding the performance trade-offs to make informed decisions.
Run it:
npx ts-node example/06-benchmarks.tsKey findings:
String Events: ~50-60% overhead vs EventEmitter
Pattern Matching: PatternEmitter exclusive feature
Scalability: Handles 100+ patterns efficiently
Best Practice: Use PatternEmitter unless profiling shows bottleneck
const emitter = new PatternEmitter();
// Exact handler
emitter.on('request', () => {
console.log('Exact request event');
});
// Wildcard for variations
emitter.on(/^request:/, () => {
console.log('Any request:* event');
});
emitter.emit('request'); // Only first fires
emitter.emit('request:endpoint1'); // Only second fires// All match the same event - they all fire
emitter.on('user:login', () => {}); // Exact
emitter.on(/^user:/, () => {}); // Prefix
emitter.on(/login$/, () => {}); // Suffix
emitter.on(/.*/, () => {}); // Everything
emitter.emit('user:login'); // All 4 fire in order// Broad to specific
emitter.on(/^app:/, () => {}); // Level 1: All app events
emitter.on(/^app:user:/, () => {}); // Level 2: User events
emitter.on('app:user:login', () => {}); // Level 3: Specific action
emitter.emit('app:user:login'); // All 3 fire (hierarchy)- Use string events for specific, known events
- Use regex patterns for categories or middleware
- Organize events with namespaces (colon-separated)
- Use
once()for one-time initialization events - Call
removeListenerto prevent memory leaks - Use
listenerCount()to debug listener registration
- Don't use overly complex regex (e.g.,
/(a|b|c|d|e|f|g|h)/) - Don't emit events synchronously in a tight loop without
setImmediate - Don't forget to remove listeners when components unmount
- Don't mix event naming conventions (choose one style)
// String events only
console.log(emitter.eventNames());
// Regex patterns only
console.log(emitter.eventPatterns());
// All listeners (unified view)
console.log(emitter.allListeners);
// Specific event
console.log(emitter.listeners('my:event'));
console.log(emitter.listenerCount('my:event'));// Returns true if any listener fired
const hadListeners = emitter.emit('my:event');
if (!hadListeners) {
console.log('No listeners for this event!');
}- Full API Documentation
- Test Suite - 100 tests showing all edge cases
- Source Code
Open an issue on GitHub