Skip to content

NestJS ​

Each bounded context is a NestJS module. Ports and repositories are the injection tokens.

Register the handlers ​

A handler has no @Injectable(): register it with a factory, listing its constructor tokens in order.

src/ordering/ordering.module.ts
ts
providers: [
	{ provide: Orders, useClass: PgOrders },
	{ provide: Clock, useClass: SystemClock },
	{ provide: IdGenerator, useClass: RandomIdGenerator },
	{
		inject: [Orders, Clock, IdGenerator],
		provide: PlaceOrderHandler,
		useFactory: (orders: Orders, clock: Clock, ids: IdGenerator) => new PlaceOrderHandler(orders, clock, ids),
	},
],

Adapters are outside the application: they may carry @Injectable(), as PgOrders does here.

Or use @Injectable() in the application ​

To list handlers as plain providers, allow Injectable, and only it, in the application:

alveolus.config.ts
ts
applicationDependencies: { "@nestjs/common": ["Injectable"] },
src/ordering/application/commands/place-order.command.ts
ts
@Injectable()
export class PlaceOrderHandler extends CommandHandler<PlaceOrder, void, PlaceOrderError> { … }
src/ordering/ordering.module.ts
ts
providers: [{ provide: Orders, useClass: PgOrders }, PlaceOrderHandler],

WARNING

  • The application then depends on NestJS, and needs emitDecoratorMetadata: Vitest and other esbuild-based tools need a SWC transform.
  • Import the injected classes as values, not with import type.

Connect two bounded contexts ​

A module exports its open host services, and nothing else. The downstream module imports it to build its anti-corruption layer.

src/catalog/catalog.module.ts
ts
@Module({ exports: [CatalogApi], providers: [CatalogApi, …] })
export class CatalogModule {}
src/ordering/ordering.module.ts
ts
@Module({ imports: [CatalogModule], providers: [{ provide: PriceList, useClass: CatalogPriceList }, …] })
export class OrderingModule {}

Troubleshooting ​

Nest can't resolve dependencies of PlaceOrderHandler (?, …): the handler is listed as a plain class without @Injectable(), or an injected class is imported with import type, or a token of inject has no provider.

Released under the MIT License.