Files
pos-system/docs/en/guides/development.md
Ho Ngoc Hai 92d14877e5 feat(docs): Revise Vietnamese and English development guides with enhanced structure and clarity
- Updated the introductory notes in both Vietnamese and English development guides for improved clarity.
- Reorganized the workflow steps in the Vietnamese documentation to align with the English version.
- Added detailed Mermaid diagrams for better visualization of development processes and testing strategies.
- Introduced new sections for color palette references and verification checklists to enhance documentation completeness.
- Simplified headers and improved formatting for better readability across both language versions.
2026-01-08 15:57:09 +07:00

9.4 KiB

Development Guide

Comprehensive standards and workflows for contributing to the GoodGo Microservices Platform

Table of Contents

  1. Project Structure
  2. Code Standards
  3. Git Workflow
  4. Backend Development
  5. Testing Strategy
  6. Database Workflow
  7. Kubernetes Deployment

Project Structure

We follow a strict monorepo structure managed by PNPM Workspaces.

Base/
├── apps/                 # Frontend applications
│   ├── web-client/       # Next.js 14+ (App Router)
│   └── mobile-client/    # Flutter
├── services/             # Backend microservices
│   ├── _template/        # Template for new services
│   ├── iam-service/      # Identity & Access Management
│   └── ...
├── packages/             # Shared libraries
│   ├── logger/           # Structured logging (Winston)
│   ├── types/            # Shared DTOs & Interfaces
│   ├── http-client/      # Internal Service Client
│   └── tracing/          # OpenTelemetry configuration
├── infra/                # Infrastructure-as-Code
│   ├── traefik/          # API Gateway
│   └── databases/        # Database setup scripts
└── docs/                 # Documentation (EN & VI)

Code Standards

Naming Conventions

  • Files: kebab-case.ts (e.g., user.controller.ts, app.config.ts)
  • Classes: PascalCase (e.g., UserController, AuthService)
  • Functions/Variables: camelCase (e.g., getUserById, isValid)
  • Constants: UPPER_SNAKE_CASE (e.g., MAX_RETRIES, DEFAULT_TIMEOUT)
  • Interfaces: PascalCase (e.g., User, CreateUserDto) - No 'I' prefix

Bilingual Comments

For core logic and public APIs, assume both international and Vietnamese developers reading the code.

/**
 * EN: Validates user credentials and returns a token
 * VI: Xác thực thông tin người dùng và trả về token
 */
async login(dto: LoginDto): Promise<TokenResponse> { ... }

TypeScript Usage

  • Strict Mode: Enabled in tsconfig.json. No any allowed (use unknown if needed).
  • DTOs: Use Zod for runtime validation and type inference.
  • Return Types: Explicitly declare return types for all public methods.

Git Workflow

Branching Strategy

  • main: Production-ready code.
  • develop: Integration branch for next release.
  • feature/xyz: New features (branch off develop).
  • fix/xyz: Bug fixes (branch off develop).
  • hotfix/xyz: Critical fixes (branch off main).
gitGraph
    commit id: "Initial"
    branch develop
    checkout develop
    commit id: "Setup"
    
    branch feature/login
    checkout feature/login
    commit id: "Add login form"
    commit id: "Add validation"
    checkout develop
    merge feature/login
    
    branch feature/dashboard
    checkout feature/dashboard
    commit id: "Create dashboard"
    checkout develop
    
    checkout main
    merge develop tag: "v1.0.0"
    
    checkout develop
    merge feature/dashboard
    
    checkout main
    branch hotfix/security
    commit id: "Fix security issue"
    checkout main
    merge hotfix/security tag: "v1.0.1"
    checkout develop
    merge hotfix/security

Commit Messages

We follow Conventional Commits:

feat(iam): add multi-factor authentication
fix(db): correct unique constraint on email
docs(guide): update development setup
style: format code with prettier
refactor: simplify auth middleware
test: add unit tests for user service
chore: update dependencies

Backend Development

graph TD
    Start([Start Creating New API]) --> DTO[1. Define DTO - Zod Schema]
    DTO --> Repo[2. Create Repository Method]
    Repo --> Service[3. Create Service Method - Business Logic]
    Service --> Controller[4. Create Controller - HTTP Handler]
    Controller --> Route[5. Register Route - Express Router]
    Route --> Middleware[6. Add Middlewares]
    Middleware --> Test[7. Write Tests]
    Test --> Done([API Complete])
    
    Service --> ErrorCheck{Has Error?}
    ErrorCheck -->|Yes| ThrowError[Throw HttpError]
    ThrowError --> ErrorHandler[Global Error Handler]
    ErrorHandler --> Response[Error Response]
    ErrorCheck -->|No| Success[Success Response]
    
    style Start fill:#27AE60,color:#fff,stroke:#27AE60,stroke-width:2px
    style Done fill:#27AE60,color:#fff,stroke:#27AE60,stroke-width:2px
    style DTO fill:#3498DB,color:#fff
    style Repo fill:#2980B9,color:#fff
    style Service fill:#8E44AD,color:#fff
    style Controller fill:#E67E22, color:#fff
    style Route fill:#2980B9,color:#fff
    style Middleware fill:#3498DB,color:#fff
    style Test fill:#27AE60,color:#fff
    style ErrorCheck fill:#E67E22,color:#fff
    style ThrowError fill:#C0392B,color:#fff
    style ErrorHandler fill:#C0392B,color:#fff
    style Response fill:#7F8C8D,color:#fff
    style Success fill:#27AE60,color:#fff

