@message-in-the-middle/core
Version:
Framework-agnostic middleware pattern for message queue processing. Core package with all middlewares.
88 lines • 3.01 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DispatcherMiddleware = exports.MessageDispatcher = void 0;
class MessageDispatcher {
handlers = new Map();
identifierField;
defaultHandler;
throwOnUnhandled;
constructor(options = {}) {
this.identifierField = options.identifierField || 'action';
this.defaultHandler = options.defaultHandler;
this.throwOnUnhandled = options.throwOnUnhandled ?? true;
}
register(identifier, handler) {
if (typeof identifier !== 'string' || identifier.length === 0) {
throw new Error('Identifier must be a non-empty string');
}
if (identifier.length > 256) {
throw new Error('Identifier too long (max 256 characters)');
}
const forbidden = ['__proto__', 'constructor', 'prototype'];
if (forbidden.includes(identifier)) {
throw new Error(`Forbidden identifier: ${identifier}`);
}
if (this.handlers.has(identifier)) {
throw new Error(`Handler already registered for identifier: ${identifier}`);
}
this.handlers.set(identifier, handler);
return this;
}
registerMany(handlers) {
Object.entries(handlers).forEach(([identifier, handler]) => {
this.register(identifier, handler);
});
return this;
}
async dispatch(context) {
const message = context.message;
const identifier = message?.[this.identifierField];
if (!identifier) {
throw new Error(`Message is missing identifier field: ${this.identifierField}`);
}
const handler = this.handlers.get(identifier);
if (handler) {
context.metadata.dispatchedTo = identifier;
await handler(context);
}
else if (this.defaultHandler) {
context.metadata.dispatchedTo = 'default';
await this.defaultHandler(context);
}
else if (this.throwOnUnhandled) {
throw new Error(`No handler registered for ${this.identifierField}: ${identifier}`);
}
else {
context.metadata.dispatchedTo = null;
context.metadata.skippedDispatch = true;
}
}
has(identifier) {
return this.handlers.has(identifier);
}
unregister(identifier) {
return this.handlers.delete(identifier);
}
getRegisteredIdentifiers() {
return Array.from(this.handlers.keys());
}
clear() {
this.handlers.clear();
}
getIdentifierField() {
return this.identifierField;
}
}
exports.MessageDispatcher = MessageDispatcher;
class DispatcherMiddleware {
dispatcher;
constructor(dispatcher) {
this.dispatcher = dispatcher;
}
async process(context, next) {
await this.dispatcher.dispatch(context);
await next();
}
}
exports.DispatcherMiddleware = DispatcherMiddleware;
//# sourceMappingURL=dispatcher.js.map