Getting Started

nest-extended works two ways: scaffold a brand-new NestJS app with the CLI, or add the packages to an app you already have. Both give you the generic CRUD controller and service, the unified query language, service lifecycle events, soft-delete and auditing.

Option A — Use the CLI

Install the CLI globally:

$npm install -g @nest-extended/cli

Scaffold a new app, then generate your first CRUD resource:

nest-cli g app my-api --db PostgreSQL --orm prisma --validator zod --auth
cd my-api
nest-cli g service cats

g service generates the schema/entity, module, service, controller, events class, DTO and specs — a complete CRUD resource wired into your app. Then start it:

$npm run start

Option B — Add to an existing app

1. Install

Install the shared core and decorators packages plus the adapter for your database (swap @nest-extended/mongoose for @nest-extended/prisma or @nest-extended/typeorm):

$npm install @nest-extended/core @nest-extended/mongoose @nest-extended/decorators nestjs-cls

2. Register the module

Wire up ClsModule, NestExtendedModule, the global exception filter and the null-response interceptor in your root module. Import GlobalExceptionFilter from the adapter you installed.

app.module.ts
import { Module } from '@nestjs/common';
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
import { ClsModule } from 'nestjs-cls';
import { NestExtendedModule, NullResponseInterceptor } from '@nest-extended/core';
import { GlobalExceptionFilter } from '@nest-extended/mongoose'; // or /prisma, /typeorm
 
@Module({
  imports: [
    ClsModule.forRoot({ global: true, middleware: { mount: true } }),
    // forRoot() also discovers @ServiceEvents() classes and registers the controller
    // hooks interceptor — see /docs/events.
    NestExtendedModule.forRoot({ queryParser: { depth: 20, arrayLimit: 100 } }),
  ],
  providers: [
    { provide: APP_FILTER, useClass: GlobalExceptionFilter },
    { provide: APP_INTERCEPTOR, useClass: NullResponseInterceptor },
  ],
})
export class AppModule {}

3. Create a service and controller

Extend NestService for your model and NestController for the routes — that's the entire CRUD layer.

cats.service.ts
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { NestService } from '@nest-extended/mongoose';
import { Cat, CatDocument } from './schemas/cat.schema';
 
@Injectable()
export class CatsService extends NestService<Cat, CatDocument> {
  constructor(@InjectModel(Cat.name) model: Model<CatDocument>) {
    super(model);
  }
}
cats.controller.ts
import { Controller } from '@nestjs/common';
import { NestController } from '@nest-extended/core';
import { CatsService } from './cats.service';
 
@Controller('cats')
export class CatsController extends NestController<Cat> {
  constructor(service: CatsService) {
    super(service);
  }
}

You now have GET /cats, GET /cats/:id, POST /cats, PATCH /cats/:id and DELETE /cats/:id — with pagination, filtering and soft-delete already wired in.

NestService gives you find, get, create, patch, remove and getCount for free. Each also has an underscore twin — _find, _get, _create, _patch, _remove — that does exactly the same work without dispatching lifecycle events; use those when one service calls another.

Upgrading from 1.0.0

Already running 1.0.0? Bump the packages and run the events codemod:

npm i @nest-extended/core@^1.5.0 @nest-extended/decorators@^1.5.0 @nest-extended/mongoose@^1.5.0
nest-cli m events --dry-run

The migration guide has the full checklist, including the NestJS 12 and Prisma 7 notes.

Next steps