Skip to content

Backend Architecture (NestJS)

apps/api คือ NestJS 11 REST API monolith ที่ลงทะเบียน 20 feature modules ไว้ใน AppModule — ทุก module เป็น self-contained (controller + service + DTOs) และ communicate กันผ่าน DI

High-Level Architecture

HTTP Request


┌────────────────────┐
│  Express adapter   │  ← from @nestjs/platform-express
└────────┬───────────┘

┌────────────────────┐
│  CORS middleware   │  main.ts — auto-allow *.pages.dev + explicit list
└────────┬───────────┘

┌────────────────────┐
│  Global Guards     │  JwtAuthGuard (default), ApiKeyGuard (integration only)
└────────┬───────────┘

┌────────────────────┐
│  RolesGuard        │  @RequireModule / @Roles → check user.adminModules*
└────────┬───────────┘

┌────────────────────┐
│  Interceptors      │  IdempotencyInterceptor (integration only)
└────────┬───────────┘

┌────────────────────┐
│  ValidationPipe    │  class-validator → 400 if DTO fails
└────────┬───────────┘

┌────────────────────┐
│  Controller        │  thin — delegates to service
└────────┬───────────┘

┌────────────────────┐
│  Service           │  business logic + PrismaService calls
└────────┬───────────┘

┌────────────────────┐
│  PrismaClient      │  PostgreSQL (pooled via PgBouncer)
└────────────────────┘

Module Registry

จาก apps/api/src/app.module.ts — ลงทะเบียน 20 modules:

