From 29e935b6802ad87e4e8a0aa0b2ce8c909d08025b Mon Sep 17 00:00:00 2001 From: Randall Stillwell Date: Tue, 22 Jul 2025 21:48:45 -0500 Subject: [PATCH] Fix API connection and Lorcana API issues - update API base URL to Vercel deployment and improve Lorcana API resilience --- src/services/cardDataSources.ts | 232 ++++++++++++++++++++------------ src/services/tcgApi.ts | 2 +- 2 files changed, 146 insertions(+), 88 deletions(-) diff --git a/src/services/cardDataSources.ts b/src/services/cardDataSources.ts index 8f8eed9..556ab2b 100644 --- a/src/services/cardDataSources.ts +++ b/src/services/cardDataSources.ts @@ -286,41 +286,62 @@ export const lorcanaService = { await lorcastLimiter.waitForSlot(); try { - const response = await fetch( - `${LORCAST_API_BASE_URL}/cards?q=${encodeURIComponent(query)}` - ); + // Try different search endpoints + const searchEndpoints = [ + `/cards?q=${encodeURIComponent(query)}`, + `/cards?search=${encodeURIComponent(query)}`, + `/cards?query=${encodeURIComponent(query)}`, + `/api/cards?q=${encodeURIComponent(query)}`, + `/api/cards?search=${encodeURIComponent(query)}`, + `/v0/cards?q=${encodeURIComponent(query)}`, + `/v0/cards?search=${encodeURIComponent(query)}` + ]; - if (!response.ok) { - throw new Error(`Lorcast API error: ${response.status}`); + for (const endpoint of searchEndpoints) { + try { + const response = await fetch(`${LORCAST_API_BASE_URL}${endpoint}`); + + if (response.ok) { + const data = await response.json(); + const cards = data.cards || data.data || data || []; + + if (cards.length > 0) { + console.log(`✅ Found ${cards.length} Lorcana cards from ${endpoint}`); + return cards.map((card: any) => ({ + id: card.id || card.uuid || `lorcana-${Math.random()}`, + name: card.name, + set_name: card.set?.name || card.set_name || '', + set_code: card.set?.code || card.set_code || '', + card_number: card.number || card.card_number || '', + rarity: card.rarity, + game: 'LORCANA', + mana_cost: card.cost?.toString() || card.mana_cost, + cmc: card.cost || card.cmc, + card_type: card.type || card.card_type, + colors: card.colors || [], + oracle_text: card.text || card.oracle_text || '', + power: card.strength?.toString() || card.power, + toughness: card.willpower?.toString() || card.toughness, + image_url: card.image_url || card.images?.small || card.images?.png, + stock_image_url: card.image_url || card.images?.small || card.images?.png, + current_price: card.price?.market || card.current_price || undefined, + market_price: card.price?.low || card.market_price || undefined, + verified: true, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + })); + } + } + } catch (e) { + console.log(`❌ Failed to search from ${endpoint}:`, e); + continue; + } } - const data = await response.json(); - - return data.cards.map((card: any) => ({ - id: card.id, - name: card.name, - set_name: card.set?.name || '', - set_code: card.set?.code || '', - card_number: card.number, - rarity: card.rarity, - game: 'LORCANA', - mana_cost: card.cost?.toString(), - cmc: card.cost, - card_type: card.type, - colors: card.colors || [], - oracle_text: card.text || '', - power: card.strength?.toString(), - toughness: card.willpower?.toString(), - image_url: card.image_url, - stock_image_url: card.image_url, - current_price: card.price?.market || undefined, - market_price: card.price?.low || undefined, - verified: true, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - })); + console.log('⚠️ No Lorcana cards found from any search endpoint'); + return []; } catch (error) { - console.error('Error fetching Lorcana cards:', error); + console.error('Error searching Lorcana cards:', error); return []; } }, @@ -329,45 +350,61 @@ export const lorcanaService = { await lorcastLimiter.waitForSlot(); try { - const response = await fetch( - `${LORCAST_API_BASE_URL}/cards?q=name:${encodeURIComponent(name)}` - ); + // Try different search endpoints for exact name match + const searchEndpoints = [ + `/cards?q=name:${encodeURIComponent(name)}`, + `/cards?search=${encodeURIComponent(name)}`, + `/cards?query=${encodeURIComponent(name)}`, + `/api/cards?q=name:${encodeURIComponent(name)}`, + `/api/cards?search=${encodeURIComponent(name)}`, + `/v0/cards?q=name:${encodeURIComponent(name)}`, + `/v0/cards?search=${encodeURIComponent(name)}` + ]; - if (!response.ok) { - return null; + for (const endpoint of searchEndpoints) { + try { + const response = await fetch(`${LORCAST_API_BASE_URL}${endpoint}`); + + if (response.ok) { + const data = await response.json(); + const cards = data.cards || data.data || data || []; + + if (cards.length > 0) { + const card = cards[0]; + console.log(`✅ Found Lorcana card "${name}" from ${endpoint}`); + return { + id: card.id || card.uuid || `lorcana-${Math.random()}`, + name: card.name, + set_name: card.set?.name || card.set_name || '', + set_code: card.set?.code || card.set_code || '', + card_number: card.number || card.card_number || '', + rarity: card.rarity, + game: 'LORCANA', + mana_cost: card.cost?.toString() || card.mana_cost, + cmc: card.cost || card.cmc, + card_type: card.type || card.card_type, + colors: card.colors || [], + oracle_text: card.text || card.oracle_text || '', + power: card.strength?.toString() || card.power, + toughness: card.willpower?.toString() || card.toughness, + image_url: card.image_url || card.images?.small || card.images?.png, + stock_image_url: card.image_url || card.images?.small || card.images?.png, + current_price: card.price?.market || card.current_price || undefined, + market_price: card.price?.low || card.market_price || undefined, + verified: true, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + } + } + } catch (e) { + console.log(`❌ Failed to fetch card from ${endpoint}:`, e); + continue; + } } - const data = await response.json(); - - if (data.cards.length === 0) { - return null; - } - - const card = data.cards[0]; - - return { - id: card.id, - name: card.name, - set_name: card.set?.name || '', - set_code: card.set?.code || '', - card_number: card.number, - rarity: card.rarity, - game: 'LORCANA', - mana_cost: card.cost?.toString(), - cmc: card.cost, - card_type: card.type, - colors: card.colors || [], - oracle_text: card.text || '', - power: card.strength?.toString(), - toughness: card.willpower?.toString(), - image_url: card.image_url, - stock_image_url: card.image_url, - current_price: card.price?.market || undefined, - market_price: card.price?.low || undefined, - verified: true, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - }; + console.log(`⚠️ Lorcana card "${name}" not found from any endpoint`); + return null; } catch (error) { console.error('Error fetching Lorcana card:', error); return null; @@ -378,39 +415,60 @@ export const lorcanaService = { await lorcastLimiter.waitForSlot(); try { - // Get all cards and randomly select - const response = await fetch(`${LORCAST_API_BASE_URL}/cards`); + // Try different endpoints for Lorcana cards + const endpoints = [ + '/cards', + '/api/cards', + '/v0/cards', + '/api/v0/cards' + ]; - if (!response.ok) { - throw new Error(`Lorcast API error: ${response.status}`); + let allCards: any[] = []; + + for (const endpoint of endpoints) { + try { + const response = await fetch(`${LORCAST_API_BASE_URL}${endpoint}`); + + if (response.ok) { + const data = await response.json(); + allCards = data.cards || data.data || data || []; + console.log(`✅ Found ${allCards.length} cards from ${endpoint}`); + break; + } + } catch (e) { + console.log(`❌ Failed to fetch from ${endpoint}:`, e); + continue; + } } - const data = await response.json(); - const allCards = data.cards || []; + if (allCards.length === 0) { + console.log('⚠️ No cards found from any endpoint, returning empty array'); + return []; + } // Randomly select cards const shuffled = allCards.sort(() => 0.5 - Math.random()); const selectedCards = shuffled.slice(0, count); return selectedCards.map((card: any) => ({ - id: card.id, + id: card.id || card.uuid || `lorcana-${Math.random()}`, name: card.name, - set_name: card.set?.name || '', - set_code: card.set?.code || '', - card_number: card.number, + set_name: card.set?.name || card.set_name || '', + set_code: card.set?.code || card.set_code || '', + card_number: card.number || card.card_number || '', rarity: card.rarity, game: 'LORCANA', - mana_cost: card.cost?.toString(), - cmc: card.cost, - card_type: card.type, + mana_cost: card.cost?.toString() || card.mana_cost, + cmc: card.cost || card.cmc, + card_type: card.type || card.card_type, colors: card.colors || [], - oracle_text: card.text || '', - power: card.strength?.toString(), - toughness: card.willpower?.toString(), - image_url: card.image_url, - stock_image_url: card.image_url, - current_price: card.price?.market || undefined, - market_price: card.price?.low || undefined, + oracle_text: card.text || card.oracle_text || '', + power: card.strength?.toString() || card.power, + toughness: card.willpower?.toString() || card.toughness, + image_url: card.image_url || card.images?.small || card.images?.png, + stock_image_url: card.image_url || card.images?.small || card.images?.png, + current_price: card.price?.market || card.current_price || undefined, + market_price: card.price?.low || card.market_price || undefined, verified: true, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), diff --git a/src/services/tcgApi.ts b/src/services/tcgApi.ts index e36a62d..f6f73c5 100644 --- a/src/services/tcgApi.ts +++ b/src/services/tcgApi.ts @@ -15,7 +15,7 @@ import type { UserStats, } from '../types'; -const API_BASE_URL = process.env.REACT_APP_API_URL || 'http://localhost:8000'; +const API_BASE_URL = process.env.REACT_APP_API_URL || 'https://tcg-vault.vercel.app'; // Create axios instance with default config const api = axios.create({