Skip to main content

Controllers

Auto-generated controllers

The simplest setup is the endpoints option of NestjsQueryRestModule. Each entry creates a Nest controller backed by an entity, assembler, or custom QueryService.

todo-item.module.ts
import { Module } from '@nestjs/common'
import { NestjsQueryRestModule, PagingStrategies } from '@ptc-org/nestjs-query-rest'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'

import { TodoItemDTO } from './dto/todo-item.dto'
import { TodoItemInputDTO } from './dto/todo-item-input.dto'
import { TodoItemUpdateDTO } from './dto/todo-item-update.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
imports: [
NestjsQueryRestModule.forFeature({
imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
endpoints: [
{
DTOClass: TodoItemDTO,
EntityClass: TodoItemEntity,
CreateDTOClass: TodoItemInputDTO,
UpdateDTOClass: TodoItemUpdateDTO,
basePath: 'todo-items',
pagingStrategy: PagingStrategies.OFFSET,
enableTotalCount: true,
tags: ['Todo items']
}
]
})
]
})
export class TodoItemModule {}

Use AssemblerClass instead of EntityClass when an assembler maps the entity and DTO, and register the assembler in the module's assemblers array. Use ServiceClass when the endpoint is backed directly by a custom QueryService, and register that provider in services.

Custom controllers

Extend CRUDController to override an endpoint or add ordinary Nest routes. Register the controller and DTO with NestjsQueryRestModule so authorizers and hooks are provided.

todo-item.controller.ts
import { Controller, Get } from '@nestjs/common'
import { InjectQueryService, QueryService } from '@ptc-org/nestjs-query-core'
import { CRUDController } from '@ptc-org/nestjs-query-rest'

import { TodoItemDTO } from './dto/todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Controller('todo-items')
export class TodoItemController extends CRUDController(TodoItemDTO) {
constructor(@InjectQueryService(TodoItemEntity) service: QueryService<TodoItemDTO>) {
super(service)
}

@Get('health')
health() {
return { status: 'ok' }
}
}
todo-item.module.ts
@Module({
imports: [
NestjsQueryRestModule.forFeature({
imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
dtos: [{ DTOClass: TodoItemDTO }],
controllers: [TodoItemController]
})
]
})
export class TodoItemModule {}

For narrower controllers, extend CreateController, ReadController, UpdateController, DeleteController, or ExportController instead.

Options

Top-level CRUDController and endpoint options include:

  • CreateDTOClass and UpdateDTOClass select mutation body DTOs.
  • basePath overrides the generated controller path.
  • dtoName changes the name used to derive operation IDs and the default path.
  • pagingStrategy, defaultResultSize, maxResultsSize, defaultSort, defaultFilter, disableFilter, enableSearch, and enableTotalCount configure collection queries.
  • guards, interceptors, pipes, filters, decorators, and tags apply Nest or OpenAPI behavior to all generated methods.
  • create, read, update, delete, and export configure one controller group independently.

Each operation group accepts disabled. The one and many nested options support a custom path, description, operationOptions, and method-level guards, interceptors, pipes, filters, decorators, and tags.

{
DTOClass: TodoItemDTO,
EntityClass: TodoItemEntity,
basePath: 'tasks',
guards: [JwtAuthGuard],
read: {
many: {
path: 'search',
description: 'Search visible tasks'
}
},
create: { disabled: true },
delete: {
useSoftDelete: true,
one: { path: ':id/archive' }
},
export: { limit: 5000 }
}
note

Static paths can conflict with the default :id route. The generated export route is registered as /export; avoid using export as a record identifier, and use explicit custom paths when necessary.