{"id":48687,"library":"nestjs-rest-query","title":"NestJS REST Query","description":"Declarative, whitelist-first REST query params for NestJS (v2.1.0). Parses query strings like ?filter[email][like]=acme&sorts=-createdAt&page=2 into safe, typed database queries for TypeORM, Drizzle, and Prisma. Active development, frequent releases. Key differentiator: zero-config whitelist pattern enforces security by default (unknown params silently ignored). Compared to nestjsx/crud or @nestjsx/crud, this library focuses on type safety, Swagger auto-documentation, and adapter-based multi-ORM support.","status":"active","version":"2.1.0","language":"javascript","source_language":"en","source_url":"https://github.com/naldomadeira/nestjs-rest-query","tags":["javascript","nestjs","typeorm","rest","query","query-params","filter","filters","pagination","typescript"],"install":[{"cmd":"npm install nestjs-rest-query","lang":"bash","label":"npm"},{"cmd":"yarn add nestjs-rest-query","lang":"bash","label":"yarn"},{"cmd":"pnpm add nestjs-rest-query","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency - NestJS decorators and module system","package":"@nestjs/common","optional":false},{"reason":"Peer dependency - NestJS module lifecycle","package":"@nestjs/core","optional":false},{"reason":"Peer dependency - TypeScript decorator metadata","package":"reflect-metadata","optional":false},{"reason":"Optional peer - TypeORM adapter (default)","package":"typeorm","optional":true},{"reason":"Optional peer - OpenAPI auto-documentation","package":"@nestjs/swagger","optional":true}],"imports":[{"note":"Module is exported as named ESM. For CommonJS use the import syntax above (NestJS requires ESM imports for decorators).","wrong":"const DynamicQueryBuilderModule = require('nestjs-rest-query').DynamicQueryBuilderModule","symbol":"DynamicQueryBuilderModule","correct":"import { DynamicQueryBuilderModule } from 'nestjs-rest-query'"},{"note":"Type for query params object. Also importable from subpaths: 'nestjs-rest-query/drizzle' etc.","wrong":"","symbol":"QueryParams","correct":"import { QueryParams } from 'nestjs-rest-query'"},{"note":"Subpath exports are required for adapter-specific types. Using the root import for DrizzleAdapter will fail.","wrong":"import { DrizzleAdapter } from 'nestjs-rest-query'","symbol":"DrizzleAdapter","correct":"import { DrizzleAdapter } from 'nestjs-rest-query/drizzle'"}],"quickstart":{"code":"import { Module } from '@nestjs/common';\nimport { DynamicQueryBuilderModule } from 'nestjs-rest-query';\nimport { TypeOrmModule } from '@nestjs/typeorm';\nimport { User } from './user.entity';\nimport { UserController } from './user.controller';\nimport { UserService } from './user.service';\n\n@Module({\n  imports: [\n    DynamicQueryBuilderModule.forRoot({\n      pagination: { defaultPerPage: 20, maxPerPage: 100 },\n    }),\n    TypeOrmModule.forFeature([User]),\n  ],\n  controllers: [UserController],\n  providers: [UserService],\n})\nexport class UserModule {}\n\n// user.controller.ts\nimport { Controller, Get } from '@nestjs/common';\nimport { QueryParams } from 'nestjs-rest-query/query-params';\nimport { UseQueryBuilder } from 'nestjs-rest-query';\nimport { UserService } from './user.service';\nimport { User } from './user.entity';\n\n@Controller('users')\nexport class UserController {\n  constructor(private readonly userService: UserService) {}\n\n  @Get()\n  @UseQueryBuilder({\n    allowedFilters: ['email', 'firstName', 'lastName', 'age'],\n    allowedSorts: ['createdAt', 'email', 'firstName'],\n    allowedIncludes: ['posts'],\n    searchFields: ['firstName', 'lastName', 'email'],\n  })\n  async findAll(@QueryParams() params: any) {\n    return this.userService.findAll(params);\n  }\n}\n\n// user.service.ts\nimport { Injectable } from '@nestjs/common';\nimport { InjectRepository } from '@nestjs/typeorm';\nimport { Repository } from 'typeorm';\nimport { User } from './user.entity';\nimport { FindOptions } from 'nestjs-rest-query';\n\n@Injectable()\nexport class UserService {\n  constructor(\n    @InjectRepository(User)\n    private readonly userRepository: Repository<User>,\n  ) {}\n\n  async findAll(query: any) {\n    const { data, total, page, perPage, lastPage } = await this.userRepository.find({\n      ...query.buildFindOptions(),\n    });\n    return { data, total, page, perPage, lastPage };\n  }\n}","lang":"typescript","description":"Full NestJS module setup with DynamicQueryBuilderModule, controller decorator, and TypeORM service integration."},"warnings":[{"fix":"Upgrade to Node >=20, NestJS >=11, TypeORM >=0.3.26.","message":"v2.0 removed support for Node <20, NestJS <11, and TypeORM <0.3.26.","severity":"breaking","affected_versions":">=1.0.0 <2.0.0"},{"fix":"Pass adapter instance: DynamicQueryBuilderModule.forRoot({ adapter: new DrizzleAdapter() }).","message":"DynamicQueryBuilderModule.forRoot() no longer accepts a 'type' option for ORM selection; use adapter parameter instead.","severity":"deprecated","affected_versions":">=1.0.0"},{"fix":"Use ?filter[column][isNull]=true instead of ?filter[column]=null.","message":"Null and undefined filter values are silently ignored; to filter null use explicit operator isNull.","severity":"gotcha","affected_versions":">=2.0.0"},{"fix":"Apply @QueryParams() decorator to the method parameter in the controller handler.","message":"The @QueryParams() decorator must be applied to the method parameter, not the class. Applying to class will be ignored.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"search_vec":"'2':25 'acm':21 'activ':36 'adapt':72 'adapter-bas':71 'auto':68 'auto-document':67 'base':73 'compar':55 'config':44 'createdat':23 'databas':29 'declar':4 'default':50 'develop':37 'differenti':41 'document':69 'drizzl':33 'email':19 'enforc':47 'filter':18,86,87 'first':7 'focus':62 'frequent':38 'ignor':54 'javascript':78 'key':40 'librari':61 'like':17,20 'multi':75 'multi-orm':74 'nestj':1,12,79 'nestjsx/crud':57,59 'orm':76 'page':24 'pagin':88 'param':10,52,85 'pars':14 'pattern':46 'prisma':35 'queri':3,9,15,30,82,84 'query-param':83 'releas':39 'rest':2,8,81 'safe':27 'safeti':65 'secur':48 'silent':53 'sort':22 'string':16 'support':77 'swagger':66 'type':28,64 'typeorm':32,80 'typescript':89 'unknown':51 'v2.1.0':13 'whitelist':6,45 'whitelist-first':5 'zero':43 'zero-config':42","created_at":"2026-06-07T16:57:55.566138+00:00","updated_at":"2026-06-07T16:57:55.566138+00:00","problems":[{"fix":"Import from 'nestjs-rest-query/drizzle' (not 'nestjs-rest-query'). Ensure your tsconfig.json includes the moduleResolution: 'node16' or 'bundler'.","cause":"Using root import path for ORM adapter that requires subpath export.","error":"Cannot find module 'nestjs-rest-query/drizzle' or its corresponding type declarations."},{"fix":"Use import { DynamicQueryBuilderModule } from 'nestjs-rest-query';","cause":"Incorrect default import; the module is a named export.","error":"DynamicQueryBuilderModule is not a function or class"},{"fix":"Update TypeORM to ^0.3.26 and nestjs-rest-query to ^2.0.0.","cause":"Incompatible TypeORM version; v0.3.26+ changed FindOptionsOrder shape.","error":"Type 'FindOptionsOrder<Entity>' is not assignable to type 'FindOptionsOrder<Entity>'."},{"fix":"Add DynamicQueryBuilderModule.forRoot({}) to the imports array of your root module (or a feature module).","cause":"Missing DynamicQueryBuilderModule.forRoot() in root module imports.","error":"Cannot use @UseQueryBuilder decorator on controller method without proper module registration."},{"fix":"Use the 'ilike' operator instead of 'like' for case-insensitive filtering: ?filter[email][ilike]=acme","cause":"Case sensitivity or whitespace mismatch; ilike operator is needed for case-insensitive matching.","error":"Query parameter 'filter[email][like]=acme' returned an empty result set even though matching records exist."}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":"https://naldomadeira.github.io/nestjs-rest-query/","github":"https://github.com/naldomadeira/nestjs-rest-query","docs":null,"changelog":null,"pypi":null,"npm":"nestjs-rest-query","openapi_spec":null,"status_page":null,"smithery":null,"categories":["database","devops"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-07","next_check":"2026-09-05","install_tag":null}}