@logistically/events
Version:
A production-ready event-driven architecture library for NestJS with Redis Streams, comprehensive batching, reliable consumption, and enterprise-grade features.
79 lines (78 loc) • 3.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EventConsumer = void 0;
class EventConsumer {
constructor(options) {
this.handlers = options.handlers;
this.onError = options.onError;
if (!options.validator) {
throw new Error('validator must be provided in EventConsumerOptions');
}
this.validator = options.validator;
this.logUnregisteredEvents = options.logUnregisteredEvents || 'debug';
}
async handleMessage(rawMessage) {
var _a, _b;
let envelope = undefined;
try {
// Validate that rawMessage has the expected structure
if (!rawMessage || typeof rawMessage !== 'object') {
throw new Error('Invalid message: not an object');
}
// Type guard to ensure proper envelope structure
if (!this.isValidEnvelope(rawMessage)) {
throw new Error('Invalid envelope structure: missing header or body');
}
envelope = rawMessage;
const { type } = envelope.header;
// Validate event body using the validator
const validation = this.validator.validate(type, envelope.body);
if (!validation.valid) {
throw new Error(`Invalid event body for type ${type}: ${validation.error}`);
}
const handler = this.handlers[type];
if (!handler) {
// Gracefully ignore events that don't have registered handlers
if (this.logUnregisteredEvents !== 'none') {
console[this.logUnregisteredEvents](`[EventConsumer] No handler registered for event type: ${type}, ignoring message`);
}
return;
}
await handler(envelope.body, envelope.header, rawMessage);
}
catch (err) {
if (this.onError) {
this.onError(err, ((_b = (_a = envelope === null || envelope === void 0 ? void 0 : envelope.header) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : 'unknown'), rawMessage);
}
else {
throw err;
}
}
}
isValidEnvelope(message) {
return (message &&
typeof message === 'object' &&
message.header &&
typeof message.header === 'object' &&
typeof message.header.id === 'string' &&
typeof message.header.type === 'string' &&
typeof message.header.origin === 'string' &&
typeof message.header.timestamp === 'string' &&
typeof message.header.hash === 'string' &&
typeof message.header.version === 'string' &&
'body' in message);
}
// Method to register handlers dynamically
registerHandler(eventType, handler) {
this.handlers[eventType] = handler;
}
// Method to unregister handlers
unregisterHandler(eventType) {
delete this.handlers[eventType];
}
// Method to get registered event types
getRegisteredEventTypes() {
return Object.keys(this.handlers);
}
}
exports.EventConsumer = EventConsumer;