/** * Maintainer GitHub Repos Route * * GET /api/maintainer/github/repos * Fetch user's owned GitHub repositories for Add Repo dropdown */ import { NextRequest, NextResponse } from "next/server"; import { getCurrentUser } from "@/lib/auth"; import { db } from "@/db"; import { repositories } from "@/db/schema"; import { eq } from "drizzle-orm"; export async function GET(request: NextRequest) { try { const user = await getCurrentUser(request); if (!user) { return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } if (!user.githubAccessToken) { return NextResponse.json({ error: "GitHub token not available" }, { status: 400 }); } // Fetch user's repos from GitHub (owned and where they have push/admin access) const response = await fetch("https://api.github.com/user/repos?affiliation=owner,collaborator&per_page=100&sort=updated", { headers: { "Authorization": `Bearer ${user.githubAccessToken}`, "Accept": "application/vnd.github.v3+json", "User-Agent": "OpenTriage" } }); if (!response.ok) { console.error("GitHub API error:", response.status, await response.text()); return NextResponse.json({ error: "Failed to fetch repos from GitHub" }, { status: 502 }); } const githubRepos = await response.json(); // Get already-added repos to filter them out (by name since githubRepoId might be 0) const existingRepos = await db.select({ name: repositories.name }) .from(repositories) .where(eq(repositories.userId, user.id)); const existingNames = new Set(existingRepos.map(r => r.name)); // Filter and format repos - filter by fullName const availableRepos = githubRepos .filter((repo: any) => !existingNames.has(repo.full_name)) // Only include repos where user has admin or push permissions .filter((repo: any) => repo.permissions?.admin || repo.permissions?.push || repo.permissions?.maintain) .map((repo: any) => ({ id: repo.id, name: repo.name, fullName: repo.full_name, owner: repo.owner.login, description: repo.description, language: repo.language, stars: repo.stargazers_count, updatedAt: repo.updated_at, isPrivate: repo.private, })); return NextResponse.json({ repos: availableRepos, total: availableRepos.length, }); } catch (error) { console.error("GET /api/maintainer/github/repos error:", error); return NextResponse.json({ error: "Internal server error" }, { status: 500 }); } }