Development Guide¶
Table of Contents¶
- Local Development Setup
- Running Services
- Code Quality
- Database Management
- RabbitMQ Management
- Debugging
- Testing
- Common Workflows
Local Development Setup¶
Prerequisites¶
- Node.js 20.x or higher
- pnpm 8.x or higher (recommended) or npm
- Docker & Docker Compose (for infrastructure)
Installation¶
1. Install Node.js¶
Download from nodejs.org or use nvm:
2. Install pnpm¶
3. Clone Repository¶
4. Install Dependencies¶
Install dependencies for all services:
# Auth Service
cd auth
pnpm install
cd ..
# Wallet Service
cd wallet
pnpm install
cd ..
# Transactions Service
cd transactions
pnpm install
cd ..
# Notifications Service
cd notifications
pnpm install
cd ..
Tip: Create a script to install all at once:
#!/bin/bash
# install-all.sh
for service in auth wallet transactions notifications; do
echo "Installing $service..."
cd $service
pnpm install
cd ..
done
5. Setup Environment Files¶
# Copy example files
for service in auth wallet transactions notifications; do
cp $service/.env.example $service/.env.local
done
Edit .env.local files with local development settings:
# Use localhost instead of Docker service names
DATABASE_URL=mongodb://root:example@localhost:27017/auth_db?authSource=admin
RABBITMQ_URL=amqp://guest:guest@localhost:5672
JWKS_URI=http://localhost:4001/.well-known/jwks.json
Running Services¶
Option 1: Full Docker (Recommended for Quick Start)¶
Run everything in Docker:
Pros: - Everything configured and working - Hot-reload enabled - Consistent environment
Cons: - Slower to restart services - Harder to debug
Option 2: Hybrid (Infrastructure in Docker, Services Local)¶
Run infrastructure in Docker, services locally:
1. Start Infrastructure¶
2. Run Services Locally¶
Open 4 terminals and run:
# Terminal 1 - Auth Service
cd auth
pnpm dev
# Terminal 2 - Wallet Service
cd wallet
pnpm dev
# Terminal 3 - Transactions Service
cd transactions
pnpm dev
# Terminal 4 - Notifications Service
cd notifications
pnpm dev
Pros: - Fast hot-reload - Easy debugging with breakpoints - Direct access to logs
Cons: - More terminal windows - Manual service management
Development Scripts¶
Each service has these scripts:
# Development with hot-reload
pnpm dev
# Build TypeScript
pnpm build
# Run production build
pnpm start
# Lint code
pnpm lint
# Format code
pnpm format
# Type check (without building)
pnpm type-check
Code Quality¶
Linting¶
All services use ESLint with TypeScript rules:
Formatting¶
Format code with Prettier:
Type Checking¶
Pre-commit Hook (Optional)¶
Install husky for automatic checks:
# In project root
pnpm install -D husky lint-staged
# Setup husky
npx husky install
# Add pre-commit hook
npx husky add .husky/pre-commit "pnpm lint-staged"
.lintstagedrc.json:
Database Management¶
Access MongoDB¶
Via Docker¶
Via Local Client¶
Common MongoDB Commands¶
// List databases
show dbs
// Switch to database
use auth_db
// List collections
show collections
// View users
db.users.find().pretty()
// Find specific user
db.users.findOne({ email: "john@example.com" })
// Update user
db.users.updateOne(
{ email: "john@example.com" },
{ $set: { name: "John Updated" } }
)
// Delete user
db.users.deleteOne({ email: "test@example.com" })
// View wallets
use wallet_db
db.wallets.find().pretty()
// View transactions
use transactions_db
db.transactions.find().pretty()
Reset Database¶
# Stop services
docker compose down
# Remove volumes (deletes all data)
docker compose down -v
# Restart
docker compose up
Seed Test Data¶
Create a seed script:
// scripts/seed.ts
import mongoose from 'mongoose';
import { User } from '../src/models/User';
async function seed() {
await mongoose.connect('mongodb://root:example@localhost:27017/auth_db?authSource=admin');
// Create test users
await User.create([
{
name: 'Alice',
email: 'alice@example.com',
password: 'password123' // Will be hashed by model
},
{
name: 'Bob',
email: 'bob@example.com',
password: 'password123'
}
]);
console.log('Seed data created');
await mongoose.disconnect();
}
seed();
Run seed script:
RabbitMQ Management¶
Access Management UI¶
Open http://localhost:15672
Credentials:
- Username: guest
- Password: guest
Management UI Features¶
- Queues: View queue depths, message rates
- Exchanges: View bindings and routing
- Connections: Active connections from services
- Channels: Open channels per connection
Useful Operations¶
View Queue Messages¶
- Go to "Queues" tab
- Click on queue name
- Scroll to "Get messages"
- Click "Get Message(s)"
Purge Queue¶
# Via UI: Queues → Queue Name → Purge
# Via CLI
docker exec mint-rabbitmq rabbitmqadmin purge queue name=email.signup.q
Publish Test Message¶
# Via CLI
docker exec mint-rabbitmq rabbitmqadmin publish \
exchange=auth.events \
routing_key=user.signup \
payload='{"userId":"123","email":"test@example.com"}'
Monitor Events¶
Watch RabbitMQ logs to see event flow:
Debugging¶
VS Code Debug Configuration¶
.vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Auth Service",
"type": "node",
"request": "launch",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev"],
"cwd": "${workspaceFolder}/auth",
"skipFiles": ["<node_internals>/**"],
"envFile": "${workspaceFolder}/auth/.env.local"
},
{
"name": "Debug Wallet Service",
"type": "node",
"request": "launch",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev"],
"cwd": "${workspaceFolder}/wallet",
"skipFiles": ["<node_internals>/**"],
"envFile": "${workspaceFolder}/wallet/.env.local"
}
]
}
Debugging Tips¶
1. Add Breakpoints¶
In VS Code, click left of line number to add breakpoint.
2. Console Logging¶
console.log('Variable value:', variable);
// Better: Use logger
import { logger } from './utils/logger';
logger.debug('Debugging info', { variable });
3. Inspect Events¶
Log RabbitMQ events:
// In consumer
channel.consume(queue, async (msg) => {
const data = JSON.parse(msg.content.toString());
console.log('Received event:', data); // Debug log
await processEvent(data);
});
4. Check Service Logs¶
# All services
docker compose logs -f
# Specific service
docker compose logs -f auth
# Filter by error
docker compose logs | grep ERROR
Testing¶
Manual API Testing¶
Using cURL¶
# Register user
curl -X POST http://localhost/api/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{
"name": "Test User",
"email": "test@example.com",
"password": "password123"
}'
# Login
curl -X POST http://localhost/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "password123"
}' \
-c cookies.txt
# Get wallet
curl http://localhost/api/v1/wallet/user -b cookies.txt
# Top-up
curl -X POST http://localhost/api/v1/transactions/topup \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"amount": 100, "description": "Test"}'
Using Postman¶
- Import collection from
postman/mint-collection.json(create if needed) - Set environment variables
- Use saved requests
Using httpie¶
# More readable than curl
http POST localhost/api/v1/auth/signup \
name="Test User" \
email="test@example.com" \
password="password123"
Integration Testing¶
Run end-to-end flow:
#!/bin/bash
# test-flow.sh
# 1. Register
RESPONSE=$(curl -s -X POST http://localhost/api/v1/auth/signup \
-H "Content-Type: application/json" \
-d '{"name":"Test","email":"test@example.com","password":"pass123"}')
echo "Register: $RESPONSE"
# 2. Login
curl -s -X POST http://localhost/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"pass123"}' \
-c cookies.txt > /dev/null
# 3. Check wallet
WALLET=$(curl -s http://localhost/api/v1/wallet/user -b cookies.txt)
echo "Wallet: $WALLET"
# 4. Top-up
curl -s -X POST http://localhost/api/v1/transactions/topup \
-H "Content-Type: application/json" \
-b cookies.txt \
-d '{"amount":100}' > /dev/null
# 5. Wait for processing
sleep 2
# 6. Check balance
UPDATED=$(curl -s http://localhost/api/v1/wallet/user -b cookies.txt)
echo "Updated wallet: $UPDATED"
Common Workflows¶
Adding a New Feature¶
-
Create feature branch
-
Make changes in appropriate service(s)
-
Test locally
-
Lint and format
-
Commit and push
Adding a New Endpoint¶
-
Define route in
src/routers/ -
Create controller in
src/controllers/ -
Add validation schema in
src/schemas/ -
Test endpoint
Adding a New Event¶
-
Define event publisher in publishing service
-
Add consumer in consuming service
-
Register consumer in RabbitMQ setup
-
Test event flow
- Trigger publisher
- Check RabbitMQ UI
- Verify consumer processes
Fixing a Bug¶
-
Reproduce the bug locally
-
Add debugging
-
Identify root cause
-
Fix and verify
-
Add test to prevent regression
Project Structure¶
Service Structure¶
service/
├── src/
│ ├── controllers/ # Request handlers
│ ├── middleware/ # Auth, error handling
│ ├── models/ # Database models
│ ├── routers/ # Express routes
│ ├── schemas/ # Zod validation
│ ├── services/ # Business logic
│ ├── utils/ # Helpers (logger, jwt)
│ ├── rabbitmq/ # RabbitMQ setup
│ ├── consumers/ # Event consumers (if applicable)
│ ├── app.ts # Express app setup
│ ├── env.ts # Environment validation
│ └── server.ts # Entry point
├── keys/ # JWT keys (auth only)
├── Dockerfile
├── package.json
├── tsconfig.json
└── .env.example
Adding New Files¶
Follow existing patterns:
- Controllers: Handle HTTP requests
- Services: Business logic
- Models: Database schemas
- Schemas: Input validation
- Utils: Shared utilities
Useful Commands¶
Docker¶
# View logs
docker compose logs -f <service>
# Restart service
docker compose restart <service>
# Rebuild service
docker compose up -d --build <service>
# Access service shell
docker exec -it mint-<service> sh
Database¶
# Access MongoDB
docker exec -it mint-mongodb mongosh -u root -p example
# Backup database
docker exec mint-mongodb mongodump --uri="mongodb://root:example@localhost:27017" --out=/backup
# Restore database
docker exec mint-mongodb mongorestore --uri="mongodb://root:example@localhost:27017" /backup
RabbitMQ¶
# List queues
docker exec mint-rabbitmq rabbitmqctl list_queues
# List exchanges
docker exec mint-rabbitmq rabbitmqctl list_exchanges
# Purge queue
docker exec mint-rabbitmq rabbitmqadmin purge queue name=<queue-name>
Environment Variables Reference¶
Create .env.local for each service with these settings:
# Common (all services)
NODE_ENV=development
PORT=<service-port>
# Database (auth, wallet, transactions)
DATABASE_URL=mongodb://root:example@localhost:27017/<db-name>?authSource=admin
# RabbitMQ (all services)
RABBITMQ_URL=amqp://guest:guest@localhost:5672
# JWT (wallet, transactions)
JWT_ISSUER=mint-auth-service
JWT_AUDIENCE=mint-api
JWKS_URI=http://localhost:4001/.well-known/jwks.json
# SMTP (notifications)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
Related Documentation¶
- Architecture Overview - System design
- Deployment Guide - Production deployment
- API Documentation - API reference
- Troubleshooting - Common issues