@@ -0,0 +1,66 @@
+const fs = require("fs");
+const path = require("path");
+
+const IGNORED_DIRS = ["node_modules", ".git", "dist", "build", "coverage"];
+
+function scanDirectory(dirPath) {
+ const stats = {
+ totalFiles: 0,
+ totalLines: 0,
+ totalSize: 0,
+ extensions: {},
+ directories: {},
+ };
+
+ walk(dirPath, dirPath, stats);
+ return stats;
+}
+
+function walk(basePath, currentPath, stats) {
+ const entries = fs.readdirSync(currentPath, { withFileTypes: true });
+
+ for (const entry of entries) {
+ const fullPath = path.join(currentPath, entry.name);
+
+ if (entry.isDirectory()) {
+ if (IGNORED_DIRS.includes(entry.name)) continue;
+ walk(basePath, fullPath, stats);
+ continue;
+ }
+
+ if (!entry.isFile()) continue;
+
+ const ext = path.extname(entry.name) || "(no ext)";
+ const relativePath = path.relative(basePath, currentPath);
+ const dir = relativePath || "(root)";
+ const fileStat = fs.statSync(fullPath);
+ const lines = countLines(fullPath);
+
+ stats.totalFiles++;
+ stats.totalLines += lines;
+ stats.totalSize += fileStat.size;
+
+ if (!stats.extensions[ext]) {
+ stats.extensions[ext] = { files: 0, lines: 0 };
+ }
+ stats.extensions[ext].files++;
+ stats.extensions[ext].lines += lines;
+
+ if (!stats.directories[dir]) {
+ stats.directories[dir] = { files: 0, size: 0 };
+ }
+ stats.directories[dir].files++;
+ stats.directories[dir].size += fileStat.size;
+ }
+}
+
+function countLines(filePath) {
+ try {
+ const content = fs.readFileSync(filePath, "utf-8");
+ return content.split("\n").length;
+ } catch {
+ return 0;
+ }
+}
+
+module.exports = { scanDirectory };