feat: add aggregate boundary validation (v0.7.0)

Implement DDD aggregate boundary validation to detect and prevent direct
entity references across aggregate boundaries.

Features:
- Detect direct entity imports between aggregates
- Allow only ID or Value Object references
- Support multiple folder structures (domain/aggregates/*, domain/*, domain/entities/*)
- Filter allowed imports (value-objects, events, repositories, services)
- Critical severity level for violations
- 41 comprehensive tests with 92.55% coverage
- CLI output with detailed suggestions
- Examples of good and bad patterns

Breaking changes: None
Backwards compatible: Yes
This commit is contained in:
imfozilbek
2025-11-24 23:54:16 +05:00
parent 83b5dccee4
commit c75738ba51
16 changed files with 1297 additions and 12 deletions

View File

@@ -155,6 +155,7 @@ program
entityExposureViolations,
dependencyDirectionViolations,
repositoryPatternViolations,
aggregateBoundaryViolations,
} = result
const minSeverity: SeverityLevel | undefined = options.onlyCritical
@@ -185,6 +186,10 @@ program
repositoryPatternViolations,
minSeverity,
)
aggregateBoundaryViolations = filterBySeverity(
aggregateBoundaryViolations,
minSeverity,
)
if (options.onlyCritical) {
console.log("\n🔴 Filtering: Showing only CRITICAL severity issues\n")
@@ -374,6 +379,35 @@ program
)
}
// Aggregate boundary violations
if (options.architecture && aggregateBoundaryViolations.length > 0) {
console.log(
`\n🔒 Found ${String(aggregateBoundaryViolations.length)} aggregate boundary violation(s)`,
)
displayGroupedViolations(
aggregateBoundaryViolations,
(ab, index) => {
const location = ab.line ? `${ab.file}:${String(ab.line)}` : ab.file
console.log(`${String(index + 1)}. ${location}`)
console.log(` Severity: ${SEVERITY_LABELS[ab.severity]}`)
console.log(` From Aggregate: ${ab.fromAggregate}`)
console.log(` To Aggregate: ${ab.toAggregate}`)
console.log(` Entity: ${ab.entityName}`)
console.log(` Import: ${ab.importPath}`)
console.log(` ${ab.message}`)
console.log(" 💡 Suggestion:")
ab.suggestion.split("\n").forEach((line) => {
if (line.trim()) {
console.log(` ${line}`)
}
})
console.log("")
},
limit,
)
}
// Hardcode violations
if (options.hardcode && hardcodeViolations.length > 0) {
console.log(
@@ -407,7 +441,8 @@ program
frameworkLeakViolations.length +
entityExposureViolations.length +
dependencyDirectionViolations.length +
repositoryPatternViolations.length
repositoryPatternViolations.length +
aggregateBoundaryViolations.length
if (totalIssues === 0) {
console.log(CLI_MESSAGES.NO_ISSUES)