# All files / src/lib/quality-validator/reporters CsvReporter.ts

0% Statements 0/126
0% Branches 0/1
0% Functions 0/1
0% Lines 0/126

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127

     /**
     * CSV Reporter
     * Generates CSV export for spreadsheet analysis
     */

    import { ScoringResult } from '../types/index.js';

    /**
     * CSV Reporter
     */
    export class CsvReporter {
      /**
       * Generate CSV report
       */
      generate(result: ScoringResult): string {
        const lines: string[] = [];

        // Summary section
        lines.push('# Quality Validation Report Summary');
        lines.push(`"Timestamp","${result.metadata.timestamp}"`);
        lines.push(`"Overall Score","${result.overall.score.toFixed(1)}%"`);
        lines.push(`"Grade","${result.overall.grade}"`);
        lines.push(`"Status","${result.overall.status.toUpperCase()}"`);
        lines.push('');

        // Component scores
        lines.push('# Component Scores');
        lines.push('"Component","Score","Weight","Weighted Score"');
        const scores = [
          {
            name: 'Code Quality',
            score: result.componentScores.codeQuality.score,
            weight: result.componentScores.codeQuality.weight,
            weighted: result.componentScores.codeQuality.weightedScore,
          },
          {
            name: 'Test Coverage',
            score: result.componentScores.testCoverage.score,
            weight: result.componentScores.testCoverage.weight,
            weighted: result.componentScores.testCoverage.weightedScore,
          },
          {
            name: 'Architecture',
            score: result.componentScores.architecture.score,
            weight: result.componentScores.architecture.weight,
            weighted: result.componentScores.architecture.weightedScore,
          },
          {
            name: 'Security',
            score: result.componentScores.security.score,
            weight: result.componentScores.security.weight,
            weighted: result.componentScores.security.weightedScore,
          },
        ];

        for (const score of scores) {
          lines.push(
            `"${score.name}","${score.score.toFixed(1)}%","${(score.weight * 100).toFixed(0)}%","${score.weighted.toFixed(1)}%"`
          );
        }

        lines.push('');

        // Findings
        lines.push('# Findings');
        lines.push('"Severity","Category","Title","File","Line","Description","Remediation"');

        for (const finding of result.findings) {
          const file = finding.location?.file || '';
          const line = finding.location?.line ? finding.location.line.toString() : '';
          lines.push(
            `"${finding.severity}","${finding.category}","${this.escapeCsv(finding.title)}","${file}","${line}","${this.escapeCsv(
              finding.description
            )}","${this.escapeCsv(finding.remediation)}"`
          );
        }

        lines.push('');

        // Recommendations
        if (result.recommendations.length > 0) {
          lines.push('# Recommendations');
          lines.push('"Priority","Category","Issue","Remediation","Effort","Impact"');

          for (const rec of result.recommendations) {
            lines.push(
              `"${rec.priority}","${rec.category}","${this.escapeCsv(rec.issue)}","${this.escapeCsv(
                rec.remediation
              )}","${rec.estimatedEffort}","${this.escapeCsv(rec.expectedImpact)}"`
            );
          }

          lines.push('');
        }

        // Trend
        if (result.trend) {
          lines.push('# Trend');
          lines.push('"Metric","Value"');
          lines.push(`"Current Score","${result.trend.currentScore.toFixed(1)}%"`);
          if (result.trend.previousScore !== undefined) {
            lines.push(`"Previous Score","${result.trend.previousScore.toFixed(1)}%"`);
            const change = result.trend.currentScore - result.trend.previousScore;
            lines.push(
              `"Change","${change >= 0 ? '+' : ''}${change.toFixed(1)}%"`
            );
          }
          if (result.trend.direction) {
            lines.push(`"Direction","${result.trend.direction}"`);
          }
        }

        return lines.join('\n');
      }

      /**
       * Escape CSV field
       */
      private escapeCsv(field: string): string {
        if (!field) return '';
        // Escape quotes and wrap in quotes if needed
        return field.replace(/"/g, '""');
      }
    }

    export const csvReporter = new CsvReporter();