Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion app/api/compare/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ export async function GET(request: Request) {
})
);

return NextResponse.json({ success: true, users: results });
return NextResponse.json(
{ success: true, users: results },
{ headers: { "Cache-Control": "public, s-maxage=300, stale-while-revalidate=60" } }
);
} catch (error: any) {
console.error("GitHub score error:", error);
const message =
Expand Down
35 changes: 35 additions & 0 deletions lib/cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
interface CacheEntry<T> {
data: T;
expiresAt: number;
}

const store = new Map<string, CacheEntry<unknown>>();

const DEFAULT_TTL_MS = 5 * 60 * 1000;

export function getCached<T>(key: string): T | undefined {
const entry = store.get(key);
if (!entry) return undefined;
if (Date.now() > entry.expiresAt) {
store.delete(key);
return undefined;
}
return entry.data as T;
}

export function setCached<T>(key: string, data: T, ttlMs = DEFAULT_TTL_MS) {
store.set(key, { data, expiresAt: Date.now() + ttlMs });
}

export function cacheStats() {
let valid = 0;
const now = Date.now();
for (const [key, entry] of store) {
if (now > entry.expiresAt) {
store.delete(key);
} else {
valid++;
}
}
return { size: valid };
}
10 changes: 9 additions & 1 deletion lib/github.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ContributionTotals, GitHubUserData, PullRequestNode, RepoNode } from "@/types/github";
import { graphql } from "@octokit/graphql";
import { getCached, setCached } from "./cache";

if (!process.env.GITHUB_TOKEN) {
throw new Error("Missing GITHUB_TOKEN");
Expand Down Expand Up @@ -60,15 +61,22 @@ const QUERY = /* GraphQL */ `
export async function fetchGitHubUserData(
username: string
): Promise<GitHubUserData> {
const cacheKey = `github:${username.toLowerCase()}`;
const cached = getCached<GitHubUserData>(cacheKey);
if (cached) return cached;

const { user } = await client<{ user: any }>(QUERY, { login: username });

if (!user) {
throw new Error("User not found");
}

return {
const data: GitHubUserData = {
repos: user.repositories.nodes as RepoNode[],
pullRequests: user.pullRequests.nodes as PullRequestNode[],
contributions: user.contributionsCollection as ContributionTotals,
};

setCached(cacheKey, data);
return data;
}
Loading