feat: script to calculate locs of repo

This commit is contained in:
Anoop M D
2025-08-01 13:50:13 +05:30
parent 98c09db820
commit 7efaa427ca

128
scripts/count-locs.js Executable file
View File

@@ -0,0 +1,128 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const PACKAGES_DIR = path.join(__dirname, '..', 'packages');
const EXCLUDE_DIRS = ['node_modules', 'dist', 'build', '.next', 'coverage', '.git'];
const EXCLUDE_PACKAGES = ['bruno-toml', 'bruno-tests', 'bruno-docs'];
const CODE_EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx', '.css', '.scss', '.json', '.md'];
function countLinesInFile(filePath) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
return content.split('\n').length;
} catch (error) {
return 0;
}
}
function shouldExcludeDir(dirName) {
return EXCLUDE_DIRS.includes(dirName) || dirName.startsWith('.');
}
function isCodeFile(fileName) {
return CODE_EXTENSIONS.some(ext => fileName.endsWith(ext));
}
function countLinesInDirectory(dirPath) {
let totalLines = 0;
let fileCount = 0;
function walkDir(currentPath) {
const items = fs.readdirSync(currentPath);
for (const item of items) {
const itemPath = path.join(currentPath, item);
const stat = fs.statSync(itemPath);
if (stat.isDirectory()) {
if (!shouldExcludeDir(item)) {
walkDir(itemPath);
}
} else if (stat.isFile() && isCodeFile(item)) {
const lines = countLinesInFile(itemPath);
totalLines += lines;
fileCount++;
}
}
}
walkDir(dirPath);
return { totalLines, fileCount };
}
function getPackages() {
const packages = [];
const items = fs.readdirSync(PACKAGES_DIR);
for (const item of items) {
const itemPath = path.join(PACKAGES_DIR, item);
const stat = fs.statSync(itemPath);
if (stat.isDirectory() && !shouldExcludeDir(item) && !EXCLUDE_PACKAGES.includes(item)) {
packages.push({
name: item,
path: itemPath
});
}
}
return packages;
}
function formatNumber(num) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
function printTable(data) {
// Calculate column widths
const nameWidth = Math.max(20, ...data.map(d => d.name.length));
const locWidth = 12;
const filesWidth = 12;
// Header
console.log('\n┌' + '─'.repeat(nameWidth + 2) + '┬' + '─'.repeat(locWidth + 2) + '┬' + '─'.repeat(filesWidth + 2) + '┐');
console.log(`${'Package'.padEnd(nameWidth)}${'LOC'.padStart(locWidth)}${'Files'.padStart(filesWidth)}`);
console.log('├' + '─'.repeat(nameWidth + 2) + '┼' + '─'.repeat(locWidth + 2) + '┼' + '─'.repeat(filesWidth + 2) + '┤');
// Data rows
let totalLOC = 0;
let totalFiles = 0;
for (const row of data) {
console.log(`${row.name.padEnd(nameWidth)}${formatNumber(row.loc).padStart(locWidth)}${formatNumber(row.files).padStart(filesWidth)}`);
totalLOC += row.loc;
totalFiles += row.files;
}
// Footer
console.log('├' + '─'.repeat(nameWidth + 2) + '┼' + '─'.repeat(locWidth + 2) + '┼' + '─'.repeat(filesWidth + 2) + '┤');
console.log(`${'TOTAL'.padEnd(nameWidth)}${formatNumber(totalLOC).padStart(locWidth)}${formatNumber(totalFiles).padStart(filesWidth)}`);
console.log('└' + '─'.repeat(nameWidth + 2) + '┴' + '─'.repeat(locWidth + 2) + '┴' + '─'.repeat(filesWidth + 2) + '┘\n');
}
function main() {
console.log('Counting lines of code in Bruno packages...\n');
const packages = getPackages();
const results = [];
for (const pkg of packages) {
process.stdout.write(`Analyzing ${pkg.name}...`);
const { totalLines, fileCount } = countLinesInDirectory(pkg.path);
results.push({
name: pkg.name,
loc: totalLines,
files: fileCount
});
process.stdout.write(' Done\n');
}
// Sort by LOC descending
results.sort((a, b) => b.loc - a.loc);
printTable(results);
}
main();