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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | 6x 6x 6x 5x 5x 5x 5x 2x 2x 2x 2x 2x 2x 2x 2x 4x 4x 4x 4x 7x 4x 4x 7x 3x 3x 7x 7x 4x 4x 2x 2x 2x 4x 1x 2x 2x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 3x 5x 3x 3x 5x 2x 2x 5x 5x 3x 3x 3x 3x 3x 3x 1x 3x 3x 6x 1x 1x 1x 1x | import { execSync } from 'child_process';
import fs from 'fs/promises';
import { Command } from 'commander';
export interface LintAgentOptions {}
export interface LintAgentResult {
passed: boolean;
/**
* Statistiques globales issues de ESLint
*/
metrics?: {
errors: number;
warnings: number;
/** Nombre de fichiers analysés */
files: number;
/** Nombre total de problèmes (errors + warnings) */
total: number;
/** Nombre de problèmes fixables */
fixable: number;
};
/** Chemin vers le rapport JSON détaillé */
detailPath?: string;
/** Contenu brut en cas d'erreur JSON */
output?: string;
/** Synthèse des fichiers et règles les plus problématiques */
summary?: {
topFiles: Array<{ filePath: string; errors: number; warnings: number; total: number; fixable: number }>;
topRules: Array<{ ruleId: string; count: number }>;
};
}
/**
* Lance ESLint et renvoie le résultat.
*/
export async function lintAgent(
_opts?: LintAgentOptions,
): Promise<LintAgentResult> {
const detailPath = 'eslint-report.json';
try {
// Run ESLint and output JSON to stdout
// Use npx to invoke the local ESLint binary (works with npm, pnpm, yarn)
const cmd = 'npx eslint . --ext .ts,.js --format json';
const stdout = execSync(cmd, { encoding: 'utf-8' });
const results = JSON.parse(stdout);
await fs.writeFile(detailPath, stdout, 'utf-8');
let errors = 0;
let warnings = 0;
let fixable = 0;
// Détails par fichier pour synthèse
const fileStats: Array<{ filePath: string; errors: number; warnings: number; total: number; fixable: number }> = [];
const ruleCounts: Record<string, number> = {};
results.forEach((file: any) => {
let fe = 0;
let fw = 0;
let ff = 0;
file.messages.forEach((m: any) => {
if (m.severity === 2) {
errors++;
fe++;
}
if (m.severity === 1) {
warnings++;
fw++;
}
Iif (m.fix) {
fixable++;
ff++;
}
Iif (m.ruleId) {
ruleCounts[m.ruleId] = (ruleCounts[m.ruleId] || 0) + 1;
}
});
const total = fe + fw;
fileStats.push({ filePath: file.filePath, errors: fe, warnings: fw, total, fixable: ff });
});
const files = results.length;
const total = errors + warnings;
// Top 5 fichiers et règles
const topFiles = fileStats
.filter(f => f.total > 0)
.sort((a, b) => b.total - a.total)
.slice(0, 5);
const topRules = Object.entries(ruleCounts)
.map(([ruleId, count]) => ({ ruleId, count }))
.sort((a, b) => b.count - a.count)
.slice(0, 5);
return { passed: errors === 0, metrics: { errors, warnings, files, total, fixable }, detailPath, summary: { topFiles, topRules } };
} catch (err: any) {
// On errors, attempt to parse output in stdout
let raw = '';
if (err.stdout) raw = err.stdout as string;
Iif (!raw && err.stderr) raw = err.stderr as string;
await fs.writeFile(detailPath, raw, 'utf-8');
let results: any[] = [];
try { results = JSON.parse(raw); } catch {}
let errors = 0;
let warnings = 0;
let fixable = 0;
const fileStats: Array<{ filePath: string; errors: number; warnings: number; total: number; fixable: number }> = [];
const ruleCounts: Record<string, number> = {};
results.forEach((file: any) => {
let fe = 0;
let fw = 0;
let ff = 0;
file.messages.forEach((m: any) => {
if (m.severity === 2) {
errors++;
fe++;
}
if (m.severity === 1) {
warnings++;
fw++;
}
Iif (m.fix) {
fixable++;
ff++;
}
Iif (m.ruleId) {
ruleCounts[m.ruleId] = (ruleCounts[m.ruleId] || 0) + 1;
}
});
const totalErr = fe + fw;
fileStats.push({ filePath: file.filePath, errors: fe, warnings: fw, total: totalErr, fixable: ff });
});
const files = results.length;
const total = errors + warnings;
const topFiles = fileStats
.filter(f => f.total > 0)
.sort((a, b) => b.total - a.total)
.slice(0, 5);
const topRules = Object.entries(ruleCounts)
.map(([ruleId, count]) => ({ ruleId, count }))
.sort((a, b) => b.count - a.count)
.slice(0, 5);
return { passed: false, metrics: { errors, warnings, files, total, fixable }, detailPath, output: raw, summary: { topFiles, topRules } };
}
}
export const cli = {
command: 'qualimetrie:lint',
description: 'Vérifie la qualité du code avec ESLint',
builder: (cmd: Command) => cmd,
handler: async (_opts: unknown) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { lintAgent: run } = require('./lintAgent');
const res = await run();
console.log(res);
},
};
|