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())
}
}