Plugin for Elysia for using CQRS pattern.
CQRS Plugin for Elysia is a lightweight extension that implements the Command Query Responsibility Segregation pattern into your Elysia-based application. This plugin allows you to effectively separate read and write operations, providing better scalability, maintainability, and testability of your code.
bun add elysia-cqrs
// commands/create-user/command.ts (example)
import { ICommand } from 'elysia-cqrs'
class CreateUserCommand extends ICommand {
constructor(public name: string) {
super()
}
}
// commands/create-user/handler.ts (example)
import { ICommandHandler } from 'elysia-cqrs'
import { CreateUserCommand } from './command.ts'
class CreateUserHandler implements ICommandHandler<CreateUserCommand, string> {
execute(command: CreateUserCommand) {
return `New user with name ${command.name} was created!`
}
}
// index.ts (example)
import { Elysia } from 'elysia'
import { cqrs } from 'elysia-cqrs'
import { CreateUserCommand, CreateUserHandler } from '@/commands/create-user'
const app = new Elysia()
.use(cqrs({
commands: [
[CreateUserCommand, new CreateUserHandler()]
]
}))
.post('/user', ({ body: { name }, commandMediator }) => {
return commandMediator.send(new CreateUserCommand(name))
}, {
body: t.Object({
name: t.String(),
})
})
.listen(5000)
This plugin decorates commandMediator
, eventMediator
, queryMediator
into Context
.
The commandMediator
implements the CommandMediator
class with these methods and properties:
class CommandMediator extends Mediator {
register<T>(
command: Class<ICommand>,
handler: ICommandHandler<ICommand, T>,
): void
async send<T = never>(command: ICommand): Promise<T>
}
The eventMediator
implements the EventMediator
class with these methods and properties:
class EventMediator extends Mediator {
register(event: Class<IEvent>, handler: IEventHandler<IEvent>): void
send(event: IEvent): void
}
The queryMediator
implements the QueryMediator
class with these methods and properties:
class QueryMediator extends Mediator {
register<T>(
query: Class<IQuery>,
handler: IQueryHandler<IQuery, T>
): void
async send<T = never>(query: IQuery): Promise<T>
}
The library features foundational abstract classes like ICommand
, IEvent
, and IQuery
. These are essential for ensuring standardization and polymorphism.
The module additionally offers a range of handler interfaces, drawing inspiration from the @nestsjs/cqrs package.
interface ICommandHandler<
TCommand extends ICommand = never,
TResponse = never,
> {
execute(command: TCommand): TResponse
}
interface IEventHandler<TEvent extends IEvent = never> {
handle(event: TEvent): void
}
interface IQueryHandler<
TQuery extends IQuery = never,
TResponse = never,
> {
execute(query: TQuery): TResponse
}
Below is the configurable property for customizing the CQRS plugin.
interface CqrsPluginParams {
commands?: Array<[Class<ICommand>, ICommandHandler<ICommand, any>]>
events?: Array<[Class<IEvent>, IEventHandler]>
queries?: Array<[Class<IQuery>, IQueryHandler<IQuery, any>]>
}