@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.
Files changed (235) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1319 -0
  3. package/dist/analytics/anonymizer.d.ts +37 -0
  4. package/dist/analytics/anonymizer.d.ts.map +1 -0
  5. package/dist/analytics/anonymizer.js +112 -0
  6. package/dist/analytics/anonymizer.js.map +1 -0
  7. package/dist/analytics/collector.d.ts +72 -0
  8. package/dist/analytics/collector.d.ts.map +1 -0
  9. package/dist/analytics/collector.js +282 -0
  10. package/dist/analytics/collector.js.map +1 -0
  11. package/dist/analytics/config.d.ts +15 -0
  12. package/dist/analytics/config.d.ts.map +1 -0
  13. package/dist/analytics/config.js +172 -0
  14. package/dist/analytics/config.js.map +1 -0
  15. package/dist/analytics/index.d.ts +8 -0
  16. package/dist/analytics/index.d.ts.map +1 -0
  17. package/dist/analytics/index.js +7 -0
  18. package/dist/analytics/index.js.map +1 -0
  19. package/dist/analytics/middleware.d.ts +33 -0
  20. package/dist/analytics/middleware.d.ts.map +1 -0
  21. package/dist/analytics/middleware.js +99 -0
  22. package/dist/analytics/middleware.js.map +1 -0
  23. package/dist/analytics/transport.d.ts +11 -0
  24. package/dist/analytics/transport.d.ts.map +1 -0
  25. package/dist/analytics/transport.js +92 -0
  26. package/dist/analytics/transport.js.map +1 -0
  27. package/dist/analytics/types.d.ts +74 -0
  28. package/dist/analytics/types.d.ts.map +1 -0
  29. package/dist/analytics/types.js +6 -0
  30. package/dist/analytics/types.js.map +1 -0
  31. package/dist/config/api.d.ts +30 -0
  32. package/dist/config/api.d.ts.map +1 -0
  33. package/dist/config/api.js +32 -0
  34. package/dist/config/api.js.map +1 -0
  35. package/dist/config/cache.d.ts +31 -0
  36. package/dist/config/cache.d.ts.map +1 -0
  37. package/dist/config/cache.js +108 -0
  38. package/dist/config/cache.js.map +1 -0
  39. package/dist/config/displayThresholds.d.ts +83 -0
  40. package/dist/config/displayThresholds.d.ts.map +1 -0
  41. package/dist/config/displayThresholds.js +83 -0
  42. package/dist/config/displayThresholds.js.map +1 -0
  43. package/dist/config/tools.d.ts +44 -0
  44. package/dist/config/tools.d.ts.map +1 -0
  45. package/dist/config/tools.js +269 -0
  46. package/dist/config/tools.js.map +1 -0
  47. package/dist/errors/ApiError.d.ts +62 -0
  48. package/dist/errors/ApiError.d.ts.map +1 -0
  49. package/dist/errors/ApiError.js +171 -0
  50. package/dist/errors/ApiError.js.map +1 -0
  51. package/dist/handlers/airQualityHandler.d.ts +11 -0
  52. package/dist/handlers/airQualityHandler.d.ts.map +1 -0
  53. package/dist/handlers/airQualityHandler.js +154 -0
  54. package/dist/handlers/airQualityHandler.js.map +1 -0
  55. package/dist/handlers/alertsHandler.d.ts +11 -0
  56. package/dist/handlers/alertsHandler.d.ts.map +1 -0
  57. package/dist/handlers/alertsHandler.js +98 -0
  58. package/dist/handlers/alertsHandler.js.map +1 -0
  59. package/dist/handlers/currentConditionsHandler.d.ts +13 -0
  60. package/dist/handlers/currentConditionsHandler.d.ts.map +1 -0
  61. package/dist/handlers/currentConditionsHandler.js +296 -0
  62. package/dist/handlers/currentConditionsHandler.js.map +1 -0
  63. package/dist/handlers/forecastHandler.d.ts +16 -0
  64. package/dist/handlers/forecastHandler.d.ts.map +1 -0
  65. package/dist/handlers/forecastHandler.js +454 -0
  66. package/dist/handlers/forecastHandler.js.map +1 -0
  67. package/dist/handlers/historicalWeatherHandler.d.ts +12 -0
  68. package/dist/handlers/historicalWeatherHandler.d.ts.map +1 -0
  69. package/dist/handlers/historicalWeatherHandler.js +188 -0
  70. package/dist/handlers/historicalWeatherHandler.js.map +1 -0
  71. package/dist/handlers/lightningHandler.d.ts +14 -0
  72. package/dist/handlers/lightningHandler.d.ts.map +1 -0
  73. package/dist/handlers/lightningHandler.js +258 -0
  74. package/dist/handlers/lightningHandler.js.map +1 -0
  75. package/dist/handlers/locationHandler.d.ts +12 -0
  76. package/dist/handlers/locationHandler.d.ts.map +1 -0
  77. package/dist/handlers/locationHandler.js +149 -0
  78. package/dist/handlers/locationHandler.js.map +1 -0
  79. package/dist/handlers/marineConditionsHandler.d.ts +13 -0
  80. package/dist/handlers/marineConditionsHandler.d.ts.map +1 -0
  81. package/dist/handlers/marineConditionsHandler.js +270 -0
  82. package/dist/handlers/marineConditionsHandler.js.map +1 -0
  83. package/dist/handlers/riverConditionsHandler.d.ts +11 -0
  84. package/dist/handlers/riverConditionsHandler.d.ts.map +1 -0
  85. package/dist/handlers/riverConditionsHandler.js +176 -0
  86. package/dist/handlers/riverConditionsHandler.js.map +1 -0
  87. package/dist/handlers/savedLocationsHandler.d.ts +50 -0
  88. package/dist/handlers/savedLocationsHandler.d.ts.map +1 -0
  89. package/dist/handlers/savedLocationsHandler.js +397 -0
  90. package/dist/handlers/savedLocationsHandler.js.map +1 -0
  91. package/dist/handlers/statusHandler.d.ts +12 -0
  92. package/dist/handlers/statusHandler.d.ts.map +1 -0
  93. package/dist/handlers/statusHandler.js +115 -0
  94. package/dist/handlers/statusHandler.js.map +1 -0
  95. package/dist/handlers/weatherImageryHandler.d.ts +14 -0
  96. package/dist/handlers/weatherImageryHandler.d.ts.map +1 -0
  97. package/dist/handlers/weatherImageryHandler.js +143 -0
  98. package/dist/handlers/weatherImageryHandler.js.map +1 -0
  99. package/dist/handlers/wildfireHandler.d.ts +11 -0
  100. package/dist/handlers/wildfireHandler.d.ts.map +1 -0
  101. package/dist/handlers/wildfireHandler.js +186 -0
  102. package/dist/handlers/wildfireHandler.js.map +1 -0
  103. package/dist/index.d.ts +7 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +735 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/services/blitzortung.d.ts +67 -0
  108. package/dist/services/blitzortung.d.ts.map +1 -0
  109. package/dist/services/blitzortung.js +475 -0
  110. package/dist/services/blitzortung.js.map +1 -0
  111. package/dist/services/geocoding.d.ts +57 -0
  112. package/dist/services/geocoding.d.ts.map +1 -0
  113. package/dist/services/geocoding.js +393 -0
  114. package/dist/services/geocoding.js.map +1 -0
  115. package/dist/services/locationStore.d.ts +62 -0
  116. package/dist/services/locationStore.d.ts.map +1 -0
  117. package/dist/services/locationStore.js +201 -0
  118. package/dist/services/locationStore.js.map +1 -0
  119. package/dist/services/ncei.d.ts +61 -0
  120. package/dist/services/ncei.d.ts.map +1 -0
  121. package/dist/services/ncei.js +126 -0
  122. package/dist/services/ncei.js.map +1 -0
  123. package/dist/services/nifc.d.ts +44 -0
  124. package/dist/services/nifc.d.ts.map +1 -0
  125. package/dist/services/nifc.js +159 -0
  126. package/dist/services/nifc.js.map +1 -0
  127. package/dist/services/noaa.d.ts +161 -0
  128. package/dist/services/noaa.d.ts.map +1 -0
  129. package/dist/services/noaa.js +681 -0
  130. package/dist/services/noaa.js.map +1 -0
  131. package/dist/services/nominatim.d.ts +62 -0
  132. package/dist/services/nominatim.d.ts.map +1 -0
  133. package/dist/services/nominatim.js +254 -0
  134. package/dist/services/nominatim.js.map +1 -0
  135. package/dist/services/openmeteo.d.ts +189 -0
  136. package/dist/services/openmeteo.d.ts.map +1 -0
  137. package/dist/services/openmeteo.js +936 -0
  138. package/dist/services/openmeteo.js.map +1 -0
  139. package/dist/services/rainviewer.d.ts +37 -0
  140. package/dist/services/rainviewer.d.ts.map +1 -0
  141. package/dist/services/rainviewer.js +115 -0
  142. package/dist/services/rainviewer.js.map +1 -0
  143. package/dist/types/imagery.d.ts +82 -0
  144. package/dist/types/imagery.d.ts.map +1 -0
  145. package/dist/types/imagery.js +6 -0
  146. package/dist/types/imagery.js.map +1 -0
  147. package/dist/types/lightning.d.ts +89 -0
  148. package/dist/types/lightning.d.ts.map +1 -0
  149. package/dist/types/lightning.js +6 -0
  150. package/dist/types/lightning.js.map +1 -0
  151. package/dist/types/noaa.d.ts +535 -0
  152. package/dist/types/noaa.d.ts.map +1 -0
  153. package/dist/types/noaa.js +5 -0
  154. package/dist/types/noaa.js.map +1 -0
  155. package/dist/types/nominatim.d.ts +72 -0
  156. package/dist/types/nominatim.d.ts.map +1 -0
  157. package/dist/types/nominatim.js +6 -0
  158. package/dist/types/nominatim.js.map +1 -0
  159. package/dist/types/openmeteo.d.ts +583 -0
  160. package/dist/types/openmeteo.d.ts.map +1 -0
  161. package/dist/types/openmeteo.js +6 -0
  162. package/dist/types/openmeteo.js.map +1 -0
  163. package/dist/types/savedLocations.d.ts +58 -0
  164. package/dist/types/savedLocations.d.ts.map +1 -0
  165. package/dist/types/savedLocations.js +5 -0
  166. package/dist/types/savedLocations.js.map +1 -0
  167. package/dist/types/wildfire.d.ts +83 -0
  168. package/dist/types/wildfire.d.ts.map +1 -0
  169. package/dist/types/wildfire.js +5 -0
  170. package/dist/types/wildfire.js.map +1 -0
  171. package/dist/utils/airQuality.d.ts +54 -0
  172. package/dist/utils/airQuality.d.ts.map +1 -0
  173. package/dist/utils/airQuality.js +251 -0
  174. package/dist/utils/airQuality.js.map +1 -0
  175. package/dist/utils/cache.d.ts +69 -0
  176. package/dist/utils/cache.d.ts.map +1 -0
  177. package/dist/utils/cache.js +164 -0
  178. package/dist/utils/cache.js.map +1 -0
  179. package/dist/utils/distance.d.ts +25 -0
  180. package/dist/utils/distance.d.ts.map +1 -0
  181. package/dist/utils/distance.js +40 -0
  182. package/dist/utils/distance.js.map +1 -0
  183. package/dist/utils/fireWeather.d.ts +76 -0
  184. package/dist/utils/fireWeather.d.ts.map +1 -0
  185. package/dist/utils/fireWeather.js +243 -0
  186. package/dist/utils/fireWeather.js.map +1 -0
  187. package/dist/utils/geography.d.ts +79 -0
  188. package/dist/utils/geography.d.ts.map +1 -0
  189. package/dist/utils/geography.js +266 -0
  190. package/dist/utils/geography.js.map +1 -0
  191. package/dist/utils/geohash.d.ts +62 -0
  192. package/dist/utils/geohash.d.ts.map +1 -0
  193. package/dist/utils/geohash.js +146 -0
  194. package/dist/utils/geohash.js.map +1 -0
  195. package/dist/utils/locationResolver.d.ts +34 -0
  196. package/dist/utils/locationResolver.d.ts.map +1 -0
  197. package/dist/utils/locationResolver.js +120 -0
  198. package/dist/utils/locationResolver.js.map +1 -0
  199. package/dist/utils/logger.d.ts +75 -0
  200. package/dist/utils/logger.d.ts.map +1 -0
  201. package/dist/utils/logger.js +153 -0
  202. package/dist/utils/logger.js.map +1 -0
  203. package/dist/utils/marine.d.ts +59 -0
  204. package/dist/utils/marine.d.ts.map +1 -0
  205. package/dist/utils/marine.js +215 -0
  206. package/dist/utils/marine.js.map +1 -0
  207. package/dist/utils/normals.d.ts +86 -0
  208. package/dist/utils/normals.d.ts.map +1 -0
  209. package/dist/utils/normals.js +223 -0
  210. package/dist/utils/normals.js.map +1 -0
  211. package/dist/utils/snow.d.ts +45 -0
  212. package/dist/utils/snow.d.ts.map +1 -0
  213. package/dist/utils/snow.js +144 -0
  214. package/dist/utils/snow.js.map +1 -0
  215. package/dist/utils/temperatureConversion.d.ts +12 -0
  216. package/dist/utils/temperatureConversion.d.ts.map +1 -0
  217. package/dist/utils/temperatureConversion.js +17 -0
  218. package/dist/utils/temperatureConversion.js.map +1 -0
  219. package/dist/utils/timezone.d.ts +56 -0
  220. package/dist/utils/timezone.d.ts.map +1 -0
  221. package/dist/utils/timezone.js +167 -0
  222. package/dist/utils/timezone.js.map +1 -0
  223. package/dist/utils/units.d.ts +69 -0
  224. package/dist/utils/units.d.ts.map +1 -0
  225. package/dist/utils/units.js +158 -0
  226. package/dist/utils/units.js.map +1 -0
  227. package/dist/utils/validation.d.ts +89 -0
  228. package/dist/utils/validation.d.ts.map +1 -0
  229. package/dist/utils/validation.js +177 -0
  230. package/dist/utils/validation.js.map +1 -0
  231. package/dist/utils/version.d.ts +15 -0
  232. package/dist/utils/version.d.ts.map +1 -0
  233. package/dist/utils/version.js +24 -0
  234. package/dist/utils/version.js.map +1 -0
  235. package/package.json +74 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Utility functions for timezone-aware time formatting
