/** * Service for fetching Google Weather API (`weather.googleapis.com`) * public-alerts data — the **optional keyed global fallback** for the * "elsewhere" branch of `get_alerts`. * * `get_alerts` routes by country: US → NOAA, Canada → ECCC via MSC GeoMet, * 38 MeteoAlarm countries → MeteoAlarm, India / the Philippines / Indonesia → * their national CAP feeds, and Japan → JMA's own disaster-prevention XML * feed. **This service is only ever reached * from the final "elsewhere" branch — none of those keyless authorities ever * contacts Google, key or no key.** See * `.devdocs/archive/completed/global-alerts-fallback-plan.md` D1/D2. Without a * `GOOGLE_WEATHER_API_KEY`, the elsewhere branch stays byte-identical to * today's not-covered message; this service never runs unkeyed. * * **Security: the key lives in the URL (query string).** Error mapping below * never logs or throws the request URL, and never interpolates the raw axios * error message/object into a thrown message or a log call — every thrown * error is a fixed, pre-written string (the `firms.ts`/`googlePollen.ts` * fixed-message-per-bucket style), so the key can never leak through a log * line or an error surfaced to a caller. Logs carry only `{ status, code }`; * coordinates in log metadata go through `redactCoordinatesForLogging`. */ import type { GoogleWeatherAlert } from '../types/googleWeather.js'; /** * Thrown when the Google Weather API rejects the configured * `GOOGLE_WEATHER_API_KEY` (HTTP 400/403 with a key-rejection marker in the * response body — see `mapPublicAlertsError`). Deliberately carries a fixed, * sanitized message — never the key or the request URL — so callers (the * alerts handler) can catch this specific case and surface an actionable, * misconfiguration-only note without ever touching the rejected key again. * * Not `ApiError` — `ApiServiceName` (`src/errors/ApiError.ts`) is a closed * union and this service deliberately stays outside it, mirroring * `FIRMSKeyRejectedError` and `GooglePollenKeyRejectedError`. */ export declare class GoogleWeatherKeyRejectedError extends Error { constructor(); } export interface GoogleWeatherServiceConfig { timeout?: number; /** Overrides the `GOOGLE_WEATHER_API_KEY` env var — primarily for tests. */ apiKey?: string; } /** * The result of a public-alerts lookup. * * `alerts` alone cannot answer the caller's question, because an empty array * has **two live-verified causes that mean opposite things**: a covered region * with nothing active (HTTP 200) and a region Google does not cover at all * (HTTP 404 `NOT_FOUND`). Collapsing both into `[]` forced the renderer to * print one message for both, so an uncovered location read as a green * all-clear — a reassurance nobody had actually established, on safety data. * `covered` carries the distinction the transport already knows. */ export interface PublicAlertsResult { /** Active alerts. Empty when none are active *or* the region is uncovered. */ alerts: GoogleWeatherAlert[]; /** * `false` only for the uncovered-region 404. An empty `alerts` with * `covered: false` means **unknown**, not "all clear". */ covered: boolean; } export declare class GoogleWeatherService { private client; private cache; private readonly apiKey; constructor(config?: GoogleWeatherServiceConfig); /** * Get cache statistics */ getCacheStats(): import("../utils/cache.js").CacheStats; /** * Clear the cache */ clearCache(): void; /** * True when a non-empty Google Weather API key is configured. */ isKeyAvailable(): boolean; /** * Active public weather alerts for a location. * * Two distinct no-data answers both resolve to an empty `alerts` array, and * both are cached so neither is re-probed for the TTL (**live-verified * 2026-08-18**) — but they are told apart by `covered`: * - a covered region with nothing active → HTTP 200, `weatherAlerts: []` * → `{ alerts: [], covered: true }`; * - a region Google does not cover → HTTP 404 `NOT_FOUND` (not the * `regionCode`-only 200 the documentation implied) * → `{ alerts: [], covered: false }`. * **No retries.** * * @throws {GoogleWeatherKeyRejectedError} the configured key was rejected * @throws {Error} no key configured, invalid coordinates, or any other failure */ getPublicAlerts(latitude: number, longitude: number): Promise; private fetchPublicAlerts; } //# sourceMappingURL=googleWeather.d.ts.map