nestjs-rest-querynestjs-rest-query
Primeiros PassosInstalação

Instalação

Como instalar e configurar o nestjs-rest-query no seu projeto.

Instalar o pacote

pnpm add nestjs-rest-query

Configurar 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

main.ts
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:

app.module.ts
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çãoTipoPadrãoDescrição
defaultPerPagenumber10Quantidade de itens por página quando perPage não é informado na requisição.
maxPerPagenumber100Limite 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çãoTipoPadrãoDescrição
allowedQueryOperator[]todos permitidosLista 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çãoTipoPadrãoDescrição
enabledbooleanfalseHabilita logs internos.
level'error' | 'warn' | 'info' | 'debug''info'Nível mínimo de log emitido.
loggerLoggerLikeNestJS LoggerLogger 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.

Editar esta página no GitHub

On this page