// Simple NestJS controller example import { Controller, Get } from '@nestjs/common'; @Controller('hello') export class HelloController { @Get() getHello(): string { return 'Hello from NestJS!'; } }
// Example of dependency injection @Injectable() export class CatsService { getCats() { return ['cat1', 'cat2']; } }
// Express route app.get('/cats', (req, res) => { res.send(['cat1', 'cat2']); }); // NestJS route (as above)
// Example Module @Module({ controllers: [CatsController], providers: [CatsService], }) export class CatsModule {}
npm i -g @nestjs/cli nest new project-name cd project-name npm run start
npm install -g @nestjs/cli
nest new my-nest-app
my-nest-app/ ├── src/ │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── package.json └── nest-cli.json
npm run start // or for live reload npm run start:dev
// Install config package npm install @nestjs/config // In app.module.ts import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ConfigModule.forRoot()], }) export class AppModule {}
import { Module } from '@nestjs/common'; @Module({ controllers: [...], providers: [...], imports: [...], exports: [...], }) export class FeatureModule {}
nest generate module cats // or nest g mo cats
@Module({ controllers: [CatsController], providers: [CatsService], imports: [], exports: [CatsService], }) export class CatsModule {}
@Module({ imports: [CatsModule], }) export class AppModule {}
import { Global, Module } from '@nestjs/common'; @Global() @Module({ providers: [ConfigService], exports: [ConfigService], }) export class ConfigModule {}
import { Controller, Get } from '@nestjs/common'; @Controller('cats') export class CatsController { @Get() findAll() { return 'This action returns all cats'; } }
@Controller('cats') export class CatsController { @Get() findAll() { /* ... */ } @Post() create() { /* ... */ } @Put(':id') update(@Param('id') id: string) { /* ... */ } @Delete(':id') remove(@Param('id') id: string) { /* ... */ } }
@Post() create(@Body() createCatDto) { return `Create cat with name ${createCatDto.name}`; }
@Get(':id') findOne(@Param('id') id: string) { return `Cat #${id}`; } @Get() findByBreed(@Query('breed') breed: string) { return `Cats of breed ${breed}`; }
import { Injectable } from '@nestjs/common'; @Injectable() export class CatsService { private readonly cats = []; findAll() { return this.cats; } } import { Controller, Get } from '@nestjs/common'; import { CatsService } from './cats.service'; @Controller('cats') export class CatsController { constructor(private readonly catsService: CatsService) {} @Get() findAll() { return this.catsService.findAll(); } }
{ provide: 'CUSTOM_TOKEN', useClass: CustomService, }
{ provide: ConfigService, useFactory: () => { return new ConfigService(process.env.CONFIG); }, }
@Injectable({ scope: Scope.REQUEST }) export class ScopedService { }
// Example: middleware logs each request function logger(req, res, next) { console.log(`${req.method} ${req.url}`); next(); }
function authMiddleware(req, res, next) { if (!req.headers.authorization) { res.status(401).send('Unauthorized'); } else { next(); } }
// Global app.use(authMiddleware); // Specific route app.get('/profile', authMiddleware, (req, res) => { res.send('User Profile'); });
const bodyParser = require('body-parser'); app.use(bodyParser.json()); // parses JSON bodies
throw new NotFoundException('Resource not found');
class CustomException extends HttpException { constructor() { super('Custom error occurred', 400); } }
@Catch() export class AllExceptionsFilter implements ExceptionFilter { catch(exception: any, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse(); response.status(500).json({ message: 'Internal server error' }); } }
@Catch(NotFoundException) export class NotFoundFilter implements ExceptionFilter { catch(exception: NotFoundException, host: ArgumentsHost) { // custom logic here } }
@Query() getUser(@Param('id', ParseIntPipe) id: number) { return this.userService.findById(id); }
@UsePipes(new ValidationPipe()) createUser(@Body() createUserDto: CreateUserDto) { // validated dto here }
@Injectable() export class TrimPipe implements PipeTransform { transform(value: any) { if (typeof value === 'string') { return value.trim(); } return value; } }
// Global app.useGlobalPipes(new ValidationPipe()); // Controller @UsePipes(new ValidationPipe()) @Controller('users') export class UsersController {} // Parameter getUser(@Param('id', ParseIntPipe) id: number) {}
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; @Injectable() export class AuthGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); return request.headers.authorization === 'valid-token'; } }
@Injectable() export class RolesGuard implements CanActivate { constructor(private readonly roles: string[]) {} canActivate(context: ExecutionContext): boolean { const user = context.switchToHttp().getRequest().user; return this.roles.includes(user.role); } }
@Injectable() export class CustomGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { // Custom logic here return true; // or false } }
import { Controller, Get, UseGuards } from '@nestjs/common'; @Controller('cats') @UseGuards(AuthGuard) export class CatsController { @Get() findAll() { return 'This route is protected by AuthGuard'; } }
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import { Observable } from 'rxjs'; import { tap } from 'rxjs/operators'; @Injectable() export class LoggingInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable{ console.log('Before handler execution'); const now = Date.now(); return next .handle() .pipe(tap(() => console.log(`After... ${Date.now() - now}ms`))); } }
// Example: Response mapping interceptor @Injectable() export class TransformInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable{ return next.handle().pipe( map(data => ({ data, timestamp: new Date().toISOString() })), ); } }
import { Controller, Get, UseInterceptors } from '@nestjs/common'; @Controller('cats') @UseInterceptors(LoggingInterceptor) export class CatsController { @Get() findAll() { return ['cat1', 'cat2']; } }
@Injectable() export class CustomInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable{ // Custom pre-processing return next.handle().pipe( // Custom post-processing ); } }
import { IsString, IsEmail } from 'class-validator'; export class CreateUserDto { @IsString() name: string; @IsEmail() email: string; }
export class UpdateUserDto { @IsString() name?: string; @IsEmail() email?: string; }
import { ValidationPipe } from '@nestjs/common'; app.useGlobalPipes(new ValidationPipe());
// Example error response { "statusCode": 400, "message": [ "name must be a string", "email must be an email" ], "error": "Bad Request" }
// Install npm install @nestjs/config // In app.module.ts import { ConfigModule } from '@nestjs/config'; @Module({ imports: [ConfigModule.forRoot()], }) export class AppModule {}
// .env file DATABASE_HOST=localhost DATABASE_PORT=5432
// Usage in service import { ConfigService } from '@nestjs/config'; constructor(private configService: ConfigService) {} const dbHost = this.configService.get('DATABASE_HOST');
interface EnvConfig { DATABASE_HOST: string; DATABASE_PORT: number; } const config = () => ({ DATABASE_HOST: process.env.DATABASE_HOST, DATABASE_PORT: parseInt(process.env.DATABASE_PORT, 10), });
ConfigModule.forRoot({ envFilePath: `.env.${process.env.NODE_ENV || 'development'}`, });
import { Logger } from '@nestjs/common'; const logger = new Logger('MyApp'); logger.log('This is a log message'); logger.error('This is an error'); logger.warn('This is a warning');
import { Logger } from '@nestjs/common'; export class MyLogger extends Logger { log(message: string) { // custom behavior super.log(message); } }
// Example with Winston integration import { WinstonModule } from 'nest-winston'; import * as winston from 'winston'; @Module({ imports: [ WinstonModule.forRoot({ transports: [ new winston.transports.Console(), new winston.transports.File({ filename: 'combined.log' }), ], }), ], }) export class AppModule {}
// Install npm install --save @nestjs/typeorm typeorm pg // Setup in app.module.ts import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', host: 'localhost', port: 5432, username: 'user', password: 'pass', database: 'mydb', entities: [__dirname + '/**/*.entity{.ts,.js}'], synchronize: true, }), ], }) export class AppModule {}
// Install npm install --save @nestjs/sequelize sequelize sequelize-typescript pg // Setup in app.module.ts import { SequelizeModule } from '@nestjs/sequelize'; @Module({ imports: [ SequelizeModule.forRoot({ dialect: 'postgres', host: 'localhost', port: 5432, username: 'user', password: 'pass', database: 'mydb', models: [User], autoLoadModels: true, }), ], }) export class AppModule {}
// Install npm install --save @nestjs/mongoose mongoose // Setup import { MongooseModule } from '@nestjs/mongoose'; @Module({ imports: [ MongooseModule.forRoot('mongodb://localhost/nest'), ], }) export class AppModule {}
@Injectable() export class UserService { constructor( @InjectRepository(User) private userRepository: Repository, ) {} findAll() { return this.userRepository.find(); } }
// TypeORM entity example @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column() name: string; }
const jwt = require('jsonwebtoken'); const token = jwt.sign({ userId: 123 }, 'your-secret-key', { expiresIn: '1h' });
const passport = require('passport'); const JwtStrategy = require('passport-jwt').Strategy; passport.use(new JwtStrategy(opts, (jwt_payload, done) => { User.findById(jwt_payload.userId) .then(user => done(null, user)) .catch(err => done(err, false)); }));
// Sessions example with express-session app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true }));
app.get('/profile', passport.authenticate('jwt', { session: false }), (req, res) => { res.send('Protected profile page'); });
// Issue refresh token alongside access token const refreshToken = jwt.sign({ userId: 123 }, 'refresh-secret', { expiresIn: '7d' });
function checkRole(role) { return (req, res, next) => { if (req.user.role === role) { next(); } else { res.status(403).send('Forbidden'); } }; }
// Example policy const canEditPost = (user, post) => user.id === post.authorId || user.role === 'admin';
app.get('/admin', passport.authenticate('jwt', { session: false }), checkRole('admin'), (req, res) => { res.send('Welcome Admin'); });
@WebSocketGateway() export class EventsGateway { @WebSocketServer() server; }
@SubscribeMessage('message') handleMessage(client: Socket, payload: any) { this.server.emit('message', payload); }
this.server.emit('eventName', data); // broadcast to all connected clients
import { Server } from 'socket.io'; const io = new Server(server); io.on('connection', socket => { socket.on('chat', msg => { io.emit('chat', msg); }); });
npm install graphql @nestjs/graphql apollo-server-express
// Code-first example (NestJS): @ObjectType() class User { @Field() name: string; }
@Resolver() export class UserResolver { @Query(() => String) hello() { return 'Hello GraphQL'; } }
@Subscription(() => Message) messageAdded() { // logic for realtime message updates }
// URI versioning example GET /api/v1/users
// Query params example GET /users?limit=10&offset=20
{ "users": [...], "links": { "next": "/api/v1/users?offset=20&limit=10" } }
HTTP/1.1 404 Not Found { "error": "User not found" }
test('adds 1 + 2 to equal 3', () => { expect(1 + 2).toBe(3); });
// Example testing a service method describe('UserService', () => { it('should return a user by ID', () => { // test code here }); });
// Example with Jest and Supertest describe('AppController (e2e)', () => { it('/GET users', () => { return request(app.getHttpServer()) .get('/users') .expect(200) .expect(response => { expect(response.body).toBeInstanceOf(Array); }); }); });
const mockUserService = { findUser: jest.fn().mockReturnValue({ id: 1, name: 'Test User' }), };
import { Injectable } from '@nestjs/common'; import { Cron, Interval, Timeout } from '@nestjs/schedule'; @Injectable() export class TasksService { @Cron('45 * * * * *') handleCron() { console.log('Called every minute at second 45'); } @Interval(10000) handleInterval() { console.log('Called every 10 seconds'); } @Timeout(5000) handleTimeout() { console.log('Called once after 5 seconds'); } }
// Cron example: every day at midnight @Cron('0 0 0 * * *') handleDailyTask() { // Do daily task } // Interval example: every 5 minutes @Interval(300000) handleRepeatTask() { // Do repeated task }
@Timeout(60000) handleDelayedTask() { console.log('Runs once after 1 minute'); }
import { SchedulerRegistry } from '@nestjs/schedule'; constructor(private schedulerRegistry: SchedulerRegistry) {} cancelJob(name: string) { const job = this.schedulerRegistry.getCronJob(name); job.stop(); }
import { BullModule } from '@nestjs/bull'; @Module({ imports: [ BullModule.forRoot({ redis: { host: 'localhost', port: 6379, }, }), BullModule.registerQueue({ name: 'email', }), ], }) export class AppModule {}
// Producer - add job await this.emailQueue.add({ to: 'user@example.com', subject: 'Hello!' }); // Consumer - process job @Processor('email') export class EmailProcessor { @Process() async handleEmailJob(job: Job) { console.log('Sending email to', job.data.to); // send email logic } }
// Add job with delay and retries await this.emailQueue.add( { to: 'user@example.com' }, { delay: 60000, // wait 60 seconds attempts: 3, // retry 3 times if failed }, );
this.emailQueue.on('completed', (job) => { console.log(`Job ${job.id} completed!`); }); this.emailQueue.on('failed', (job, err) => { console.log(`Job ${job.id} failed with error ${err.message}`); });
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; @Controller('upload') export class UploadController { @Post() @UseInterceptors(FileInterceptor('file')) uploadFile(@UploadedFile() file: Express.Multer.File) { console.log(file); return { message: 'File uploaded successfully!' }; } }
// HTML form example <form method="POST" enctype="multipart/form-data" action="/upload"> <input type="file" name="file" /> <button type="submit">Upload</button> </form>
@Post('stream') @UseInterceptors(FileInterceptor('file')) uploadStream(@UploadedFile() file: Express.Multer.File) { const stream = file.stream; // Process stream data chunk by chunk }
@UseInterceptors(FileInterceptor('file', { limits: { fileSize: 2 * 1024 * 1024 }, // 2MB max fileFilter: (req, file, cb) => { if (!file.mimetype.match(/\/(jpg|jpeg|png|gif)$/)) { return cb(new Error('Only images are allowed!'), false); } cb(null, true); } }))
import { CacheModule, Module } from '@nestjs/common'; @Module({ imports: [CacheModule.register()], }) export class AppModule {}
import { Injectable, Cacheable } from '@nestjs/common'; @Injectable() export class CatsService { @Cacheable() getCats() { // This result will be cached in memory } }
CacheModule.register({ store: require('cache-manager-redis-store'), host: 'localhost', port: 6379, });
import { CacheInterceptor, UseInterceptors, Controller, Get } from '@nestjs/common'; @Controller('cats') @UseInterceptors(CacheInterceptor) export class CatsController { @Get() findAll() { // Response will be cached automatically return ['cat1', 'cat2']; } }
import * as helmet from 'helmet'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.use(helmet()); await app.listen(3000); } bootstrap();
// Example: Using csurf middleware for CSRF protection import * as csurf from 'csurf'; app.use(csurf());
import { ThrottlerModule } from '@nestjs/throttler'; @Module({ imports: [ ThrottlerModule.forRoot({ ttl: 60, limit: 10, }), ], }) export class AppModule {}
@Injectable() export class ApiKeyGuard implements CanActivate { canActivate(context: ExecutionContext): boolean { const request = context.switchToHttp().getRequest(); return request.headers['x-api-key'] === 'my-secret-key'; } }
npm install nestjs-i18n import { I18nModule } from 'nestjs-i18n'; @Module({ imports: [ I18nModule.forRoot({ fallbackLanguage: 'en', loaderOptions: { path: path.join(__dirname, '/i18n/'), watch: true, }, }), ], }) export class AppModule {}
{ "HELLO": "Hello", "WELCOME": "Welcome to our app" }
@Get() async hello(@I18nLang() lang: string, @I18n() i18n: I18nService) { return i18n.t('HELLO', { lang }); }
// Install npm install --save @nestjs/swagger swagger-ui-express // main.ts setup import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; const config = new DocumentBuilder() .setTitle('My API') .setDescription('API description') .setVersion('1.0') .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document);
import { Controller, Get } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiResponse } from '@nestjs/swagger'; @ApiTags('cats') @Controller('cats') export class CatsController { @Get() @ApiOperation({ summary: 'Get all cats' }) @ApiResponse({ status: 200, description: 'List of cats.' }) findAll() { return []; } }
import { ApiProperty } from '@nestjs/swagger'; export class CreateCatDto { @ApiProperty({ description: 'Name of the cat' }) name: string; @ApiProperty({ description: 'Age of the cat', minimum: 0 }) age: number; }
// After setup, visit http://localhost:3000/api
npm run build node dist/main.js
# Dockerfile example FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm install --production COPY dist ./dist CMD ["node", "dist/main.js"]
// Example GitHub Actions snippet name: CI on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Setup Node uses: actions/setup-node@v2 with: node-version: '18' - run: npm install - run: npm run build - run: npm test - run: npm run deploy
ConfigModule.forRoot({ envFilePath: `.env.${process.env.NODE_ENV}`, });
import { Transport, ClientProxyFactory } from '@nestjs/microservices'; const client = ClientProxyFactory.create({ transport: Transport.TCP, options: { host: 'localhost', port: 4000 }, });
import { Controller } from '@nestjs/common'; import { MessagePattern } from '@nestjs/microservices'; @Controller() export class MathController { @MessagePattern({ cmd: 'sum' }) accumulate(data: number[]): number { return (data || []).reduce((a, b) => a + b); } }
client.send({ cmd: 'sum' }, [1, 2, 3]).subscribe(result => { console.log('Sum is', result); });
// Create monorepo nest new project-name --monorepo
// Generate library nest generate library common // Use shared code import { SharedService } from '@project/common';
// Run specific app npm run start:app1 // Build specific app npm run build:app2
@Module({}) export class DynamicModule { static forRoot(options: any): DynamicModule { return { module: DynamicModule, providers: [{ provide: 'CONFIG_OPTIONS', useValue: options }], exports: ['CONFIG_OPTIONS'], }; } }
@Injectable() export class AppService implements OnModuleInit, OnModuleDestroy { onModuleInit() { console.log('Module initialized'); } onModuleDestroy() { console.log('Module destroyed'); } }
export function Roles(...roles: string[]) { return SetMetadata('roles', roles); } @Roles('admin') @Controller('admin') export class AdminController {}
import 'reflect-metadata'; Reflect.defineMetadata('role', 'admin', AdminController); const role = Reflect.getMetadata('role', AdminController); console.log(role); // admin
@Module({ imports: [LazyModule], }) export class AppModule {} @NgModule({ imports: [RouterModule.forChild([{ path: '', component: LazyComponent }])], }) export class LazyModule {}
@Injectable() export class CacheService { private cache = new Map(); get(key: string) { return this.cache.get(key); } set(key: string, value: any) { this.cache.set(key, value); } }
const users = await userRepository.find({ where: { isActive: true }, relations: ['profile'], });
// Example with New Relic or similar tools app.use(newrelicMiddleware());
// Example folder structure by domain src/ ├── users/ │ ├── domain/ │ │ ├── entities/ │ │ │ └── user.entity.ts │ │ ├── services/ │ │ │ └── user.service.ts │ ├── application/ │ │ └── user.use-case.ts │ ├── infrastructure/ │ │ └── user.repository.ts │ └── users.module.ts
// Example of layered approach @Controller('users') export class UserController { constructor(private readonly userUseCase: UserUseCase) {} @Get(':id') getUser(@Param('id') id: string) { return this.userUseCase.execute(id); } } // Application layer export class UserUseCase { constructor(private readonly userService: UserService) {} execute(id: string) { return this.userService.findById(id); } }
src/ ├── users/ │ ├── controllers/ │ │ └── user.controller.ts │ ├── services/ │ │ └── user.service.ts │ ├── repositories/ │ │ └── user.repository.ts │ ├── dtos/ │ │ └── create-user.dto.ts │ └── entities/ │ └── user.entity.ts
// Example shared module @Module({ providers: [LoggerService], exports: [LoggerService], }) export class SharedModule {}