3
+ * Uses Luxon for timezone support with native Intl API
4
+ */
5
+ import { DateTime } from 'luxon';
6
+ /**
7
+ * Format an ISO 8601 datetime string in the specified timezone
8
+ * @param isoString - ISO 8601 datetime string (e.g., "2025-11-07T14:30:00+00:00")
9
+ * @param timezone - IANA timezone identifier (e.g., "America/New_York", "Asia/Tokyo")
10
+ * @param format - Optional format style ('full', 'long', 'medium', 'short')
11
+ * @returns Formatted datetime string in local timezone
12
+ */
13
+ export function formatInTimezone(isoString, timezone, format = 'medium') {
14
+ try {
15
+ const dt = DateTime.fromISO(isoString, { setZone: false });
16
+ if (!dt.isValid) {
17
+ // Fallback to JavaScript Date if Luxon can't parse
18
+ return new Date(isoString).toLocaleString('en-US', { timeZone: timezone });
19
+ }
20
+ const zonedDt = dt.setZone(timezone);
21
+ // Format based on requested style
22
+ switch (format) {
23
+ case 'full':
24
+ return zonedDt.toLocaleString(DateTime.DATETIME_FULL);
25
+ case 'long':
26
+ return zonedDt.toLocaleString(DateTime.DATETIME_MED_WITH_SECONDS);
27
+ case 'short':
28
+ return zonedDt.toLocaleString(DateTime.DATETIME_SHORT);
29
+ case 'medium':
30
+ default:
31
+ return zonedDt.toLocaleString(DateTime.DATETIME_MED);
32
+ }
33
+ }
34
+ catch (error) {
35
+ // Fallback to standard Date formatting if anything goes wrong
36
+ return new Date(isoString).toLocaleString('en-US', { timeZone: timezone });
37
+ }
38
+ }
39
+ /**
40
+ * Format a date-only ISO string in the specified timezone
41
+ * @param isoString - ISO 8601 datetime string
42
+ * @param timezone - IANA timezone identifier
43
+ * @returns Formatted date string (e.g., "Nov 7, 2025")
44
+ */
45
+ export function formatDateInTimezone(isoString, timezone) {
46
+ try {
47
+ const dt = DateTime.fromISO(isoString, { setZone: false });
48
+ if (!dt.isValid) {
49
+ return new Date(isoString).toLocaleDateString('en-US', { timeZone: timezone });
50
+ }
51
+ const zonedDt = dt.setZone(timezone);
52
+ return zonedDt.toLocaleString(DateTime.DATE_MED);
53
+ }
54
+ catch (error) {
55
+ return new Date(isoString).toLocaleDateString('en-US', { timeZone: timezone });
56
+ }
57
+ }
58
+ /**
59
+ * Format a time-only ISO string in the specified timezone
60
+ * @param isoString - ISO 8601 datetime string
61
+ * @param timezone - IANA timezone identifier
62
+ * @returns Formatted time string (e.g., "2:30 PM EST")
63
+ */
64
+ export function formatTimeInTimezone(isoString, timezone) {
65
+ try {
66
+ const dt = DateTime.fromISO(isoString, { setZone: false });
67
+ if (!dt.isValid) {
68
+ return new Date(isoString).toLocaleTimeString('en-US', {
69
+ timeZone: timezone,
70
+ timeZoneName: 'short'
71
+ });
72
+ }
73
+ const zonedDt = dt.setZone(timezone);
74
+ return zonedDt.toLocaleString(DateTime.TIME_WITH_SHORT_OFFSET);
75
+ }
76
+ catch (error) {
77
+ return new Date(isoString).toLocaleTimeString('en-US', {
78
+ timeZone: timezone,
79
+ timeZoneName: 'short'
80
+ });
81
+ }
82
+ }
83
+ /**
84
+ * Get timezone abbreviation from IANA timezone identifier
85
+ * @param timezone - IANA timezone identifier (e.g., "America/New_York")
86
+ * @param datetime - Optional datetime to determine DST status
87
+ * @returns Timezone abbreviation (e.g., "EST" or "EDT")
88
+ */
89
+ export function getTimezoneAbbreviation(timezone, datetime) {
90
+ try {
91
+ const dt = datetime
92
+ ? DateTime.fromJSDate(datetime).setZone(timezone)
93
+ : DateTime.now().setZone(timezone);
94
+ return dt.offsetNameShort || dt.toFormat('ZZZZ');
95
+ }
96
+ catch (error) {
97
+ return timezone;
98
+ }
99
+ }
100
+ /**
101
+ * Detect timezone from coordinates using a simple heuristic
102
+ * This is a fallback when timezone is not provided by APIs
103
+ * @param latitude - Latitude
104
+ * @param longitude - Longitude
105
+ * @returns Best-guess IANA timezone identifier
106
+ */
107
+ export function guessTimezoneFromCoords(latitude, longitude) {
108
+ // This is a simplified heuristic - in practice, APIs usually provide timezone
109
+ // For production use, consider integrating a proper coordinate-to-timezone library
110
+ // like tz-lookup or @photostructure/tz-lookup for accurate global coverage
111
+ // Map to common US timezones for North America based on longitude
112
+ if (latitude >= 24 && latitude <= 50 && longitude >= -125 && longitude <= -66) {
113
+ if (longitude >= -75)
114
+ return 'America/New_York';
115
+ if (longitude >= -87)
116
+ return 'America/Chicago';
117
+ if (longitude >= -104)
118
+ return 'America/Denver';
119
+ if (longitude >= -125)
120
+ return 'America/Los_Angeles';
121
+ }
122
+ // For international locations, default to UTC instead of server timezone
123
+ // This provides predictable, unambiguous timestamps for all users
124
+ // Note: The previous fallback to Intl.DateTimeFormat().resolvedOptions().timeZone
125
+ // would return the server's local timezone, which is misleading for international queries
126
+ return 'UTC';
127
+ }
128
+ /**
129
+ * Format a time range with timezone context
130
+ * @param startTime - Start time ISO string
131
+ * @param endTime - End time ISO string
132
+ * @param timezone - IANA timezone identifier
133
+ * @returns Formatted range (e.g., "Nov 7, 2:00 PM - 5:00 PM EST")
134
+ */
135
+ export function formatTimeRangeInTimezone(startTime, endTime, timezone) {
136
+ try {
137
+ const start = DateTime.fromISO(startTime, { setZone: false }).setZone(timezone);
138
+ const end = DateTime.fromISO(endTime, { setZone: false }).setZone(timezone);
139
+ if (!start.isValid || !end.isValid) {
140
+ return `${formatInTimezone(startTime, timezone, 'short')} - ${formatInTimezone(endTime, timezone, 'short')}`;
141
+ }
142
+ // If same day, show: "Nov 7, 2:00 PM - 5:00 PM EST"
143
+ if (start.hasSame(end, 'day')) {
144
+ return `${start.toLocaleString(DateTime.DATE_MED)}, ${start.toLocaleString(DateTime.TIME_SIMPLE)} - ${end.toLocaleString(DateTime.TIME_SIMPLE)} ${start.offsetNameShort}`;
145
+ }
146
+ // Different days: "Nov 7, 2:00 PM - Nov 8, 5:00 PM EST"
147
+ return `${start.toLocaleString(DateTime.DATETIME_MED)} - ${end.toLocaleString(DateTime.DATETIME_MED)}`;
148
+ }
149
+ catch (error) {
150
+ return `${formatInTimezone(startTime, timezone, 'short')} - ${formatInTimezone(endTime, timezone, 'short')}`;
151
+ }
152
+ }
153
+ /**
154
+ * Check if a timezone is valid IANA timezone identifier
155
+ * @param timezone - Timezone string to validate
156
+ * @returns true if valid, false otherwise
157
+ */
158
+ export function isValidTimezone(timezone) {
159
+ try {
160
+ DateTime.now().setZone(timezone);
161
+ return DateTime.now().setZone(timezone).isValid;
162
+ }
163
+ catch {
164
+ return false;
165
+ }
166
+ }
167
+ //# sourceMappingURL=timezone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timezone.js","sourceRoot":"","sources":["../../src/utils/timezone.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Utility functions for unit conversion and formatting
3
+ */
4
+ import { QuantitativeValue } from '../types/noaa.js';
5
+ /**
6
+ * Extract numeric value from QuantitativeValue, handling null values
7
+ */
8
+ export declare function extractValue(qv: QuantitativeValue | undefined): number | null;
9
+ /**
10
+ * Convert Celsius to Fahrenheit
11
+ */
12
+ export declare function celsiusToFahrenheit(celsius: number): number;
13
+ /**
14
+ * Convert meters per second to miles per hour
15
+ */
16
+ export declare function mpsToMph(mps: number): number;
17
+ /**
18
+ * Convert kilometers per hour to miles per hour
19
+ */
20
+ export declare function kphToMph(kph: number): number;
21
+ /**
22
+ * Convert meters to miles
23
+ */
24
+ export declare function metersToMiles(meters: number): number;
25
+ /**
26
+ * Convert meters to feet
27
+ */
28
+ export declare function metersToFeet(meters: number): number;
29
+ /**
30
+ * Convert Pascals to inches of mercury
31
+ */
32
+ export declare function pascalsToInHg(pa: number): number;
33
+ /**
34
+ * Convert Pascals to millibars/hectopascals
35
+ */
36
+ export declare function pascalsToMb(pa: number): number;
37
+ /**
38
+ * Format temperature with unit
39
+ */
40
+ export declare function formatTemperature(qv: QuantitativeValue | undefined, preferFahrenheit?: boolean): string;
41
+ /**
42
+ * Format wind speed with unit
43
+ */
44
+ export declare function formatWindSpeed(qv: QuantitativeValue | undefined): string;
45
+ /**
46
+ * Format visibility with unit
47
+ */
48
+ export declare function formatVisibility(qv: QuantitativeValue | undefined): string;
49
+ /**
50
+ * Format pressure with unit
51
+ */
52
+ export declare function formatPressure(qv: QuantitativeValue | undefined): string;
53
+ /**
54
+ * Format a percentage value
55
+ */
56
+ export declare function formatPercentage(qv: QuantitativeValue | undefined): string;
57
+ /**
58
+ * Format wind direction from degrees to cardinal direction
59
+ */
60
+ export declare function formatWindDirection(qv: QuantitativeValue | undefined): string;
61
+ /**
62
+ * Format date/time in readable format
63
+ */
64
+ export declare function formatDateTime(isoString: string): string;
65
+ /**
66
+ * Format date only
67
+ */
68
+ export declare function formatDate(isoString: string): string;
69
+ //# sourceMappingURL=units.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"units.d.ts","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD;;GAEG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAK7E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,EAAE,gBAAgB,UAAO,GAAG,MAAM,CAcpG;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAazE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAO1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAOxE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAK1E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,iBAAiB,GAAG,SAAS,GAAG,MAAM,CAQ7E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAUxD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQpD"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Utility functions for unit conversion and formatting
3
+ */
4
+ /**
5
+ * Extract numeric value from QuantitativeValue, handling null values
6
+ */
7
+ export function extractValue(qv) {
8
+ if (!qv || qv.value === null || qv.value === undefined) {
9
+ return null;
10
+ }
11
+ return qv.value;
12
+ }
13
+ /**
14
+ * Convert Celsius to Fahrenheit
15
+ */
16
+ export function celsiusToFahrenheit(celsius) {
17
+ return (celsius * 9 / 5) + 32;
18
+ }
19
+ /**
20
+ * Convert meters per second to miles per hour
21
+ */
22
+ export function mpsToMph(mps) {
23
+ return mps * 2.23694;
24
+ }
25
+ /**
26
+ * Convert kilometers per hour to miles per hour
27
+ */
28
+ export function kphToMph(kph) {
29
+ return kph * 0.621371;
30
+ }
31
+ /**
32
+ * Convert meters to miles
33
+ */
34
+ export function metersToMiles(meters) {
35
+ return meters * 0.000621371;
36
+ }
37
+ /**
38
+ * Convert meters to feet
39
+ */
40
+ export function metersToFeet(meters) {
41
+ return meters * 3.28084;
42
+ }
43
+ /**
44
+ * Convert Pascals to inches of mercury
45
+ */
46
+ export function pascalsToInHg(pa) {
47
+ return pa * 0.0002953;
48
+ }
49
+ /**
50
+ * Convert Pascals to millibars/hectopascals
51
+ */
52
+ export function pascalsToMb(pa) {
53
+ return pa / 100;
54
+ }
55
+ /**
56
+ * Format temperature with unit
57
+ */
58
+ export function formatTemperature(qv, preferFahrenheit = true) {
59
+ const value = extractValue(qv);
60
+ if (value === null)
61
+ return 'N/A';
62
+ // NOAA returns temperature in Celsius in unitCode format "wmoUnit:degC"
63
+ if (qv?.unitCode?.includes('degC')) {
64
+ if (preferFahrenheit) {
65
+ return `${Math.round(celsiusToFahrenheit(value))}°F`;
66
+ }
67
+ return `${Math.round(value)}°C`;
68
+ }
69
+ // If already in Fahrenheit
70
+ return `${Math.round(value)}°F`;
71
+ }
72
+ /**
73
+ * Format wind speed with unit
74
+ */
75
+ export function formatWindSpeed(qv) {
76
+ const value = extractValue(qv);
77
+ if (value === null)
78
+ return 'Calm';
79
+ // Convert to mph if needed
80
+ let mph = value;
81
+ if (qv?.unitCode?.includes('km_h')) {
82
+ mph = kphToMph(value);
83
+ }
84
+ else if (qv?.unitCode?.includes('m_s')) {
85
+ mph = mpsToMph(value);
86
+ }
87
+ return `${Math.round(mph)} mph`;
88
+ }
89
+ /**
90
+ * Format visibility with unit
91
+ */
92
+ export function formatVisibility(qv) {
93
+ const value = extractValue(qv);
94
+ if (value === null)
95
+ return 'N/A';
96
+ // Convert meters to miles
97
+ const miles = metersToMiles(value);
98
+ return `${miles.toFixed(1)} miles`;
99
+ }
100
+ /**
101
+ * Format pressure with unit
102
+ */
103
+ export function formatPressure(qv) {
104
+ const value = extractValue(qv);
105
+ if (value === null)
106
+ return 'N/A';
107
+ // Convert Pascals to inHg
108
+ const inHg = pascalsToInHg(value);
109
+ return `${inHg.toFixed(2)} inHg`;
110
+ }
111
+ /**
112
+ * Format a percentage value
113
+ */
114
+ export function formatPercentage(qv) {
115
+ const value = extractValue(qv);
116
+ if (value === null)
117
+ return 'N/A';
118
+ return `${Math.round(value)}%`;
119
+ }
120
+ /**
121
+ * Format wind direction from degrees to cardinal direction
122
+ */
123
+ export function formatWindDirection(qv) {
124
+ const degrees = extractValue(qv);
125
+ if (degrees === null)
126
+ return 'Variable';
127
+ const directions = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
128
+ 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'];
129
+ const index = Math.round(degrees / 22.5) % 16;
130
+ return directions[index];
131
+ }
132
+ /**
133
+ * Format date/time in readable format
134
+ */
135
+ export function formatDateTime(isoString) {
136
+ const date = new Date(isoString);
137
+ return date.toLocaleString('en-US', {
138
+ weekday: 'short',
139
+ month: 'short',
140
+ day: 'numeric',
141
+ hour: 'numeric',
142
+ minute: '2-digit',
143
+ timeZoneName: 'short'
144
+ });
145
+ }
146
+ /**
147
+ * Format date only
148
+ */
149
+ export function formatDate(isoString) {
150
+ const date = new Date(isoString);
151
+ return date.toLocaleDateString('en-US', {
152
+ weekday: 'long',
153
+ month: 'long',
154
+ day: 'numeric',
155
+ year: 'numeric'
156
+ });
157
+ }
158
+ //# sourceMappingURL=units.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"units.js","sourceRoot":"","sources":["../../src/utils/units.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Input validation utilities for API parameters
3
+ * Provides runtime type checking and sanitization
4
+ */
5
+ /**
6
+ * Validate that latitude is a valid number within range
7
+ * @param lat - Latitude value to validate
8
+ * @throws {Error} If latitude is invalid
9
+ */
10
+ export declare function validateLatitude(lat: unknown): asserts lat is number;
11
+ /**
12
+ * Validate that longitude is a valid number within range
13
+ * @param lon - Longitude value to validate
14
+ * @throws {Error} If longitude is invalid
15
+ */
16
+ export declare function validateLongitude(lon: unknown): asserts lon is number;
17
+ /**
18
+ * Validate coordinate pair
19
+ * @param args - Arguments object potentially containing coordinates
20
+ * @returns Validated coordinates
21
+ * @throws {Error} If coordinates are invalid
22
+ */
23
+ export declare function validateCoordinates(args: unknown): {
24
+ latitude: number;
25
+ longitude: number;
26
+ };
27
+ /**
28
+ * Validate a positive integer within optional range
29
+ * @param value - Value to validate
30
+ * @param name - Parameter name for error messages
31
+ * @param min - Minimum allowed value (inclusive)
32
+ * @param max - Maximum allowed value (inclusive)
33
+ * @returns Validated number
34
+ * @throws {Error} If value is invalid
35
+ */
36
+ export declare function validatePositiveInteger(value: unknown, name: string, min?: number, max?: number): number;
37
+ /**
38
+ * Validate a boolean value
39
+ * @param value - Value to validate
40
+ * @param name - Parameter name for error messages
41
+ * @returns Validated boolean
42
+ * @throws {Error} If value is invalid
43
+ */
44
+ export declare function validateBoolean(value: unknown, name: string): boolean;
45
+ /**
46
+ * Validate a date string in ISO format
47
+ * @param value - Value to validate
48
+ * @param name - Parameter name for error messages
49
+ * @returns Validated date string
50
+ * @throws {Error} If value is invalid
51
+ */
52
+ export declare function validateDateString(value: unknown, name: string): string;
53
+ /**
54
+ * Validate forecast days parameter
55
+ * @param args - Arguments object potentially containing days parameter
56
+ * @returns Validated days value (defaults to 7 if not provided)
57
+ * @throws {Error} If days parameter is invalid
58
+ */
59
+ export declare function validateForecastDays(args: unknown): number;
60
+ /**
61
+ * Validate granularity parameter
62
+ * @param value - Value to validate
63
+ * @returns Validated granularity ('daily' or 'hourly')
64
+ * @throws {Error} If value is invalid
65
+ */
66
+ export declare function validateGranularity(value: unknown): 'daily' | 'hourly';
67
+ /**
68
+ * Validate optional boolean with default
69
+ * @param value - Value to validate
70
+ * @param name - Parameter name for error messages
71
+ * @param defaultValue - Default value if undefined
72
+ * @returns Validated boolean
73
+ * @throws {Error} If value is invalid
74
+ */
75
+ export declare function validateOptionalBoolean(value: unknown, name: string, defaultValue: boolean): boolean;
76
+ /**
77
+ * Validate historical weather parameters
78
+ * @param args - Arguments object
79
+ * @returns Validated parameters
80
+ * @throws {Error} If parameters are invalid
81
+ */
82
+ export declare function validateHistoricalWeatherParams(args: unknown): {
83
+ latitude: number;
84
+ longitude: number;
85
+ start_date: string;
86
+ end_date: string;
87
+ limit?: number;
88
+ };
89
+ //# sourceMappingURL=validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,MAAM,CAOpE;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,MAAM,CAOrE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAW1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,GAAG,GAAE,MAAU,EACf,GAAG,GAAE,MAAgC,GACpC,MAAM,CAWR;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKrE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAYvE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAY1D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,QAAQ,CActE;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,OAAO,GACpB,OAAO,CAKT;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,OAAO,GAAG;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAoCA"}