@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
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
import { useCallback as B, useEffect as q, useMemo as Q } from "react";
|
|
2
|
+
import { create as $ } from "zustand";
|
|
3
|
+
import { produce as z } from "immer";
|
|
4
|
+
function V(e, a) {
|
|
5
|
+
let t;
|
|
6
|
+
try {
|
|
7
|
+
t = e();
|
|
8
|
+
} catch {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
return {
|
|
12
|
+
getItem: (u) => {
|
|
13
|
+
var r;
|
|
14
|
+
const s = (d) => d === null ? null : JSON.parse(d, void 0), i = (r = t.getItem(u)) != null ? r : null;
|
|
15
|
+
return i instanceof Promise ? i.then(s) : s(i);
|
|
16
|
+
},
|
|
17
|
+
setItem: (u, r) => t.setItem(
|
|
18
|
+
u,
|
|
19
|
+
JSON.stringify(r, void 0)
|
|
20
|
+
),
|
|
21
|
+
removeItem: (u) => t.removeItem(u)
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const x = (e) => (a) => {
|
|
25
|
+
try {
|
|
26
|
+
const t = e(a);
|
|
27
|
+
return t instanceof Promise ? t : {
|
|
28
|
+
then(o) {
|
|
29
|
+
return x(o)(t);
|
|
30
|
+
},
|
|
31
|
+
catch(o) {
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
} catch (t) {
|
|
36
|
+
return {
|
|
37
|
+
then(o) {
|
|
38
|
+
return this;
|
|
39
|
+
},
|
|
40
|
+
catch(o) {
|
|
41
|
+
return x(o)(t);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}, X = (e, a) => (t, o, u) => {
|
|
46
|
+
let r = {
|
|
47
|
+
storage: V(() => localStorage),
|
|
48
|
+
partialize: (c) => c,
|
|
49
|
+
version: 0,
|
|
50
|
+
merge: (c, T) => ({
|
|
51
|
+
...T,
|
|
52
|
+
...c
|
|
53
|
+
}),
|
|
54
|
+
...a
|
|
55
|
+
}, s = !1;
|
|
56
|
+
const i = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
|
|
57
|
+
let m = r.storage;
|
|
58
|
+
if (!m)
|
|
59
|
+
return e(
|
|
60
|
+
(...c) => {
|
|
61
|
+
console.warn(
|
|
62
|
+
`[zustand persist middleware] Unable to update item '${r.name}', the given storage is currently unavailable.`
|
|
63
|
+
), t(...c);
|
|
64
|
+
},
|
|
65
|
+
o,
|
|
66
|
+
u
|
|
67
|
+
);
|
|
68
|
+
const g = () => {
|
|
69
|
+
const c = r.partialize({ ...o() });
|
|
70
|
+
return m.setItem(r.name, {
|
|
71
|
+
state: c,
|
|
72
|
+
version: r.version
|
|
73
|
+
});
|
|
74
|
+
}, p = u.setState;
|
|
75
|
+
u.setState = (c, T) => {
|
|
76
|
+
p(c, T), g();
|
|
77
|
+
};
|
|
78
|
+
const l = e(
|
|
79
|
+
(...c) => {
|
|
80
|
+
t(...c), g();
|
|
81
|
+
},
|
|
82
|
+
o,
|
|
83
|
+
u
|
|
84
|
+
);
|
|
85
|
+
u.getInitialState = () => l;
|
|
86
|
+
let v;
|
|
87
|
+
const L = () => {
|
|
88
|
+
var c, T;
|
|
89
|
+
if (!m) return;
|
|
90
|
+
s = !1, i.forEach((R) => {
|
|
91
|
+
var y;
|
|
92
|
+
return R((y = o()) != null ? y : l);
|
|
93
|
+
});
|
|
94
|
+
const N = ((T = r.onRehydrateStorage) == null ? void 0 : T.call(r, (c = o()) != null ? c : l)) || void 0;
|
|
95
|
+
return x(m.getItem.bind(m))(r.name).then((R) => {
|
|
96
|
+
if (R)
|
|
97
|
+
if (typeof R.version == "number" && R.version !== r.version) {
|
|
98
|
+
if (r.migrate) {
|
|
99
|
+
const y = r.migrate(
|
|
100
|
+
R.state,
|
|
101
|
+
R.version
|
|
102
|
+
);
|
|
103
|
+
return y instanceof Promise ? y.then((D) => [!0, D]) : [!0, y];
|
|
104
|
+
}
|
|
105
|
+
console.error(
|
|
106
|
+
"State loaded from storage couldn't be migrated since no migrate function was provided"
|
|
107
|
+
);
|
|
108
|
+
} else
|
|
109
|
+
return [!1, R.state];
|
|
110
|
+
return [!1, void 0];
|
|
111
|
+
}).then((R) => {
|
|
112
|
+
var y;
|
|
113
|
+
const [D, U] = R;
|
|
114
|
+
if (v = r.merge(
|
|
115
|
+
U,
|
|
116
|
+
(y = o()) != null ? y : l
|
|
117
|
+
), t(v, !0), D)
|
|
118
|
+
return g();
|
|
119
|
+
}).then(() => {
|
|
120
|
+
N == null || N(v, void 0), v = o(), s = !0, d.forEach((R) => R(v));
|
|
121
|
+
}).catch((R) => {
|
|
122
|
+
N == null || N(void 0, R);
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
return u.persist = {
|
|
126
|
+
setOptions: (c) => {
|
|
127
|
+
r = {
|
|
128
|
+
...r,
|
|
129
|
+
...c
|
|
130
|
+
}, c.storage && (m = c.storage);
|
|
131
|
+
},
|
|
132
|
+
clearStorage: () => {
|
|
133
|
+
m == null || m.removeItem(r.name);
|
|
134
|
+
},
|
|
135
|
+
getOptions: () => r,
|
|
136
|
+
rehydrate: () => L(),
|
|
137
|
+
hasHydrated: () => s,
|
|
138
|
+
onHydrate: (c) => (i.add(c), () => {
|
|
139
|
+
i.delete(c);
|
|
140
|
+
}),
|
|
141
|
+
onFinishHydration: (c) => (d.add(c), () => {
|
|
142
|
+
d.delete(c);
|
|
143
|
+
})
|
|
144
|
+
}, r.skipHydration || L(), v || l;
|
|
145
|
+
}, ee = X;
|
|
146
|
+
var I = /* @__PURE__ */ ((e) => (e.SUCCESS = "success", e.ERROR = "error", e.WARNING = "warning", e.INFO = "info", e))(I || {}), w = /* @__PURE__ */ ((e) => (e.NETWORK_ERROR = "network_error", e.API_ERROR = "api_error", e.DATA_ERROR = "data_error", e.UNKNOWN_ERROR = "unknown_error", e))(w || {}), k = /* @__PURE__ */ ((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))(k || {}), G = /* @__PURE__ */ ((e) => (e.TemperatureMax = "temperature_2m_max", e.TemperatureMin = "temperature_2m_min", e.Sunrise = "sunrise", e.Sunset = "sunset", e.DaylightDuration = "daylight_duration", e))(G || {}), E = /* @__PURE__ */ ((e) => (e.UNKNOWN = "Desconocido", e.LOW = "Bajo", e.MODERATE = "Moderado", e.HIGH = "Alto", e))(E || {}), h = /* @__PURE__ */ ((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 || {});
|
|
147
|
+
const te = "https://api.open-meteo.com/v1/forecast", A = {
|
|
148
|
+
/** Zona horaria por defecto para las consultas */
|
|
149
|
+
DEFAULT_TIMEZONE: "America/Sao_Paulo",
|
|
150
|
+
/** Parámetros meteorológicos por hora solicitados por defecto */
|
|
151
|
+
DEFAULT_HOURLY_PARAMS: [
|
|
152
|
+
k.Temperature,
|
|
153
|
+
k.WeatherCode
|
|
154
|
+
],
|
|
155
|
+
/** Parámetros meteorológicos diarios solicitados por defecto */
|
|
156
|
+
DEFAULT_DAILY_PARAMS: [
|
|
157
|
+
G.TemperatureMax,
|
|
158
|
+
G.TemperatureMin
|
|
159
|
+
],
|
|
160
|
+
/** Número de días pasados a incluir por defecto */
|
|
161
|
+
DEFAULT_PAST_DAYS: 0,
|
|
162
|
+
/** Número de días de pronóstico a incluir por defecto */
|
|
163
|
+
DEFAULT_FORECAST_DAYS: 7,
|
|
164
|
+
/** Duración del caché en milisegundos (10 minutos) */
|
|
165
|
+
DEFAULT_CACHE_DURATION: 10 * 60 * 1e3,
|
|
166
|
+
/** Timeout para las solicitudes HTTP en milisegundos */
|
|
167
|
+
REQUEST_TIMEOUT: 1e4
|
|
168
|
+
}, H = {
|
|
169
|
+
/** Descripciones de recomendaciones por nivel de riesgo UV */
|
|
170
|
+
DESCRIPTIONS: {
|
|
171
|
+
[E.UNKNOWN]: "No se puede determinar el riesgo de exposición",
|
|
172
|
+
[E.LOW]: "Puedes disfrutar de estar afuera con seguridad",
|
|
173
|
+
[E.MODERATE]: "Busca sombra durante las horas del mediodía. Ponte una remera, utiliza protector solar y un sombrero.",
|
|
174
|
+
[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."
|
|
175
|
+
}
|
|
176
|
+
}, re = {
|
|
177
|
+
// Cielo despejado y parcialmente nublado
|
|
178
|
+
0: h.clear_sky,
|
|
179
|
+
1: h.mainly_clear,
|
|
180
|
+
2: h.partly_cloudy,
|
|
181
|
+
3: h.overcast,
|
|
182
|
+
// Niebla
|
|
183
|
+
45: h.fog,
|
|
184
|
+
48: h.depositing_rime_fog,
|
|
185
|
+
// Llovizna
|
|
186
|
+
51: h.drizzle_light,
|
|
187
|
+
53: h.drizzle_moderate,
|
|
188
|
+
55: h.drizzle_dense,
|
|
189
|
+
56: h.freezing_drizzle_light,
|
|
190
|
+
57: h.freezing_drizzle_dense,
|
|
191
|
+
// Lluvia
|
|
192
|
+
61: h.rain_slight,
|
|
193
|
+
63: h.rain_moderate,
|
|
194
|
+
65: h.rain_heavy,
|
|
195
|
+
66: h.freezing_rain_light,
|
|
196
|
+
67: h.freezing_rain_heavy,
|
|
197
|
+
// Nieve
|
|
198
|
+
71: h.snowfall_slight,
|
|
199
|
+
73: h.snowfall_moderate,
|
|
200
|
+
75: h.snowfall_heavy,
|
|
201
|
+
77: h.snow_grains,
|
|
202
|
+
// Chubascos
|
|
203
|
+
80: h.rain_showers_slight,
|
|
204
|
+
81: h.rain_showers_moderate,
|
|
205
|
+
82: h.rain_showers_violent,
|
|
206
|
+
85: h.snow_showers_slight,
|
|
207
|
+
86: h.snow_showers_heavy,
|
|
208
|
+
// Tormentas
|
|
209
|
+
95: h.thunderstorm
|
|
210
|
+
}, f = {
|
|
211
|
+
// Tiempo
|
|
212
|
+
time: "iso8601",
|
|
213
|
+
hour: "iso8601",
|
|
214
|
+
// Temperatura
|
|
215
|
+
temperature_2m: "ºC",
|
|
216
|
+
temperature_2m_max: "ºC",
|
|
217
|
+
temperature_2m_min: "ºC",
|
|
218
|
+
dew_point_2m: "ºC",
|
|
219
|
+
apparent_temperature: "ºC",
|
|
220
|
+
// Humedad y precipitación
|
|
221
|
+
relative_humidity_2m: "%",
|
|
222
|
+
precipitation_probability: "%",
|
|
223
|
+
precipitation: "mm",
|
|
224
|
+
rain: "mm",
|
|
225
|
+
snowfall: "cm",
|
|
226
|
+
snow_depth: "m",
|
|
227
|
+
// Presión y viento
|
|
228
|
+
pressure_msl: "hPa",
|
|
229
|
+
wind_speed_10m: "km/h",
|
|
230
|
+
wind_direction_10m: "°",
|
|
231
|
+
// Cielo y visibilidad
|
|
232
|
+
cloud_cover: "%",
|
|
233
|
+
visibility: "km",
|
|
234
|
+
weather_code: "wmo code",
|
|
235
|
+
// Sol y UV
|
|
236
|
+
sunrise: "iso8601",
|
|
237
|
+
sunset: "iso8601",
|
|
238
|
+
daylight_duration: "h",
|
|
239
|
+
is_day: "flag"
|
|
240
|
+
};
|
|
241
|
+
class ae {
|
|
242
|
+
async fetchRaw({
|
|
243
|
+
latitude: a,
|
|
244
|
+
longitude: t,
|
|
245
|
+
hourly: o = A.DEFAULT_HOURLY_PARAMS,
|
|
246
|
+
daily: u = A.DEFAULT_DAILY_PARAMS,
|
|
247
|
+
timezone: r = A.DEFAULT_TIMEZONE,
|
|
248
|
+
past_days: s = A.DEFAULT_PAST_DAYS,
|
|
249
|
+
forecast_days: i = A.DEFAULT_FORECAST_DAYS
|
|
250
|
+
}) {
|
|
251
|
+
try {
|
|
252
|
+
const d = new URL(te), m = new URLSearchParams({
|
|
253
|
+
latitude: a.toString(),
|
|
254
|
+
longitude: t.toString(),
|
|
255
|
+
hourly: o.join(","),
|
|
256
|
+
daily: u.join(","),
|
|
257
|
+
timezone: r,
|
|
258
|
+
past_days: s.toString(),
|
|
259
|
+
forecast_days: i.toString()
|
|
260
|
+
});
|
|
261
|
+
d.search = m.toString();
|
|
262
|
+
const g = new AbortController(), p = setTimeout(() => g.abort(), A.REQUEST_TIMEOUT), l = await fetch(d.toString(), {
|
|
263
|
+
signal: g.signal
|
|
264
|
+
});
|
|
265
|
+
return clearTimeout(p), l.ok ? await l.json() : l.status >= 500 ? this.buildError({
|
|
266
|
+
error: "Debido a un problema en el servidor, no podemos obtener la información del clima.",
|
|
267
|
+
info: "Por favor, inténtalo de nuevo más tarde.",
|
|
268
|
+
status: l.status,
|
|
269
|
+
errorType: w.API_ERROR
|
|
270
|
+
}) : l.status >= 400 ? l.status === 408 ? this.buildError({
|
|
271
|
+
error: "La solicitud ha tardado demasiado tiempo en completarse.",
|
|
272
|
+
status: 408,
|
|
273
|
+
info: "Revisa tu conexión a internet e intenta de nuevo.",
|
|
274
|
+
type: I.WARNING,
|
|
275
|
+
errorType: w.NETWORK_ERROR
|
|
276
|
+
}) : this.buildError({
|
|
277
|
+
error: "No pudimos obtener la información del clima.",
|
|
278
|
+
info: "Verifica que la ubicación ingresada sea correcta e inténtalo de nuevo.",
|
|
279
|
+
status: l.status,
|
|
280
|
+
type: I.WARNING,
|
|
281
|
+
errorType: w.API_ERROR
|
|
282
|
+
}) : this.buildError({
|
|
283
|
+
error: "Ocurrió un error al obtener los datos del clima.",
|
|
284
|
+
status: l.status,
|
|
285
|
+
errorType: w.UNKNOWN_ERROR
|
|
286
|
+
});
|
|
287
|
+
} catch (d) {
|
|
288
|
+
return d instanceof DOMException && d.name === "AbortError" ? this.buildError({
|
|
289
|
+
error: "La solicitud ha tardado demasiado tiempo en completarse.",
|
|
290
|
+
status: 408,
|
|
291
|
+
info: "Revisa tu conexión a internet e intenta de nuevo.",
|
|
292
|
+
type: I.WARNING,
|
|
293
|
+
errorType: w.NETWORK_ERROR
|
|
294
|
+
}) : this.buildError({
|
|
295
|
+
error: "Ocurrió un error inesperado al obtener los datos meteorológicos.",
|
|
296
|
+
type: I.ERROR,
|
|
297
|
+
status: 0,
|
|
298
|
+
errorType: w.UNKNOWN_ERROR
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
buildError({ error: a, info: t, status: o, type: u, errorType: r }) {
|
|
303
|
+
return {
|
|
304
|
+
error: a || "Error desconocido.",
|
|
305
|
+
info: t,
|
|
306
|
+
status: o || 0,
|
|
307
|
+
type: u || I.ERROR,
|
|
308
|
+
errorType: r || w.UNKNOWN_ERROR
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
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];
|
|
313
|
+
class ie {
|
|
314
|
+
adapt(a, t, o) {
|
|
315
|
+
const u = t, r = u + 1, s = t + o + 1, i = this.processWeatherData(
|
|
316
|
+
a,
|
|
317
|
+
u,
|
|
318
|
+
r
|
|
319
|
+
), d = i.length > 0 ? i[0] : {};
|
|
320
|
+
return {
|
|
321
|
+
pastDay: this.processWeatherData(a, 0, u),
|
|
322
|
+
currentDay: d,
|
|
323
|
+
forecast: this.processWeatherData(a, r, s),
|
|
324
|
+
timezone: a.timezone,
|
|
325
|
+
latitude: a.latitude,
|
|
326
|
+
longitude: a.longitude
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
processWeatherData(a, t, o) {
|
|
330
|
+
const { daily: u } = a, r = [], {
|
|
331
|
+
time: s,
|
|
332
|
+
temperature_2m_max: i,
|
|
333
|
+
temperature_2m_min: d,
|
|
334
|
+
sunrise: m,
|
|
335
|
+
sunset: g,
|
|
336
|
+
daylight_duration: p
|
|
337
|
+
} = u;
|
|
338
|
+
for (let l = t; l < o; l++) {
|
|
339
|
+
const v = {};
|
|
340
|
+
s != null && s[l] && (v.day = { value: new Date(s[l]), unit: f.time }), (i == null ? void 0 : i[l]) !== void 0 && (v.temperatureMax = {
|
|
341
|
+
value: i[l],
|
|
342
|
+
unit: f.temperature_2m_max
|
|
343
|
+
}), (d == null ? void 0 : d[l]) !== void 0 && (v.temperatureMin = {
|
|
344
|
+
value: d[l],
|
|
345
|
+
unit: f.temperature_2m_min
|
|
346
|
+
}), m != null && m[l] && (v.sunrise = {
|
|
347
|
+
value: new Date(m[l]),
|
|
348
|
+
unit: f.sunrise
|
|
349
|
+
}), g != null && g[l] && (v.sunset = { value: new Date(g[l]), unit: f.sunset }), (p == null ? void 0 : p[l]) !== void 0 && (v.daylightDuration = {
|
|
350
|
+
value: p[l] / 3600,
|
|
351
|
+
unit: f.daylight_duration
|
|
352
|
+
}), v.hourly = this.getHourlyData(a, l), r.push(v);
|
|
353
|
+
}
|
|
354
|
+
return r;
|
|
355
|
+
}
|
|
356
|
+
getHourlyData(a, t) {
|
|
357
|
+
const { hourly: o, daily: u } = a, {
|
|
358
|
+
time: r,
|
|
359
|
+
temperature_2m: s,
|
|
360
|
+
relative_humidity_2m: i,
|
|
361
|
+
dew_point_2m: d,
|
|
362
|
+
apparent_temperature: m,
|
|
363
|
+
precipitation_probability: g,
|
|
364
|
+
precipitation: p,
|
|
365
|
+
rain: l,
|
|
366
|
+
snowfall: v,
|
|
367
|
+
snow_depth: L,
|
|
368
|
+
weather_code: c,
|
|
369
|
+
pressure_msl: T,
|
|
370
|
+
cloud_cover: N,
|
|
371
|
+
visibility: R,
|
|
372
|
+
wind_direction_10m: y,
|
|
373
|
+
wind_speed_10m: D,
|
|
374
|
+
uv_index: U,
|
|
375
|
+
is_day: C
|
|
376
|
+
} = o, b = a.timezone || "UTC";
|
|
377
|
+
let F, M, P;
|
|
378
|
+
const W = u.time[t];
|
|
379
|
+
if (typeof W == "string" && /^\d{4}-\d{2}-\d{2}$/.test(W)) {
|
|
380
|
+
const S = W.split("-").map(Number);
|
|
381
|
+
F = S[0], M = S[1] - 1, P = S[2];
|
|
382
|
+
} else {
|
|
383
|
+
const S = new Date(W);
|
|
384
|
+
F = Number(
|
|
385
|
+
S.toLocaleString("en", { timeZone: b, year: "numeric" })
|
|
386
|
+
), M = Number(S.toLocaleString("en", { timeZone: b, month: "numeric" })) - 1, P = Number(
|
|
387
|
+
S.toLocaleString("en", { timeZone: b, day: "numeric" })
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
const Y = [];
|
|
391
|
+
for (let S = 0; S < 24; S++) {
|
|
392
|
+
let K = -1;
|
|
393
|
+
for (let n = 0; n < r.length; n++) {
|
|
394
|
+
const _ = new Date(r[n]), O = Number(
|
|
395
|
+
_.toLocaleString("en", { timeZone: b, year: "numeric" })
|
|
396
|
+
), j = Number(
|
|
397
|
+
_.toLocaleString("en", { timeZone: b, month: "numeric" })
|
|
398
|
+
) - 1, Z = Number(
|
|
399
|
+
_.toLocaleString("en", { timeZone: b, day: "numeric" })
|
|
400
|
+
), J = Number(
|
|
401
|
+
_.toLocaleString("en", {
|
|
402
|
+
timeZone: b,
|
|
403
|
+
hour: "numeric",
|
|
404
|
+
hour12: !1
|
|
405
|
+
})
|
|
406
|
+
);
|
|
407
|
+
if (O === F && j === M && Z === P && J === S) {
|
|
408
|
+
K = n;
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (K !== -1) {
|
|
413
|
+
const n = K, _ = {};
|
|
414
|
+
if (_.hour = { value: new Date(r[n]), unit: f.hour }, (s == null ? void 0 : s[n]) !== void 0 && (_.temperature = {
|
|
415
|
+
value: s[n],
|
|
416
|
+
unit: f.temperature_2m
|
|
417
|
+
}), (i == null ? void 0 : i[n]) !== void 0 && (_.relativeHumidity = {
|
|
418
|
+
value: i[n],
|
|
419
|
+
unit: f.relative_humidity_2m
|
|
420
|
+
}), (d == null ? void 0 : d[n]) !== void 0 && (_.dewPoint = {
|
|
421
|
+
value: d[n],
|
|
422
|
+
unit: f.dew_point_2m
|
|
423
|
+
}), (m == null ? void 0 : m[n]) !== void 0 && (_.apparentTemperature = {
|
|
424
|
+
value: m[n],
|
|
425
|
+
unit: f.apparent_temperature
|
|
426
|
+
}), (g == null ? void 0 : g[n]) !== void 0 && (_.precipitationProbability = {
|
|
427
|
+
value: g[n],
|
|
428
|
+
unit: f.precipitation_probability
|
|
429
|
+
}), (p == null ? void 0 : p[n]) !== void 0 && (_.precipitation = {
|
|
430
|
+
value: p[n],
|
|
431
|
+
unit: f.precipitation
|
|
432
|
+
}), (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 }), (L == null ? void 0 : L[n]) !== void 0 && (_.snowDepth = { value: L[n], unit: f.snow_depth }), (c == null ? void 0 : c[n]) !== void 0) {
|
|
433
|
+
_.weatherCode = {
|
|
434
|
+
value: c[n],
|
|
435
|
+
unit: f.weather_code
|
|
436
|
+
};
|
|
437
|
+
const O = re[c[n]];
|
|
438
|
+
O && (_.weatherDescription = { value: O, unit: "text" });
|
|
439
|
+
}
|
|
440
|
+
if ((T == null ? void 0 : T[n]) !== void 0 && (_.pressureMsl = {
|
|
441
|
+
value: T[n],
|
|
442
|
+
unit: f.pressure_msl
|
|
443
|
+
}), (N == null ? void 0 : N[n]) !== void 0 && (_.cloudCover = {
|
|
444
|
+
value: N[n],
|
|
445
|
+
unit: f.cloud_cover
|
|
446
|
+
}), (R == null ? void 0 : R[n]) !== void 0 && (_.visibility = {
|
|
447
|
+
value: R[n] / 1e3,
|
|
448
|
+
unit: f.visibility
|
|
449
|
+
}), ((D == null ? void 0 : D[n]) !== void 0 || (y == null ? void 0 : y[n]) !== void 0) && (_.wind = {
|
|
450
|
+
speed: {
|
|
451
|
+
value: (D == null ? void 0 : D[n]) || 0,
|
|
452
|
+
unit: f.wind_speed_10m
|
|
453
|
+
}
|
|
454
|
+
}, (y == null ? void 0 : y[n]) !== void 0 && (_.wind.direction = {
|
|
455
|
+
value: y[n],
|
|
456
|
+
unit: f.wind_direction_10m
|
|
457
|
+
})), (U == null ? void 0 : U[n]) !== void 0) {
|
|
458
|
+
const O = U[n];
|
|
459
|
+
_.uv = {
|
|
460
|
+
value: O,
|
|
461
|
+
riskLevel: ne(O),
|
|
462
|
+
description: oe(O),
|
|
463
|
+
unit: "index"
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
(C == null ? void 0 : C[n]) !== void 0 && (_.isDay = { value: C[n], unit: f.is_day }), Y.push(_);
|
|
467
|
+
} else {
|
|
468
|
+
const n = new Date(
|
|
469
|
+
Date.UTC(F, M, P, S, 0, 0, 0)
|
|
470
|
+
);
|
|
471
|
+
Y.push({ hour: { value: n, unit: f.hour } });
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return Y;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
const se = async (e, a) => {
|
|
478
|
+
const {
|
|
479
|
+
latitude: t,
|
|
480
|
+
longitude: o,
|
|
481
|
+
hourly: u = A.DEFAULT_HOURLY_PARAMS,
|
|
482
|
+
daily: r = A.DEFAULT_DAILY_PARAMS,
|
|
483
|
+
timezone: s = A.DEFAULT_TIMEZONE,
|
|
484
|
+
past_days: i = A.DEFAULT_PAST_DAYS,
|
|
485
|
+
forecast_days: d = A.DEFAULT_FORECAST_DAYS
|
|
486
|
+
} = e, m = (a == null ? void 0 : a.client) || new ae(), g = (a == null ? void 0 : a.adapter) || new ie(), p = await m.fetchRaw({
|
|
487
|
+
latitude: t,
|
|
488
|
+
longitude: o,
|
|
489
|
+
hourly: u,
|
|
490
|
+
daily: r,
|
|
491
|
+
timezone: s,
|
|
492
|
+
past_days: i,
|
|
493
|
+
forecast_days: d
|
|
494
|
+
});
|
|
495
|
+
return "error" in p ? p : g.adapt(
|
|
496
|
+
p,
|
|
497
|
+
i || 0,
|
|
498
|
+
d || 0
|
|
499
|
+
);
|
|
500
|
+
};
|
|
501
|
+
let ue = (e) => se(e);
|
|
502
|
+
function le(e, a) {
|
|
503
|
+
return JSON.stringify(e) === JSON.stringify(a);
|
|
504
|
+
}
|
|
505
|
+
const de = $()(
|
|
506
|
+
ee(
|
|
507
|
+
(e, a) => ({
|
|
508
|
+
data: null,
|
|
509
|
+
loading: !1,
|
|
510
|
+
error: null,
|
|
511
|
+
autoRefresh: !0,
|
|
512
|
+
fetchParams: null,
|
|
513
|
+
// Variables de caché
|
|
514
|
+
lastFetchTime: null,
|
|
515
|
+
cacheDuration: 10 * 60 * 1e3,
|
|
516
|
+
// 10 minutos por defecto
|
|
517
|
+
/**
|
|
518
|
+
* Realiza la solicitud para obtener datos meteorológicos.
|
|
519
|
+
* Si los parámetros y el caché lo permiten, reutiliza los datos existentes.
|
|
520
|
+
* Si no, realiza una nueva consulta y actualiza el estado.
|
|
521
|
+
*/
|
|
522
|
+
fetchWeather: async (t) => {
|
|
523
|
+
const o = a(), u = Date.now();
|
|
524
|
+
if (!(o.fetchParams && le(o.fetchParams, t) && o.data && o.lastFetchTime !== null && u - o.lastFetchTime < o.cacheDuration)) {
|
|
525
|
+
e(
|
|
526
|
+
z((s) => {
|
|
527
|
+
s.loading = !0, s.error = null, s.fetchParams = t;
|
|
528
|
+
})
|
|
529
|
+
);
|
|
530
|
+
try {
|
|
531
|
+
const s = await ue(t);
|
|
532
|
+
if ("error" in s) {
|
|
533
|
+
e(
|
|
534
|
+
z((i) => {
|
|
535
|
+
i.error = s, i.loading = !1;
|
|
536
|
+
})
|
|
537
|
+
);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
e(
|
|
541
|
+
z((i) => {
|
|
542
|
+
i.data = s, i.loading = !1, i.error = null, i.lastFetchTime = Date.now();
|
|
543
|
+
})
|
|
544
|
+
);
|
|
545
|
+
} catch (s) {
|
|
546
|
+
const i = s instanceof Error ? s.message : "Error desconocido.";
|
|
547
|
+
e(
|
|
548
|
+
z((d) => {
|
|
549
|
+
d.error = {
|
|
550
|
+
error: i,
|
|
551
|
+
type: I.WARNING,
|
|
552
|
+
errorType: w.UNKNOWN_ERROR,
|
|
553
|
+
status: 0
|
|
554
|
+
}, d.loading = !1;
|
|
555
|
+
})
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
/** Indica si está en proceso de carga */
|
|
561
|
+
isLoading: () => a().loading,
|
|
562
|
+
/** Indica si se ha producido algún error */
|
|
563
|
+
hasError: () => a().error !== null,
|
|
564
|
+
/** Devuelve el error actual */
|
|
565
|
+
getError: () => a().error,
|
|
566
|
+
/** Limpia el error actual */
|
|
567
|
+
clearError: () => e(
|
|
568
|
+
z((t) => {
|
|
569
|
+
t.error = null;
|
|
570
|
+
})
|
|
571
|
+
),
|
|
572
|
+
/**
|
|
573
|
+
* Activa o desactiva la actualización automática.
|
|
574
|
+
* Si se activa, programa la actualización para la próxima medianoche local.
|
|
575
|
+
*/
|
|
576
|
+
setAutoRefresh: (t) => {
|
|
577
|
+
e({ autoRefresh: t }), t && a().scheduleAutoRefresh();
|
|
578
|
+
},
|
|
579
|
+
/**
|
|
580
|
+
* Programa una actualización automática de datos para la medianoche local
|
|
581
|
+
* en la zona horaria de los datos obtenidos, y vuelve a programarla
|
|
582
|
+
* cada vez que se llega a esa hora.
|
|
583
|
+
*/
|
|
584
|
+
scheduleAutoRefresh: () => {
|
|
585
|
+
const { data: t, fetchParams: o } = a();
|
|
586
|
+
if (!t || !t.timezone || !o) return;
|
|
587
|
+
const u = (/* @__PURE__ */ new Date()).toLocaleString("es-ES", {
|
|
588
|
+
timeZone: t.timezone
|
|
589
|
+
}), r = new Date(u), s = new Date(r);
|
|
590
|
+
s.setHours(24, 0, 0, 0);
|
|
591
|
+
const i = s.getTime() - r.getTime();
|
|
592
|
+
setTimeout(async () => {
|
|
593
|
+
await a().fetchWeather(o), a().scheduleAutoRefresh();
|
|
594
|
+
}, i);
|
|
595
|
+
},
|
|
596
|
+
/** Devuelve todos los datos meteorológicos */
|
|
597
|
+
getAllWeatherData: () => a().data,
|
|
598
|
+
getCurrentDayWeather: () => {
|
|
599
|
+
var t;
|
|
600
|
+
return ((t = a().data) == null ? void 0 : t.currentDay) || null;
|
|
601
|
+
},
|
|
602
|
+
getPastDayWeather: () => {
|
|
603
|
+
var t;
|
|
604
|
+
return ((t = a().data) == null ? void 0 : t.pastDay) || null;
|
|
605
|
+
},
|
|
606
|
+
getForecastWeather: () => {
|
|
607
|
+
var t;
|
|
608
|
+
return ((t = a().data) == null ? void 0 : t.forecast) || null;
|
|
609
|
+
},
|
|
610
|
+
/**
|
|
611
|
+
* Devuelve los datos meteorológicos de la hora actual.
|
|
612
|
+
* Busca la hora local actual en el array de horas del día.
|
|
613
|
+
*/
|
|
614
|
+
getCurrentHourWeather() {
|
|
615
|
+
var i, d;
|
|
616
|
+
const { data: t } = a();
|
|
617
|
+
if (!t) return null;
|
|
618
|
+
const o = t.timezone, u = (/* @__PURE__ */ new Date()).toLocaleString("en", {
|
|
619
|
+
timeZone: o
|
|
620
|
+
}), r = new Date(u);
|
|
621
|
+
return ((d = (i = t.currentDay) == null ? void 0 : i.hourly) == null ? void 0 : d.find((m) => m.hour ? new Date(m.hour.value).getHours() === r.getHours() : null)) || null;
|
|
622
|
+
}
|
|
623
|
+
}),
|
|
624
|
+
{
|
|
625
|
+
name: "weather-store",
|
|
626
|
+
partialize: (e) => ({
|
|
627
|
+
data: e.data,
|
|
628
|
+
fetchParams: e.fetchParams,
|
|
629
|
+
lastFetchTime: e.lastFetchTime,
|
|
630
|
+
autoRefresh: e.autoRefresh
|
|
631
|
+
})
|
|
632
|
+
}
|
|
633
|
+
)
|
|
634
|
+
), _e = () => {
|
|
635
|
+
const e = de(), a = B(
|
|
636
|
+
async (o) => {
|
|
637
|
+
await e.fetchWeather(o);
|
|
638
|
+
},
|
|
639
|
+
[e.fetchWeather]
|
|
640
|
+
);
|
|
641
|
+
return q(() => {
|
|
642
|
+
e.autoRefresh && e.fetchParams && e.scheduleAutoRefresh();
|
|
643
|
+
}, [e.autoRefresh, e.fetchParams]), {
|
|
644
|
+
...Q(
|
|
645
|
+
() => {
|
|
646
|
+
var o, u, r;
|
|
647
|
+
return {
|
|
648
|
+
// Datos meteorológicos principales
|
|
649
|
+
data: e.data,
|
|
650
|
+
currentDay: ((o = e.data) == null ? void 0 : o.currentDay) || null,
|
|
651
|
+
pastDays: ((u = e.data) == null ? void 0 : u.pastDay) || null,
|
|
652
|
+
forecast: ((r = e.data) == null ? void 0 : r.forecast) || null,
|
|
653
|
+
currentHour: e.getCurrentHourWeather(),
|
|
654
|
+
// Estado
|
|
655
|
+
isLoading: e.loading,
|
|
656
|
+
error: e.error
|
|
657
|
+
};
|
|
658
|
+
},
|
|
659
|
+
[e.data, e.loading, e.error]
|
|
660
|
+
),
|
|
661
|
+
/** Acción para solicitar datos meteorológicos */
|
|
662
|
+
fetchWeather: a,
|
|
663
|
+
/** Activa o desactiva la actualización automática */
|
|
664
|
+
setAutoRefresh: e.setAutoRefresh,
|
|
665
|
+
/** Limpia el error actual */
|
|
666
|
+
clearError: e.clearError
|
|
667
|
+
};
|
|
668
|
+
};
|
|
669
|
+
export {
|
|
670
|
+
se as fetchWeather,
|
|
671
|
+
_e as useWeather,
|
|
672
|
+
de as useWeatherStore
|
|
673
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { WeatherData } from "../../types/apiTypes";
|
|
2
|
+
import { StructureWeatherData } from "../../types/weatherTypes";
|
|
3
|
+
export interface IWeatherAdapter {
|
|
4
|
+
adapt(raw: WeatherData, pastDays: number, forecastDays: number): StructureWeatherData;
|
|
5
|
+
}
|
|
6
|
+
export declare class OpenMeteoAdapter implements IWeatherAdapter {
|
|
7
|
+
adapt(raw: WeatherData, pastDays: number, forecastDays: number): StructureWeatherData;
|
|
8
|
+
private processWeatherData;
|
|
9
|
+
private getHourlyData;
|
|
10
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FetchWeatherProps, FetchError } from "../../types/weatherTypes";
|
|
2
|
+
import { WeatherData } from "../../types/apiTypes";
|
|
3
|
+
export interface IWeatherApiClient {
|
|
4
|
+
fetchRaw(params: FetchWeatherProps): Promise<WeatherData | FetchError>;
|
|
5
|
+
}
|
|
6
|
+
export declare class OpenMeteoClient implements IWeatherApiClient {
|
|
7
|
+
fetchRaw({ latitude, longitude, hourly, daily, timezone, past_days, forecast_days, }: FetchWeatherProps): Promise<WeatherData | FetchError>;
|
|
8
|
+
private buildError;
|
|
9
|
+
}
|