diff --git a/app/api/compare/route.ts b/app/api/compare/route.ts index 809b290..78306d7 100644 --- a/app/api/compare/route.ts +++ b/app/api/compare/route.ts @@ -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 = diff --git a/lib/cache.ts b/lib/cache.ts new file mode 100644 index 0000000..5a9db2a --- /dev/null +++ b/lib/cache.ts @@ -0,0 +1,35 @@ +interface CacheEntry { + data: T; + expiresAt: number; +} + +const store = new Map>(); + +const DEFAULT_TTL_MS = 5 * 60 * 1000; + +export function getCached(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(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 }; +} diff --git a/lib/github.ts b/lib/github.ts index 4023aac..0dd995e 100644 --- a/lib/github.ts +++ b/lib/github.ts @@ -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"); @@ -60,15 +61,22 @@ const QUERY = /* GraphQL */ ` export async function fetchGitHubUserData( username: string ): Promise { + const cacheKey = `github:${username.toLowerCase()}`; + const cached = getCached(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; }