UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

331 lines • 15.9 kB
import { Command } from 'commander'; import chalk from 'chalk'; import ora from 'ora'; import * as path from 'path'; import { AnalyzerConfigLoader } from '../config/analyzer-config.js'; import { SecurityAnalyzer } from '../analyzers/SecurityAnalyzer.js'; import { PerformanceAnalyzer } from '../analyzers/PerformanceAnalyzer.js'; import { DocumentationAnalyzer } from '../analyzers/DocumentationAnalyzer.js'; import { CodeQualityAnalyzer } from '../analyzers/CodeQualityAnalyzer.js'; import { CrossPlatformAnalyzer } from '../analyzers/CrossPlatformAnalyzer.js'; import { UnusedCodeAnalyzer } from '../analyzers/UnusedCodeAnalyzer.js'; import { DetailedReportGenerator } from '../reporting/DetailedReportGenerator.js'; export function createAnalyzeConfigurableCommand() { return new Command('analyze-config') .alias('ac') .description('Run code analysis with configurable rules and thresholds') .option('-s, --security', 'Run security analysis only') .option('-p, --performance', 'Run performance analysis only') .option('-d, --documentation', 'Run documentation analysis only') .option('-q, --quality', 'Run code quality analysis only') .option('-x, --cross-platform', 'Run cross-platform analysis only') .option('-u, --unused', 'Run unused code analysis only') .option('--config <path>', 'Path to custom analyzer configuration file') .option('--save-config <path>', 'Save current configuration to file') .option('--show-config', 'Display current configuration') .option('--disable <analyzers>', 'Disable specific analyzers (comma-separated)') .option('--threshold <name=value>', 'Override specific threshold', collectThresholds, {}) .option('--format <format>', 'Report format: console, markdown, html, json', 'console') .option('--output <path>', 'Output report to file') .option('--no-details', 'Skip detailed recommendations') .option('--no-examples', 'Skip code examples in report') .action(async (options) => { const projectRoot = process.cwd(); // Load configuration let configLoader; if (options.config) { configLoader = await AnalyzerConfigLoader.loadFromFile(options.config); console.log(chalk.gray(`Using custom configuration from: ${options.config}`)); } else { const defaultConfigPath = path.join(projectRoot, '.mira-analyzer-config.json'); configLoader = await AnalyzerConfigLoader.loadFromFile(defaultConfigPath); } const config = configLoader.getConfig(); // Handle --show-config if (options.showConfig) { console.log(chalk.cyan('\nšŸ“‹ Current Analyzer Configuration:\n')); console.log(JSON.stringify(config, null, 2)); return; } // Handle --save-config if (options.saveConfig) { await configLoader.saveToFile(options.saveConfig); console.log(chalk.green(`āœ… Configuration saved to: ${options.saveConfig}`)); return; } // Handle --disable if (options.disable) { const disabledAnalyzers = options.disable.split(',').map((a) => a.trim()); disabledAnalyzers.forEach((analyzer) => { if (config[analyzer]) { config[analyzer].enabled = false; } }); } // Handle --threshold overrides if (options.threshold && Object.keys(options.threshold).length > 0) { applyThresholdOverrides(config, options.threshold); } console.log(chalk.cyan('\nšŸ” Running Configurable Code Analysis\n')); const results = {}; const errors = []; // Determine which analyzers to run const runAll = !options.security && !options.performance && !options.documentation && !options.quality && !options.crossPlatform && !options.unused; // Security Analysis if ((runAll || options.security) && config.security?.enabled) { const spinner = ora('Running security analysis...').start(); try { const analyzer = new SecurityAnalyzer(projectRoot); results.security = await analyzer.fullAnalysis(); // Apply configuration-based scoring const securityConfig = config.security; if (results.security.criticalIssues > securityConfig.thresholds.criticalIssuesMax) { results.security.configViolation = 'Exceeded critical issues threshold'; } spinner.succeed('Security analysis complete'); } catch (error) { spinner.fail('Security analysis failed'); errors.push(`Security: ${error}`); } } // Performance Analysis if ((runAll || options.performance) && config.performance?.enabled) { const spinner = ora('Running performance analysis...').start(); try { const analyzer = new PerformanceAnalyzer(projectRoot); results.performance = await analyzer.analyze(); spinner.succeed('Performance analysis complete'); } catch (error) { spinner.fail('Performance analysis failed'); errors.push(`Performance: ${error}`); } } // Documentation Analysis if ((runAll || options.documentation) && config.documentation?.enabled) { const spinner = ora('Running documentation analysis...').start(); try { const analyzer = new DocumentationAnalyzer(projectRoot); results.documentation = await analyzer.analyze(); spinner.succeed('Documentation analysis complete'); } catch (error) { spinner.fail('Documentation analysis failed'); errors.push(`Documentation: ${error}`); } } // Code Quality Analysis if ((runAll || options.quality) && config.codeQuality?.enabled) { const spinner = ora('Running code quality analysis...').start(); try { const analyzer = new CodeQualityAnalyzer(projectRoot); results.codeQuality = await analyzer.fullAnalysis(); spinner.succeed('Code quality analysis complete'); } catch (error) { spinner.fail('Code quality analysis failed'); errors.push(`Code Quality: ${error}`); } } // Cross-Platform Analysis if ((runAll || options.crossPlatform) && config.crossPlatform?.enabled) { const spinner = ora('Running cross-platform analysis...').start(); try { const analyzer = new CrossPlatformAnalyzer(projectRoot); results.crossPlatform = await analyzer.analyze(); spinner.succeed('Cross-platform analysis complete'); } catch (error) { spinner.fail('Cross-platform analysis failed'); errors.push(`Cross-Platform: ${error}`); } } // Unused Code Analysis if ((runAll || options.unused) && config.unusedCode?.enabled) { const spinner = ora('Running unused code analysis...').start(); try { const analyzer = new UnusedCodeAnalyzer(projectRoot); results.unusedCode = await analyzer.analyze(); spinner.succeed('Unused code analysis complete'); } catch (error) { spinner.fail('Unused code analysis failed'); errors.push(`Unused Code: ${error}`); } } // Generate detailed report const reportOptions = { format: options.format, outputPath: options.output, includeDetails: options.details !== false, includeExamples: options.examples !== false, includeTrends: false, maxIssuesPerCategory: 10 }; const reportGenerator = new DetailedReportGenerator(reportOptions); await reportGenerator.generateReport(results, projectRoot); // If not console output, still show summary if (options.format !== 'console' && !options.output) { displayResults(results, config, errors); } }); } function collectThresholds(value, previous) { const [key, val] = value.split('='); previous[key] = isNaN(Number(val)) ? val : Number(val); return previous; } function applyThresholdOverrides(config, overrides) { for (const [key, value] of Object.entries(overrides)) { const parts = key.split('.'); let target = config; for (let i = 0; i < parts.length - 1; i++) { if (target[parts[i]]) { target = target[parts[i]]; } } const lastPart = parts[parts.length - 1]; if (target.thresholds && lastPart in target.thresholds) { target.thresholds[lastPart] = value; } } } function displayResults(results, config, errors) { console.log(chalk.cyan('\nšŸ“Š Analysis Results Summary\n')); // Overall score calculation let totalScore = 0; let analyzersRun = 0; // Security Results if (results.security) { analyzersRun++; const score = results.security.securityScore || 0; totalScore += score; console.log(chalk.yellow('šŸ”’ Security Analysis:')); console.log(` Score: ${getScoreColor(score)}${score}/100${chalk.reset()}`); console.log(` Risk Level: ${getRiskColor(results.security.riskLevel)}${results.security.riskLevel}${chalk.reset()}`); console.log(` Critical Issues: ${results.security.criticalIssues}`); console.log(` Total Issues: ${results.security.issues}`); if (results.security.configViolation) { console.log(chalk.red(` āš ļø Config Violation: ${results.security.configViolation}`)); } if (config.security?.thresholds.minSecurityScore && score < config.security.thresholds.minSecurityScore) { console.log(chalk.red(` āŒ Below minimum score threshold (${config.security.thresholds.minSecurityScore})`)); } console.log(); } // Performance Results if (results.performance) { analyzersRun++; const score = results.performance.score || 0; totalScore += score; console.log(chalk.blue('⚔ Performance Analysis:')); console.log(` Score: ${getScoreColor(score)}${score}/100${chalk.reset()}`); console.log(` Issues: ${results.performance.issues}`); if (results.performance.bundleSizeKB && config.performance?.rules.bundleSize.enabled) { const maxSize = config.performance.rules.bundleSize.maxSizeKB; const bundleSize = results.performance.bundleSizeKB; if (bundleSize > maxSize) { console.log(chalk.red(` āŒ Bundle size (${bundleSize}KB) exceeds limit (${maxSize}KB)`)); } } console.log(); } // Documentation Results if (results.documentation) { analyzersRun++; const score = results.documentation.score || 0; totalScore += score; console.log(chalk.green('šŸ“š Documentation Analysis:')); console.log(` Score: ${getScoreColor(score)}${score}/100${chalk.reset()}`); console.log(` Coverage: ${results.documentation.coverage}%`); console.log(` Issues: ${results.documentation.issues}`); if (config.documentation?.thresholds.minDocumentationScore && score < config.documentation.thresholds.minDocumentationScore) { console.log(chalk.red(` āŒ Below minimum score threshold (${config.documentation.thresholds.minDocumentationScore})`)); } console.log(); } // Code Quality Results if (results.codeQuality) { analyzersRun++; const score = results.codeQuality.score || 0; totalScore += score; console.log(chalk.magenta('✨ Code Quality Analysis:')); console.log(` Score: ${getScoreColor(score)}${score}/100${chalk.reset()}`); console.log(` Issues: ${results.codeQuality.issues}`); console.log(` Duplicates: ${results.codeQuality.duplicates || 0}`); console.log(` Complexity Issues: ${results.codeQuality.complexityIssues || 0}`); console.log(); } // Cross-Platform Results if (results.crossPlatform) { analyzersRun++; const score = results.crossPlatform.overallScore || 0; totalScore += score; console.log(chalk.cyan('šŸ–„ļø Cross-Platform Analysis:')); console.log(` Score: ${getScoreColor(score)}${score}/100${chalk.reset()}`); console.log(` Risk Level: ${getRiskColor(results.crossPlatform.riskLevel)}${results.crossPlatform.riskLevel}${chalk.reset()}`); console.log(` Issues: ${results.crossPlatform.issues.length}`); // Platform-specific scores if (results.crossPlatform.platformCompatibility) { console.log(' Platform Compatibility:'); for (const [platform, compat] of Object.entries(results.crossPlatform.platformCompatibility)) { if (platform !== 'overall' && typeof compat === 'object') { const platCompat = compat; console.log(` ${platform}: ${getScoreColor(platCompat.score)}${platCompat.score}/100${chalk.reset()} (${platCompat.status})`); } } } console.log(); } // Unused Code Results if (results.unusedCode) { analyzersRun++; const score = results.unusedCode.score || 0; totalScore += score; console.log(chalk.gray('šŸ—‘ļø Unused Code Analysis:')); console.log(` Score: ${getScoreColor(score)}${score}/100${chalk.reset()}`); console.log(` Unused Functions: ${results.unusedCode.unusedFunctions?.length || 0}`); console.log(` Unused Files: ${results.unusedCode.unusedFiles?.length || 0}`); console.log(` Dead Code Blocks: ${results.unusedCode.deadCode?.length || 0}`); console.log(); } // Overall Summary if (analyzersRun > 0) { const overallScore = Math.round(totalScore / analyzersRun); console.log(chalk.bold.cyan('šŸ“ˆ Overall Project Health:')); console.log(` Average Score: ${getScoreColor(overallScore)}${overallScore}/100${chalk.reset()}`); console.log(` Analyzers Run: ${analyzersRun}`); if (errors.length > 0) { console.log(chalk.red(`\nāŒ Errors encountered:`)); errors.forEach(error => console.log(` - ${error}`)); } // Configuration summary console.log(chalk.gray('\nšŸ“‹ Configuration Summary:')); console.log(chalk.gray(` Severity Penalties: Critical=${config.severity.critical}, High=${config.severity.high}, Medium=${config.severity.medium}, Low=${config.severity.low}`)); } else { console.log(chalk.yellow('No analyzers were run. Check your configuration.')); } } function getScoreColor(score) { if (score >= 90) return chalk.green(''); if (score >= 70) return chalk.yellow(''); if (score >= 50) return chalk.rgb(255, 165, 0)(''); // orange return chalk.red(''); } function getRiskColor(risk) { switch (risk) { case 'low': return chalk.green(''); case 'medium': return chalk.yellow(''); case 'high': return chalk.rgb(255, 165, 0)(''); // orange case 'critical': return chalk.red(''); default: return chalk.gray(''); } } //# sourceMappingURL=analyze-configurable.js.map