fix(web): keep contributor stats current

This commit is contained in:
Hunter Bown
2026-05-12 15:32:01 -05:00
parent ad70655bbb
commit 9fb3d5d636
2 changed files with 33 additions and 8 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ const FALLBACK_STATS: RepoStats = {
forks: 0,
openIssues: 0,
openPulls: 0,
contributors: 1,
contributors: 69,
fetchedAt: new Date().toISOString(),
};
+32 -7
View File
@@ -2,6 +2,7 @@ import type { FeedItem, RepoStats } from "./types";
const REPO = process.env.GITHUB_REPO ?? "Hmbown/deepseek-tui";
const GH = "https://api.github.com";
const MIN_KNOWN_CONTRIBUTORS = 69;
function headers(token?: string): HeadersInit {
const h: Record<string, string> = {
@@ -29,13 +30,7 @@ export async function fetchRepoStats(token?: string): Promise<RepoStats> {
open_issues_count: number;
};
// Contributor count from Link header (anon=true). Fallback to 1.
let contributors = 1;
const link = contribRes.headers.get("link");
if (link) {
const m = link.match(/&page=(\d+)>; rel="last"/);
if (m) contributors = parseInt(m[1], 10);
}
const contributors = await contributorCount(contribRes);
// Open PRs: cheapest path is the search API.
const prRes = await fetch(
@@ -63,6 +58,36 @@ export async function fetchRepoStats(token?: string): Promise<RepoStats> {
};
}
async function contributorCount(res: Response): Promise<number> {
if (!res.ok) return MIN_KNOWN_CONTRIBUTORS;
const fromLink = lastPageFromLink(res.headers.get("link"));
if (fromLink) return Math.max(fromLink, MIN_KNOWN_CONTRIBUTORS);
const body = await res.json().catch(() => null);
if (Array.isArray(body)) return Math.max(body.length, MIN_KNOWN_CONTRIBUTORS);
return MIN_KNOWN_CONTRIBUTORS;
}
function lastPageFromLink(link: string | null): number | undefined {
if (!link) return undefined;
for (const part of link.split(",")) {
const [rawUrl, rawRel] = part.split(";").map((segment) => segment.trim());
if (rawRel !== 'rel="last"') continue;
const match = rawUrl.match(/^<(.+)>$/);
if (!match) continue;
const page = new URL(match[1]).searchParams.get("page");
const parsed = page ? Number.parseInt(page, 10) : NaN;
if (Number.isFinite(parsed) && parsed > 0) return parsed;
}
return undefined;
}
interface RawIssue {
number: number;
title: string;