import { NextRequest, NextResponse } from 'next/server' export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams const code = searchParams.get('code') const state = searchParams.get('state') const error = searchParams.get('error') // Handle OAuth error if (error) { const errorUrl = new URL('/dashboard', process.env.NEXT_PUBLIC_BASE_URL!) errorUrl.searchParams.set('error', `GitHub OAuth error: ${error}`) return NextResponse.redirect(errorUrl.toString()) } if (!code || !state) { const errorUrl = new URL('/dashboard', process.env.NEXT_PUBLIC_BASE_URL!) errorUrl.searchParams.set('error', 'Missing authorization code or state') return NextResponse.redirect(errorUrl.toString()) } try { // Decode state to get bookId and redirectUrl const decodedState = JSON.parse(Buffer.from(state, 'base64').toString()) const { bookId, redirectUrl } = decodedState // Exchange code for access token using repository management app const tokenResponse = await fetch('https://github.com/login/oauth/access_token', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ client_id: process.env.GITHUB_REPO_CLIENT_ID, client_secret: process.env.GITHUB_REPO_CLIENT_SECRET, code, }), }) if (!tokenResponse.ok) { throw new Error('Failed to exchange code for token') } const tokenData = await tokenResponse.json() if (tokenData.error) { throw new Error(`GitHub OAuth error: ${tokenData.error}`) } const accessToken = tokenData.access_token // Get user info from GitHub const userResponse = await fetch('https://api.github.com/user', { headers: { 'Authorization': `Bearer ${accessToken}`, 'Accept': 'application/vnd.github.v3+json', }, }) if (!userResponse.ok) { throw new Error('Failed to fetch user info from GitHub') } const githubUser = await userResponse.json() // Get user's repositories const reposResponse = await fetch('https://api.github.com/user/repos?type=all&sort=updated&per_page=100', { headers: { 'Authorization': `Bearer ${accessToken}`, 'Accept': 'application/vnd.github.v3+json', }, }) if (!reposResponse.ok) { throw new Error('Failed to fetch repositories from GitHub') } const repositories = await reposResponse.json() // Store the OAuth data and redirect to repository selection const oauthData = { bookId, accessToken, githubUsername: githubUser.login, redirectUrl, repositories: repositories.slice(0, 50).map((repo: any) => ({ id: repo.id, name: repo.name, full_name: repo.full_name, private: repo.private, updated_at: repo.updated_at, description: repo.description })) } // Redirect to repository selection page const handlerUrl = new URL('/auth/github/complete', process.env.NEXT_PUBLIC_BASE_URL!) handlerUrl.searchParams.set('data', Buffer.from(JSON.stringify(oauthData)).toString('base64')) return NextResponse.redirect(handlerUrl.toString()) } catch (error) { const errorUrl = new URL('/dashboard', process.env.NEXT_PUBLIC_BASE_URL!) errorUrl.searchParams.set('error', error instanceof Error ? error.message : 'GitHub OAuth failed') return NextResponse.redirect(errorUrl.toString()) } }