-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
60 lines (49 loc) · 1.83 KB
/
server.js
File metadata and controls
60 lines (49 loc) · 1.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const express = require("express");
const fetch = require("node-fetch");
const app = express();
app.use(express.static("public")); // Serve frontend files
// Count LOC from file text
function countLOC(content) {
return content.split("\n").length;
}
// Endpoint: Get LOC for all repos of a user
app.get("/loc/:username", async (req, res) => {
const username = req.params.username;
try {
let page = 1, repos = [];
// Fetch all repos
while (true) {
const r = await fetch(`https://api.github.com/users/${username}/repos?per_page=100&page=${page}`);
if (!r.ok) throw new Error("Failed to fetch repos");
const data = await r.json();
repos = repos.concat(data);
if (data.length < 100) break;
page++;
}
let totalLOC = 0;
let repoResults = [];
for (const repo of repos) {
const filesRes = await fetch(`https://api.github.com/repos/${username}/${repo.name}/git/trees/${repo.default_branch}?recursive=1`);
if (!filesRes.ok) continue;
const filesData = await filesRes.json();
let repoLOC = 0;
if (filesData.tree) {
for (const file of filesData.tree) {
if (file.type === "blob" && !file.path.includes("node_modules") && !file.path.includes("dist")) {
const rawFile = await fetch(`https://raw.githubusercontent.com/${username}/${repo.name}/${repo.default_branch}/${file.path}`);
if (rawFile.ok) {
const content = await rawFile.text();
repoLOC += countLOC(content);
}
}
}
}
totalLOC += repoLOC;
repoResults.push({ repo: repo.name, loc: repoLOC });
}
res.json({ totalLOC, repos: repoResults });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
app.listen(3000, () => console.log("Server running on http://localhost:3000"));