ngperf-audit
Version:
A comprehensive Angular performance analyzer that identifies performance bottlenecks, memory leaks, and optimization opportunities in Angular applications
249 lines (241 loc) ⢠9.99 kB
JavaScript
;
/**
* CLI Entry Point for Angular Performance Analyzer
*/
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;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.commands = void 0;
const path = __importStar(require("path"));
const performance_analyzer_1 = require("./performance-analyzer");
// Helper function to resolve project path
function resolveProjectPath(inputPath) {
if (!inputPath) {
return process.cwd();
}
if (path.isAbsolute(inputPath)) {
return inputPath;
}
return path.resolve(process.cwd(), inputPath);
}
// Helper function to create output directory if needed
async function ensureOutputDirectory(outputPath) {
const fs = await Promise.resolve().then(() => __importStar(require('fs/promises')));
const outputDir = path.dirname(outputPath);
try {
await fs.access(outputDir);
}
catch {
await fs.mkdir(outputDir, { recursive: true });
console.log(`š Created output directory: ${outputDir}`);
}
}
// Helper function to parse command line arguments
function parseArgs(args) {
const parsed = { _: [] };
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg.startsWith('--')) {
// Long flag: --output
const key = arg.slice(2);
const nextArg = args[i + 1];
if (nextArg && !nextArg.startsWith('-')) {
parsed[key] = nextArg;
i++; // Skip next arg since we consumed it
}
else {
parsed[key] = true;
}
}
else if (arg.startsWith('-') && arg.length === 2) {
// Short flag: -o
const key = arg.slice(1);
const nextArg = args[i + 1];
if (nextArg && !nextArg.startsWith('-')) {
parsed[key] = nextArg;
i++; // Skip next arg since we consumed it
}
else {
parsed[key] = true;
}
}
else {
// Positional argument
parsed._.push(arg);
}
}
return parsed;
}
// Command handlers
const commands = {
// Analyze entire project
async project(projectPath, outputPath, format) {
const resolvedPath = resolveProjectPath(projectPath);
console.log(`š Analyzing project: ${resolvedPath}`);
if (outputPath) {
await ensureOutputDirectory(outputPath);
}
if (format === 'json') {
// Handle JSON format
const { analyses, summary } = performance_analyzer_1.PerformanceAnalyzerCLI.analyzeProjectWithSummary(resolvedPath);
const jsonReport = {
summary,
analyses,
generatedAt: new Date().toISOString()
};
const outputFile = outputPath || './performance-report.json';
await performance_analyzer_1.PerformanceAnalyzerCLI.saveReportToFile(JSON.stringify(jsonReport, null, 2), outputFile);
console.log(`š JSON report saved to: ${outputFile}`);
return { analyses, summary, reportPath: outputFile };
}
else {
// Default markdown format
return performance_analyzer_1.PerformanceAnalyzerCLI.runAnalysis(resolvedPath, outputPath);
}
},
// Analyze single component
async component(componentPath) {
if (!componentPath) {
throw new Error('Component path is required');
}
const resolvedPath = path.resolve(componentPath);
console.log(`š Analyzing component: ${resolvedPath}`);
const analyzer = new performance_analyzer_1.PerformanceAnalyzer();
const analysis = analyzer.analyzeComponent(resolvedPath);
console.log(`\nš Component Analysis Results:`);
console.log(` Name: ${analysis.componentName}`);
console.log(` Performance Score: ${analysis.performanceScore}/100`);
const totalIssues = analysis.changeDetectionIssues.length +
analysis.templateIssues.length +
analysis.subscriptionIssues.length;
console.log(` Issues Found: ${totalIssues}`);
if (analysis.recommendations.length > 0) {
console.log(`\nš” Top Recommendations:`);
analysis.recommendations.slice(0, 3).forEach((rec, index) => {
console.log(` ${index + 1}. ${rec.title} (${rec.priority} priority)`);
});
}
return analysis;
},
// Generate detailed report
async report(projectPath, outputPath) {
const resolvedPath = resolveProjectPath(projectPath);
const defaultOutput = outputPath || './performance-report.md';
console.log(`š Generating detailed report for: ${resolvedPath}`);
await ensureOutputDirectory(defaultOutput);
const { analyses, summary } = performance_analyzer_1.PerformanceAnalyzerCLI.analyzeProjectWithSummary(resolvedPath);
const report = performance_analyzer_1.PerformanceAnalyzerCLI.generateReportWithSummary(analyses, summary);
await performance_analyzer_1.PerformanceAnalyzerCLI.saveReportToFile(report, defaultOutput);
// Also log summary to console
console.log(`\nš Analysis Summary:`);
console.log(` Components: ${summary.totalComponents}`);
console.log(` Average Score: ${summary.averagePerformanceScore}/100`);
console.log(` Total Issues: ${summary.totalIssues}`);
return { analyses, summary, reportPath: defaultOutput };
},
// Show help
help() {
console.log(`
š Angular Performance Analyzer CLI
USAGE:
ngperf-audit <command> [options]
COMMANDS:
project [path] Analyze entire project
component <path> Analyze single component
report [path] Generate detailed report
help Show this help
OPTIONS:
-o, --output <file> Output file path
-f, --format <type> Report format: 'markdown' or 'json' (default: markdown)
EXAMPLES:
ngperf-audit help # Show this help
ngperf-audit project # Analyze current project
ngperf-audit project ./src/app # Analyze src/app folder
ngperf-audit project ./src/app -o ./reports/report.md # Save to custom file
ngperf-audit project ./src/app -f json # Generate JSON report
ngperf-audit project ./src/app -o ./report.json -f json # JSON report with custom path
ngperf-audit component ./src/app/app.component.ts # Analyze single component
ngperf-audit report # Generate detailed report
ngperf-audit report ./src/app -o ./my-report.md # Custom output path
DEVELOPMENT USAGE (in project root):
npm run ngperf-audit project # If added to package.json scripts
npx tsx src/ngperf/cli.ts project # Direct TypeScript execution
For more information: https://github.com/eawebmaster20/ngperf
`);
}
};
exports.commands = commands;
// Main CLI handler
async function main() {
const args = process.argv.slice(2);
const parsed = parseArgs(args);
const command = parsed._[0];
if (!command || command === 'help' || !commands[command]) {
commands.help();
return;
}
try {
console.log('š Angular Performance Analyzer');
console.log('================================\n');
const startTime = Date.now();
switch (command) {
case 'project':
const projectPath = parsed._[1];
const outputPath = parsed.output || parsed.o;
const format = parsed.format || parsed.f || 'markdown';
await commands.project(projectPath, outputPath, format);
break;
case 'component':
await commands.component(parsed._[1]);
break;
case 'report':
const reportPath = parsed._[1];
const reportOutput = parsed.output || parsed.o;
await commands.report(reportPath, reportOutput);
break;
}
const duration = Date.now() - startTime;
console.log(`\nā
Completed in ${duration}ms`);
}
catch (error) {
console.error('ā Error:', error instanceof Error ? error.message : error);
process.exit(1);
}
}
// Run if called directly
if (require.main === module) {
main();
}
//# sourceMappingURL=cli.js.map