Summary
NestJS is a progressive Node.js framework built with TypeScript that provides a robust foundation for building scalable server-side applications. Inspired by Angular's architecture, it combines elements of OOP, FP, and FRP. This cheatsheet covers core NestJS concepts including modules, controllers, providers, dependency injection, middleware, guards, pipes, interceptors, exception handling, database integration with TypeORM, authentication with Passport, testing strategies, microservices, and best practices for enterprise-grade applications.
1. Introduction & Core Concepts
What is NestJS?
- Progressive Node.js framework built with TypeScript
- Uses Express/Fastify under the hood
- Inspired by Angular's architecture
- Follows SOLID principles and MVC pattern
Key Features
- Modular Architecture: Organize code into modules
- Dependency Injection: IoC container manages dependencies
- Decorators: TypeScript decorators for metadata
- Platform Agnostic: Works with Express, Fastify, etc.
2. Project Setup
# Install CLI
npm i -g @nestjs/cli
# Create new project
nest new project-name
# Generate resources
nest g module users
nest g controller users
nest g service users
3. Controllers
Basic Controller
@Controller('users')
export class UsersController {
@Get()
findAll(): string {
return 'All users';
}
@Get(':id')
findOne(@Param('id') id: string): string {
return `User ${id}`;
}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return 'User created';
}
@Put(':id')
update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {
return `Updated user ${id}`;
}
@Delete(':id')
remove(@Param('id') id: string) {
return `Removed user ${id}`;
}
}
Request Decorators
@Param()- Route parameters@Query()- Query parameters@Body()- Request body@Headers()- Request headers@Req()- Full request object@Res()- Response object
4. Providers/Services
Basic Service
@Injectable()
export class UsersService {
private users = [];
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find(user => user.id === id);
}
create(user: any) {
this.users.push(user);
return user;
}
}
Dependency Injection
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
}
5. Modules
Module Structure
@Module({
imports: [DatabaseModule], // Other modules
controllers: [UsersController], // Controllers
providers: [UsersService], // Services/Providers
exports: [UsersService] // Exported providers
})
export class UsersModule {}
Root Module
@Module({
imports: [UsersModule, ProductsModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
6. Middleware
Custom Middleware
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
}
}
// Apply in module
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*');
}
}
7. Guards
Authorization Guard
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}
// Usage
@Controller('users')
@UseGuards(AuthGuard)
export class UsersController {}
8. Interceptors
Response Transform Interceptor
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map(data => ({ data, timestamp: new Date().toISOString() }))
);
}
}
// Usage
@UseInterceptors(TransformInterceptor)
@Controller('users')
export class UsersController {}
9. Pipes
Validation Pipe
// DTO with class-validator
export class CreateUserDto {
@IsString()
@IsNotEmpty()
name: string;
@IsEmail()
email: string;
@IsInt()
@Min(0)
age: number;
}
// Global validation pipe
app.useGlobalPipes(new ValidationPipe());
// Controller method
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
Custom Pipe
@Injectable()
export class ParseIntPipe implements PipeTransform<string, number> {
transform(value: string): number {
const val = parseInt(value, 10);
if (isNaN(val)) {
throw new BadRequestException('Validation failed');
}
return val;
}
}
10. Exception Filters
Custom Exception Filter
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
message: exception.message,
});
}
}
// Usage
@UseFilters(HttpExceptionFilter)
@Controller('users')
export class UsersController {}
11. Database Integration
TypeORM Setup
// app.module.ts
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'test',
password: 'test',
database: 'test',
entities: [User],
synchronize: true,
}),
UsersModule,
],
})
export class AppModule {}
Entity
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column({ unique: true })
email: string;
@CreateDateColumn()
createdAt: Date;
}
Repository Pattern
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
findAll(): Promise<User[]> {
return this.usersRepository.find();
}
findOne(id: number): Promise<User> {
return this.usersRepository.findOne({ where: { id } });
}
create(user: CreateUserDto): Promise<User> {
return this.usersRepository.save(user);
}
}
12. Authentication
JWT Strategy
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'secret',
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
// Auth Service
@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService
) {}
async login(user: any) {
const payload = { username: user.username, sub: user.userId };
return {
access_token: this.jwtService.sign(payload),
};
}
}
13. Testing
Unit Testing
describe('UsersService', () => {
let service: UsersService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService],
}).compile();
service = module.get<UsersService>(UsersService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should create a user', () => {
const user = { name: 'John', email: 'john@example.com' };
expect(service.create(user)).toEqual(user);
});
});
E2E Testing
describe('UsersController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/users (GET)', () => {
return request(app.getHttpServer())
.get('/users')
.expect(200)
.expect([]);
});
});
14. Advanced Concepts
Custom Decorators
// Create decorator
export const User = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
},
);
// Usage
@Get('profile')
getProfile(@User() user: UserEntity) {
return user;
}
Dynamic Modules
@Module({})
export class ConfigModule {
static forRoot(options: ConfigOptions): DynamicModule {
return {
module: ConfigModule,
providers: [
{
provide: 'CONFIG_OPTIONS',
useValue: options,
},
ConfigService,
],
exports: [ConfigService],
};
}
}
Microservices
// Main.ts for microservice
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
AppModule,
{
transport: Transport.TCP,
options: {
host: '127.0.0.1',
port: 8877,
},
},
);
// Message pattern
@MessagePattern('sum')
accumulate(data: number[]): number {
return data.reduce((a, b) => a + b);
}
15. Best Practices
1. Use DTOs for Type Safety
export class CreateUserDto {
@IsString()
name: string;
@IsEmail()
email: string;
}
2. Implement Error Handling
@Get(':id')
async findOne(@Param('id') id: string) {
const user = await this.usersService.findOne(id);
if (!user) {
throw new NotFoundException('User not found');
}
return user;
}
3. Use Configuration Module
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
}),
],
})
export class AppModule {}
4. Implement Logging
@Injectable()
export class MyService {
private readonly logger = new Logger(MyService.name);
doSomething() {
this.logger.log('Doing something...');
}
}
5. Use Async/Await
@Get()
async findAll(): Promise<User[]> {
return await this.usersService.findAll();
}
16. Key Concepts & Comparisons
NestJS Component Hierarchy & Execution Order
| Order | Component | Purpose | Access | Return Type |
|---|---|---|---|---|
| 1 | Middleware | Request preprocessing | req/res objects | void |
| 2 | Guards | Authentication/Authorization | ExecutionContext | boolean/Promise |
| 3 | Interceptors (Before) | Pre-processing, logging | ExecutionContext, CallHandler | Observable |
| 4 | Pipes | Validation, transformation | Input value | Transformed value |
| 5 | Route Handler | Business logic | Processed inputs | Response data |
| 6 | Interceptors (After) | Post-processing, formatting | Response data | Modified response |
| 7 | Exception Filters | Error handling | Exception, ArgumentsHost | Error response |
Middleware vs Guards vs Interceptors
| Aspect | Middleware | Guards | Interceptors |
|---|---|---|---|
| Execution Time | Before all NestJS components | After middleware, before handler | Before and after handler |
| Access to | req, res, next | ExecutionContext | ExecutionContext, CallHandler |
| Primary Use | Request parsing, logging, CORS | Authentication, authorization | Transform data, logging, caching |
| Return Type | void (calls next()) | boolean | Observable |
| Can Modify Response | Yes (via res object) | No | Yes (via Observable operators) |
| Error Handling | Manual try-catch | Throw exceptions | Automatic via Observable |
Dependency Injection Scopes
| Scope | Lifecycle | Use Case | Memory Impact | Example |
|---|---|---|---|---|
| Singleton | One instance per application | Stateless services, utilities | Low | Database connections, configs |
| Request | New instance per request | Request-specific data | Medium | User context, request logging |
| Transient | New instance every time injected | Stateful operations | High | File processors, calculators |
Provider Registration Patterns
| Pattern | Syntax | Use Case | Benefits |
|---|---|---|---|
| Class Provider | providers: [UserService] |
Standard service injection | Type safety, automatic instantiation |
| Value Provider | { provide: 'CONFIG', useValue: config } |
Constants, configuration | Simple value injection |
| Factory Provider | { provide: 'DB', useFactory: createDB } |
Dynamic creation logic | Runtime configuration |
| Async Provider | { provide: 'ASYNC', useFactory: async () => {...} } |
Async initialization | Database connections |
Module Types & Organization
| Module Type | Purpose | Characteristics | Example |
|---|---|---|---|
| Feature Module | Business domain logic | Encapsulates related functionality | UsersModule, OrdersModule |
| Shared Module | Common functionality | Exported providers for reuse | DatabaseModule, ConfigModule |
| Core Module | App-wide singletons | Global providers, typically imported once | AuthModule, LoggerModule |
| Dynamic Module | Configurable modules | Runtime configuration | ConfigModule.forRoot(options) |
HTTP Decorators & Use Cases
| Decorator | HTTP Method | Idempotent | Safe | Use Case |
|---|---|---|---|---|
@Get() |
GET | Yes | Yes | Retrieve data |
@Post() |
POST | No | No | Create resources |
@Put() |
PUT | Yes | No | Update/replace resource |
@Patch() |
PATCH | No | No | Partial update |
@Delete() |
DELETE | Yes | No | Remove resource |
@Options() |
OPTIONS | Yes | Yes | Preflight requests |
@Head() |
HEAD | Yes | Yes | Metadata only |
Parameter Decorators
| Decorator | Source | Type | Example Usage |
|---|---|---|---|
@Param() |
URL path | Route parameters | @Param('id') id: string |
@Query() |
Query string | Query parameters | @Query('search') search: string |
@Body() |
Request body | JSON payload | @Body() createDto: CreateUserDto |
@Headers() |
HTTP headers | Header values | @Headers('authorization') auth: string |
@Req() |
Express request | Full request object | @Req() request: Request |
@Res() |
Express response | Full response object | @Res() response: Response |
Validation Strategies
| Strategy | Implementation | Pros | Cons | Use Case |
|---|---|---|---|---|
| Class Validator | DTO with decorators | Type-safe, declarative | Additional dependency | API input validation |
| Joi Schema | Schema objects | Flexible, runtime | No compile-time checking | Configuration validation |
| Custom Pipes | Manual validation logic | Full control | More code | Complex business rules |
| Transform Pipes | Built-in transformations | Simple, fast | Limited functionality | Type conversion |
Error Handling Patterns
| Pattern | Implementation | Use Case | Benefits |
|---|---|---|---|
| Built-in Exceptions | throw new NotFoundException() |
Standard HTTP errors | Consistent response format |
| Custom Exceptions | Extend HttpException |
Business-specific errors | Domain-specific messaging |
| Exception Filters | @Catch() decorator |
Cross-cutting error handling | Centralized error processing |
| Global Filters | app.useGlobalFilters() |
Application-wide handling | Consistent error responses |
Database Integration Patterns
| Pattern | ORM | Implementation | Use Case |
|---|---|---|---|
| Repository Pattern | TypeORM | @InjectRepository() |
Standard CRUD operations |
| Active Record | TypeORM | Entity methods | Simple operations |
| Query Builder | TypeORM | Fluent API | Complex queries |
| Raw Queries | TypeORM | SQL strings | Performance-critical operations |
| Mongoose | Mongoose | Schema-based | MongoDB integration |
Authentication Strategies
| Strategy | Implementation | Use Case | Security Level |
|---|---|---|---|
| JWT | @nestjs/jwt + Passport |
Stateless API auth | High |
| Session | Express sessions | Web applications | Medium |
| OAuth2 | Passport strategies | Third-party auth | High |
| API Keys | Custom guards | Service-to-service | Medium |
| Basic Auth | Passport basic | Simple scenarios | Low |
Testing Strategies
| Test Type | Scope | Tools | Focus |
|---|---|---|---|
| Unit Tests | Individual components | Jest, Testing module | Business logic |
| Integration Tests | Module interactions | TestingModule | Component integration |
| E2E Tests | Full application | Supertest | User workflows |
| Contract Tests | API contracts | Pact, OpenAPI | API compatibility |
Performance Optimization Techniques
| Technique | Implementation | Impact | Use Case |
|---|---|---|---|
| Caching | @nestjs/cache-manager |
High | Frequent data access |
| Compression | Middleware | Medium | Reduce bandwidth |
| Rate Limiting | @nestjs/throttler |
Security/Performance | API protection |
| Database Indexing | ORM configuration | High | Query optimization |
| Connection Pooling | Database config | Medium | Concurrent requests |
| Lazy Loading | Dynamic imports | Medium | Startup time |
Microservices Communication
| Transport | Protocol | Use Case | Characteristics |
|---|---|---|---|
| TCP | TCP sockets | High performance | Fast, binary protocol |
| Redis | Pub/Sub | Scalable messaging | Message queuing |
| NATS | NATS protocol | Cloud-native | Lightweight, resilient |
| RabbitMQ | AMQP | Enterprise messaging | Reliable, feature-rich |
| gRPC | HTTP/2 | Service mesh | Type-safe, efficient |
Security Best Practices Implementation
| Security Aspect | NestJS Implementation | Purpose |
|---|---|---|
| Input Validation | ValidationPipe with class-validator | Prevent injection attacks |
| Rate Limiting | ThrottlerModule | Prevent abuse |
| CORS | Enable CORS middleware | Control cross-origin requests |
| Helmet | Security headers middleware | Protect against attacks |
| Authentication | Guards with Passport | Verify user identity |
| Authorization | Role-based guards | Control resource access |
| HTTPS | Express/Fastify configuration | Encrypt data in transit |
Quick Reference & Best Practices
Essential NestJS CLI Commands
| Command | Description | Example |
|---|---|---|
nest new <name> |
Create new project | nest new my-app |
nest g module <name> |
Generate module | nest g module users |
nest g controller <name> |
Generate controller | nest g controller users |
nest g service <name> |
Generate service | nest g service users |
nest g guard <name> |
Generate guard | nest g guard auth |
nest g pipe <name> |
Generate pipe | nest g pipe validation |
nest g filter <name> |
Generate exception filter | nest g filter http-exception |
nest g interceptor <name> |
Generate interceptor | nest g interceptor transform |
nest g middleware <name> |
Generate middleware | nest g middleware logger |
nest g decorator <name> |
Generate custom decorator | nest g decorator user |
Core Decorators Reference
| Category | Decorator | Purpose | Example |
|---|---|---|---|
| Class | @Controller(path) |
Define controller | @Controller('users') |
| Class | @Injectable() |
Mark as injectable service | @Injectable() |
| Class | @Module(metadata) |
Define module | @Module({ imports: [...] }) |
| Method | @Get(path) |
Handle GET requests | @Get(':id') |
| Method | @Post(path) |
Handle POST requests | @Post() |
| Method | @Put(path) |
Handle PUT requests | @Put(':id') |
| Method | @Delete(path) |
Handle DELETE requests | @Delete(':id') |
| Parameter | @Body() |
Extract request body | @Body() dto: CreateUserDto |
| Parameter | @Param(key) |
Extract route parameter | @Param('id') id: string |
| Parameter | @Query(key) |
Extract query parameter | @Query('search') search: string |
| Enhancement | @UseGuards(guard) |
Apply guard | @UseGuards(AuthGuard) |
| Enhancement | @UseInterceptors(interceptor) |
Apply interceptor | @UseInterceptors(LoggingInterceptor) |
TypeORM Entity Quick Reference
@Entity('users')
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column()
name: string;
@Column({ nullable: true })
profilePicture?: string;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@OneToMany(() => Order, order => order.user)
orders: Order[];
@ManyToOne(() => Role, role => role.users)
role: Role;
}
Validation Pipe Configuration
// Global validation setup
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // Strip non-whitelisted properties
forbidNonWhitelisted: true, // Throw error for non-whitelisted properties
transform: true, // Auto-transform payloads to DTO instances
transformOptions: {
enableImplicitConversion: true, // Allow type conversion
},
}));
// DTO with validation decorators
export class CreateUserDto {
@IsString()
@IsNotEmpty()
@Length(2, 50)
name: string;
@IsEmail()
email: string;
@IsOptional()
@IsString()
@Length(8, 100)
password?: string;
@IsInt()
@Min(18)
@Max(120)
age: number;
@IsArray()
@ArrayNotEmpty()
@IsString({ each: true })
roles: string[];
}
Security Implementation Checklist
// 1. Enable CORS
app.enableCors({
origin: ['http://localhost:3000'],
credentials: true,
});
// 2. Add security headers
app.use(helmet());
// 3. Rate limiting
app.use(
rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
}),
);
// 4. Global validation
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
transform: true,
}));
// 5. Authentication guard
@UseGuards(JwtAuthGuard)
@Controller('protected')
export class ProtectedController {}
// 6. Role-based authorization
@Roles('admin')
@UseGuards(JwtAuthGuard, RolesGuard)
@Delete(':id')
deleteUser() {}
Error Handling Best Practices
// Custom business exception
export class UserAlreadyExistsException extends ConflictException {
constructor(email: string) {
super(`User with email ${email} already exists`);
}
}
// Global exception filter
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
private readonly logger = new Logger(AllExceptionsFilter.name);
catch(exception: unknown, host: ArgumentsHost): void {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
let status = HttpStatus.INTERNAL_SERVER_ERROR;
let message = 'Internal server error';
if (exception instanceof HttpException) {
status = exception.getStatus();
message = exception.message;
}
this.logger.error(`${request.method} ${request.url}`, exception);
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
message,
});
}
}
Testing Patterns
// Unit test with mocked dependencies
describe('UsersService', () => {
let service: UsersService;
let repository: Repository<User>;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: getRepositoryToken(User),
useValue: {
find: jest.fn(),
findOne: jest.fn(),
save: jest.fn(),
delete: jest.fn(),
},
},
],
}).compile();
service = module.get<UsersService>(UsersService);
repository = module.get<Repository<User>>(getRepositoryToken(User));
});
it('should find all users', async () => {
const users = [{ id: 1, name: 'John' }];
jest.spyOn(repository, 'find').mockResolvedValue(users);
expect(await service.findAll()).toEqual(users);
});
});
// Integration test
describe('UsersController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/users (POST)', () => {
return request(app.getHttpServer())
.post('/users')
.send({ name: 'John', email: 'john@example.com' })
.expect(201);
});
});
Performance Optimization Strategies
// 1. Caching with Redis
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
@Inject(CACHE_MANAGER)
private cacheManager: Cache,
) {}
async findOne(id: number): Promise<User> {
const cacheKey = `user:${id}`;
const cached = await this.cacheManager.get<User>(cacheKey);
if (cached) {
return cached;
}
const user = await this.usersRepository.findOne({ where: { id } });
await this.cacheManager.set(cacheKey, user, { ttl: 300 });
return user;
}
}
// 2. Database query optimization
@Injectable()
export class UsersService {
async getUsersWithOrders(): Promise<User[]> {
return this.usersRepository.find({
relations: ['orders'],
select: ['id', 'name', 'email'], // Only select needed fields
take: 50, // Limit results
});
}
}
// 3. Async initialization
@Injectable()
export class DatabaseService implements OnModuleInit {
async onModuleInit() {
await this.connect();
}
private async connect() {
// Async initialization logic
}
}
Configuration Management
// config/configuration.ts
export default () => ({
port: parseInt(process.env.PORT, 10) || 3000,
database: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
name: process.env.DATABASE_NAME,
},
jwt: {
secret: process.env.JWT_SECRET,
expiresIn: process.env.JWT_EXPIRES_IN || '1h',
},
});
// app.module.ts
@Module({
imports: [
ConfigModule.forRoot({
load: [configuration],
isGlobal: true,
validationSchema: Joi.object({
NODE_ENV: Joi.string().valid('development', 'production', 'test').required(),
PORT: Joi.number().default(3000),
DATABASE_HOST: Joi.string().required(),
JWT_SECRET: Joi.string().required(),
}),
}),
],
})
export class AppModule {}
Essential Package Dependencies
{
"dependencies": {
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/config": "^3.0.0",
"@nestjs/typeorm": "^10.0.0",
"@nestjs/jwt": "^10.0.0",
"@nestjs/passport": "^10.0.0",
"@nestjs/swagger": "^7.0.0",
"class-validator": "^0.14.0",
"class-transformer": "^0.5.0",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"typeorm": "^0.3.0",
"pg": "^8.11.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
"@nestjs/testing": "^10.0.0",
"@types/jest": "^29.5.0",
"@types/supertest": "^2.0.12",
"jest": "^29.5.0",
"supertest": "^6.3.0",
"ts-jest": "^29.1.0"
}
}
Deployment Best Practices
// main.ts - Production configuration
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Security
app.enableCors();
app.use(helmet());
// Validation
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
transform: true,
}));
// Global exception filter
app.useGlobalFilters(new AllExceptionsFilter());
// API documentation
if (process.env.NODE_ENV !== 'production') {
const config = new DocumentBuilder()
.setTitle('API Documentation')
.setVersion('1.0')
.addBearerAuth()
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
}
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('SIGTERM received');
app.close();
});
await app.listen(process.env.PORT || 3000);
}
bootstrap();
Key Interview Topics Summary
- Architecture: Modular design, dependency injection, decorators
- Request Lifecycle: Middleware → Guards → Interceptors → Pipes → Handler
- Database Integration: TypeORM patterns, repository usage, migrations
- Authentication: JWT strategies, guards, role-based access control
- Testing: Unit tests with mocking, integration tests, e2e testing
- Performance: Caching strategies, database optimization, async patterns
- Security: Input validation, rate limiting, security headers
- Microservices: Transport layers, message patterns, service communication