Creating a New API Endpoint

  1. Define DTO (modules/user/user.dto.ts):

    export const CreateUserDto = z.object({
      email: z.string().email(),
      name: z.string().min(2),
    });
    export type CreateUserDto = z.infer<typeof CreateUserDto>;
    
  2. Create Service Method (modules/user/user.service.ts):

    • Implement business logic.
    • Use BaseRepository.
    • Throw HttpError (e.g., NotFound, BadRequest).
  3. Create Controller (modules/user/user.controller.ts):

    • Parse body with DTO: const dto = CreateUserDto.parse(req.body).
    • Call service.
    • Return success response: res.json({ success: true, data: result }).
  4. Register Route (modules/user/index.ts):

    • Add to Express router with middlewares.

Error Handling

Always use the custom error classes from core/errors:

import { NotFoundError, ConflictError } from '../../core/errors';

if (!user) {
  throw new NotFoundError('User not found');
}

Testing Strategy

graph TB
    subgraph "Testing Pyramid - Bottom to Top"
        Unit[Unit Tests - Most, Fastest]
        Integration[Integration Tests - Medium]
        E2E[E2E Tests - Least, Slowest]
    end
    
    Code[Code Changes] --> CheckLint{Lint Pass?}
    CheckLint -->|No| FixLint[Fix Linting Errors]
    FixLint --> CheckLint
    CheckLint -->|Yes| RunUnit[Run Unit Tests]
    
    RunUnit --> UnitPass{Unit Tests Pass?}
    UnitPass -->|No| FixUnit[Fix Unit Tests]
    FixUnit --> RunUnit
    UnitPass -->|Yes| RunIntegration[Run Integration Tests]
    
    RunIntegration --> IntPass{Integration Pass?}
    IntPass -->|No| FixIntegration[Fix Integration]
    FixIntegration --> RunIntegration
    IntPass -->|Yes| RunE2E[Run E2E Tests]
    
    RunE2E --> E2EPass{E2E Pass?}
    E2EPass -->|No| FixE2E[Fix E2E]
    FixE2E --> RunE2E
    E2EPass -->|Yes| Coverage{Coverage > 70%?}
    
    Coverage -->|No| AddTests[Add More Tests]
    AddTests --> RunUnit
    Coverage -->|Yes| ReadyMerge[Ready to Merge]
    
    style Unit fill:#27AE60,color:#fff
    style Integration fill:#3498DB,color:#fff
    style E2E fill:#8E44AD,color:#fff
    style Code fill:#2980B9,color:#fff
    style CheckLint fill:#E67E22,color:#fff
    style UnitPass fill:#27AE60,color:#fff
    style IntPass fill:#3498DB,color:#fff
    style E2EPass fill:#8E44AD,color:#fff
    style Coverage fill:#F39C12,color:#fff
    style RunUnit fill:#27AE60,color:#fff
    style RunIntegration fill:#3498DB,color:#fff
    style RunE2E fill:#8E44AD,color:#fff
    style ReadyMerge fill:#27AE60,color:#fff,stroke:#27AE60,stroke-width:2px
    style FixLint fill:#C0392B,color:#fff
    style FixUnit fill:#C0392B,color:#fff
    style FixIntegration fill:#C0392B,color:#fff
    style FixE2E fill:#C0392B,color:#fff
    style AddTests fill:#F39C12,color:#fff

Unit Tests (*.test.ts)

  • Scope: Individual classes/functions.
  • Mocking: Mock all external dependencies (DB, other services) using jest-mock-extended.
  • Location: Co-located with source files.
  • Run: pnpm test

E2E Tests (tests/**/*.e2e.ts)

  • Scope: Full API flows (Controller -> Service -> DB).
  • Database: Use a separate test database (Dockerized).
  • Run: pnpm test:e2e

Linting & Formatting

  • Lint: pnpm lint (ESLint)
  • Format: pnpm format (Prettier)
  • Typecheck: pnpm typecheck (TSC)

Database Workflow

We use Prisma with Neon PostgreSQL.

Migrations

  1. Modify prisma/schema.prisma.
  2. Create migration (Dev):
    ./scripts/db/migrate.sh iam-service dev --name add_user_profile
    
  3. Apply to Production (CI/CD):
    ./scripts/db/migrate.sh iam-service deploy
    

Seed Data

Populate database with initial data:

./scripts/db/seed.sh iam-service

Visualizing Data

Use Prisma Studio:

pnpm --filter @goodgo/iam-service prisma studio

Kubernetes Deployment

For local Kubernetes testing (Docker Desktop / Minikube):

# 1. Build images
docker build -t goodgo/iam-service:latest -f services/iam-service/Dockerfile .

# 2. Deploy
cd deployments/local/kubernetes
./deploy.sh

# 3. Verify
kubectl get pods -n iam-local
kubectl logs -f -l app=iam-service -n iam-local

See Kubernetes Guide for detailed setup.