let cachedToken: { token: string; expiresAt: number } | null = null export async function getAccessToken(): Promise { if (cachedToken && Date.now() < cachedToken.expiresAt - 30_000) { return cachedToken.token } const refreshToken = process.env.SPOTIFY_REFRESH_TOKEN if (!refreshToken) throw new Error('SPOTIFY_REFRESH_TOKEN not set') const clientId = process.env.SPOTIFY_CLIENT_ID! const clientSecret = process.env.SPOTIFY_CLIENT_SECRET! const res = await fetch('https://accounts.spotify.com/api/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`, }, body: new URLSearchParams({ grant_type: 'refresh_token', refresh_token: refreshToken, }), }) const data = await res.json() if (!data.access_token) throw new Error(`Spotify token refresh failed: ${JSON.stringify(data)}`) cachedToken = { token: data.access_token, expiresAt: Date.now() + (data.expires_in || 3600) * 1000, } return cachedToken.token }