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
JavaScript
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 };