8.7 KiB
8.7 KiB
Development Guide
Comprehensive standards and workflows for contributing to the GoodGo Microservices Platform.
Table of Contents
- Project Structure
- Code Standards
- Git Workflow
- Backend Development
- Testing Strategy
- Database Workflow
- 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. Noanyallowed (useunknownif 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 offdevelop).fix/xyz: Bug fixes (branch offdevelop).hotfix/xyz: Critical fixes (branch offmain).
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:#1e3a2e,color:#4ade80,stroke:#4ade80,stroke-width:3px
style Done fill:#1e3a2e,color:#4ade80,stroke:#4ade80,stroke-width:3px
style DTO fill:#1e293b,color:#60a5fa
style Repo fill:#1e293b,color:#3b82f6
style Service fill:#2e1a47,color:#a78bfa
style Controller fill:#2d1b0e,color:#fb923c
style Route fill:#1e293b,color:#3b82f6
style Middleware fill:#1e293b,color:#60a5fa
style Test fill:#1e3a2e,color:#4ade80
style ErrorCheck fill:#2d1b0e,color:#fb923c
style ThrowError fill:#3f1a1a,color:#f87171
style ErrorHandler fill:#3f1a1a,color:#f87171
style Response fill:#27272a,color:#a1a1aa
style Success fill:#1e3a2e,color:#4ade80
Creating a New API Endpoint
- 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>;
- Create Service Method (
modules/user/user.service.ts):
- Implement business logic.
- Use
BaseRepository. - Throw
HttpError(e.g.,NotFound,BadRequest).
- 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 }).
- 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:#1e3a2e,color:#4ade80
style Integration fill:#1e293b,color:#60a5fa
style E2E fill:#2e1a47,color:#a78bfa
style Code fill:#1e293b,color:#3b82f6
style CheckLint fill:#2d1b0e,color:#fb923c
style UnitPass fill:#1e3a2e,color:#4ade80
style IntPass fill:#1e293b,color:#60a5fa
style E2EPass fill:#2e1a47,color:#a78bfa
style Coverage fill:#2d1b0e,color:#fbbf24
style RunUnit fill:#1e3a2e,color:#4ade80
style RunIntegration fill:#1e293b,color:#60a5fa
style RunE2E fill:#2e1a47,color:#a78bfa
style ReadyMerge fill:#1e3a2e,color:#4ade80,stroke:#4ade80,stroke-width:3px
style FixLint fill:#3f1a1a,color:#f87171
style FixUnit fill:#3f1a1a,color:#f87171
style FixIntegration fill:#3f1a1a,color:#f87171
style FixE2E fill:#3f1a1a,color:#f87171
style AddTests fill:#2d1b0e,color:#fbbf24
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
- Modify
prisma/schema.prisma. - Create migration (Dev):
./scripts/db/migrate.sh iam-service dev --name add_user_profile
- 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.