mirror of
https://github.com/better-auth/better-auth.git
synced 2026-05-24 08:01:56 -05:00
124 lines
3.2 KiB
TypeScript
124 lines
3.2 KiB
TypeScript
import { unstable_cache } from "next/cache";
|
|
import staticContributors from "./contributors-data.json";
|
|
|
|
export interface CommunityStats {
|
|
npmDownloads: number;
|
|
githubStars: number;
|
|
contributors: number;
|
|
discordMembers: number;
|
|
}
|
|
|
|
export interface ContributorInfo {
|
|
login: string;
|
|
avatar_url: string;
|
|
html_url: string;
|
|
}
|
|
|
|
export function getContributors(): ContributorInfo[] {
|
|
return staticContributors as ContributorInfo[];
|
|
}
|
|
|
|
const staticContributorsCount = staticContributors.length;
|
|
|
|
// Fetch NPM download stats for the last year
|
|
async function fetchNpmDownloads(): Promise<number> {
|
|
try {
|
|
const response = await fetch(
|
|
"https://api.npmjs.org/downloads/point/last-year/better-auth",
|
|
{ next: { revalidate: 3600 } }, // Cache for 1 hour
|
|
);
|
|
|
|
if (!response.ok) {
|
|
console.error("Failed to fetch NPM downloads:", response.status);
|
|
return 500000; // Fallback value
|
|
}
|
|
|
|
const data = await response.json();
|
|
return data.downloads || 500000;
|
|
} catch (error) {
|
|
console.error("Error fetching NPM downloads:", error);
|
|
return 500000; // Fallback value
|
|
}
|
|
}
|
|
|
|
// Shared headers for GitHub API requests
|
|
const githubHeaders = {
|
|
Accept: "application/vnd.github.v3+json",
|
|
...(process.env.GITHUB_TOKEN && {
|
|
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
|
|
}),
|
|
};
|
|
|
|
// Fetch GitHub repository stats — repo info and contributors in parallel
|
|
async function fetchGitHubStats(): Promise<{
|
|
stars: number;
|
|
contributors: number;
|
|
}> {
|
|
try {
|
|
const [repoResponse, contributorsResponse] = await Promise.all([
|
|
fetch("https://api.github.com/repos/better-auth/better-auth", {
|
|
next: { revalidate: 3600 },
|
|
headers: githubHeaders,
|
|
}),
|
|
fetch(
|
|
"https://api.github.com/repos/better-auth/better-auth/contributors?per_page=1&anon=true",
|
|
{
|
|
next: { revalidate: 3600 },
|
|
headers: githubHeaders,
|
|
},
|
|
),
|
|
]);
|
|
|
|
let stars = 26000;
|
|
if (repoResponse.ok) {
|
|
const data = await repoResponse.json();
|
|
stars = data.stargazers_count || 26000;
|
|
} else {
|
|
console.error("Failed to fetch GitHub repo stats:", repoResponse.status);
|
|
}
|
|
|
|
let contributorsCount = staticContributorsCount;
|
|
if (contributorsResponse.ok) {
|
|
const linkHeader = contributorsResponse.headers.get("Link");
|
|
if (linkHeader) {
|
|
const match = linkHeader.match(/page=(\d+)>; rel="last"/);
|
|
if (match) {
|
|
contributorsCount = parseInt(match[1], 10);
|
|
}
|
|
}
|
|
} else {
|
|
console.error(
|
|
"Failed to fetch contributors:",
|
|
contributorsResponse.status,
|
|
);
|
|
}
|
|
|
|
return { stars, contributors: contributorsCount };
|
|
} catch (error) {
|
|
console.error("Error fetching GitHub stats:", error);
|
|
return { stars: 26000, contributors: staticContributorsCount };
|
|
}
|
|
}
|
|
|
|
// Cached function to get all community stats
|
|
export const getCommunityStats = unstable_cache(
|
|
async (): Promise<CommunityStats> => {
|
|
const [npmDownloads, githubStats] = await Promise.all([
|
|
fetchNpmDownloads(),
|
|
fetchGitHubStats(),
|
|
]);
|
|
|
|
return {
|
|
npmDownloads,
|
|
githubStars: githubStats.stars,
|
|
contributors: githubStats.contributors,
|
|
discordMembers: 10000, // Discord API requires bot token, using static value
|
|
};
|
|
},
|
|
["community-stats"],
|
|
{
|
|
revalidate: 3600, // Revalidate every hour
|
|
tags: ["community-stats"],
|
|
},
|
|
);
|