UNPKG

woaru

Version:

Universal Project Setup Autopilot - Analyze and automatically configure development tools for ANY programming language

693 lines 31.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WAUEngine = void 0; const ProjectAnalyzer_1 = require("../analyzer/ProjectAnalyzer"); const CodeAnalyzer_1 = require("../analyzer/CodeAnalyzer"); const DatabaseManager_1 = require("../database/DatabaseManager"); const PluginManager_1 = require("../plugins/PluginManager"); const ActionManager_1 = require("../actions/ActionManager"); const ProductionReadinessAuditor_1 = require("../auditor/ProductionReadinessAuditor"); const QualityRunner_1 = require("../quality/QualityRunner"); const NotificationManager_1 = require("../supervisor/NotificationManager"); const chalk_1 = __importDefault(require("chalk")); const path = __importStar(require("path")); const child_process_1 = require("child_process"); const util_1 = require("util"); const execAsync = (0, util_1.promisify)(child_process_1.exec); class WAUEngine { constructor() { this.projectAnalyzer = new ProjectAnalyzer_1.ProjectAnalyzer(); this.codeAnalyzer = new CodeAnalyzer_1.CodeAnalyzer(); this.databaseManager = new DatabaseManager_1.DatabaseManager(); this.pluginManager = new PluginManager_1.PluginManager(); this.actionManager = new ActionManager_1.ActionManager(); this.notificationManager = new NotificationManager_1.NotificationManager({ terminal: false, desktop: false, }); this.qualityRunner = new QualityRunner_1.QualityRunner(this.notificationManager); } async analyzeProject(projectPath) { try { console.log(chalk_1.default.blue('🔍 Analyzing project...')); const analysis = await this.projectAnalyzer.analyzeProject(projectPath); const metadata = await this.projectAnalyzer.getProjectMetadata(projectPath); console.log(chalk_1.default.gray(`📦 Project: ${metadata.name} (${metadata.version})`)); console.log(chalk_1.default.gray(`🔧 Language: ${analysis.language}`)); console.log(chalk_1.default.gray(`⚡ Frameworks: ${analysis.framework.join(', ') || 'None detected'}`)); // Analyze code for specific insights console.log(chalk_1.default.blue('🔬 Analyzing codebase for insights...')); const codeInsights = await this.codeAnalyzer.analyzeCodebase(projectPath, analysis.language); // Get recommendations from plugins with code insights const recommendations = this.pluginManager.getAllRecommendations(analysis); // Enhance recommendations with code insights this.enhanceRecommendationsWithInsights(recommendations, codeInsights); const refactorSuggestions = this.pluginManager.getAllRefactorSuggestions(analysis); const frameworkSpecificPackages = this.pluginManager.getAllSpecificPackages(analysis); // Detect already installed tools const installedTools = await this.detectInstalledTools(analysis); // Run comprehensive security analysis console.log(chalk_1.default.blue('🔒 Running comprehensive security analysis...')); const securityResults = await this.runComprehensiveSecurityAnalysis(projectPath); // Run infrastructure security check console.log(chalk_1.default.blue('🛡️ Running infrastructure security audit...')); const infrastructureResults = await this.runInfrastructureSecurityCheck(projectPath); // Run production-readiness audit (including security) console.log(chalk_1.default.blue('🏗️ Running production readiness audit...')); const productionAuditor = new ProductionReadinessAuditor_1.ProductionReadinessAuditor(projectPath); const auditConfig = { language: analysis.language, frameworks: analysis.framework, projectType: this.determineProjectType(analysis), }; const productionAudits = await productionAuditor.auditProject(auditConfig); // Combine all security findings const allSecurityFindings = this.combineSecurityFindings(securityResults, infrastructureResults); // Group production audits by category and priority const securityAudits = productionAudits.filter(audit => audit.category === 'security'); const criticalSecurityAudits = securityAudits.filter(audit => audit.priority === 'critical'); const highSecurityAudits = securityAudits.filter(audit => audit.priority === 'high'); // Calculate comprehensive security metrics const totalCritical = allSecurityFindings.critical + criticalSecurityAudits.length; const totalHigh = allSecurityFindings.high + highSecurityAudits.length; // Log critical security issues immediately if (totalCritical > 0) { console.log(chalk_1.default.red(`🚨 ${totalCritical} critical security issues found across codebase and infrastructure!`)); } if (totalHigh > 0) { console.log(chalk_1.default.yellow(`⚠️ ${totalHigh} high-severity security issues found!`)); } // Generate Claude automation suggestions const claudeAutomations = this.generateClaudeAutomations(analysis); return { setup_recommendations: recommendations.map(r => `Install ${r.tool} for ${r.category}: ${r.reason}`), tool_suggestions: recommendations.map(r => r.tool), framework_specific_tools: frameworkSpecificPackages, refactor_suggestions: refactorSuggestions, installed_tools_detected: installedTools, claude_automations: claudeAutomations, code_insights: Array.from(codeInsights.entries()).map(([tool, insight]) => ({ tool, reason: insight.reason, evidence: insight.evidence, severity: insight.severity, })), // Add production audit results production_audits: productionAudits.map(audit => ({ category: audit.category, check: audit.check, priority: audit.priority, message: audit.message, recommendation: audit.recommendation, packages: audit.packages || [], files: audit.files || [], })), security_summary: { total_issues: allSecurityFindings.total + securityAudits.length, critical: totalCritical, high: totalHigh, medium: allSecurityFindings.medium + securityAudits.filter(audit => audit.priority === 'medium').length, low: allSecurityFindings.low + securityAudits.filter(audit => audit.priority === 'low').length, health_score: this.calculateComprehensiveSecurityScore(allSecurityFindings, securityAudits, infrastructureResults), // Extended security metrics secrets_found: allSecurityFindings.secrets, vulnerabilities_found: allSecurityFindings.vulnerabilities, infrastructure_issues: infrastructureResults?.findings?.length || 0, tools_used: this.getSecurityToolsUsed(securityResults, infrastructureResults), recommendations: this.generateSecurityRecommendations(allSecurityFindings, securityAudits), }, // Add detailed security results (extended data) detailed_security: { dependency_vulnerabilities: securityResults, infrastructure_security: infrastructureResults, configuration_audits: securityAudits, }, }; // Extended with comprehensive security analysis } catch (error) { throw new Error(`Analysis failed: ${error instanceof Error ? error.message : 'Unknown error'}`); } } async setupProject(projectPath, options = {}) { try { const analysis = await this.projectAnalyzer.analyzeProject(projectPath); const recommendations = this.pluginManager.getAllRecommendations(analysis); if (recommendations.length === 0) { console.log(chalk_1.default.green('✅ Project is already well configured!')); return true; } console.log(chalk_1.default.blue(`🎯 Found ${recommendations.length} recommendations`)); if (options.dryRun) { console.log(chalk_1.default.yellow('🔍 Dry run mode - showing what would be done:')); recommendations.forEach(rec => { console.log(chalk_1.default.gray(` • ${rec.tool}: ${rec.reason}`)); }); return true; } const result = await this.actionManager.executeRecommendations(projectPath, recommendations, options); return result.success; } catch (error) { console.error(chalk_1.default.red(`❌ Setup failed: ${error instanceof Error ? error.message : 'Unknown error'}`)); return false; } } async updateDatabase() { console.log(chalk_1.default.blue('📡 Updating tools database...')); const success = await this.databaseManager.updateDatabase(); if (success) { console.log(chalk_1.default.green('✅ Database updated successfully')); } else { console.log(chalk_1.default.red('❌ Failed to update database')); } return success; } async detectInstalledTools(analysis) { try { const installedTools = []; const allDeps = [...analysis.dependencies, ...analysis.devDependencies]; const toolChecks = this.getToolChecks(); const projectPath = this.getValidatedProjectPath(analysis.projectPath); for (const [tool, check] of Object.entries(toolChecks)) { const hasPackage = this.checkPackageDependency(check.packages, allDeps); const hasConfig = await this.checkConfigFiles(check.configs || [], projectPath); if (hasPackage || hasConfig) { installedTools.push(tool); } } return installedTools; } catch (error) { console.warn(`Warning: Tool detection failed: ${error instanceof Error ? error.message : 'Unknown error'}`); return []; } } getToolChecks() { return { eslint: { packages: ['eslint'], configs: [ '.eslintrc.js', '.eslintrc.json', '.eslintrc.yml', '.eslintrc.yaml', '.eslintrc', 'eslint.config.js', ], }, prettier: { packages: ['prettier'], configs: [ '.prettierrc', '.prettierrc.json', '.prettierrc.yml', '.prettierrc.yaml', '.prettierrc.js', 'prettier.config.js', ], }, husky: { packages: ['husky'], configs: ['.husky', '.git/hooks'], }, jest: { packages: ['jest'], configs: ['jest.config.js', 'jest.config.ts', 'jest.config.json'], }, typescript: { packages: ['typescript'], configs: ['tsconfig.json'], }, tailwindcss: { packages: ['tailwindcss'], configs: ['tailwind.config.js', 'tailwind.config.ts'], }, postcss: { packages: ['postcss'], configs: ['postcss.config.js', 'postcss.config.ts'], }, commitlint: { packages: ['@commitlint/cli', '@commitlint/config-conventional'], configs: [ 'commitlint.config.js', '.commitlintrc.js', '.commitlintrc.json', ], }, webpack: { packages: ['webpack'], configs: ['webpack.config.js', 'webpack.config.ts'], }, vite: { packages: ['vite'], configs: ['vite.config.js', 'vite.config.ts'], }, rollup: { packages: ['rollup'], configs: ['rollup.config.js', 'rollup.config.ts'], }, babel: { packages: ['@babel/core', 'babel-core'], configs: [ '.babelrc', '.babelrc.js', '.babelrc.json', 'babel.config.js', ], }, }; } getValidatedProjectPath(projectPath) { const validPath = projectPath || process.cwd(); try { return path.resolve(validPath); } catch { throw new Error(`Invalid project path: ${validPath}`); } } checkPackageDependency(packages, allDeps) { return packages.some(pkg => allDeps.includes(pkg)); } async checkConfigFiles(configFiles, projectPath) { const fs = await Promise.resolve().then(() => __importStar(require('fs-extra'))); for (const configFile of configFiles) { try { const configPath = path.join(projectPath, configFile); if (await fs.pathExists(configPath)) { return true; } } catch { // Continue checking other config files continue; } } return false; } generateClaudeAutomations(analysis) { const automations = []; // Framework-specific automations if (analysis.framework.includes('nextjs')) { automations.push('Generate Next.js API routes with proper TypeScript types'); automations.push('Create reusable Next.js components with proper prop types'); automations.push('Setup Next.js middleware for authentication'); } if (analysis.framework.includes('react')) { automations.push('Refactor class components to functional components with hooks'); automations.push('Generate custom hooks for common functionality'); automations.push('Create component documentation with Storybook'); } // Language-specific automations if (analysis.language === 'TypeScript') { automations.push('Generate TypeScript interfaces from API responses'); automations.push('Add strict typing to existing JavaScript functions'); automations.push('Create utility types for better type safety'); } // Testing automations if (!analysis.devDependencies.includes('jest') && !analysis.devDependencies.includes('vitest')) { automations.push('Setup testing framework with example tests'); automations.push('Generate unit tests for existing components'); } // Documentation automations automations.push('Generate README.md with project setup instructions'); automations.push('Create CONTRIBUTING.md with development guidelines'); automations.push('Generate API documentation from code comments'); return automations; } enhanceRecommendationsWithInsights(recommendations, codeInsights) { recommendations.forEach((rec) => { const insight = codeInsights.get(rec.tool); if (insight) { rec.reason = insight.reason; rec.evidence = insight.evidence; rec.priority = insight.severity === 'critical' ? 'high' : insight.severity === 'high' ? 'high' : insight.severity === 'medium' ? 'medium' : 'low'; } }); } determineProjectType(analysis) { // Check for frontend frameworks const frontendFrameworks = ['react', 'vue', 'angular', 'svelte', 'next']; const hasFrontend = analysis.framework.some(f => frontendFrameworks.includes(f)); // Check for backend frameworks const backendFrameworks = ['express', 'fastify', 'koa', 'nest']; const hasBackend = analysis.framework.some(f => backendFrameworks.includes(f)); // Check dependencies for more clues const allDeps = [...analysis.dependencies, ...analysis.devDependencies]; const hasServerDeps = allDeps.some(dep => ['express', 'fastify', 'koa', '@nestjs/core', 'http-server'].includes(dep)); const hasFrontendDeps = allDeps.some(dep => ['react', 'vue', '@angular/core', 'svelte'].includes(dep)); // Check for CLI tools const hasCliDeps = allDeps.some(dep => ['commander', 'yargs', 'inquirer', '@oclif/core'].includes(dep)); // Determine type based on evidence if (hasCliDeps) return 'cli'; if (hasFrontend && (hasBackend || hasServerDeps)) return 'fullstack'; if (hasFrontend || hasFrontendDeps) return 'frontend'; if (hasBackend || hasServerDeps) return 'backend'; // Default to library if no clear indicators return 'library'; } calculateSecurityHealthScore(securityAudits) { if (securityAudits.length === 0) return 100; let score = 100; securityAudits.forEach(audit => { switch (audit.priority) { case 'critical': score -= 25; break; case 'high': score -= 15; break; case 'medium': score -= 8; break; case 'low': score -= 3; break; } }); return Math.max(0, score); } /** * Run comprehensive security analysis using multiple tools */ async runComprehensiveSecurityAnalysis(projectPath) { console.log(chalk_1.default.gray(' Running Snyk + Gitleaks security scan...')); try { // Get all project files for security scanning const allFiles = []; // For comprehensive analysis, we can scan the entire project const securityResults = await this.qualityRunner.runSecurityChecksForReview(allFiles); // Log summary of findings let totalFindings = 0; let criticalFindings = 0; securityResults.forEach(result => { totalFindings += result.summary.total; criticalFindings += result.summary.critical; if (result.error) { console.log(chalk_1.default.red(` ⚠️ ${result.tool}: ${result.error}`)); } else if (result.summary.total > 0) { console.log(chalk_1.default.yellow(` 🔍 ${result.tool}: ${result.summary.total} issues found`)); } else { console.log(chalk_1.default.green(` ✅ ${result.tool}: No issues found`)); } }); if (criticalFindings > 0) { console.log(chalk_1.default.red(` 🚨 ${criticalFindings} critical security vulnerabilities detected!`)); } return securityResults; } catch (error) { console.log(chalk_1.default.red(` ❌ Security analysis failed: ${error}`)); return []; } } /** * Run infrastructure security check using Trivy */ async runInfrastructureSecurityCheck(projectPath) { console.log(chalk_1.default.gray(' Scanning containers and infrastructure...')); try { // Check if Trivy is installed await execAsync('which trivy'); const findings = []; const scanTargets = []; // Look for Docker files const dockerFile = path.join(projectPath, 'Dockerfile'); if (await this.fileExists(dockerFile)) { scanTargets.push({ type: 'dockerfile', path: dockerFile }); } // Look for docker-compose files const composeFiles = [ 'docker-compose.yml', 'docker-compose.yaml', 'compose.yml', ]; for (const file of composeFiles) { const composePath = path.join(projectPath, file); if (await this.fileExists(composePath)) { scanTargets.push({ type: 'compose', path: composePath }); } } // Look for Kubernetes manifests const k8sDir = path.join(projectPath, 'k8s'); if (await this.fileExists(k8sDir)) { scanTargets.push({ type: 'kubernetes', path: k8sDir }); } // Scan each target for (const target of scanTargets) { try { const { stdout } = await execAsync(`trivy config --format json "${target.path}"`, { cwd: projectPath, maxBuffer: 10 * 1024 * 1024 }); if (stdout) { const results = JSON.parse(stdout); if (results.Results) { results.Results.forEach((result) => { if (result.Misconfigurations) { result.Misconfigurations.forEach((misc) => { findings.push({ tool: 'trivy', type: 'misconfiguration', severity: misc.Severity?.toLowerCase() || 'medium', title: misc.Title, description: misc.Description, file: target.path, recommendation: misc.Resolution, references: misc.References, }); }); } }); } } console.log(chalk_1.default.green(` ✅ Trivy: Scanned ${target.type} - ${target.path}`)); } catch (scanError) { console.log(chalk_1.default.yellow(` ⚠️ Trivy: Failed to scan ${target.path}`)); } } if (scanTargets.length === 0) { console.log(chalk_1.default.gray(' 📋 No infrastructure files found to scan')); return null; } const summary = { total: findings.length, critical: findings.filter(f => f.severity === 'critical').length, high: findings.filter(f => f.severity === 'high').length, medium: findings.filter(f => f.severity === 'medium').length, low: findings.filter(f => f.severity === 'low').length, info: findings.filter(f => f.severity === 'info').length, }; if (findings.length > 0) { console.log(chalk_1.default.yellow(` 🛡️ Trivy: ${findings.length} infrastructure issues found`)); } else { console.log(chalk_1.default.green(` ✅ Trivy: No infrastructure issues found`)); } return { tool: 'trivy', scanTime: new Date(), findings, summary, targets_scanned: scanTargets.length, }; } catch (error) { if (error instanceof Error && error.message.includes('command not found')) { console.log(chalk_1.default.gray(' 📋 Trivy not installed - skipping infrastructure scan')); console.log(chalk_1.default.gray(' 💡 Install with: brew install trivy (macOS) or apt-get install trivy (Linux)')); } else { console.log(chalk_1.default.red(` ❌ Infrastructure scan failed: ${error}`)); } return null; } } /** * Combine security findings from different tools */ combineSecurityFindings(securityResults, infrastructureResults) { let total = 0; let critical = 0; let high = 0; let medium = 0; let low = 0; let secrets = 0; let vulnerabilities = 0; // Count findings from security tools (Snyk, Gitleaks) securityResults.forEach(result => { total += result.summary.total; critical += result.summary.critical; high += result.summary.high; medium += result.summary.medium; low += result.summary.low; if (result.tool === 'gitleaks') { secrets += result.findings.length; } else if (result.tool === 'snyk') { vulnerabilities += result.findings.length; } }); // Add infrastructure findings if (infrastructureResults) { total += infrastructureResults.summary.total; critical += infrastructureResults.summary.critical; high += infrastructureResults.summary.high; medium += infrastructureResults.summary.medium; low += infrastructureResults.summary.low; } return { total, critical, high, medium, low, secrets, vulnerabilities, }; } /** * Calculate comprehensive security score including all security aspects */ calculateComprehensiveSecurityScore(allFindings, securityAudits, infrastructureResults) { let score = 100; // Penalize based on security findings score -= allFindings.critical * 30; // Critical vulnerabilities are severe score -= allFindings.high * 20; score -= allFindings.medium * 10; score -= allFindings.low * 3; score -= allFindings.secrets * 25; // Exposed secrets are very serious // Penalize based on production audit findings securityAudits.forEach(audit => { switch (audit.priority) { case 'critical': score -= 25; break; case 'high': score -= 15; break; case 'medium': score -= 8; break; case 'low': score -= 3; break; } }); // Penalize for infrastructure issues if (infrastructureResults) { score -= infrastructureResults.summary.critical * 20; score -= infrastructureResults.summary.high * 12; score -= infrastructureResults.summary.medium * 6; } return Math.max(0, Math.min(100, score)); } /** * Get list of security tools that were used in the analysis */ getSecurityToolsUsed(securityResults, infrastructureResults) { const tools = new Set(); securityResults.forEach(result => { if (!result.error) { tools.add(result.tool); } }); if (infrastructureResults && !infrastructureResults.error) { tools.add('trivy'); } return Array.from(tools); } /** * Generate actionable security recommendations */ generateSecurityRecommendations(allFindings, securityAudits) { const recommendations = []; if (allFindings.critical > 0) { recommendations.push(`🚨 URGENT: Fix ${allFindings.critical} critical security vulnerabilities immediately`); } if (allFindings.secrets > 0) { recommendations.push(`🔐 URGENT: Remove ${allFindings.secrets} exposed secrets from codebase and rotate them`); } if (allFindings.vulnerabilities > 0) { recommendations.push(`📦 Update vulnerable dependencies - ${allFindings.vulnerabilities} packages need attention`); } if (allFindings.high > 0) { recommendations.push(`⚠️ Address ${allFindings.high} high-severity security issues`); } const criticalAudits = securityAudits.filter(a => a.priority === 'critical'); if (criticalAudits.length > 0) { recommendations.push(`🔧 Configure missing security tools: ${criticalAudits.map(a => a.check).join(', ')}`); } if (recommendations.length === 0) { recommendations.push('✅ No critical security issues found - maintain good security hygiene'); } return recommendations; } /** * Helper to check if file exists */ async fileExists(filePath) { try { const fs = require('fs-extra'); return await fs.pathExists(filePath); } catch { return false; } } } exports.WAUEngine = WAUEngine; //# sourceMappingURL=WAUEngine.js.map