arela
Version:
AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.
215 lines ⢠7.74 kB
JavaScript
/**
* Format and report contract generation results
*/
import pc from 'picocolors';
/**
* Display contract generation report
*/
export function displayContractReport(report) {
console.log(pc.bold(pc.cyan('\nš API Contract Analysis Results\n')));
// Summary statistics
displaySummary(report);
// Matched endpoints
displayMatches(report);
// Drift issues
displayDrift(report);
// Slice details
if (report.slices.length > 0) {
displaySlices(report.slices);
}
// Footer
displayFooter(report);
}
/**
* Display summary statistics
*/
function displaySummary(report) {
console.log(pc.gray('Summary:'));
console.log(pc.cyan(` š Backend Endpoints: ${report.totalEndpoints}`));
console.log(pc.cyan(` š Frontend API Calls: ${report.totalCalls}`));
console.log(pc.green(` ā
Matched: ${report.matchedCount} (${calculatePercentage(report.matchedCount, report.totalEndpoints)}%)`));
if (report.unmatchedCalls.length > 0) {
console.log(pc.yellow(` ā ļø Unmatched Calls: ${report.unmatchedCalls.length}`));
}
if (report.unmatchedEndpoints.length > 0) {
console.log(pc.yellow(` ā ļø Unmatched Endpoints: ${report.unmatchedEndpoints.length}`));
}
console.log('');
}
/**
* Display matched endpoints
*/
function displayMatches(report) {
if (report.matchedCount === 0) {
console.log(pc.yellow('ā No matched endpoints found\n'));
return;
}
console.log(pc.bold(`ā
Matched Endpoints (${report.matchedCount}):`));
// Show first 10 matches
const matchCount = Math.min(10, report.matchedCount);
// Reconstruct matches from slices for display
let displayedCount = 0;
for (const slice of report.slices) {
for (const match of slice.matches) {
if (displayedCount < matchCount) {
const method = match.endpoint.method.padEnd(6);
const path = match.endpoint.path;
const calls = match.calls.length;
console.log(` ${pc.cyan(method)} ${path} ${pc.gray(`(${calls} call${calls !== 1 ? 's' : ''})`)}`);
displayedCount++;
}
}
}
if (report.matchedCount > matchCount) {
console.log(pc.gray(` ... and ${report.matchedCount - matchCount} more`));
}
console.log('');
}
/**
* Display drift issues
*/
function displayDrift(report) {
if (report.driftIssues.length === 0) {
console.log(pc.green('ā
No drift issues detected!\n'));
return;
}
console.log(pc.bold(pc.red(`ā Schema Drift Detected (${report.driftIssues.length}):`)));
// Group by severity
const bySeverity = groupDriftBySeverity(report.driftIssues);
// Display critical issues
if (bySeverity.critical.length > 0) {
console.log(pc.red(`\n š“ Critical (${bySeverity.critical.length}):`));
for (const issue of bySeverity.critical.slice(0, 3)) {
console.log(` ${issue.message}`);
if (issue.suggestion) {
console.log(pc.gray(` š” ${issue.suggestion}`));
}
}
if (bySeverity.critical.length > 3) {
console.log(pc.gray(` ... and ${bySeverity.critical.length - 3} more`));
}
}
// Display high severity issues
if (bySeverity.high.length > 0) {
console.log(pc.yellow(`\n š High (${bySeverity.high.length}):`));
for (const issue of bySeverity.high.slice(0, 3)) {
console.log(` ${issue.message}`);
if (issue.suggestion) {
console.log(pc.gray(` š” ${issue.suggestion}`));
}
}
if (bySeverity.high.length > 3) {
console.log(pc.gray(` ... and ${bySeverity.high.length - 3} more`));
}
}
// Display medium severity issues
if (bySeverity.medium.length > 0) {
console.log(pc.blue(`\n š” Medium (${bySeverity.medium.length}):`));
for (const issue of bySeverity.medium.slice(0, 2)) {
console.log(` ${issue.message}`);
if (issue.suggestion) {
console.log(pc.gray(` š” ${issue.suggestion}`));
}
}
if (bySeverity.medium.length > 2) {
console.log(pc.gray(` ... and ${bySeverity.medium.length - 2} more`));
}
}
console.log('');
}
/**
* Display slice details
*/
function displaySlices(slices) {
console.log(pc.bold(`š¦ Contracts Per Slice (${slices.length}):`));
for (const slice of slices) {
const endpointCount = slice.endpoints.length;
const matchCount = slice.matches.length;
const driftCount = slice.drift.length;
let icon = 'ā
';
if (driftCount > 0) {
icon = pc.red('ā');
}
else if (matchCount === 0) {
icon = pc.yellow('ā ļø ');
}
console.log(` ${icon} ${slice.name.padEnd(15)} ${endpointCount} endpoints, ${matchCount} matched, ${driftCount} drift issues`);
}
console.log('');
}
/**
* Display footer with next steps
*/
function displayFooter(report) {
console.log(pc.bold('š Next Steps:'));
if (report.driftIssues.length > 0) {
console.log(pc.yellow(' 1. Fix schema drift issues'));
console.log(pc.gray(` - ${report.driftIssues.length} issue${report.driftIssues.length !== 1 ? 's' : ''} to resolve`));
}
console.log(pc.cyan(' 2. Review generated OpenAPI specs'));
console.log(pc.gray(` - ${report.specs.length} spec${report.specs.length !== 1 ? 's' : ''} generated`));
console.log(pc.cyan(' 3. Set up contract testing'));
console.log(pc.gray(' - Use Dredd or Prism for validation'));
console.log(pc.cyan(' 4. Generate documentation'));
console.log(pc.gray(' - Use Swagger UI with generated specs'));
console.log(pc.gray(`\nā±ļø Analysis completed in ${report.duration}ms\n`));
}
/**
* Group drift issues by severity
*/
function groupDriftBySeverity(issues) {
return {
critical: issues.filter(i => i.severity === 'critical'),
high: issues.filter(i => i.severity === 'high'),
medium: issues.filter(i => i.severity === 'medium'),
low: issues.filter(i => i.severity === 'low'),
};
}
/**
* Calculate percentage
*/
function calculatePercentage(current, total) {
if (total === 0)
return 0;
return Math.round((current / total) * 100);
}
/**
* Export results as JSON
*/
export function reportToJson(report) {
return JSON.stringify(report, null, 2);
}
/**
* Export results as CSV
*/
export function reportToCsv(report) {
const lines = [];
// Header
lines.push('Slice,Endpoints,Calls,Matched,Drift');
// Slice data
for (const slice of report.slices) {
lines.push(`${slice.name},${slice.endpoints.length},${slice.calls.length},${slice.matches.length},${slice.drift.length}`);
}
// Total
lines.push(`TOTAL,${report.totalEndpoints},${report.totalCalls},${report.matchedCount},${report.driftIssues.length}`);
return lines.join('\n');
}
/**
* Create summary statistics
*/
export function getSummaryStats(report) {
return {
title: 'API Contract Generation Summary',
timestamp: report.generatedAt,
duration: `${report.duration}ms`,
stats: {
totalEndpoints: report.totalEndpoints,
totalCalls: report.totalCalls,
matchedPercentage: `${calculatePercentage(report.matchedCount, report.totalEndpoints)}%`,
driftIssuesCount: report.driftIssues.length,
sliceCount: report.slices.length,
specCount: report.specs.length,
},
};
}
//# sourceMappingURL=reporter.js.map