A comprehensive Domain-Driven Design (DDD) implementation in TypeScript and Node.js, following hexagonal architecture principles and CQRS patterns.
This project demonstrates advanced DDD concepts including:
- Domain-Driven Design: Clear separation of domain, application, and infrastructure layers
- CQRS: Command Query Responsibility Segregation with separate buses
- Event-Driven Architecture: Domain events with RabbitMQ support
- Hexagonal Architecture: Clean architecture with dependency inversion
- Dependency Injection: IoC container with YAML configuration
- Testing Strategy: Unit tests with Jest and BDD with Cucumber
- Runtime: Node.js (>=14.0.0)
- Language: TypeScript (^4.4.3)
- DI Container: Node Dependency Injection
- Message Broker: RabbitMQ with amqp-connection-manager
- Database: MongoDB (^3.5.2)
- Web Framework: Express.js (^4.17.1)
- Testing: Jest + Cucumber
- Code Quality: Prettier + Husky pre-commit hooks
- Node.js >= 14.0.0
- npm >= 6.14.0
- Docker and Docker Compose (for MongoDB and RabbitMQ)
-
Clone the repository
git clone https://github.com/mayalaat/node-typescript-ddd.git cd node-typescript-ddd
-
Install dependencies
npm install
-
Start infrastructure services
docker-compose up -d
This starts:
- MongoDB on port 27017
- RabbitMQ on port 5672 (management UI on 15672)
-
Configure RabbitMQ
npm run command:mooc:rabbitmq
npm run dev:mooc:backend
The API will be available at http://localhost:3000
PUT /courses
Content-Type: application/json
{
"id": "course-uuid",
"name": "Course Name",
"duration": "10 hours"
}
GET /courses_counter
GET /status
npm run build # Full build (clean + compile + copy assets)
npm run build:tsc # TypeScript compilation only
npm run build:clean # Clean dist directory
npm test # Run all tests
npm run test:unit # Unit tests only (Jest)
npm run test:features # Feature tests only (Cucumber)
npm run test:mooc:backend:features # Backend feature tests
npm run lint # Format code with Prettier
src/
βββ Contexts/ # Bounded Contexts
β βββ Mooc/ # Main business context
β β βββ Courses/ # Course aggregate
β β βββ CoursesCounter/ # Counter aggregate
β βββ Shared/ # Shared kernel
β βββ domain/ # Base classes and interfaces
β βββ infrastructure/ # Shared infrastructure
βββ apps/
βββ mooc/
βββ backend/ # Express application
βββ controllers/ # HTTP controllers
βββ routes/ # Route definitions
βββ config/ # Application configuration
- Commands: Modify state through
CommandBus
- Queries: Read data through
QueryBus
- Separate handlers for each command/query
- Aggregates extend
AggregateRoot
- Events are recorded and published after successful operations
- Supports both in-memory and RabbitMQ event buses
- Encapsulate business rules and validation
- Extend base classes:
StringValueObject
,IntValueObject
,Uuid
- Abstract repositories in domain layer
- Concrete implementations in infrastructure
- Support for MongoDB and file-based storage
The application uses YAML configuration for dependency injection:
# Environment-specific configuration files
βββ application_dev.yaml # Development environment
βββ application_production.yaml # Production environment
βββ application_test.yaml # Test environment
Services are organized by bounded context and automatically wired based on configuration.
- Domain logic testing with mocks
- Test doubles follow
*Mock.ts
and*Mother.ts
patterns - Located in
tests/
directory mirroring source structure
- BDD scenarios in Gherkin syntax
- End-to-end API testing
- Located in
tests/apps/mooc/backend/features/
# Run tests for specific bounded context
npm run test:unit -- --testPathPattern=Courses
# Run single feature file
npx cucumber-js tests/apps/mooc/backend/features/courses/create-course.feature
The application uses environment-specific configuration:
NODE_ENV=dev
- Development (default)NODE_ENV=test
- TestingNODE_ENV=production
- Production
Configuration is managed through convict
with JSON files in /config/
.
Use the provided docker-compose.yml
for local development:
docker-compose up -d # Start services in background
docker-compose down # Stop and remove containers
docker-compose logs -f # Follow logs
- Fork the repository
- Create a feature branch
- Make your changes following the existing patterns
- Ensure tests pass:
npm test
- Format code:
npm run lint
- Submit a pull request
The project uses Husky pre-commit hooks to ensure code quality.
This project is part of a Domain-Driven Design course and is for educational purposes.