@dangahagan/weather-mcp 1.23.0 → 1.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +60 -12
  2. package/dist/config/api.d.ts +2 -1
  3. package/dist/config/api.d.ts.map +1 -1
  4. package/dist/config/api.js +2 -1
  5. package/dist/config/api.js.map +1 -1
  6. package/dist/config/cache.d.ts +1 -0
  7. package/dist/config/cache.d.ts.map +1 -1
  8. package/dist/config/cache.js +6 -0
  9. package/dist/config/cache.js.map +1 -1
  10. package/dist/config/displayThresholds.d.ts +16 -0
  11. package/dist/config/displayThresholds.d.ts.map +1 -1
  12. package/dist/config/displayThresholds.js +16 -0
  13. package/dist/config/displayThresholds.js.map +1 -1
  14. package/dist/errors/ApiError.d.ts +61 -0
  15. package/dist/errors/ApiError.d.ts.map +1 -1
  16. package/dist/errors/ApiError.js +77 -0
  17. package/dist/errors/ApiError.js.map +1 -1
  18. package/dist/handlers/alertsHandler.d.ts +11 -7
  19. package/dist/handlers/alertsHandler.d.ts.map +1 -1
  20. package/dist/handlers/alertsHandler.js +255 -16
  21. package/dist/handlers/alertsHandler.js.map +1 -1
  22. package/dist/handlers/currentConditionsHandler.d.ts.map +1 -1
  23. package/dist/handlers/currentConditionsHandler.js +138 -4
  24. package/dist/handlers/currentConditionsHandler.js.map +1 -1
  25. package/dist/handlers/weatherSummaryHandler.d.ts +2 -1
  26. package/dist/handlers/weatherSummaryHandler.d.ts.map +1 -1
  27. package/dist/handlers/weatherSummaryHandler.js +2 -2
  28. package/dist/handlers/weatherSummaryHandler.js.map +1 -1
  29. package/dist/index.js +15 -6
  30. package/dist/index.js.map +1 -1
  31. package/dist/services/blitzortung.d.ts.map +1 -1
  32. package/dist/services/blitzortung.js +126 -3
  33. package/dist/services/blitzortung.js.map +1 -1
  34. package/dist/services/googleWeather.d.ts +5 -4
  35. package/dist/services/googleWeather.d.ts.map +1 -1
  36. package/dist/services/googleWeather.js +5 -4
  37. package/dist/services/googleWeather.js.map +1 -1
  38. package/dist/services/nationalCap.d.ts +172 -0
  39. package/dist/services/nationalCap.d.ts.map +1 -0
  40. package/dist/services/nationalCap.js +670 -0
  41. package/dist/services/nationalCap.js.map +1 -0
  42. package/dist/types/cap.d.ts +217 -0
  43. package/dist/types/cap.d.ts.map +1 -0
  44. package/dist/types/cap.js +13 -0
  45. package/dist/types/cap.js.map +1 -0
  46. package/dist/utils/capParse.d.ts +171 -0
  47. package/dist/utils/capParse.d.ts.map +1 -0
  48. package/dist/utils/capParse.js +616 -0
  49. package/dist/utils/capParse.js.map +1 -0
  50. package/dist/utils/pointInPolygon.d.ts +50 -0
  51. package/dist/utils/pointInPolygon.d.ts.map +1 -0
  52. package/dist/utils/pointInPolygon.js +135 -0
  53. package/dist/utils/pointInPolygon.js.map +1 -0
  54. package/dist/utils/thermalStress.d.ts +114 -0
  55. package/dist/utils/thermalStress.d.ts.map +1 -0
  56. package/dist/utils/thermalStress.js +186 -0
  57. package/dist/utils/thermalStress.js.map +1 -0
  58. package/dist/utils/units.d.ts +4 -0
  59. package/dist/utils/units.d.ts.map +1 -1
  60. package/dist/utils/units.js +6 -0
  61. package/dist/utils/units.js.map +1 -1
  62. package/package.json +6 -3
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  [![npm version](https://badge.fury.io/js/@dangahagan%2Fweather-mcp.svg)](https://www.npmjs.com/package/@dangahagan/weather-mcp)
4
4
  [![MCP Registry](https://img.shields.io/badge/MCP-Registry-blue)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
- [![Tests](https://img.shields.io/badge/tests-2%2C274%20passing-brightgreen)](./docs/testing/TEST_SUITE_README.md)
6
+ [![Tests](https://img.shields.io/badge/tests-2%2C520%20passing-brightgreen)](./docs/testing/TEST_SUITE_README.md)
7
7
  [![Node](https://img.shields.io/badge/node-%3E%3D18-339933?logo=node.js&logoColor=white)](https://nodejs.org)
8
8
 
9
9
  **Give your AI assistant real weather data — 17 tools, zero API keys, zero signup, zero cost.**
@@ -42,6 +42,14 @@ Then just ask:
42
42
 
43
43
  📦 Listed in the [Official MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp) as `io.github.dgahagan/weather-mcp`.
44
44
 
45
+ ✅ **The official package is [`@dangahagan/weather-mcp`](https://www.npmjs.com/package/@dangahagan/weather-mcp)**, published from this repository via npm [trusted publishing](https://docs.npmjs.com/trusted-publishers). Every release carries a signed provenance attestation tying the tarball to the exact commit and workflow that built it — verify any version without installing it:
46
+
47
+ ```bash
48
+ npm view @dangahagan/weather-mcp@latest dist.attestations
49
+ ```
50
+
51
+ Republished copies of this server exist under other npm scopes. They are MIT-licensed forks, which the license permits, but they are not maintained here and are usually many versions behind. This issue tracker covers `@dangahagan/weather-mcp` only — for anything installed from another scope, please report it to that package's publisher.
52
+
45
53
  ## Why this server?
46
54
 
47
55
  There are excellent commercial weather MCPs backed by paid APIs and full-time teams. If you need SLA-backed data, minute-level nowcasting, or premium global station coverage, they're worth a look — this project won't pretend otherwise.
@@ -50,7 +58,7 @@ Choose this one if you want:
50
58
 
51
59
  - **Genuinely free** — every data source is a free public API. No trial that expires, no credit card, no rate-limited "free tier" bait.
52
60
  - **No API keys** — install to first forecast in under a minute. Nothing to configure, nothing to leak into a repo. ([Three optional keys](#optional-api-keys) add extras if you want them; the default configuration needs none.)
53
- - **Fully open source** — MIT licensed, readable TypeScript, 2,274 tests. Audit it, fork it, fix it.
61
+ - **Fully open source** — MIT licensed, readable TypeScript, 2,520 tests. Audit it, fork it, fix it.
54
62
  - **Privacy-respecting** — your queries go directly from your machine to public weather APIs. No middleman server, no telemetry.
55
63
  - **Breadth** — 17 tools covering weather, safety hazards (lightning, floods, wildfires), marine conditions, air quality, and historical data back to 1940. Most weather MCPs stop at forecasts.
56
64
 
@@ -63,8 +71,8 @@ All 17 tools, documented in detail in **[docs/TOOLS.md](./docs/TOOLS.md)**:
63
71
  | Tool | What it does | Coverage |
64
72
  |------|-------------|----------|
65
73
  | `get_forecast` | Daily/hourly forecasts up to 16 days by coordinates, saved location, or city name; sunrise/sunset, UV, precipitation probability, optional climate-normals comparison, optional moon phase & twilight almanac, optional five-model agreement comparison | 🌍 Global |
66
- | `get_current_conditions` | Current weather: temperature, wind, humidity, pressure; NOAA station observations in the US (plus heat index/wind chill, snow depth, optional NOAA fire-weather indices), Open-Meteo model data elsewhere (with an optional computed Fosberg fire-weather index), or real airport station observations worldwide with `source="metar"`. Always states the observation's age, and automatically falls back to a fresher nearby station when the nearest one has gone dark | 🌍 Global |
67
- | `get_alerts` | Active watches, warnings, and advisories sorted by severity; official national warnings for the US (NOAA), Canada (ECCC), and 38 European countries (MeteoAlarm) | 🇺🇸 🇨🇦 🇪🇺 |
74
+ | `get_current_conditions` | Current weather: temperature, wind, humidity, pressure; NOAA station observations in the US (plus heat index/wind chill, snow depth, optional NOAA fire-weather indices), Open-Meteo model data elsewhere (with an optional computed Fosberg fire-weather index), or real airport station observations worldwide with `source="metar"`. Always states the observation's age, and automatically falls back to a fresher nearby station when the nearest one has gone dark. In extreme conditions automatically adds frostbite time-to-onset (computed wind chill) or heat-stress context (estimated WBGT) | 🌍 Global |
75
+ | `get_alerts` | Active watches, warnings, and advisories sorted by severity; official national warnings for the US (NOAA), Canada (ECCC), 38 European countries (MeteoAlarm), India (NDMA SACHET), the Philippines (PAGASA), and Indonesia (BMKG) | 🇺🇸 🇨🇦 🇪🇺 🇮🇳 🇵🇭 🇮🇩 |
68
76
  | `get_historical_weather` | Hourly/daily observations from 1940 to present | 🌍 Global |
69
77
  | `get_weather_summary` | One-call overview combining current conditions, forecast, and alerts (optionally air quality and lightning) | 🌍 Global |
70
78
  | `search_location` | Geocode place names to coordinates ("Paris" → 48.85, 2.35) | 🌍 Global |
@@ -89,7 +97,7 @@ All 17 tools, documented in detail in **[docs/TOOLS.md](./docs/TOOLS.md)**:
89
97
  ## Feature highlights
90
98
 
91
99
  - **Smart source selection** — US queries use NOAA (detailed, includes forecaster narratives); everywhere else uses Open-Meteo. You never pick; it just works.
92
- - **International weather alerts** — `get_alerts` routes by country: NOAA in the US, Environment and Climate Change Canada alerts in Canada, and the official national warnings of 38 European countries via EUMETNET MeteoAlarm — shown unmodified, with the issuing service credited. Border cities like Toronto get the right country's alerts, not the nearest bounding box's.
100
+ - **International weather alerts** — `get_alerts` routes by country: NOAA in the US, Environment and Climate Change Canada alerts in Canada, the official national warnings of 38 European countries via EUMETNET MeteoAlarm, and the national CAP feeds of India (NDMA SACHET), the Philippines (PAGASA) and Indonesia (BMKG) — shown unmodified, with the issuing service credited. Where a feed publishes geometry inline, warnings are matched to your exact point by the alert's own polygon rather than to the whole country (the Philippines and Indonesia today; Europe remains country-level). Border cities like Toronto get the right country's alerts, not the nearest bounding box's.
93
101
  - **Real observations worldwide** — ask for what a station is *actually reporting* and `get_current_conditions` will read the nearest airport's METAR (`source="metar"`): a genuine instrument reading anywhere on earth, with the station, its distance, and the observation age always stated. Outside the US this is the difference between a measurement and a model estimate.
94
102
  - **Model agreement** — ask *"how confident is this forecast?"* and `compare_models=true` compares five global models (GFS, ECMWF, ICON, GEM, UKMO) in one request, summarizing where they agree and where they split rather than dumping five forecasts. Spread across models is a proxy for uncertainty, not a guarantee — a tight spread can still be wrong, and the output says so.
95
103
  - **Ensemble spread** — the sibling question: *"how confident is the model itself?"* `ensemble_spread=true` summarizes ECMWF ENS's 50 perturbed members — per-day High/Moderate/Low confidence, interquartile temperature bands, and how many members produce rain — instead of one deterministic forecast. Member fractions are raw model output, **not calibrated probabilities**: a confident ensemble can still be wrong, and the output says so. Mutually exclusive with `compare_models`; the two answer different questions.
@@ -115,6 +123,9 @@ All free, all public, no authentication required:
115
123
  | [RCC ACIS](https://www.rcc-acis.org/) | Daily record high/low temperatures | US |
116
124
  | [EUMETNET MeteoAlarm](https://meteoalarm.org/) | Official national weather warnings (38 European countries) | Europe |
117
125
  | [MSC GeoMet](https://api.weather.gc.ca/) | Environment and Climate Change Canada weather alerts | Canada |
126
+ | [NDMA SACHET](https://sachet.ndma.gov.in/) | Official Indian warnings (CAP, polygon geometry) — public domain | India |
127
+ | [PAGASA](https://publicalert.pagasa.dost.gov.ph/) | Official Philippine warnings (CAP, inline polygons) — CC BY 4.0 | Philippines |
128
+ | [BMKG](https://www.bmkg.go.id/) | Official Indonesian nowcast warnings (CAP, inline polygons) — attribution required | Indonesia |
118
129
  | [NIFC WFIGS](https://data-nifc.opendata.arcgis.com/) | Active wildfire perimeters and incidents | US |
119
130
  | [NASA FIRMS](https://firms.modaps.eosdis.nasa.gov/) | Satellite fire detections (VIIRS, near real-time) | Global |
120
131
  | [RainViewer](https://www.rainviewer.com/api.html) | Precipitation radar imagery | Global |
@@ -166,7 +177,7 @@ npm run build
166
177
 
167
178
  Then point your MCP client at `node /absolute/path/to/weather-mcp/dist/index.js`.
168
179
 
169
- Requires Node.js 18+. No API keys, tokens, or accounts needed — see [Optional API keys](#optional-api-keys) for the three that add optional extras.
180
+ Requires Node.js 18+. No API keys, tokens, or accounts needed — see [Optional API keys](#optional-api-keys) for the three that add optional extras, and [Optional dependency](#optional-dependency) if you want a smaller install.
170
181
 
171
182
  ### Works with
172
183
 
@@ -256,7 +267,7 @@ Supported on `get_forecast`, `get_current_conditions`, and `get_historical_weath
256
267
  | `NCEI_API_TOKEN` | — | Optional [free NCEI token](https://www.ncdc.noaa.gov/cdo-web/token) for official NOAA climate normals (US); falls back to Open-Meteo automatically. See [Optional API keys](#optional-api-keys) |
257
268
  | `FIRMS_MAP_KEY` | — | Optional [free FIRMS key](https://firms.modaps.eosdis.nasa.gov/api/map_key/) for targeted wildfire queries and up to 5 days of detection history. See [Optional API keys](#optional-api-keys) |
258
269
  | `GOOGLE_POLLEN_API_KEY` | — | Optional key for pollen outside Europe (incl. the US). **Requires a Google Cloud billing account** — free tier is 5,000 lookups/month. See [Optional API keys](#optional-api-keys) and [the setup guide](./docs/GOOGLE_POLLEN_KEY_SETUP.md) |
259
- | `GOOGLE_WEATHER_API_KEY` | — | Optional key for official weather alerts beyond the US, Canada, and Europe (~45+ more territories). **Requires a Google Cloud billing account.** See [Optional API keys](#optional-api-keys) and [the setup guide](./docs/GOOGLE_WEATHER_KEY_SETUP.md) |
270
+ | `GOOGLE_WEATHER_API_KEY` | — | Optional key for official weather alerts beyond the US, Canada, Europe, India, the Philippines, and Indonesia (~45+ more territories). **Requires a Google Cloud billing account.** See [Optional API keys](#optional-api-keys) and [the setup guide](./docs/GOOGLE_WEATHER_KEY_SETUP.md) |
260
271
 
261
272
  For caching architecture details, see [.github/CACHING.md](./.github/CACHING.md).
262
273
 
@@ -275,7 +286,7 @@ still works; it just returns the keyless answer.
275
286
  | [`NCEI_API_TOKEN`](https://www.ncdc.noaa.gov/cdo-web/token) | Free registration (email) | Official NOAA station climate normals for US locations | Normals are computed from the Open-Meteo reanalysis archive — global, and the path virtually every user is already on |
276
287
  | [`FIRMS_MAP_KEY`](https://firms.modaps.eosdis.nasa.gov/api/map_key/) | Free registration (email) | Targeted wildfire bbox queries with 1–5 days of detection history | Keyless 24-hour regional detection files — `get_wildfire_info` still works globally |
277
288
  | `GOOGLE_POLLEN_API_KEY` | **Free tier, but requires a Google Cloud billing account (credit card on file)** — 5,000 lookups/month free, ~$10/1,000 after. [Setup guide](./docs/GOOGLE_POLLEN_KEY_SETUP.md) | Grass/tree/weed Universal Pollen Index outside Europe, including the US (65+ countries) | European pollen via CAMS still works keyless; elsewhere no pollen section renders |
278
- | `GOOGLE_WEATHER_API_KEY` | **Free tier, but requires a Google Cloud billing account (credit card on file)** — the Weather API bills under a Maps Platform Essentials SKU; check Google's current allowance. [Setup guide](./docs/GOOGLE_WEATHER_KEY_SETUP.md) | Official weather alerts for ~45+ more territories — Australia, Japan, Brazil, Mexico and others ([Google's coverage list](https://developers.google.com/maps/documentation/weather/coverage) is authoritative) | US, Canadian, and European alerts still work keyless; elsewhere `get_alerts` returns today's not-covered message |
289
+ | `GOOGLE_WEATHER_API_KEY` | **Free tier, but requires a Google Cloud billing account (credit card on file)** — the Weather API bills under a Maps Platform Essentials SKU; check Google's current allowance. [Setup guide](./docs/GOOGLE_WEATHER_KEY_SETUP.md) | Official weather alerts for ~45+ more territories — Australia, Japan, Brazil, Mexico and others ([Google's coverage list](https://developers.google.com/maps/documentation/weather/coverage) is authoritative) | US, Canadian, European, Indian, Philippine, and Indonesian alerts still work keyless; elsewhere `get_alerts` returns today's not-covered message |
279
290
 
280
291
  The NCEI and FIRMS keys are true free registrations. **The two Google keys are
281
292
  not** — each has a free usage tier, but Google requires a billing account with
@@ -297,6 +308,41 @@ three rules:
297
308
  3. **Features that would require a *paid* key are out of scope** unless there's
298
309
  significant user demand for that specific service.
299
310
 
311
+ ## Optional dependency
312
+
313
+ Everything above installs by default and nothing here needs configuring — this section only
314
+ matters if you want a smaller install.
315
+
316
+ One dependency, `mqtt`, exists for a single tool: `get_lightning_activity` streams live strikes
317
+ from Blitzortung.org over MQTT, and nothing else in the server uses that transport. It is declared
318
+ as an `optionalDependency`, so a normal install still includes it and lightning works exactly as
319
+ described above. You can decline it:
320
+
321
+ ```bash
322
+ npm install -g @dangahagan/weather-mcp --omit=optional
323
+ ```
324
+
325
+ That installs **121 packages instead of 163** — 42 fewer, `mqtt` and its transitive tree.
326
+
327
+ **What you give up**, on both paths that reach lightning:
328
+
329
+ - `get_lightning_activity` returns an error naming the package and how to get it back, rather than
330
+ a result. It never reports "no strikes" — a missing dependency rendering as an all-clear on
331
+ lightning is precisely the kind of confidently wrong safety answer this project treats as its
332
+ worst failure.
333
+ - `get_weather_summary` still works, but its optional `lightning` section renders as
334
+ `## lightning (unavailable)` with the same message. Every other section is unaffected.
335
+
336
+ Nothing else changes: all 16 remaining tools behave identically, and `get_lightning_activity` still
337
+ appears in `tools/list`.
338
+
339
+ To get lightning back, reinstall without the flag.
340
+
341
+ > **Source builds still use a plain `npm install`.** TypeScript needs `mqtt`'s bundled type
342
+ > declarations at build time even though the emitted server loads the package only when lightning
343
+ > is actually requested, so `--omit=optional` belongs to the published package, not to a build from
344
+ > a clone.
345
+
300
346
  ## Coverage & Limitations
301
347
 
302
348
  Being honest about what free public data can and can't do:
@@ -307,17 +353,19 @@ Being honest about what free public data can and can't do:
307
353
  | Historical weather (1940+) | ✅ (>7 days old) | Station-level detail for last 7 days |
308
354
  | Air quality, marine, radar, lightning | ✅ | — |
309
355
  | Current conditions | ✅ (model data, or real station observations via `source="metar"`) | Station observations via NOAA (richer detail) |
310
- | Weather alerts | ✅ US, Canada, and 38 European countries keyless; ~45+ more territories with an optional key | NWS zone-level precision; Europe is matched at country level |
356
+ | Weather alerts | ✅ US, Canada, 38 European countries, India, the Philippines, and Indonesia keyless; ~45+ more territories with an optional key | NWS zone-level precision; Europe and India country-level; Philippines and Indonesia polygon-level |
311
357
  | River conditions | ✅ (GloFAS modeled discharge) | Gauge observations + official flood stages via NWPS |
312
358
  | Wildfires | ✅ (FIRMS satellite detections) | Named incidents with acreage + containment via NIFC |
313
359
  | Fire weather | ✅ (computed Fosberg index + dryness context) | NOAA-published Haines, grassland, red-flag indices |
314
360
  | Pollen | 🇪🇺 Europe keyless (CAMS, grains/m³); elsewhere needs an optional key | Universal Pollen Index with `GOOGLE_POLLEN_API_KEY` |
315
361
 
316
362
  - European alerts are matched at **country level** — the keyless MeteoAlarm feeds carry no region polygons, so warnings for a large country may not affect the requested point; the output says so. Canadian alerts use a real bbox query with polygon-backed features.
317
- - Outside the US, Canada, and Europe, alerts need an optional [`GOOGLE_WEATHER_API_KEY`](#optional-api-keys); without one `get_alerts` says plainly that the region isn't covered rather than guessing. With a key, Google aggregates official national feeds for roughly 45 more territoriesAustralia, Japan, Brazil and Mexico among them, with [Google's coverage page](https://developers.google.com/maps/documentation/weather/coverage) as the authoritative list. Matching is by **provider polygon**, so coverage alignment may not be exact and an empty answer means "no alerts found", not a guarantee of coverage; the output says so both ways. Alert text appears in the publisher's source language. **The US, Canada, and Europe never contact Google** those authorities stay first choice, key or no key and a key failure surfaces loudly rather than degrading to a possibly-false all-clear.
363
+ - **Philippine and Indonesian alerts are matched by the alert's own polygon**, so a warning is shown only when it actually covers the requested pointfiner than Europe's country-level matching. **Indian alerts are currently country-level**: SACHET publishes each alert's geometry from a separate endpoint that is not reliably reachable from servers, so Indian warnings are listed with an explicit note that they may not affect your exact location, exactly as Europe's are. Any alert whose geometry cannot be loaded is always listed rather than droppednever silently treated as "not near you".
364
+ - Outside the US, Canada, Europe, India, the Philippines, and Indonesia, alerts need an optional [`GOOGLE_WEATHER_API_KEY`](#optional-api-keys); without one `get_alerts` says plainly that the region isn't covered rather than guessing. With a key, Google aggregates official national feeds for roughly 45 more territories — Australia, Japan, Brazil and Mexico among them, with [Google's coverage page](https://developers.google.com/maps/documentation/weather/coverage) as the authoritative list. Matching is by **provider polygon**, so coverage alignment may not be exact and an empty answer means "no alerts found", not a guarantee of coverage; the output says so both ways. Alert text appears in the publisher's source language. **The US, Canada, Europe, India, the Philippines, and Indonesia never contact Google** — those authorities stay first choice, key or no key — and a key failure surfaces loudly rather than degrading to a possibly-false all-clear.
318
365
  - International current conditions default to **model-interpolated** values at the exact coordinates. `source="metar"` returns a **real instrument reading** instead — but from the nearest airport, which may be tens of km away and up to an hour old. The output always names the station, its distance and bearing, and the observation age, so the tradeoff is visible rather than assumed. METAR coverage follows airports, so remote land and open ocean have real gaps.
319
366
  - Historical data older than 7 days comes from reanalysis models (9–25km grid), not direct station observations, and trails real time by ~5 days.
320
367
  - Non-US wildfire results are **satellite heat detections, not managed incidents** — no fire names, sizes, or containment percentages exist in the data, detections can include industrial heat sources or agricultural burns, and a clear result is not an all-clear (cloud cover hides fires; small or new fires evade detection). The output frames all of this explicitly. Keyless data covers the last 24 hours; an optional free [`FIRMS_MAP_KEY`](https://firms.modaps.eosdis.nasa.gov/api/map_key/) unlocks targeted queries and up to 5 days of detection history (`day_range`).
368
+ - Frostbite-risk and heat-stress (WBGT) lines are **computed by this server** from temperature, humidity, and wind — not agency-published ratings. The wind chill is the standard 2001 North American model; the frostbite time bands are adapted from Environment Canada's published categories and the WBGT is the Australian Bureau of Meteorology's *simplified* estimate, which assumes full sun and light wind and so can overestimate in shade or overcast. Exertion thresholds also genuinely shift with acclimatization. Treat both as context, not as an occupational-safety determination.
321
369
  - Non-US fire weather is a **Fosberg Fire Weather Index computed by this server** from current model values, not an agency-published rating — US locations get NOAA's own Haines/grassland/red-flag indices instead. The output says which it is and defers to national fire authorities; its category bands are a project heuristic.
322
370
  - Non-US river discharge is **modeled**, not observed, and has no official flood-stage thresholds — levels are shown relative to recent history and the forecast ensemble. The ~5km model grid means the reported channel may be a few km from the requested point; the output says so when it is.
323
371
  - Pollen is **Europe-only without a key**: it rides the CAMS European model on the air-quality endpoint, which returns real grains/m³ in Europe and nothing anywhere else. An optional [`GOOGLE_POLLEN_API_KEY`](#optional-api-keys) fills the gap for 65+ countries including the US, as a grass/tree/weed Universal Pollen Index (0–5) rather than per-species counts. Europe keeps the richer keyless data and never contacts Google.
@@ -330,7 +378,7 @@ Being honest about what free public data can and can't do:
330
378
  ```bash
331
379
  npm run build # Compile TypeScript
332
380
  npm run dev # Run in development mode
333
- npm test # Run all 2,274 tests
381
+ npm test # Run all 2,520 tests
334
382
  npm run test:coverage # Coverage report
335
383
  npm run audit # Dependency vulnerability scan
336
384
  ```
@@ -348,7 +396,7 @@ Project structure, patterns, and contribution guidance:
348
396
  - Error messages sanitized — no internal details leak to output
349
397
  - Zero secrets by design: no keys means nothing to steal or misconfigure
350
398
  - Automated dependency scanning (npm audit + Dependabot), minimal dependency footprint
351
- - Independent security audit: see [docs/development/SECURITY_AUDIT.md](./docs/development/SECURITY_AUDIT.md)
399
+ - Security policy and supported versions: see [SECURITY.md](./SECURITY.md)
352
400
 
353
401
  To report a vulnerability, see [SECURITY.md](./SECURITY.md).
354
402
 
@@ -91,7 +91,8 @@ export declare function isGooglePollenKeyAvailable(): boolean;
91
91
  * Brazil, Mexico, and others) via the Google Weather API
92
92
  *
93
93
  * If not provided:
94
- * - US, Canadian, and European alerts continue to work keyless
94
+ * - US, Canadian, European, Indian, Philippine, and Indonesian alerts
95
+ * continue to work keyless
95
96
  * - Alerts outside these regions are unavailable
96
97
  * - No setup required
97
98
  *
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/config/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,oBAA6B,CAAC;AAEzD;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,oBAA4B,CAAC;AAEvD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,qBAAqB,oBAAoC,CAAC;AAEvE;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,sBAAsB,oBAAqC,CAAC;AAEzE;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAErD"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/config/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,oBAA6B,CAAC;AAEzD;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,oBAA4B,CAAC;AAEvD;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,qBAAqB,oBAAoC,CAAC;AAEvE;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,sBAAsB,oBAAqC,CAAC;AAEzE;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAErD"}
@@ -97,7 +97,8 @@ export function isGooglePollenKeyAvailable() {
97
97
  * Brazil, Mexico, and others) via the Google Weather API
98
98
  *
99
99
  * If not provided:
100
- * - US, Canadian, and European alerts continue to work keyless
100
+ * - US, Canadian, European, Indian, Philippine, and Indonesian alerts
101
+ * continue to work keyless
101
102
  * - Alerts outside these regions are unavailable
102
103
  * - No setup required
103
104
  *
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/config/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAEzD;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,CAAC,cAAc,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AAEvD;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,CAAC,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;AAEvE;;GAEG;AACH,MAAM,UAAU,0BAA0B;IACxC,OAAO,CAAC,CAAC,qBAAqB,IAAI,qBAAqB,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;AAEzE;;GAEG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,CAAC,CAAC,sBAAsB,IAAI,sBAAsB,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9E,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/config/api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;AAEzD;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,CAAC,CAAC,cAAc,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AAEvD;;GAEG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,CAAC,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;AAEvE;;GAEG;AACH,MAAM,UAAU,0BAA0B;IACxC,OAAO,CAAC,CAAC,qBAAqB,IAAI,qBAAqB,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;AAEzE;;GAEG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,CAAC,CAAC,sBAAsB,IAAI,sBAAsB,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9E,CAAC"}
@@ -32,6 +32,7 @@ export declare const CacheConfig: {
32
32
  readonly reverseCountry: number;
33
33
  readonly firmsAreaQuery: number;
34
34
  readonly firmsRegionalFile: number;
35
+ readonly capDocument: number;
35
36
  };
36
37
  };
37
38
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkDH,eAAO,MAAM,WAAW;aAEtB,OAAO;aAIP,OAAO;aAIP,YAAY;aAGZ,GAAG;iBAGD,eAAe;iBAIf,SAAS;iBAIT,QAAQ;iBAIR,QAAQ;iBAIR,iBAAiB;iBAIjB,MAAM;iBAIN,gBAAgB;iBAIhB,cAAc;iBAKd,OAAO;iBAIP,aAAa;iBAMb,cAAc;iBAMd,YAAY;iBAMZ,OAAO;iBAIP,cAAc;iBAMd,iBAAiB;iBAQjB,YAAY;iBAQZ,cAAc;iBAKd,cAAc;iBAKd,cAAc;iBAKd,iBAAiB;;CAEX,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYrE"}
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkDH,eAAO,MAAM,WAAW;aAEtB,OAAO;aAIP,OAAO;aAIP,YAAY;aAGZ,GAAG;iBAGD,eAAe;iBAIf,SAAS;iBAIT,QAAQ;iBAIR,QAAQ;iBAIR,iBAAiB;iBAIjB,MAAM;iBAIN,gBAAgB;iBAIhB,cAAc;iBAKd,OAAO;iBAIP,aAAa;iBAMb,cAAc;iBAMd,YAAY;iBAMZ,OAAO;iBAIP,cAAc;iBAMd,iBAAiB;iBAQjB,YAAY;iBAQZ,cAAc;iBAKd,cAAc;iBAKd,cAAc;iBAKd,iBAAiB;iBAOjB,WAAW;;CAEL,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYrE"}
@@ -141,6 +141,12 @@ export const CacheConfig = {
141
141
  // rows per region file (not per request), so repeated queries anywhere
142
142
  // in a region cost one fetch per half hour.
143
143
  firmsRegionalFile: 30 * MINUTE,
144
+ // National CAP documents and polygon documents, keyed on (index identifier,
145
+ // index published stamp). SACHET re-serves a thread's latest version under
146
+ // one GUID; the stamp (not the identifier) makes the key immutable. A named
147
+ // 24h entry rather than Infinity so a long-running server's LRU is not
148
+ // pinned with dead alerts.
149
+ capDocument: 24 * HOUR,
144
150
  },
145
151
  };
146
152
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"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"}
@@ -91,6 +91,22 @@ export declare const DisplayThresholds: {
91
91
  readonly mm: 0.05;
92
92
  };
93
93
  };
94
+ /**
95
+ * Thermal stress thresholds
96
+ */
97
+ readonly thermalStress: {
98
+ /**
99
+ * Display gates only. The band boundaries themselves live in
100
+ * `src/utils/thermalStress.ts` (where Fosberg's live), and those functions
101
+ * return null below their own lowest band — so *raising* a gate here
102
+ * suppresses lines as expected, while *lowering* one past the pure
103
+ * module's floor has no effect until that floor moves too.
104
+ */
105
+ /** Render the frostbite line when effective wind chill (°F) is at or below this */
106
+ readonly showFrostbiteAtWindChillF: -18;
107
+ /** Compute/render WBGT only when air temp (°F) is at or above showHeatIndex and rounded WBGT (°F) is at or above this */
108
+ readonly showWbgtF: 80;
109
+ };
94
110
  };
95
111
  /**
96
112
  * API-related constants
@@ -1 +1 @@
1
- {"version":3,"file":"displayThresholds.d.ts","sourceRoot":"","sources":["../../src/config/displayThresholds.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,iBAAiB;IAC5B;;OAEG;aACH,WAAW;QACT,2DAA2D;iBAC3D,aAAa,EAAE,EAAE;QACjB,2DAA2D;iBAC3D,aAAa,EAAE,EAAE;QACjB;;;;;;WAMG;iBACH,YAAY;qBACV,CAAC,EAAE,CAAC;qBACJ,CAAC,EAAE,CAAC;;;IAIR;;OAEG;aACH,IAAI;QACF,4FAA4F;iBAC5F,qBAAqB,EAAE,GAAG;;IAG5B;;OAEG;aACH,UAAU;QACR,gBAAgB;iBAChB,QAAQ,EAAE,IAAI;QACd,UAAU;iBACV,GAAG,EAAE,CAAG;QACR,mBAAmB;iBACnB,QAAQ,EAAE,CAAG;QACb,uBAAuB;iBACvB,KAAK,EAAE,EAAI;;IAGb;;OAEG;aACH,iBAAiB;QACf;;;;WAIG;iBACH,mBAAmB,EAAE,GAAG;QACxB;;;;WAIG;iBACH,sBAAsB,EAAE,GAAG;QAC3B;;;WAGG;iBACH,kBAAkB,EAAE,CAAC;;IAGvB;;OAEG;aACH,aAAa;QACX,4CAA4C;iBAC5C,KAAK,EAAE,GAAG;QACV,+CAA+C;iBAC/C,QAAQ,EAAE,GAAG;QACb,4CAA4C;iBAC5C,KAAK,EAAE,GAAG;QACV;;;;;;;;;WASG;iBACH,UAAU;qBACR,IAAI,EAAE,KAAK;qBACX,EAAE,EAAE,IAAI;;;CAGJ,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB;;;OAGG;aACH,2BAA2B,EAAE,CAAC;IAE9B;;OAEG;aACH,uBAAuB,EAAE,EAAE;CACnB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;aACH,mBAAmB,EAAE,CAAC;IAEtB;;OAEG;aACH,eAAe,EAAE,EAAE;IAEnB;;OAEG;aACH,sBAAsB,EAAE,GAAG;IAE3B;;;;;OAKG;aACH,kBAAkB,EAAE,GAAG;CACf,CAAC"}
1
+ {"version":3,"file":"displayThresholds.d.ts","sourceRoot":"","sources":["../../src/config/displayThresholds.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,iBAAiB;IAC5B;;OAEG;aACH,WAAW;QACT,2DAA2D;iBAC3D,aAAa,EAAE,EAAE;QACjB,2DAA2D;iBAC3D,aAAa,EAAE,EAAE;QACjB;;;;;;WAMG;iBACH,YAAY;qBACV,CAAC,EAAE,CAAC;qBACJ,CAAC,EAAE,CAAC;;;IAIR;;OAEG;aACH,IAAI;QACF,4FAA4F;iBAC5F,qBAAqB,EAAE,GAAG;;IAG5B;;OAEG;aACH,UAAU;QACR,gBAAgB;iBAChB,QAAQ,EAAE,IAAI;QACd,UAAU;iBACV,GAAG,EAAE,CAAG;QACR,mBAAmB;iBACnB,QAAQ,EAAE,CAAG;QACb,uBAAuB;iBACvB,KAAK,EAAE,EAAI;;IAGb;;OAEG;aACH,iBAAiB;QACf;;;;WAIG;iBACH,mBAAmB,EAAE,GAAG;QACxB;;;;WAIG;iBACH,sBAAsB,EAAE,GAAG;QAC3B;;;WAGG;iBACH,kBAAkB,EAAE,CAAC;;IAGvB;;OAEG;aACH,aAAa;QACX,4CAA4C;iBAC5C,KAAK,EAAE,GAAG;QACV,+CAA+C;iBAC/C,QAAQ,EAAE,GAAG;QACb,4CAA4C;iBAC5C,KAAK,EAAE,GAAG;QACV;;;;;;;;;WASG;iBACH,UAAU;qBACR,IAAI,EAAE,KAAK;qBACX,EAAE,EAAE,IAAI;;;IAIZ;;OAEG;aACH,aAAa;QACX;;;;;;WAMG;QACH,mFAAmF;iBACnF,yBAAyB,EAAE,CAAC,EAAE;QAC9B,yHAAyH;iBACzH,SAAS,EAAE,EAAE;;CAEP,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB;;;OAGG;aACH,2BAA2B,EAAE,CAAC;IAE9B;;OAEG;aACH,uBAAuB,EAAE,EAAE;CACnB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;aACH,mBAAmB,EAAE,CAAC;IAEtB;;OAEG;aACH,eAAe,EAAE,EAAE;IAEnB;;OAEG;aACH,sBAAsB,EAAE,GAAG;IAE3B;;;;;OAKG;aACH,kBAAkB,EAAE,GAAG;CACf,CAAC"}
@@ -91,6 +91,22 @@ export const DisplayThresholds = {
91
91
  mm: 0.05,
92
92
  },
93
93
  },
94
+ /**
95
+ * Thermal stress thresholds
96
+ */
97
+ thermalStress: {
98
+ /**
99
+ * Display gates only. The band boundaries themselves live in
100
+ * `src/utils/thermalStress.ts` (where Fosberg's live), and those functions
101
+ * return null below their own lowest band — so *raising* a gate here
102
+ * suppresses lines as expected, while *lowering* one past the pure
103
+ * module's floor has no effect until that floor moves too.
104
+ */
105
+ /** Render the frostbite line when effective wind chill (°F) is at or below this */
106
+ showFrostbiteAtWindChillF: -18,
107
+ /** Compute/render WBGT only when air temp (°F) is at or above showHeatIndex and rounded WBGT (°F) is at or above this */
108
+ showWbgtF: 80,
109
+ },
94
110
  };
95
111
  /**
96
112
  * API-related constants
@@ -1 +1 @@
1
- {"version":3,"file":"displayThresholds.js","sourceRoot":"","sources":["../../src/config/displayThresholds.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B;;OAEG;IACH,WAAW,EAAE;QACX,2DAA2D;QAC3D,aAAa,EAAE,EAAE;QACjB,2DAA2D;QAC3D,aAAa,EAAE,EAAE;QACjB;;;;;;WAMG;QACH,YAAY,EAAE;YACZ,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,CAAC;SACL;KACF;IAED;;OAEG;IACH,IAAI,EAAE;QACJ,4FAA4F;QAC5F,qBAAqB,EAAE,GAAG;KAC3B;IAED;;OAEG;IACH,UAAU,EAAE;QACV,gBAAgB;QAChB,QAAQ,EAAE,IAAI;QACd,UAAU;QACV,GAAG,EAAE,GAAG;QACR,mBAAmB;QACnB,QAAQ,EAAE,GAAG;QACb,uBAAuB;QACvB,KAAK,EAAE,IAAI;KACZ;IAED;;OAEG;IACH,iBAAiB,EAAE;QACjB;;;;WAIG;QACH,mBAAmB,EAAE,GAAG;QACxB;;;;WAIG;QACH,sBAAsB,EAAE,GAAG;QAC3B;;;WAGG;QACH,kBAAkB,EAAE,CAAC;KACtB;IAED;;OAEG;IACH,aAAa,EAAE;QACb,4CAA4C;QAC5C,KAAK,EAAE,GAAG;QACV,+CAA+C;QAC/C,QAAQ,EAAE,GAAG;QACb,4CAA4C;QAC5C,KAAK,EAAE,GAAG;QACV;;;;;;;;;WASG;QACH,UAAU,EAAE;YACV,IAAI,EAAE,KAAK;YACX,EAAE,EAAE,IAAI;SACT;KACF;CACO,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;;;OAGG;IACH,2BAA2B,EAAE,CAAC;IAE9B;;OAEG;IACH,uBAAuB,EAAE,EAAE;CACnB,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;;OAEG;IACH,mBAAmB,EAAE,CAAC;IAEtB;;OAEG;IACH,eAAe,EAAE,EAAE;IAEnB;;OAEG;IACH,sBAAsB,EAAE,GAAG,EAAE,0BAA0B;IAEvD;;;;;OAKG;IACH,kBAAkB,EAAE,GAAG;CACf,CAAC"}
1
+ {"version":3,"file":"displayThresholds.js","sourceRoot":"","sources":["../../src/config/displayThresholds.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B;;OAEG;IACH,WAAW,EAAE;QACX,2DAA2D;QAC3D,aAAa,EAAE,EAAE;QACjB,2DAA2D;QAC3D,aAAa,EAAE,EAAE;QACjB;;;;;;WAMG;QACH,YAAY,EAAE;YACZ,CAAC,EAAE,CAAC;YACJ,CAAC,EAAE,CAAC;SACL;KACF;IAED;;OAEG;IACH,IAAI,EAAE;QACJ,4FAA4F;QAC5F,qBAAqB,EAAE,GAAG;KAC3B;IAED;;OAEG;IACH,UAAU,EAAE;QACV,gBAAgB;QAChB,QAAQ,EAAE,IAAI;QACd,UAAU;QACV,GAAG,EAAE,GAAG;QACR,mBAAmB;QACnB,QAAQ,EAAE,GAAG;QACb,uBAAuB;QACvB,KAAK,EAAE,IAAI;KACZ;IAED;;OAEG;IACH,iBAAiB,EAAE;QACjB;;;;WAIG;QACH,mBAAmB,EAAE,GAAG;QACxB;;;;WAIG;QACH,sBAAsB,EAAE,GAAG;QAC3B;;;WAGG;QACH,kBAAkB,EAAE,CAAC;KACtB;IAED;;OAEG;IACH,aAAa,EAAE;QACb,4CAA4C;QAC5C,KAAK,EAAE,GAAG;QACV,+CAA+C;QAC/C,QAAQ,EAAE,GAAG;QACb,4CAA4C;QAC5C,KAAK,EAAE,GAAG;QACV;;;;;;;;;WASG;QACH,UAAU,EAAE;YACV,IAAI,EAAE,KAAK;YACX,EAAE,EAAE,IAAI;SACT;KACF;IAED;;OAEG;IACH,aAAa,EAAE;QACb;;;;;;WAMG;QACH,mFAAmF;QACnF,yBAAyB,EAAE,CAAC,EAAE;QAC9B,yHAAyH;QACzH,SAAS,EAAE,EAAE;KACd;CACO,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;;;OAGG;IACH,2BAA2B,EAAE,CAAC;IAE9B;;OAEG;IACH,uBAAuB,EAAE,EAAE;CACnB,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;;OAEG;IACH,mBAAmB,EAAE,CAAC;IAEtB;;OAEG;IACH,eAAe,EAAE,EAAE;IAEnB;;OAEG;IACH,sBAAsB,EAAE,GAAG,EAAE,0BAA0B;IAEvD;;;;;OAKG;IACH,kBAAkB,EAAE,GAAG;CACf,CAAC"}
@@ -55,6 +55,67 @@ export declare class ValidationError extends Error {
55
55
  readonly value?: any;
56
56
  constructor(message: string, field?: string, value?: any);
57
57
  }
58
+ /**
59
+ * The user-facing text shown when the optional `mqtt` package is absent.
60
+ *
61
+ * This single string reaches the user through three surfaces, so it is defined
62
+ * once and never reworded per-surface:
63
+ * 1. `get_lightning_activity` — as `Error: <this>` via `formatErrorForUser`
64
+ * 2. `get_weather_summary` — inline in its `## lightning (unavailable)` section
65
+ * 3. `docs/ERROR_HANDLING.md` — quoted verbatim
66
+ *
67
+ * It names the package, states plainly that it is not installed, and gives the
68
+ * remedy. It carries no file path and no stack: the reader needs the fix, not
69
+ * our node_modules layout.
70
+ */
71
+ export declare const MQTT_UNAVAILABLE_MESSAGE: string;
72
+ /**
73
+ * The optional `mqtt` package could not be resolved.
74
+ *
75
+ * Deliberately a plain `Error` and **not** an `ApiError`: `ApiServiceName` is a
76
+ * closed union that does not include Blitzortung, and this is a local packaging
77
+ * state rather than an upstream service failure. `formatErrorForUser` has no
78
+ * branch for it, so it falls through to the generic sanitiser and the user sees
79
+ * `Error: <message>`.
80
+ *
81
+ * This is a **contract** failure, not garnish. Lightning is safety data, so an
82
+ * absent module must never degrade into an empty strike list — that would render
83
+ * as an all-clear built from a missing dependency.
84
+ */
85
+ export declare class MqttUnavailableError extends Error {
86
+ constructor(message?: string);
87
+ }
88
+ /**
89
+ * The user-facing text shown when the optional `mqtt` package is installed but
90
+ * cannot be loaded.
91
+ *
92
+ * A different state from `MQTT_UNAVAILABLE_MESSAGE`, and deliberately a
93
+ * different message: telling someone to reinstall without `--omit=optional`
94
+ * when they never omitted it sends them after the wrong fix. Reaches the same
95
+ * two surfaces (`get_lightning_activity`, `get_weather_summary`).
96
+ *
97
+ * Fixed text with no path and no stack — the underlying failure can carry a
98
+ * `Require stack:` of absolute paths, and none of that belongs in a tool result.
99
+ */
100
+ export declare const MQTT_LOAD_FAILED_MESSAGE: string;
101
+ /**
102
+ * The optional `mqtt` package resolved but failed to load.
103
+ *
104
+ * Distinct from {@link MqttUnavailableError} so the two remedies stay distinct,
105
+ * but the same **contract** posture: lightning is safety data, and a module that
106
+ * failed to load is not an empty feed. Without this, the loader's "real fault"
107
+ * rethrow fell through `getLightningStrikes`'s generic catch to `return []` and
108
+ * rendered a green safety verdict built from a broken dependency — verified
109
+ * against the built dist with a corrupted `mqtt` and with one of its transitive
110
+ * dependencies removed.
111
+ *
112
+ * Note that a corrupt CommonJS package reports `MODULE_NOT_FOUND`, not
113
+ * `ERR_MODULE_NOT_FOUND`, so it never reaches the absence branch — see
114
+ * `loadMqtt` in `src/services/blitzortung.ts`.
115
+ */
116
+ export declare class MqttLoadFailedError extends Error {
117
+ constructor(message?: string);
118
+ }
58
119
  /**
59
120
  * Check if an error is retryable
60
121
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ApiError.d.ts","sourceRoot":"","sources":["../../src/errors/ApiError.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,WAAW,GACX,MAAM,GACN,YAAY,GACZ,WAAW,GACX,iBAAiB,CAAC;AAEtB;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,OAAO,EAAE,cAAc,CAAC;IACxC,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,SAAgB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpC,SAAgB,WAAW,EAAE,OAAO,CAAC;IAErC,YACE,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAM,EAAO,EACxB,WAAW,GAAE,OAAe,EAc7B;IAED;;OAEG;IACH,aAAa,IAAI,MAAM,CAWtB;CACF;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpC,YAAY,OAAO,EAAE,cAAc,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAgC9F;CACF;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;IACnD,YAAY,OAAO,EAAE,cAAc,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,aAAa,CAAC,EAAE,KAAK,EAiC1F;CACF;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnC,YACE,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAcnB;CACF;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;IAC7C,YAAY,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAWnD;CACF;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAgB,KAAK,CAAC,EAAE,GAAG,CAAC;IAE5B,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EASvD;CACF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAetD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAgBvD"}
1
+ {"version":3,"file":"ApiError.d.ts","sourceRoot":"","sources":["../../src/errors/ApiError.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,WAAW,GACX,MAAM,GACN,YAAY,GACZ,WAAW,GACX,iBAAiB,CAAC;AAEtB;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,OAAO,EAAE,cAAc,CAAC;IACxC,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,SAAgB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpC,SAAgB,WAAW,EAAE,OAAO,CAAC;IAErC,YACE,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,EACvB,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAM,EAAO,EACxB,WAAW,GAAE,OAAe,EAc7B;IAED;;OAEG;IACH,aAAa,IAAI,MAAM,CAWtB;CACF;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpC,YAAY,OAAO,EAAE,cAAc,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAgC9F;CACF;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;IACnD,YAAY,OAAO,EAAE,cAAc,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,aAAa,CAAC,EAAE,KAAK,EAiC1F;CACF;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,QAAQ;IAChD,SAAgB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClC,SAAgB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnC,YACE,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,EAcnB;CACF;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,QAAQ;IAC7C,YAAY,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAWnD;CACF;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;IAC/B,SAAgB,KAAK,CAAC,EAAE,GAAG,CAAC;IAE5B,YAAY,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,GAAG,EASvD;CACF;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,QAG0B,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,GAAE,MAAiC,EAOrD;CACF;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,QAGgD,CAAC;AAEtF;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,YAAY,OAAO,GAAE,MAAiC,EAOrD;CACF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAetD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAgBvD"}
@@ -136,6 +136,83 @@ export class ValidationError extends Error {
136
136
  }
137
137
  }
138
138
  }
139
+ /**
140
+ * The user-facing text shown when the optional `mqtt` package is absent.
141
+ *
142
+ * This single string reaches the user through three surfaces, so it is defined
143
+ * once and never reworded per-surface:
144
+ * 1. `get_lightning_activity` — as `Error: <this>` via `formatErrorForUser`
145
+ * 2. `get_weather_summary` — inline in its `## lightning (unavailable)` section
146
+ * 3. `docs/ERROR_HANDLING.md` — quoted verbatim
147
+ *
148
+ * It names the package, states plainly that it is not installed, and gives the
149
+ * remedy. It carries no file path and no stack: the reader needs the fix, not
150
+ * our node_modules layout.
151
+ */
152
+ export const MQTT_UNAVAILABLE_MESSAGE = 'This server was installed without the optional "mqtt" package, which lightning ' +
153
+ 'detection requires. Reinstall without --omit=optional ' +
154
+ '(e.g. npm install -g @dangahagan/weather-mcp) to enable it.';
155
+ /**
156
+ * The optional `mqtt` package could not be resolved.
157
+ *
158
+ * Deliberately a plain `Error` and **not** an `ApiError`: `ApiServiceName` is a
159
+ * closed union that does not include Blitzortung, and this is a local packaging
160
+ * state rather than an upstream service failure. `formatErrorForUser` has no
161
+ * branch for it, so it falls through to the generic sanitiser and the user sees
162
+ * `Error: <message>`.
163
+ *
164
+ * This is a **contract** failure, not garnish. Lightning is safety data, so an
165
+ * absent module must never degrade into an empty strike list — that would render
166
+ * as an all-clear built from a missing dependency.
167
+ */
168
+ export class MqttUnavailableError extends Error {
169
+ constructor(message = MQTT_UNAVAILABLE_MESSAGE) {
170
+ super(message);
171
+ this.name = 'MqttUnavailableError';
172
+ if (Error.captureStackTrace) {
173
+ Error.captureStackTrace(this, this.constructor);
174
+ }
175
+ }
176
+ }
177
+ /**
178
+ * The user-facing text shown when the optional `mqtt` package is installed but
179
+ * cannot be loaded.
180
+ *
181
+ * A different state from `MQTT_UNAVAILABLE_MESSAGE`, and deliberately a
182
+ * different message: telling someone to reinstall without `--omit=optional`
183
+ * when they never omitted it sends them after the wrong fix. Reaches the same
184
+ * two surfaces (`get_lightning_activity`, `get_weather_summary`).
185
+ *
186
+ * Fixed text with no path and no stack — the underlying failure can carry a
187
+ * `Require stack:` of absolute paths, and none of that belongs in a tool result.
188
+ */
189
+ export const MQTT_LOAD_FAILED_MESSAGE = 'The optional "mqtt" package is installed but could not be loaded, so lightning ' +
190
+ 'detection is unavailable. This usually means a damaged or partial install; ' +
191
+ 'reinstalling the server (e.g. npm install -g @dangahagan/weather-mcp) repairs it.';
192
+ /**
193
+ * The optional `mqtt` package resolved but failed to load.
194
+ *
195
+ * Distinct from {@link MqttUnavailableError} so the two remedies stay distinct,
196
+ * but the same **contract** posture: lightning is safety data, and a module that
197
+ * failed to load is not an empty feed. Without this, the loader's "real fault"
198
+ * rethrow fell through `getLightningStrikes`'s generic catch to `return []` and
199
+ * rendered a green safety verdict built from a broken dependency — verified
200
+ * against the built dist with a corrupted `mqtt` and with one of its transitive
201
+ * dependencies removed.
202
+ *
203
+ * Note that a corrupt CommonJS package reports `MODULE_NOT_FOUND`, not
204
+ * `ERR_MODULE_NOT_FOUND`, so it never reaches the absence branch — see
205
+ * `loadMqtt` in `src/services/blitzortung.ts`.
206
+ */
207
+ export class MqttLoadFailedError extends Error {
208
+ constructor(message = MQTT_LOAD_FAILED_MESSAGE) {
209
+ super(message);
210
+ this.name = 'MqttLoadFailedError';
211
+ if (Error.captureStackTrace) {
212
+ Error.captureStackTrace(this, this.constructor);
213
+ }
214
+ }
215
+ }
139
216
  /**
140
217
  * Check if an error is retryable
141
218
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ApiError.js","sourceRoot":"","sources":["../../src/errors/ApiError.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;GAEG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IACjB,UAAU,CAAS;IACnB,OAAO,CAAiB;IACxB,WAAW,CAAS;IACpB,SAAS,CAAW;IACpB,WAAW,CAAU;IAErC,YACE,OAAe,EACf,UAAkB,EAClB,OAAuB,EACvB,WAAmB,EACnB,SAAS,GAAa,EAAE,EACxB,WAAW,GAAY,KAAK;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAE/B,qFAAqF;QACrF,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa;QACX,IAAI,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,eAAe,IAAI,CAAC,WAAW,EAAE,CAAC;QAE/D,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,6BAA6B,CAAC;YACzC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;gBAC5B,OAAO,IAAI,KAAK,IAAI,IAAI,CAAC;YAC3B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,QAAQ;IAC1B,UAAU,CAAU;IAEpC,YAAY,OAAuB,EAAE,mBAAqC,EAAE,UAAmB;QAC7F,oFAAoF;QACpF,IAAI,OAA2B,CAAC;QAChC,IAAI,KAAyB,CAAC;QAE9B,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE,CAAC;YAC5C,OAAO,GAAG,SAAS,CAAC;YACpB,KAAK,GAAG,mBAAmB,CAAC;QAC9B,CAAC;aAAM,IAAI,OAAO,mBAAmB,KAAK,QAAQ,EAAE,CAAC;YACnD,OAAO,GAAG,mBAAmB,CAAC;YAC9B,KAAK,GAAG,UAAU,CAAC;QACrB,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,IAAI,CAAC,KAAK;YACnC,CAAC,CAAC,2CAA2C,KAAK,WAAW;YAC7D,CAAC,CAAC,qDAAqD,CAAC,CAAC;QAE3D,KAAK,CACH,2BAA2B,OAAO,EAAE,EACpC,GAAG,EACH,OAAO,EACP,WAAW,EACX;YACE,oDAAoD;YACpD,sDAAsD;YACtD,+CAA+C;SAChD,EACD,IAAI,CAAC,0BAA0B;SAChC,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,QAAQ;IACnD,YAAY,OAAuB,EAAE,cAA+B,EAAE,aAAqB;QACzF,sFAAsF;QACtF,IAAI,OAA2B,CAAC;QAChC,IAAI,KAAwB,CAAC;QAE7B,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;YACvC,OAAO,GAAG,cAAc,CAAC;YACzB,KAAK,GAAG,aAAa,CAAC;QACxB,CAAC;aAAM,IAAI,cAAc,YAAY,KAAK,EAAE,CAAC;YAC3C,OAAO,GAAG,SAAS,CAAC;YACpB,KAAK,GAAG,cAAc,CAAC;QACzB,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,IAAI,OAAO,OAAO,iFAAiF,CAAC;QAC/H,MAAM,QAAQ,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,0BAA0B;YAC9D,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,4BAA4B;gBACnD,CAAC,CAAC,OAAO,KAAK,YAAY,CAAC,CAAC,CAAC,6BAA6B;oBAC1D,CAAC,CAAC,yBAAyB,CAAC;QAE9B,KAAK,CACH,GAAG,OAAO,+BAA+B,EACzC,GAAG,EACH,OAAO,EACP,WAAW,EACX,CAAC,QAAQ,CAAC,EACV,IAAI,CAAC,YAAY;SAClB,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QAEtC,IAAI,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,GAAG,IAAI,CAAC,KAAK,gBAAgB,KAAK,CAAC,KAAK,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IAChC,QAAQ,CAAU;IAClB,SAAS,CAAU;IAEnC,YACE,OAAuB,EACvB,OAAe,EACf,QAAiB,EACjB,SAAkB;QAElB,KAAK,CACH,OAAO,EACP,GAAG,EACH,OAAO,EACP,OAAO,EACP,EAAE,EACF,KAAK,CAAC,gBAAgB;SACvB,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;IAC7C,YAAY,OAAuB,EAAE,OAAe;QAClD,KAAK,CACH,OAAO,EACP,GAAG,EACH,OAAO,EACP,OAAO,EACP,EAAE,EACF,KAAK,CAAC,gBAAgB;SACvB,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxB,KAAK,CAAU;IACf,KAAK,CAAO;IAE5B,YAAY,OAAe,EAAE,KAAc,EAAE,KAAW;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QAEnB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,WAAW,CAAC;IAC3B,CAAC;IAED,yCAAyC;IACzC,IACE,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;QACtC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;QACnC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EACnC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAY;IAC7C,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC,aAAa,EAAE,CAAC;IAC/B,CAAC;IAED,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;QACrC,OAAO,qBAAqB,KAAK,CAAC,OAAO,EAAE,CAAC;IAC9C,CAAC;IAED,iEAAiE;IACjE,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO;SACnC,OAAO,CAAC,cAAc,EAAE,oBAAoB,CAAC;SAC7C,OAAO,CAAC,WAAW,EAAE,sBAAsB,CAAC;SAC5C,OAAO,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC;IAE7C,OAAO,UAAU,gBAAgB,EAAE,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"ApiError.js","sourceRoot":"","sources":["../../src/errors/ApiError.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,21 @@
1
1
  /**
2
2
  * Handler for get_alerts tool.
3
3
  *
4
- * Routed by country (see docs/plans/international-alerts-plan.md D1):
4
+ * Routed by country (see .devdocs/archive/completed/international-alerts-plan.md D1):
5
5
  * US → NOAA (the original path, byte-identical output),
6
6
  * Canada → MSC GeoMet (Environment and Climate Change Canada),
7
7
  * MeteoAlarm member countries → the country's MeteoAlarm feed,
8
+ * India / Philippines / Indonesia → their national CAP feeds (NDMA SACHET,
9
+ * PAGASA, BMKG), matched to the requested point by alert polygon
10
+ * (see .devdocs/archive/completed/plan-national-cap-alerts.md D1),
8
11
  * elsewhere → the optional keyed Google Weather API fallback when a
9
12
  * `GOOGLE_WEATHER_API_KEY` is configured, else a clean not-covered
10
- * message (see docs/global-alerts-fallback-plan.md D1).
13
+ * message (see .devdocs/archive/completed/global-alerts-fallback-plan.md D1).
11
14
  *
12
- * The branch order is the invariant: a US, Canadian, or MeteoAlarm-country
13
- * request never contacts Google, key or no key — those are jurisdictional
14
- * authorities and stay first-choice. Without a key the elsewhere branch is
15
- * byte-identical to before the fallback existed.
15
+ * The branch order is the invariant: a US, Canadian, MeteoAlarm-country, or
16
+ * national-CAP-country request never contacts Google, key or no key — those
17
+ * are jurisdictional authorities and stay first-choice. Without a key the
18
+ * elsewhere branch is byte-identical to before the fallback existed.
16
19
  *
17
20
  * Country resolution order: a `country_code` already carried by the resolved
18
21
  * location (saved location or geocoded city_name), else a cached
@@ -29,12 +32,13 @@ import { MeteoAlarmService } from '../services/meteoalarm.js';
29
32
  import { GeoMetService } from '../services/geomet.js';
30
33
  import { NominatimService } from '../services/nominatim.js';
31
34
  import { GoogleWeatherService } from '../services/googleWeather.js';
35
+ import { NationalCapService } from '../services/nationalCap.js';
32
36
  type HandlerResult = {
33
37
  content: Array<{
34
38
  type: string;
35
39
  text: string;
36
40
  }>;
37
41
  };
38
- export declare function handleGetAlerts(args: unknown, noaaService: NOAAService, locationStore: LocationStore, geocodingService: GeocodingService, meteoAlarmService?: MeteoAlarmService, geoMetService?: GeoMetService, nominatimService?: NominatimService, googleWeatherService?: GoogleWeatherService): Promise<HandlerResult>;
42
+ export declare function handleGetAlerts(args: unknown, noaaService: NOAAService, locationStore: LocationStore, geocodingService: GeocodingService, meteoAlarmService?: MeteoAlarmService, geoMetService?: GeoMetService, nominatimService?: NominatimService, googleWeatherService?: GoogleWeatherService, nationalCapService?: NationalCapService): Promise<HandlerResult>;
39
43
  export {};
40
44
  //# sourceMappingURL=alertsHandler.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"alertsHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/alertsHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EACL,iBAAiB,EAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAuBpE,KAAK,aAAa,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC;AAMxE,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,aAAa,CAAC,EAAE,aAAa,EAC7B,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,oBAAoB,CAAC,EAAE,oBAAoB,GAC1C,OAAO,CAAC,aAAa,CAAC,CAsExB"}
1
+ {"version":3,"file":"alertsHandler.d.ts","sourceRoot":"","sources":["../../src/handlers/alertsHandler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EACL,iBAAiB,EAGlB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EACL,kBAAkB,EAGnB,MAAM,4BAA4B,CAAC;AAyBpC,KAAK,aAAa,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC;AAMxE,wBAAsB,eAAe,CACnC,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,EAClC,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,aAAa,CAAC,EAAE,aAAa,EAC7B,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,oBAAoB,CAAC,EAAE,oBAAoB,EAC3C,kBAAkB,CAAC,EAAE,kBAAkB,GACtC,OAAO,CAAC,aAAa,CAAC,CA8ExB"}