import { createServerFileRoute } from '@tanstack/react-start/server' const SPOTIFY_CLIENT_ID = import.meta.env.VITE_SPOTIFY_CLIENT_ID! const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET! export const ServerRoute = createServerFileRoute('/api/spotify/token').methods({ POST: async ({ request }: { request: Request }) => { try { const body = await request.json() const { refresh_token } = body if (!refresh_token) { return new Response( JSON.stringify({ error: 'refresh_token is required' }), { status: 400, headers: { 'Content-Type': 'application/json' }, } ) } // Refresh access token const tokenResponse = await fetch('https://accounts.spotify.com/api/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': `Basic ${Buffer.from(`${SPOTIFY_CLIENT_ID}:${SPOTIFY_CLIENT_SECRET}`).toString('base64')}`, }, body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token, }), }) if (!tokenResponse.ok) { const error = await tokenResponse.json() console.error('Token refresh error:', error) return new Response( JSON.stringify({ error: 'Failed to refresh token', details: error }), { status: tokenResponse.status, headers: { 'Content-Type': 'application/json' }, } ) } const tokens = await tokenResponse.json() // Return new tokens return new Response( JSON.stringify({ access_token: tokens.access_token, expires_in: tokens.expires_in, scope: tokens.scope, token_type: tokens.token_type, }), { status: 200, headers: { 'Content-Type': 'application/json' }, } ) } catch (error) { console.error('Token refresh endpoint error:', error) return new Response( JSON.stringify({ error: 'Internal server error' }), { status: 500, headers: { 'Content-Type': 'application/json' }, } ) } }, // GET endpoint to retrieve current tokens from cookies GET: async ({ request }: { request: Request }) => { try { const cookieHeader = request.headers.get('cookie') if (!cookieHeader) { return new Response( JSON.stringify({ error: 'No cookies found' }), { status: 401, headers: { 'Content-Type': 'application/json' }, } ) } const cookies = Object.fromEntries( cookieHeader.split('; ').map((c: string) => c.split('=')) ) const accessToken = cookies.spotify_access_token const refreshToken = cookies.spotify_refresh_token if (!accessToken && !refreshToken) { return new Response( JSON.stringify({ error: 'No Spotify tokens found' }), { status: 401, headers: { 'Content-Type': 'application/json' }, } ) } return new Response( JSON.stringify({ access_token: accessToken || null, refresh_token: refreshToken || null, has_tokens: !!(accessToken || refreshToken), }), { status: 200, headers: { 'Content-Type': 'application/json' }, } ) } catch (error) { console.error('Get tokens endpoint error:', error) return new Response( JSON.stringify({ error: 'Internal server error' }), { status: 500, headers: { 'Content-Type': 'application/json' }, } ) } }, })