Codegen
A typed-client codegen for NestJS — routes, API client, and validation schemas, generated from your controllers.
@dudousxd/nestjs-codegen reads your NestJS controllers, contracts, and DTOs and generates a fully-typed client for them: a route map, a typed API client, and client-side validation schemas. Your backend stays the single source of truth — change a controller and the client follows. It works with or without Inertia.js, and every moving part is pluggable: the validation library, the HTTP client, the serializer, and the query layer.
Coming from nestjs-inertia?
This is the same codegen, extracted into its own repo. The config file
nestjs-codegen.config.ts is the successor of nestjs-inertia.config.ts (the old
name is still accepted). See Getting Started.
The problem it solves
A NestJS controller already knows everything a client needs: the path, the HTTP method, the request body shape, and the response type. Yet most frontends re-state all of it by hand — hand-written fetch wrappers, duplicated route strings, a second copy of every validation rule. That copy drifts the moment a controller changes, and nothing tells you until something breaks at runtime.
nestjs-codegen closes that gap by deriving the client from the server. It discovers your routes and types once, emits typed artifacts, and keeps them in sync — in dev as you edit, and in CI as a gate that fails the build when the committed client drifts.
What you get
The codegen writes these files into your output directory:
routes.ts— aROUTESmap, aRouteNameunion, and a typedroute()helper.api.ts— a Tuyau-stylecreateApi(fetcher)factory; nested by route name, fully typed.forms.ts— a validation schema per validated endpoint, in your chosen lib.pages.d.ts/components.json— when the Inertia integration is enabled.
Quickstart
The whole loop — install, register the module, use the client — in three steps. For the full walkthrough, including the CI flow, see Getting Started.
Install the codegen and the runtime the generated client imports its Fetcher type from:
pnpm add -D @dudousxd/nestjs-codegen @dudousxd/nestjs-codegen-zod
pnpm add @dudousxd/nestjs-clientRegister NestjsCodegenModule in your root module. It starts with your dev server and regenerates the client as you edit your controllers — no config file, no extra process to run:
import { Module } from '@nestjs/common';
import { NestjsCodegenModule } from '@dudousxd/nestjs-codegen/nest';
import { zodAdapter } from '@dudousxd/nestjs-codegen-zod';
@Module({
imports: [
NestjsCodegenModule.forRoot({
contracts: { glob: 'src/**/*.controller.ts' }, // controllers to scan
codegen: { outDir: 'src/generated' }, // where to write the client
validation: zodAdapter, // zodAdapter | valibotAdapter | arktypeAdapter
}),
],
})
export class AppModule {}Run your app as usual (nest start --watch) and the generated files appear in src/generated, kept in sync while the server runs.
Create the client once, injecting your fetcher, then call your endpoints with full type safety:
import { createApi } from '../generated/api';
import { createFetcher } from '@dudousxd/nestjs-client';
export const api = createApi(createFetcher({ baseUrl: '/api' }));import { api } from './lib/api';
const users = await api.users.list(); // typed User[]
const created = await api.users.create({ body }); // typed body + responseThe watcher is a dev/CI concern, so the module skips it automatically when
NODE_ENV === 'production'. For CI, the same generator ships as a CLI —
npx nestjs-codegen codegen — to fail the build before deploy if the committed
client has drifted. See CLI.
Key features
- Pluggable validation — one neutral
SchemaNodeIR, rendered by zod, valibot, or arktype adapters (each a separate package). See Validation. - Typed API client —
createApi(fetcher): inject your own client at runtime. See API client. - Bring your own fetcher — native
fetchby default, or an axios instance; superjson and transformer pipelines supported. See Fetcher. - Extension-based integrations — register integrations in
extensions: [...]; each shapes the generatedapi.ts. See Extensions.- TanStack Query (
tanstackQuery()) — emitsqueryOptions/mutationOptionsfrom your adapter package (react/vue/svelte/solid). See TanStack Query. - nestjs-filter (
nestjsFilterCodegen()) —@FilterFor/@ApplyFilter→ typedfilterQuery()helpers. See Filters. - nestjs-inertia (
nestjsInertiaCodegen()) — pages, shared props, and the Inertiarouter+navigate()helper. See Inertia.
- TanStack Query (
Where to go next
Getting Started
Install, wire the module, generate in CI, and use the typed client.
Configuration
Every forRoot / defineConfig option, in one place.
CLI
The codegen / init / doctor commands and the CI drift check.
Validation
The SchemaNode IR and the zod, valibot, and arktype adapters.
API client
The createApi(fetcher) factory and the typed call surface.
Fetcher
Bring your own transport — native fetch, axios, and superjson.
TanStack Query
Opt-in queryOptions / mutationOptions handles in api.ts.
Extensions
How integrations register and shape the generated client.
Programmatic
loadConfig, generate, and watch — the codegen as a library.