Stop writing if/if/if chains.
Declarative, ORM-agnostic filter classes for NestJS. One decorator in your controller reads query params, validates them, dispatches to filter methods, and hands you a ready-to-execute query builder — with 22 operators, auto-fields, and a typed client-side builder for your frontend team. MikroORM and TypeORM.
4 packages on npm · 22 operators · MikroORM + TypeORM adapters
async findUsers(query: UserQuery) { const qb = this.repo.createQueryBuilder('u'); if (query.name) { qb.andWhere({ name: { $like: `%${query.name}%` } }); } if (query.email) { qb.andWhere({ email: query.email }); } if (query.active !== undefined) { qb.andWhere({ active: query.active }); } // ...20 more fields return qb.getResultList();}@Filterable({ entity: User })export class UserFilter extends MikroOrmFilter<User> { @FilterFor() name(v: string) { this.whereLike('name', v); } @FilterFor() status(v: string[]) { this.whereIn('status', v); }} // Controller: one line@Get() list(@ApplyFilter(UserFilter) qb) { return qb.getResultList();}Filtering as a first-class citizen
Six guarantees, one mental model. Query-string in, validated and composable query builder out.
@ApplyFilter decorator
One decorator in your controller. It reads query params (GET) or body (POST), validates with class-validator, dispatches to filter methods, and hands you back a ready-to-execute query builder.
Auto-fields
For simple equality and operator filters, skip writing methods entirely: declare autoFields with an allowlist and WHERE clauses are generated from query params automatically.
22 built-in operators
equals, contains, gte, between, in, isNull, isAnyOf and friends — composable with AND/OR logic via bracket notation, for auto-fields and custom @FilterFor methods alike.
Client-side query builder
A fluent, type-safe API for building filter queries in the browser or Node. Zero dependencies, generates the exact format the server expects. Ship it to your frontend team.
ORM-agnostic core
First-class MikroORM and TypeORM adapters over a shared core. Filter classes express intent (whereLike, whereIn); the adapter translates to your query builder.
Validated input
Filter payloads run through class-validator before any method fires. Unknown fields are rejected by the allowlist — clients only ever filter what you exposed.
The frontend speaks filter too.
filterQuery() builds the exact query format the server expects — fluent, typed, zero dependencies. No more hand-assembled query strings drifting out of sync with the backend's parser.
import { filterQuery } from '@dudousxd/nestjs-filter-client'; const query = filterQuery() .contains('name', 'Al') .gte('age', 18) .in('status', ['active', 'pending']) .build(); // => name[contains]=Al&age[gte]=18// &status[in]=active,pendingZero to filtering in under 5 minutes.
Install the core, pick your ORM adapter, write one filter class — and delete the if-chain for good.