@454creative/easy-events
Version:
A minimal event engine for Node.js and NestJS, wrapping Emmett for lightweight in-process event handling
493 lines (370 loc) ⢠12.9 kB
Markdown
A lightweight, in-process event engine for Node.js and NestJS applications. Built on top of [Emmett](https://github.com/event-driven-io/emmett) with optional observability and storage capabilities.
```ts
import { Events } from '@454creative/easy-events';
// Emit events
Events.emit('user.created', { id: 1, name: 'John' });
// Handle events
Events.on('user.created', (payload) => {
console.log('User created:', payload);
});
// Handle events once (auto-removes after execution)
Events.once('app.initialized', (payload) => {
console.log('App initialized:', payload);
});
// Remove specific handler
const handler = (payload) => console.log(payload);
Events.on('user.updated', handler);
Events.off('user.updated', handler);
// Check if event has listeners
if (Events.hasListeners('user.created')) {
console.log('User creation is being monitored');
}
// Get listener count
const count = Events.listeners('user.created');
console.log(`${count} handlers listening to user.created`);
// Remove all listeners for an event
Events.removeAllListeners('user.created');
// Clear all listeners
Events.clear();
```
```ts
import { Events, DefaultObservabilityEngine } from '@454creative/easy-events';
// Configure observability
const observability = new DefaultObservabilityEngine({
enableMetrics: true,
enableAuditing: true,
logLevel: 'info'
});
Events.setObservability(observability);
// Your events now include metrics and audit logs
Events.emit('user.created', { id: 1 });
// Get metrics
const metrics = observability.getMetrics();
console.log('Total events:', metrics.totalEvents);
// Get audit logs
const logs = observability.getAuditLogs();
console.log('Recent events:', logs);
```
- **[Quick Start Guide](docs/quick-start-guide.md)** - Complete setup and examples
- **[API Reference](docs/api-reference.md)** - Complete method documentation and examples
- **[Migration Guide](docs/migration-guide.md)** - Solving duplicate events and memory leaks
- **[Observability Guide](docs/observability-guide.md)** - Metrics, auditing, and monitoring
- **[Observability Examples](docs/observability-examples-guide.md)** - Working observability examples
- **[Logging Examples](docs/logging-examples-guide.md)** - Custom logging and Winston integration
- **[Event-Driven Best Practices](docs/event-driven-best-practices.md)** - Architecture patterns and guidelines
- **[Cost-Effective Message Brokers](docs/cost-effective-message-brokers.md)** - Migration from in-process to distributed events
- **[Publishing Guide](docs/publishing-guide.md)** - How to publish to npm registry
```ts
// 1. Event Engine (Required)
import { Events, EmmettEngine } from '@454creative/easy-events';
// 2. Observability Engine (Optional)
import { DefaultObservabilityEngine } from '@454creative/easy-events';
// 3. Storage Engine (Optional)
import { MemoryStorageEngine, FileStorageEngine } from '@454creative/easy-events';
```
```ts
import { Events } from '@454creative/easy-events';
// Lightweight, no overhead
Events.emit('order.placed', { orderId: '123' });
Events.on('order.placed', (order) => {
// Process order
});
```
```ts
import { Events, DefaultObservabilityEngine } from '@454creative/easy-events';
const observability = new DefaultObservabilityEngine();
Events.setObservability(observability);
// Events are automatically tracked
Events.emit('payment.processed', { amount: 100 });
```
```ts
import { Events, DefaultObservabilityEngine, FileStorageEngine } from '@454creative/easy-events';
const storage = new FileStorageEngine({ path: './logs' });
const observability = new DefaultObservabilityEngine({ storage });
Events.setObservability(observability);
```
```ts
// For basic usage (recommended)
import { SimpleEasyEventsProvider } from '@454creative/easy-events';
@Module({
providers: [SimpleEasyEventsProvider],
exports: [SimpleEasyEventsProvider],
})
export class EventsModule {}
// For production with observability
import { EnhancedEasyEventsProvider } from '@454creative/easy-events';
@Module({
providers: [EnhancedEasyEventsProvider],
exports: [EnhancedEasyEventsProvider],
})
export class EventsModule {}
// In your service
@Injectable()
export class UserService {
constructor(@Inject('SIMPLE_EVENTS') private readonly events) {}
createUser() {
this.events.emit('user.created', { id: 1 });
}
}
```
š **See [NestJS Integration Guide](docs/nestjs-integration-guide.md) for detailed setup and error handling.**
```json
{
"dependencies": {
"@454creative/easy-events": "file:../path/to/easy-events"
}
}
```
```bash
npm install @454creative/easy-events
```
- Works out of the box with minimal setup
- Optional observability and storage
- Lightweight bundle size
- In-process event handling for local development
- Easy migration to distributed message brokers
- Custom storage and observability engines
- TypeScript support
- Comprehensive examples
- Clear documentation
- NestJS integration ready
- Error handling and recovery
- Performance monitoring
- Audit logging
- Custom logging support
- Full Node.js EventEmitter compatibility
- Memory leak prevention with `once()` handlers
- Comprehensive listener management
- Debugging and monitoring tools
```ts
const observability = new DefaultObservabilityEngine({
enableMetrics: true, // Track event metrics
enableAuditing: true, // Log all events
enableTracing: true, // Include correlation IDs
enablePerformanceMonitoring: true, // Track processing times
logLevel: 'info', // 'debug' | 'info' | 'warn' | 'error'
auditRetentionDays: 30, // How long to keep audit logs
metricsRetentionDays: 7, // How long to keep metrics
customAuditLogger: (audit) => {
// Custom audit logging
}
});
```
```ts
const storage = new FileStorageEngine({
type: 'file',
path: './logs', // Where to store logs
maxLogs: 10000, // Maximum logs to keep
retentionDays: 30 // How long to keep logs
});
```
Emit an event with optional tracing information.
```ts
Events.emit('user.created', { id: 1, name: 'John' });
Events.emit('payment.processed', { amount: 100 }, {
traceId: 'trace-123',
userId: 'user-456'
});
```
Register a handler for an event. Handlers persist until manually removed.
```ts
Events.on('user.created', (user) => {
console.log('User created:', user);
});
```
Register a handler that executes only once and automatically removes itself. Perfect for one-time events.
```ts
Events.once('app.initialized', (config) => {
console.log('App initialized with config:', config);
});
Events.once('database.connected', () => {
console.log('Database connection established');
});
```
Remove event handlers. Supports multiple removal patterns.
```ts
// Remove specific handler for specific event
const handler = (user) => console.log(user);
Events.on('user.created', handler);
Events.off('user.created', handler);
// Remove all handlers for specific event
Events.off('user.created');
// Remove specific handler from all events
Events.off(undefined, handler);
// Remove all handlers from all events
Events.off();
```
Get the number of listeners for a specific event.
```ts
const count = Events.listeners('user.created');
console.log(`${count} handlers listening to user.created`);
```
Alias for `listeners(event)` - follows Node.js EventEmitter naming.
```ts
const count = Events.listenerCount('user.created');
```
Check if an event has any listeners.
```ts
if (Events.hasListeners('user.created')) {
console.log('User creation is being monitored');
}
```
Get an array of all registered event names.
```ts
const events = Events.eventNames();
console.log('Active events:', events);
// Output: ['user.created', 'payment.processed', 'app.initialized']
```
Remove all listeners for a specific event (or all events if no event specified).
```ts
// Remove all handlers for specific event
Events.removeAllListeners('user.created');
// Remove all handlers from all events
Events.removeAllListeners();
```
Remove all listeners from all events. Shorter alias for `removeAllListeners()`.
```ts
Events.clear(); // Removes all listeners
```
Add a listener to the beginning of the listeners array (executes first). Note: Emmett doesn't support true prepend, so this acts like `on()`.
```ts
Events.prependListener('user.created', (user) => {
console.log('First handler to execute');
});
```
Get the raw listener functions (including wrapper functions used internally).
```ts
const rawListeners = Events.rawListeners('user.created');
console.log('Raw listener functions:', rawListeners);
```
Set maximum number of listeners per event. Warns when exceeded.
```ts
Events.setMaxListeners(5); // Allow max 5 listeners per event
```
Get the current maximum listeners setting.
```ts
const max = Events.getMaxListeners();
console.log(`Max listeners per event: ${max}`);
```
Set the observability engine for metrics and audit logging.
```ts
const observability = new DefaultObservabilityEngine();
Events.setObservability(observability);
```
Get the current observability engine.
```ts
const obs = Events.getObservability();
if (obs) {
const metrics = obs.getMetrics();
}
```
```bash
npx ts-node examples/basic-observability-example.ts
npx ts-node examples/simple-observability-example.ts
npx ts-node examples/observability-example.ts
npx ts-node examples/custom-logging-example.ts
npx ts-node examples/winston-integration-example.ts
npx ts-node examples/storage-example.ts
npx ts-node examples/simple-storage-demo.ts
npx ts-node examples/nestjs-email-example/src/simple-app.ts
npx ts-node examples/nestjs-email-example/src/easy-events-demo.ts
npx ts-node examples/nestjs-email-example/src/email-with-observability.ts
```
- Total events processed
- Events by type
- Average processing time
- Error count
- Active handlers
- Event ID and type
- Timestamp and payload
- Correlation ID
- User ID and source
- Processing time
- Success/error status
- Correlation IDs for request tracking
- User context
- Source identification
- Performance monitoring
1. **Start Simple**: Use in-process events for local development
2. **Add Observability**: Enable metrics and audit logging
3. **Add Storage**: Persist logs to file or database
4. **Scale Up**: Migrate to distributed message brokers (Kafka, Redis, etc.)
## š¤ Contributing
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests
5. Submit a pull request
## š License
MIT License - see [LICENSE](LICENSE) for details.
## š Support
- **Documentation**: [docs/](docs/)
- **Examples**: [examples/](examples/)
- **Issues**: [Bitbucket Issues](https://bitbucket.org/454creative/easy-events/issues)
---
**Built with ā¤ļø by [454 Creative](https://454creative.com)**