@dangahagan/weather-mcp 0.2.0 → 0.4.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 (68) hide show
  1. package/README.md +252 -53
  2. package/dist/config/cache.d.ts +1 -0
  3. package/dist/config/cache.d.ts.map +1 -1
  4. package/dist/config/cache.js +45 -2
  5. package/dist/config/cache.js.map +1 -1
  6. package/dist/config/displayThresholds.d.ts +83 -0
  7. package/dist/config/displayThresholds.d.ts.map +1 -0
  8. package/dist/config/displayThresholds.js +83 -0
  9. package/dist/config/displayThresholds.js.map +1 -0
  10. package/dist/errors/ApiError.d.ts +62 -0
  11. package/dist/errors/ApiError.d.ts.map +1 -0
  12. package/dist/errors/ApiError.js +147 -0
  13. package/dist/errors/ApiError.js.map +1 -0
  14. package/dist/handlers/alertsHandler.d.ts +11 -0
  15. package/dist/handlers/alertsHandler.d.ts.map +1 -0
  16. package/dist/handlers/alertsHandler.js +79 -0
  17. package/dist/handlers/alertsHandler.js.map +1 -0
  18. package/dist/handlers/currentConditionsHandler.d.ts +11 -0
  19. package/dist/handlers/currentConditionsHandler.d.ts.map +1 -0
  20. package/dist/handlers/currentConditionsHandler.js +168 -0
  21. package/dist/handlers/currentConditionsHandler.js.map +1 -0
  22. package/dist/handlers/forecastHandler.d.ts +13 -0
  23. package/dist/handlers/forecastHandler.d.ts.map +1 -0
  24. package/dist/handlers/forecastHandler.js +226 -0
  25. package/dist/handlers/forecastHandler.js.map +1 -0
  26. package/dist/handlers/historicalWeatherHandler.d.ts +12 -0
  27. package/dist/handlers/historicalWeatherHandler.d.ts.map +1 -0
  28. package/dist/handlers/historicalWeatherHandler.js +188 -0
  29. package/dist/handlers/historicalWeatherHandler.js.map +1 -0
  30. package/dist/handlers/locationHandler.d.ts +11 -0
  31. package/dist/handlers/locationHandler.d.ts.map +1 -0
  32. package/dist/handlers/locationHandler.js +113 -0
  33. package/dist/handlers/locationHandler.js.map +1 -0
  34. package/dist/handlers/statusHandler.d.ts +12 -0
  35. package/dist/handlers/statusHandler.d.ts.map +1 -0
  36. package/dist/handlers/statusHandler.js +106 -0
  37. package/dist/handlers/statusHandler.js.map +1 -0
  38. package/dist/index.js +148 -376
  39. package/dist/index.js.map +1 -1
  40. package/dist/services/noaa.d.ts +14 -1
  41. package/dist/services/noaa.d.ts.map +1 -1
  42. package/dist/services/noaa.js +74 -42
  43. package/dist/services/noaa.js.map +1 -1
  44. package/dist/services/openmeteo.d.ts +54 -3
  45. package/dist/services/openmeteo.d.ts.map +1 -1
  46. package/dist/services/openmeteo.js +256 -112
  47. package/dist/services/openmeteo.js.map +1 -1
  48. package/dist/types/noaa.d.ts +64 -12
  49. package/dist/types/noaa.d.ts.map +1 -1
  50. package/dist/types/openmeteo.d.ts +156 -0
  51. package/dist/types/openmeteo.d.ts.map +1 -1
  52. package/dist/utils/cache.d.ts +11 -4
  53. package/dist/utils/cache.d.ts.map +1 -1
  54. package/dist/utils/cache.js +33 -4
  55. package/dist/utils/cache.js.map +1 -1
  56. package/dist/utils/logger.d.ts +59 -0
  57. package/dist/utils/logger.d.ts.map +1 -0
  58. package/dist/utils/logger.js +128 -0
  59. package/dist/utils/logger.js.map +1 -0
  60. package/dist/utils/temperatureConversion.d.ts +12 -0
  61. package/dist/utils/temperatureConversion.d.ts.map +1 -0
  62. package/dist/utils/temperatureConversion.js +17 -0
  63. package/dist/utils/temperatureConversion.js.map +1 -0
  64. package/dist/utils/validation.d.ts +89 -0
  65. package/dist/utils/validation.d.ts.map +1 -0
  66. package/dist/utils/validation.js +177 -0
  67. package/dist/utils/validation.js.map +1 -0
  68. package/package.json +10 -3
