@dawans/promptshield
Version:
Secure your LLM stack with enterprise-grade RulePacks for AI safety scanning
136 lines (135 loc) • 8.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TableRenderer = void 0;
const Result_1 = require("../../../../shared/types/Result");
const Violation_1 = require("../../../../shared/types/Violation");
const ScanMetrics_1 = require("../../../../shared/types/ScanMetrics");
/**
* Table format renderer
*/
class TableRenderer {
/**
* Renders a report to table format
*/
async render(report) {
try {
const violations = report.getFilteredViolations();
const summary = Violation_1.ViolationUtils.createSummary(violations);
const metrics = report.scanResult.metrics;
let output = '';
// Header
output +=
'┌─────────────────────────────────────────────────────────────────────────────────┐\n';
output +=
'│ PromptShield Scan Report │\n';
output +=
'└─────────────────────────────────────────────────────────────────────────────────┘\n\n';
// Summary table
output += '📊 SUMMARY\n';
output +=
'┌─────────────────────┬─────────────────────────────────────────────────────────┐\n';
output +=
'│ Metric │ Value │\n';
output +=
'├─────────────────────┼─────────────────────────────────────────────────────────┤\n';
output += `│ Total Violations │ ${summary.total.toString().padEnd(55)} │\n`;
output += `│ Objects Scanned │ ${metrics.objectsScanned.toString().padEnd(55)} │\n`;
output += `│ Processing Time │ ${ScanMetrics_1.ScanMetricsUtils.formatProcessingTime(metrics.processingTime).padEnd(55)} │\n`;
output += `│ Memory Usage │ ${ScanMetrics_1.ScanMetricsUtils.formatMemoryUsage(metrics.memoryUsage).padEnd(55)} │\n`;
output += `│ Rules Applied │ ${metrics.rulesApplied.toString().padEnd(55)} │\n`;
output +=
'└─────────────────────┴─────────────────────────────────────────────────────────┘\n\n';
// Severity breakdown
if (summary.total > 0) {
output += '🚨 SEVERITY BREAKDOWN\n';
output +=
'┌─────────────────────┬─────────────────────────────────────────────────────────┐\n';
output +=
'│ Severity │ Count │\n';
output +=
'├─────────────────────┼─────────────────────────────────────────────────────────┤\n';
for (const [severity, count] of Object.entries(summary.bySeverity)) {
const emoji = this.getSeverityEmoji(severity);
const severityText = `${emoji} ${severity}`;
output += `│ ${severityText.padEnd(19)} │ ${count.toString().padEnd(55)} │\n`;
}
output +=
'└─────────────────────┴─────────────────────────────────────────────────────────┘\n\n';
}
// Violations table
if (violations.length > 0) {
output += '🔍 VIOLATIONS\n';
output +=
'┌─────────────────────┬─────────────────────┬─────────────────────┬─────────────────────┐\n';
output +=
'│ Rule ID │ Severity │ Category │ Message │\n';
output +=
'├─────────────────────┼─────────────────────┼─────────────────────┼─────────────────────┤\n';
for (const violation of violations) {
const emoji = this.getSeverityEmoji(violation.severity);
const ruleId = this.truncateText(violation.ruleId, 19);
const severity = `${emoji} ${violation.severity}`.padEnd(19);
const category = this.truncateText(violation.category, 19);
const message = this.truncateText(violation.message, 19);
output += `│ ${ruleId} │ ${severity} │ ${category} │ ${message} │\n`;
}
output +=
'└─────────────────────┴─────────────────────┴─────────────────────┴─────────────────────┘\n\n';
}
else {
output += '✅ NO VIOLATIONS FOUND\n';
output +=
'┌─────────────────────────────────────────────────────────────────────────────────┐\n';
output +=
'│ No safety violations detected in the scanned content. │\n';
output +=
'└─────────────────────────────────────────────────────────────────────────────────┘\n\n';
}
// Footer
output += `Generated at ${new Date().toISOString()} by PromptShield v1.0.0\n`;
return (0, Result_1.ok)(output);
}
catch (error) {
return (0, Result_1.err)(new Error(`Failed to render table report: ${error}`));
}
}
/**
* Gets the output format this renderer handles
*/
getFormat() {
return 'table';
}
/**
* Checks if this renderer supports streaming
*/
supportsStreaming() {
return false;
}
/**
* Gets emoji for severity level
*/
getSeverityEmoji(severity) {
switch (severity.toLowerCase()) {
case 'critical':
return '🔴';
case 'high':
return '🟠';
case 'medium':
return '🟡';
case 'low':
return '🟢';
default:
return '⚪';
}
}
/**
* Truncates text to fit in table cells
*/
truncateText(text, maxLength) {
if (text.length <= maxLength) {
return text.padEnd(maxLength);
}
return text.substring(0, maxLength - 3) + '...';
}
}
exports.TableRenderer = TableRenderer;