import { BalanceMap, newCategoryBalanceMapFromDto } from "../types/balanceMap"; import { BudgetMap, newBudgetMapFromDto } from "../types/budgetMap"; import { BudgetUpdate, newBudgetUpdateFromDto } from "../types/budgetUpdate"; import { Category, newCategoryFromDto } from "../types/category"; const backendUrl = "http://localhost:8000"; function makeGetter(params: FetcherMakerParams): Getter { const parser = "parser" in params ? params.parser : (dto: unknown[]) => dto.map(params.elementParser); return async function () { const response = await fetch(`${backendUrl}${params.path}`); const dto = await response.json(); try { return parser(dto); } catch (err) { console.error(`Error parsing DTO. ${err?.toString() ?? ""}`); return null; } }; } export const getAllBudgetUpdates: Getter = makeGetter< BudgetUpdate[] >({ path: "/budget-update", elementParser: newBudgetUpdateFromDto, }); export const getAllCategories: Getter = async () => { const balances = await getAllCategoryBalances(); const budgets = await getAllCurrentCategoryBudgets(); return makeGetter({ path: "/category", elementParser: newCategoryFromDto(balances, budgets), })(); }; export const getAllCategoryBalances: Getter> = makeGetter< BalanceMap >({ path: "/balance/category", parser: newCategoryBalanceMapFromDto, }); export const getAllCurrentCategoryBudgets: Getter> = makeGetter>({ path: "/budget/category?current", parser: newBudgetMapFromDto, }); type FetcherMakerParams = { path: string; } & AnyParser; type Parser = { parser: (dto: unknown) => T | null }; type ElementParser = { elementParser: (dto: unknown) => T | null }; type AnyParser = T extends any[] ? Parser | ElementParser : Parser; type Getter = () => Promise;