@cosmejs/event-arc
v1.0.3
Published
Reactive RxJS-based event decorators for Node.js.
Maintainers
Readme
@cosme/event-decorators
Event-driven decorators for Node.js using RxJS — create custom decorators that listen to events, with support for filters, debounce, throttle, one-time listeners, validators, and parsers.
📦 Installation
npm install @cosmejs/event-arc rxjsor
yarn add @cosmejs/event-arc rxjsconfigure tsconfig to use experimental decorators:
{
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
}🚀 Basic Usage
1. Create an event handler class
const { OnEvent, registerEventHandlers, EventBus } = require('@cosmejs/event-arc');
class UserHandler {
constructor() {
registerEventHandlers(this);
}
@OnEvent('user:created')
onUserCreated(data: any) {
console.log('User created:', data);
}
}
const handler = new UserHandler();
// Emit event using EventBus
EventBus.emit('user:created', { id: 1, name: 'Alice' });⚙️ Advanced Usage
With configuration
const { OnEvent, registerEventHandlers, EventBus } = require('@cosmejs/event-arc');
class ProductHandler {
constructor() {
registerEventHandlers(this);
}
@OnEvent('product:updated', {
debounce: 300,
throttle: 1000,
once: false,
filter: (data) => data.price > 0,
})
onProductUpdated(data: any) {
console.log('Valid product update:', data);
}
}
// Emit an event through the EventBus
EventBus.emit('product:updated', { id: 1, price: 25 });✅ Validators
Create validators that run before executing the method.
If any validator returns false, the method won’t be called.
const { EventValidator, OnEvent, registerEventHandlers, EventBus } = require('@cosmejs/event-arc');
export class PriceValidator extends EventValidator {
async validate(data: any): Promise<boolean> {
return data.price > 0;
}
}
class ProductHandler {
constructor() {
registerEventHandlers(this);
}
@OnEvent('product:updated', { validators: [PriceValidator] })
onProductUpdated(data: any) {
console.log('Valid update:', data);
}
}
const handler = new ProductHandler();
EventBus.emit('product:updated', { id: 1, price: 20 }); // ✅ Triggers
EventBus.emit('product:updated', { id: 2, price: 0 }); // ❌ Skipped🧩 Parsers
Parsers can transform data before reaching your method.
const { EventParser, OnEvent, registerEventHandlers, EventBus } = require('@cosmejs/event-arc');
export class PriceParser extends EventParser {
async parse(data: any) {
return { ...data, price: Number(data.price) };
}
}
class ProductHandler {
constructor() {
registerEventHandlers(this);
}
@OnEvent('product:updated', { parsers: [PriceParser] })
onProductUpdated(data: any) {
console.log('Parsed data:', data);
}
}
const handler = new ProductHandler();
EventBus.emit('product:updated', { id: 1, price: '99.99' });🔧 EventBus
The library exports a singleton EventBus to emit and subscribe to events.
const { EventBus } = require('@cosmejs/event-arc');
// Emit events
EventBus.emit('user:created', { id: 1, name: 'Alice' });
// Subscribe manually (if needed)
EventBus.on('user:created').subscribe(({ data }) => console.log(data));Internal Implementation (Simplified)
import { Subject, filter } from 'rxjs';
class EventBusClass {
private bus = new Subject<{ name: string; data: any }>();
emit(name: string, data: any) {
this.bus.next({ name, data });
}
on(name: string) {
return this.bus.asObservable().pipe(filter((e) => e.name === name));
}
}
export const EventBus = new EventBusClass();The @OnEvent decorator automatically subscribes to the EventBus.on(eventName) observable.
🏗 Creating Custom Decorators
You can build your own decorators extending EventValidator or EventParser.
Example:
const { EventValidator, OnEvent, registerEventHandlers, EventBus } = require('@cosmejs/event-arc');
class NotEmptyValidator extends EventValidator {
async validate(data: any) {
return !!data && Object.keys(data).length > 0;
}
}
class CustomHandler {
constructor() {
registerEventHandlers(this);
}
@OnEvent('custom:event', { validators: [NotEmptyValidator] })
onCustomEvent(data: any) {
console.log('Custom event received:', data);
}
}
const handler = new CustomHandler();
EventBus.emit('custom:event', { name: 'Test' });📜 License
MIT © Cosme França
