UNPKG

mediatr-ts

Version:

Mimic the famous MediatR csharp library see: (https://github.com/jbogard/MediatR)

247 lines 11.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var index_js_1 = require("../models/mappings/index.js"); var instantiationResolver_js_1 = require("./instantiationResolver.js"); var publish_error_js_1 = __importDefault(require("../errors/publish-error.js")); /** * The mediator class. * Sends request and publishes events. * * @export * @class Mediator * @implements {Mediator} */ var Mediator = /** @class */ (function () { /** * The constructor. * If custom settings are provided, it uses the resolver from those settings; * otherwise, it defaults to a new InstantiationResolver * * @param settings The custom settings */ function Mediator(settings) { var resolver = (settings === null || settings === void 0 ? void 0 : settings.resolver) || new instantiationResolver_js_1.InstantiationResolver(); this._resolver = resolver; this.registerTypesInResolver(resolver); } Object.defineProperty(Mediator.prototype, "notifications", { /** * Gets the notifications. */ get: function () { return index_js_1.typeMappings.notifications; }, enumerable: false, configurable: true }); Object.defineProperty(Mediator.prototype, "pipelineBehaviors", { /** * Gets the pipeline behaviors. */ get: function () { return index_js_1.typeMappings.pipelineBehaviors; }, enumerable: false, configurable: true }); /** * This method registers types with a resolver. * If custom settings are provided, it uses the resolver from those settings; * otherwise, it defaults to a new InstantiationResolver where add method is not used * * @param resolver The resolver */ Mediator.prototype.registerTypesInResolver = function (resolver) { for (var _i = 0, _a = index_js_1.typeMappings.notifications.getAll(); _i < _a.length; _i++) { var mapping = _a[_i]; resolver.add(mapping.handlerClass); } for (var _b = 0, _c = index_js_1.typeMappings.requestHandlers.getAll(); _b < _c.length; _b++) { var mapping = _c[_b]; resolver.add(mapping.handlerClass); } for (var _d = 0, _e = index_js_1.typeMappings.pipelineBehaviors.getAll(); _d < _e.length; _d++) { var mapping = _e[_d]; resolver.add(mapping.behaviorClass); } }; /** * Send a request to the mediator. * * @template T * @param {RequestData<T>} request The request to send * @returns {Promise<T>} * @memberof Mediator */ Mediator.prototype.send = function (request) { return __awaiter(this, void 0, void 0, function () { var handler; var _this = this; return __generator(this, function (_a) { handler = this.getRequiredHandlerForRequest(request); return [2 /*return*/, this.wrapInPipelineBehaviorChainCalls(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, handler.handle(request)]; }); }); }, request)]; }); }); }; /** * Wraps the given function in a chain of pipeline behavior calls. * * @param func The function to wrap * @param request The request to send * @returns The result of the action * @memberof Mediator * @private * */ Mediator.prototype.wrapInPipelineBehaviorChainCalls = function (func, request) { return __awaiter(this, void 0, void 0, function () { var currentBehaviorIndex, behaviors, execBehavior, next; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: currentBehaviorIndex = 0; behaviors = index_js_1.typeMappings.pipelineBehaviors.getAll(); execBehavior = function (request, next) { return __awaiter(_this, void 0, void 0, function () { var behaviorClass, nextBehaviorInChain; return __generator(this, function (_a) { switch (_a.label) { case 0: behaviorClass = behaviors[currentBehaviorIndex++].behaviorClass; nextBehaviorInChain = this._resolver.resolve(behaviorClass); return [4 /*yield*/, nextBehaviorInChain.handle(request, next)]; case 1: return [2 /*return*/, (_a.sent())]; } }); }); }; next = function () { return __awaiter(_this, void 0, void 0, function () { var areMoreBehaviorsNeedingProcessing; return __generator(this, function (_a) { switch (_a.label) { case 0: areMoreBehaviorsNeedingProcessing = currentBehaviorIndex < behaviors.length; if (!areMoreBehaviorsNeedingProcessing) return [3 /*break*/, 2]; return [4 /*yield*/, execBehavior(request, next)]; case 1: return [2 /*return*/, _a.sent()]; // Process the behavior case 2: return [4 /*yield*/, func()]; case 3: return [2 /*return*/, _a.sent()]; // Process the handler } }); }); }; return [4 /*yield*/, next()]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; /** * Get the handler for the given request * * @param {RequestData<TResult>} request The request * @returns {RequestHandler<RequestData<TResult>, TResult>} The handler * @private * @memberof Mediator */ Mediator.prototype.getRequiredHandlerForRequest = function (request) { var handlerClasses = index_js_1.typeMappings.requestHandlers.getAll(request.constructor); var handler = this._resolver.resolve(handlerClasses[0].handlerClass); return handler; }; /** * Publish a new message * * @param {Notification} message The message to publish * @returns {Promise<void>} * @memberof Mediator */ Mediator.prototype.publish = function (message) { return __awaiter(this, void 0, void 0, function () { var events, results; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: events = index_js_1.typeMappings.notifications.getAll(message.constructor); return [4 /*yield*/, Promise.allSettled(events.map(function (p) { return __awaiter(_this, void 0, void 0, function () { var handler; return __generator(this, function (_a) { handler = this._resolver.resolve(p.handlerClass); return [2 /*return*/, handler.handle(message)]; }); }); }))]; case 1: results = _a.sent(); if (results.some(function (r) { return r.status === "rejected"; })) throw new publish_error_js_1.default("Error publishing notification", results); return [2 /*return*/]; } }); }); }; /** * @description - Manually register a handler without {@requestHandler()} * @type * @param {RequestDataClass<T>} request - request class * @param {RequestHandlerClass<RequestData<unknown>, unknown>} handler - request handler class * @memberof Mediator */ Mediator.prototype.registerHandler = function (request, handler) { index_js_1.typeMappings.requestHandlers.throwIfExistingTypeMappings(request); // check if handler in resolver try { this._resolver.resolve(handler); } catch (error) { // adds handler to resolver, since it wont added in constructing phase this._resolver.add(handler); } index_js_1.typeMappings.requestHandlers.add({ requestClass: request, handlerClass: handler, }); }; return Mediator; }()); exports.default = Mediator; //# sourceMappingURL=mediator.js.map