160 lines
3.7 KiB
TypeScript
160 lines
3.7 KiB
TypeScript
import * as fs from 'fs';
|
|
|
|
interface Stat {
|
|
fileType: string;
|
|
count: number;
|
|
lines: number;
|
|
}
|
|
|
|
abstract class StatsBase {
|
|
parent: StatsBase | undefined;
|
|
path: string;
|
|
name: string;
|
|
stats: Stat[];
|
|
|
|
constructor(parent: StatsBase | undefined, path: string, name: string, stats: Stat[]) {
|
|
this.parent = parent;
|
|
|
|
this.path = path;
|
|
this.name = name;
|
|
this.stats = stats;
|
|
}
|
|
|
|
abstract addChild(child: StatsBase): void;
|
|
|
|
abstract mergeStats(stats: Stat[]): void;
|
|
|
|
abstract print(depth: number, lastChildArr: boolean[]): void;
|
|
|
|
abstract sort(): void;
|
|
|
|
getPrefix(depth: number, lastChildArr: boolean[]): string {
|
|
let prefix = '';
|
|
for (let i = 0; i < depth; i++) {
|
|
prefix += lastChildArr[i] ? ' ' : '│ ';
|
|
}
|
|
|
|
if (lastChildArr.at(-1)) {
|
|
prefix += '└─ ';
|
|
} else {
|
|
prefix += '├─ ';
|
|
}
|
|
|
|
return prefix;
|
|
}
|
|
}
|
|
|
|
class FolderStats extends StatsBase {
|
|
children: StatsBase[];
|
|
|
|
constructor(parent: StatsBase | undefined, path: string, name: string) {
|
|
super(parent, path, name, []);
|
|
|
|
this.children = [];
|
|
}
|
|
|
|
addChild(child: StatsBase) {
|
|
this.children.push(child);
|
|
this.mergeStats(child.stats);
|
|
}
|
|
|
|
mergeStats(stats: Stat[]): void {
|
|
// console.log(this, stats);
|
|
for (const stat of stats) {
|
|
const existingStat = this.stats.find(s => s.fileType === stat.fileType);
|
|
if (existingStat) {
|
|
existingStat.count += stat.count;
|
|
existingStat.lines += stat.lines;
|
|
} else {
|
|
this.stats.push(structuredClone(stat));
|
|
}
|
|
}
|
|
|
|
this.parent?.mergeStats(stats);
|
|
}
|
|
|
|
print(depth: number, lastChildArr: boolean[]): void {
|
|
console.log(
|
|
`${this.getPrefix(depth, lastChildArr)}${this.name} | ${this.stats.reduce((acc, s) => acc + s.count, 0)} files | ${this.stats.reduce((acc, s) => acc + s.lines, 0)} lines`,
|
|
);
|
|
for (let i = 0; i < this.children.length; i++) {
|
|
const child = this.children[i];
|
|
child.print(depth + 1, [...lastChildArr, i === this.children.length - 1]);
|
|
}
|
|
}
|
|
|
|
sort(): void {
|
|
this.children.sort((a, b) => {
|
|
if (a instanceof FolderStats && b instanceof FileStats) {
|
|
return 1;
|
|
} else if (a instanceof FileStats && b instanceof FolderStats) {
|
|
return -1;
|
|
} else {
|
|
return a.name.localeCompare(b.name);
|
|
}
|
|
});
|
|
this.children.forEach(c => c.sort());
|
|
}
|
|
}
|
|
|
|
class FileStats extends StatsBase {
|
|
constructor(parent: StatsBase, path: string, name: string, stats: Stat[]) {
|
|
super(parent, path, name, stats);
|
|
}
|
|
|
|
addChild(_child: StatsBase): void {
|
|
throw new Error('Cannot add child to file');
|
|
}
|
|
|
|
mergeStats(_stats: Stat[]): void {
|
|
throw new Error('Cannot merge stats to file');
|
|
}
|
|
|
|
print(depth: number, lastChildArr: boolean[]): void {
|
|
console.log(`${this.getPrefix(depth, lastChildArr)}${this.name} | ${this.stats[0].lines} lines`);
|
|
}
|
|
|
|
sort(): void {}
|
|
}
|
|
|
|
function collectStats() {
|
|
const root = new FolderStats(undefined, './src', 'src');
|
|
const ignore = ['node_modules', 'extraTypes', 'bun.lockb'];
|
|
|
|
const todo: FolderStats[] = [root];
|
|
|
|
while (todo.length > 0) {
|
|
const current = todo.pop()!;
|
|
const children = fs.readdirSync(current.path, { withFileTypes: true });
|
|
|
|
for (const child of children) {
|
|
if (ignore.includes(child.name)) {
|
|
continue;
|
|
}
|
|
|
|
if (child.isDirectory()) {
|
|
const folder = new FolderStats(current, `${current.path}/${child.name}`, child.name);
|
|
current.addChild(folder);
|
|
|
|
todo.push(folder);
|
|
} else {
|
|
const content = fs.readFileSync(`${current.path}/${child.name}`, 'utf-8');
|
|
|
|
const file = new FileStats(current, `${current.path}/${child.name}`, child.name, [
|
|
{
|
|
fileType: child.name.split('.').splice(1).join('.'),
|
|
count: 1,
|
|
lines: content.split('\n').length,
|
|
},
|
|
]);
|
|
current.addChild(file);
|
|
}
|
|
}
|
|
}
|
|
|
|
root.sort();
|
|
|
|
root.print(0, [true]);
|
|
}
|
|
|
|
collectStats();
|