package/README.md CHANGED
@@ -4,16 +4,36 @@
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
6
 
7
- An MCP (Model Context Protocol) server that provides weather data to AI systems like Claude Code. Uses NOAA's API for US weather forecasts and current conditions, plus Open-Meteo for global historical weather data.
7
+ An MCP (Model Context Protocol) server that provides **global weather data** to AI systems like Claude Code. Uses NOAA's API for detailed US weather, plus Open-Meteo for international forecasts and historical weather data worldwide.
8
8
 
9
9
  **📦 Available in the [Official MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.dgahagan/weather-mcp)** as `io.github.dgahagan/weather-mcp`
10
10
 
11
- **No API keys required!** Both NOAA and Open-Meteo APIs are free to use with no authentication needed.
11
+ **No API keys required!** All APIs (NOAA, Open-Meteo) are free to use with no authentication needed.
12
12
 
13
13
  ## Features
14
14
 
15
- - **Get Forecast**: Retrieve weather forecasts for any US location (7-day forecast)
16
- - **Current Conditions**: Get real-time weather observations for US locations
15
+ - **Location Search**: Find coordinates for any location worldwide (NEW in v0.4.0)
16
+ - Convert location names to coordinates ("Paris" 48.8534°, 2.3488°)
17
+ - Support for cities, airports, landmarks, and regions globally
18
+ - Detailed metadata: timezone, elevation, population, country
19
+ - Enables natural language queries: "What's the weather in Tokyo?"
20
+ - **Global Weather Forecasts**: Get forecasts for any location worldwide (ENHANCED in v0.4.0)
21
+ - Automatic source selection: NOAA (US, more detailed) or Open-Meteo (international)
22
+ - Extended forecasts up to 16 days (was 7)
23
+ - Sunrise/sunset times with daylight duration
24
+ - Daily or hourly granularity
25
+ - Precipitation probability display
26
+ - Temperature trends, humidity, wind, and UV index
27
+ - **Weather Alerts**: Get active weather watches, warnings, and advisories for US locations
28
+ - Severity levels (Extreme, Severe, Moderate, Minor)
29
+ - Urgency and certainty indicators
30
+ - Effective and expiration times
31
+ - Instructions and recommended responses
32
+ - **Current Conditions**: Get enhanced real-time weather observations for US locations
33
+ - Heat index and wind chill when relevant
34
+ - 24-hour temperature range
35
+ - Wind gusts and detailed cloud cover
36
+ - Recent precipitation history
17
37
  - **Historical Data**: Access historical weather observations for any location worldwide
18
38
  - Recent data (last 7 days): Detailed hourly observations from NOAA real-time API (US only)
19
39
  - Archival data (>7 days old): Hourly/daily weather data from 1940-present via Open-Meteo (global coverage)
@@ -36,6 +56,8 @@ The Weather MCP server includes an intelligent in-memory caching system that sig
36
56
 
37
57
  The cache automatically stores and retrieves weather data with intelligent expiration:
38
58
 
