/**
* WPCS MCP Server - Report Generator
* Generates JSON, Markdown, or summary reports.
*/
import { writeFileSync } from 'fs';
import type { ReportFormat, ReportResult, ReportSection, IssueSeverity } from './types.js';
/**
* Calculate a grade (A-F) based on issue density.
*/
function calculateGrade(errors: number, warnings: number): string {
const score = errors * 3 + warnings;
if (score === 0) return 'A';
if (score <= 5) return 'B';
if (score <= 15) return 'C';
if (score <= 30) return 'D';
return 'F';
}
/**
* Generate a report from collected sections.
*/
export function generateReport(
projectPath: string,
projectType: string,
sections: ReportSection[],
format: ReportFormat,
outputFile?: string
): { content: string; report: ReportResult } {
const totalErrors = sections.reduce((s, sec) => s + sec.errors, 0);
const totalWarnings = sections.reduce((s, sec) => s + sec.warnings, 0);
const totalInfos = sections.reduce((s, sec) => s + sec.issues.filter(i => i.type === 'info').length, 0);
const report: ReportResult = {
projectPath,
projectType,
timestamp: new Date().toISOString(),
grade: calculateGrade(totalErrors, totalWarnings),
sections,
totals: { errors: totalErrors, warnings: totalWarnings, infos: totalInfos },
};
let content: string;
switch (format) {
case 'json':
content = formatJson(report);
break;
case 'markdown':
content = formatMarkdown(report);
break;
case 'summary':
default:
content = formatSummary(report);
break;
}
if (outputFile) {
try {
writeFileSync(outputFile, content);
} catch {
// Ignore write errors
}
}
return { content, report };
}
function formatJson(report: ReportResult): string {
return JSON.stringify(report, null, 2);
}
function formatMarkdown(report: ReportResult): string {
const lines: string[] = [];
lines.push(`# WPCS Report: Grade ${report.grade}`);
lines.push('');
lines.push(`| Field | Value |`);
lines.push(`|-------|-------|`);
lines.push(`| Path | \`${report.projectPath}\` |`);
lines.push(`| Type | ${report.projectType} |`);
lines.push(`| Date | ${report.timestamp} |`);
lines.push(`| Errors | ${report.totals.errors} |`);
lines.push(`| Warnings | ${report.totals.warnings} |`);
lines.push(`| Grade | **${report.grade}** |`);
lines.push('');
for (const section of report.sections) {
const status = section.passed ? 'PASSED' : 'ISSUES';
lines.push(`## ${section.name} — ${status}`);
lines.push('');
if (section.issues.length === 0) {
lines.push('No issues found.');
lines.push('');
continue;
}
lines.push(`| Severity | File | Line | Message |`);
lines.push(`|----------|------|------|---------|`);
for (const issue of section.issues.slice(0, 30)) {
const severity = issue.type.toUpperCase();
lines.push(`| ${severity} | \`${issue.file}\` | ${issue.line} | ${issue.message} |`);
}
if (section.issues.length > 30) {
lines.push(`| ... | ... | ... | *${section.issues.length - 30} more issues* |`);
}
lines.push('');
}
lines.push('---');
lines.push(`*Generated by WPCS MCP Server v2.0.0*`);
return lines.join('\n');
}
function formatSummary(report: ReportResult): string {
const sectionSummaries = report.sections
.filter(s => !s.passed)
.map(s => `${s.name}: ${s.errors} error(s), ${s.warnings} warning(s)`)
.slice(0, 3);
if (report.totals.errors === 0 && report.totals.warnings === 0) {
return `Grade: ${report.grade}. All checks passed for ${report.projectType} at ${report.projectPath}. Ready for submission.`;
}
let summary = `Grade: ${report.grade}. Found ${report.totals.errors} error(s) and ${report.totals.warnings} warning(s).`;
if (sectionSummaries.length > 0) {
summary += ` Top issues: ${sectionSummaries.join('; ')}.`;
}
if (report.totals.errors > 0) {
summary += ' Fix errors before submission.';
}
return summary;
}
/**
* Helper to build a report section from a generic checker result.
*/
export function buildSection(
name: string,
issues: Array<{ file: string; line: number; type: IssueSeverity; message: string; code: string }>,
): ReportSection {
const errors = issues.filter(i => i.type === 'error').length;
const warnings = issues.filter(i => i.type === 'warning').length;
return {
name,
passed: errors === 0,
errors,
warnings,
issues,
};
}