UNPKG

mira-consciousness

Version:

Memory & Intelligence Retention Archive - Preserving The Spark

370 lines 16 kB
/** * Cross-Platform Analyzer Orchestrator * Coordinates all cross-platform compatibility analysis modules */ import { FileSystemAnalyzer } from './FileSystemAnalyzer.js'; import { ShellCommandAnalyzer } from './ShellCommandAnalyzer.js'; import { EnvironmentAnalyzer } from './EnvironmentAnalyzer.js'; export class CrossPlatformAnalyzer { projectRoot; fileSystemAnalyzer; shellCommandAnalyzer; environmentAnalyzer; constructor(projectRoot) { this.projectRoot = projectRoot; this.fileSystemAnalyzer = new FileSystemAnalyzer(projectRoot); this.shellCommandAnalyzer = new ShellCommandAnalyzer(projectRoot); this.environmentAnalyzer = new EnvironmentAnalyzer(projectRoot); } async analyze() { const issues = []; // Run all analyzers in parallel const [fileSystemAnalysis, shellAnalysis, environmentAnalysis] = await Promise.all([ this.fileSystemAnalyzer.analyze(issues), this.shellCommandAnalyzer.analyze(issues), this.environmentAnalyzer.analyze(issues) ]); // Merge shell analysis into environment analysis environmentAnalysis.shellCompatibility = shellAnalysis; environmentAnalysis.fileSystemRequirements = fileSystemAnalysis; // Analyze platform compatibility const platformCompatibility = this.calculatePlatformCompatibility(issues); // Calculate platform-specific issues const platformSpecificIssues = this.categorizePlatformIssues(issues); // Calculate overall score and risk const { overallScore, riskLevel } = this.calculateOverallScore(issues, platformCompatibility); // Generate recommendations const recommendations = this.generateRecommendations(issues, platformCompatibility, environmentAnalysis); return { issues, platformCompatibility, overallScore, riskLevel, recommendations, platformSpecificIssues, environmentAnalysis }; } calculatePlatformCompatibility(issues) { const platforms = ['windows', 'macOS', 'linux', 'unix']; const compatibility = this.initializePlatformCompatibility(); // Count issues per platform this.countIssuesPerPlatform(issues, compatibility, platforms); // Calculate scores for each platform platforms.forEach(platform => { this.calculatePlatformScore(compatibility[platform]); }); // Calculate overall compatibility this.calculateOverallCompatibility(issues, compatibility); return compatibility; } initializePlatformCompatibility() { const createCompatLevel = () => ({ score: 100, issues: 0, critical: 0, status: 'excellent' }); return { windows: createCompatLevel(), macOS: createCompatLevel(), linux: createCompatLevel(), unix: createCompatLevel(), overall: createCompatLevel() }; } countIssuesPerPlatform(issues, compatibility, platforms) { issues.forEach(issue => { issue.affectedPlatforms.forEach(platform => { if (platform === 'all') { this.incrementAllPlatforms(compatibility, platforms, issue); } else if (platform in compatibility) { this.incrementPlatform(compatibility[platform], issue); } }); }); } incrementAllPlatforms(compatibility, platforms, issue) { platforms.forEach(p => this.incrementPlatform(compatibility[p], issue)); } incrementPlatform(platComp, issue) { platComp.issues++; if (issue.severity === 'critical') { platComp.critical++; } } calculatePlatformScore(comp) { const criticalPenalty = comp.critical * 15; const issuePenalty = comp.issues > 0 ? Math.log10(comp.issues + 1) * 10 : 0; const penalty = criticalPenalty + issuePenalty; comp.score = Math.max(0, Math.round(100 - penalty)); comp.status = this.getStatusFromScore(comp.score); } calculateOverallCompatibility(issues, compatibility) { const severityCounts = this.countIssueBySeverity(issues); compatibility.overall.issues = issues.length; compatibility.overall.critical = severityCounts.critical; const penalty = this.calculateOverallPenalty(severityCounts, issues.length); compatibility.overall.score = Math.max(0, Math.round(100 - penalty)); compatibility.overall.status = this.getStatusFromScore(compatibility.overall.score); } countIssueBySeverity(issues) { return issues.reduce((counts, issue) => { if (issue.severity === 'critical') counts.critical++; else if (issue.severity === 'high') counts.high++; return counts; }, { critical: 0, high: 0 }); } calculateOverallPenalty(severityCounts, totalIssues) { const criticalPenalty = severityCounts.critical * 15; const highPenalty = severityCounts.high * 5; const otherPenalty = totalIssues > 0 ? Math.log10(totalIssues + 1) * 15 : 0; return criticalPenalty + highPenalty + otherPenalty; } getStatusFromScore(score) { if (score >= 90) return 'excellent'; if (score >= 75) return 'good'; if (score >= 50) return 'fair'; if (score >= 25) return 'poor'; return 'incompatible'; } categorizePlatformIssues(issues) { const categorized = { windows: [], macOS: [], linux: [], unix: [] }; const typeMap = new Map(); for (const issue of issues) { for (const platform of issue.affectedPlatforms) { if (platform === 'all') { // Add to all platforms for (const p of ['windows', 'macOS', 'linux', 'unix']) { this.addToPlatformIssues(p, issue, typeMap); } } else if (platform in categorized) { this.addToPlatformIssues(platform, issue, typeMap); } } } // Convert map to arrays for (const [platform, types] of typeMap.entries()) { const platKey = platform; categorized[platKey] = Array.from(types.values()) .sort((a, b) => { const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 }; return severityOrder[a.severity] - severityOrder[b.severity]; }); } return categorized; } addToPlatformIssues(platform, issue, typeMap) { if (!typeMap.has(platform)) { typeMap.set(platform, new Map()); } const platformMap = typeMap.get(platform); if (!platformMap.has(issue.type)) { platformMap.set(issue.type, { type: issue.type, message: issue.message, files: [], severity: issue.severity }); } const platformIssue = platformMap.get(issue.type); platformIssue.files.push(issue.file + (issue.line ? `:${issue.line}` : '')); // Update severity to highest const severityOrder = { critical: 0, high: 1, medium: 2, low: 3 }; if (severityOrder[issue.severity] < severityOrder[platformIssue.severity]) { platformIssue.severity = issue.severity; } } calculateOverallScore(issues, compatibility) { const overallScore = compatibility.overall.score; let riskLevel; const criticalCount = issues.filter(i => i.severity === 'critical').length; const highCount = issues.filter(i => i.severity === 'high').length; if (criticalCount > 0 || overallScore < 30) { riskLevel = 'critical'; } else if (highCount >= 5 || overallScore < 50) { riskLevel = 'high'; } else if (highCount >= 1 || overallScore < 70) { riskLevel = 'medium'; } else { riskLevel = 'low'; } return { overallScore, riskLevel }; } // Recommendation generators configuration RECOMMENDATION_CONFIGS = [ { filter: (issues) => issues.filter(i => i.severity === 'critical'), condition: (filtered) => filtered.length > 0, generator: (filtered) => ({ priority: 'critical', category: 'Critical Compatibility Issues', title: 'Address Critical Cross-Platform Issues', description: `${filtered.length} critical issues prevent cross-platform compatibility`, platforms: ['all'], actionItems: [ 'Fix all critical issues immediately', 'Test on all target platforms', 'Use cross-platform alternatives for platform-specific code' ] }) }, { filter: (issues) => issues.filter(i => i.type.includes('path')), condition: (filtered) => filtered.length > 0, generator: (filtered) => ({ priority: 'high', category: 'Path Handling', title: 'Use Cross-Platform Path Handling', description: `${filtered.length} path-related issues found`, platforms: ['all'], actionItems: [ 'Always use path.join() instead of string concatenation', 'Use path.sep instead of hardcoded separators', 'Avoid hardcoded absolute paths', 'Use path.resolve() for absolute paths' ], codeExamples: { bad: `const file = __dirname + '/config/' + name + '.json';`, good: `const file = path.join(__dirname, 'config', name + '.json');` } }) }, { filter: (issues) => issues.filter(i => i.type.includes('command') || i.type.includes('shell')), condition: (filtered) => filtered.length > 0, generator: (filtered) => ({ priority: 'high', category: 'Shell Commands', title: 'Avoid Platform-Specific Shell Commands', description: `${filtered.length} shell command compatibility issues`, platforms: ['all'], actionItems: [ 'Use Node.js APIs instead of shell commands', 'If shell commands are necessary, check platform first', 'Use cross-platform npm packages for common operations', 'Test shell scripts on all target platforms' ] }) }, { filter: (issues) => issues.filter(i => i.type.includes('env')), condition: (filtered) => filtered.length > 0, generator: (filtered) => ({ priority: 'medium', category: 'Environment Variables', title: 'Handle Platform-Specific Environment Variables', description: `${filtered.length} environment variable issues`, platforms: ['all'], actionItems: [ 'Use os.homedir() instead of HOME/USERPROFILE', 'Use os.tmpdir() instead of TEMP/TMPDIR', 'Check for variable existence before use', 'Provide fallback values for missing variables' ], codeExamples: { bad: `const home = process.env.HOME;`, good: `const home = os.homedir();` } }) } ]; generateRecommendations(issues, compatibility, environmentAnalysis) { const recommendations = []; // Generate issue-based recommendations this.RECOMMENDATION_CONFIGS.forEach(config => { const filtered = config.filter(issues); if (config.condition(filtered)) { recommendations.push(config.generator(filtered)); } }); // Platform-specific recommendations this.addPlatformSpecificRecommendations(compatibility, issues, recommendations); // Native module recommendations if (environmentAnalysis.dependencies.some((d) => d.nativeModules)) { recommendations.push({ priority: 'medium', category: 'Dependencies', title: 'Native Module Compatibility', description: 'Project uses native modules requiring compilation', platforms: ['all'], actionItems: [ 'Document build requirements for each platform', 'Consider using prebuilt binaries', 'Provide fallback pure JavaScript alternatives', 'Test native module installation on all platforms' ] }); } // General best practices recommendations.push({ priority: 'low', category: 'Best Practices', title: 'Cross-Platform Development Guidelines', description: 'Follow these practices for better compatibility', platforms: ['all'], actionItems: [ 'Always test on Windows, macOS, and Linux', 'Use CI/CD to test on multiple platforms', 'Prefer Node.js built-in modules over shell commands', 'Document any platform-specific requirements', 'Use ESLint with platform-specific rules', 'Configure Git for consistent line endings' ] }); return recommendations; } getPlatformSpecificActions(platform, issues) { const platformIssues = issues.filter(i => i.affectedPlatforms.includes(platform)); const actions = []; const issueTypes = new Set(platformIssues.map(i => i.type)); if (platform === 'windows') { if (issueTypes.has('unix_command')) { actions.push('Replace Unix commands with Node.js APIs or cross-platform tools'); } if (issueTypes.has('unix_path')) { actions.push('Use path module for all file paths'); } if (issueTypes.has('file_permissions')) { actions.push('Handle file permissions gracefully on Windows'); } } else { if (issueTypes.has('windows_command')) { actions.push('Replace Windows commands with cross-platform alternatives'); } if (issueTypes.has('windows_path')) { actions.push('Avoid Windows-style paths'); } } return actions.length > 0 ? actions : ['Review and fix platform-specific issues']; } addPlatformSpecificRecommendations(compatibility, issues, recommendations) { Object.entries(compatibility).forEach(([platform, compat]) => { if (platform !== 'overall' && compat.score < 70) { recommendations.push({ priority: compat.score < 50 ? 'high' : 'medium', category: 'Platform Compatibility', title: `Improve ${platform} Compatibility`, description: `${platform} compatibility score: ${compat.score}/100`, platforms: [platform], actionItems: this.getPlatformSpecificActions(platform, issues) }); } }); } } //# sourceMappingURL=CrossPlatformAnalyzer.js.map