@jablum/weather-mcp 1.7.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.
- package/LICENSE +21 -0
- package/README.md +1319 -0
- package/dist/analytics/anonymizer.d.ts +37 -0
- package/dist/analytics/anonymizer.d.ts.map +1 -0
- package/dist/analytics/anonymizer.js +112 -0
- package/dist/analytics/anonymizer.js.map +1 -0
- package/dist/analytics/collector.d.ts +72 -0
- package/dist/analytics/collector.d.ts.map +1 -0
- package/dist/analytics/collector.js +282 -0
- package/dist/analytics/collector.js.map +1 -0
- package/dist/analytics/config.d.ts +15 -0
- package/dist/analytics/config.d.ts.map +1 -0
- package/dist/analytics/config.js +172 -0
- package/dist/analytics/config.js.map +1 -0
- package/dist/analytics/index.d.ts +8 -0
- package/dist/analytics/index.d.ts.map +1 -0
- package/dist/analytics/index.js +7 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/middleware.d.ts +33 -0
- package/dist/analytics/middleware.d.ts.map +1 -0
- package/dist/analytics/middleware.js +99 -0
- package/dist/analytics/middleware.js.map +1 -0
- package/dist/analytics/transport.d.ts +11 -0
- package/dist/analytics/transport.d.ts.map +1 -0
- package/dist/analytics/transport.js +92 -0
- package/dist/analytics/transport.js.map +1 -0
- package/dist/analytics/types.d.ts +74 -0
- package/dist/analytics/types.d.ts.map +1 -0
- package/dist/analytics/types.js +6 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/config/api.d.ts +30 -0
- package/dist/config/api.d.ts.map +1 -0
- package/dist/config/api.js +32 -0
- package/dist/config/api.js.map +1 -0
- package/dist/config/cache.d.ts +31 -0
- package/dist/config/cache.d.ts.map +1 -0
- package/dist/config/cache.js +108 -0
- package/dist/config/cache.js.map +1 -0
- package/dist/config/displayThresholds.d.ts +83 -0
- package/dist/config/displayThresholds.d.ts.map +1 -0
- package/dist/config/displayThresholds.js +83 -0
- package/dist/config/displayThresholds.js.map +1 -0
- package/dist/config/tools.d.ts +44 -0
- package/dist/config/tools.d.ts.map +1 -0
- package/dist/config/tools.js +269 -0
- package/dist/config/tools.js.map +1 -0
- package/dist/errors/ApiError.d.ts +62 -0
- package/dist/errors/ApiError.d.ts.map +1 -0
- package/dist/errors/ApiError.js +171 -0
- package/dist/errors/ApiError.js.map +1 -0
- package/dist/handlers/airQualityHandler.d.ts +11 -0
- package/dist/handlers/airQualityHandler.d.ts.map +1 -0
- package/dist/handlers/airQualityHandler.js +154 -0
- package/dist/handlers/airQualityHandler.js.map +1 -0
- package/dist/handlers/alertsHandler.d.ts +11 -0
- package/dist/handlers/alertsHandler.d.ts.map +1 -0
- package/dist/handlers/alertsHandler.js +98 -0
- package/dist/handlers/alertsHandler.js.map +1 -0
- package/dist/handlers/currentConditionsHandler.d.ts +13 -0
- package/dist/handlers/currentConditionsHandler.d.ts.map +1 -0
- package/dist/handlers/currentConditionsHandler.js +296 -0
- package/dist/handlers/currentConditionsHandler.js.map +1 -0
- package/dist/handlers/forecastHandler.d.ts +16 -0
- package/dist/handlers/forecastHandler.d.ts.map +1 -0
- package/dist/handlers/forecastHandler.js +454 -0
- package/dist/handlers/forecastHandler.js.map +1 -0
- package/dist/handlers/historicalWeatherHandler.d.ts +12 -0
- package/dist/handlers/historicalWeatherHandler.d.ts.map +1 -0
- package/dist/handlers/historicalWeatherHandler.js +188 -0
- package/dist/handlers/historicalWeatherHandler.js.map +1 -0
- package/dist/handlers/lightningHandler.d.ts +14 -0
- package/dist/handlers/lightningHandler.d.ts.map +1 -0
- package/dist/handlers/lightningHandler.js +258 -0
- package/dist/handlers/lightningHandler.js.map +1 -0
- package/dist/handlers/locationHandler.d.ts +12 -0
- package/dist/handlers/locationHandler.d.ts.map +1 -0
- package/dist/handlers/locationHandler.js +149 -0
- package/dist/handlers/locationHandler.js.map +1 -0
- package/dist/handlers/marineConditionsHandler.d.ts +13 -0
- package/dist/handlers/marineConditionsHandler.d.ts.map +1 -0
- package/dist/handlers/marineConditionsHandler.js +270 -0
- package/dist/handlers/marineConditionsHandler.js.map +1 -0
- package/dist/handlers/riverConditionsHandler.d.ts +11 -0
- package/dist/handlers/riverConditionsHandler.d.ts.map +1 -0
- package/dist/handlers/riverConditionsHandler.js +176 -0
- package/dist/handlers/riverConditionsHandler.js.map +1 -0
- package/dist/handlers/savedLocationsHandler.d.ts +50 -0
- package/dist/handlers/savedLocationsHandler.d.ts.map +1 -0
- package/dist/handlers/savedLocationsHandler.js +397 -0
- package/dist/handlers/savedLocationsHandler.js.map +1 -0
- package/dist/handlers/statusHandler.d.ts +12 -0
- package/dist/handlers/statusHandler.d.ts.map +1 -0
- package/dist/handlers/statusHandler.js +115 -0
- package/dist/handlers/statusHandler.js.map +1 -0
- package/dist/handlers/weatherImageryHandler.d.ts +14 -0
- package/dist/handlers/weatherImageryHandler.d.ts.map +1 -0
- package/dist/handlers/weatherImageryHandler.js +143 -0
- package/dist/handlers/weatherImageryHandler.js.map +1 -0
- package/dist/handlers/wildfireHandler.d.ts +11 -0
- package/dist/handlers/wildfireHandler.d.ts.map +1 -0
- package/dist/handlers/wildfireHandler.js +186 -0
- package/dist/handlers/wildfireHandler.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +735 -0
- package/dist/index.js.map +1 -0
- package/dist/services/blitzortung.d.ts +67 -0
- package/dist/services/blitzortung.d.ts.map +1 -0
- package/dist/services/blitzortung.js +475 -0
- package/dist/services/blitzortung.js.map +1 -0
- package/dist/services/geocoding.d.ts +57 -0
- package/dist/services/geocoding.d.ts.map +1 -0
- package/dist/services/geocoding.js +393 -0
- package/dist/services/geocoding.js.map +1 -0
- package/dist/services/locationStore.d.ts +62 -0
- package/dist/services/locationStore.d.ts.map +1 -0
- package/dist/services/locationStore.js +201 -0
- package/dist/services/locationStore.js.map +1 -0
- package/dist/services/ncei.d.ts +61 -0
- package/dist/services/ncei.d.ts.map +1 -0
- package/dist/services/ncei.js +126 -0
- package/dist/services/ncei.js.map +1 -0
- package/dist/services/nifc.d.ts +44 -0
- package/dist/services/nifc.d.ts.map +1 -0
- package/dist/services/nifc.js +159 -0
- package/dist/services/nifc.js.map +1 -0
- package/dist/services/noaa.d.ts +161 -0
- package/dist/services/noaa.d.ts.map +1 -0
- package/dist/services/noaa.js +681 -0
- package/dist/services/noaa.js.map +1 -0
- package/dist/services/nominatim.d.ts +62 -0
- package/dist/services/nominatim.d.ts.map +1 -0
- package/dist/services/nominatim.js +254 -0
- package/dist/services/nominatim.js.map +1 -0
- package/dist/services/openmeteo.d.ts +189 -0
- package/dist/services/openmeteo.d.ts.map +1 -0
- package/dist/services/openmeteo.js +936 -0
- package/dist/services/openmeteo.js.map +1 -0
- package/dist/services/rainviewer.d.ts +37 -0
- package/dist/services/rainviewer.d.ts.map +1 -0
- package/dist/services/rainviewer.js +115 -0
- package/dist/services/rainviewer.js.map +1 -0
- package/dist/types/imagery.d.ts +82 -0
- package/dist/types/imagery.d.ts.map +1 -0
- package/dist/types/imagery.js +6 -0
- package/dist/types/imagery.js.map +1 -0
- package/dist/types/lightning.d.ts +89 -0
- package/dist/types/lightning.d.ts.map +1 -0
- package/dist/types/lightning.js +6 -0
- package/dist/types/lightning.js.map +1 -0
- package/dist/types/noaa.d.ts +535 -0
- package/dist/types/noaa.d.ts.map +1 -0
- package/dist/types/noaa.js +5 -0
- package/dist/types/noaa.js.map +1 -0
- package/dist/types/nominatim.d.ts +72 -0
- package/dist/types/nominatim.d.ts.map +1 -0
- package/dist/types/nominatim.js +6 -0
- package/dist/types/nominatim.js.map +1 -0
- package/dist/types/openmeteo.d.ts +583 -0
- package/dist/types/openmeteo.d.ts.map +1 -0
- package/dist/types/openmeteo.js +6 -0
- package/dist/types/openmeteo.js.map +1 -0
- package/dist/types/savedLocations.d.ts +58 -0
- package/dist/types/savedLocations.d.ts.map +1 -0
- package/dist/types/savedLocations.js +5 -0
- package/dist/types/savedLocations.js.map +1 -0
- package/dist/types/wildfire.d.ts +83 -0
- package/dist/types/wildfire.d.ts.map +1 -0
- package/dist/types/wildfire.js +5 -0
- package/dist/types/wildfire.js.map +1 -0
- package/dist/utils/airQuality.d.ts +54 -0
- package/dist/utils/airQuality.d.ts.map +1 -0
- package/dist/utils/airQuality.js +251 -0
- package/dist/utils/airQuality.js.map +1 -0
- package/dist/utils/cache.d.ts +69 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +164 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/distance.d.ts +25 -0
- package/dist/utils/distance.d.ts.map +1 -0
- package/dist/utils/distance.js +40 -0
- package/dist/utils/distance.js.map +1 -0
- package/dist/utils/fireWeather.d.ts +76 -0
- package/dist/utils/fireWeather.d.ts.map +1 -0
- package/dist/utils/fireWeather.js +243 -0
- package/dist/utils/fireWeather.js.map +1 -0
- package/dist/utils/geography.d.ts +79 -0
- package/dist/utils/geography.d.ts.map +1 -0
- package/dist/utils/geography.js +266 -0
- package/dist/utils/geography.js.map +1 -0
- package/dist/utils/geohash.d.ts +62 -0
- package/dist/utils/geohash.d.ts.map +1 -0
- package/dist/utils/geohash.js +146 -0
- package/dist/utils/geohash.js.map +1 -0
- package/dist/utils/locationResolver.d.ts +34 -0
- package/dist/utils/locationResolver.d.ts.map +1 -0
- package/dist/utils/locationResolver.js +120 -0
- package/dist/utils/locationResolver.js.map +1 -0
- package/dist/utils/logger.d.ts +75 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +153 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/marine.d.ts +59 -0
- package/dist/utils/marine.d.ts.map +1 -0
- package/dist/utils/marine.js +215 -0
- package/dist/utils/marine.js.map +1 -0
- package/dist/utils/normals.d.ts +86 -0
- package/dist/utils/normals.d.ts.map +1 -0
- package/dist/utils/normals.js +223 -0
- package/dist/utils/normals.js.map +1 -0
- package/dist/utils/snow.d.ts +45 -0
- package/dist/utils/snow.d.ts.map +1 -0
- package/dist/utils/snow.js +144 -0
- package/dist/utils/snow.js.map +1 -0
- package/dist/utils/temperatureConversion.d.ts +12 -0
- package/dist/utils/temperatureConversion.d.ts.map +1 -0
- package/dist/utils/temperatureConversion.js +17 -0
- package/dist/utils/temperatureConversion.js.map +1 -0
- package/dist/utils/timezone.d.ts +56 -0
- package/dist/utils/timezone.d.ts.map +1 -0
- package/dist/utils/timezone.js +167 -0
- package/dist/utils/timezone.js.map +1 -0
- package/dist/utils/units.d.ts +69 -0
- package/dist/utils/units.d.ts.map +1 -0
- package/dist/utils/units.js +158 -0
- package/dist/utils/units.js.map +1 -0
- package/dist/utils/validation.d.ts +89 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +177 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/utils/version.d.ts +15 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +24 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geographic utility functions for location detection and classification
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Great Lakes bounding boxes (approximate)
|
|
6
|
+
* Source: NOAA Great Lakes Environmental Research Laboratory
|
|
7
|
+
*/
|
|
8
|
+
const GREAT_LAKES_REGIONS = [
|
|
9
|
+
{
|
|
10
|
+
name: 'Lake Superior',
|
|
11
|
+
bbox: {
|
|
12
|
+
minLat: 46.4,
|
|
13
|
+
maxLat: 49.0,
|
|
14
|
+
minLon: -92.2,
|
|
15
|
+
maxLon: -84.3
|
|
16
|
+
},
|
|
17
|
+
description: 'Largest Great Lake by surface area'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Lake Michigan',
|
|
21
|
+
bbox: {
|
|
22
|
+
minLat: 41.6,
|
|
23
|
+
maxLat: 46.0,
|
|
24
|
+
minLon: -87.8,
|
|
25
|
+
maxLon: -84.8
|
|
26
|
+
},
|
|
27
|
+
description: 'Third largest Great Lake, only one entirely in US'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'Lake Huron',
|
|
31
|
+
bbox: {
|
|
32
|
+
minLat: 43.0,
|
|
33
|
+
maxLat: 46.5,
|
|
34
|
+
minLon: -84.8,
|
|
35
|
+
maxLon: -79.8
|
|
36
|
+
},
|
|
37
|
+
description: 'Second largest Great Lake by surface area'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: 'Lake Erie',
|
|
41
|
+
bbox: {
|
|
42
|
+
minLat: 41.3,
|
|
43
|
+
maxLat: 42.9,
|
|
44
|
+
minLon: -83.5,
|
|
45
|
+
maxLon: -78.9
|
|
46
|
+
},
|
|
47
|
+
description: 'Shallowest of the Great Lakes'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'Lake Ontario',
|
|
51
|
+
bbox: {
|
|
52
|
+
minLat: 43.2,
|
|
53
|
+
maxLat: 44.3,
|
|
54
|
+
minLon: -79.8,
|
|
55
|
+
maxLon: -76.1
|
|
56
|
+
},
|
|
57
|
+
description: 'Smallest Great Lake by surface area'
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
/**
|
|
61
|
+
* Major US coastal bays and large inland lakes with NOAA marine forecasts
|
|
62
|
+
* These locations have NOAA marine zone forecasts available
|
|
63
|
+
*/
|
|
64
|
+
const MAJOR_COASTAL_BAYS = [
|
|
65
|
+
{
|
|
66
|
+
name: 'Chesapeake Bay',
|
|
67
|
+
bbox: {
|
|
68
|
+
minLat: 36.9,
|
|
69
|
+
maxLat: 39.6,
|
|
70
|
+
minLon: -76.6,
|
|
71
|
+
maxLon: -75.9
|
|
72
|
+
},
|
|
73
|
+
description: 'Largest estuary in the United States'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'San Francisco Bay',
|
|
77
|
+
bbox: {
|
|
78
|
+
minLat: 37.4,
|
|
79
|
+
maxLat: 38.2,
|
|
80
|
+
minLon: -122.6,
|
|
81
|
+
maxLon: -121.8
|
|
82
|
+
},
|
|
83
|
+
description: 'West Coast major bay area'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'Tampa Bay',
|
|
87
|
+
bbox: {
|
|
88
|
+
minLat: 27.5,
|
|
89
|
+
maxLat: 28.0,
|
|
90
|
+
minLon: -82.8,
|
|
91
|
+
maxLon: -82.4
|
|
92
|
+
},
|
|
93
|
+
description: 'Gulf Coast major bay'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'Puget Sound',
|
|
97
|
+
bbox: {
|
|
98
|
+
minLat: 47.0,
|
|
99
|
+
maxLat: 48.5,
|
|
100
|
+
minLon: -122.9,
|
|
101
|
+
maxLon: -122.2
|
|
102
|
+
},
|
|
103
|
+
description: 'Pacific Northwest inland sea'
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'Lake Okeechobee',
|
|
107
|
+
bbox: {
|
|
108
|
+
minLat: 26.7,
|
|
109
|
+
maxLat: 27.2,
|
|
110
|
+
minLon: -81.0,
|
|
111
|
+
maxLon: -80.6
|
|
112
|
+
},
|
|
113
|
+
description: 'Largest freshwater lake in Florida'
|
|
114
|
+
}
|
|
115
|
+
];
|
|
116
|
+
/**
|
|
117
|
+
* Check if a point is within a bounding box
|
|
118
|
+
*/
|
|
119
|
+
function isInBoundingBox(lat, lon, bbox) {
|
|
120
|
+
return (lat >= bbox.minLat &&
|
|
121
|
+
lat <= bbox.maxLat &&
|
|
122
|
+
lon >= bbox.minLon &&
|
|
123
|
+
lon <= bbox.maxLon);
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Check if coordinates are within the Great Lakes region
|
|
127
|
+
* @param latitude Latitude coordinate
|
|
128
|
+
* @param longitude Longitude coordinate
|
|
129
|
+
* @returns The Great Lake name if in region, null otherwise
|
|
130
|
+
*/
|
|
131
|
+
export function getGreatLakeRegion(latitude, longitude) {
|
|
132
|
+
for (const region of GREAT_LAKES_REGIONS) {
|
|
133
|
+
if (isInBoundingBox(latitude, longitude, region.bbox)) {
|
|
134
|
+
return region.name;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if coordinates are within a major US coastal bay or large inland lake
|
|
141
|
+
* @param latitude Latitude coordinate
|
|
142
|
+
* @param longitude Longitude coordinate
|
|
143
|
+
* @returns The bay/lake name if in region, null otherwise
|
|
144
|
+
*/
|
|
145
|
+
export function getMajorCoastalBayRegion(latitude, longitude) {
|
|
146
|
+
for (const region of MAJOR_COASTAL_BAYS) {
|
|
147
|
+
if (isInBoundingBox(latitude, longitude, region.bbox)) {
|
|
148
|
+
return region.name;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Check if coordinates should use NOAA marine data (Great Lakes or major coastal bays)
|
|
155
|
+
* @param latitude Latitude coordinate
|
|
156
|
+
* @param longitude Longitude coordinate
|
|
157
|
+
* @returns Object with detection results
|
|
158
|
+
*/
|
|
159
|
+
export function shouldUseNOAAMarine(latitude, longitude) {
|
|
160
|
+
// Check Great Lakes first
|
|
161
|
+
const greatLake = getGreatLakeRegion(latitude, longitude);
|
|
162
|
+
if (greatLake) {
|
|
163
|
+
return {
|
|
164
|
+
useNOAA: true,
|
|
165
|
+
region: greatLake,
|
|
166
|
+
source: 'great-lakes'
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// Check major coastal bays
|
|
170
|
+
const coastalBay = getMajorCoastalBayRegion(latitude, longitude);
|
|
171
|
+
if (coastalBay) {
|
|
172
|
+
return {
|
|
173
|
+
useNOAA: true,
|
|
174
|
+
region: coastalBay,
|
|
175
|
+
source: 'coastal-bay'
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
// Default to Open-Meteo for oceans and other locations
|
|
179
|
+
return {
|
|
180
|
+
useNOAA: false,
|
|
181
|
+
region: null,
|
|
182
|
+
source: 'ocean'
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Get a human-readable description of the marine region
|
|
187
|
+
* @param latitude Latitude coordinate
|
|
188
|
+
* @param longitude Longitude coordinate
|
|
189
|
+
* @returns Description string
|
|
190
|
+
*/
|
|
191
|
+
export function getMarineRegionDescription(latitude, longitude) {
|
|
192
|
+
const detection = shouldUseNOAAMarine(latitude, longitude);
|
|
193
|
+
if (detection.region) {
|
|
194
|
+
return `${detection.region} (${detection.source === 'great-lakes' ? 'Great Lakes' : 'Coastal Bay'})`;
|
|
195
|
+
}
|
|
196
|
+
return 'Open ocean or coastal waters';
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get all Great Lakes regions (for testing and documentation)
|
|
200
|
+
*/
|
|
201
|
+
export function getGreatLakesRegions() {
|
|
202
|
+
return GREAT_LAKES_REGIONS;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get all major coastal bay regions (for testing and documentation)
|
|
206
|
+
*/
|
|
207
|
+
export function getMajorCoastalBayRegions() {
|
|
208
|
+
return MAJOR_COASTAL_BAYS;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Approximate country/region detection from coordinates
|
|
212
|
+
* PRIVACY: Intentionally vague - only major regions for privacy
|
|
213
|
+
* ACCURACY: This is a ROUGH approximation with known inaccuracies:
|
|
214
|
+
* - Mexico, Caribbean, Central America -> OTHER
|
|
215
|
+
* - Some border regions may be misclassified
|
|
216
|
+
* - Alaska and Hawaii have special handling
|
|
217
|
+
*
|
|
218
|
+
* This is called OUTSIDE the analytics module to ensure coordinates
|
|
219
|
+
* never enter the analytics boundary. Trade-off: Privacy (no reverse geocoding)
|
|
220
|
+
* vs Accuracy (bounding boxes)
|
|
221
|
+
*
|
|
222
|
+
* @param lat Latitude (-90 to 90)
|
|
223
|
+
* @param lon Longitude (-180 to 180)
|
|
224
|
+
* @returns ISO 3166-1 alpha-2 region code (US, CA, EU, AP, SA, AF, OC, OTHER)
|
|
225
|
+
*/
|
|
226
|
+
export function getCountryFromCoordinates(lat, lon) {
|
|
227
|
+
// Handle Alaska (49°N+, west of 130°W)
|
|
228
|
+
if (lat >= 49 && lon <= -130 && lon >= -180) {
|
|
229
|
+
return 'US';
|
|
230
|
+
}
|
|
231
|
+
// Handle Hawaii (18-23°N, 154-162°W)
|
|
232
|
+
if (lat >= 18 && lat <= 23 && lon >= -162 && lon <= -154) {
|
|
233
|
+
return 'US';
|
|
234
|
+
}
|
|
235
|
+
// Continental US: Approximately 25-49°N, 125-66°W
|
|
236
|
+
if (lat >= 24 && lat <= 50 && lon >= -125 && lon <= -66) {
|
|
237
|
+
return 'US';
|
|
238
|
+
}
|
|
239
|
+
// Canada: Approximately 42-83°N, 141-52°W
|
|
240
|
+
if (lat >= 41 && lat <= 84 && lon >= -142 && lon <= -52) {
|
|
241
|
+
return 'CA';
|
|
242
|
+
}
|
|
243
|
+
// Europe: Approximately 35-71°N, 10°W-40°E
|
|
244
|
+
if (lat >= 35 && lat <= 72 && lon >= -11 && lon <= 41) {
|
|
245
|
+
return 'EU';
|
|
246
|
+
}
|
|
247
|
+
// Asia-Pacific: Rough approximation
|
|
248
|
+
if (lat >= -10 && lat <= 55 && lon >= 60 && lon <= 180) {
|
|
249
|
+
return 'AP';
|
|
250
|
+
}
|
|
251
|
+
// South America: Approximate
|
|
252
|
+
if (lat >= -56 && lat <= 13 && lon >= -82 && lon <= -34) {
|
|
253
|
+
return 'SA';
|
|
254
|
+
}
|
|
255
|
+
// Africa: Approximate
|
|
256
|
+
if (lat >= -35 && lat <= 38 && lon >= -18 && lon <= 52) {
|
|
257
|
+
return 'AF';
|
|
258
|
+
}
|
|
259
|
+
// Australia/Oceania: Approximate
|
|
260
|
+
if (lat >= -48 && lat <= -10 && lon >= 112 && lon <= 180) {
|
|
261
|
+
return 'OC';
|
|
262
|
+
}
|
|
263
|
+
// Default to OTHER for privacy (intentionally vague)
|
|
264
|
+
return 'OTHER';
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=geography.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geography.js","sourceRoot":"","sources":["../../src/utils/geography.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geohash utilities for lightning strike location filtering
|
|
3
|
+
* Based on the homeassistant-blitzortung implementation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Bounding box for geographic area
|
|
7
|
+
*/
|
|
8
|
+
export interface BoundingBox {
|
|
9
|
+
minLat: number;
|
|
10
|
+
minLon: number;
|
|
11
|
+
maxLat: number;
|
|
12
|
+
maxLon: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Calculate bounding box around a point given a radius in kilometers
|
|
16
|
+
* @param lat Latitude
|
|
17
|
+
* @param lon Longitude
|
|
18
|
+
* @param radiusKm Radius in kilometers
|
|
19
|
+
* @returns Bounding box
|
|
20
|
+
*/
|
|
21
|
+
export declare function calculateBoundingBox(lat: number, lon: number, radiusKm: number): BoundingBox;
|
|
22
|
+
/**
|
|
23
|
+
* Get all geohash neighbors for a given geohash
|
|
24
|
+
* @param hash Geohash string
|
|
25
|
+
* @returns Array of neighbor geohashes (up to 8 neighbors)
|
|
26
|
+
*/
|
|
27
|
+
export declare function getGeohashNeighbors(hash: string): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Compute geohash tiles that overlap a circular search area
|
|
30
|
+
* Uses breadth-first search to find all geohashes within the bounding box
|
|
31
|
+
* @param lat Center latitude
|
|
32
|
+
* @param lon Center longitude
|
|
33
|
+
* @param radiusKm Search radius in kilometers
|
|
34
|
+
* @param precision Geohash precision (1-12)
|
|
35
|
+
* @returns Set of geohash strings that overlap the search area
|
|
36
|
+
*/
|
|
37
|
+
export declare function computeGeohashTiles(lat: number, lon: number, radiusKm: number, precision: number): Set<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Calculate optimal geohash tiles for MQTT subscription
|
|
40
|
+
* Selects the coarsest precision that keeps the tile count at or below maxTiles
|
|
41
|
+
* This balances spatial granularity against subscription overhead
|
|
42
|
+
*
|
|
43
|
+
* @param lat Center latitude
|
|
44
|
+
* @param lon Center longitude
|
|
45
|
+
* @param radiusKm Search radius in kilometers
|
|
46
|
+
* @param maxTiles Maximum number of tiles (default 9, as used by homeassistant-blitzortung)
|
|
47
|
+
* @returns Set of geohash strings to subscribe to
|
|
48
|
+
*/
|
|
49
|
+
export declare function calculateGeohashSubscriptions(lat: number, lon: number, radiusKm: number, maxTiles?: number): Set<string>;
|
|
50
|
+
/**
|
|
51
|
+
* Check if a point is within a radius of a center point
|
|
52
|
+
* Uses Haversine formula for great-circle distance
|
|
53
|
+
*
|
|
54
|
+
* @param centerLat Center latitude
|
|
55
|
+
* @param centerLon Center longitude
|
|
56
|
+
* @param pointLat Point latitude
|
|
57
|
+
* @param pointLon Point longitude
|
|
58
|
+
* @param radiusKm Radius in kilometers
|
|
59
|
+
* @returns true if point is within radius
|
|
60
|
+
*/
|
|
61
|
+
export declare function isWithinRadius(centerLat: number, centerLon: number, pointLat: number, pointLon: number, radiusKm: number): boolean;
|
|
62
|
+
//# sourceMappingURL=geohash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geohash.d.ts","sourceRoot":"","sources":["../../src/utils/geohash.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAW5F;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB1D;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,GAAG,CAAC,MAAM,CAAC,CA0Cb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,QAAQ,GAAE,MAAU,GACnB,GAAG,CAAC,MAAM,CAAC,CAsBb;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAgBT"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Geohash utilities for lightning strike location filtering
|
|
3
|
+
* Based on the homeassistant-blitzortung implementation
|
|
4
|
+
*/
|
|
5
|
+
import geohash from 'ngeohash';
|
|
6
|
+
/**
|
|
7
|
+
* Calculate bounding box around a point given a radius in kilometers
|
|
8
|
+
* @param lat Latitude
|
|
9
|
+
* @param lon Longitude
|
|
10
|
+
* @param radiusKm Radius in kilometers
|
|
11
|
+
* @returns Bounding box
|
|
12
|
+
*/
|
|
13
|
+
export function calculateBoundingBox(lat, lon, radiusKm) {
|
|
14
|
+
// Earth's circumference at equator: ~40,000 km
|
|
15
|
+
const latDelta = (radiusKm * 360) / 40000;
|
|
16
|
+
const lonDelta = latDelta / Math.cos((lat * Math.PI) / 180);
|
|
17
|
+
return {
|
|
18
|
+
minLat: Math.max(-90, lat - latDelta),
|
|
19
|
+
minLon: Math.max(-180, lon - lonDelta),
|
|
20
|
+
maxLat: Math.min(90, lat + latDelta),
|
|
21
|
+
maxLon: Math.min(180, lon + lonDelta)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get all geohash neighbors for a given geohash
|
|
26
|
+
* @param hash Geohash string
|
|
27
|
+
* @returns Array of neighbor geohashes (up to 8 neighbors)
|
|
28
|
+
*/
|
|
29
|
+
export function getGeohashNeighbors(hash) {
|
|
30
|
+
const neighbors = [];
|
|
31
|
+
try {
|
|
32
|
+
// Get all 8 neighbors (N, S, E, W, NE, NW, SE, SW)
|
|
33
|
+
neighbors.push(geohash.neighbor(hash, [0, 1])); // N
|
|
34
|
+
neighbors.push(geohash.neighbor(hash, [0, -1])); // S
|
|
35
|
+
neighbors.push(geohash.neighbor(hash, [1, 0])); // E
|
|
36
|
+
neighbors.push(geohash.neighbor(hash, [-1, 0])); // W
|
|
37
|
+
neighbors.push(geohash.neighbor(hash, [1, 1])); // NE
|
|
38
|
+
neighbors.push(geohash.neighbor(hash, [-1, 1])); // NW
|
|
39
|
+
neighbors.push(geohash.neighbor(hash, [1, -1])); // SE
|
|
40
|
+
neighbors.push(geohash.neighbor(hash, [-1, -1])); // SW
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
// If neighbor calculation fails, return empty array
|
|
44
|
+
// This can happen at edge cases (poles, date line)
|
|
45
|
+
}
|
|
46
|
+
return neighbors;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Compute geohash tiles that overlap a circular search area
|
|
50
|
+
* Uses breadth-first search to find all geohashes within the bounding box
|
|
51
|
+
* @param lat Center latitude
|
|
52
|
+
* @param lon Center longitude
|
|
53
|
+
* @param radiusKm Search radius in kilometers
|
|
54
|
+
* @param precision Geohash precision (1-12)
|
|
55
|
+
* @returns Set of geohash strings that overlap the search area
|
|
56
|
+
*/
|
|
57
|
+
export function computeGeohashTiles(lat, lon, radiusKm, precision) {
|
|
58
|
+
const bbox = calculateBoundingBox(lat, lon, radiusKm);
|
|
59
|
+
const tiles = new Set();
|
|
60
|
+
const queue = [];
|
|
61
|
+
const MAX_TILES = 10000; // Safety limit to prevent memory exhaustion
|
|
62
|
+
// Start with the center point's geohash
|
|
63
|
+
const centerHash = geohash.encode(lat, lon, precision);
|
|
64
|
+
queue.push(centerHash);
|
|
65
|
+
tiles.add(centerHash);
|
|
66
|
+
// Breadth-first search to find all tiles within bounding box
|
|
67
|
+
while (queue.length > 0) {
|
|
68
|
+
const currentHash = queue.shift();
|
|
69
|
+
const neighbors = getGeohashNeighbors(currentHash);
|
|
70
|
+
for (const neighbor of neighbors) {
|
|
71
|
+
if (tiles.has(neighbor)) {
|
|
72
|
+
continue; // Already visited
|
|
73
|
+
}
|
|
74
|
+
// Safety check: prevent unbounded growth
|
|
75
|
+
if (tiles.size >= MAX_TILES) {
|
|
76
|
+
return tiles;
|
|
77
|
+
}
|
|
78
|
+
// Decode neighbor to check if it's within bounding box
|
|
79
|
+
const decoded = geohash.decode(neighbor);
|
|
80
|
+
if (decoded.latitude >= bbox.minLat &&
|
|
81
|
+
decoded.latitude <= bbox.maxLat &&
|
|
82
|
+
decoded.longitude >= bbox.minLon &&
|
|
83
|
+
decoded.longitude <= bbox.maxLon) {
|
|
84
|
+
tiles.add(neighbor);
|
|
85
|
+
queue.push(neighbor);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return tiles;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Calculate optimal geohash tiles for MQTT subscription
|
|
93
|
+
* Selects the coarsest precision that keeps the tile count at or below maxTiles
|
|
94
|
+
* This balances spatial granularity against subscription overhead
|
|
95
|
+
*
|
|
96
|
+
* @param lat Center latitude
|
|
97
|
+
* @param lon Center longitude
|
|
98
|
+
* @param radiusKm Search radius in kilometers
|
|
99
|
+
* @param maxTiles Maximum number of tiles (default 9, as used by homeassistant-blitzortung)
|
|
100
|
+
* @returns Set of geohash strings to subscribe to
|
|
101
|
+
*/
|
|
102
|
+
export function calculateGeohashSubscriptions(lat, lon, radiusKm, maxTiles = 9) {
|
|
103
|
+
let result = new Set();
|
|
104
|
+
// Iterate through precision levels 1-12
|
|
105
|
+
// Start with coarse precision and increase until we exceed maxTiles
|
|
106
|
+
for (let precision = 1; precision <= 12; precision++) {
|
|
107
|
+
const tiles = computeGeohashTiles(lat, lon, radiusKm, precision);
|
|
108
|
+
if (tiles.size <= maxTiles) {
|
|
109
|
+
result = tiles;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Exceeded maxTiles, use previous precision
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// If result is empty (shouldn't happen), fall back to center point at precision 4
|
|
117
|
+
if (result.size === 0) {
|
|
118
|
+
result.add(geohash.encode(lat, lon, 4));
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Check if a point is within a radius of a center point
|
|
124
|
+
* Uses Haversine formula for great-circle distance
|
|
125
|
+
*
|
|
126
|
+
* @param centerLat Center latitude
|
|
127
|
+
* @param centerLon Center longitude
|
|
128
|
+
* @param pointLat Point latitude
|
|
129
|
+
* @param pointLon Point longitude
|
|
130
|
+
* @param radiusKm Radius in kilometers
|
|
131
|
+
* @returns true if point is within radius
|
|
132
|
+
*/
|
|
133
|
+
export function isWithinRadius(centerLat, centerLon, pointLat, pointLon, radiusKm) {
|
|
134
|
+
const R = 6371; // Earth's radius in km
|
|
135
|
+
const dLat = ((pointLat - centerLat) * Math.PI) / 180;
|
|
136
|
+
const dLon = ((pointLon - centerLon) * Math.PI) / 180;
|
|
137
|
+
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
138
|
+
Math.cos((centerLat * Math.PI) / 180) *
|
|
139
|
+
Math.cos((pointLat * Math.PI) / 180) *
|
|
140
|
+
Math.sin(dLon / 2) *
|
|
141
|
+
Math.sin(dLon / 2);
|
|
142
|
+
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
143
|
+
const distance = R * c;
|
|
144
|
+
return distance <= radiusKm;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=geohash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geohash.js","sourceRoot":"","sources":["../../src/utils/geohash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility for resolving location coordinates from various input formats
|
|
3
|
+
*/
|
|
4
|
+
import type { GeocodingService } from '../services/geocoding.js';
|
|
5
|
+
import { LocationStore } from '../services/locationStore.js';
|
|
6
|
+
export interface LocationInput {
|
|
7
|
+
latitude?: number;
|
|
8
|
+
longitude?: number;
|
|
9
|
+
location_name?: string;
|
|
10
|
+
city_name?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ResolvedLocation {
|
|
13
|
+
latitude: number;
|
|
14
|
+
longitude: number;
|
|
15
|
+
source: 'coordinates' | 'saved_location' | 'geocoded';
|
|
16
|
+
location_name?: string;
|
|
17
|
+
display_name?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve location coordinates from either direct coordinates or a saved location name
|
|
21
|
+
*
|
|
22
|
+
* @param args - Arguments containing either (latitude + longitude) OR location_name
|
|
23
|
+
* @param locationStore - Location store instance
|
|
24
|
+
* @returns Resolved coordinates and metadata
|
|
25
|
+
* @throws Error if neither coordinates nor location_name provided, or if validation fails
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveLocation(args: LocationInput, locationStore: LocationStore): ResolvedLocation;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve location coordinates from coordinates, saved location name, or city name (geocoded)
|
|
30
|
+
*
|
|
31
|
+
* Priority: coordinates > location_name > city_name
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveLocationAsync(args: LocationInput, locationStore: LocationStore, geocodingService: GeocodingService): Promise<ResolvedLocation>;
|
|
34
|
+
//# sourceMappingURL=locationResolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locationResolver.d.ts","sourceRoot":"","sources":["../../src/utils/locationResolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAG7D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,aAAa,GAAG,gBAAgB,GAAG,UAAU,CAAC;IACtD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwDD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,aAAa,EAAE,aAAa,GAC3B,gBAAgB,CAgClB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,aAAa,EACnB,aAAa,EAAE,aAAa,EAC5B,gBAAgB,EAAE,gBAAgB,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility for resolving location coordinates from various input formats
|
|
3
|
+
*/
|
|
4
|
+
import { validateLatitude, validateLongitude } from './validation.js';
|
|
5
|
+
function hasCoordinates(args) {
|
|
6
|
+
return typeof args.latitude === 'number' && typeof args.longitude === 'number';
|
|
7
|
+
}
|
|
8
|
+
function hasLocationName(args) {
|
|
9
|
+
return typeof args.location_name === 'string' && args.location_name.trim().length > 0;
|
|
10
|
+
}
|
|
11
|
+
function resolveSavedLocation(locationName, locationStore) {
|
|
12
|
+
const normalizedName = locationName.toLowerCase().trim();
|
|
13
|
+
let savedLocation = locationStore.get(normalizedName);
|
|
14
|
+
let matchedAlias = normalizedName;
|
|
15
|
+
if (!savedLocation) {
|
|
16
|
+
const allLocations = locationStore.getAll();
|
|
17
|
+
for (const [alias, location] of Object.entries(allLocations)) {
|
|
18
|
+
if (location.alternateNames && location.alternateNames.length > 0) {
|
|
19
|
+
const normalizedAlternates = location.alternateNames.map(name => name.toLowerCase().trim());
|
|
20
|
+
if (normalizedAlternates.includes(normalizedName)) {
|
|
21
|
+
savedLocation = location;
|
|
22
|
+
matchedAlias = alias;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (!savedLocation) {
|
|
29
|
+
const available = Object.keys(locationStore.getAll());
|
|
30
|
+
throw new Error(`Saved location "${normalizedName}" not found.\n\n` +
|
|
31
|
+
(available.length > 0
|
|
32
|
+
? `Available locations: ${available.join(', ')}\n\n`
|
|
33
|
+
: 'No saved locations yet. Use save_location to create one.\n\n') +
|
|
34
|
+
`Use list_saved_locations to see all saved locations.`);
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
latitude: savedLocation.latitude,
|
|
38
|
+
longitude: savedLocation.longitude,
|
|
39
|
+
source: 'saved_location',
|
|
40
|
+
location_name: matchedAlias
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Resolve location coordinates from either direct coordinates or a saved location name
|
|
45
|
+
*
|
|
46
|
+
* @param args - Arguments containing either (latitude + longitude) OR location_name
|
|
47
|
+
* @param locationStore - Location store instance
|
|
48
|
+
* @returns Resolved coordinates and metadata
|
|
49
|
+
* @throws Error if neither coordinates nor location_name provided, or if validation fails
|
|
50
|
+
*/
|
|
51
|
+
export function resolveLocation(args, locationStore) {
|
|
52
|
+
// Check if location_name is provided
|
|
53
|
+
if (args.location_name && typeof args.location_name === 'string') {
|
|
54
|
+
const locationName = args.location_name.toLowerCase().trim();
|
|
55
|
+
if (locationName.length === 0) {
|
|
56
|
+
throw new Error('location_name cannot be empty');
|
|
57
|
+
}
|
|
58
|
+
return resolveSavedLocation(locationName, locationStore);
|
|
59
|
+
}
|
|
60
|
+
// Check if direct coordinates are provided
|
|
61
|
+
if (hasCoordinates(args)) {
|
|
62
|
+
validateLatitude(args.latitude);
|
|
63
|
+
validateLongitude(args.longitude);
|
|
64
|
+
return {
|
|
65
|
+
latitude: args.latitude,
|
|
66
|
+
longitude: args.longitude,
|
|
67
|
+
source: 'coordinates'
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
// Neither location_name nor coordinates provided
|
|
71
|
+
throw new Error('Either location_name OR (latitude + longitude) must be provided.\n\n' +
|
|
72
|
+
'Examples:\n' +
|
|
73
|
+
' - Using coordinates: latitude=47.6062, longitude=-122.3321\n' +
|
|
74
|
+
' - Using saved location: location_name="home"\n\n' +
|
|
75
|
+
'Use save_location to save frequently used locations.');
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Resolve location coordinates from coordinates, saved location name, or city name (geocoded)
|
|
79
|
+
*
|
|
80
|
+
* Priority: coordinates > location_name > city_name
|
|
81
|
+
*/
|
|
82
|
+
export async function resolveLocationAsync(args, locationStore, geocodingService) {
|
|
83
|
+
if (hasCoordinates(args)) {
|
|
84
|
+
validateLatitude(args.latitude);
|
|
85
|
+
validateLongitude(args.longitude);
|
|
86
|
+
return {
|
|
87
|
+
latitude: args.latitude,
|
|
88
|
+
longitude: args.longitude,
|
|
89
|
+
source: 'coordinates'
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (hasLocationName(args)) {
|
|
93
|
+
const locationName = args.location_name.trim();
|
|
94
|
+
if (locationName.length === 0) {
|
|
95
|
+
throw new Error('location_name cannot be empty');
|
|
96
|
+
}
|
|
97
|
+
return resolveSavedLocation(locationName, locationStore);
|
|
98
|
+
}
|
|
99
|
+
if (typeof args.city_name === 'string') {
|
|
100
|
+
const cityName = args.city_name.trim();
|
|
101
|
+
if (cityName.length === 0) {
|
|
102
|
+
throw new Error('city_name cannot be empty');
|
|
103
|
+
}
|
|
104
|
+
const results = await geocodingService.geocode(cityName, 1);
|
|
105
|
+
const match = results[0];
|
|
106
|
+
return {
|
|
107
|
+
latitude: match.latitude,
|
|
108
|
+
longitude: match.longitude,
|
|
109
|
+
source: 'geocoded',
|
|
110
|
+
display_name: match.display_name || match.name
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
throw new Error('Either city_name, location_name, OR (latitude + longitude) must be provided.\n\n' +
|
|
114
|
+
'Examples:\n' +
|
|
115
|
+
' - Using city name: city_name="Seattle, WA"\n' +
|
|
116
|
+
' - Using coordinates: latitude=47.6062, longitude=-122.3321\n' +
|
|
117
|
+
' - Using saved location: location_name="home"\n\n' +
|
|
118
|
+
'Use save_location to save frequently used locations.');
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=locationResolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locationResolver.js","sourceRoot":"","sources":["../../src/utils/locationResolver.ts"],"names":[],"mappings":"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"}
|