feat: build production-ready wtr weather PWA
This commit is contained in:
57
lib/imgw-api.ts
Normal file
57
lib/imgw-api.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import {
|
||||
normalizeHydroStation,
|
||||
normalizeSynopStation,
|
||||
normalizeWarning,
|
||||
} from "@/lib/weather-utils";
|
||||
import type {
|
||||
HydroStation,
|
||||
RawHydroStation,
|
||||
RawSynopStation,
|
||||
RawWarning,
|
||||
SynopStation,
|
||||
WeatherWarning,
|
||||
WarningKind,
|
||||
} from "@/types/imgw";
|
||||
|
||||
async function getJson<T>(path: string, signal?: AbortSignal): Promise<T> {
|
||||
const response = await fetch(`/api/imgw/${path}`, { signal });
|
||||
if (!response.ok) {
|
||||
const details = await response.text().catch(() => "");
|
||||
throw new Error(details || `IMGW API zwróciło status ${response.status}.`);
|
||||
}
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
|
||||
export async function fetchSynopStations(signal?: AbortSignal): Promise<SynopStation[]> {
|
||||
const rows = await getJson<RawSynopStation[]>("synop", signal);
|
||||
return rows.map(normalizeSynopStation).filter((station): station is SynopStation => station !== null);
|
||||
}
|
||||
|
||||
export async function fetchSynopStation(id: string, signal?: AbortSignal): Promise<SynopStation> {
|
||||
const row = await getJson<RawSynopStation>(`synop/id/${encodeURIComponent(id)}`, signal);
|
||||
const station = normalizeSynopStation(row);
|
||||
if (!station) throw new Error("IMGW zwróciło niekompletne dane stacji.");
|
||||
return station;
|
||||
}
|
||||
|
||||
export async function fetchHydroStations(signal?: AbortSignal): Promise<HydroStation[]> {
|
||||
const rows = await getJson<RawHydroStation[]>("hydro", signal);
|
||||
return rows.map(normalizeHydroStation).filter((station): station is HydroStation => station !== null);
|
||||
}
|
||||
|
||||
async function fetchWarningsByKind(kind: WarningKind, signal?: AbortSignal): Promise<WeatherWarning[]> {
|
||||
const rows = await getJson<RawWarning[]>(kind === "meteo" ? "warningsmeteo" : "warningshydro", signal);
|
||||
return Array.isArray(rows) ? rows.map((warning, index) => normalizeWarning(warning, kind, index)) : [];
|
||||
}
|
||||
|
||||
export async function fetchWarnings(signal?: AbortSignal): Promise<WeatherWarning[]> {
|
||||
const results = await Promise.allSettled([
|
||||
fetchWarningsByKind("meteo", signal),
|
||||
fetchWarningsByKind("hydro", signal),
|
||||
]);
|
||||
const warnings = results.flatMap((result) => result.status === "fulfilled" ? result.value : []);
|
||||
if (results.every((result) => result.status === "rejected")) {
|
||||
throw new Error("Nie udało się pobrać ostrzeżeń IMGW.");
|
||||
}
|
||||
return warnings.sort((a, b) => (b.publishedAt ?? "").localeCompare(a.publishedAt ?? ""));
|
||||
}
|
||||
Reference in New Issue
Block a user