import type { DataProvider } from "../../../types/data-provider"; import type { Quote } from "../../../types/financials"; import { getActiveQuoteDisplay } from "../../../market-data/market/status"; import type { AlertRule } from "./types"; export function normalizeAlertSymbol(value: string | null | undefined): string { return value?.trim().toUpperCase() ?? ""; } export function createQuoteErrorMessage( symbol: string, error?: unknown, ): string { if (error instanceof Error && error.message.trim()) return error.message; return `No quote found for "${symbol}".`; } export async function resolveAlertQuote( marketData: Pick, symbol: string, exchange = "", ): Promise { const quote = await marketData.getQuote(symbol, exchange); const display = getActiveQuoteDisplay(quote); if (!display || !Number.isFinite(display.price)) { throw new Error(`No quote found for "${symbol}".`); } return { ...quote, price: display.price, change: display.change ?? Number.NaN, changePercent: display.changePercent ?? Number.NaN, }; } export function quoteAlertFields( quote: Quote, checkedAt = Date.now(), ): Pick< AlertRule, | "lastCheckedPrice" | "lastCheckedAt" | "lastQuoteUpdatedAt" | "lastQuoteSource" | "lastQuoteProviderId" > & { lastCheckError?: undefined } { return { lastCheckedPrice: quote.price, lastCheckedAt: checkedAt, lastQuoteUpdatedAt: quote.lastUpdated, lastQuoteSource: quote.dataSource, lastQuoteProviderId: quote.providerId, lastCheckError: undefined, }; } export function quoteErrorAlertFields( error: string, checkedAt = Date.now(), ): Pick { return { lastCheckedAt: checkedAt, lastCheckError: error, }; }