UNPKG

agentsqripts

Version:

Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems

220 lines (196 loc) 8.97 kB
#!/usr/bin/env node /** * @file Command-line interface for scalability analysis and bottleneck detection * @description Single responsibility: Provide interactive CLI for identifying scalability concerns * * This CLI tool serves as the scalability analysis interface for the AgentSqripts platform, * detecting blocking operations, N+1 query patterns, unbounded memory growth, and other * performance bottlenecks that impact application scalability under load. It implements * severity-based filtering, category analysis, and comprehensive reporting to support * systematic scalability optimization workflows. * * Design rationale: * - Scalability-focused analysis enables proactive performance planning * - Category filtering (API, Database, Infrastructure) enables targeted optimization * - Severity thresholds help prioritize critical scalability threats * - Multiple output formats support both development analysis and CI/CD integration * - Comprehensive detection coverage from database patterns to system resource usage */ const fs = require('fs'); const { promises: fsPromises } = require('fs'); const path = require('path'); const { analyzeProjectScalability, analyzeFileScalability } = require('../lib/scalability/analyzeScalability'); const { formatResults, getGradeEmoji, formatSeverity } = require('./lib/commonFormatters'); const { createSummaryFormatter, createRecommendationsSection, createTopIssuesSection } = require('./lib/summaryFormatter'); const { createDetailedFormatter, formatIssueWithIcons } = require('./lib/detailedFormatter'); /** * Display help information */ const { createHelpFunction } = require('./lib/helpFormatter'); const { parseArgs: sharedParseArgs } = require('./lib/argumentParser'); const { handleAnalysisError } = require('./lib/errorHandler'); const showHelp = createHelpFunction({ command: 'analyze-scalability.js', description: 'Analyzes code for scalability bottlenecks including blocking sync operations, N+1 queries,\nunbounded memory growth, and other performance issues that can hurt application scalability.', options: [ { flag: '--extensions <exts>', description: 'Comma-separated list of file extensions (default: .js,.ts,.jsx,.tsx)' }, { flag: '--output-format <fmt>', description: 'Output format: json, summary, detailed (default: summary)' }, { flag: '--severity <level>', description: 'Minimum severity to report: LOW, MEDIUM, HIGH, CRITICAL (default: LOW)' }, { flag: '--category <cat>', description: 'Filter by category: API, Database, Infrastructure (default: all)' }, { flag: '--max-files <num>', description: 'Maximum number of files to analyze (default: all files)' }, { flag: '--help', description: 'Show this help message' } ], modes: ' file Analyze a single file\n project Analyze entire project (default)', examples: [ 'node analyze-scalability.js .', 'node analyze-scalability.js --severity HIGH src/', 'node analyze-scalability.js --output-format json --extensions .js,.ts .', 'node analyze-scalability.js --category Database --output-format detailed src/' ], output: ' The tool identifies scalability bottlenecks by checking:\n - Blocking synchronous operations (fs.readFileSync, execSync)\n - N+1 query patterns (database calls in loops)\n - Per-request file I/O operations\n - Unbounded memory growth patterns\n - CPU-intensive operations in request paths\n - Inefficient string operations', sections: { 'ISSUE TYPES': ' 🚨 CRITICAL: Immediate scalability threats\n ⚠️ HIGH: Major bottlenecks affecting performance\n 📊 MEDIUM: Moderate scalability concerns\n 📝 LOW: Minor optimizations', 'CATEGORIES': ' 📡 API: Request/response path issues\n 🗄️ Database: Data access bottlenecks\n 🏗️ Infrastructure: System resource issues' } }); // Removed duplicate formatResults - now using shared version from commonFormatters // Create custom summary formatter using shared utility const formatSummary = createSummaryFormatter({ title: '🚨 Scalability Analysis Results', scoreField: 'scalabilityScore', gradeField: 'scalabilityGrade', filesField: 'totalFiles', issuesField: 'totalIssues', customMetrics: [ { field: 'filesWithIssues', icon: '⚠️', label: 'Files with Issues' } ], breakdowns: [ { field: 'severityBreakdown', type: 'severity', icon: '📈', title: 'Issue Breakdown', levels: ['CRITICAL', 'HIGH', 'MEDIUM', 'LOW'] }, { field: 'categoryBreakdown', type: 'category', icon: '🏷️', title: 'Category Breakdown', icons: { 'API': '📡', 'Database': '🗄️', 'Infrastructure': '🏗️' } } ], customSections: [ createRecommendationsSection(), createTopIssuesSection({ field: 'issues', title: 'Top Scalability Issues', limit: 10, formatItem: (issue, i) => { const severityIcon = issue.severity === 'CRITICAL' ? '🚨' : issue.severity === 'HIGH' ? '⚠️' : issue.severity === 'MEDIUM' ? '📊' : '📝'; const categoryIcon = issue.category === 'API' ? '📡' : issue.category === 'Database' ? '🗄️' : '🏗️'; const fileInfo = issue.file ? `\n 📁 File: ${path.relative('.', issue.file)}` : ''; const lineInfo = issue.line ? `:${issue.line}` : ''; return ` ${i + 1}. ${severityIcon} ${categoryIcon} ${issue.type}${fileInfo}${lineInfo}\n 📍 ${issue.summary}\n 💡 ${issue.recommendation}\n 🎯 Impact: ${issue.impact}`; } }) ] }); // Old formatSummary implementation fully removed - using shared formatter // Old formatDetailed removed - using shared detailed formatter // Replace with shared detailed formatter const formatDetailedNew = createDetailedFormatter({ title: '🔍 Detailed Scalability Analysis', formatSummary: formatSummary, filesField: 'files', issuesField: 'issues', formatFile: (fileData) => { return `📄 ${path.relative('.', fileData.file)} (Score: ${fileData.scalabilityScore}/100)\n`; }, formatIssue: (issue) => { const icons = { severity: { 'CRITICAL': '🚨', 'HIGH': '⚠️', 'MEDIUM': '📊', 'LOW': '📝' }, category: { 'API': '📡', 'Database': '🗄️', 'Infrastructure': '🏗️' } }; const lines = formatIssueWithIcons(issue, icons); // Add pattern info if available if (issue.pattern) { lines.splice(1, 0, ` 📊 Pattern: ${issue.pattern}`); } return lines; } }); /** * Main function */ async function main() { const { getProcessArgs } = require('../lib/utils/processHelpers'); const args = getProcessArgs(); const { shouldShowHelp } = require('../lib/utils/cliHelpers'); if (shouldShowHelp(args)) { showHelp(); return; } // Parse arguments using shared parser const { options: parsedOptions, targetPath: parsedPath, error } = sharedParseArgs(args, { defaults: { extensions: ['.js', '.ts', '.jsx', '.tsx'], outputFormat: 'summary', severity: 'LOW', category: null, maxFiles: Infinity }, flags: { extensions: { type: 'list' }, outputFormat: { type: 'string' }, severity: { type: 'string', transform: (v) => v.toUpperCase() }, category: { type: 'string' }, maxFiles: { type: 'number' } } }); if (error) { const { logAnalysisError } = require('../lib/utils/errorMessages'); logAnalysisError('scalability', error); process.exit(1); } const { extensions, outputFormat, severity, category, maxFiles } = parsedOptions; const targetPath = parsedPath; try { // Check if target is a file or directory const stat = await fsPromises.stat(targetPath); let results; if (stat.isFile()) { // Analyze single file results = await analyzeFileScalability(targetPath); } else { // Analyze project results = await analyzeProjectScalability(targetPath, { extensions, excludePatterns: ['node_modules', '.git', 'dist', 'build', 'coverage'], maxFiles // Use CLI option or default to all files }); } // Output results const formatted = formatResults(results, outputFormat, { severity, category }, formatSummary, formatDetailedNew); console.log(formatted); // Exit with error code if critical issues found const hasCritical = results.summary ? results.summary.severityBreakdown.CRITICAL > 0 : results.issues.some(i => i.severity === 'CRITICAL'); if (hasCritical) { process.exit(1); } } catch (error) { handleAnalysisError(error, 'scalability'); } } if (require.main === module) { main().catch(error => { console.error("Fatal error:", error); process.exit(1); }); }