UNPKG

stack-performance

Version:

A comprehensive application stack analyzer that evaluates MEAN, MERN, and other Node.js-based applications across 15 performance criteria

277 lines (226 loc) 9.13 kB
const fs = require('fs-extra'); const path = require('path'); // Create all remaining analyzer files const analyzers = [ 'DeveloperProductivityAnalyzer', 'ApiResponseTimeAnalyzer', 'LearningCurveAnalyzer', 'SecurityFeaturesAnalyzer', 'ToolingEcosystemAnalyzer', 'MongoIntegrationAnalyzer', 'ModularityScalabilityAnalyzer', 'PackageEcosystemAnalyzer', 'StartupTimeAnalyzer', 'MaintenanceDebuggingAnalyzer', 'HostingDeploymentAnalyzer', 'MemoryCpuEfficiencyAnalyzer', 'ConcurrentLoadAnalyzer', 'MonitoringObservabilityAnalyzer' ]; // Template for analyzer const createAnalyzerContent = (className, criterionName) => `const BaseAnalyzer = require('./BaseAnalyzer'); /** * ${criterionName} Analyzer with algorithmic scoring */ class ${className} extends BaseAnalyzer { constructor(stackInfo, projectPath) { super(stackInfo, projectPath, '${criterionName}'); } async analyze() { const factors = []; ${getAnalysisFactors(criterionName)} const finalScore = this.calculateWeightedScore(factors); const details = { stackType: this.stackInfo.type, analysisMethod: 'algorithmic', factors: factors.map(f => ({ score: f.score, weight: f.weight })) }; return this.createResult(finalScore, details, this.generateRecommendations(finalScore)); } ${getSpecificMethods(criterionName)} generateRecommendations(score) { const recommendations = []; if (score < 70) { recommendations.push(`Improve ${criterionName.toLowerCase()} through targeted optimizations`); } return recommendations; } } module.exports = ${className};`; // Get analysis factors based on criterion function getAnalysisFactors(criterionName) { const factorMap = { 'Developer Productivity': ` // Factor 1: Development Tools (40%) const toolingScore = this.analyzeToolingSupport(); factors.push({ score: toolingScore, weight: 0.4 }); // Factor 2: Framework Learning Curve (30%) const learningScore = this.analyzeLearningComplexity(); factors.push({ score: learningScore, weight: 0.3 }); // Factor 3: Documentation & Community (20%) const communityScore = this.analyzeCommunitySupport(); factors.push({ score: communityScore, weight: 0.2 }); // Factor 4: Code Reusability (10%) const reusabilityScore = this.analyzeCodeReusability(); factors.push({ score: reusabilityScore, weight: 0.1 });`, 'API Response Time': ` // Factor 1: Framework Efficiency (35%) const frameworkScore = this.analyzeFrameworkEfficiency(); factors.push({ score: frameworkScore, weight: 0.35 }); // Factor 2: Database Query Optimization (25%) const dbOptScore = this.analyzeDatabaseOptimization(); factors.push({ score: dbOptScore, weight: 0.25 }); // Factor 3: Middleware Overhead (25%) const middlewareScore = this.analyzeMiddlewareEfficiency(); factors.push({ score: middlewareScore, weight: 0.25 }); // Factor 4: Response Compression (15%) const compressionScore = this.analyzeCompressionUsage(); factors.push({ score: compressionScore, weight: 0.15 });`, 'Security Features': ` // Factor 1: Authentication Implementation (30%) const authScore = this.analyzeAuthentication(); factors.push({ score: authScore, weight: 0.3 }); // Factor 2: Data Validation (25%) const validationScore = this.analyzeDataValidation(); factors.push({ score: validationScore, weight: 0.25 }); // Factor 3: Security Headers (20%) const headersScore = this.analyzeSecurityHeaders(); factors.push({ score: headersScore, weight: 0.2 }); // Factor 4: Dependency Vulnerabilities (25%) const vulnScore = this.analyzeDependencyVulnerabilities(); factors.push({ score: vulnScore, weight: 0.25 });` }; return factorMap[criterionName] || ` // Generic algorithmic analysis const baseScore = this.performBaseAnalysis(); factors.push({ score: baseScore, weight: 1.0 });`; } // Get specific methods based on criterion function getSpecificMethods(criterionName) { const methodMap = { 'Developer Productivity': ` analyzeToolingSupport() { let score = 60; if (this.hasDependency('eslint')) score += 10; if (this.hasDependency('prettier')) score += 8; if (this.hasDependency('typescript')) score += 12; if (this.hasDependency('nodemon')) score += 5; if (this.hasDependency('jest')) score += 8; return Math.min(100, score); } analyzeLearningComplexity() { const { technologies } = this.stackInfo; let score = 70; if (technologies.includes('Express.js')) score += 15; // Simple and well-documented if (technologies.includes('React')) score += 10; // Popular, good docs if (technologies.includes('Angular')) score -= 5; // Steeper learning curve if (technologies.includes('Vue.js')) score += 12; // Easy to learn return Math.min(100, score); } analyzeCommunitySupport() { let score = 65; const packageJson = this.stackInfo.packageJson; if (packageJson && packageJson.dependencies) { const depCount = Object.keys(packageJson.dependencies).length; score += Math.min(20, depCount * 2); // More deps suggests active ecosystem } return Math.min(100, score); } analyzeCodeReusability() { return 75; // Base score for Node.js modularity }`, 'API Response Time': ` analyzeFrameworkEfficiency() { const { technologies } = this.stackInfo; let score = 60; if (technologies.includes('Fastify')) score += 25; // Highly optimized if (technologies.includes('Express.js')) score += 20; // Good performance if (technologies.includes('Koa')) score += 18; // Lightweight return Math.min(100, score); } analyzeDatabaseOptimization() { let score = 60; if (this.hasDependency('mongoose')) { score += 15; // Check for connection pooling indicators if (this.findFiles('**/config/**/*.js').length > 0) score += 10; } return Math.min(100, score); } analyzeMiddlewareEfficiency() { let score = 70; if (this.hasDependency('helmet')) score += 5; // Security without major overhead if (this.hasDependency('cors')) score += 3; if (this.hasDependency('compression')) score += 8; // Actually improves response time return Math.min(100, score); } analyzeCompressionUsage() { let score = 50; if (this.hasDependency('compression')) score += 30; if (this.hasDependency('gzip')) score += 25; return Math.min(100, score); }`, 'Security Features': ` analyzeAuthentication() { let score = 50; if (this.hasDependency('passport')) score += 20; if (this.hasDependency('jsonwebtoken')) score += 15; if (this.hasDependency('bcrypt')) score += 15; if (this.hasDependency('express-session')) score += 10; return Math.min(100, score); } analyzeDataValidation() { let score = 50; if (this.hasDependency('joi')) score += 20; if (this.hasDependency('express-validator')) score += 18; if (this.hasDependency('yup')) score += 15; if (this.hasDependency('ajv')) score += 12; return Math.min(100, score); } analyzeSecurityHeaders() { let score = 50; if (this.hasDependency('helmet')) score += 25; if (this.hasDependency('cors')) score += 15; if (this.hasDependency('express-rate-limit')) score += 10; return Math.min(100, score); } analyzeDependencyVulnerabilities() { // Check for security-focused packages let score = 60; if (this.hasDependency('audit')) score += 15; if (this.hasDependency('snyk')) score += 20; return Math.min(100, score); }` }; return methodMap[criterionName] || ` performBaseAnalysis() { // Generic algorithmic analysis based on stack type const { type, technologies } = this.stackInfo; let score = 65; // Base score // Adjust based on stack maturity and adoption if (type.includes('MEAN') || type.includes('MERN')) score += 15; if (technologies.includes('Node.js')) score += 10; return Math.min(100, score); }`; } // Create all analyzer files async function createAnalyzers() { console.log('Creating analyzer files...'); for (const analyzer of analyzers) { const criterionName = analyzer .replace('Analyzer', '') .replace(/([A-Z])/g, ' $1') .trim() .replace(/^./, str => str.toUpperCase()); const content = createAnalyzerContent(analyzer, criterionName); const filePath = path.join(__dirname, 'analyzers', `${analyzer}.js`); await fs.writeFile(filePath, content); console.log(`Created ${analyzer}.js`); } console.log('All analyzer files created successfully!'); } // Run if this file is executed directly if (require.main === module) { createAnalyzers().catch(console.error); } module.exports = { createAnalyzers };