Files
market_screener/ui/src/lib/api.ts
T
2026-06-06 22:55:43 -04:00

128 lines
4.1 KiB
TypeScript

import type {
ScreenerResult,
MarketContext,
MarketCall,
CalendarEvent,
CatalystStory,
LLMAnalysis,
PortfolioHolding,
PortfolioAdvice,
} from '$lib/types.js';
const BASE = '/api';
// ── Screener ──────────────────────────────────────────────────────────────────
export async function screenTickers(tickers: string[]): Promise<ScreenerResult> {
const res = await fetch(`${BASE}/screen`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tickers }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function fetchCatalysts(): Promise<{ tickers: string[]; stories: CatalystStory[] }> {
const res = await fetch(`${BASE}/screen/catalysts`);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function analyzeTickers(tickers: string[]): Promise<{ analysis: LLMAnalysis | null }> {
const res = await fetch(`${BASE}/analyze`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tickers }),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
// ── Finance / Portfolio ───────────────────────────────────────────────────────
export async function fetchPortfolio(): Promise<{
advice: PortfolioAdvice[];
holdings: PortfolioHolding[];
marketContext: MarketContext | null;
netWorth: number | null;
error?: string;
}> {
const res = await fetch(`${BASE}/finance/portfolio`);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function addHolding(
holding: Omit<PortfolioHolding, never>,
): Promise<{ holdings: PortfolioHolding[] }> {
const res = await fetch(`${BASE}/finance/holdings`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(holding),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function removeHolding(ticker: string): Promise<{ holdings: PortfolioHolding[] }> {
const res = await fetch(`${BASE}/finance/holdings/${ticker}`, {
method: 'DELETE',
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function fetchMarketContext(): Promise<MarketContext> {
const res = await fetch(`${BASE}/finance/market-context`);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
// ── Market Calls ──────────────────────────────────────────────────────────────
export async function fetchCalls(): Promise<{ calls: MarketCall[] }> {
const res = await fetch(`${BASE}/calls`);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function fetchCall(id: string): Promise<MarketCall & { current: ScreenerResult }> {
const res = await fetch(`${BASE}/calls/${id}`);
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function createCall(payload: {
title: string;
quarter: string;
thesis: string;
tickers: string[];
date?: string;
}): Promise<MarketCall> {
const res = await fetch(`${BASE}/calls`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload),
});
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function deleteCall(id: string): Promise<{ ok: boolean }> {
const res = await fetch(`${BASE}/calls/${id}`, { method: 'DELETE' });
if (!res.ok) throw new Error(await res.text());
return res.json();
}
export async function fetchCallsCalendar(
tickers: string[] | null = null,
): Promise<{ events: CalendarEvent[] }> {
const url = tickers?.length
? `${BASE}/calls/calendar?tickers=${tickers.join(',')}`
: `${BASE}/calls/calendar`;
const res = await fetch(url);
if (!res.ok) throw new Error(await res.text());
return res.json();
}