app/lib/githubAPIService.ts (179 lines of code) (raw):
// GitHub API service for fetching user repositories
export class GitHubAPIService {
private static readonly GITHUB_API_BASE = "https://api.github.com";
/**
* Fetch user's repositories from GitHub
*/
static async getUserRepositories(
token: string,
options: {
type?: "all" | "owner" | "member";
sort?: "created" | "updated" | "pushed" | "full_name";
direction?: "asc" | "desc";
per_page?: number;
page?: number;
} = {}
): Promise<GitHubRepository[]> {
try {
const params = new URLSearchParams({
type: options.type || "all",
sort: options.sort || "updated",
direction: options.direction || "desc",
per_page: String(options.per_page || 100),
page: String(options.page || 1),
});
const response = await fetch(
`${this.GITHUB_API_BASE}/user/repos?${params}`,
{
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
},
}
);
if (!response.ok) {
console.error("Failed to fetch GitHub repositories:", response.status);
return [];
}
const repos = await response.json();
return repos.map((repo: any) => ({
id: repo.id,
name: repo.name,
full_name: repo.full_name,
description: repo.description,
private: repo.private,
fork: repo.fork,
clone_url: repo.clone_url,
ssh_url: repo.ssh_url,
html_url: repo.html_url,
language: repo.language,
stargazers_count: repo.stargazers_count,
updated_at: repo.updated_at,
pushed_at: repo.pushed_at,
default_branch: repo.default_branch,
owner: {
login: repo.owner.login,
avatar_url: repo.owner.avatar_url,
},
}));
} catch (error) {
console.error("Error fetching GitHub repositories:", error);
return [];
}
}
/**
* Search user's repositories
*/
static async searchUserRepositories(
token: string,
query: string,
username?: string
): Promise<GitHubRepository[]> {
try {
if (!query.trim()) {
return [];
}
const searchQuery = username ? `${query} user:${username}` : query;
const params = new URLSearchParams({
q: searchQuery,
sort: "updated",
order: "desc",
per_page: "50",
});
const response = await fetch(
`${this.GITHUB_API_BASE}/search/repositories?${params}`,
{
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
},
}
);
if (!response.ok) {
console.error("Failed to search GitHub repositories:", response.status);
return [];
}
const data = await response.json();
return data.items.map((repo: any) => ({
id: repo.id,
name: repo.name,
full_name: repo.full_name,
description: repo.description,
private: repo.private,
fork: repo.fork,
clone_url: repo.clone_url,
ssh_url: repo.ssh_url,
html_url: repo.html_url,
language: repo.language,
stargazers_count: repo.stargazers_count,
updated_at: repo.updated_at,
pushed_at: repo.pushed_at,
default_branch: repo.default_branch,
owner: {
login: repo.owner.login,
avatar_url: repo.owner.avatar_url,
},
}));
} catch (error) {
console.error("Error searching GitHub repositories:", error);
return [];
}
}
/**
* Get repository branches
*/
static async getRepositoryBranches(
token: string,
owner: string,
repo: string
): Promise<GitHubBranch[]> {
try {
const response = await fetch(
`${this.GITHUB_API_BASE}/repos/${owner}/${repo}/branches`,
{
headers: {
Authorization: `Bearer ${token}`,
Accept: "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
},
}
);
if (!response.ok) {
console.error("Failed to fetch repository branches:", response.status);
return [];
}
const branches = await response.json();
return branches.map((branch: any) => ({
name: branch.name,
commit: {
sha: branch.commit.sha,
url: branch.commit.url,
},
protected: branch.protected,
}));
} catch (error) {
console.error("Error fetching repository branches:", error);
return [];
}
}
}
export interface GitHubRepository {
id: number;
name: string;
full_name: string;
description: string | null;
private: boolean;
fork: boolean;
clone_url: string;
ssh_url: string;
html_url: string;
language: string | null;
stargazers_count: number;
updated_at: string;
pushed_at: string;
default_branch: string;
owner: {
login: string;
avatar_url: string;
};
}
export interface GitHubBranch {
name: string;
commit: {
sha: string;
url: string;
};
protected: boolean;
}