mirror of
https://github.com/samiyev/puaros.git
synced 2025-12-28 07:16:53 +05:00
Refactored three largest detectors to improve maintainability and reduce complexity: - AggregateBoundaryDetector: 381 → 162 lines (57% reduction) - HardcodeDetector: 459 → 89 lines (81% reduction) - RepositoryPatternDetector: 479 → 106 lines (78% reduction) Added 13 new strategy classes: - FolderRegistry - centralized DDD folder name management - AggregatePathAnalyzer - path parsing and aggregate extraction - ImportValidator - import validation logic - BraceTracker - brace and bracket counting - ConstantsFileChecker - constants file detection - ExportConstantAnalyzer - export const analysis - MagicNumberMatcher - magic number detection - MagicStringMatcher - magic string detection - OrmTypeMatcher - ORM type matching - MethodNameValidator - repository method validation - RepositoryFileAnalyzer - file role detection - RepositoryViolationDetector - violation detection logic All 519 tests passing, zero ESLint errors, no breaking changes.
107 lines
3.8 KiB
TypeScript
107 lines
3.8 KiB
TypeScript
import { IRepositoryPatternDetector } from "../../domain/services/RepositoryPatternDetectorService"
|
|
import { RepositoryViolation } from "../../domain/value-objects/RepositoryViolation"
|
|
import { OrmTypeMatcher } from "../strategies/OrmTypeMatcher"
|
|
import { MethodNameValidator } from "../strategies/MethodNameValidator"
|
|
import { RepositoryFileAnalyzer } from "../strategies/RepositoryFileAnalyzer"
|
|
import { RepositoryViolationDetector } from "../strategies/RepositoryViolationDetector"
|
|
|
|
/**
|
|
* Detects Repository Pattern violations in the codebase
|
|
*
|
|
* This detector identifies violations where the Repository Pattern is not properly implemented:
|
|
* 1. ORM-specific types in repository interfaces (domain should be ORM-agnostic)
|
|
* 2. Concrete repository usage in use cases (violates dependency inversion)
|
|
* 3. Repository instantiation with 'new' in use cases (should use DI)
|
|
* 4. Non-domain method names in repositories (should use ubiquitous language)
|
|
*
|
|
* @example
|
|
* ```typescript
|
|
* const detector = new RepositoryPatternDetector()
|
|
*
|
|
* // Detect violations in a repository interface
|
|
* const code = `
|
|
* interface IUserRepository {
|
|
* findOne(query: Prisma.UserWhereInput): Promise<User>
|
|
* }
|
|
* `
|
|
* const violations = detector.detectViolations(
|
|
* code,
|
|
* 'src/domain/repositories/IUserRepository.ts',
|
|
* 'domain'
|
|
* )
|
|
*
|
|
* // violations will contain ORM type violation
|
|
* console.log(violations.length) // 1
|
|
* console.log(violations[0].violationType) // 'orm-type-in-interface'
|
|
* ```
|
|
*/
|
|
export class RepositoryPatternDetector implements IRepositoryPatternDetector {
|
|
private readonly ormMatcher: OrmTypeMatcher
|
|
private readonly methodValidator: MethodNameValidator
|
|
private readonly fileAnalyzer: RepositoryFileAnalyzer
|
|
private readonly violationDetector: RepositoryViolationDetector
|
|
|
|
constructor() {
|
|
this.ormMatcher = new OrmTypeMatcher()
|
|
this.methodValidator = new MethodNameValidator(this.ormMatcher)
|
|
this.fileAnalyzer = new RepositoryFileAnalyzer()
|
|
this.violationDetector = new RepositoryViolationDetector(
|
|
this.ormMatcher,
|
|
this.methodValidator,
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Detects all Repository Pattern violations in the given code
|
|
*/
|
|
public detectViolations(
|
|
code: string,
|
|
filePath: string,
|
|
layer: string | undefined,
|
|
): RepositoryViolation[] {
|
|
const violations: RepositoryViolation[] = []
|
|
|
|
if (this.fileAnalyzer.isRepositoryInterface(filePath, layer)) {
|
|
violations.push(...this.violationDetector.detectOrmTypes(code, filePath, layer))
|
|
violations.push(...this.violationDetector.detectNonDomainMethods(code, filePath, layer))
|
|
}
|
|
|
|
if (this.fileAnalyzer.isUseCase(filePath, layer)) {
|
|
violations.push(
|
|
...this.violationDetector.detectConcreteRepositoryUsage(code, filePath, layer),
|
|
)
|
|
violations.push(...this.violationDetector.detectNewInstantiation(code, filePath, layer))
|
|
}
|
|
|
|
return violations
|
|
}
|
|
|
|
/**
|
|
* Checks if a type is an ORM-specific type
|
|
*/
|
|
public isOrmType(typeName: string): boolean {
|
|
return this.ormMatcher.isOrmType(typeName)
|
|
}
|
|
|
|
/**
|
|
* Checks if a method name follows domain language conventions
|
|
*/
|
|
public isDomainMethodName(methodName: string): boolean {
|
|
return this.methodValidator.isDomainMethodName(methodName)
|
|
}
|
|
|
|
/**
|
|
* Checks if a file is a repository interface
|
|
*/
|
|
public isRepositoryInterface(filePath: string, layer: string | undefined): boolean {
|
|
return this.fileAnalyzer.isRepositoryInterface(filePath, layer)
|
|
}
|
|
|
|
/**
|
|
* Checks if a file is a use case
|
|
*/
|
|
public isUseCase(filePath: string, layer: string | undefined): boolean {
|
|
return this.fileAnalyzer.isUseCase(filePath, layer)
|
|
}
|
|
}
|