59
+ - **Location Searches**: Cached for 30 days (locations don't move) - NEW in v0.4.0
60
+ - **Weather Alerts**: Cached for 5 minutes (alerts can change rapidly)
39
61
  - **Forecasts**: Cached for 2 hours (updated approximately hourly)
40
62
  - **Current Conditions**: Cached for 15 minutes (observations update every 20-60 minutes)
41
63
  - **Historical Data (>1 day old)**: Cached indefinitely (finalized data never changes)
@@ -150,60 +172,109 @@ Restart Claude Code and the weather tools will be available.
150
172
 
151
173
  ## Finding Coordinates
152
174
 
153
- All tools require latitude and longitude coordinates. You can find coordinates for any location by:
154
- - Asking Claude Code: "What are the coordinates for [city name]?"
175
+ **NEW in v0.4.0**: Use the built-in `search_location` tool to find coordinates automatically!
176
+
177
+ ```
178
+ "What's the weather in Paris?"
179
+ → Uses search_location to find Paris coordinates (48.8534°, 2.3488°)
180
+ → Then gets the forecast for those coordinates
181
+ ```
182
+
183
+ You can also find coordinates manually:
155
184
  - Using Google Maps: Right-click a location and select the coordinates
156
185
  - Using a geocoding service like geocode.maps.co or nominatim.org
157
186
 
158
- ### Common US City Coordinates
187
+ ### Common City Coordinates (For Reference)
159
188
 
160
189
  | City | Latitude | Longitude |
161
190
  |------|----------|-----------|
162
- | San Francisco, CA | 37.7749 | -122.4194 |
191
+ | Paris, France | 48.8534 | 2.3488 |
192
+ | Tokyo, Japan | 35.6895 | 139.6917 |
193
+ | London, UK | 51.5085 | -0.1257 |
163
194
  | New York, NY | 40.7128 | -74.0060 |
164
- | Chicago, IL | 41.8781 | -87.6298 |
165
- | Los Angeles, CA | 34.0522 | -118.2437 |
166
- | Denver, CO | 39.7392 | -104.9903 |
167
- | Miami, FL | 25.7617 | -80.1918 |
168
- | Seattle, WA | 47.6062 | -122.3321 |
169
- | Austin, TX | 30.2672 | -97.7431 |
195
+ | San Francisco, CA | 37.7749 | -122.4194 |
196
+ | Sydney, Australia | -33.8688 | 151.2093 |
197
+ | Berlin, Germany | 52.5200 | 13.4050 |
198
+ | Dubai, UAE | 25.2048 | 55.2708 |
170
199
 
171
200
  ## Available Tools
172
201
 
173
- ### 1. check_service_status
174
- Check the operational status of weather APIs and cache performance.
202
+ ### 1. search_location (NEW in v0.4.0)
203
+ Find coordinates for any location worldwide by name.
175
204
 
176
- **Parameters:** None
205
+ **Parameters:**
206
+ - `query` (required): Location name to search for (e.g., "Paris", "New York, NY", "Tokyo")
207
+ - `limit` (optional): Maximum number of results to return (1-100, default: 5)
177
208
 
178
209
  **Description:**
179
- Performs health checks on both NOAA and Open-Meteo APIs to verify they are operational. Use this tool when experiencing errors or to proactively verify service availability before making weather data requests. Returns current status, helpful messages, links to official status pages, and cache statistics.
210
+ Converts location names to coordinates using the Open-Meteo Geocoding API. Returns multiple matches with detailed metadata including coordinates, timezone, elevation, population, and administrative regions. Enables natural language weather queries by finding coordinates automatically.
180
211
 
181
- **Example:**
212
+ **Examples:**
182
213
  ```
183
- Check if the weather services are operational
214
+ "Find coordinates for Paris"
215
+ "Search for Tokyo, Japan"
216
+ "Where is San Francisco, CA?"
184
217
  ```
185
218
 
186
219
  **Returns:**
187
- - Operational status for NOAA API (forecasts & current conditions)
188
- - Operational status for Open-Meteo API (historical data)
189
- - Cache statistics (hit rate, size, API call reduction)
190
- - Status page links and recommended actions if issues are detected
191
- - Overall service availability summary
220
+ - Location name and full administrative hierarchy
221
+ - Latitude and longitude coordinates
222
+ - Timezone and elevation
223
+ - Population (when available)
224
+ - Country and region information
225
+ - Feature type (capital, city, airport, etc.)
192
226
 
193
- ### 2. get_forecast
194
- Get weather forecast for a location.
227
+ ### 2. get_forecast (ENHANCED in v0.4.0)
228
+ Get weather forecast for any location worldwide.
195
229
 
196
230
  **Parameters:**
197
231
  - `latitude` (required): Latitude coordinate (-90 to 90)
198
232
  - `longitude` (required): Longitude coordinate (-180 to 180)
199
- - `days` (optional): Number of days in forecast (1-7, default: 7)
233
+ - `days` (optional): Number of days in forecast (1-16, default: 7)
234
+ - `granularity` (optional): "daily" or "hourly" (default: "daily")
235
+ - `include_precipitation_probability` (optional): Include rain chances (default: true)
236
+ - `source` (optional): "auto" (default), "noaa" (US only), or "openmeteo" (global)
237
+
238
+ **Description:**
239
+ Automatically selects the best data source: NOAA for US locations (more detailed) or Open-Meteo for international locations. Supports extended forecasts up to 16 days. Includes sunrise/sunset times, daylight duration, temperature, precipitation, wind, and UV index.
240
+
241
+ **Examples:**
242
+ ```
243
+ "Get a 7-day forecast for Paris (48.8534, 2.3488)"
244
+ "Hourly forecast for Tokyo for the next 3 days"
245
+ "16-day extended forecast for Sydney, Australia"
246
+ ```
247
+
248
+ **Returns:**
249
+ - Temperature (high/low, feels like)
250
+ - Sunrise and sunset times with daylight duration (NEW in v0.4.0)
251
+ - Precipitation chances and amounts
252
+ - Wind speed, direction, and gusts
253
+ - Weather conditions and descriptions
254
+ - UV index (for international locations)
255
+ - Humidity and atmospheric conditions
256
+
257
+ ### 3. check_service_status
258
+ Check the operational status of weather APIs and cache performance.
259
+
260
+ **Parameters:** None
261
+
262
+ **Description:**
263
+ Performs health checks on both NOAA and Open-Meteo APIs to verify they are operational. Use this tool when experiencing errors or to proactively verify service availability before making weather data requests. Returns current status, helpful messages, links to official status pages, and cache statistics.
200
264
 
201
265
  **Example:**
202
266
  ```
203
- Get the weather forecast for San Francisco (latitude: 37.7749, longitude: -122.4194)
267
+ Check if the weather services are operational
204
268
  ```
205
269
 
206
- ### 3. get_current_conditions
270
+ **Returns:**
271
+ - Operational status for NOAA API (forecasts & current conditions)
272
+ - Operational status for Open-Meteo API (historical data & forecasts)
273
+ - Cache statistics (hit rate, size, API call reduction)
274
+ - Status page links and recommended actions if issues are detected
275
+ - Overall service availability summary
276
+
277
+ ### 4. get_current_conditions
207
278
  Get current weather conditions for a location.
208
279
 
209
280
  **Parameters:**
@@ -215,7 +286,7 @@ Get current weather conditions for a location.
215
286
  What are the current weather conditions in New York? (latitude: 40.7128, longitude: -74.0060)
216
287
  ```
217
288
 
218
- ### 4. get_historical_weather
289
+ ### 5. get_historical_weather
219
290
  Get historical weather observations for a location.
220
291
 
221
292
  **Parameters:**
@@ -346,19 +417,45 @@ Use the `check_service_status` tool to proactively verify API availability:
346
417
 
347
418
  ## Testing
348
419
 
349
- ### Quick Test
420
+ ### Automated Test Suite
421
+
422
+ This project includes a comprehensive test suite with 247 automated tests:
350
423
 
351
- Verify NOAA API connectivity:
352
424
  ```bash
353
- npx tsx tests/test_noaa_api.ts
425
+ # Run all tests
426
+ npm test
427
+
428
+ # Run tests with coverage report
429
+ npm run test:coverage
430
+
431
+ # Run tests in watch mode (during development)
432
+ npm run test:watch
433
+
434
+ # Run tests with interactive UI
435
+ npm run test:ui
354
436
  ```
355
437
 
356
- This runs 5 tests covering all major functionality with real NOAA API calls.
438
+ **Test Coverage:**
439
+ - **247 tests** across unit and integration test suites
440
+ - **100% coverage** on critical utilities (cache, validation, units, errors)
441
+ - **54% overall coverage** with focus on reliability and security
442
+ - All tests execute in ~1 second
443
+
444
+ **Test Categories:**
445
+ - **Unit Tests** (228 tests) - Cache, validation, units, errors, config, retry logic
446
+ - **Integration Tests** (19 tests) - Error recovery scenarios, service status checks
447
+
448
+ ### Quick API Connectivity Test
449
+
450
+ Verify NOAA API connectivity with a quick integration test:
451
+ ```bash
452
+ npx tsx tests/test_noaa_api.ts
453
+ ```
357
454
 
358
455
  ### Manual Testing with Claude Code
359
456
 
360
- See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive testing instructions including:
361
- - Setup steps
457
+ See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive manual testing instructions including:
458
+ - Setup steps for MCP clients
362
459
  - Test cases for all tools
363
460
  - Error handling verification
364
461
  - Performance testing
@@ -368,43 +465,89 @@ See [TESTING_GUIDE.md](./docs/TESTING_GUIDE.md) for comprehensive testing instru
368
465
 
369
466
  ### Available Scripts
370
467
 
468
+ **Build & Run:**
371
469
  - `npm run build` - Compile TypeScript to JavaScript
372
470
  - `npm run dev` - Run the server in development mode with tsx
373
471
  - `npm start` - Run the compiled server
374
- - `npx tsx tests/test_noaa_api.ts` - Run API connectivity tests
472
+
473
+ **Testing:**
474
+ - `npm test` - Run all automated tests
475
+ - `npm run test:coverage` - Run tests with coverage report
476
+ - `npm run test:watch` - Run tests in watch mode
477
+ - `npm run test:ui` - Run tests with interactive UI
478
+ - `npx tsx tests/test_noaa_api.ts` - Quick API connectivity test
479
+
480
+ **Security & Maintenance:**
481
+ - `npm run audit` - Check for dependency vulnerabilities
482
+ - `npm run audit:fix` - Automatically fix dependency vulnerabilities
375
483
 
376
484
  ### Project Structure
377
485
 
378
486
  ```
379
487
  weather-mcp/
380
488
  ├── src/
381
- │ ├── index.ts # Main MCP server
489
+ │ ├── index.ts # Main MCP server
490
+ │ ├── config/
491
+ │ │ ├── cache.ts # Cache configuration and TTL strategies
492
+ │ │ └── displayThresholds.ts # Display thresholds for weather conditions
493
+ │ ├── errors/
494
+ │ │ └── ApiError.ts # Custom error class hierarchy
495
+ │ ├── handlers/
496
+ │ │ ├── alertsHandler.ts # Weather alerts tool handler
497
+ │ │ ├── currentConditionsHandler.ts # Current conditions handler
498
+ │ │ ├── forecastHandler.ts # Forecast tool handler
499
+ │ │ ├── historicalWeatherHandler.ts # Historical weather handler
500
+ │ │ └── statusHandler.ts # Service status handler
382
501
  │ ├── services/
383
- │ │ ├── noaa.ts # NOAA real-time API service
384
- │ │ └── openmeteo.ts # Open-Meteo historical weather API service
502
+ │ │ ├── noaa.ts # NOAA API service
503
+ │ │ └── openmeteo.ts # Open-Meteo API service
385
504
  │ ├── types/
386
- │ │ ├── noaa.ts # NOAA TypeScript type definitions
387
- │ │ └── openmeteo.ts # Open-Meteo TypeScript type definitions
505
+ │ │ ├── noaa.ts # NOAA TypeScript type definitions
506
+ │ │ └── openmeteo.ts # Open-Meteo TypeScript type definitions
388
507
  │ └── utils/
389
- └── units.ts # Unit conversion utilities
390
- ├── dist/ # Compiled JavaScript (generated)
391
- ├── tests/ # Test files
508
+ ├── cache.ts # LRU cache implementation
509
+ ├── logger.ts # Structured logging utilities
510
+ ├── temperatureConversion.ts # Temperature conversion helpers
511
+ │ ├── units.ts # Unit conversion utilities
512
+ │ └── validation.ts # Input validation functions
513
+ ├── tests/
514
+ │ ├── unit/ # Unit tests (228 tests)
515
+ │ └── integration/ # Integration tests (19 tests)
516
+ ├── dist/ # Compiled JavaScript (generated)
517
+ ├── docs/ # Documentation
392
518
  └── package.json
393
519
  ```
394
520
 
395
521
  ## API Information
396
522
 
397
- This server uses two weather APIs:
523
+ This server uses three weather APIs:
398
524
 
399
- ### NOAA Weather API (Real-time)
525
+ ### NOAA Weather API (Real-time, US)
400
526
  - **Base URL**: https://api.weather.gov
401
527
  - **Authentication**: None required (User-Agent header only)
402
528
  - **Rate Limits**: Enforced with 5-second retry window
403
529
  - **Coverage**: United States locations only
404
- - **Use cases**: Forecasts, current conditions, recent observations (last 7 days)
530
+ - **Use cases**: US forecasts (detailed), current conditions, recent observations (last 7 days)
405
531
  - **Data**: Detailed hourly observations from weather stations
406
532
 
407
- ### Open-Meteo Historical Weather API (Archival)
533
+ ### Open-Meteo Forecast API (Global) - NEW in v0.4.0
534
+ - **Base URL**: https://api.open-meteo.com/v1
535
+ - **Authentication**: None required (no API token needed)
536
+ - **Rate Limits**: 10,000 requests/day for non-commercial use
537
+ - **Coverage**: Global (worldwide locations)
538
+ - **Use cases**: International forecasts, extended forecasts (up to 16 days)
539
+ - **Data**: Temperature, precipitation, wind, humidity, UV index, sunrise/sunset
540
+ - **Resolution**: 11km global grid resolution
541
+
542
+ ### Open-Meteo Geocoding API (Global) - NEW in v0.4.0
543
+ - **Base URL**: https://geocoding-api.open-meteo.com/v1
544
+ - **Authentication**: None required (no API token needed)
545
+ - **Coverage**: Global (worldwide locations)
546
+ - **Use cases**: Location name to coordinates conversion
547
+ - **Data**: Coordinates, timezone, elevation, population, administrative regions
548
+ - **Cache**: 30-day TTL (locations don't move)
549
+
550
+ ### Open-Meteo Historical Weather API (Global, Archival)
408
551
  - **Base URL**: https://archive-api.open-meteo.com/v1
409
552
  - **Authentication**: None required (no API token needed)
410
553
  - **Rate Limits**: 10,000 requests/day for non-commercial use
@@ -420,9 +563,15 @@ For more details on NOAA APIs, see [NOAA_API_RESEARCH.md](./docs/NOAA_API_RESEAR
420
563
 
421
564
  ### Geographic Coverage
422
565
 
423
- **Forecasts and Current Conditions:**
424
- - NOAA APIs only cover **United States locations**
425
- - International locations are not supported for forecasts and current conditions
566
+ **Forecasts:** (UPDATED in v0.4.0)
567
+ - **Global coverage** via automatic source selection
568
+ - US locations: Uses NOAA API (more detailed, includes narratives)
569
+ - International locations: Uses Open-Meteo API (reliable global forecasts)
570
+ - Extended forecasts (>7 days, up to 16 days): Open-Meteo only
571
+
572
+ **Current Conditions:**
573
+ - **US locations only** (NOAA API)
574
+ - International real-time conditions not yet supported
426
575
 
427
576
  **Historical Data:**
428
577
  - Recent data (last 7 days): **US locations only** (NOAA API)
@@ -455,6 +604,51 @@ For more details on NOAA APIs, see [NOAA_API_RESEARCH.md](./docs/NOAA_API_RESEAR
455
604
  - **For historical analysis**: Open-Meteo provides reliable global coverage back to 1940
456
605
  - **For international locations**: Only historical data (>7 days old) is supported
457
606
 
607
+ ## Security
608
+
609
+ This project takes security seriously and implements multiple layers of protection:
610
+
611
+ ### Security Features
612
+
613
+ **Input Validation:**
614
+ - Comprehensive runtime validation for all user inputs
615
+ - NaN and Infinity checks for numeric coordinates
616
+ - Range validation for latitude (-90 to 90) and longitude (-180 to 180)
617
+ - Type checking with TypeScript strict mode
618
+
619
+ **Error Handling:**
620
+ - Custom error class hierarchy with typed errors
621
+ - Error message sanitization to prevent information leakage
622
+ - Retryable errors clearly identified for graceful recovery
623
+ - Network errors sanitized before display
624
+
625
+ **Dependency Security:**
626
+ - Automated dependency scanning via `npm audit`
627
+ - GitHub Dependabot configured for weekly security updates
628
+ - Minimal dependency footprint (3 runtime dependencies)
629
+ - Zero known vulnerabilities in current dependencies
630
+
631
+ **Reliability:**
632
+ - Exponential backoff with jitter prevents thundering herd problems
633
+ - Comprehensive test suite (247 tests) with 100% coverage on critical utilities
634
+ - Memory-safe cache with automatic cleanup
635
+ - Graceful shutdown handling
636
+
637
+ ### Security Audit
638
+
639
+ The project has undergone a comprehensive security audit:
640
+ - **Overall Security Posture:** B+ (Good)
641
+ - **Risk Level:** LOW
642
+ - **Vulnerabilities:** Zero critical or high-severity issues
643
+ - See [SECURITY_AUDIT.md](./docs/development/SECURITY_AUDIT.md) for full audit report
644
+
645
+ ### Reporting Security Issues
646
+
647
+ To report a security vulnerability, please see our [Security Policy](./SECURITY.md) which includes:
648
+ - Vulnerability reporting procedures
649
+ - Response timeline commitments (48hr acknowledgment, 7-day assessment)
650
+ - Security best practices for users and developers
651
+
458
652
  ## License
459
653
 
460
654
  MIT
@@ -462,3 +656,8 @@ MIT
462
656
  ## Contributing
463
657
 
464
658
  Contributions are welcome! Please feel free to submit a Pull Request.
659
+
660
+ For information about code quality, security considerations, and development best practices, see:
661
+ - [CODE_REVIEW.md](./docs/development/CODE_REVIEW.md) - Comprehensive code quality analysis
662
+ - [CONTRIBUTING.md](./CONTRIBUTING.md) - Contribution guidelines
663
+ - [SECURITY.md](./SECURITY.md) - Security policy and vulnerability reporting
@@ -15,6 +15,7 @@ export declare const CacheConfig: {
15
15
  readonly stations: number;
16
16
  readonly forecast: number;
17
17
  readonly currentConditions: number;
18
+ readonly alerts: number;
18
19
  readonly recentHistorical: number;
19
20
  readonly historicalData: number;
20
21
  readonly serviceStatus: number;
@@ -1 +1 @@
1
- {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,eAAO,MAAM,WAAW;;;;;;;;;;;;CAqCd,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;;;;;;;;;;;;;CA0Cd,CAAC;AAEX;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYrE"}
@@ -11,11 +11,51 @@
11
11
  const MINUTE = 60 * 1000;
12
12
  const HOUR = 60 * MINUTE;
13
13
  const DAY = 24 * HOUR;
14
+ /**
15
+ * Parse a boolean environment variable
16
+ * @param key Environment variable key
17
+ * @param defaultValue Default value if not set
18
+ * @returns Boolean value
19
+ */
20
+ function getEnvBoolean(key, defaultValue) {
21
+ const value = process.env[key];
22
+ if (value === undefined)
23
+ return defaultValue;
24
+ return value !== 'false' && value !== '0';
25
+ }
26
+ /**
27
+ * Parse a number environment variable with validation
28
+ * @param key Environment variable key
29
+ * @param defaultValue Default value if not set or invalid
30
+ * @param min Minimum allowed value (optional)
31
+ * @param max Maximum allowed value (optional)
32
+ * @returns Validated number value
33
+ */
34
+ function getEnvNumber(key, defaultValue, min, max) {
35
+ const value = process.env[key];
36
+ if (value === undefined)
37
+ return defaultValue;
38
+ const parsed = parseInt(value, 10);
39
+ if (isNaN(parsed)) {
40
+ console.warn(`Invalid ${key}: "${value}". Using default: ${defaultValue}`);
41
+ return defaultValue;
42
+ }
43
+ if (min !== undefined && parsed < min) {
44
+ console.warn(`${key} too low: ${parsed}. Using minimum: ${min}`);
45
+ return min;
46
+ }
47
+ if (max !== undefined && parsed > max) {
48
+ console.warn(`${key} too high: ${parsed}. Using maximum: ${max}`);
49
+ return max;
50
+ }
51
+ return parsed;
52
+ }
14
53
  export const CacheConfig = {
15
54
  // Enable/disable caching globally
16
- enabled: process.env.CACHE_ENABLED !== 'false', // Default: enabled
55
+ enabled: getEnvBoolean('CACHE_ENABLED', true),
17
56
  // Maximum number of entries in cache before LRU eviction
18
- maxSize: parseInt(process.env.CACHE_MAX_SIZE || '1000', 10),
57
+ // Min: 100, Max: 10000, Default: 1000
58
+ maxSize: getEnvNumber('CACHE_MAX_SIZE', 1000, 100, 10000),
19
59
  // TTL values for different data types
20
60
  ttl: {
21
61
  // Grid coordinate lookups (lat/lon -> grid mapping)
@@ -30,6 +70,9 @@ export const CacheConfig = {
30
70
  // Current weather conditions
31
71
  // Observations typically update every 20-60 minutes
32
72
  currentConditions: 15 * MINUTE,
73
+ // Weather alerts
74
+ // Alerts can change rapidly, cache for shorter period
75
+ alerts: 5 * MINUTE,
33
76
  // Recent historical data (< 7 days old)
34
77
  // Recent data may still be updated/corrected
35
78
  recentHistorical: 1 * HOUR,
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iCAAiC;AACjC,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC;AACzB,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC;AACzB,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;AAEtB,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,OAAO,EAAE,mBAAmB;IAEnE,yDAAyD;IACzD,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,MAAM,EAAE,EAAE,CAAC;IAE3D,sCAAsC;IACtC,GAAG,EAAE;QACH,oDAAoD;QACpD,wCAAwC;QACxC,eAAe,EAAE,QAAQ;QAEzB,wBAAwB;QACxB,yBAAyB;QACzB,QAAQ,EAAE,EAAE,GAAG,IAAI;QAEnB,kBAAkB;QAClB,8CAA8C;QAC9C,QAAQ,EAAE,CAAC,GAAG,IAAI;QAElB,6BAA6B;QAC7B,oDAAoD;QACpD,iBAAiB,EAAE,EAAE,GAAG,MAAM;QAE9B,wCAAwC;QACxC,6CAA6C;QAC7C,gBAAgB,EAAE,CAAC,GAAG,IAAI;QAE1B,kDAAkD;QAClD,6DAA6D;QAC7D,cAAc,EAAE,QAAQ;QAExB,8BAA8B;QAC9B,+BAA+B;QAC/B,aAAa,EAAE,CAAC,GAAG,MAAM;KAC1B;CACO,CAAC;AAEX;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAwB;IAC3D,MAAM,KAAK,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC9E,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC;IAEzD,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,gEAAgE;QAChE,OAAO,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC;IACxC,CAAC;SAAM,CAAC;QACN,mCAAmC;QACnC,OAAO,WAAW,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC1C,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/config/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Display thresholds and constants for weather data formatting
3
+ *
4
+ * These values determine when certain weather metrics are shown or highlighted
5
+ */
6
+ export declare const DisplayThresholds: {
7
+ /**
8
+ * Temperature thresholds (in Fahrenheit)
9
+ */
10
+ readonly temperature: {
11
+ /** Show heat index when temperature is above this value */
12
+ readonly showHeatIndex: 80;
13
+ /** Show wind chill when temperature is below this value */
14
+ readonly showWindChill: 50;
15
+ };
16
+ /**
17
+ * Wind thresholds
18
+ */
19
+ readonly wind: {
20
+ /** Show gusts if they are this ratio higher than sustained wind speed (1.2 = 20% higher) */
21
+ readonly gustSignificanceRatio: 1.2;
22
+ };
23
+ /**
24
+ * Visibility thresholds (in miles)
25
+ */
26
+ readonly visibility: {
27
+ /** Dense fog */
28
+ readonly denseFog: 0.25;
29
+ /** Fog */
30
+ readonly fog: 1;
31
+ /** Haze or mist */
32
+ readonly hazeMist: 3;
33
+ /** Clear visibility */
34
+ readonly clear: 10;
35
+ };
36
+ /**
37
+ * Precipitation thresholds
38
+ */
39
+ readonly precipitation: {
40
+ /** Light precipitation (inches per hour) */
41
+ readonly light: 0.1;
42
+ /** Moderate precipitation (inches per hour) */
43
+ readonly moderate: 0.3;
44
+ /** Heavy precipitation (inches per hour) */
45
+ readonly heavy: 0.5;
46
+ };
47
+ };
48
+ /**
49
+ * API-related constants
50
+ */
51
+ export declare const ApiConstants: {
52
+ /**
53
+ * Historical data threshold (in days)
54
+ * Data older than this uses archival API instead of recent observations
55
+ */
56
+ readonly historicalDataThresholdDays: 7;
57
+ /**
58
+ * Maximum date range for hourly historical data (in days)
59
+ */
60
+ readonly maxHourlyHistoricalDays: 31;
61
+ };
62
+ /**
63
+ * Formatting constants
64
+ */
65
+ export declare const FormatConstants: {
66
+ /**
67
+ * Default forecast periods to show
68
+ */
69
+ readonly defaultForecastDays: 7;
70
+ /**
71
+ * Maximum forecast days (Open-Meteo supports up to 16 days)
72
+ */
73
+ readonly maxForecastDays: 16;
74
+ /**
75
+ * Default observation limit for historical data
76
+ */
77
+ readonly defaultHistoricalLimit: 168;
78
+ /**
79
+ * Maximum observations to return
80
+ */
81
+ readonly maxHistoricalLimit: 500;
82
+ };
83
+ //# sourceMappingURL=displayThresholds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"displayThresholds.d.ts","sourceRoot":"","sources":["../../src/config/displayThresholds.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAO,MAAM,iBAAiB;IAC5B;;OAEG;;QAED,2DAA2D;;QAE3D,2DAA2D;;;IAI7D;;OAEG;;QAED,4FAA4F;;;IAI9F;;OAEG;;QAED,gBAAgB;;QAEhB,UAAU;;QAEV,mBAAmB;;QAEnB,uBAAuB;;;IAIzB;;OAEG;;QAED,4CAA4C;;QAE5C,+CAA+C;;QAE/C,4CAA4C;;;CAGtC,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,YAAY;IACvB;;;OAGG;;IAGH;;OAEG;;CAEK,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,eAAe;IAC1B;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEK,CAAC"}