feat: enhance logging and linting functionality with detailed reports
All checks were successful
Lint / lint (pull_request) Successful in 16s
All checks were successful
Lint / lint (pull_request) Successful in 16s
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import { spawnSync } from 'child_process';
|
||||
import { logStep, logSuccess, logWarning, logInfo } from '../utils/logger';
|
||||
import { logStep, logSuccess, logWarning, logDetail } from '../utils/logger';
|
||||
import type { LintResult } from '../types';
|
||||
|
||||
/**
|
||||
* Walks up the directory tree from `startDir` to find the nearest
|
||||
@@ -36,17 +37,19 @@ function collectTsFiles(dir: string): string[] {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a command synchronously and returns whether it succeeded.
|
||||
* Prints stdout/stderr to the console only on failure.
|
||||
* Runs a command synchronously. Only prints to console on fatal failure (exit >= 2).
|
||||
* Exit code 1 from ESLint means "warnings remain after --fix" — not a fatal error.
|
||||
* Returns captured output for logging to file.
|
||||
*/
|
||||
function run(cmd: string, args: string[], cwd: string): boolean {
|
||||
function run(cmd: string, args: string[], cwd: string): { success: boolean; output: string } {
|
||||
const result = spawnSync(cmd, args, { cwd, encoding: 'utf8', shell: true });
|
||||
if (result.status !== 0) {
|
||||
const output = [result.stdout, result.stderr].filter(Boolean).join('\n').trim();
|
||||
const fatalError = result.status === null || result.status >= 2;
|
||||
if (fatalError) {
|
||||
if (result.stderr) process.stderr.write(result.stderr);
|
||||
if (result.stdout) process.stdout.write(result.stdout);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return { success: !fatalError, output };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,28 +59,39 @@ function run(cmd: string, args: string[], cwd: string): boolean {
|
||||
*
|
||||
* - Prettier: always attempted; logs a warning if not found.
|
||||
* - ESLint: optional; silently skipped if no config is found in the project root.
|
||||
*
|
||||
* Returns a `LintResult` with the outcome of each tool for inclusion in the report.
|
||||
*/
|
||||
export function lintGeneratedFiles(outputDir: string): void {
|
||||
export function lintGeneratedFiles(outputDir: string): LintResult {
|
||||
logStep('Linting generated files...');
|
||||
|
||||
const result: LintResult = {
|
||||
prettier: { ran: false, filesFormatted: 0 },
|
||||
eslint: { ran: false, filesFixed: 0 }
|
||||
};
|
||||
|
||||
const projectRoot = findProjectRoot(outputDir);
|
||||
if (!projectRoot) {
|
||||
logWarning('Could not locate a project root (package.json). Skipping lint.');
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
logInfo(` Project root: ${projectRoot}`);
|
||||
|
||||
const files = collectTsFiles(outputDir);
|
||||
if (files.length === 0) {
|
||||
logWarning('No TypeScript files found in output directory. Skipping lint.');
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
logDetail('lint', `Project root: ${projectRoot}`);
|
||||
logDetail('lint', `Files to process: ${files.length}`);
|
||||
|
||||
const relativePaths = files.map((f) => path.relative(projectRoot, f));
|
||||
|
||||
// --- Prettier ---
|
||||
const prettierOk = run('npx', ['prettier', '--write', ...relativePaths], projectRoot);
|
||||
if (prettierOk) {
|
||||
const prettier = run('npx', ['prettier', '--write', ...relativePaths], projectRoot);
|
||||
if (prettier.output) logDetail('prettier', prettier.output);
|
||||
if (prettier.success) {
|
||||
result.prettier = { ran: true, filesFormatted: files.length };
|
||||
logSuccess(`Prettier formatted ${files.length} files`);
|
||||
} else {
|
||||
logWarning('Prettier not available or encountered errors. Skipping formatting.');
|
||||
@@ -94,13 +108,17 @@ export function lintGeneratedFiles(outputDir: string): void {
|
||||
|
||||
if (!hasEslintConfig) {
|
||||
logWarning('No ESLint config found in project root. Skipping ESLint fix.');
|
||||
return;
|
||||
return result;
|
||||
}
|
||||
|
||||
const eslintOk = run('npx', ['eslint', '--fix', ...relativePaths], projectRoot);
|
||||
if (eslintOk) {
|
||||
const eslint = run('npx', ['eslint', '--fix', ...relativePaths], projectRoot);
|
||||
if (eslint.output) logDetail('eslint', eslint.output);
|
||||
if (eslint.success) {
|
||||
result.eslint = { ran: true, filesFixed: files.length };
|
||||
logSuccess(`ESLint fixed ${files.length} files`);
|
||||
} else {
|
||||
logWarning('ESLint reported errors that could not be auto-fixed. Review the output above.');
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user