
Security News
Federal Audit Finds NIST Wasted Funds With No Plan to Clear NVD Backlog
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.
@454creative/easy-events
Advanced tools
A minimal event engine for Node.js and NestJS, wrapping Emmett for lightweight in-process event handling
A lightweight, in-process event engine for Node.js and NestJS applications. Built on top of Emmett with optional observability and storage capabilities.
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();
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);
Easy-Events 2.0 features a modular architecture with clear separation of concerns:
// 1. Core 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/events';
// 4. Event Sourcing (Optional - Phase 3)
import { EmmettEngine } from '@454creative/easy-events';
// Event sourcing features are automatically available with storage
// 5. Distributed Events (Optional - Phase 4)
import { createDistributedEventEngine } from '@454creative/easy-events';
import { Events } from '@454creative/easy-events';
// Lightweight, no overhead
Events.emit('order.placed', { orderId: '123' });
Events.on('order.placed', (order) => {
// Process order
});
import { Events, DefaultObservabilityEngine } from '@454creative/easy-events';
const observability = new DefaultObservabilityEngine();
Events.setObservability(observability);
// Events are automatically tracked
Events.emit('payment.processed', { amount: 100 });
import { Events, DefaultObservabilityEngine, FileStorageEngine } from '@454creative/easy-events';
const storage = new FileStorageEngine({ path: './logs' });
const observability = new DefaultObservabilityEngine({ storage });
Events.setObservability(observability);
// For basic usage (recommended)
import { EasyEventsProvider } from '@454creative/easy-events';
@Module({
providers: [EasyEventsProvider],
exports: [EasyEventsProvider],
})
export class EventsModule {}
// In your service
@Injectable()
export class UserService {
constructor(@Inject('EVENTS') private readonly events) {}
createUser() {
this.events.emit('user.created', { id: 1 });
}
}
import { EmmettEngine } from '@454creative/easy-events';
import { createStorageEngine } from '@454creative/easy-events';
const storage = createStorageEngine({ type: 'file', path: './events' });
const engine = new EmmettEngine(undefined, storage);
// Events are automatically persisted with full event sourcing
await engine.emit('user.created', { userId: '123' });
// Replay events from storage
const events = await engine.replayEvents();
import { createDistributedEventEngine } from '@454creative/easy-events';
const engine = createDistributedEventEngine(undefined, {
mode: 'hybrid',
instanceId: 'app-1',
clusterName: 'production-cluster'
});
// Events can be local or distributed based on routing rules
await engine.emitWithRouting('user.created', { userId: '123' }, 'distributed');
📖 See NestJS Integration Guide for detailed setup and error handling.
{
"dependencies": {
"@454creative/easy-events": "file:../path/to/easy-events"
}
}
npm install @454creative/easy-events
once() handlersconst 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
}
});
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<T>(event: string, payload: T, tracing?: EventTracing): voidEmit an event with optional tracing information.
Events.emit('user.created', { id: 1, name: 'John' });
Events.emit('payment.processed', { amount: 100 }, {
traceId: 'trace-123',
userId: 'user-456'
});
on<T>(event: string, handler: (payload: T) => void): voidRegister a handler for an event. Handlers persist until manually removed.
Events.on('user.created', (user) => {
console.log('User created:', user);
});
once<T>(event: string, handler: (payload: T) => void): voidRegister a handler that executes only once and automatically removes itself. Perfect for one-time events.
Events.once('app.initialized', (config) => {
console.log('App initialized with config:', config);
});
Events.once('database.connected', () => {
console.log('Database connection established');
});
off(event?: string, handler?: (payload: any) => void): voidRemove event handlers. Supports multiple removal patterns.
// 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();
listeners(event: string): numberGet the number of listeners for a specific event.
const count = Events.listeners('user.created');
console.log(`${count} handlers listening to user.created`);
listenerCount(event: string): numberAlias for listeners(event) - follows Node.js EventEmitter naming.
const count = Events.listenerCount('user.created');
hasListeners(event: string): booleanCheck if an event has any listeners.
if (Events.hasListeners('user.created')) {
console.log('User creation is being monitored');
}
eventNames(): string[]Get an array of all registered event names.
const events = Events.eventNames();
console.log('Active events:', events);
// Output: ['user.created', 'payment.processed', 'app.initialized']
removeAllListeners(event?: string): voidRemove all listeners for a specific event (or all events if no event specified).
// Remove all handlers for specific event
Events.removeAllListeners('user.created');
// Remove all handlers from all events
Events.removeAllListeners();
clear(): voidRemove all listeners from all events. Shorter alias for removeAllListeners().
Events.clear(); // Removes all listeners
prependListener<T>(event: string, handler: (payload: T) => void): voidAdd a listener to the beginning of the listeners array (executes first). Note: Emmett doesn't support true prepend, so this acts like on().
Events.prependListener('user.created', (user) => {
console.log('First handler to execute');
});
rawListeners(event: string): Function[]Get the raw listener functions (including wrapper functions used internally).
const rawListeners = Events.rawListeners('user.created');
console.log('Raw listener functions:', rawListeners);
setMaxListeners(n: number): voidSet maximum number of listeners per event. Warns when exceeded.
Events.setMaxListeners(5); // Allow max 5 listeners per event
getMaxListeners(): numberGet the current maximum listeners setting.
const max = Events.getMaxListeners();
console.log(`Max listeners per event: ${max}`);
setObservability(observability: ObservabilityEngine): voidSet the observability engine for metrics and audit logging.
const observability = new DefaultObservabilityEngine();
Events.setObservability(observability);
getObservability(): ObservabilityEngine | undefinedGet the current observability engine.
const obs = Events.getObservability();
if (obs) {
const metrics = obs.getMetrics();
}
# Basic observability
npx ts-node examples/basic-observability-example.ts
# Simple observability
npx ts-node examples/simple-observability-example.ts
# Full observability
npx ts-node examples/observability-example.ts
# Custom logging
npx ts-node examples/custom-logging-example.ts
# Winston integration
npx ts-node examples/winston-integration-example.ts
# Storage examples
npx ts-node examples/storage-example.ts
npx ts-node examples/simple-storage-demo.ts
# Email examples
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
MIT License - see LICENSE for details.
Built with ❤️ by 454 Creative
FAQs
A minimal event engine for Node.js and NestJS, wrapping Emmett for lightweight in-process event handling
We found that @454creative/easy-events demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.