feat: add global weather support
All checks were successful
CI / Lint, typecheck and build (push) Successful in 9m54s

This commit is contained in:
zv
2026-06-14 15:53:34 +02:00
parent d572c9cc53
commit 2182297adc
45 changed files with 739 additions and 212 deletions

View File

@@ -8,6 +8,7 @@ import type {
RawWeatherForecast,
WeatherForecast,
} from "@/types/forecast";
import { getWeatherCapabilities, type WeatherRegion } from "@/types/weather-region";
const WARSAW_TIME_ZONE = "Europe/Warsaw";
const warsawHourFormatter = new Intl.DateTimeFormat("en-CA", {
@@ -96,17 +97,20 @@ function normalizeOpenMeteoDaily(series: RawForecastSeries = {}): DailyForecast[
});
}
function normalizeOpenMeteoForecast(raw: RawWeatherForecast): WeatherForecast {
function normalizeOpenMeteoForecast(raw: RawWeatherForecast, region: WeatherRegion): WeatherForecast {
const latitude = Number(raw.latitude);
const longitude = Number(raw.longitude);
if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) throw new Error("Forecast service returned invalid coordinates.");
return {
latitude,
longitude,
region,
timezone: typeof raw.timezone === "string" ? raw.timezone : WARSAW_TIME_ZONE,
hourly: normalizeOpenMeteoHourly(raw.hourly),
daily: normalizeOpenMeteoDaily(raw.daily),
sources: ["open-meteo"],
capabilities: getWeatherCapabilities(region),
unavailableReasons: region === "GLOBAL" ? ["official-warnings"] : [],
};
}
@@ -188,8 +192,8 @@ function summarizeDay(day: DailyForecast, hours: HourlyForecast[]): DailyForecas
};
}
export function mergeForecastSources(openMeteoPayload: RawWeatherForecast, imgwPayload?: RawImgwForecastResponse | null): WeatherForecast {
const openMeteoForecast = normalizeOpenMeteoForecast(openMeteoPayload);
export function mergeForecastSources(openMeteoPayload: RawWeatherForecast, imgwPayload?: RawImgwForecastResponse | null, region: WeatherRegion = "PL"): WeatherForecast {
const openMeteoForecast = normalizeOpenMeteoForecast(openMeteoPayload, region);
const imgwHours = normalizeImgwHourly(imgwPayload);
let hasImgwHours = false;
const hourly = openMeteoForecast.hourly.map((hour) => {