This is a simple library for using the mediator pattern in your typescript and deno projects. While not entirely a true port, the MediatR library for .NET is a direct influence.
- Former US President Jimmy Carter was known for his ability at being a great mediator.
- The .NET Core library MediatR was written by Jimmy Bogard.
- Coicdence? I think not.
# npm
npm install --save @myty/jimmy
npx jsr add @myty/jimmy
import { Mediator, Request, Notification } from "jsr:@myty/jimmy";
const mediator = new Mediator();
class TestRequest extends Request<Promise<string>> {
constructor(public name: string) {
super();
}
}
mediator.handle(
TestRequest,
(request) => Promise.resolve(`Hello, ${request.name}!`),
);
const response = await mediator.send(new TestRequest("Jimmy"));
console.log(response); // "Hello, Jimmy!"
Jimmy is inspired by the MediatR project, so here's what's been implemented:
- Request/Response messages
- Notification messages
- Publish Strategies (Notifications)
Just like MediatR, Jimmy has two kinds of messages it dispatches:
- Request/response messages, dispatched to a single handler
- Notification messages, dispatched to multiple handlers
The request/response interface handles both command and query scenarios. First, create a message:
class Ping extends Request<Promise<string>> {}
Next, register a handler:
mediator.handle(Ping, (request) => Promise.resolve("Pong"));
Finally, send a message through the mediator:
const response = await mediator.send(new Ping());
console.log(response); // "Pong"
In the case your message does not require a response, use
Request<Promise<void>>
as your base class :
class OneWay extends Request<Promise<void>> {}
mediator.handle(OneWay, () => {
// Twiddle thumbs
Promise.resolve();
});
Or if the request is completely synchronous, inherit from the base Request
class without any generic parameters. void
is the default return type.
class Ping extends Request {}
mediator.handle(Ping, () => "Pong");
For notifications, first create your notification message:
class Ping extends Notification {}
Next, register zero or more handlers for your notification:
mediator.handle(Ping, (notification) => {
console.log("Pong 1");
return Promsie.resolve();
}
mediator.handle(Ping, (notification) => {
console.log("Pong 2");
return Promsie.resolve();
}
Finally, publish your message via the mediator:
await mediator.publish(new Ping());
The default implementation of Publish loops through the notification handlers and awaits each one. This ensures each handler is run after one another.
Depending on your use-case for publishing notifications, you might need a different strategy for handling the notifications. Maybe you want to publish all notifications in parallel, or wrap each notification handler with your own exception handling logic.