Folder Structure
Karma Ecommerce follows a feature-based modular architecture where each feature is organized into Domain, Application, and Infrastructure layers.Complete Directory Tree
Root Level Structure
Application Files
main.ts
Application entry point that bootstraps the Angular app
app.config.ts
Application-wide configuration (providers, routes, HTTP client)
app.routes.ts
Top-level routing configuration
app.ts
Root component of the application
Configuration Example
src/app/app.config.ts
Feature Module Structure
Each feature (e.g.,usuario) follows the same three-layer structure.
The Usuario Module
Theusuario module handles user authentication and registration. It demonstrates the complete clean architecture pattern:
Domain Layer
The innermost layer with no dependencies on frameworks or outer layers.Structure
Models
Domain entities represent core business concepts:src/app/usuario/domain/models/usuario.ts
- Pure TypeScript interfaces or classes
- No framework imports
- Represent business entities
- Contain validation rules (when applicable)
Repository Interfaces
Define contracts for data access:src/app/usuario/domain/repositories/usuario.repository.ts
Repositories are abstract classes (not interfaces) to work with Angular’s dependency injection system.
Application Layer
Orchestrates use cases using domain objects and repository interfaces.Structure
Commands (Write Operations)
Represent intent to change state:src/app/usuario/application/commands/register-user.command.ts
{Verb}{Entity}Command
RegisterUserCommandUpdateProfileCommandDeleteAccountCommand
Queries (Read Operations)
Represent requests for data:src/app/usuario/application/queries/login-user.query.ts
{Verb}{Entity}Query
LoginUserQueryGetUserProfileQueryListUsersQuery
Command Handlers
Execute write operations:src/app/usuario/application/usecases/commandHandlers/register-user.handler.ts
- Injectable for dependency injection
- Depends on repository interface (not implementation)
- Single responsibility: one handler per command
- Returns Observable for async operations
Query Handlers
Execute read operations:src/app/usuario/application/usecases/queryHandlers/login-user.handler.ts
Infrastructure Layer
Handles all external dependencies and framework-specific code.Structure
Services
Implement repository interfaces with concrete technology:src/app/usuario/infrastructure/services/auth-service.ts
- Implements
UsuarioRepositoryinterface - Uses Angular’s
HttpClientfor HTTP calls - Provided in root for singleton pattern
- Can be easily swapped with different implementation
UI Components
Angular components for presentation:src/app/usuario/infrastructure/ui/pages/register-page/register-page.ts
- Each page has 4 files:
.ts,.html,.css,.spec.ts - Components are in
ui/pages/directory - Use services (not handlers directly) for simplicity
- Handle UI concerns (loading states, errors, validation)
Naming Conventions
Files
| Type | Pattern | Example |
|---|---|---|
| Command | {verb}-{entity}.command.ts | register-user.command.ts |
| Query | {verb}-{entity}.query.ts | login-user.query.ts |
| Handler | {verb}-{entity}.handler.ts | register-user.handler.ts |
| Repository | {entity}.repository.ts | usuario.repository.ts |
| Model | {entity}.ts | usuario.ts |
| Service | {name}-service.ts | auth-service.ts |
| Component | {name}-page.ts | register-page.ts |
Classes
| Type | Pattern | Example |
|---|---|---|
| Command | {Verb}{Entity}Command | RegisterUserCommand |
| Query | {Verb}{Entity}Query | LoginUserQuery |
| Handler | {Verb}{Entity}Handler | RegisterUserHandler |
| Repository | {Entity}Repository | UsuarioRepository |
| Service | {Name}Service | AuthService |
| Component | {Name}Page | RegisterPage |
Directory Responsibilities
domain/models/
domain/models/
Purpose: Define business entities and value objectsContains:
- Interfaces or classes for entities
- Value objects
- Domain types
- No framework imports
- Pure TypeScript
- No business logic (entities are data structures)
domain/repositories/
domain/repositories/
Purpose: Define contracts for data accessContains:
- Abstract classes or interfaces
- Method signatures for data operations
- Abstract classes (for Angular DI)
- No implementation details
- Return types use domain models
application/commands/
application/commands/
Purpose: Represent write operationsContains:
- Command classes
- Immutable data structures
- Readonly properties
- No business logic
- Verb-based naming
application/queries/
application/queries/
Purpose: Represent read operationsContains:
- Query classes
- Search/filter parameters
- Readonly properties
- No business logic
- Verb-based naming
application/usecases/commandHandlers/
application/usecases/commandHandlers/
Purpose: Execute commandsContains:
- Handler classes
- Command execution logic
- One handler per command
- Use repository interfaces
- Injectable services
application/usecases/queryHandlers/
application/usecases/queryHandlers/
Purpose: Execute queriesContains:
- Handler classes
- Query execution logic
- One handler per query
- Use repository interfaces
- Injectable services
infrastructure/services/
infrastructure/services/
Purpose: Implement repository interfacesContains:
- Service classes
- HTTP client code
- External API integrations
- Implement repository interfaces
- Use Angular HttpClient
- Handle errors and transformations
infrastructure/ui/pages/
infrastructure/ui/pages/
Purpose: User interface componentsContains:
- Angular components
- Templates and styles
- Component tests
- One component per feature/page
- 4 files per component (ts, html, css, spec)
- Use services for data access
Adding a New Feature
When adding a new feature (e.g.,producto for products), follow this structure:
Testing Structure
Each layer has corresponding test files:- Unit tests for services and handlers
- Component tests for UI
- Mock repositories in handler tests
- Use TestBed for Angular component tests
Best Practices
Keep Layers Separate
Never import from outer layers into inner layersInfrastructure → Application → Domain ✓Domain → Infrastructure ✗
Single Responsibility
Each file should have one clear purposeOne command per file ✓Multiple commands in one file ✗
Consistent Naming
Follow naming conventions strictly
register-user.command.ts ✓userRegister.cmd.ts ✗Colocate Tests
Keep tests next to implementation
auth-service.spec.ts next to auth-service.ts ✓Common Patterns
Import Paths
Relative imports respect layer boundaries:Barrel Exports (Optional)
Createindex.ts files for cleaner imports:
src/app/usuario/domain/index.ts
Next Steps
Clean Architecture
Understand the architectural principles
Architecture Overview
See the high-level architecture diagram
