Skip to content

Commit d0eb0e1

Browse files
feat:added pagination repo so all the dashboard data is correct
1 parent c449e64 commit d0eb0e1

3 files changed

Lines changed: 105 additions & 12 deletions

File tree

1

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
pick 2e4dc56 # feat:added pagination repo so all the dashboard data is correct
2+
s a0d8df7 # added UPPER_SNAKE_CASE
3+
4+
# Rebase c449e64..a0d8df7 onto c449e64 (2 commands)
5+
#
6+
# Commands:
7+
# p, pick <commit> = use commit
8+
# r, reword <commit> = use commit, but edit the commit message
9+
# e, edit <commit> = use commit, but stop for amending
10+
# s, squash <commit> = use commit, but meld into previous commit
11+
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
12+
# commit's log message, unless -C is used, in which case
13+
# keep only this commit's message; -c is same as -C but
14+
# opens the editor
15+
# x, exec <command> = run command (the rest of the line) using shell
16+
# b, break = stop here (continue rebase later with 'git rebase --continue')
17+
# d, drop <commit> = remove commit
18+
# l, label <label> = label current HEAD with a name
19+
# t, reset <label> = reset HEAD to a label
20+
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
21+
# create a merge commit using the original merge commit's
22+
# message (or the oneline, if no original merge commit was
23+
# specified); use -c <commit> to reword the commit message
24+
# u, update-ref <ref> = track a placeholder for the <ref> to be updated
25+
# to this position in the new commits. The <ref> is
26+
# updated at the end of the rebase
27+
#
28+
# These lines can be re-ordered; they are executed from top to bottom.
29+
#
30+
# If you remove a line here THAT COMMIT WILL BE LOST.
31+
#
32+
# However, if you remove everything, the rebase will be aborted.
33+
#

lib/github.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,53 @@ describe('fetchUserRepos', () => {
222222
vi.mocked(fetch).mockResolvedValue(mockResponse({ message: 'Error' }, 500));
223223
await expect(fetchUserRepos('octocat')).rejects.toThrow('GitHub REST API error: 500');
224224
});
225+
226+
it('fetches multiple pages of repos', async () => {
227+
vi.mocked(fetch)
228+
.mockResolvedValueOnce(
229+
mockResponse(
230+
Array.from({ length: 100 }, (_, i) => ({
231+
id: i,
232+
stargazers_count: i,
233+
language: 'TypeScript',
234+
}))
235+
)
236+
)
237+
.mockResolvedValueOnce(
238+
mockResponse([
239+
{
240+
id: 101,
241+
stargazers_count: 101,
242+
language: 'JavaScript',
243+
},
244+
])
245+
)
246+
.mockImplementation(() => Promise.resolve(mockResponse([])) as Promise<Response>);
247+
248+
const result = await fetchUserRepos('octocat');
249+
250+
expect(fetch).toHaveBeenCalledTimes(2);
251+
expect(result.length).toBe(101);
252+
});
253+
254+
it('stops fetching after reaching max pages', async () => {
255+
vi.mocked(fetch).mockImplementation(
256+
() =>
257+
Promise.resolve(
258+
mockResponse(
259+
Array.from({ length: 100 }, (_, i) => ({
260+
id: i,
261+
stargazers_count: i,
262+
language: 'TypeScript',
263+
}))
264+
)
265+
) as Promise<Response>
266+
);
267+
268+
await fetchUserRepos('octocat');
269+
270+
expect(fetch).toHaveBeenCalledTimes(100);
271+
});
225272
});
226273

227274
describe('getFullDashboardData', () => {

lib/github.ts

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,26 +238,39 @@ export async function fetchUserRepos(
238238
const cached = reposCache.get(key);
239239
if (cached) return cached;
240240
}
241+
const allRepos: GitHubRepo[] = [];
241242

242-
const res = await fetchWithRetry(
243-
`${GITHUB_REST_URL}/users/${username}/repos?per_page=100&sort=pushed`,
244-
{
245-
headers: getHeaders(),
246-
cache: 'no-store',
243+
let PAGE = 1;
244+
const MAX_PAGES = 100;
245+
while (PAGE <= MAX_PAGES) {
246+
const res = await fetchWithRetry(
247+
`${GITHUB_REST_URL}/users/${username}/repos?per_page=100&page=${PAGE}&sort=pushed`,
248+
{
249+
headers: getHeaders(),
250+
cache: 'no-store',
251+
}
252+
);
253+
254+
if (!res.ok) {
255+
throw new Error(`GitHub REST API error: ${res.status}`);
247256
}
248-
);
249257

250-
if (!res.ok) {
251-
throw new Error(`GitHub REST API error: ${res.status}`);
252-
}
258+
const repos = (await res.json()) as GitHubRepo[];
259+
260+
allRepos.push(...repos);
253261

254-
const repos = (await res.json()) as GitHubRepo[];
262+
if (repos.length < 100) {
263+
break;
264+
}
265+
266+
PAGE++;
267+
}
255268

256269
if (!options.bypassCache) {
257-
reposCache.set(key, repos, GITHUB_CACHE_TTL_MS);
270+
reposCache.set(key, allRepos, GITHUB_CACHE_TTL_MS);
258271
}
259272

260-
return repos;
273+
return allRepos;
261274
}
262275

263276
export function generateAchievements(totalContributions: number, currentStreak: number) {

0 commit comments

Comments
 (0)