Instalação
Como instalar e configurar o nestjs-rest-query no seu projeto.
Instalar o pacote
pnpm add nestjs-rest-queryConfigurar o bootstrap
Três ajustes são necessários no main.ts para que a biblioteca funcione corretamente.
1. Query parser estendido
app.set('query parser', 'extended');O Express 5 alterou o parser de query padrão de qs (extended) para simple. A biblioteca espera que parâmetros como ?filter[name][eq]=foo sejam expandidos em objetos aninhados pelo framework antes de chegar ao controller — isso só acontece com o parser extended.
2. ValidationPipe com conversão implícita
app.useGlobalPipes(
new ValidationPipe({
transform: true,
transformOptions: {
enableImplicitConversion: true,
},
})
);O DTO usa string para campos como page e perPage. O enableImplicitConversion: true instrui o class-transformer a converter esses valores para os tipos esperados automaticamente, sem a necessidade de decorators adicionais no DTO.
3. Interceptor do Swagger (opcional)
import { dqbSwaggerRequestInterceptor } from 'nestjs-rest-query';
SwaggerModule.setup('/', app, document, {
swaggerOptions: {
requestInterceptor: dqbSwaggerRequestInterceptor(document),
},
});O Swagger UI serializa filtros como múltiplos query params (filter[name][eq]=foo). Sem o interceptor, o browser envia esses parâmetros de forma que o Express pode não preservar a notação de colchetes corretamente. O dqbSwaggerRequestInterceptor reescreve a URL antes de disparar a requisição, garantindo que os filtros cheguem ao controller no formato esperado.
Este interceptor só é necessário para testar filtros pela interface do Swagger UI. Clientes externos (Postman, aplicações frontend, etc.) constroem a URL diretamente e não precisam dele. A seção Swagger explica o cenário completo.
Exemplo completo
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { ValidationPipe } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { AppModule } from './app.module';
import { dqbSwaggerRequestInterceptor } from 'nestjs-rest-query';
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
// Required to expand filter[field][op]=value into nested objects
app.set('query parser', 'extended');
app.useGlobalPipes(
new ValidationPipe({
transform: true,
transformOptions: {
enableImplicitConversion: true,
},
})
);
const document = SwaggerModule.createDocument(
app,
new DocumentBuilder().setTitle('Minha API').setVersion('1.0').build()
);
SwaggerModule.setup('/', app, document, {
swaggerOptions: {
requestInterceptor: dqbSwaggerRequestInterceptor(document),
},
});
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();Registrar o módulo
Importe DynamicQueryBuilderModule no AppModule raiz com forRoot. Todas as opções são opcionais — sem configuração, a biblioteca usa os valores padrão:
import { Module } from '@nestjs/common';
import { DynamicQueryBuilderModule } from 'nestjs-rest-query';
@Module({
imports: [
DynamicQueryBuilderModule.forRoot({
// all options are optional
}),
],
})
export class AppModule {}O módulo é @Global, portanto não é necessário importá-lo em módulos de funcionalidade — o QueryBuilderService fica disponível em toda a aplicação automaticamente.
Opções de configuração
forRoot aceita um objeto QueryBuilderConfig. Todas as propriedades são opcionais.
pagination
Controla o comportamento padrão de paginação.
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
defaultPerPage | number | 10 | Quantidade de itens por página quando perPage não é informado na requisição. |
maxPerPage | number | 100 | Limite máximo de itens por página, ignorando valores maiores enviados pelo cliente. |
operators
Restringe os operadores de filtro permitidos globalmente na aplicação.
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
allowed | QueryOperator[] | todos permitidos | Lista de operadores aceitos. undefined = todos. [] (lista vazia) = nenhum operador permitido. |
DynamicQueryBuilderModule.forRoot({
operators: {
allowed: ['eq', 'like', 'in', 'between'],
},
});Você também pode sobrescrever isso por endpoint com RulesConfig.operators; quando presente, o valor do endpoint vence a configuração global do forRoot apenas naquela rota.
@ApiDynamicQuery({
filters: ['name', 'status'],
operators: { allowed: ['eq', 'ilike'] },
})
list(@Query() query: DynamicQueryDto, @QueryRules() rules: RulesConfig) {
return this.service.list(query, rules);
}Se o endpoint definir explicitamente operators: {}, aquela rota volta a permitir todos os operadores.
logging
Habilita e configura os logs internos de construção de queries.
| Opção | Tipo | Padrão | Descrição |
|---|---|---|---|
enabled | boolean | false | Habilita logs internos. |
level | 'error' | 'warn' | 'info' | 'debug' | 'info' | Nível mínimo de log emitido. |
logger | LoggerLike | NestJS Logger | Logger customizado. Qualquer objeto com error/warn/log/debug funciona (winston, pino, etc.). |
DynamicQueryBuilderModule.forRoot({
logging: {
enabled: true,
level: 'debug',
},
});Próximos passos
Com o módulo registrado, injete o QueryBuilderService em qualquer provider e comece a construir queries dinâmicas a partir dos parâmetros de requisição HTTP.
Se quiser sair do zero com um endpoint real, siga para Primeiro endpoint. Para entender a integração com OpenAPI, veja Swagger.