Controllers

Thin HTTP controllers that delegate to handlers.

Controllers are the HTTP entry layer. In Koala Nest, they are thin — they receive the request, delegate to the handler, and return the response. They contain no business logic.

All controllers implement IController<Request, Response>:

typescript
export abstract class IController<Request, Response, Params = any> {
  abstract handle(
    request: Request,
    params?: Params,
    response?: HttpResponse,
  ): Promise<Response>;
}

The custom decorator lives in src/host/decorators/controller.decorator.ts and applies route and Swagger tag from a RouterConfigBase:

typescript
export function Controller(config: RouterConfigBase) {
  return function (target: any) {
    NestController(config.group)(target);
    ApiTags(config.tag)(target);
  };
}

Create — POST

typescript
@Controller(PERSON_ROUTER_CONFIG)
export class CreatePersonController implements IController<
  CreatePersonRequest,
  CreatePersonResponse
> {
  constructor(private readonly handler: CreatePersonHandler) {}

  @Post()
  @ApiCreatedResponse({ type: CreatePersonResponse })
  @HttpCode(HttpStatus.CREATED)
  handle(@Body() request: CreatePersonRequest): Promise<CreatePersonResponse> {
    return this.handler.handle(request);
  }
}
typescript
@Controller(PERSON_ROUTER_CONFIG)
export class ReadManyPersonController implements IController<
  ReadManyPersonRequest,
  ReadManyPersonResponse
> {
  constructor(private readonly handler: ReadManyPersonHandler) {}

  @Get()
  @ApiOkResponse({ type: ReadManyPersonResponse })
  async handle(
    @Query() query: ReadManyPersonRequest,
  ): Promise<ReadManyPersonResponse> {
    return await this.handler.handle(query);
  }
}
typescript
@Controller(PERSON_ROUTER_CONFIG)
export class UpdatePersonController implements IController<
  UpdatePersonRequest,
  void
> {
  constructor(private readonly handler: UpdatePersonHandler) {}

  @Put()
  @ApiOkResponse()
  @HttpCode(HttpStatus.OK)
  handle(@Body() request: UpdatePersonRequest): Promise<void> {
    return this.handler.handle(request);
  }
}
typescript
@Controller(PERSON_ROUTER_CONFIG)
export class ReadPersonController implements IController<
  string,
  ReadPersonResponse
> {
  constructor(private readonly handler: ReadPersonHandler) {}

  @Get(':id')
  @ApiOkResponse({ type: ReadPersonResponse })
  async handle(@Param('id') id: string): Promise<ReadPersonResponse> {
    return await this.handler.handle(+id);
  }
}
typescript
@Controller(PERSON_ROUTER_CONFIG)
export class DeletePersonController implements IController<string, void> {
  constructor(private readonly handler: DeletePersonHandler) {}

  @Delete(':id')
  @ApiOkResponse()
  handle(@Param('id') id: string): Promise<void> {
    return this.handler.handle(+id);
  }
}
  1. Apply @Controller(ROUTER_CONFIG) on the class.
  2. Inject the corresponding handler in the constructor.
  3. Use HTTP decorators (@Get, @Post, @Put, @Delete) on the handle method.
  4. Document with @ApiOkResponse, @ApiCreatedResponse, etc.
  5. Delegate immediately to this.handler.handle(...).

Controllers and handlers are registered together:

typescript
@Module({
  imports: [ControllerModule],
  controllers: [
    CreatePersonController,
    ReadPersonController,
    ReadManyPersonController,
    UpdatePersonController,
    DeletePersonController,
  ],
  providers: [
    CreatePersonHandler,
    ReadPersonHandler,
    ReadManyPersonHandler,
    UpdatePersonHandler,
    DeletePersonHandler,
  ],
})
export class PersonModule {}

Koala Nest

A facilitator for building NestJS APIs with DDD architecture. Code copied into your repository — readable, adaptable, and under your control.

Creator

igordrangel.com.br

Design, back-end, and product strategy.

Quick Commands

Global CLI and scripts in the generated project

  • bun install -g @koalarx/nest
  • kl-nest new
  • kl-nest add cache
  • bun run migration:run # CRUD template
  • kl-nest --help
© 2026 Koala NestBuilt for NestJS developers and AI-assisted workflows.