src / fredClient.ts
const BASE = "https://api.stlouisfed.org/fred";
export async function fredFetch(
endpoint: string,
params: Record<string, any>,
apiKey: string
) {
const url = new URL(`${BASE}/${endpoint}`);
url.searchParams.set("api_key", apiKey);
url.searchParams.set("file_type", "json");
for (const [k, v] of Object.entries(params)) {
if (v === undefined || v === null || v === "") continue;
url.searchParams.set(k, String(v));
}
const res = await fetch(url.toString());
if (!res.ok) {
const txt = await res.text();
throw new Error(`FRED ${res.status}: ${txt.slice(0, 500)}`);
}
return res.json();
}
// small helper to prune empty keys
export function clean<T extends Record<string, any>>(o: T): Partial<T> {
const r: any = {};
for (const [k, v] of Object.entries(o)) if (v !== undefined && v !== null && v !== "") r[k] = v;
return r;
}
src / fredClient.ts
const BASE = "https://api.stlouisfed.org/fred";
export async function fredFetch(
endpoint: string,
params: Record<string, any>,
apiKey: string
) {
const url = new URL(`${BASE}/${endpoint}`);
url.searchParams.set("api_key", apiKey);
url.searchParams.set("file_type", "json");
for (const [k, v] of Object.entries(params)) {
if (v === undefined || v === null || v === "") continue;
url.searchParams.set(k, String(v));
}
const res = await fetch(url.toString());
if (!res.ok) {
const txt = await res.text();
throw new Error(`FRED ${res.status}: ${txt.slice(0, 500)}`);
}
return res.json();
}
// small helper to prune empty keys
export function clean<T extends Record<string, any>>(o: T): Partial<T> {
const r: any = {};
for (const [k, v] of Object.entries(o)) if (v !== undefined && v !== null && v !== "") r[k] = v;
return r;
}