#ModulePathบทบาท
1PrismaModuleinfrastructure/prismaGlobal PrismaService — DI ทุก module
2HealthModulemodules/health/health/live, /health/ready, /health/stats
3AuthModulemodules/authlogin/register/me + JWT strategy + guards
4MasterDataModulemodules/master-dataitems, locations, partners, uoms, warehouses (5 controllers)
5InboundModulemodules/inboundasn, grn, putaway, putaway-rules
6InventoryModulemodules/inventorystock, movements, adjustments, cycle-counts
7OutboundModulemodules/outboundorders, waves, pick-tasks, shipments
8ReturnsModulemodules/returnsrma
9ConfigWmsModulemodules/configsystem config keys (8-tab settings)
10WebhookModulemodules/webhookwebhook subscriptions + deliveries
11AuditModulemodules/auditaudit log query
12FilesModulemodules/filesR2 presigned uploads
13ApprovalsModulemodules/approvalsthreshold-based approval queue
14ReplenishmentModulemodules/replenishmentmin/max rules + tasks
15UsersModulemodules/usersuser CRUD + permissions
16AnnouncementsModulemodules/announcementsbanner messages
17ApiKeysModulemodules/api-keysAPI key CRUD + stats + IP/origin/rate config
18ReportsModulemodules/reports22 aggregated GET endpoints
19IntegrationModulemodules/integration/integration/v1/* push API
20LpnModulemodules/lpnLicense Plate CRUD + movements

ดูรายละเอียดทุก module: Module Reference

Module Folder Convention

modules/<feature>/
├─ <feature>.module.ts        # @Module — imports + providers + controllers
├─ <feature>.controller.ts    # routes + decorators
├─ <feature>.service.ts       # business logic
└─ dto/
   ├─ create-<feature>.dto.ts
   └─ update-<feature>.dto.ts

ตัวอย่างจริง (modules/auth/):

auth/
├─ auth.module.ts
├─ auth.controller.ts
├─ auth.service.ts
├─ auth.service.spec.ts        ← unit test (Jest)
├─ dto/
│  ├─ login.dto.ts
│  └─ register.dto.ts
├─ guards/
│  ├─ jwt-auth.guard.ts
│  ├─ api-key.guard.ts
│  ├─ roles.guard.ts
│  ├─ api-key-rate-limit.ts
│  └─ ip-cidr.util.ts
├─ decorators/
│  ├─ public.decorator.ts        ← @Public() bypass JWT
│  ├─ current-user.decorator.ts  ← @CurrentUser() param
│  ├─ roles.decorator.ts         ← @Roles('admin', …)
│  ├─ require-module.decorator.ts← @RequireModule('items', 'write')
│  └─ api-key.decorator.ts       ← @ApiKey() + @ApiKeyScopes(…)
├─ interfaces/
│  └─ jwt-payload.interface.ts
└─ strategies/
   └─ jwt.strategy.ts

โมดูลที่มี sub-controllers (master-data, inbound, inventory, outbound, returns) จะ nest อีกชั้นเช่น inbound/asn/, inbound/grn/, inbound/putaway/

Global Pipes

จาก main.ts:

typescript
app.useGlobalPipes(new ValidationPipe({
  whitelist: true,              // strip props ไม่อยู่ใน DTO
  forbidNonWhitelisted: true,   // ตอบ 400 ถ้ามี extra props
  transform: true,              // string → number / Date / class instance
}));

ผลคือทุก DTO ที่ใช้ class-validator decorators (@IsString, @IsUUID, @IsEmail, …) จะถูก validate อัตโนมัติ

Guards

JwtAuthGuard

  • ใช้กับทุก route ยกเว้น ที่ติด @Public() decorator
  • อ่าน Bearer token จาก Authorization header → verify ด้วย JWT_SECRET
  • Attach payload ไว้ที่ request.user

ApiKeyGuard

  • ใช้กับ /integration/v1/* เท่านั้น (controller-level @UseGuards)
  • อ่าน X-API-Key หรือ Authorization: ApiKey …
  • SHA-256 hash → lookup ที่ api_key table
  • เช็คตามลำดับ: validity → IP whitelist (exact + CIDR) → allowed origins (CORS) → rate limit (sliding 60s)
  • Attach ApiKey record ที่ request.apiKey

RolesGuard

  • ทำงานหลัง JwtAuthGuard
  • Admin / superadmin → bypass ทุกอย่าง
  • เช็ค @Roles('manager', 'supervisor') หรือ @RequireModule('items', 'write') กับ user.adminModules / user.adminModulesWrite

ดูเต็ม: Authorization

Interceptors

IdempotencyInterceptor (modules/integration/idempotency.interceptor.ts)

  • รัน เฉพาะ integration controller
  • ถ้า request มี Idempotency-Key header:
    1. คำนวณ SHA-256 ของ body
    2. lookup integration_request ด้วย (tenantId, idempotencyKey, endpoint)
    3. ถ้าเจอ + body hash ตรง → replay cached response (header Idempotent-Replay: true)
    4. ถ้าเจอ + body hash ไม่ตรง → 409 IDEMPOTENCY_KEY_MISMATCH
    5. ถ้าไม่เจอ → run handler + บันทึก response
  • TTL: 24 ชั่วโมง

Error Handling

  • NestJS built-in HttpException ครอบ standard codes (400 BadRequestException, 401 UnauthorizedException, 403 ForbiddenException, 404 NotFoundException, 409 ConflictException)
  • ValidationPipe throw BadRequestException พร้อม messages: string[]
  • Custom error codes (เช่น IDEMPOTENCY_KEY_MISMATCH) ใช้ throw HttpException({ code, message }, status) ตรง ๆ
  • ยังไม่มี global ExceptionFilter — error format ใช้ค่า default ของ NestJS

Logging

  • ใช้ Logger ของ Nest (new Logger(ClassName.name))
  • Print ไป stdout — Render.com capture log อัตโนมัติ
  • Bootstrap log: WMS API [<NODE_ENV>] listening on port <PORT>
  • Auth, ApiKeyGuard log สำคัญทุกอัน (login success/failed, key validation, rate limit hit)

Where to find…

สิ่งที่ต้องการpath
HTTP route definitionssrc/modules/*/*.controller.ts
Business logicsrc/modules/*/*.service.ts
Validation rulessrc/modules/*/dto/*.dto.ts (class-validator decorators)
Database queriesservice files (PrismaService)
Database schemaprisma/schema.prisma
Auth logicsrc/modules/auth/auth.service.ts
Permission checksrc/modules/auth/guards/roles.guard.ts
Env validationsrc/app.module.ts (Joi schema)
Bootstrap configsrc/main.ts

เผยแพร่ภายใต้ Digital Outsourcing