Skip to main content
Glama
sascodiego

MCP Vibe Coding Knowledge Graph

by sascodiego
RefactoredValidationHandler.js25.4 kB
/** * CONTEXT: Refactored validation handler using Strategy pattern * REASON: Eliminate nested conditionals and switch statements in validation logic * CHANGE: Apply Strategy pattern for different validation types and debt detection * PREVENTION: Reduces cyclomatic complexity and improves maintainability */ import { logger } from '../utils/logger.js'; import { parse } from '@babel/parser'; import traverse from '@babel/traverse'; /** * Base validation strategy interface */ class ValidationStrategy { async validate(characteristics, strictMode) { throw new Error('Validate method must be implemented by subclasses'); } } /** * Pattern validation strategy */ class PatternValidationStrategy extends ValidationStrategy { constructor(kuzu) { super(); this.kuzu = kuzu; } async validate(characteristics, strictMode) { try { const detectedPatterns = await this.detectPatterns(characteristics); const validationScore = this.calculatePatternScore(detectedPatterns, strictMode); return { type: 'patterns', score: validationScore, detectedPatterns, violations: this.findPatternViolations(characteristics, detectedPatterns), suggestions: this.generatePatternSuggestions(characteristics, detectedPatterns) }; } catch (error) { logger.error('Pattern validation failed:', error); return this.createErrorResult('patterns', error); } } async detectPatterns(characteristics) { const patterns = []; // Singleton pattern detection if (this.isSingletonPattern(characteristics)) { patterns.push({ name: 'Singleton', confidence: 0.8 }); } // Factory pattern detection if (this.isFactoryPattern(characteristics)) { patterns.push({ name: 'Factory', confidence: 0.7 }); } // Observer pattern detection if (this.isObserverPattern(characteristics)) { patterns.push({ name: 'Observer', confidence: 0.6 }); } return patterns; } isSingletonPattern(characteristics) { return characteristics.classes.some(cls => cls.methods.some(method => method.name === 'getInstance') && cls.properties.some(prop => prop.static && prop.name.includes('instance')) ); } isFactoryPattern(characteristics) { return characteristics.functions.some(func => func.name.toLowerCase().includes('create') || func.name.toLowerCase().includes('factory') ); } isObserverPattern(characteristics) { return characteristics.classes.some(cls => cls.methods.some(method => ['addEventListener', 'subscribe', 'notify'].includes(method.name) ) ); } calculatePatternScore(detectedPatterns, strictMode) { if (detectedPatterns.length === 0) { return strictMode ? 0.3 : 0.6; } const avgConfidence = detectedPatterns.reduce((sum, p) => sum + p.confidence, 0) / detectedPatterns.length; return Math.min(avgConfidence + 0.2, 1.0); } findPatternViolations(characteristics, detectedPatterns) { const violations = []; // Check for pattern implementation issues for (const pattern of detectedPatterns) { if (pattern.name === 'Singleton' && pattern.confidence < 0.9) { violations.push({ type: 'incomplete_singleton', message: 'Singleton pattern implementation appears incomplete', severity: 'warning' }); } } return violations; } generatePatternSuggestions(characteristics, detectedPatterns) { const suggestions = []; if (detectedPatterns.length === 0 && characteristics.classes.length > 0) { suggestions.push('Consider implementing design patterns for better code organization'); } return suggestions; } createErrorResult(type, error) { return { type, score: 0, error: error.message, detectedPatterns: [], violations: [], suggestions: [] }; } } /** * Rules validation strategy */ class RulesValidationStrategy extends ValidationStrategy { constructor(kuzu) { super(); this.kuzu = kuzu; } async validate(characteristics, strictMode) { try { const ruleViolations = await this.checkRuleViolations(characteristics); const validationScore = this.calculateRulesScore(ruleViolations, strictMode); return { type: 'rules', score: validationScore, violations: ruleViolations, appliedRules: await this.getAppliedRules(), suggestions: this.generateRulesSuggestions(ruleViolations) }; } catch (error) { logger.error('Rules validation failed:', error); return this.createErrorResult('rules', error); } } async checkRuleViolations(characteristics) { const violations = []; // Security rule violations violations.push(...this.checkSecurityRules(characteristics)); // Complexity rule violations violations.push(...this.checkComplexityRules(characteristics)); // Code quality rule violations violations.push(...this.checkQualityRules(characteristics)); return violations; } checkSecurityRules(characteristics) { const violations = []; if (characteristics.hasEval) { violations.push({ rule: 'no-eval', severity: 'high', message: 'Use of eval() is not allowed', line: null }); } if (characteristics.hasInnerHTML) { violations.push({ rule: 'no-inner-html', severity: 'medium', message: 'Direct innerHTML usage can lead to XSS vulnerabilities', line: null }); } return violations; } checkComplexityRules(characteristics) { const violations = []; if (characteristics.maxNestingLevel > 4) { violations.push({ rule: 'max-nesting-depth', severity: 'medium', message: `Nesting depth ${characteristics.maxNestingLevel} exceeds maximum of 4`, line: null }); } if (characteristics.complexity > 10) { violations.push({ rule: 'max-complexity', severity: 'high', message: `Cyclomatic complexity ${characteristics.complexity} exceeds maximum of 10`, line: null }); } return violations; } checkQualityRules(characteristics) { const violations = []; if (characteristics.unusedVariables.length > 0) { violations.push({ rule: 'no-unused-vars', severity: 'low', message: `${characteristics.unusedVariables.length} unused variables found`, line: null }); } return violations; } async getAppliedRules() { try { const result = await this.kuzu.query(` MATCH (r:Rule) RETURN r.name as name, r.severity as severity, r.description as description ORDER BY r.severity DESC `); return result; } catch (error) { logger.error('Error getting applied rules:', error); return []; } } calculateRulesScore(violations, strictMode) { if (violations.length === 0) { return 1.0; } const severityWeights = { high: 0.4, medium: 0.2, low: 0.1 }; const penalty = violations.reduce((sum, v) => sum + (severityWeights[v.severity] || 0.1), 0); const baseScore = Math.max(0, 1.0 - penalty); return strictMode ? baseScore * 0.8 : baseScore; } generateRulesSuggestions(violations) { const suggestions = []; const severityGroups = violations.reduce((groups, v) => { groups[v.severity] = (groups[v.severity] || 0) + 1; return groups; }, {}); if (severityGroups.high > 0) { suggestions.push('Address high-severity rule violations immediately'); } if (severityGroups.medium > 2) { suggestions.push('Consider refactoring to reduce medium-severity violations'); } return suggestions; } createErrorResult(type, error) { return { type, score: 0, error: error.message, violations: [], appliedRules: [], suggestions: [] }; } } /** * Standards validation strategy */ class StandardsValidationStrategy extends ValidationStrategy { constructor(kuzu) { super(); this.kuzu = kuzu; } async validate(characteristics, strictMode) { try { const standardsCompliance = await this.checkStandardsCompliance(characteristics); const validationScore = this.calculateStandardsScore(standardsCompliance, strictMode); return { type: 'standards', score: validationScore, compliance: standardsCompliance, appliedStandards: await this.getAppliedStandards(), suggestions: this.generateStandardsSuggestions(standardsCompliance) }; } catch (error) { logger.error('Standards validation failed:', error); return this.createErrorResult('standards', error); } } async checkStandardsCompliance(characteristics) { const compliance = []; // Naming conventions compliance.push(...this.checkNamingConventions(characteristics)); // Code formatting compliance.push(...this.checkCodeFormatting(characteristics)); // Documentation standards compliance.push(...this.checkDocumentationStandards(characteristics)); return compliance; } checkNamingConventions(characteristics) { const compliance = []; // Check camelCase for functions const badFunctionNames = characteristics.functions.filter(func => !/^[a-z][a-zA-Z0-9]*$/.test(func.name) ); if (badFunctionNames.length > 0) { compliance.push({ standard: 'camelCase-functions', status: 'violation', message: `${badFunctionNames.length} functions don't follow camelCase convention`, details: badFunctionNames.map(f => f.name) }); } else { compliance.push({ standard: 'camelCase-functions', status: 'compliant', message: 'All functions follow camelCase convention' }); } return compliance; } checkCodeFormatting(characteristics) { const compliance = []; if (characteristics.maxLineLength > 80) { compliance.push({ standard: 'line-length', status: 'violation', message: `Line length ${characteristics.maxLineLength} exceeds 80 characters` }); } else { compliance.push({ standard: 'line-length', status: 'compliant', message: 'Line length within standards' }); } return compliance; } checkDocumentationStandards(characteristics) { const compliance = []; const undocumentedFunctions = characteristics.functions.filter(func => !func.hasDocumentation ); if (undocumentedFunctions.length > 0) { compliance.push({ standard: 'function-documentation', status: 'violation', message: `${undocumentedFunctions.length} functions lack documentation` }); } else { compliance.push({ standard: 'function-documentation', status: 'compliant', message: 'All functions are documented' }); } return compliance; } async getAppliedStandards() { try { const result = await this.kuzu.query(` MATCH (s:Standard) RETURN s.name as name, s.value as value, s.category as category ORDER BY s.category, s.name `); return result; } catch (error) { logger.error('Error getting applied standards:', error); return []; } } calculateStandardsScore(compliance, strictMode) { const total = compliance.length; if (total === 0) return strictMode ? 0.5 : 0.7; const compliant = compliance.filter(c => c.status === 'compliant').length; const baseScore = compliant / total; return strictMode ? baseScore * 0.9 : baseScore; } generateStandardsSuggestions(compliance) { const suggestions = []; const violations = compliance.filter(c => c.status === 'violation'); if (violations.length > 0) { suggestions.push('Review and fix coding standards violations'); const categories = [...new Set(violations.map(v => v.standard))]; if (categories.length > 1) { suggestions.push('Consider using automated formatting tools'); } } return suggestions; } createErrorResult(type, error) { return { type, score: 0, error: error.message, compliance: [], appliedStandards: [], suggestions: [] }; } } /** * Technical debt detection strategies */ class TechnicalDebtStrategy { constructor(kuzu) { this.kuzu = kuzu; } async detectDebt(scope, target, debtTypes) { const detectionStrategies = { module: () => this.detectModuleDebt(target, debtTypes), project: () => this.detectProjectDebt(debtTypes), specific: () => this.detectSpecificDebt(target, debtTypes) }; const strategy = detectionStrategies[scope]; if (!strategy) { throw new Error(`Unknown debt detection scope: ${scope}`); } return await strategy(); } async detectModuleDebt(target, debtTypes) { const query = ` MATCH (e:CodeEntity) WHERE e.filePath CONTAINS $target OPTIONAL MATCH (e)-[:HAS_ISSUE]->(debt:TechnicalDebt) WHERE debt.type IN $debtTypes RETURN { module: $target, entities: collect(DISTINCT {name: e.name, type: e.type}), debts: collect(DISTINCT { type: debt.type, severity: debt.severity, description: debt.description, entity: e.name }) } as analysis `; const result = await this.kuzu.query(query, { target, debtTypes }); return result[0]?.analysis || {}; } async detectProjectDebt(debtTypes) { const query = ` MATCH (debt:TechnicalDebt) WHERE debt.type IN $debtTypes OPTIONAL MATCH (e:CodeEntity)-[:HAS_ISSUE]->(debt) RETURN { project: "entire", totalDebtItems: count(DISTINCT debt), byType: collect(DISTINCT { type: debt.type, count: size((debt)<-[:HAS_ISSUE]-()) }), byModule: collect(DISTINCT { module: split(e.filePath, '/')[0], debts: count(debt) }) } as analysis `; const result = await this.kuzu.query(query, { debtTypes }); return result[0]?.analysis || {}; } async detectSpecificDebt(target, debtTypes) { const query = ` MATCH (e:CodeEntity {name: $target}) OPTIONAL MATCH (e)-[:HAS_ISSUE]->(debt:TechnicalDebt) WHERE debt.type IN $debtTypes RETURN { entity: {name: e.name, type: e.type, filePath: e.filePath}, debts: collect(DISTINCT { type: debt.type, severity: debt.severity, description: debt.description, impact: debt.impact }) } as analysis `; const result = await this.kuzu.query(query, { target, debtTypes }); return result[0]?.analysis || {}; } } /** * Refactored validation handler using Strategy pattern */ export class RefactoredValidationHandler { constructor(serviceLocator) { this.serviceLocator = serviceLocator; this.kuzu = serviceLocator.get('database'); // Initialize validation strategies this.validationStrategies = { patterns: new PatternValidationStrategy(this.kuzu), rules: new RulesValidationStrategy(this.kuzu), standards: new StandardsValidationStrategy(this.kuzu) }; this.debtStrategy = new TechnicalDebtStrategy(this.kuzu); } /** * Validate code against KG using strategy pattern */ async validateAgainstKG(args) { const { codeSnippet, validationTypes = ['patterns', 'rules', 'standards'], strictMode = true } = args; try { // Parse code and extract characteristics const ast = this.parseCode(codeSnippet); const characteristics = this.extractCodeCharacteristics(ast); // Execute validation strategies const validationResults = await this.executeValidationStrategies( validationTypes, characteristics, strictMode ); const overallScore = this.calculateOverallScore(validationResults); return { content: [ { type: 'text', text: JSON.stringify({ codeSnippet: this.truncateCode(codeSnippet), validationResults, overallScore, strictMode, recommendations: this.generateRecommendations(validationResults) }, null, 2) } ] }; } catch (error) { logger.error('Error validating against KG:', error); throw error; } } /** * Detect technical debt using strategy pattern */ async detectTechnicalDebt(args) { const { scope, target, debtTypes = ['complexity', 'duplication', 'coupling'] } = args; try { const analysis = await this.debtStrategy.detectDebt(scope, target, debtTypes); const debtAnalysis = this.analyzeDebtResults(analysis, scope, debtTypes); return { content: [ { type: 'text', text: JSON.stringify({ scope, target, debtTypes, analysis: debtAnalysis, recommendations: this.generateDebtRecommendations(debtAnalysis) }, null, 2) } ] }; } catch (error) { logger.error('Error detecting technical debt:', error); throw error; } } /** * Parse code with error handling */ parseCode(codeSnippet) { try { return parse(codeSnippet, { sourceType: 'module', plugins: ['jsx', 'typescript', 'decorators-legacy'] }); } catch (error) { logger.warn('Failed to parse code snippet:', error.message); // Return a minimal AST for basic analysis return { type: 'Program', body: [] }; } } /** * Execute validation strategies in parallel */ async executeValidationStrategies(validationTypes, characteristics, strictMode) { const validationPromises = validationTypes.map(async (type) => { const strategy = this.validationStrategies[type]; if (!strategy) { logger.warn(`Unknown validation type: ${type}`); return null; } try { return await strategy.validate(characteristics, strictMode); } catch (error) { logger.error(`Validation strategy ${type} failed:`, error); return { type, error: error.message, score: 0 }; } }); const results = await Promise.all(validationPromises); return results.filter(result => result !== null); } /** * Extract code characteristics using visitor pattern */ extractCodeCharacteristics(ast) { const characteristics = { functions: [], classes: [], variables: [], imports: [], complexity: 0, patterns: [], maxNestingLevel: 0, maxLineLength: 0, hasEval: false, hasInnerHTML: false, unusedVariables: [] }; const visitor = new CodeCharacteristicsVisitor(characteristics); visitor.visit(ast); return characteristics; } /** * Calculate overall validation score */ calculateOverallScore(validationResults) { if (validationResults.length === 0) return 0; const totalScore = validationResults.reduce((sum, result) => sum + (result.score || 0), 0); return Number((totalScore / validationResults.length).toFixed(2)); } /** * Generate validation recommendations */ generateRecommendations(validationResults) { const recommendations = []; for (const result of validationResults) { if (result.suggestions && result.suggestions.length > 0) { recommendations.push(...result.suggestions); } if (result.score < 0.5) { recommendations.push(`Improve ${result.type} validation score (currently ${result.score})`); } } return [...new Set(recommendations)]; // Remove duplicates } /** * Analyze debt detection results */ analyzeDebtResults(analysis, scope, debtTypes) { return { summary: this.createDebtSummary(analysis, scope), details: analysis, metrics: this.calculateDebtMetrics(analysis, debtTypes), trends: this.analyzeDebtTrends(analysis) }; } createDebtSummary(analysis, scope) { switch (scope) { case 'module': return { scope: 'module', totalEntities: analysis.entities?.length || 0, totalDebts: analysis.debts?.length || 0, avgDebtsPerEntity: analysis.entities?.length > 0 ? ((analysis.debts?.length || 0) / analysis.entities.length).toFixed(2) : 0 }; case 'project': return { scope: 'project', totalDebtItems: analysis.totalDebtItems || 0, moduleCount: analysis.byModule?.length || 0, typeCount: analysis.byType?.length || 0 }; case 'specific': return { scope: 'specific', entity: analysis.entity?.name || 'unknown', totalDebts: analysis.debts?.length || 0 }; default: return { scope, error: 'Unknown scope' }; } } calculateDebtMetrics(analysis, debtTypes) { // Implementation would calculate various debt metrics return { debtTypes: debtTypes, coverage: 0.8, // Example metric severity: 'medium' // Example metric }; } analyzeDebtTrends(analysis) { // Implementation would analyze trends in technical debt return { trend: 'stable', recommendation: 'Monitor for increases' }; } /** * Generate debt recommendations */ generateDebtRecommendations(debtAnalysis) { const recommendations = []; if (debtAnalysis.summary.totalDebts > 10) { recommendations.push('High debt detected - prioritize refactoring efforts'); } if (debtAnalysis.metrics.severity === 'high') { recommendations.push('Address high-severity debt items immediately'); } return recommendations; } /** * Truncate code for display */ truncateCode(codeSnippet, maxLength = 200) { return codeSnippet.length > maxLength ? codeSnippet.substring(0, maxLength) + '...' : codeSnippet; } } /** * Visitor pattern for code characteristics extraction */ class CodeCharacteristicsVisitor { constructor(characteristics) { this.characteristics = characteristics; this.nestingLevel = 0; } visit(node) { if (!node) return; this.enter(node); // Visit child nodes for (const key in node) { const child = node[key]; if (Array.isArray(child)) { child.forEach(c => this.visit(c)); } else if (child && typeof child === 'object' && child.type) { this.visit(child); } } this.exit(node); } enter(node) { const nodeHandlers = { FunctionDeclaration: () => this.handleFunction(node), ClassDeclaration: () => this.handleClass(node), VariableDeclarator: () => this.handleVariable(node), ImportDeclaration: () => this.handleImport(node), IfStatement: () => this.handleComplexity(node), CallExpression: () => this.handleCallExpression(node), MemberExpression: () => this.handleMemberExpression(node) }; const handler = nodeHandlers[node.type]; if (handler) { handler(); } // Track nesting if (this.isNestingNode(node)) { this.nestingLevel++; this.characteristics.maxNestingLevel = Math.max( this.characteristics.maxNestingLevel, this.nestingLevel ); } } exit(node) { if (this.isNestingNode(node)) { this.nestingLevel--; } } handleFunction(node) { this.characteristics.functions.push({ name: node.id?.name || 'anonymous', hasDocumentation: this.hasLeadingComments(node), params: node.params?.length || 0 }); } handleClass(node) { this.characteristics.classes.push({ name: node.id?.name || 'anonymous', methods: [], properties: [] }); } handleVariable(node) { if (node.id?.name) { this.characteristics.variables.push({ name: node.id.name, type: node.init?.type || 'unknown' }); } } handleImport(node) { this.characteristics.imports.push({ source: node.source?.value || 'unknown', specifiers: node.specifiers?.length || 0 }); } handleComplexity(node) { this.characteristics.complexity++; } handleCallExpression(node) { if (node.callee?.name === 'eval') { this.characteristics.hasEval = true; } } handleMemberExpression(node) { if (node.property?.name === 'innerHTML') { this.characteristics.hasInnerHTML = true; } } isNestingNode(node) { return [ 'IfStatement', 'ForStatement', 'WhileStatement', 'DoWhileStatement', 'SwitchStatement' ].includes(node.type); } hasLeadingComments(node) { return node.leadingComments && node.leadingComments.length > 0; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sascodiego/KGsMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server