npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dudousxd/nestjs-filter-codegen

v0.1.1

Published

nestjs-codegen extension for @dudousxd/nestjs-filter — emits a typed filterQuery() helper on filtered routes.

Readme

@dudousxd/nestjs-filter-codegen

Make your nestjs-filter search endpoints type-safe on the client.

npm

A @dudousxd/nestjs-codegen extension that teaches the generated api.ts client about your filter endpoints. For every route decorated with @ApplyFilter/@FilterFor, it adds a typed filterQuery() helper to the generated client — a field-aware, operator-aware builder for the structured where/sort/paginate input your endpoint already accepts. Wrong field names and wrong operator/value pairings become compile-time errors instead of runtime 400s.

It is a type-only contribution: filterQuery() is backed by filterQueryTyped() from @dudousxd/nestjs-filter-client, so there is zero runtime overhead beyond the client builder you would use anyway.

Install

pnpm add -D @dudousxd/nestjs-filter-codegen

It is a peer of the codegen and the client runtime, so make sure those are present too:

pnpm add -D @dudousxd/nestjs-codegen
pnpm add @dudousxd/nestjs-filter-client

| Peer dependency | Range | |-----------------|-------| | @dudousxd/nestjs-codegen | >=0.1.0 | | @dudousxd/nestjs-filter-client | >=1.0.0 |

Setup

Register the extension where you configure the codegen — the extensions array on NestjsCodegenModule.forRoot():

// src/app.module.ts
import { Module } from '@nestjs/common';
import { NestjsCodegenModule } from '@dudousxd/nestjs-codegen/nest';
import { nestjsFilterCodegen } from '@dudousxd/nestjs-filter-codegen';

@Module({
  imports: [
    NestjsCodegenModule.forRoot({
      contracts: { glob: 'src/**/*.controller.ts' },
      codegen: { outDir: 'src/generated' },
      extensions: [nestjsFilterCodegen()],
    }),
    // ... your FilterModule.forRoot(), ORM modules, etc.
  ],
})
export class AppModule {}

That's all the configuration there is — nestjsFilterCodegen() takes no options. On the next regen, the codegen discovers which routes are filtered and emits filterQuery() only on those leaves.

Usage

Given a controller endpoint that applies a filter:

@Controller('users')
export class UsersController {
  @Post('search')
  search(@ApplyFilter(UserFilter) qb: QueryBuilder<User>) {
    return qb.getResultList();
  }
}

…the generated client gains a filterQuery() member on that leaf. It returns a typed builder whose field names are restricted to your filter's fields, and whose operators/values are checked against each field's type:

import { api } from './generated/api';

// `filterQuery()` is typed to this endpoint's filter fields — e.g. 'name' | 'age' | 'status'
const query = api.users.search
  .filterQuery()
  .contains('name', 'Al')   // string field → string ops only
  .gte('age', 18)           // numeric field → ordering ops
  .equals('status', 'active')
  .sortDesc('age')
  .page(0, 25)
  .build();

// ❌ Compile error — 'invalid' is not one of this endpoint's filter fields:
// api.users.search.filterQuery().where('invalid', 'foo');

// Send it however your transport expects — structured body or flat query string:
const result = await api.users.search(query);             // structured input
// or: fetch(`/users?${api.users.search.filterQuery()....toQueryString()}`)

When the codegen also knows each field's concrete type (enums, Date, nullability, named DTO refs), it threads that into the builder so e.g. .equals('status', …) only accepts the enum members, and ordering operators are gated to orderable fields.

The builder is the standard @dudousxd/nestjs-filter-client TypedFilterQueryBuilder: where / add / equals / contains / in / between / gt·gte·lt·lte / isNull / sort / search / include / page / or / and, terminating in build(), toQueryString(), or toFlatObject().

How it fits

@dudousxd/nestjs-codegen has an extension model: extensions implement the CodegenExtension contract from @dudousxd/nestjs-codegen/extension and hook into the api.ts emitter. This package implements two of those hooks — apiHeader (adds the filterQueryTyped import to the top of api.ts, but only when at least one route is filtered) and apiMembers (adds the filterQuery member to each handle leaf whose route carries filterFields). Because member contributions only land on handle leaves, you get filterQuery() alongside whatever other client layer is active (e.g. the plain fetcher or TanStack Query). The codegen owns discovery, the field-type IR, and the emit; this extension just maps that IR onto a typed filterQuery() call.

Links

License

MIT