Files
puaros/packages/guardian/examples/good-architecture/dependency-direction/GoodDomainLayer.ts
imfozilbek 3fecc98676 feat: add dependency direction enforcement (v0.4.0)
Implement dependency direction detection to enforce Clean Architecture rules:
- Domain layer can only import from Domain and Shared
- Application layer can only import from Domain, Application, and Shared
- Infrastructure layer can import from all layers
- Shared layer can be imported by all layers

Added:
- IDependencyDirectionDetector interface in domain layer
- DependencyViolation value object with detailed suggestions and examples
- DependencyDirectionDetector implementation in infrastructure
- Integration with AnalyzeProject use case
- New DEPENDENCY_DIRECTION rule in constants
- 43 comprehensive tests covering all scenarios (100% passing)
- Good and bad examples in examples directory

Improvements:
- Optimized extractLayerFromImport method to reduce complexity
- Fixed indentation in DependencyGraph.ts
- Updated getExampleFix to avoid false positives in old detector

Test Results:
- All 261 tests passing
- Build successful
- Self-check: 0 architecture violations in src code
2025-11-24 18:31:41 +05:00

57 lines
1.3 KiB
TypeScript

/**
* ✅ GOOD: Domain layer with correct dependencies
*
* Domain should only import from:
* - Other domain files
* - Shared utilities
*
* Domain should NOT import from:
* - Application layer
* - Infrastructure layer
*/
import { Email } from "../domain/value-objects/Email"
import { UserId } from "../domain/value-objects/UserId"
import { Result } from "../../../src/shared/types/Result"
/**
* ✅ Domain entity using only domain value objects and shared types
*/
export class User {
private readonly id: UserId
private email: Email
private readonly createdAt: Date
constructor(id: UserId, email: Email, createdAt: Date = new Date()) {
this.id = id
this.email = email
this.createdAt = createdAt
}
public getId(): UserId {
return this.id
}
public getEmail(): Email {
return this.email
}
public changeEmail(newEmail: Email): Result<void> {
if (this.email.equals(newEmail)) {
return Result.fail("Email is the same")
}
this.email = newEmail
return Result.ok()
}
}
/**
* ✅ Domain repository interface (not importing from infrastructure)
*/
export interface IUserRepository {
findById(id: UserId): Promise<User | null>
save(user: User): Promise<void>
delete(id: UserId): Promise<void>
}