| .. | ||
| docs | ||
| load-tests | ||
| postman | ||
| src | ||
| test | ||
| .dockerignore | ||
| .env.example | ||
| .eslintrc.js | ||
| apps.zip | ||
| DATABASE-SCHEMA.md | ||
| docker-compose.yaml | ||
| docker-entrypoint.sh | ||
| Dockerfile | ||
| fix-domain-imports.js | ||
| fix-imports.js | ||
| generate-hash.js | ||
| nest-cli.json | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| run-migrations.js | ||
| startup.js | ||
| test-csv-api.js | ||
| test-csv-api.sh | ||
| tsconfig.build.json | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
Xpeditis Backend API
NestJS-based API for the Xpeditis maritime freight booking platform, built with Hexagonal Architecture.
🏗️ Architecture
This backend follows Hexagonal Architecture (Ports & Adapters pattern):
src/
├── domain/ # 🔵 Pure business logic (NO external dependencies)
│ ├── entities/ # Business entities
│ ├── value-objects/ # Value objects (Email, PortCode, etc.)
│ ├── services/ # Domain services
│ ├── ports/
│ │ ├── in/ # API Ports (use cases exposed by domain)
│ │ └── out/ # SPI Ports (interfaces required by domain)
│ └── exceptions/ # Business exceptions
│
├── application/ # 🟢 Controllers & DTOs
│ ├── controllers/ # REST controllers
│ ├── dto/ # Data Transfer Objects
│ ├── mappers/ # DTO ↔ Domain mappers
│ └── config/ # Application configuration
│
└── infrastructure/ # 🟡 External integrations
├── persistence/ # TypeORM repositories
├── cache/ # Redis cache adapter
├── carriers/ # Maersk, MSC, CMA CGM connectors
├── email/ # Email service adapter
├── storage/ # S3 storage adapter
└── config/ # Infrastructure configuration
Key Principles
- Domain is isolated: No imports of NestJS, TypeORM, or any framework in domain layer
- Dependencies point inward: Infrastructure → Application → Domain
- Testable: Domain can be tested without any framework
- Flexible: Change database, framework, or external services without touching domain
🚀 Quick Start
Prerequisites
- Node.js 20+
- PostgreSQL 15+
- Redis 7+
- Docker (optional, for local development)
Install Dependencies
npm install
Setup Environment
cp .env.example .env
# Edit .env with your configuration
Start Development Server
npm run dev
Server runs on: http://localhost:4000
API Documentation: http://localhost:4000/api/docs
📝 Available Scripts
Development
npm run dev- Start development server with hot reloadnpm run start- Start servernpm run start:debug- Start with debuggingnpm run build- Build for productionnpm run start:prod- Start production server
Testing
npm test- Run unit testsnpm run test:watch- Run tests in watch modenpm run test:cov- Run tests with coveragenpm run test:e2e- Run end-to-end testsnpm run test:debug- Debug tests
Code Quality
npm run lint- Lint codenpm run format- Format code with Prettier
Database
npm run migration:generate -- src/infrastructure/persistence/migrations/MigrationName- Generate migrationnpm run migration:run- Run migrationsnpm run migration:revert- Revert last migration
🔑 Environment Variables
See .env.example for all available variables.
Required:
DATABASE_HOST,DATABASE_PORT,DATABASE_USER,DATABASE_PASSWORD,DATABASE_NAMEREDIS_HOST,REDIS_PORT,REDIS_PASSWORDJWT_SECRET
Optional (for production):
- OAuth credentials (Google, Microsoft)
- Carrier API keys (Maersk, MSC, CMA CGM, etc.)
- AWS S3 credentials
- Email service credentials
- Sentry DSN
📚 API Documentation
Swagger/OpenAPI documentation is available at /api/docs when the server is running.
Endpoints:
Health
GET /api/v1/health- Health checkGET /api/v1/health/ready- Readiness checkGET /api/v1/health/live- Liveness check
(More endpoints will be added in Phase 1)
🧪 Testing
Unit Tests
Test domain logic without any external dependencies:
npm test
Example (domain/services/booking.service.spec.ts):
describe('BookingService', () => {
it('should create booking with valid rate quote', () => {
const service = new BookingService(mockRepository);
const result = service.createBooking(validInput);
expect(result.bookingNumber).toMatch(/^WCM-\d{4}-[A-Z0-9]{6}$/);
});
});
Integration Tests
Test infrastructure adapters with real dependencies:
npm run test:e2e
Coverage
npm run test:cov
Targets:
- Domain: 90%+
- Application: 80%+
- Infrastructure: 70%+
🏛️ Hexagonal Architecture Guidelines
✅ DO
-
Domain layer:
- Pure TypeScript classes
- Define interfaces (ports)
- Implement business logic
- Throw domain exceptions
-
Application layer:
- Import from
@domain/*only - Validate DTOs
- Map DTOs ↔ Domain entities
- Handle HTTP-specific concerns
- Import from
-
Infrastructure layer:
- Import from
@domain/*only - Implement port interfaces
- Handle framework-specific code
- Map ORM entities ↔ Domain entities
- Import from
❌ DON'T
- Import NestJS decorators in domain
- Import TypeORM in domain
- Put business logic in controllers
- Put business logic in repositories
- Use
anytype - Skip tests
🔒 Security
- Passwords hashed with bcrypt (12 rounds)
- JWT tokens (access: 15min, refresh: 7 days)
- Helmet.js for security headers
- CORS configured
- Rate limiting enabled
- Input validation with class-validator
- SQL injection prevention (TypeORM)
- XSS protection
📊 Logging
Using Pino logger with structured JSON logs.
Log levels:
- Development:
debug - Production:
info
Pretty print in development with pino-pretty.
🚢 Carrier Integrations
MVP supports these carriers:
- Maersk
- MSC
- CMA CGM
- Hapag-Lloyd
- ONE (Ocean Network Express)
Each connector implements CarrierConnectorPort with:
- Circuit breaker (5s timeout)
- Retry logic
- Rate limiting
- Error normalization
📖 Further Reading
- CLAUDE.md - Complete architecture guidelines
- TODO.md - Development roadmap
- SPRINT-0-FINAL.md - Sprint 0 completion
🤝 Contributing
- Follow hexagonal architecture principles
- Write tests (domain: 90%+, application: 80%+)
- Use TypeScript strict mode
- Format with Prettier
- Lint with ESLint
- Document API with Swagger decorators
📝 License
Proprietary - All rights reserved
Built with ❤️ using NestJS and Hexagonal Architecture