NestJS Framework - Enterprise Node.js Development
NestJS হলো একটি progressive Node.js framework যা TypeScript-first এবং enterprise-level applications তৈরির জন্য ডিজাইন করা।
কেন NestJS?
Express এর সমস্যা:
- কোনো standard structure নেই
- TypeScript support limited
- Dependency injection নেই
- Testing করা কঠিন
- Large applications এ messy হয়ে যায়
NestJS এর সুবিধা:
- ✅ TypeScript-first (built with TypeScript)
- ✅ Angular-inspired architecture
- ✅ Built-in Dependency Injection
- ✅ Modular architecture
- ✅ Powerful CLI
- ✅ Built-in testing support
- ✅ Microservices ready
- ✅ GraphQL, WebSockets support
- ✅ Excellent documentation
Installation & Setup
bash
# Install NestJS CLI globally
npm install -g @nestjs/cli
# Create new project
nest new my-project
# Navigate to project
cd my-project
# Start development server
npm run start:devProject Structure
src/
├── app.controller.ts # Controller
├── app.service.ts # Service (Business logic)
├── app.module.ts # Root module
└── main.ts # Entry pointCore Concepts
1. Controllers
Controllers handle incoming requests এবং responses return করে।
typescript
// cats.controller.ts
import { Controller, Get, Post, Body, Param } from "@nestjs/common";
import { CatsService } from "./cats.service";
import { CreateCatDto } from "./dto/create-cat.dto";
@Controller("cats")
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Post()
create(@Body() createCatDto: CreateCatDto) {
return this.catsService.create(createCatDto);
}
@Get()
findAll() {
return this.catsService.findAll();
}
@Get(":id")
findOne(@Param("id") id: string) {
return this.catsService.findOne(+id);
}
}2. Services (Providers)
Services contain business logic।
typescript
// cats.service.ts
import { Injectable } from "@nestjs/common";
import { Cat } from "./interfaces/cat.interface";
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
create(cat: Cat) {
this.cats.push(cat);
return cat;
}
findAll(): Cat[] {
return this.cats;
}
findOne(id: number): Cat {
return this.cats.find((cat) => cat.id === id);
}
}3. Modules
Modules organize code into cohesive blocks।
typescript
// cats.module.ts
import { Module } from "@nestjs/common";
import { CatsController } from "./cats.controller";
import { CatsService } from "./cats.service";
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService], // Export to use in other modules
})
export class CatsModule {}4. DTOs (Data Transfer Objects)
typescript
// dto/create-cat.dto.ts
export class CreateCatDto {
name: string;
age: number;
breed: string;
}Dependency Injection
NestJS এর সবচেয়ে powerful feature।
typescript
// users.service.ts
@Injectable()
export class UsersService {
findAll() {
return ["user1", "user2"];
}
}
// auth.service.ts
@Injectable()
export class AuthService {
constructor(private usersService: UsersService) {} // Automatic injection
validateUser(username: string) {
const users = this.usersService.findAll();
return users.includes(username);
}
}Validation with Pipes
bash
npm install class-validator class-transformertypescript
// dto/create-user.dto.ts
import { IsString, IsInt, IsEmail, MinLength } from "class-validator";
export class CreateUserDto {
@IsString()
@MinLength(3)
name: string;
@IsEmail()
email: string;
@IsInt()
age: number;
}typescript
// main.ts
import { ValidationPipe } from "@nestjs/common";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe()); // Enable validation globally
await app.listen(3000);
}Guards (Authentication)
typescript
// auth.guard.ts
import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return this.validateRequest(request);
}
private validateRequest(request: any): boolean {
// Your authentication logic
return request.headers.authorization !== undefined;
}
}typescript
// Using guard
@Controller("cats")
@UseGuards(AuthGuard)
export class CatsController {
// All routes protected
}Interceptors
Request/Response transformation এর জন্য।
typescript
// logging.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from "@nestjs/common";
import { Observable } from "rxjs";
import { tap } from "rxjs/operators";
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
console.log("Before...");
const now = Date.now();
return next
.handle()
.pipe(tap(() => console.log(`After... ${Date.now() - now}ms`)));
}
}Database Integration (TypeORM)
bash
npm install @nestjs/typeorm typeorm mysql2typescript
// app.module.ts
import { TypeOrmModule } from "@nestjs/typeorm";
@Module({
imports: [
TypeOrmModule.forRoot({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "password",
database: "test",
entities: [User],
synchronize: true,
}),
],
})
export class AppModule {}typescript
// user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@Column()
email: string;
}typescript
// users.service.ts
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { User } from "./user.entity";
@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.findOneBy({ id });
}
async create(user: User): Promise<User> {
return this.usersRepository.save(user);
}
}Prisma Integration
bash
npm install @prisma/client
npm install -D prisma
npx prisma inittypescript
// prisma.service.ts
import { Injectable, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
}Configuration
bash
npm install @nestjs/configtypescript
// app.module.ts
import { ConfigModule } from "@nestjs/config";
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
],
})
export class AppModule {}typescript
// Using config
import { ConfigService } from "@nestjs/config";
@Injectable()
export class AppService {
constructor(private configService: ConfigService) {}
getDatabaseHost(): string {
return this.configService.get<string>("DATABASE_HOST");
}
}Testing
typescript
// cats.service.spec.ts
import { Test, TestingModule } from "@nestjs/testing";
import { CatsService } from "./cats.service";
describe("CatsService", () => {
let service: CatsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [CatsService],
}).compile();
service = module.get<CatsService>(CatsService);
});
it("should be defined", () => {
expect(service).toBeDefined();
});
it("should return all cats", () => {
const result = service.findAll();
expect(result).toEqual([]);
});
});CLI Commands
bash
# Generate module
nest generate module cats
# Generate controller
nest generate controller cats
# Generate service
nest generate service cats
# Generate complete resource (CRUD)
nest generate resource cats
# Build
npm run build
# Start production
npm run start:prodBest Practices
- Module Organization: Feature-based modules
- DTOs: Always use DTOs for validation
- Services: Keep business logic in services
- Guards: Use for authentication/authorization
- Interceptors: For logging, transformation
- Pipes: For validation and transformation
- Exception Filters: For custom error handling
TIP
NestJS শেখার সবচেয়ে ভালো উপায় হলো official documentation follow করা এবং একটা complete CRUD application তৈরি করা।