26 lines
1 KiB
TypeScript
26 lines
1 KiB
TypeScript
|
|
import type { Place, ProviderId, ProviderInfo, WeatherReport } from "./weather/types";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Browser-side calls to our own API routes.
|
||
|
|
* Each throws an Error carrying the server's message, ready to show in the UI.
|
||
|
|
*/
|
||
|
|
|
||
|
|
async function getJson<T>(url: string, signal?: AbortSignal): Promise<T> {
|
||
|
|
const response = await fetch(url, { signal });
|
||
|
|
const body = await response.json().catch(() => ({}));
|
||
|
|
if (!response.ok) {
|
||
|
|
throw new Error(body.error ?? `Request failed (HTTP ${response.status})`);
|
||
|
|
}
|
||
|
|
return body as T;
|
||
|
|
}
|
||
|
|
|
||
|
|
export const fetchProviders = () => getJson<ProviderInfo[]>("/api/providers");
|
||
|
|
|
||
|
|
export const searchPlaces = (query: string, signal?: AbortSignal) =>
|
||
|
|
getJson<Place[]>(`/api/geocode?q=${encodeURIComponent(query)}`, signal);
|
||
|
|
|
||
|
|
export const namePlace = (lat: number, lon: number) => getJson<Place>(`/api/geocode?lat=${lat}&lon=${lon}`);
|
||
|
|
|
||
|
|
export const fetchWeather = (provider: ProviderId, place: Place, signal?: AbortSignal) =>
|
||
|
|
getJson<WeatherReport>(`/api/weather?provider=${provider}&lat=${place.lat}&lon=${place.lon}`, signal);
|