codecare
Version:
A CLI for codebase health check
186 lines (172 loc) ⢠6.21 kB
JavaScript
const { program } = require("commander");
const path = require("path");
const clc = require("cli-color");
const fs = require("fs/promises");
const {
getAllFiles,
getLargeFiles,
getCodeStats,
findDuplicates,
findEmptyFiles,
findFilesExceedingLineLimit,
} = require("../utils/fileUtils");
const {
generatePdfReport,
generateJsonReport,
} = require("../utils/reportUtils");
const config = require("../config");
function checkCommand() {
program
.command("check")
.description(clc.cyanBright("Check the health of the codebase"))
.option(
"-p, --pattern <pattern>",
"Glob pattern to specify which files to include in the scan.",
"**/*"
)
.option(
"-s, --size <size>",
"Size limit (in bytes) to classify files as large",
config.defaultSizeLimit
)
.option(
"-o, --output <output>",
"Output format (pdf/json)",
config.defaultOutput
)
.option(
"-d, --directory <directory>",
"Directory to save the generated report",
config.defaultDirectory
)
.option(
"-l, --max-lines <maxLines>",
"Maximum lines of code allowed in a single file",
config.defaultMaxLines
)
.action(async (options) => {
const { pattern, size, output, directory, maxLines } = options;
try {
console.log(clc.cyanBright.bold("\nšÆ Codebase Health Check šÆ"));
console.log(
clc.yellow(
"Scanning your codebase for large files, duplicates, and empty files... šµļøāāļø\n"
)
);
const files = await getAllFiles(pattern);
const largeFiles = await getLargeFiles(files, parseInt(size));
const { totalLines, totalFiles } = await getCodeStats(files);
const duplicates = await findDuplicates(files);
const emptyFiles = await findEmptyFiles(files);
const filesExceedingLines = await findFilesExceedingLineLimit(
files,
parseInt(maxLines)
);
console.log(clc.cyanBright.bold("\nš Codebase Statistics š"));
console.log(clc.magenta(`- Total files scanned: ${totalFiles}`));
console.log(clc.magenta(`- Total lines of code: ${totalLines}`));
console.log(
clc.magenta(`- Total duplicate files: ${duplicates.length}`)
);
console.log(clc.magenta(`- Total empty files: ${emptyFiles.length}`));
console.log(
clc.magenta(
`- Total files exceeding line limit: ${filesExceedingLines.length}`
)
);
console.log(clc.magenta(`- Total large files: ${largeFiles.length}`));
console.log(clc.yellow.bold("\nDuplicate Files Found š"));
if (duplicates.length === 0) {
console.log(clc.greenBright("ā
No duplicate files found!"));
} else {
duplicates.forEach(({ file1, file2 }) => {
console.log(
clc.redBright(` š“ Duplicate files: ${file1} and ${file2}`)
);
});
}
console.log(clc.yellow.bold("\nEmpty Files Found š"));
if (emptyFiles.length === 0) {
console.log(
clc.greenBright(
"ā
No empty files found! Your code is in great shape!"
)
);
} else {
emptyFiles.forEach((file) => {
console.log(clc.redBright(` š“ Empty file: ${file}`));
});
}
console.log(
clc.yellow.bold(`\nFiles Exceeding ${maxLines} Line Limit š`)
);
if (filesExceedingLines.length === 0) {
console.log(
clc.greenBright(
`ā
No files exceed the ${maxLines}-line limit! Your code is concise!`
)
);
} else {
filesExceedingLines.forEach(({ file, lines }) => {
console.log(clc.redBright(` š“ ${file} - ${lines} lines`));
});
}
console.log(
clc.yellow.bold(`\nLarge Files Found (More than ${size} bytes) šļø`)
);
if (largeFiles.length === 0) {
console.log(
clc.greenBright(
"ā
No large files found! Your code is neat and optimized!"
)
);
} else {
largeFiles.forEach(({ file, size }) => {
console.log(clc.redBright(` š“ ${file} - ${size} bytes`));
});
}
console.log(clc.greenBright.bold("\nš§ Health Check Complete! š§"));
const reportDirectory = path.resolve(directory);
await fs.mkdir(reportDirectory, { recursive: true });
if (output === "pdf") {
const now = new Date();
const formattedDate = now.toISOString().split("T")[0]; // Format the date as YYYY-MM-DD
// Format time as HH-MM-SS AM/PM
const formattedTime = now
.toLocaleString("en-US", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: true,
})
.replace(/:/g, "-")
.replace(/\s/g, ""); // Remove colons & spaces
const reportFileName = `report-${formattedDate}-${formattedTime}.pdf`;
const reportPath = path.join(reportDirectory, reportFileName);
generatePdfReport(
{ totalLines, totalFiles },
largeFiles,
duplicates,
emptyFiles,
filesExceedingLines,
size,
maxLines,
reportPath
);
} else if (output === "json") {
const jsonReportPath = path.join(reportDirectory, "report.json");
generateJsonReport(
{ totalLines, totalFiles },
largeFiles,
duplicates,
emptyFiles,
filesExceedingLines,
jsonReportPath
);
}
} catch (err) {
console.error(clc.redBright("ā An error occurred:"), err.message);
}
});
}
module.exports = checkCommand;