### Execute Command Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Shows a concise example of how to execute a command using the commandBus instance. This is typically done in controllers or services. ```typescript const result = await commandBus.execute(new CreateUserCommand('user@example.com', 'John')); ``` -------------------------------- ### NestJS CQRS Basic Command Handling Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md This example shows the complete setup for command handling in NestJS CQRS. It includes module setup, command definition, command handler implementation, and command execution via a controller. ```typescript // 1. Setup module @Module({ imports: [CqrsModule.forRoot()], }) export class AppModule {} // 2. Define command export class CreateUserCommand extends Command { constructor(public readonly email: string) { super(); } } // 3. Create handler @CommandHandler(CreateUserCommand) export class CreateUserHandler implements ICommandHandler { async execute(command: CreateUserCommand): Promise { return 'user-123'; } } // 4. Execute command @Controller('users') export class UsersController { constructor(private commandBus: CommandBus) {} @Post() async create(@Body('email') email: string) { const result = await this.commandBus.execute( new CreateUserCommand(email) ); return { userId: result }; } } ``` -------------------------------- ### forRoot() Configuration Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/cqrs-module.md Example of configuring the CqrsModule using the `forRoot` static method with custom command and event publishers, and enabling rethrow of unhandled exceptions. ```typescript import { Module } from '@nestjs/common'; import { CqrsModule } from '@nestjs/cqrs'; @Module({ imports: [ CqrsModule.forRoot({ commandPublisher: customCommandPublisher, eventPublisher: customEventPublisher, rethrowUnhandled: true, }), ], }) export class AppModule {} ``` -------------------------------- ### Executing a Query Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/query-bus.md Shows a concise example of how to instantiate a query and execute it using the queryBus instance. ```typescript const user = await queryBus.execute(new GetUserQuery('user-123')); ``` -------------------------------- ### Command Handling Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md Demonstrates how to define and execute a typed command using the CommandBus. ```APIDOC ## Command Handling ### Description Commands are typed by their expected result. The `CommandBus` executes a command and returns a promise of the result type. ### Usage ```typescript // Define a command that returns a string class MyCommand extends Command {} // Execute the command using the CommandBus const result: string = await commandBus.execute(myCommand); ``` ### Handler Definition ```typescript @CommandHandler(MyCommand) class MyHandler implements ICommandHandler { async execute(command: MyCommand): Promise { // Command execution logic here } } ``` ``` -------------------------------- ### Create Command Class Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Defines a command class by extending the base Command class. This example shows a CreateUserCommand that carries user email and name. ```typescript export class CreateUserCommand extends Command { constructor( public readonly email: string, public readonly name: string, ) { super(); } } ``` -------------------------------- ### Query Handling Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md Illustrates how to define and execute a typed query using the QueryBus. ```APIDOC ## Query Handling ### Description Queries are typed by their expected result. The `QueryBus` executes a query and returns a promise of the result type. ### Usage ```typescript // Define a query that returns a UserDto object class MyQuery extends Query {} // Execute the query using the QueryBus const user: UserDto = await queryBus.execute(myQuery); ``` ### Handler Definition ```typescript @QueryHandler(MyQuery) class MyHandler implements IQueryHandler { async execute(query: MyQuery): Promise { // Query execution logic here } } ``` ``` -------------------------------- ### Commit message samples Source: https://github.com/nestjs/cqrs/blob/master/CONTRIBUTING.md Examples of correctly formatted commit messages. ```text docs(changelog) update change log to beta.5 ``` ```text fix(@nestjs/core) need to depend on latest rxjs and zone.js The version in our package.json gets copied to the one we publish, and users need the latest of these. ``` -------------------------------- ### Event Handling Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md Shows how to define and handle events using the EventBus. ```APIDOC ## Event Handling ### Description Event handlers subscribe to specific event types and are executed when those events are published. ### Usage ```typescript // Define an event class MyEvent {} // Define an event handler for MyEvent @EventsHandler(MyEvent) class MyEventHandler implements IEventHandler { async handle(event: MyEvent): Promise { // Event handling logic here } } // Publish an event using the EventBus eventBus.publish(new MyEvent()); ``` ``` -------------------------------- ### Patterns Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/COMPLETION_SUMMARY.txt Real-world patterns and examples for implementing CQRS features. ```APIDOC ## Patterns ### Description Illustrates complete, real-world patterns and walkthroughs for implementing various CQRS features using the NestJS CQRS module. These examples cover common use cases and architectural considerations. ``` -------------------------------- ### QueryBus execute Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/query-bus.md Demonstrates how to use the QueryBus to execute a GetUserQuery from a controller. Ensure the QueryBus is injected into the controller. ```typescript import { Controller, Get, Param } from '@nestjs/common'; import { QueryBus } from '@nestjs/cqrs'; import { GetUserQuery } from './queries/get-user.query'; @Controller('users') export class UsersController { constructor(private queryBus: QueryBus) {} @Get(':id') async getUser(@Param('id') userId: string) { const query = new GetUserQuery(userId); return await this.queryBus.execute(query); } } ``` -------------------------------- ### Order Aggregate Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/aggregate-root.md Example of an Order aggregate applying an OrderPlacedEvent and handling it internally. ```typescript export class Order extends AggregateRoot { private status: 'pending' | 'shipped' | 'delivered'; placeOrder(items: OrderItem[]) { const event = new OrderPlacedEvent(this.id, items); this.apply(event); } onOrderPlacedEvent(event: OrderPlacedEvent) { this.status = 'pending'; this.items = event.items; } } ``` -------------------------------- ### Invalid Query Handler Examples Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/errors.md Shows examples of invalid and valid query handlers. An invalid handler might lack an 'execute' method or have one with an incorrect signature. ```typescript // ❌ Invalid - missing execute method @QueryHandler(GetUserQuery) export class BadHandler implements IQueryHandler { // Missing execute method! } ``` ```typescript // ✅ Valid @QueryHandler(GetUserQuery) export class ValidHandler implements IQueryHandler { async execute(query: GetUserQuery): Promise { return this.usersService.findById(query.userId); } } ``` -------------------------------- ### Users Controller with Command and Query Buses Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Implement a controller to handle incoming HTTP requests, dispatching commands to the CommandBus and queries to the QueryBus. This example includes endpoints for creating, retrieving, listing, and activating users. ```typescript // users/users.controller.ts import { Controller, Post, Get, Body, Param } from '@nestjs/common'; import { CommandBus, QueryBus } from '@nestjs/cqrs'; @Controller('users') export class UsersController { constructor( private commandBus: CommandBus, private queryBus: QueryBus, ) {} @Post() async create(@Body() dto: CreateUserDto) { const command = new CreateUserCommand(dto.email, dto.name); const userId = await this.commandBus.execute(command); return { userId }; } @Get(':id') async getUser(@Param('id') userId: string) { const query = new GetUserQuery(userId); return this.queryBus.execute(query); } @Get() async listUsers(@Query('limit') limit = 10, @Query('offset') offset = 0) { const query = new ListUsersQuery(limit, offset); return this.queryBus.execute(query); } @Post(':id/activate') async activateUser(@Param('id') userId: string) { const command = new ActivateUserCommand(userId); await this.commandBus.execute(command); return { success: true }; } } ``` -------------------------------- ### CommandBus Execute Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Demonstrates how to execute a CreateUserCommand using the CommandBus within a NestJS controller. Ensure the CommandBus is injected into the controller. ```typescript import { Controller, Post, Body, } from '@nestjs/common'; import { CommandBus } from '@nestjs/cqrs'; import { CreateUserCommand } from './commands/create-user.command'; @Controller('users') export class UsersController { constructor(private commandBus: CommandBus) {} @Post() async create(@Body() dto: CreateUserDto) { const command = new CreateUserCommand(dto.email, dto.name); const userId = await this.commandBus.execute(command); return { userId }; } } ``` -------------------------------- ### Basic Command Handler Implementation Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/decorators.md Example of a class decorated with @CommandHandler to process CreateUserCommand. It implements the ICommandHandler interface and defines an execute method. ```typescript import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { CreateUserCommand } from './create-user.command'; export class CreateUserCommand { constructor( public readonly email: string, public readonly name: string, ) {} } @CommandHandler(CreateUserCommand) export class CreateUserHandler implements ICommandHandler { constructor(private usersService: UsersService) {} async execute(command: CreateUserCommand): Promise { return this.usersService.create(command.email, command.name); } } ``` -------------------------------- ### Usage Pattern with Aggregate Roots Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/event-publisher.md This example demonstrates the usage pattern with Aggregate Roots, including static creation methods and event publishing. Ensure necessary events and repositories are imported. ```typescript import { AggregateRoot, Publishable } from '@nestjs/cqrs'; import { UserCreatedEvent, UserActivatedEvent } from './events'; @Publishable() export class User extends AggregateRoot { constructor( public readonly id: string, public email: string, public name: string, ) { super(); } static create(email: string, name: string): User { const user = new User(uuidv4(), email, name); user.publish(new UserCreatedEvent(user.id, email, name)); return user; } activate(): void { this.publish(new UserActivatedEvent(this.id)); } } @Injectable() export class UsersService { constructor(private repository: UsersRepository) {} async create(email: string, name: string): Promise { const user = User.create(email, name); await this.repository.save(user); return user; } } ``` -------------------------------- ### forRootAsync() with useFactory Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/cqrs-module.md Demonstrates configuring the CqrsModule asynchronously using `forRootAsync` with a `useFactory` function. This approach allows for dependency injection of services like `ConfigService` to determine configuration options. ```typescript import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { CqrsModule } from '@nestjs/cqrs'; @Module({ imports: [ ConfigModule, CqrsModule.forRootAsync({ imports: [ConfigModule], useFactory: async (configService: ConfigService) => ({ eventPublisher: new CustomEventPublisher(configService.get('EVENT_PROVIDER_URL')), rethrowUnhandled: configService.get('RETHROW_ERRORS') === 'true', }), inject: [ConfigService], }), ], }) export class AppModule {} ``` -------------------------------- ### forRootAsync() with useClass Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/cqrs-module.md Shows how to configure the CqrsModule asynchronously using `forRootAsync` with a `useClass` option. A dedicated factory class (`CqrsOptionsFactory`) is used to create the configuration, promoting modularity and testability. ```typescript import { Injectable, Module } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { CqrsModule, CqrsModuleOptions, CqrsModuleOptionsFactory } from '@nestjs/cqrs'; @Injectable() export class CqrsOptionsFactory implements CqrsModuleOptionsFactory { constructor(private configService: ConfigService) {} async createCqrsOptions(): Promise { return { eventPublisher: await this.configService.getEventPublisher(), rethrowUnhandled: this.configService.get('RETHROW_ERRORS'), }; } } @Module({ imports: [ CqrsModule.forRootAsync({ useClass: CqrsOptionsFactory, }), ], }) export class AppModule {} ``` -------------------------------- ### CommandBus Publisher Property Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Allows getting or setting the command publisher. Defaults to DefaultCommandPubSub for in-memory publishing. ```typescript get publisher(): ICommandPublisher set publisher(_publisher: ICommandPublisher) ``` -------------------------------- ### Command Handler Implementation Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Implements the ICommandHandler interface to handle a specific command. The execute method contains the business logic for the command. ```typescript @CommandHandler(CreateUserCommand) export class CreateUserHandler implements ICommandHandler { constructor(private usersService: UsersService) {} async execute(command: CreateUserCommand): Promise { return this.usersService.create(command.email, command.name); } } ``` -------------------------------- ### Request-Scoped Provider Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/async-context.md Demonstrates injecting and using a request-scoped provider within a command handler. The RequestContext is unique to each command's execution context. ```typescript import { Injectable, Scope } from "@nestjs/common"; import { CommandHandler, ICommandHandler } from "@nestjs/cqrs"; import { v4 as uuidv4 } from "uuid"; @Injectable({ scope: Scope.REQUEST }) export class RequestContext { private requestId = uuidv4(); getId(): string { return this.requestId; } } @CommandHandler(MyCommand) export class MyHandler implements ICommandHandler { constructor(private requestContext: RequestContext) {} async execute(command: MyCommand) { // This RequestContext instance is unique to this command's context const id = this.requestContext.getId(); } } ``` -------------------------------- ### User Event Handlers Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Implement IEventHandler to react to specific domain events. This example shows handlers for UserCreatedEvent and UserActivatedEvent, triggering email and notification services respectively. ```typescript // users/handlers/user-created.handler.ts import { EventsHandler, IEventHandler } from '@nestjs/cqrs'; @EventsHandler(UserCreatedEvent) export class UserCreatedHandler implements IEventHandler { constructor(private emailService: EmailService) {} async handle(event: UserCreatedEvent) { await this.emailService.sendWelcomeEmail( event.email, event.name, ); } } @EventsHandler(UserActivatedEvent) export class UserActivatedHandler implements IEventHandler { constructor(private notificationService: NotificationService) {} async handle(event: UserActivatedEvent) { await this.notificationService.sendActivationNotification( event.userId, ); } } ``` -------------------------------- ### Invalid Command Handler Examples Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/errors.md Illustrates invalid and valid implementations of command handlers. Invalid handlers may be missing the 'execute' method or have a method with an incorrect signature. ```typescript // ❌ Invalid - missing execute method @CommandHandler(CreateUserCommand) export class BadHandler implements ICommandHandler { // Missing execute method! } ``` ```typescript // ❌ Invalid - wrong method name @CommandHandler(CreateUserCommand) export class AlsoInvalid implements ICommandHandler { async run(command: CreateUserCommand) { // Wrong method name } } ``` ```typescript // ✅ Valid @CommandHandler(CreateUserCommand) export class ValidHandler implements ICommandHandler { async execute(command: CreateUserCommand) { // Correct implementation } } ``` -------------------------------- ### Unhandled Exception Handling with Observables Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Set up a subscription to the UnhandledExceptionBus to monitor and react to exceptions that are not caught by other handlers. This example demonstrates logging and alerting for critical errors. ```typescript // unhandled-exception.handler.ts @Injectable() export class UnhandledExceptionHandler { constructor(private unhandledExceptionBus: UnhandledExceptionBus) { this.setupExceptionHandling(); } private setupExceptionHandling() { this.unhandledExceptionBus .asObservable() .pipe( tap((info) => { this.logException(info); }), filter((info) => this.isCritical(info.exception)), tap((info) => { this.alertOnCritical(info); }), ) .subscribe(); } private logException(info: UnhandledExceptionInfo) { console.error( `Unhandled exception: ${info.exception?.message}`, info.cause, ); } private isCritical(error: any): boolean { return ( error instanceof DatabaseError || error instanceof TimeoutError ); } private alertOnCritical(info: UnhandledExceptionInfo) { // Send alert to monitoring system console.error('CRITICAL ERROR:', info.exception); } } ``` -------------------------------- ### Publishing an Unhandled Exception Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/unhandled-exception-bus.md Example of how to publish an unhandled exception using the UnhandledExceptionBus. Ensure the 'cause' and 'exception' properties are correctly populated. ```typescript const info: UnhandledExceptionInfo = { cause: command, exception: new Error('Handler failed'), }; this.unhandledExceptionBus.publish(info); ``` -------------------------------- ### Custom Event ID Provider Implementation Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/configuration.md Implement a custom event ID provider by extending the EventIdProvider interface. This example uses the event class name as the ID. Ensure the provider is correctly instantiated and passed to CqrsModule.forRoot(). ```typescript import { Injectable } from '@nestjs/common'; import { IEvent, Type } from '@nestjs/cqrs'; import { EventIdProvider } from '@nestjs/cqrs'; @Injectable() export class CustomEventIdProvider implements EventIdProvider { getEventId(event: Type | IEvent): string | null { // Use event class name as ID const eventClass = typeof event === 'function' ? event : (event.constructor as Type); return eventClass.name; } } CqrsModule.forRoot({ eventIdProvider: new CustomEventIdProvider(), }) ``` -------------------------------- ### Module Bootstrap - OnApplicationBootstrap Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/cqrs-module.md This method is called when the application bootstraps. It explores and registers all command, query, event handlers, and sagas with their respective buses. It also merges the event publisher context into aggregate roots. ```typescript onApplicationBootstrap() { const { events, queries, sagas, commands } = this.explorerService.explore(); this.eventBus.register(events); this.commandBus.register(commands); this.queryBus.register(queries); this.eventBus.registerSagas(sagas); AggregateRootStorage.mergeContext(this.eventBus); } ``` -------------------------------- ### Event Sourcing with Snapshots Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/COMPLETION_SUMMARY.txt Explains how to implement event sourcing with snapshotting for efficient state management and recovery. ```APIDOC ## Event Sourcing with Snapshots This pattern describes the implementation of event sourcing combined with snapshotting for performance and state recovery. ### Snapshot Loading - Loading aggregate state from snapshots. ### Event History Replay - Replaying events to reconstruct state. ### Snapshot Generation - Strategies and mechanisms for generating snapshots. ``` -------------------------------- ### Get Uncommitted Events Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/aggregate-root.md Retrieves all events that have been applied but not yet committed. Useful for inspection or custom event handling logic. ```typescript getUncommittedEvents(): EventBase[] ``` -------------------------------- ### Create a Custom Event (UserCreatedEvent) Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md User-defined events should extend or implement the IEvent interface. This example shows a UserCreatedEvent with specific properties. ```typescript export class UserCreatedEvent implements IEvent { constructor( public readonly userId: string, public readonly email: string, ) {} } ``` -------------------------------- ### Test Command Handler with Mock Repository Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md Demonstrates how to test a command handler by mocking the repository and asserting the command execution result. ```typescript // Test command handler describe('CreateUserHandler', () => { it('should create a user', async () => { const handler = new CreateUserHandler(mockRepository); const command = new CreateUserCommand('user@example.com'); const result = await handler.execute(command); expect(result).toBe('user-123'); }); }); ``` -------------------------------- ### Implement a Custom Query (TypeScript) Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md User-defined queries should extend or implement the IQuery interface. This example shows a GetUserQuery with a userId parameter. ```typescript export class GetUserQuery implements IQuery { constructor(public readonly userId: string) {} } ``` -------------------------------- ### Commit Events Example Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/aggregate-root.md Commits all uncommitted events, publishing them and clearing the queue. This is typically called after an operation that results in state changes. ```typescript export class Order extends AggregateRoot { async place(items: OrderItem[]): Promise { this.apply(new OrderPlacedEvent(this.id, items)); // ... additional logic ... this.commit(); // Publish all uncommitted events } } ``` -------------------------------- ### Using AggregateRoot with Commands Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/aggregate-root.md Handles a PlaceOrderCommand by creating a new Order aggregate, applying the placeOrder method, saving the aggregate, and committing its events. Requires an OrderRepository to persist the aggregate. ```typescript @CommandHandler(PlaceOrderCommand) export class PlaceOrderHandler implements ICommandHandler { constructor(private orderRepository: OrderRepository) {} async execute(command: PlaceOrderCommand): Promise { const order = new Order(uuidv4()); order.placeOrder(command.items); // Save and publish events await this.orderRepository.save(order); order.commit(); return order.id; } } ``` -------------------------------- ### Create Command Handlers for User Commands Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Implement command handlers to process CreateUserCommand and ActivateUserCommand. These handlers interact with repositories and the event bus. ```typescript // users/handlers/create-user.handler.ts import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'; import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; @CommandHandler(CreateUserCommand) export class CreateUserHandler implements ICommandHandler { constructor( private userRepository: UserRepository, private eventBus: EventBus, ) {} async execute(command: CreateUserCommand): Promise { const userId = uuidv4(); const user = User.create(userId, command.email, command.name); await this.userRepository.save(user); user.commit(); return userId; } } @CommandHandler(ActivateUserCommand) export class ActivateUserHandler implements ICommandHandler { constructor(private userRepository: UserRepository) {} async execute(command: ActivateUserCommand): Promise { const user = await this.userRepository.findById(command.userId); if (!user) { throw new NotFoundException('User not found'); } user.activate(); await this.userRepository.save(user); user.commit(); } } ``` -------------------------------- ### Retrieve Async Context from Object Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/async-context.md Use `of` to get the `AsyncContext` instance attached to a specific object. Returns `undefined` if no context is found. ```typescript const context = AsyncContext.of(command); if (context) { console.log('Context ID:', context.id); } ``` -------------------------------- ### Environment-Based NestJS CQRS Configuration Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/configuration.md Dynamically configure CqrsModule based on environment variables. This example sets 'rethrowUnhandled' and the 'eventPublisher' based on NODE_ENV. ```typescript CqrsModule.forRootAsync({ imports: [ConfigModule], useFactory: (configService: ConfigService) => { const env = configService.get('NODE_ENV'); return { rethrowUnhandled: env === 'development', eventPublisher: env === 'production' ? new PersistentEventPublisher() : new DefaultPubSub(), }; }, inject: [ConfigService], }) ``` -------------------------------- ### IQueryPublisher Interface Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md Interface for publishing queries, allowing for observation of when queries are executed. ```APIDOC ## IQueryPublisher Interface ### Description Interface for publishing queries (observing when they're executed). ### Type Definition ```typescript interface IQueryPublisher { publish(query: T): any; } ``` ``` -------------------------------- ### EventBus Constructor Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/event-bus.md The constructor initializes the EventBus with dependencies like CommandBus, ModuleRef, UnhandledExceptionBus, and optional CQRS module options. ```APIDOC ## Constructor ```typescript constructor( private readonly commandBus: CommandBus, private readonly moduleRef: ModuleRef, private readonly unhandledExceptionBus: UnhandledExceptionBus, @Optional() @Inject(CQRS_MODULE_OPTIONS) private readonly options?: CqrsModuleOptions, ) ``` ### Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | commandBus | CommandBus | yes | Reference to the command bus for saga dispatch | | moduleRef | ModuleRef | yes | NestJS module reference for resolving dependencies | | unhandledExceptionBus | UnhandledExceptionBus | yes | Bus for publishing unhandled exceptions | | options | CqrsModuleOptions | no | Configuration options | ``` -------------------------------- ### Create Query Handlers for User Queries Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Implement query handlers to process GetUserQuery and ListUsersQuery. These handlers retrieve data using repositories and mappers. ```typescript // users/handlers/get-user.handler.ts import { QueryHandler, IQueryHandler } from '@nestjs/cqrs'; @QueryHandler(GetUserQuery) export class GetUserHandler implements IQueryHandler { constructor( private userRepository: UserRepository, private mapper: UserMapper, ) {} async execute(query: GetUserQuery): Promise { const user = await this.userRepository.findById(query.userId); if (!user) { throw new NotFoundException('User not found'); } return this.mapper.toDto(user); } } @QueryHandler(ListUsersQuery) export class ListUsersHandler implements IQueryHandler { constructor( private userRepository: UserRepository, private mapper: UserMapper, ) {} async execute(query: ListUsersQuery): Promise { const users = await this.userRepository.findMany( query.limit, query.offset, ); return users.map((user) => this.mapper.toDto(user)); } } ``` -------------------------------- ### Async CqrsModule Configuration with Factory Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/configuration.md Configure CqrsModule asynchronously using `forRootAsync` and a configuration factory. This approach allows for dependency injection and dynamic configuration based on environment variables or other services. It demonstrates setting various publishers and rethrowing unhandled exceptions in development. ```typescript import { Module, Injectable } from '@nestjs/common'; import { CqrsModule, CqrsModuleOptions } from '@nestjs/cqrs'; import { ConfigModule, ConfigService } from '@nestjs/config'; // Assume these are imported and available // import { EventStorePublisher } from './event-store.publisher'; // import { KafkaCommandPublisher } from './kafka.publisher'; // import { MetricsQueryPublisher } from './metrics.publisher'; // import { SentryExceptionPublisher } from './sentry.publisher'; @Injectable() export class CqrsConfigFactory { // Assume these are injected or available // constructor(private eventStore, private kafka, private metrics, private sentry, private configService: ConfigService) {} constructor(private configService: ConfigService) {} createCqrsOptions(): CqrsModuleOptions { const isDevelopment = this.configService.get('NODE_ENV') === 'development'; return { rethrowUnhandled: isDevelopment, // eventPublisher: new EventStorePublisher(this.eventStore), // commandPublisher: new KafkaCommandPublisher(this.kafka), // queryPublisher: new MetricsQueryPublisher(this.metrics), // unhandledExceptionPublisher: new SentryExceptionPublisher( // this.sentry, // ), }; } } @Module({ imports: [ ConfigModule.forRoot(), CqrsModule.forRootAsync({ imports: [ConfigModule], useClass: CqrsConfigFactory, inject: [ConfigService], }), ], }) export class AppModule {} ``` -------------------------------- ### EventBus Constructor Parameters Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/event-bus.md Details the dependencies injected into the EventBus constructor, including CommandBus, ModuleRef, UnhandledExceptionBus, and optional configuration options. ```typescript constructor( private readonly commandBus: CommandBus, private readonly moduleRef: ModuleRef, private readonly unhandledExceptionBus: UnhandledExceptionBus, @Optional() @Inject(CQRS_MODULE_OPTIONS) private readonly options?: CqrsModuleOptions, ) ``` -------------------------------- ### Define a Command Publisher Interface Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md Implement ICommandPublisher to observe command execution. This is useful for logging or triggering side effects when commands are published. ```typescript interface ICommandPublisher { publish(command: T): any; } ``` -------------------------------- ### Usage of ofType in Sagas Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/operators.md This example demonstrates the common use case of filtering events in sagas using the `ofType` operator. It pipes the event stream, filters for `UserCreatedEvent`, and maps to a `SendWelcomeEmailCommand`. ```typescript import { Saga, ICommand } from '@nestjs/cqrs'; import { ofType } from '@nestjs/cqrs'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable() export class UserSagas { constructor(private commandBus: CommandBus) {} @Saga() userCreated$ = (events$: Observable) => { return events$.pipe( ofType(UserCreatedEvent), map((event) => new SendWelcomeEmailCommand(event.email)), ); }; } ``` -------------------------------- ### ICommand Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md The base interface for all commands. Commands represent actions that modify the application's state. ```APIDOC ## ICommand ### Description Base interface for commands. Commands are actions that modify application state. ### Interface Definition ```typescript interface ICommand {} ``` ### Usage Example Commands are user-defined classes that extend or implement this interface. ```typescript export class CreateUserCommand implements ICommand { constructor( public readonly email: string, public readonly name: string, ) {} } ``` ``` -------------------------------- ### ICommandPublisher Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md Interface for publishing commands, allowing observation of command execution. ```APIDOC ## ICommandPublisher ### Description Interface for publishing commands (observing when they're executed). ### Interface Definition ```typescript interface ICommandPublisher { publish(command: T): any; } ``` ``` -------------------------------- ### Custom Kafka Command Publisher Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/configuration.md Implement a custom command publisher using Kafka to send commands to a specific topic. Register this publisher in the module's configuration. ```typescript import { ICommandPublisher, ICommand } from '@nestjs/cqrs'; @Injectable() export class KafkaCommandPublisher implements ICommandPublisher { constructor(private kafka: KafkaService) {} publish(command: ICommand) { const topic = `commands.${command.constructor.name}`; return this.kafka.send(topic, JSON.stringify(command)); } } // Register in module CqrsModule.forRoot({ commandPublisher: new KafkaCommandPublisher(kafkaService), }) ``` -------------------------------- ### Trigger Alerts for Severe Exceptions Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/unhandled-exception-bus.md Implement an alerting mechanism for severe exceptions by filtering the observable stream for specific error types or conditions. This example demonstrates sending alerts for database, timeout, or authorization errors. ```typescript @Injectable() export class ExceptionAlerter { constructor( private unhandledExceptionBus: UnhandledExceptionBus, private alertService: AlertService, ) { this.subscribeToSevereExceptions(); } private subscribeToSevereExceptions() { this.unhandledExceptionBus .asObservable() .pipe( filter((info) => this.isSevere(info.exception)), tap((info) => { this.alertService.sendAlert({ severity: 'high', message: `Unhandled exception: ${info.exception.message}`, cause: info.cause, }); }), ) .subscribe(); } private isSevere(error: any): boolean { return ( error instanceof DatabaseError || error instanceof TimeoutError || error instanceof AuthorizationError ); } } ``` -------------------------------- ### Combine ofType with Other RxJS Operators Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/operators.md Integrate the `ofType` operator with other RxJS operators like `filter` and `debounceTime` for complex event processing. This example shows filtering for `PaymentProcessedEvent` with an amount greater than 1000 and debouncing to avoid rapid processing. ```typescript @Saga() complexFlow$ = (events$: Observable) => { return events$.pipe( ofType(PaymentProcessedEvent), filter((event) => event.amount > 1000), debounceTime(500), mergeMap((event) => this.commandBus.execute( new CreateInvoiceCommand(event.transactionId), ), ), ); }; ``` -------------------------------- ### Create a Query Handler Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/INDEX.md Implement the `IQueryHandler` interface and use the `@QueryHandler` decorator to register a handler for a specific query. This defines the logic executed when a query is dispatched. ```typescript @QueryHandler(GetUserQuery) export class GetUserHandler implements IQueryHandler { async execute(query: GetUserQuery): Promise { // Fetch and return user } } ``` -------------------------------- ### Register CQRS Module Synchronously Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/configuration.md Use CqrsModule.forRoot() for synchronous configuration. Pass configuration options directly within the object. ```typescript import { Module } from '@nestjs/common'; import { CqrsModule } from '@nestjs/cqrs'; @Module({ imports: [ CqrsModule.forRoot({ // Configuration options here }), ], }) export class AppModule {} ``` -------------------------------- ### Typed Commands, Queries, and Handlers in NestJS CQRS Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md Demonstrates how to define typed commands and queries, and how handlers infer types from their targets. Ensure your command and query classes extend the base Command and Query classes respectively. ```typescript class MyCommand extends Command {} const result: string = await commandBus.execute(myCommand); class MyQuery extends Query {} const user: UserDto = await queryBus.execute(myQuery); @CommandHandler(MyCommand) class MyHandler implements ICommandHandler { async execute(command: MyCommand): Promise { } } ``` -------------------------------- ### Create a new git branch Source: https://github.com/nestjs/cqrs/blob/master/CONTRIBUTING.md Use this command to create and switch to a new branch for your changes. ```shell git checkout -b my-fix-branch master ``` -------------------------------- ### Users Module Configuration Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Configure the UsersModule by importing necessary modules and registering controllers, repositories, handlers, sagas, and services. This ensures all CQRS components are available within the module's scope. ```typescript // users/users.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [TypeOrmModule.forFeature([UserEntity])], controllers: [UsersController], providers: [ // Repository UserRepository, UserMapper, // Command handlers CreateUserHandler, ActivateUserHandler, // Query handlers GetUserHandler, ListUsersHandler, // Event handlers UserCreatedHandler, UserActivatedHandler, // Sagas UserSagas, // Services EmailService, NotificationService, ], }) export class UsersModule {} ``` -------------------------------- ### CQRS Project Structure Recommendation Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md A recommended directory structure for organizing CQRS features within a NestJS application. ```typescript src/ ├── app.module.ts └── features/ ├── users/ │ ├── users.module.ts │ ├── users.controller.ts │ ├── commands/ │ │ ├── create-user.command.ts │ │ └── create-user.handler.ts │ ├── queries/ │ │ ├── get-user.query.ts │ │ └── get-user.handler.ts │ ├── events/ │ │ ├── user-created.event.ts │ │ └── user-created.handler.ts │ ├── sagas/ │ │ └── user.sagas.ts │ └── domain/ │ └── user.aggregate.ts └── orders/ └── ... ``` -------------------------------- ### Event Sourcing with Aggregates Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/INDEX.md Extend `AggregateRoot` to implement event sourcing. Use `apply()` to record events and `on()` methods to handle them. ```typescript @Publishable() export class Order extends AggregateRoot { constructor(public readonly id: string) { super(); } placeOrder(items: OrderItem[]): void { this.apply(new OrderPlacedEvent(this.id, items)); } onOrderPlacedEvent(event: OrderPlacedEvent) { this.items = event.items; this.status = 'pending'; } } ``` -------------------------------- ### Define Commands for User Operations Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Define commands for creating and activating users. Commands represent intent to change the application state. ```typescript // users/commands/create-user.command.ts export class CreateUserCommand extends Command { constructor( public readonly email: string, public readonly name: string, ) { super(); } } export class ActivateUserCommand extends Command { constructor(public readonly userId: string) { super(); } } ``` -------------------------------- ### Define a Base Command Interface Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md Use ICommand as the base interface for all commands. Commands represent actions that modify application state. ```typescript interface ICommand {} ``` -------------------------------- ### publishAll Method Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/aggregate-root.md Publishes multiple events at once. ```APIDOC ## publishAll ### Description Publishes multiple events. ### Signature ```typescript publishAll(events: T[]): void ``` ### Parameters #### Path Parameters - **events** (T[]) - Required - Array of events to publish ### Example ```typescript const events = [ new OrderConfirmedEvent(this.id), new InventoryReservedEvent(this.id, items), ]; this.publishAll(events); ``` ``` -------------------------------- ### CqrsModule Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/COMPLETION_SUMMARY.txt Root module for CQRS functionality. Provides static methods for initialization. ```APIDOC ## CqrsModule ### Description Root module initialization for the NestJS CQRS module. Use `forRoot()` and `forRootAsync()` for setup. ### Methods - `forRoot(options?: CqrsModuleOptions)`: Initializes the module with synchronous options. - `forRootAsync(options?: CqrsModuleAsyncOptions)`: Initializes the module with asynchronous options. ### Options - `CqrsModuleOptions`: Configuration options for the module. - `CqrsModuleAsyncOptions`: Asynchronous configuration options, including `imports`, `useClass`, `useFactory`, `inject`. ``` -------------------------------- ### IQuery Interface Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md The base interface for all queries. Queries represent read operations to fetch data. ```APIDOC ## IQuery Interface ### Description Base interface for queries. Queries are read operations that fetch data. ### Type Definition ```typescript interface IQuery {} ``` ### Usage Queries are user-defined classes that extend or implement this interface. ### Example ```typescript export class GetUserQuery implements IQuery { constructor(public readonly userId: string) {} } ``` ``` -------------------------------- ### CommandBus.execute Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Executes a command and returns a promise with the result. It can also accept an optional async context. ```APIDOC ## execute(command: Command): Promise ## execute(command: Command, context?: AsyncContext): Promise ## execute(command: T, context?: AsyncContext): Promise ### Description Executes a command and returns a promise with the result. It can also accept an optional async context for scoped resolution. ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **command** (Command | T) - Required - The command to execute. - **context** (AsyncContext) - Optional - Optional async context for scoped resolution. ### Response #### Success Response (200) - **R** (any) - A promise that resolves to the result returned by the command handler. #### Error Response - **CommandHandlerNotFoundException** - When no handler is registered for the command. - Any exception thrown by the command handler. ### Example ```typescript import { CommandBus } from '@nestjs/cqrs'; import { CreateUserCommand } from './commands/create-user.command'; @Controller('users') export class UsersController { constructor(private commandBus: CommandBus) {} @Post() async create(@Body() dto: CreateUserDto) { const command = new CreateUserCommand(dto.email, dto.name); const userId = await this.commandBus.execute(command); return { userId }; } } ``` ``` -------------------------------- ### Define Query Publisher Interface (TypeScript) Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md The IQueryPublisher interface is used for observing when queries are published or executed. It provides a publish method. ```typescript interface IQueryPublisher { publish(query: T): any; } ``` -------------------------------- ### publishAll Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/event-bus.md Publishes multiple events to all registered handlers. It supports optional dispatcher and async contexts. ```APIDOC ## publishAll ### Description Publishes multiple events to all registered handlers. ### Method Signature ```typescript publishAll(events: TEvent[]): any; publishAll(events: TEvent[], asyncContext: AsyncContext): any; publishAll(events: TEvent[], dispatcherContext: TContext): any; publishAll(events: TEvent[], dispatcherContext: TContext, asyncContext: AsyncContext): any; ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None #### Method Parameters - **events** (TEvent[]) - Required - Array of events to publish - **dispatcherContext** (TContext) - Optional - Optional context passed to event publisher - **asyncContext** (AsyncContext) - Optional - Optional async context for scoped resolution ### Request Example ```typescript const events = [ new UserCreatedEvent(userId, email, name), new UserActivatedEvent(userId), ]; this.eventBus.publishAll(events); ``` ### Response #### Success Response - **Results** (any[]) - Array of results from the publisher #### Response Example None provided. ``` -------------------------------- ### publish Method Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/aggregate-root.md Publishes a single event immediately. ```APIDOC ## publish ### Description Publishes a single event immediately. ### Signature ```typescript publish(event: T): void ``` ### Parameters #### Path Parameters - **event** (T) - Required - The event to publish ### Example ```typescript const event = new OrderShippedEvent(this.id, trackingNumber); this.publish(event); ``` ``` -------------------------------- ### AsyncContext Usage in Controllers Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/async-context.md Demonstrates how to create and attach an AsyncContext to a command within a NestJS controller, ensuring request-scoped providers are resolved correctly during command execution. ```APIDOC ## Request-Scoped Context in Controllers ```typescript import { Controller, Post, Body } from '@nestjs/common'; import { CommandBus } from '@nestjs/cqrs'; import { AsyncContext } from '@nestjs/cqrs'; @Controller('users') export class UsersController { constructor(private commandBus: CommandBus) {} @Post() async create(@Body() dto: CreateUserDto) { // Create context for this request const context = new AsyncContext(); const command = new CreateUserCommand(dto.email, dto.name); context.attachTo(command); // Execute with context - ensures request-scoped providers are resolved const userId = await this.commandBus.execute(command, context); return { userId }; } } ``` ``` -------------------------------- ### Import CQRS Module in Application Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/cqrs-module.md Import the `CqrsModule` into your application's root module. Use `forRoot()` for basic configuration. This makes CQRS functionalities available throughout your application. ```typescript import { Module } from '@nestjs/common'; import { CqrsModule } from '@nestjs/cqrs'; import { UsersModule } from './users/users.module'; @Module({ imports: [CqrsModule.forRoot(), UsersModule], }) export class AppModule {} ``` -------------------------------- ### CommandBus Constructor Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/command-bus.md Initializes the CommandBus with a ModuleRef for dependency resolution and optional CqrsModuleOptions. ```typescript constructor( private readonly moduleRef: ModuleRef, @Optional() @Inject(CQRS_MODULE_OPTIONS) private readonly options?: CqrsModuleOptions, ) ``` -------------------------------- ### Configure CqrsModule Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/README.md Optional configuration for the CqrsModule, allowing custom publishers and event ID providers. ```typescript CqrsModule.forRoot({ commandPublisher?: ICommandPublisher; eventPublisher?: IEventPublisher; queryPublisher?: IQueryPublisher; unhandledExceptionPublisher?: IUnhandledExceptionPublisher; eventIdProvider?: EventIdProvider; rethrowUnhandled?: boolean; }) ``` -------------------------------- ### Implement a Concrete Command Class Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/types.md Extend ICommand to create specific command classes. These classes typically hold data relevant to the action being performed. ```typescript export class CreateUserCommand implements ICommand { constructor( public readonly email: string, public readonly name: string, ) {} } ``` -------------------------------- ### Create Aggregate Root for User Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/patterns.md Implement the User aggregate root, which encapsulates user state and behavior. It applies events to manage state transitions. ```typescript // users/domain/user.aggregate.ts import { AggregateRoot, Publishable } from '@nestjs/cqrs'; import { UserCreatedEvent, UserActivatedEvent } from '../events'; @Publishable() export class User extends AggregateRoot { constructor( public readonly id: string, email: string, name: string, private status: 'pending' | 'active' = 'pending', ) { super(); } static create(id: string, email: string, name: string): User { const user = new User(id, email, name); user.apply(new UserCreatedEvent(id, email, name)); return user; } activate(): void { if (this.status === 'active') { return; } this.apply(new UserActivatedEvent(this.id)); } onUserCreatedEvent(event: UserCreatedEvent) { this.email = event.email; this.name = event.name; this.status = 'pending'; } onUserActivatedEvent(event: UserActivatedEvent) { this.status = 'active'; } getStatus(): string { return this.status; } } ``` -------------------------------- ### Merging Context Between Operations Source: https://github.com/nestjs/cqrs/blob/master/_autodocs/api-reference/async-context.md Demonstrates how to merge the context from one object (e.g., a command) to another (e.g., an event) using `AsyncContext.merge`. This ensures that the context is propagated when events are published. ```APIDOC ## Merging Context Between Operations ```typescript // Command triggers event with same context @CommandHandler(CreateUserCommand) export class CreateUserHandler implements ICommandHandler { constructor( private userRepository: UserRepository, private eventBus: EventBus, ) {} async execute(command: CreateUserCommand): Promise { const userId = await this.userRepository.create(command.email); const event = new UserCreatedEvent(userId, command.email); // Merge the context from the command to the event AsyncContext.merge(command, event); // Event will be published with the same context this.eventBus.publish(event); return userId; } } ``` ```