import { NextResponse, type NextRequest } from "next/server"; import { getLocalContext, type LocalContext } from "@/lib/weather/extras/air-quality"; import { getNwsAlerts } from "@/lib/weather/extras/nws-alerts"; import { isProviderId, isReady, PROVIDERS } from "@/lib/weather/providers"; import { badRequest, errorResponse, forbidCrossSite, parseCoords } from "@/lib/weather/respond"; import type { WeatherAlert, WeatherReport } from "@/lib/weather/types"; /** * GET /api/weather?provider=openweather&lat=44.77&lon=-93.27 * * Runs on the server so API keys stay in .env / .env.local and never reach the browser. * * Three things are fetched at once: * 1. the forecast from the chosen provider (required — failure is an error) * 2. air quality + time zone from Open-Meteo (optional — failure just hides it) * 3. NWS alerts for US locations (optional — failure just hides them) */ export async function GET(request: NextRequest) { const blocked = forbidCrossSite(request); if (blocked) return blocked; const params = request.nextUrl.searchParams; const providerId = params.get("provider") ?? "openweather"; const coords = parseCoords(params); if (!isProviderId(providerId)) return badRequest(`Unknown provider "${providerId}"`); if (!coords) return badRequest("lat and lon are required"); const provider = PROVIDERS[providerId]; if (!isReady(provider)) return badRequest(`${provider.label} has no API key configured`); const [forecast, context, nwsAlerts] = await Promise.allSettled([ provider.getForecast(coords.lat, coords.lon), getLocalContext(coords.lat, coords.lon), getNwsAlerts(coords.lat, coords.lon), ]); if (forecast.status === "rejected") return errorResponse(forecast.reason); const local: LocalContext | null = context.status === "fulfilled" ? context.value : null; const official: WeatherAlert[] = nwsAlerts.status === "fulfilled" ? nwsAlerts.value : []; // Prefer official NWS alerts in the US; elsewhere use whatever the provider gave us. const alerts = official.length > 0 ? official : forecast.value.alerts; const alertSource = official.length > 0 ? "National Weather Service" : alerts.length > 0 ? provider.label : null; const report: WeatherReport = { ...forecast.value, provider: providerId, timeZone: forecast.value.timeZone ?? local?.timeZone ?? null, airQuality: local?.airQuality ?? null, alerts, alertSource, fetchedAt: new Date().toISOString(), }; return NextResponse.json(report); }