@i-giann/open-meteo-wrapper 1.0.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 +148 -0
- package/dist/hooks/useWeather.d.ts +22 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.esm.js +673 -0
- package/dist/services/adapters/OpenMeteoAdapter.d.ts +10 -0
- package/dist/services/api/OpenMeteoClient.d.ts +9 -0
- package/dist/services/index.d.ts +3 -0
- package/dist/services/weatherService.d.ts +24 -0
- package/dist/store/useWeatherStore.d.ts +66 -0
- package/dist/types/apiTypes.d.ts +23 -0
- package/dist/types/weatherTypes.d.ts +162 -0
- package/dist/utils/constants.d.ts +87 -0
- package/dist/utils/utils.d.ts +13 -0
- package/package.json +91 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Giann Iacono
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# @i-giann/open-meteo-wrapper
|
|
2
|
+
|
|
3
|
+
Un wrapper completo para la API de Open-Meteo que proporciona hooks de React y servicios reutilizables para obtener datos meteorológicos.
|
|
4
|
+
|
|
5
|
+
## 🌟 Características
|
|
6
|
+
|
|
7
|
+
- ✅ **Hook de React optimizado** con caché automático
|
|
8
|
+
- ✅ **Servicio puro** sin dependencias de React
|
|
9
|
+
- ✅ **TypeScript completo** con tipos seguros
|
|
10
|
+
- ✅ **Caché inteligente** para optimizar las llamadas a la API
|
|
11
|
+
- ✅ **Manejo de errores robusto**
|
|
12
|
+
- ✅ **Auto-refresh programable**
|
|
13
|
+
- ✅ **Zero configuración** - funciona out-of-the-box
|
|
14
|
+
|
|
15
|
+
## 📦 Instalación
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @i-giann/open-meteo-wrapper
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 🚀 Uso Rápido
|
|
22
|
+
|
|
23
|
+
### Con React Hook
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { useWeather } from "@i-giann/open-meteo-wrapper";
|
|
27
|
+
|
|
28
|
+
function WeatherComponent() {
|
|
29
|
+
const { data, isLoading, error, fetchWeather } = useWeather();
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
fetchWeather({
|
|
33
|
+
latitude: 40.7128,
|
|
34
|
+
longitude: -74.006,
|
|
35
|
+
hourly: ["temperature_2m", "weather_code"],
|
|
36
|
+
daily: ["temperature_2m_max", "temperature_2m_min"],
|
|
37
|
+
});
|
|
38
|
+
}, []);
|
|
39
|
+
|
|
40
|
+
if (isLoading) return <div>Cargando...</div>;
|
|
41
|
+
if (error) return <div>Error: {error.error}</div>;
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div>
|
|
45
|
+
<h1>Clima Actual</h1>
|
|
46
|
+
<p>Temperatura: {data?.currentDay?.temperatureMax?.value}°C</p>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Con Servicio Puro
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { fetchWeather } from "@i-giann/open-meteo-wrapper";
|
|
56
|
+
|
|
57
|
+
async function getWeatherData() {
|
|
58
|
+
const result = await fetchWeather({
|
|
59
|
+
latitude: 40.7128,
|
|
60
|
+
longitude: -74.006,
|
|
61
|
+
hourly: ["temperature_2m", "relative_humidity_2m"],
|
|
62
|
+
daily: ["temperature_2m_max", "temperature_2m_min"],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if ("error" in result) {
|
|
66
|
+
console.error("Error:", result.error);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log("Datos meteorológicos:", result);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 📋 API Reference
|
|
75
|
+
|
|
76
|
+
### useWeather Hook
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const {
|
|
80
|
+
data, // Datos meteorológicos estructurados
|
|
81
|
+
currentDay, // Datos del día actual
|
|
82
|
+
pastDays, // Datos de días pasados
|
|
83
|
+
forecast, // Pronóstico futuro
|
|
84
|
+
currentHour, // Datos de la hora actual
|
|
85
|
+
isLoading, // Estado de carga
|
|
86
|
+
error, // Error si existe
|
|
87
|
+
fetchWeather, // Función para obtener datos
|
|
88
|
+
setAutoRefresh, // Configurar auto-refresh
|
|
89
|
+
clearError, // Limpiar errores
|
|
90
|
+
} = useWeather();
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### fetchWeather Service
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const result = await fetchWeather({
|
|
97
|
+
latitude: number, // Latitud (requerido)
|
|
98
|
+
longitude: number, // Longitud (requerido)
|
|
99
|
+
hourly?: HourlyParams[], // Parámetros por hora
|
|
100
|
+
daily?: DailyParams[], // Parámetros diarios
|
|
101
|
+
timezone?: string, // Zona horaria
|
|
102
|
+
past_days?: number, // Días pasados
|
|
103
|
+
forecast_days?: number // Días de pronóstico
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 🎯 Parámetros Disponibles
|
|
108
|
+
|
|
109
|
+
### Parámetros Horarios (HourlyParams)
|
|
110
|
+
|
|
111
|
+
- `temperature_2m` - Temperatura a 2m
|
|
112
|
+
- `relative_humidity_2m` - Humedad relativa
|
|
113
|
+
- `weather_code` - Código meteorológico WMO
|
|
114
|
+
- `wind_speed_10m` - Velocidad del viento
|
|
115
|
+
- `precipitation` - Precipitación
|
|
116
|
+
- Y muchos más...
|
|
117
|
+
|
|
118
|
+
### Parámetros Diarios (DailyParams)
|
|
119
|
+
|
|
120
|
+
- `temperature_2m_max` - Temperatura máxima
|
|
121
|
+
- `temperature_2m_min` - Temperatura mínima
|
|
122
|
+
- `sunrise` - Hora de salida del sol
|
|
123
|
+
- `sunset` - Hora de puesta del sol
|
|
124
|
+
|
|
125
|
+
## 🔧 Configuración Avanzada
|
|
126
|
+
|
|
127
|
+
### Auto-refresh
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
const { setAutoRefresh } = useWeather();
|
|
131
|
+
setAutoRefresh(true); // Actualización automática a medianoche
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Caché personalizado
|
|
135
|
+
|
|
136
|
+
El hook incluye caché inteligente de 10 minutos por defecto.
|
|
137
|
+
|
|
138
|
+
## 🌍 Ejemplos Completos
|
|
139
|
+
|
|
140
|
+
Visita la carpeta `docs/` para ejemplos completos y casos de uso avanzados.
|
|
141
|
+
|
|
142
|
+
## 📄 Licencia
|
|
143
|
+
|
|
144
|
+
MIT
|
|
145
|
+
|
|
146
|
+
## 🤝 Contribuciones
|
|
147
|
+
|
|
148
|
+
¡Las contribuciones son bienvenidas! Por favor, abre un issue o pull request.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FetchWeatherProps } from "../types/weatherTypes";
|
|
2
|
+
/**
|
|
3
|
+
* Hook personalizado para el manejo de los datos meteorológicos.
|
|
4
|
+
* Proporciona una interfaz React con memoización y acciones del store.
|
|
5
|
+
*
|
|
6
|
+
* @returns {object} Datos meteorológicos, estado y acciones.
|
|
7
|
+
*/
|
|
8
|
+
export declare const useWeather: () => {
|
|
9
|
+
/** Acción para solicitar datos meteorológicos */
|
|
10
|
+
fetchWeather: (params: FetchWeatherProps) => Promise<void>;
|
|
11
|
+
/** Activa o desactiva la actualización automática */
|
|
12
|
+
setAutoRefresh: (value: boolean) => void;
|
|
13
|
+
/** Limpia el error actual */
|
|
14
|
+
clearError: () => void;
|
|
15
|
+
data: import("..").StructureWeatherData | null;
|
|
16
|
+
currentDay: import("..").DailyWeatherData | null;
|
|
17
|
+
pastDays: import("..").DailyWeatherData[] | null;
|
|
18
|
+
forecast: import("..").DailyWeatherData[] | null;
|
|
19
|
+
currentHour: import("..").HourlyWeatherData | null;
|
|
20
|
+
isLoading: boolean;
|
|
21
|
+
error: import("..").FetchError | null;
|
|
22
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x=require("react"),$=require("zustand"),z=require("immer");function V(e,a){let t;try{t=e()}catch{return}return{getItem:u=>{var r;const s=c=>c===null?null:JSON.parse(c,void 0),i=(r=t.getItem(u))!=null?r:null;return i instanceof Promise?i.then(s):s(i)},setItem:(u,r)=>t.setItem(u,JSON.stringify(r,void 0)),removeItem:u=>t.removeItem(u)}}const k=e=>a=>{try{const t=e(a);return t instanceof Promise?t:{then(o){return k(o)(t)},catch(o){return this}}}catch(t){return{then(o){return this},catch(o){return k(o)(t)}}}},X=(e,a)=>(t,o,u)=>{let r={storage:V(()=>localStorage),partialize:d=>d,version:0,merge:(d,T)=>({...T,...d}),...a},s=!1;const i=new Set,c=new Set;let m=r.storage;if(!m)return e((...d)=>{console.warn(`[zustand persist middleware] Unable to update item '${r.name}', the given storage is currently unavailable.`),t(...d)},o,u);const g=()=>{const d=r.partialize({...o()});return m.setItem(r.name,{state:d,version:r.version})},p=u.setState;u.setState=(d,T)=>{p(d,T),g()};const l=e((...d)=>{t(...d),g()},o,u);u.getInitialState=()=>l;let v;const b=()=>{var d,T;if(!m)return;s=!1,i.forEach(R=>{var y;return R((y=o())!=null?y:l)});const N=((T=r.onRehydrateStorage)==null?void 0:T.call(r,(d=o())!=null?d:l))||void 0;return k(m.getItem.bind(m))(r.name).then(R=>{if(R)if(typeof R.version=="number"&&R.version!==r.version){if(r.migrate){const y=r.migrate(R.state,R.version);return y instanceof Promise?y.then(D=>[!0,D]):[!0,y]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return[!1,R.state];return[!1,void 0]}).then(R=>{var y;const[D,U]=R;if(v=r.merge(U,(y=o())!=null?y:l),t(v,!0),D)return g()}).then(()=>{N==null||N(v,void 0),v=o(),s=!0,c.forEach(R=>R(v))}).catch(R=>{N==null||N(void 0,R)})};return u.persist={setOptions:d=>{r={...r,...d},d.storage&&(m=d.storage)},clearStorage:()=>{m==null||m.removeItem(r.name)},getOptions:()=>r,rehydrate:()=>b(),hasHydrated:()=>s,onHydrate:d=>(i.add(d),()=>{i.delete(d)}),onFinishHydration:d=>(c.add(d),()=>{c.delete(d)})},r.skipHydration||b(),v||l},ee=X;var I=(e=>(e.SUCCESS="success",e.ERROR="error",e.WARNING="warning",e.INFO="info",e))(I||{}),w=(e=>(e.NETWORK_ERROR="network_error",e.API_ERROR="api_error",e.DATA_ERROR="data_error",e.UNKNOWN_ERROR="unknown_error",e))(w||{}),G=(e=>(e.Temperature="temperature_2m",e.RelativeHumidity="relative_humidity_2m",e.DewPoint="dew_point_2m",e.ApparentTemperature="apparent_temperature",e.PrecipitationProbability="precipitation_probability",e.Precipitation="precipitation",e.Rain="rain",e.Snowfall="snowfall",e.SnowDepth="snow_depth",e.WeatherCode="weather_code",e.PressureMsl="pressure_msl",e.CloudCover="cloud_cover",e.Visibility="visibility",e.WindSpeed="wind_speed_10m",e.WindDirection="wind_direction_10m",e.UvIndex="uv_index",e.IsDay="is_day",e))(G||{}),j=(e=>(e.TemperatureMax="temperature_2m_max",e.TemperatureMin="temperature_2m_min",e.Sunrise="sunrise",e.Sunset="sunset",e.DaylightDuration="daylight_duration",e))(j||{}),E=(e=>(e.UNKNOWN="Desconocido",e.LOW="Bajo",e.MODERATE="Moderado",e.HIGH="Alto",e))(E||{}),h=(e=>(e.clear_sky="Cielo despejado",e.mainly_clear="Mayormente despejado",e.partly_cloudy="Parcialmente nublado",e.overcast="Mayormente nublado",e.fog="Niebla",e.depositing_rime_fog="Niebla con escarcha",e.drizzle_light="Llovizna ligera",e.drizzle_moderate="Llovizna moderada",e.drizzle_dense="Llovizna densa",e.freezing_drizzle_light="Llovizna helada ligera",e.freezing_drizzle_dense="Llovizna helada densa",e.rain_slight="Lluvia ligera",e.rain_moderate="Lluvia moderada",e.rain_heavy="Lluvia intensa",e.freezing_rain_light="Lluvia helada ligera",e.freezing_rain_heavy="Lluvia helada intensa",e.snowfall_slight="Nevada ligera",e.snowfall_moderate="Nevada moderada",e.snowfall_heavy="Nevada intensa",e.snow_grains="Precipitación de granos de nieve",e.rain_showers_slight="Chubascos ligeros",e.rain_showers_moderate="Chubascos moderados",e.rain_showers_violent="Chubascos violentos",e.snow_showers_slight="Chubascos de nieve ligeros",e.snow_showers_heavy="Chubascos de nieve intensos",e.thunderstorm="Tormenta",e))(h||{});const te="https://api.open-meteo.com/v1/forecast",A={DEFAULT_TIMEZONE:"America/Sao_Paulo",DEFAULT_HOURLY_PARAMS:[G.Temperature,G.WeatherCode],DEFAULT_DAILY_PARAMS:[j.TemperatureMax,j.TemperatureMin],DEFAULT_PAST_DAYS:0,DEFAULT_FORECAST_DAYS:7,DEFAULT_CACHE_DURATION:10*60*1e3,REQUEST_TIMEOUT:1e4},H={DESCRIPTIONS:{[E.UNKNOWN]:"No se puede determinar el riesgo de exposición",[E.LOW]:"Puedes disfrutar de estar afuera con seguridad",[E.MODERATE]:"Busca sombra durante las horas del mediodía. Ponte una remera, utiliza protector solar y un sombrero.",[E.HIGH]:"Evita estar afuera durante las horas del mediodía. Asegúrate de buscar sombra. La remera, el protector solar y el sombrero son imprescindibles."}},re={0:h.clear_sky,1:h.mainly_clear,2:h.partly_cloudy,3:h.overcast,45:h.fog,48:h.depositing_rime_fog,51:h.drizzle_light,53:h.drizzle_moderate,55:h.drizzle_dense,56:h.freezing_drizzle_light,57:h.freezing_drizzle_dense,61:h.rain_slight,63:h.rain_moderate,65:h.rain_heavy,66:h.freezing_rain_light,67:h.freezing_rain_heavy,71:h.snowfall_slight,73:h.snowfall_moderate,75:h.snowfall_heavy,77:h.snow_grains,80:h.rain_showers_slight,81:h.rain_showers_moderate,82:h.rain_showers_violent,85:h.snow_showers_slight,86:h.snow_showers_heavy,95:h.thunderstorm},f={time:"iso8601",hour:"iso8601",temperature_2m:"ºC",temperature_2m_max:"ºC",temperature_2m_min:"ºC",dew_point_2m:"ºC",apparent_temperature:"ºC",relative_humidity_2m:"%",precipitation_probability:"%",precipitation:"mm",rain:"mm",snowfall:"cm",snow_depth:"m",pressure_msl:"hPa",wind_speed_10m:"km/h",wind_direction_10m:"°",cloud_cover:"%",visibility:"km",weather_code:"wmo code",sunrise:"iso8601",sunset:"iso8601",daylight_duration:"h",is_day:"flag"};class ae{async fetchRaw({latitude:a,longitude:t,hourly:o=A.DEFAULT_HOURLY_PARAMS,daily:u=A.DEFAULT_DAILY_PARAMS,timezone:r=A.DEFAULT_TIMEZONE,past_days:s=A.DEFAULT_PAST_DAYS,forecast_days:i=A.DEFAULT_FORECAST_DAYS}){try{const c=new URL(te),m=new URLSearchParams({latitude:a.toString(),longitude:t.toString(),hourly:o.join(","),daily:u.join(","),timezone:r,past_days:s.toString(),forecast_days:i.toString()});c.search=m.toString();const g=new AbortController,p=setTimeout(()=>g.abort(),A.REQUEST_TIMEOUT),l=await fetch(c.toString(),{signal:g.signal});return clearTimeout(p),l.ok?await l.json():l.status>=500?this.buildError({error:"Debido a un problema en el servidor, no podemos obtener la información del clima.",info:"Por favor, inténtalo de nuevo más tarde.",status:l.status,errorType:w.API_ERROR}):l.status>=400?l.status===408?this.buildError({error:"La solicitud ha tardado demasiado tiempo en completarse.",status:408,info:"Revisa tu conexión a internet e intenta de nuevo.",type:I.WARNING,errorType:w.NETWORK_ERROR}):this.buildError({error:"No pudimos obtener la información del clima.",info:"Verifica que la ubicación ingresada sea correcta e inténtalo de nuevo.",status:l.status,type:I.WARNING,errorType:w.API_ERROR}):this.buildError({error:"Ocurrió un error al obtener los datos del clima.",status:l.status,errorType:w.UNKNOWN_ERROR})}catch(c){return c instanceof DOMException&&c.name==="AbortError"?this.buildError({error:"La solicitud ha tardado demasiado tiempo en completarse.",status:408,info:"Revisa tu conexión a internet e intenta de nuevo.",type:I.WARNING,errorType:w.NETWORK_ERROR}):this.buildError({error:"Ocurrió un error inesperado al obtener los datos meteorológicos.",type:I.ERROR,status:0,errorType:w.UNKNOWN_ERROR})}}buildError({error:a,info:t,status:o,type:u,errorType:r}){return{error:a||"Error desconocido.",info:t,status:o||0,type:u||I.ERROR,errorType:r||w.UNKNOWN_ERROR}}}const ne=e=>e<0?E.UNKNOWN:e<=2?E.LOW:e<=7?E.MODERATE:E.HIGH,oe=e=>e<0?H.DESCRIPTIONS[E.UNKNOWN]:e<=2?H.DESCRIPTIONS[E.LOW]:e<=7?H.DESCRIPTIONS[E.MODERATE]:H.DESCRIPTIONS[E.HIGH];class ie{adapt(a,t,o){const u=t,r=u+1,s=t+o+1,i=this.processWeatherData(a,u,r),c=i.length>0?i[0]:{};return{pastDay:this.processWeatherData(a,0,u),currentDay:c,forecast:this.processWeatherData(a,r,s),timezone:a.timezone,latitude:a.latitude,longitude:a.longitude}}processWeatherData(a,t,o){const{daily:u}=a,r=[],{time:s,temperature_2m_max:i,temperature_2m_min:c,sunrise:m,sunset:g,daylight_duration:p}=u;for(let l=t;l<o;l++){const v={};s!=null&&s[l]&&(v.day={value:new Date(s[l]),unit:f.time}),(i==null?void 0:i[l])!==void 0&&(v.temperatureMax={value:i[l],unit:f.temperature_2m_max}),(c==null?void 0:c[l])!==void 0&&(v.temperatureMin={value:c[l],unit:f.temperature_2m_min}),m!=null&&m[l]&&(v.sunrise={value:new Date(m[l]),unit:f.sunrise}),g!=null&&g[l]&&(v.sunset={value:new Date(g[l]),unit:f.sunset}),(p==null?void 0:p[l])!==void 0&&(v.daylightDuration={value:p[l]/3600,unit:f.daylight_duration}),v.hourly=this.getHourlyData(a,l),r.push(v)}return r}getHourlyData(a,t){const{hourly:o,daily:u}=a,{time:r,temperature_2m:s,relative_humidity_2m:i,dew_point_2m:c,apparent_temperature:m,precipitation_probability:g,precipitation:p,rain:l,snowfall:v,snow_depth:b,weather_code:d,pressure_msl:T,cloud_cover:N,visibility:R,wind_direction_10m:y,wind_speed_10m:D,uv_index:U,is_day:C}=o,L=a.timezone||"UTC";let F,M,P;const W=u.time[t];if(typeof W=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(W)){const S=W.split("-").map(Number);F=S[0],M=S[1]-1,P=S[2]}else{const S=new Date(W);F=Number(S.toLocaleString("en",{timeZone:L,year:"numeric"})),M=Number(S.toLocaleString("en",{timeZone:L,month:"numeric"}))-1,P=Number(S.toLocaleString("en",{timeZone:L,day:"numeric"}))}const Y=[];for(let S=0;S<24;S++){let K=-1;for(let n=0;n<r.length;n++){const _=new Date(r[n]),O=Number(_.toLocaleString("en",{timeZone:L,year:"numeric"})),J=Number(_.toLocaleString("en",{timeZone:L,month:"numeric"}))-1,B=Number(_.toLocaleString("en",{timeZone:L,day:"numeric"})),Q=Number(_.toLocaleString("en",{timeZone:L,hour:"numeric",hour12:!1}));if(O===F&&J===M&&B===P&&Q===S){K=n;break}}if(K!==-1){const n=K,_={};if(_.hour={value:new Date(r[n]),unit:f.hour},(s==null?void 0:s[n])!==void 0&&(_.temperature={value:s[n],unit:f.temperature_2m}),(i==null?void 0:i[n])!==void 0&&(_.relativeHumidity={value:i[n],unit:f.relative_humidity_2m}),(c==null?void 0:c[n])!==void 0&&(_.dewPoint={value:c[n],unit:f.dew_point_2m}),(m==null?void 0:m[n])!==void 0&&(_.apparentTemperature={value:m[n],unit:f.apparent_temperature}),(g==null?void 0:g[n])!==void 0&&(_.precipitationProbability={value:g[n],unit:f.precipitation_probability}),(p==null?void 0:p[n])!==void 0&&(_.precipitation={value:p[n],unit:f.precipitation}),(l==null?void 0:l[n])!==void 0&&(_.rain={value:l[n],unit:f.rain}),(v==null?void 0:v[n])!==void 0&&(_.snowfall={value:v[n],unit:f.snowfall}),(b==null?void 0:b[n])!==void 0&&(_.snowDepth={value:b[n],unit:f.snow_depth}),(d==null?void 0:d[n])!==void 0){_.weatherCode={value:d[n],unit:f.weather_code};const O=re[d[n]];O&&(_.weatherDescription={value:O,unit:"text"})}if((T==null?void 0:T[n])!==void 0&&(_.pressureMsl={value:T[n],unit:f.pressure_msl}),(N==null?void 0:N[n])!==void 0&&(_.cloudCover={value:N[n],unit:f.cloud_cover}),(R==null?void 0:R[n])!==void 0&&(_.visibility={value:R[n]/1e3,unit:f.visibility}),((D==null?void 0:D[n])!==void 0||(y==null?void 0:y[n])!==void 0)&&(_.wind={speed:{value:(D==null?void 0:D[n])||0,unit:f.wind_speed_10m}},(y==null?void 0:y[n])!==void 0&&(_.wind.direction={value:y[n],unit:f.wind_direction_10m})),(U==null?void 0:U[n])!==void 0){const O=U[n];_.uv={value:O,riskLevel:ne(O),description:oe(O),unit:"index"}}(C==null?void 0:C[n])!==void 0&&(_.isDay={value:C[n],unit:f.is_day}),Y.push(_)}else{const n=new Date(Date.UTC(F,M,P,S,0,0,0));Y.push({hour:{value:n,unit:f.hour}})}}return Y}}const Z=async(e,a)=>{const{latitude:t,longitude:o,hourly:u=A.DEFAULT_HOURLY_PARAMS,daily:r=A.DEFAULT_DAILY_PARAMS,timezone:s=A.DEFAULT_TIMEZONE,past_days:i=A.DEFAULT_PAST_DAYS,forecast_days:c=A.DEFAULT_FORECAST_DAYS}=e,m=(a==null?void 0:a.client)||new ae,g=(a==null?void 0:a.adapter)||new ie,p=await m.fetchRaw({latitude:t,longitude:o,hourly:u,daily:r,timezone:s,past_days:i,forecast_days:c});return"error"in p?p:g.adapt(p,i||0,c||0)};let se=e=>Z(e);function ue(e,a){return JSON.stringify(e)===JSON.stringify(a)}const q=$.create()(ee((e,a)=>({data:null,loading:!1,error:null,autoRefresh:!0,fetchParams:null,lastFetchTime:null,cacheDuration:10*60*1e3,fetchWeather:async t=>{const o=a(),u=Date.now();if(!(o.fetchParams&&ue(o.fetchParams,t)&&o.data&&o.lastFetchTime!==null&&u-o.lastFetchTime<o.cacheDuration)){e(z.produce(s=>{s.loading=!0,s.error=null,s.fetchParams=t}));try{const s=await se(t);if("error"in s){e(z.produce(i=>{i.error=s,i.loading=!1}));return}e(z.produce(i=>{i.data=s,i.loading=!1,i.error=null,i.lastFetchTime=Date.now()}))}catch(s){const i=s instanceof Error?s.message:"Error desconocido.";e(z.produce(c=>{c.error={error:i,type:I.WARNING,errorType:w.UNKNOWN_ERROR,status:0},c.loading=!1}))}}},isLoading:()=>a().loading,hasError:()=>a().error!==null,getError:()=>a().error,clearError:()=>e(z.produce(t=>{t.error=null})),setAutoRefresh:t=>{e({autoRefresh:t}),t&&a().scheduleAutoRefresh()},scheduleAutoRefresh:()=>{const{data:t,fetchParams:o}=a();if(!t||!t.timezone||!o)return;const u=new Date().toLocaleString("es-ES",{timeZone:t.timezone}),r=new Date(u),s=new Date(r);s.setHours(24,0,0,0);const i=s.getTime()-r.getTime();setTimeout(async()=>{await a().fetchWeather(o),a().scheduleAutoRefresh()},i)},getAllWeatherData:()=>a().data,getCurrentDayWeather:()=>{var t;return((t=a().data)==null?void 0:t.currentDay)||null},getPastDayWeather:()=>{var t;return((t=a().data)==null?void 0:t.pastDay)||null},getForecastWeather:()=>{var t;return((t=a().data)==null?void 0:t.forecast)||null},getCurrentHourWeather(){var i,c;const{data:t}=a();if(!t)return null;const o=t.timezone,u=new Date().toLocaleString("en",{timeZone:o}),r=new Date(u);return((c=(i=t.currentDay)==null?void 0:i.hourly)==null?void 0:c.find(m=>m.hour?new Date(m.hour.value).getHours()===r.getHours():null))||null}}),{name:"weather-store",partialize:e=>({data:e.data,fetchParams:e.fetchParams,lastFetchTime:e.lastFetchTime,autoRefresh:e.autoRefresh})})),le=()=>{const e=q(),a=x.useCallback(async o=>{await e.fetchWeather(o)},[e.fetchWeather]);return x.useEffect(()=>{e.autoRefresh&&e.fetchParams&&e.scheduleAutoRefresh()},[e.autoRefresh,e.fetchParams]),{...x.useMemo(()=>{var o,u,r;return{data:e.data,currentDay:((o=e.data)==null?void 0:o.currentDay)||null,pastDays:((u=e.data)==null?void 0:u.pastDay)||null,forecast:((r=e.data)==null?void 0:r.forecast)||null,currentHour:e.getCurrentHourWeather(),isLoading:e.loading,error:e.error}},[e.data,e.loading,e.error]),fetchWeather:a,setAutoRefresh:e.setAutoRefresh,clearError:e.clearError}};exports.fetchWeather=Z;exports.useWeather=le;exports.useWeatherStore=q;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module hooks/useWeather
|
|
3
|
+
* Este módulo contiene el hook personalizado `useWeather` que permite obtener datos meteorológicos.
|
|
4
|
+
*/
|
|
5
|
+
export { useWeather } from "./hooks/useWeather";
|
|
6
|
+
/**
|
|
7
|
+
* @module store/useWeatherStore
|
|
8
|
+
* Este módulo contiene el store de Zustand para gestionar el estado meteorológico.
|
|
9
|
+
*/
|
|
10
|
+
export { useWeatherStore } from "./store/useWeatherStore";
|
|
11
|
+
/**
|
|
12
|
+
* @module services/weatherService
|
|
13
|
+
* Este módulo contiene la función `fetchWeather` que permite obtener datos meteorológicos.
|
|
14
|
+
*/
|
|
15
|
+
export { fetchWeather } from "./services/weatherService";
|
|
16
|
+
/**
|
|
17
|
+
* @module types/weatherTypes
|
|
18
|
+
* Este módulo contiene las propiedades necesarias para realizar una solicitud de datos
|
|
19
|
+
* meteorológicos.
|
|
20
|
+
*/
|
|
21
|
+
export type { FetchWeatherProps, DailyParams, HourlyParams, StructureWeatherData, FetchError, DailyWeatherData, HourlyWeatherData, WeatherValue, DateValue, TextValue, WindData, UVData, UvRiskLevels, WeatherDescriptions, } from "./types/weatherTypes";
|