- 1. NestJS คืออะไร
- 2. สิ่งที่จะสร้าง
- 3. เตรียมเครื่องมือ
- 4. สร้าง DTO และตรวจสอบข้อมูล
- 5. สร้าง Service
- 6. สร้าง Controller
- 7. เปิดใช้งาน ValidationPipe
- 8. เรียกใช้งานและทดสอบ
- 9. สถาปัตยกรรมการทำงาน
- 10. แนวทางต่อยอดสำหรับ Production
- แหล่งศึกษา
#1. NestJS คืออะไร
NestJS เป็นเฟรมเวิร์กฝั่งเซิร์ฟเวอร์สำหรับ Node.js ที่ใช้ TypeScript เป็นหลัก มีโครงสร้างแบบโมดูล และใช้แนวคิด Dependency Injection ช่วยให้พัฒนาและทดสอบ API ได้เป็นระบบ โดยค่าเริ่มต้นใช้ Express และสามารถเลือก Fastify ได้
#2. สิ่งที่จะสร้าง
สร้าง Products API แบบ CRUD โดยเก็บข้อมูลในหน่วยความจำเพื่อเรียนรู้พื้นฐาน (ข้อมูลจะหายเมื่อรีสตาร์ตแอป)
| Method | Endpoint | หน้าที่ |
|---|---|---|
| GET | /products |
ดูสินค้าทั้งหมด |
| GET | /products/:id |
ดูสินค้าตาม ID |
| POST | /products |
เพิ่มสินค้า |
| PATCH | /products/:id |
แก้ไขสินค้า |
| DELETE | /products/:id |
ลบสินค้า |
#3. เตรียมเครื่องมือ
ติดตั้ง Node.js เวอร์ชัน LTS ที่ NestJS รุ่นที่ใช้งานรองรับ และ npm จากนั้นสร้างโครงการ:
npm i -g @nestjs/cli
nest new nest-products-api
cd nest-products-api
npm install class-validator class-transformer @nestjs/mapped-types
nest g module products
nest g controller products
nest g service products
#4. สร้าง DTO และตรวจสอบข้อมูล
สร้าง src/products/dto/create-product.dto.ts
import { IsNotEmpty, IsNumber, IsString, Min } from 'class-validator';
export class CreateProductDto {
@IsString()
@IsNotEmpty()
name!: string;
@IsNumber()
@Min(0)
price!: number;
}
สร้าง src/products/dto/update-product.dto.ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateProductDto } from './create-product.dto';
export class UpdateProductDto extends PartialType(CreateProductDto) {}
#5. สร้าง Service
แก้ไข src/products/products.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateProductDto } from './dto/create-product.dto';
import { UpdateProductDto } from './dto/update-product.dto';
type Product = { id: number; name: string; price: number };
@Injectable()
export class ProductsService {
private products: Product[] = [];
private nextId = 1;
findAll(): Product[] {
return this.products;
}
findOne(id: number): Product {
const product = this.products.find((item) => item.id === id);
if (!product) throw new NotFoundException(`Product ${id} not found`);
return product;
}
create(dto: CreateProductDto): Product {
const product: Product = { id: this.nextId++, ...dto };
this.products.push(product);
return product;
}
update(id: number, dto: UpdateProductDto): Product {
const product = this.findOne(id);
Object.assign(product, dto);
return product;
}
remove(id: number): void {
this.findOne(id);
this.products = this.products.filter((item) => item.id !== id);
}
}
#6. สร้าง Controller
แก้ไข src/products/products.controller.ts
import {
Body, Controller, Delete, Get, HttpCode, HttpStatus,
Param, ParseIntPipe, Patch, Post,
} from '@nestjs/common';
import { ProductsService } from './products.service';
import { CreateProductDto } from './dto/create-product.dto';
import { UpdateProductDto } from './dto/update-product.dto';
@Controller('products')
export class ProductsController {
constructor(private readonly productsService: ProductsService) {}
@Get()
findAll() { return this.productsService.findAll(); }
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.productsService.findOne(id);
}
@Post()
create(@Body() dto: CreateProductDto) {
return this.productsService.create(dto);
}
@Patch(':id')
update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateProductDto) {
return this.productsService.update(id, dto);
}
@Delete(':id')
@HttpCode(HttpStatus.NO_CONTENT)
remove(@Param('id', ParseIntPipe) id: number) {
this.productsService.remove(id);
}
}
nest g จะลงทะเบียน Controller และ Service ใน ProductsModule และเพิ่มโมดูลเข้า AppModule ตามค่าเริ่มต้นของ CLI ตรวจสอบไฟล์เหล่านี้หากใช้โครงสร้างโครงการที่ปรับแต่งเอง
#7. เปิดใช้งาน ValidationPipe
แก้ไข src/main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}));
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
#8. เรียกใช้งานและทดสอบ
npm run start:dev
เปิดเทอร์มินัลอีกหน้าต่าง:
# เพิ่มสินค้า
curl -i -X POST http://localhost:3000/products \
-H 'Content-Type: application/json' \
-d '{"name":"Keyboard","price":990}'
# แสดงทั้งหมด
curl -i http://localhost:3000/products
# แสดงรายการเดียว
curl -i http://localhost:3000/products/1
# แก้ไขราคา
curl -i -X PATCH http://localhost:3000/products/1 \
-H 'Content-Type: application/json' \
-d '{"price":890}'
# ลบสินค้า
curl -i -X DELETE http://localhost:3000/products/1
ผลลัพธ์ที่คาดหวัง: POST ได้ 201 Created, GET/PATCH สำเร็จได้ 200 OK, DELETE ได้ 204 No Content, ID ที่ไม่มีอยู่ได้ 404 Not Found, และข้อมูลไม่ผ่าน DTO ได้ 400 Bad Request
#9. สถาปัตยกรรมการทำงาน
flowchart LR
A[Client / Postman] --> B[ProductsController]
B --> C[ValidationPipe + DTO]
C --> D[ProductsService]
D --> E[(In-memory products)]
หมายเหตุ: ในการทำงานจริง
ValidationPipeตรวจสอบข้อมูลระหว่างกระบวนการรับคำขอและเรียกเมธอด Controller; แผนภาพนี้แสดงส่วนประกอบเชิงแนวคิด
#10. แนวทางต่อยอดสำหรับ Production
- ใช้ PostgreSQL ร่วมกับ Prisma หรือ TypeORM แทนการเก็บข้อมูลในหน่วยความจำ
- เพิ่ม JWT Authentication และ Role-based Authorization
- เพิ่ม Swagger/OpenAPI ด้วย
@nestjs/swagger - จัดการ Configuration ผ่าน Environment Variables และตรวจสอบค่า config
- เพิ่ม Unit Test, Integration Test และ E2E Test
- ใช้ Pagination, Logging, Rate Limiting และระบบจัดการข้อผิดพลาด
- ตรวจสอบ Dependency และใช้ HTTPS ก่อนเปิดบริการสู่สาธารณะ