From 3cac486f6fdad9b54b2521676380872035af5660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Fri, 6 Feb 2026 22:25:04 +0100 Subject: [PATCH] fix Steam API: transform response format and add comprehensive logging - Backend: transform Steam API response to match frontend expectations (games/count structure) - Frontend: map Steam game fields (appid, name, playtime_forever) to database schema (id, title, playtimeHours) - Add detailed logging throughout request lifecycle for debugging - Add 60-second timeout with AbortController to prevent indefinite hanging - Fix IndexedDB constraint violation by properly transforming game data before save Co-Authored-By: Claude --- server/index.js | 21 ++++++- src/pages/Settings/SettingsDetailPage.tsx | 75 +++++++++++++++++------ 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/server/index.js b/server/index.js index 1f5e355..ebc7d72 100644 --- a/server/index.js +++ b/server/index.js @@ -23,9 +23,10 @@ app.get("/health", (req, res) => { app.post("/steam/refresh", async (req, res) => { const { apiKey, steamId } = req.body; - console.log(`Steam refresh for user: ${steamId}`); + console.log(`[Steam] Starting refresh for user: ${steamId}`); if (!apiKey || !steamId) { + console.log("[Steam] Missing credentials"); return res.status(400).json({ error: "Missing required fields: apiKey and steamId", }); @@ -35,9 +36,12 @@ app.post("/steam/refresh", async (req, res) => { // Call Steam Web API const steamUrl = `https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/?key=${apiKey}&steamid=${steamId}&include_appinfo=1&include_played_free_games=1&format=json`; + console.log("[Steam] Calling Steam API..."); const response = await fetch(steamUrl); + console.log(`[Steam] Got response: ${response.status}`); if (!response.ok) { + console.log(`[Steam] Steam API error: ${response.statusText}`); return res.status(response.status).json({ error: "Steam API error", message: response.statusText, @@ -45,9 +49,20 @@ app.post("/steam/refresh", async (req, res) => { } const data = await response.json(); - res.json(data); + console.log(`[Steam] Success! Games count: ${data.response?.game_count || 0}`); + + // Transform Steam API response to match frontend expectations + const transformed = { + games: data.response?.games || [], + count: data.response?.game_count || 0, + }; + + const responseSize = JSON.stringify(transformed).length; + console.log(`[Steam] Sending response: ${responseSize} bytes, ${transformed.games.length} games`); + res.json(transformed); + console.log(`[Steam] Response sent successfully`); } catch (error) { - console.error("Steam API error:", error); + console.error("[Steam] Exception:", error); res.status(500).json({ error: "Failed to fetch games", message: error.message, diff --git a/src/pages/Settings/SettingsDetailPage.tsx b/src/pages/Settings/SettingsDetailPage.tsx index a72ec12..2248eff 100644 --- a/src/pages/Settings/SettingsDetailPage.tsx +++ b/src/pages/Settings/SettingsDetailPage.tsx @@ -122,28 +122,65 @@ export default function SettingsDetailPage() { } const apiUrl = ConfigService.getApiUrl("/api/steam/refresh"); - const response = await fetch(apiUrl, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - apiKey: steamConfig.apiKey, - steamId: steamConfig.steamId, - }), - }); + console.log("[Frontend] Calling Steam API:", apiUrl); - if (!response.ok) { - const errorText = await response.text(); - setApiOutput(`❌ API Fehler: ${response.status}\n${errorText}`); - setAlertMessage("Steam Refresh fehlgeschlagen"); - setShowAlert(true); - return; + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 60000); // 60 second timeout + + try { + const response = await fetch(apiUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + apiKey: steamConfig.apiKey, + steamId: steamConfig.steamId, + }), + signal: controller.signal, + }); + clearTimeout(timeoutId); + + console.log("[Frontend] Got response:", response.status, response.statusText); + + if (!response.ok) { + const errorText = await response.text(); + console.error("[Frontend] API error:", errorText); + setApiOutput(`❌ API Fehler: ${response.status}\n${errorText}`); + setAlertMessage("Steam Refresh fehlgeschlagen"); + setShowAlert(true); + return; + } + + console.log("[Frontend] Parsing JSON response..."); + result = await response.json(); + console.log("[Frontend] Parsed result:", { + count: result.count, + gamesLength: result.games?.length, + }); + } catch (fetchError) { + clearTimeout(timeoutId); + if (fetchError.name === 'AbortError') { + throw new Error('Request timeout - Steam API took too long to respond'); + } + throw fetchError; } - - result = await response.json(); } if (result) { - await db.saveGames(result.games); + console.log("[Frontend] Saving games to database..."); + + // Transform Steam games to match our Game interface + const transformedGames = result.games.map((steamGame: any) => ({ + id: `steam-${steamGame.appid}`, + title: steamGame.name, + source: 'steam', + sourceId: String(steamGame.appid), + platform: 'steam', + playtimeHours: steamGame.playtime_forever ? Math.round(steamGame.playtime_forever / 60) : 0, + url: `https://store.steampowered.com/app/${steamGame.appid}`, + })); + + await db.saveGames(transformedGames); + console.log("[Frontend] Games saved successfully"); const updatedConfig = { ...config, @@ -155,14 +192,16 @@ export default function SettingsDetailPage() { setConfig(updatedConfig); await ConfigService.saveConfig(updatedConfig); + console.log("[Frontend] Update complete, showing results"); setApiOutput( - `✓ ${result.count} Spiele abgerufen\n\nBeispiel:\n${JSON.stringify(result.games.slice(0, 2), null, 2)}`, + `✓ ${result.count} Spiele abgerufen\n\nBeispiel:\n${JSON.stringify(transformedGames.slice(0, 2), null, 2)}`, ); setAlertMessage(`✓ ${result.count} Spiele aktualisiert`); setShowAlert(true); } } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); + console.error("[Frontend] Error during refresh:", error); setApiOutput(`❌ Fehler: ${errorMsg}`); setAlertMessage("Aktualisierung fehlgeschlagen"); setShowAlert(true);