Repository navigation
Expand file tree
/
Copy pathclient.ts
More file actions
80 lines (70 loc) · 2.29 KB
/
Copy pathclient.ts
File metadata and controls
80 lines (70 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { Octokit } from '@octokit/rest';
let octokitInstance: Octokit | null = null;
export function resetOctokit(): void {
octokitInstance = null;
}
export function getOctokit(token?: string): Octokit {
if (token) {
return new Octokit({
auth: token,
userAgent: 'gitSdm/1.0',
});
}
if (!octokitInstance) {
const envToken = process.env.GITHUB_TOKEN?.trim();
octokitInstance = new Octokit({
auth: envToken || undefined,
userAgent: 'gitSdm/1.0',
});
}
return octokitInstance;
}
export function isGitHubAuthenticated(): boolean {
return Boolean(process.env.GITHUB_TOKEN?.trim());
}
export class GitHubRateLimitError extends Error {
constructor(
message: string,
public retryAfter?: number,
) {
super(message);
this.name = 'GitHubRateLimitError';
}
}
export function handleOctokitError(error: unknown): never {
if (error && typeof error === 'object' && 'status' in error) {
const err = error as {
status: number;
message?: string;
response?: { headers?: Record<string, string> };
};
const headers = err.response?.headers ?? {};
const limit = headers['x-ratelimit-limit'];
if (err.status === 401) {
throw new Error(
'Invalid or expired GITHUB_TOKEN. Create a new token at github.com/settings/tokens with public repo read access.',
);
}
if (err.status === 403 || err.status === 429) {
const retryAfter = headers['retry-after'];
const resetAt = headers['x-ratelimit-reset'];
const resetHint = resetAt
? ` Try again after ${new Date(parseInt(resetAt, 10) * 1000).toLocaleTimeString()}.`
: '';
if (limit === '60' || !isGitHubAuthenticated()) {
throw new GitHubRateLimitError(
`GitHub API rate limit exceeded (unauthenticated — 60/hr). Set GITHUB_TOKEN in .env and restart \`npm run dev\`.${resetHint}`,
retryAfter ? parseInt(retryAfter, 10) : 60,
);
}
throw new GitHubRateLimitError(
`GitHub API rate limit exceeded (authenticated quota used).${resetHint}`,
retryAfter ? parseInt(retryAfter, 10) : 60,
);
}
if (err.status === 404) {
throw new Error('Repository not found or is private.');
}
}
throw error instanceof Error ? error : new Error('GitHub API error');
}