| import { Asset, DashboardOverview, LiveNewsArticle, MarketSentiment, PipelineStatus, RelatedNews, Signal } from "./types"; |
|
|
| const API_BASE = process.env.NEXT_PUBLIC_API_BASE ?? ""; |
|
|
| async function getJson<T>(path: string): Promise<T> { |
| const response = await fetch(`${API_BASE}${path}`, { cache: "no-store" }); |
| if (!response.ok) { |
| throw new Error(`${response.status} ${response.statusText}`); |
| } |
| return response.json() as Promise<T>; |
| } |
|
|
| async function postJson<T>(path: string, payload: unknown): Promise<T> { |
| const response = await fetch(`${API_BASE}${path}`, { |
| method: "POST", |
| headers: { "Content-Type": "application/json" }, |
| body: JSON.stringify(payload) |
| }); |
| if (!response.ok) { |
| throw new Error(`${response.status} ${response.statusText}`); |
| } |
| return response.json() as Promise<T>; |
| } |
|
|
| export const api = { |
| assets: () => getJson<Asset[]>("/assets"), |
| asset: (ticker: string) => getJson<{ asset: Asset; market_snapshot: Asset["market_snapshot"]; prices: any[]; latest_signal: Signal | null; related_news: RelatedNews[] }>(`/assets/${ticker}`), |
| overview: () => getJson<DashboardOverview>("/dashboard/overview"), |
| liveNews: (limit = 60) => getJson<LiveNewsArticle[]>(`/news/live?limit=${limit}`), |
| marketSentiment: (hours = 48) => getJson<MarketSentiment>(`/sentiment/market?hours=${hours}`), |
| pipelineStatus: () => getJson<PipelineStatus>("/pipeline/status"), |
| topSignals: (query = "") => getJson<Signal[]>(`/signals/top${query}`), |
| signal: (ticker: string) => getJson<Signal>(`/signals/${ticker}`), |
| sentiment: (ticker: string) => getJson<any[]>(`/sentiment/${ticker}`), |
| explain: (ticker: string) => getJson<any>(`/ai/explain/${ticker}`), |
| relatedNews: (ticker: string) => getJson<RelatedNews[]>(`/related-news?ticker=${ticker}`), |
| themes: () => getJson<any[]>("/themes"), |
| etfTrends: () => getJson<any[]>("/etf-trends"), |
| semanticSearch: (query: string) => postJson<any[]>("/semantic-search", { query, limit: 12 }), |
| marketUpdate: () => postJson("/market/update", { period: "max", limit: 36 }), |
| newsUpdate: () => postJson("/news/update", { lookback_hours: 72, limit_per_feed: 35 }), |
| runSignals: () => postJson("/signals/run", { refresh_prices: false, limit: 36 }), |
| runPipeline: () => postJson<any>("/pipeline/run", { refresh_prices: false, limit: 36 }), |
| backtest: (ticker: string) => postJson<any>(`/backtest/${ticker}`, {}) |
| }; |
|
|