@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 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;
@@ -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";