NestJSAdvanced
Real-world NestJS Project
পূর্ণ Blog API — modules, auth, relations, guards, swagger সহ project বাংলায়।
14টি অংশবাংলা ভাষায়
চলুন একটি Blog API project বানাই — যা একটি realistic NestJS application-এর সব layers দেখাবে।
Setup & Generate
nest new blog-api
cd blog-api
npm i @nestjs/mongoose mongoose @nestjs/config bcryptjs @nestjs/jwt class-validator class-transformer
npm i -D @types/bcryptjs
nest g module auth
nest g module users
nest g module posts
nest g module posts
nest g resource posts --no-spec # controller+service+module+DTO
nest g controller auth --no-spec
nest g service auth --no-spec
nest g service users --no-specPost Schema
src/posts/schemas/post.schema.tstypescript
typescript
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Types } from "mongoose";
@Schema({ timestamps: true })
export class Post {
@Prop({ required: true, trim: true })
title: string;
@Prop({ required: true })
content: string;
@Prop({ type: Types.ObjectId, ref: "User", required: true })
author: Types.ObjectId;
}
export const PostSchema = SchemaFactory.createForClass(Post);Post DTO (Create)
src/posts/dto/create-post.dto.tstypescript
typescript
import { ApiProperty } from "@nestjs/swagger";
import { IsString, MinLength } from "class-validator";
export class CreatePostDto {
@ApiProperty({ example: "My first post" })
@IsString()
@MinLength(3)
title: string;
@ApiProperty({ example: "Content here..." })
@IsString()
@MinLength(10)
content: string;
}Post Service
src/posts/posts.service.tstypescript
typescript
import { Injectable, NotFoundException } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { Post } from "./schemas/post.schema";
import { CreatePostDto } from "./dto/create-post.dto";
import { UpdatePostDto } from "./dto/update-post.dto";
@Injectable()
export class PostsService {
constructor(@InjectModel(Post.name) private postModel: Model<Post>) {}
async create(dto: CreatePostDto, authorId: string) {
const post = await this.postModel.create({ ...dto, author: authorId });
return post.populate("author", "name email");
}
async findAll() {
return this.postModel.find().populate("author", "name email").sort("-createdAt");
}
async findOne(id: string) {
const post = await this.postModel.findById(id).populate("author", "name");
if (!post) throw new NotFoundException("Post পাওয়া যায়নি");
return post;
}
async update(id: string, authorId: string, dto: UpdatePostDto) {
const post = await this.postModel.findOneAndUpdate(
{ _id: id, author: authorId }, // owner only
dto,
{ new: true },
);
if (!post) throw new NotFoundException("Post খুঁজে পাওয়া যায়নি বা অনুমতি নেই");
return post;
}
async remove(id: string, authorId: string) {
const post = await this.postModel.findOneAndDelete({ _id: id, author: authorId });
if (!post) throw new NotFoundException("Post খুঁজে পাওয়া যায়নি");
}
}Post Controller (protected)
src/posts/posts.controller.tstypescript
typescript
import { Body, Controller, Delete, Get, Param, Post, Put, Req, UseGuards } from "@nestjs/common";
import { ApiBearerAuth, ApiTags } from "@nestjs/swagger";
import { JwtAuthGuard } from "../common/guards/jwt-auth.guard";
import { PostsService } from "./posts.service";
@ApiTags("posts")
@Controller("posts")
export class PostsController {
constructor(private readonly postsService: PostsService) {}
@Get()
findAll() {
return this.postsService.findAll();
}
@Get(":id")
findOne(@Param("id") id: string) {
return this.postsService.findOne(id);
}
@Post()
@UseGuards(JwtAuthGuard) // author দরকার → protected
@ApiBearerAuth()
create(@Body() dto: CreatePostDto, @Req() req: any) {
return this.postsService.create(dto, req.user.sub);
}
@Put(":id")
@UseGuards(JwtAuthGuard)
update(@Param("id") id: string, @Body() dto: UpdatePostDto, @Req() req) {
return this.postsService.update(id, req.user.sub, dto);
}
@Delete(":id")
@UseGuards(JwtAuthGuard)
remove(@Param("id") id: string, @Req() req) {
return this.postsService.remove(id, req.user.sub);
}
}Test Flow
npm run start:dev
# 1. register/login → token
POST /api/v1/auth/login
JSON: { email, password }
→ { access_token }
# 2. create post (Authorized)
POST /api/v1/posts
Authorization: Bearer <token>
JSON: { "title": "হ্যালো", "content": "বিস্তারিত..." }
# 3. list
GET /api/v1/posts
# 4. swagger docs
GET /api → OpenAPI UI
আরও প্রসারিত
Tags (categories), comments, likes, pagination, refresh token — আস্তে আস্তে যোগ করুন। প্রতিটি feature user-ভিত্তিক authorization মনে রাখুন।
শেষ প্যারায় নিজে practice করুন — কোড কপি করে নিজের এডিটরে চালিয়ে দেখুন।