agentsqripts
Version:
Comprehensive static code analysis toolkit for identifying technical debt, security vulnerabilities, performance issues, and code quality problems
175 lines (156 loc) • 6.04 kB
JavaScript
/**
* @file Report exporter for problem-scope CLI
* @description Exports analysis results to various formats
*/
const fs = require('fs').promises;
const path = require('path');
/**
* Export analysis report to file
* @param {Object} results - Analysis results
* @param {string} filePath - Output file path
*/
async function exportReport(results, filePath) {
const extension = path.extname(filePath).toLowerCase();
try {
switch (extension) {
case '.json':
await exportJSON(results, filePath);
break;
case '.md':
await exportMarkdown(results, filePath);
break;
case '.html':
await exportHTML(results, filePath);
break;
default:
// Default to JSON
await exportJSON(results, filePath);
}
console.log(`📄 Report exported to: ${filePath}`);
} catch (error) {
console.error(`❌ Failed to export report: ${error.message}`);
throw error;
}
}
/**
* Export results as JSON
* @param {Object} results - Analysis results
* @param {string} filePath - Output file path
*/
async function exportJSON(results, filePath) {
const jsonContent = JSON.stringify(results, null, 2);
await fs.writeFile(filePath, jsonContent, 'utf8');
}
/**
* Export results as Markdown
* @param {Object} results - Analysis results
* @param {string} filePath - Output file path
*/
async function exportMarkdown(results, filePath) {
let markdown = `# Problem Scope Analysis Report\n\n`;
// Metadata
markdown += `## Analysis Metadata\n`;
markdown += `- **Project Path**: ${results.metadata.projectPath}\n`;
markdown += `- **Analysis Types**: ${results.metadata.analysisTypes.join(', ')}\n`;
markdown += `- **Timestamp**: ${results.metadata.timestamp}\n`;
markdown += `- **Execution Time**: ${results.metadata.executionTime}ms\n\n`;
// Summary
markdown += `## Summary\n`;
markdown += `- **Overall Risk Level**: ${results.summary.overallRiskLevel}\n`;
markdown += `- **Total Issues**: ${results.summary.totalIssues}\n`;
markdown += `- **Critical Issues**: ${results.summary.criticalIssues}\n`;
markdown += `- **Recommendations**: ${results.summary.recommendationsCount}\n\n`;
// Individual analyses
Object.entries(results.analyses).forEach(([type, analysis]) => {
markdown += `## ${type.charAt(0).toUpperCase() + type.slice(1)} Analysis\n`;
if (analysis.error) {
markdown += `❌ **Error**: ${analysis.error}\n\n`;
} else {
markdown += `**Severity**: ${analysis.severity || 'N/A'}\n\n`;
if (analysis.vulnerabilities) {
markdown += `### Vulnerabilities (${analysis.vulnerabilities.length})\n`;
analysis.vulnerabilities.slice(0, 5).forEach(vuln => {
markdown += `- **${vuln.severity}**: ${vuln.title || vuln.description}\n`;
});
if (analysis.vulnerabilities.length > 5) {
markdown += `- ... and ${analysis.vulnerabilities.length - 5} more\n`;
}
markdown += `\n`;
}
if (analysis.violations) {
markdown += `### Violations (${analysis.violations.length})\n`;
analysis.violations.slice(0, 5).forEach(violation => {
markdown += `- **${violation.severity}**: ${violation.description}\n`;
});
if (analysis.violations.length > 5) {
markdown += `- ... and ${analysis.violations.length - 5} more\n`;
}
markdown += `\n`;
}
}
});
await fs.writeFile(filePath, markdown, 'utf8');
}
/**
* Export results as HTML
* @param {Object} results - Analysis results
* @param {string} filePath - Output file path
*/
async function exportHTML(results, filePath) {
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Problem Scope Analysis Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }
.header { background: #f4f4f4; padding: 20px; border-radius: 5px; }
.summary { background: #e8f4f8; padding: 15px; border-radius: 5px; margin: 20px 0; }
.analysis { margin: 20px 0; padding: 15px; border-left: 4px solid #007acc; }
.critical { border-left-color: #d32f2f; }
.high { border-left-color: #f57c00; }
.medium { border-left-color: #fbc02d; }
.low { border-left-color: #388e3c; }
.error { background: #ffebee; color: #c62828; padding: 10px; border-radius: 3px; }
ul { list-style-type: none; padding-left: 0; }
li { padding: 5px 0; }
</style>
</head>
<body>
<div class="header">
<h1>Problem Scope Analysis Report</h1>
<p><strong>Project:</strong> ${results.metadata.projectPath}</p>
<p><strong>Analysis Types:</strong> ${results.metadata.analysisTypes.join(', ')}</p>
<p><strong>Generated:</strong> ${results.metadata.timestamp}</p>
</div>
<div class="summary">
<h2>Summary</h2>
<ul>
<li><strong>Overall Risk Level:</strong> ${results.summary.overallRiskLevel}</li>
<li><strong>Total Issues:</strong> ${results.summary.totalIssues}</li>
<li><strong>Critical Issues:</strong> ${results.summary.criticalIssues}</li>
<li><strong>Recommendations:</strong> ${results.summary.recommendationsCount}</li>
</ul>
</div>
${Object.entries(results.analyses).map(([type, analysis]) => `
<div class="analysis ${(analysis.severity || 'low').toLowerCase()}">
<h3>${type.charAt(0).toUpperCase() + type.slice(1)} Analysis</h3>
${analysis.error ?
`<div class="error">Error: ${analysis.error}</div>` :
`<p><strong>Severity:</strong> ${analysis.severity || 'N/A'}</p>`
}
</div>
`).join('')}
</body>
</html>
`;
await fs.writeFile(filePath, html, 'utf8');
}
module.exports = {
exportReport,
exportJSON,
exportMarkdown,
exportHTML
};