← back to Wine Finder Next
src/api/wineProviders.ts
133 lines
/**
* Wine Providers API - Aggregates auction and retail wine data
*/
import { apiClient } from './httpClient';
import { WineListing, PriceHistoryPoint } from '../types/wine';
interface SearchResponse {
wines: WineListing[];
}
interface PriceHistoryResponse {
history: PriceHistoryPoint[];
}
/**
* Search WineBid auctions
*/
export async function fetchFromWineBid(query: string): Promise<WineListing[]> {
try {
const response = await apiClient.get<SearchResponse>('/winebid/search', { q: query });
return response.wines || [];
} catch (error) {
console.error('WineBid fetch failed:', error);
return [];
}
}
/**
* Search Sotheby's wine auctions
*/
export async function fetchFromSothebys(query: string): Promise<WineListing[]> {
try {
const response = await apiClient.get<SearchResponse>('/sothebys/search', { q: query });
return response.wines || [];
} catch (error) {
console.error('Sothebys fetch failed:', error);
return [];
}
}
/**
* Search Zachys wine auctions
*/
export async function fetchFromZachys(query: string): Promise<WineListing[]> {
try {
const response = await apiClient.get<SearchResponse>('/zachys/search', { q: query });
return response.wines || [];
} catch (error) {
console.error('Zachys fetch failed:', error);
return [];
}
}
/**
* Search Wine.com retail
*/
export async function fetchFromWineCom(query: string): Promise<WineListing[]> {
try {
const response = await apiClient.get<SearchResponse>('/winecom/search', { q: query });
return response.wines || [];
} catch (error) {
console.error('Wine.com fetch failed:', error);
return [];
}
}
/**
* Search Vivino retail
*/
export async function fetchFromVivino(query: string): Promise<WineListing[]> {
try {
const response = await apiClient.get<SearchResponse>('/vivino/search', { q: query });
return response.wines || [];
} catch (error) {
console.error('Vivino fetch failed:', error);
return [];
}
}
/**
* Search Wine-Searcher (aggregates retail + auction)
*/
export async function fetchFromWineSearcher(query: string): Promise<WineListing[]> {
try {
const response = await apiClient.get<SearchResponse>('/wine-searcher/search', { q: query });
return response.wines || [];
} catch (error) {
console.error('Wine-Searcher fetch failed:', error);
return [];
}
}
/**
* Search ALL providers in parallel and aggregate results
*/
export async function searchWineEverywhere(query: string): Promise<WineListing[]> {
const results = await Promise.allSettled([
fetchFromWineBid(query),
fetchFromSothebys(query),
fetchFromZachys(query),
fetchFromWineCom(query),
fetchFromVivino(query),
fetchFromWineSearcher(query),
]);
const allWines: WineListing[] = [];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
allWines.push(...result.value);
} else {
const providers = ['WineBid', 'Sothebys', 'Zachys', 'Wine.com', 'Vivino', 'Wine-Searcher'];
console.warn(`${providers[index]} search failed:`, result.reason);
}
});
return allWines;
}
/**
* Get price history for a specific wine
*/
export async function fetchPriceHistory(wineId: string): Promise<PriceHistoryPoint[]> {
try {
const response = await apiClient.get<PriceHistoryResponse>('/price-history', { wineId });
return response.history || [];
} catch (error) {
console.error('Price history fetch failed:', error);
return [];
}
}