import { EventEmitter } from 'events'; import * as ts from 'typescript'; export interface ArchitecturalReport { solidCompliance: SOLIDReport; layerSeparation: LayerReport; dependencyDirection: DependencyReport; designPatterns: DesignPatternReport; recommendations: ArchitecturalRecommendation[]; overallScore: number; } export interface SOLIDReport { singleResponsibility: SRPValidation; openClosed: OCPValidation; liskovSubstitution: LSPValidation; interfaceSegregation: ISPValidation; dependencyInversion: DIPValidation; overallScore: number; } export interface SRPValidation { valid: boolean; classResponsibilities: ResponsibilityAnalysis[]; cohesionScore: number; refactoringRecommendations: string[]; } export interface ResponsibilityAnalysis { className: string; responsibilities: string[]; cohesionMetrics: CohesionMetrics; violatesRule: boolean; } export interface CohesionMetrics { lackOfCohesion: number; responseForClass: number; weightedMethodsPerClass: number; } export interface OCPValidation { valid: boolean; extensionPoints: ExtensionPoint[]; modificationRisks: ModificationRisk[]; abstractionOpportunities: AbstractionOpportunity[]; } export interface ExtensionPoint { location: string; type: 'interface' | 'abstract' | 'plugin' | 'strategy'; description: string; } export interface ModificationRisk { location: string; risk: 'low' | 'medium' | 'high'; reason: string; mitigation: string; } export interface AbstractionOpportunity { location: string; pattern: string; benefit: string; } export interface LSPValidation { valid: boolean; substitutionViolations: SubstitutionViolation[]; contractConsistency: ContractAnalysis[]; behavioralCompatibility: CompatibilityCheck[]; } export interface SubstitutionViolation { baseClass: string; derivedClass: string; violationType: 'precondition' | 'postcondition' | 'exception' | 'behavior'; description: string; } export interface ContractAnalysis { method: string; preconditions: string[]; postconditions: string[]; invariants: string[]; consistent: boolean; } export interface CompatibilityCheck { method: string; compatible: boolean; issues: string[]; } export interface ISPValidation { valid: boolean; interfaceAnalysis: InterfaceAnalysis[]; segregationOpportunities: SegregationOpportunity[]; } export interface InterfaceAnalysis { interfaceName: string; methods: string[]; clients: string[]; cohesion: number; needsSegregation: boolean; } export interface SegregationOpportunity { interfaceName: string; suggestedSplit: InterfaceSplit[]; rationale: string; } export interface InterfaceSplit { name: string; methods: string[]; purpose: string; } export interface DIPValidation { valid: boolean; dependencyAnalysis: DependencyAnalysis[]; inversionOpportunities: InversionOpportunity[]; abstractionLevel: number; } export interface DependencyAnalysis { from: string; to: string; type: 'concrete' | 'abstract'; violatesRule: boolean; level: 'high' | 'application' | 'domain' | 'infrastructure'; } export interface InversionOpportunity { location: string; currentDependency: string; suggestedAbstraction: string; benefit: string; } export interface LayerReport { domainPurity: DomainLayerReport; applicationServices: ApplicationLayerReport; infrastructureIsolation: InfrastructureLayerReport; presentationConcerns: PresentationLayerReport; crossCuttingConcerns: CrossCuttingAnalysis[]; dependencyViolations: LayerViolation[]; } export interface DomainLayerReport { externalDependencies: ExternalDependency[]; entityPatterns: EntityPattern[]; businessRuleEncapsulation: BusinessRuleAnalysis[]; frameworkCoupling: FrameworkCoupling[]; purity: number; } export interface ExternalDependency { from: string; to: string; type: string; severity: 'low' | 'medium' | 'high' | 'critical'; } export interface EntityPattern { className: string; pattern: 'entity' | 'value_object' | 'aggregate_root' | 'domain_service'; valid: boolean; issues: string[]; } export interface BusinessRuleAnalysis { rule: string; location: string; encapsulated: boolean; issues: string[]; } export interface FrameworkCoupling { framework: string; couplingPoints: string[]; severity: 'low' | 'medium' | 'high'; } export interface ApplicationLayerReport { useCaseImplementation: UseCaseAnalysis[]; orchestrationPatterns: OrchestrationPattern[]; transactionBoundaries: TransactionBoundary[]; } export interface UseCaseAnalysis { useCaseName: string; implementation: string; followsPattern: boolean; issues: string[]; } export interface OrchestrationPattern { pattern: string; location: string; appropriate: boolean; alternatives: string[]; } export interface TransactionBoundary { boundary: string; appropriate: boolean; issues: string[]; } export interface InfrastructureLayerReport { dataAccessPatterns: DataAccessPattern[]; externalServiceIntegration: ExternalServiceIntegration[]; configurationManagement: ConfigurationAnalysis[]; } export interface DataAccessPattern { pattern: 'repository' | 'dao' | 'active_record' | 'data_mapper'; implementation: string; followsPattern: boolean; issues: string[]; } export interface ExternalServiceIntegration { service: string; integrationPattern: string; resilient: boolean; issues: string[]; } export interface ConfigurationAnalysis { configType: string; managementPattern: string; secure: boolean; issues: string[]; } export interface PresentationLayerReport { mvpPatterns: MVPPattern[]; dataTransferObjects: DTOAnalysis[]; validationPatterns: ValidationPattern[]; } export interface MVPPattern { pattern: 'mvc' | 'mvp' | 'mvvm' | 'component'; implementation: string; followsPattern: boolean; issues: string[]; } export interface DTOAnalysis { dtoClass: string; purpose: string; appropriate: boolean; issues: string[]; } export interface ValidationPattern { validationType: string; location: string; appropriate: boolean; issues: string[]; } export interface CrossCuttingAnalysis { concern: 'logging' | 'security' | 'caching' | 'monitoring' | 'validation'; implementation: string; separation: number; issues: string[]; } export interface LayerViolation { from: string; to: string; violationType: 'dependency_direction' | 'layer_bypass' | 'circular_dependency'; severity: 'low' | 'medium' | 'high' | 'critical'; } export interface DependencyReport { dependencyDirection: DirectionAnalysis; circularDependencies: CircularDependency[]; dependencyMetrics: DependencyMetrics; } export interface DirectionAnalysis { valid: boolean; violations: DirectionViolation[]; dependencyFlow: DependencyFlow[]; } export interface DirectionViolation { from: string; to: string; expectedDirection: string; actualDirection: string; } export interface DependencyFlow { layer: string; dependsOn: string[]; dependents: string[]; } export interface CircularDependency { cycle: string[]; severity: 'low' | 'medium' | 'high'; resolution: string; } export interface DependencyMetrics { instability: number; abstractness: number; distance: number; coupling: number; } export interface DesignPatternReport { detectedPatterns: DetectedPattern[]; patternOpportunities: PatternOpportunity[]; antiPatterns: AntiPattern[]; } export interface DetectedPattern { pattern: string; location: string; confidence: number; quality: number; } export interface PatternOpportunity { pattern: string; location: string; benefit: string; effort: 'low' | 'medium' | 'high'; } export interface AntiPattern { antiPattern: string; location: string; severity: 'low' | 'medium' | 'high' | 'critical'; resolution: string; } export interface ArchitecturalRecommendation { type: 'refactor' | 'pattern' | 'structure' | 'dependency'; priority: 'low' | 'medium' | 'high' | 'critical'; description: string; benefit: string; effort: string; steps: string[]; } export interface ArchitecturalContext { projectType: 'web' | 'api' | 'desktop' | 'mobile' | 'library'; architecture: 'layered' | 'hexagonal' | 'clean' | 'microservices' | 'monolithic'; frameworks: string[]; constraints: string[]; } export interface Codebase { domain: string; application: string; infrastructure: string; presentation: string; } /** * Clean Architecture & SOLID Principles Engine for FlowX * Validates architectural patterns and design principles */ export class CleanArchitectureEngine extends EventEmitter { private solidValidator: SOLIDPrinciplesValidator; private layerAnalyzer: ArchitecturalLayerAnalyzer; private dependencyAnalyzer: DependencyDirectionAnalyzer; private patternDetector: DesignPatternDetector; constructor() { super(); this.solidValidator = new SOLIDPrinciplesValidator(); this.layerAnalyzer = new ArchitecturalLayerAnalyzer(); this.dependencyAnalyzer = new DependencyDirectionAnalyzer(); this.patternDetector = new DesignPatternDetector(); } /** * Validate complete architectural structure */ async validateArchitecture(code: string, context: ArchitecturalContext): Promise { try { this.emit('validation:start', { context }); // Parse code into AST for analysis const sourceFile = ts.createSourceFile( 'temp.ts', code, ts.ScriptTarget.Latest, true ); // Run all architectural validations in parallel const [solidReport, layerReport, dependencyReport, patternReport] = await Promise.all([ this.validateSOLIDPrinciples(sourceFile), this.validateLayerSeparation(sourceFile, context), this.validateDependencyDirection(sourceFile), this.analyzeDesignPatterns(sourceFile) ]); // Generate architectural recommendations const recommendations = await this.generateArchitecturalRecommendations( solidReport, layerReport, dependencyReport, patternReport ); // Calculate overall architectural score const overallScore = this.calculateOverallScore( solidReport, layerReport, dependencyReport, patternReport ); const report: ArchitecturalReport = { solidCompliance: solidReport, layerSeparation: layerReport, dependencyDirection: dependencyReport, designPatterns: patternReport, recommendations, overallScore }; this.emit('validation:complete', { score: overallScore, recommendations: recommendations.length }); return report; } catch (error) { this.emit('validation:error', error); throw new Error(`Architecture validation failed: ${error instanceof Error ? error.message : String(error)}`); } } /** * Validate SOLID principles */ private async validateSOLIDPrinciples(sourceFile: ts.SourceFile): Promise { const [srp, ocp, lsp, isp, dip] = await Promise.all([ this.solidValidator.checkSingleResponsibility(sourceFile), this.solidValidator.checkOpenClosed(sourceFile), this.solidValidator.checkLiskovSubstitution(sourceFile), this.solidValidator.checkInterfaceSegregation(sourceFile), this.solidValidator.checkDependencyInversion(sourceFile) ]); const overallScore = ( (srp.valid ? 1 : 0) + (ocp.valid ? 1 : 0) + (lsp.valid ? 1 : 0) + (isp.valid ? 1 : 0) + (dip.valid ? 1 : 0) ) / 5; return { singleResponsibility: srp, openClosed: ocp, liskovSubstitution: lsp, interfaceSegregation: isp, dependencyInversion: dip, overallScore }; } /** * Validate architectural layer separation */ private async validateLayerSeparation(sourceFile: ts.SourceFile, context: ArchitecturalContext): Promise { const layers = await this.layerAnalyzer.identifyLayers(sourceFile); return { domainPurity: await this.checkDomainLayerPurity(layers.domain), applicationServices: await this.checkApplicationLayer(layers.application), infrastructureIsolation: await this.checkInfrastructureIsolation(layers.infrastructure), presentationConcerns: await this.checkPresentationLayer(layers.presentation), crossCuttingConcerns: await this.analyzeCrossCuttingConcerns(sourceFile), dependencyViolations: await this.findLayerViolations(sourceFile) }; } /** * Validate dependency direction */ private async validateDependencyDirection(sourceFile: ts.SourceFile): Promise { return this.dependencyAnalyzer.analyze(sourceFile); } /** * Analyze design patterns */ private async analyzeDesignPatterns(sourceFile: ts.SourceFile): Promise { return this.patternDetector.analyze(sourceFile); } /** * Check domain layer purity */ private async checkDomainLayerPurity(domainCode: string): Promise { // Analyze domain layer for external dependencies and framework coupling return { externalDependencies: [], entityPatterns: [], businessRuleEncapsulation: [], frameworkCoupling: [], purity: 0.9 }; } /** * Check application layer */ private async checkApplicationLayer(applicationCode: string): Promise { return { useCaseImplementation: [], orchestrationPatterns: [], transactionBoundaries: [] }; } /** * Check infrastructure isolation */ private async checkInfrastructureIsolation(infrastructureCode: string): Promise { return { dataAccessPatterns: [], externalServiceIntegration: [], configurationManagement: [] }; } /** * Check presentation layer */ private async checkPresentationLayer(presentationCode: string): Promise { return { mvpPatterns: [], dataTransferObjects: [], validationPatterns: [] }; } /** * Analyze cross-cutting concerns */ private async analyzeCrossCuttingConcerns(sourceFile: ts.SourceFile): Promise { return []; } /** * Find layer violations */ private async findLayerViolations(sourceFile: ts.SourceFile): Promise { return []; } /** * Generate architectural recommendations */ private async generateArchitecturalRecommendations( solidReport: SOLIDReport, layerReport: LayerReport, dependencyReport: DependencyReport, patternReport: DesignPatternReport ): Promise { const recommendations: ArchitecturalRecommendation[] = []; // SOLID violations if (!solidReport.singleResponsibility.valid) { recommendations.push({ type: 'refactor', priority: 'high', description: 'Classes have multiple responsibilities - violates Single Responsibility Principle', benefit: 'Improved maintainability and testability', effort: 'Medium', steps: solidReport.singleResponsibility.refactoringRecommendations }); } // Anti-patterns for (const antiPattern of patternReport.antiPatterns) { recommendations.push({ type: 'pattern', priority: antiPattern.severity === 'critical' ? 'critical' : 'high', description: `Anti-pattern detected: ${antiPattern.antiPattern}`, benefit: 'Improved code quality and maintainability', effort: 'Medium', steps: [antiPattern.resolution] }); } // Dependency violations if (!dependencyReport.dependencyDirection.valid) { recommendations.push({ type: 'dependency', priority: 'high', description: 'Dependency direction violations detected', benefit: 'Better separation of concerns and reduced coupling', effort: 'High', steps: ['Invert dependencies', 'Introduce abstractions', 'Apply dependency injection'] }); } return recommendations; } /** * Calculate overall architectural score */ private calculateOverallScore( solidReport: SOLIDReport, layerReport: LayerReport, dependencyReport: DependencyReport, patternReport: DesignPatternReport ): number { const solidScore = solidReport.overallScore; const layerScore = layerReport.domainPurity.purity; const dependencyScore = dependencyReport.dependencyDirection.valid ? 1 : 0; const patternScore = 1 - (patternReport.antiPatterns.length * 0.1); return Math.max(0, (solidScore + layerScore + dependencyScore + patternScore) / 4); } } /** * SOLID Principles Validator */ export class SOLIDPrinciplesValidator { async checkSingleResponsibility(sourceFile: ts.SourceFile): Promise { const responsibilities: ResponsibilityAnalysis[] = []; // Visit all classes and analyze their responsibilities const visitor = (node: ts.Node): void => { if (ts.isClassDeclaration(node) && node.name) { const className = node.name.text; const methods = node.members.filter(ts.isMethodDeclaration); const properties = node.members.filter(ts.isPropertyDeclaration); // Analyze responsibilities based on method groupings const responsibilityGroups = this.groupMethodsByResponsibility(methods); responsibilities.push({ className, responsibilities: Array.from(responsibilityGroups.keys()), cohesionMetrics: this.calculateCohesionMetrics(methods, properties), violatesRule: responsibilityGroups.size > 1 }); } ts.forEachChild(node, visitor); }; visitor(sourceFile); const violatingClasses = responsibilities.filter(r => r.violatesRule); const cohesionScore = responsibilities.length > 0 ? responsibilities.reduce((sum, r) => sum + (1 - r.cohesionMetrics.lackOfCohesion), 0) / responsibilities.length : 1; return { valid: violatingClasses.length === 0, classResponsibilities: responsibilities, cohesionScore, refactoringRecommendations: violatingClasses.map(c => `Split ${c.className} into ${c.responsibilities.length} classes: ${c.responsibilities.join(', ')}` ) }; } async checkOpenClosed(sourceFile: ts.SourceFile): Promise { // Analyze for extension points and modification risks return { valid: true, extensionPoints: [], modificationRisks: [], abstractionOpportunities: [] }; } async checkLiskovSubstitution(sourceFile: ts.SourceFile): Promise { // Analyze inheritance hierarchies for substitution violations return { valid: true, substitutionViolations: [], contractConsistency: [], behavioralCompatibility: [] }; } async checkInterfaceSegregation(sourceFile: ts.SourceFile): Promise { // Analyze interfaces for segregation opportunities return { valid: true, interfaceAnalysis: [], segregationOpportunities: [] }; } async checkDependencyInversion(sourceFile: ts.SourceFile): Promise { // Analyze dependency directions and abstraction opportunities return { valid: true, dependencyAnalysis: [], inversionOpportunities: [], abstractionLevel: 0.8 }; } private groupMethodsByResponsibility(methods: ts.MethodDeclaration[]): Map { const groups = new Map(); for (const method of methods) { if (method.name && ts.isIdentifier(method.name)) { const methodName = method.name.text; // Simple heuristic: group by prefix (get, set, validate, process, etc.) const prefix = methodName.split(/[A-Z]/)[0].toLowerCase(); if (!groups.has(prefix)) { groups.set(prefix, []); } groups.get(prefix)!.push(method); } } return groups; } private calculateCohesionMetrics(methods: ts.MethodDeclaration[], properties: ts.PropertyDeclaration[]): CohesionMetrics { // Simplified cohesion calculation return { lackOfCohesion: Math.max(0, methods.length - properties.length) / Math.max(1, methods.length), responseForClass: methods.length, weightedMethodsPerClass: methods.length // Simplified }; } } /** * Architectural Layer Analyzer */ export class ArchitecturalLayerAnalyzer { async identifyLayers(sourceFile: ts.SourceFile): Promise<{domain: string, application: string, infrastructure: string, presentation: string}> { // Analyze code structure to identify architectural layers return { domain: '', application: '', infrastructure: '', presentation: '' }; } } /** * Dependency Direction Analyzer */ export class DependencyDirectionAnalyzer { async analyze(sourceFile: ts.SourceFile): Promise { // Analyze dependency directions and detect violations return { dependencyDirection: { valid: true, violations: [], dependencyFlow: [] }, circularDependencies: [], dependencyMetrics: { instability: 0.5, abstractness: 0.5, distance: 0.1, coupling: 0.3 } }; } } /** * Design Pattern Detector */ export class DesignPatternDetector { async analyze(sourceFile: ts.SourceFile): Promise { // Detect design patterns and anti-patterns in code return { detectedPatterns: [], patternOpportunities: [], antiPatterns: [] }; } }