* feat: added stock price widget * fix: formatting * fix: broken lock file * fix: requested changes * fix: added parsing schema * fix: improve time range and interval inputs * fix: only return required data * fix: formatting * fix: deepsource tests * fix: moved all time frames into one location * fix: formatting * fix: requested changes * fix: formatting * fix: parse response data * fix: update packages * fix: typescript issues * fix: formatting * fix: broken lockfile --------- Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import dayjs from "dayjs";
|
|
import { z } from "zod";
|
|
|
|
import { fetchWithTimeout } from "@homarr/common";
|
|
|
|
import { createCachedWidgetRequestHandler } from "./lib/cached-widget-request-handler";
|
|
|
|
export const fetchStockPriceHandler = createCachedWidgetRequestHandler({
|
|
queryKey: "fetchStockPriceResult",
|
|
widgetKind: "stockPrice",
|
|
async requestAsync(input: { stock: string; timeRange: string; timeInterval: string }) {
|
|
const response = await fetchWithTimeout(
|
|
`https://query1.finance.yahoo.com/v8/finance/chart/${input.stock}?range=${input.timeRange}&interval=${input.timeInterval}`,
|
|
);
|
|
const data = dataSchema.parse(await response.json());
|
|
|
|
if ("error" in data) {
|
|
throw new Error(data.error.description);
|
|
}
|
|
if (data.chart.result.length !== 1) {
|
|
throw new Error("Received multiple results");
|
|
}
|
|
if (!data.chart.result[0]) {
|
|
throw new Error("Received invalid data");
|
|
}
|
|
|
|
return data.chart.result[0];
|
|
},
|
|
cacheDuration: dayjs.duration(5, "minutes"),
|
|
});
|
|
|
|
const dataSchema = z
|
|
.object({
|
|
error: z.object({
|
|
description: z.string(),
|
|
}),
|
|
})
|
|
.or(
|
|
z.object({
|
|
chart: z.object({
|
|
result: z.array(
|
|
z.object({
|
|
indicators: z.object({
|
|
quote: z.array(
|
|
z.object({
|
|
close: z.array(z.number()),
|
|
}),
|
|
),
|
|
}),
|
|
meta: z.object({
|
|
symbol: z.string(),
|
|
shortName: z.string(),
|
|
}),
|
|
}),
|
|
),
|
|
}),
|
|
}),
|
|
);
|