Skip to content

CommandBaseHandler

Defined in: packages/ddd-core/application/command-base.handler.ts:87

Base class for all CQRS command handlers.

Wraps every concrete command handler with shared lifecycle behavior:

  1. Executes command logic via the abstract handle method.
  2. If the result is an aggregate root (IAggregateRoot, such as an AggregateRoot) or an object containing one as aggregate, its buffered uncommitted domain events are published through the IDomainEventPublisher, with the aggregate as the dispatcher context, and cleared after publication.

It is framework-neutral. With NestJS CQRS, decorate the subclass with @CommandHandler and pass the injected EventBus, which satisfies IDomainEventPublisher; Nest calls execute as the handler entry point.

Returning aggregate root directly (auto-published)

@CommandHandler(CreateUserCommand)
export class CreateUserHandler extends CommandBaseHandler<CreateUserCommand, User> {
constructor(
@Inject(COMMAND_REPOSITORY.createUser)
private readonly commandRepository: ICommandRepository<User, UserSnapshot>,
protected readonly eventBus: EventBus,
) {
super(eventBus);
}
async handle(command: CreateUserCommand): Promise<User> {
const user = User.create(command.username, command.email);
await this.commandRepository.save(user);
return user; // execute() automatically publishes user.getUncommittedEvents()
}
}

Returning an application result carrying an AggregateRoot (auto-published)

@CommandHandler(CreateAuthCommand)
export class CreateAuthHandler extends CommandBaseHandler<CreateAuthCommand, CreateAuthResult> {
constructor(
@Inject(COMMAND_REPOSITORY.createAuth)
private readonly commandRepository: ICommandRepository<Auth, null>,
protected readonly eventBus: EventBus,
) {
super(eventBus);
}
async handle(command: CreateAuthCommand): Promise<CreateAuthResult> {
const auth = Auth.create(userId, token);
await this.commandRepository.save(auth);
return {
aggregate: auth, // execute() automatically detects aggregate and publishes events
id: userId,
tenant: tenant,
token,
};
}
}

TCommand = unknown

The concrete command type this handler processes.

TResult extends AggregateBearingResult = AggregateBearingResult

The handler’s return type (e.g. aggregate entity or result carrying aggregate).

protected new CommandBaseHandler<TCommand, TResult>(eventBus): CommandBaseHandler<TCommand, TResult>

Defined in: packages/ddd-core/application/command-base.handler.ts:97

Constructs the handler with the publisher of domain events.

IDomainEventPublisher

The publisher used to dispatch domain events, such as the NestJS CQRS EventBus.

CommandBaseHandler<TCommand, TResult>

protected readonly eventBus: IDomainEventPublisher

Defined in: packages/ddd-core/application/command-base.handler.ts:97

The publisher used to dispatch domain events, such as the NestJS CQRS EventBus.

execute(command): Promise<TResult>

Defined in: packages/ddd-core/application/command-base.handler.ts:133

Handler entry point, invoked by the command bus (for example the NestJS CQRS CommandBus).

Delegates to handle and automatically publishes any uncommitted domain events if the result is an aggregate root (or an object containing one as aggregate). The publisher receives the aggregate as its dispatcher context, as NestJS’s EventPublisher passes it on commit().

The events are handed to the publisher and cleared from the aggregate, then execute() awaits what publishAll() returned: an asynchronous publisher delays the result, and its rejection rejects the command, although the aggregate is already persisted. A publisher that throws synchronously leaves the events buffered.

Persistence and in-memory event publication are not atomic. A crash after persistence can lose events; durable delivery requires an explicit outbox.

TCommand

The command dispatched through the command bus.

Promise<TResult>

The result produced by handle.

The error of handle, or of a publisher that throws or rejects.


abstract handle(command): Promise<TResult>

Defined in: packages/ddd-core/application/command-base.handler.ts:109

Executes the business logic for the command.

Concrete handlers must implement this method instead of execute(). If the returned result is an AggregateRoot (or contains an aggregate property), any uncommitted domain events recorded on it will be published automatically.

TCommand

The typed command to process.

Promise<TResult>

The result of the command execution.