@angelrove/forecast-utils 1.1.1

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 (64) hide show
  1. package/README.md +1046 -0
  2. package/dist/types/OpenMeteo/conf.d.ts +13 -0
  3. package/dist/types/OpenMeteo/current/fetchParams.d.ts +1 -0
  4. package/dist/types/OpenMeteo/current/transformer.d.ts +13 -0
  5. package/dist/types/OpenMeteo/current/useForecastCurrent.d.ts +14 -0
  6. package/dist/types/OpenMeteo/daily/fetchParams.d.ts +1 -0
  7. package/dist/types/OpenMeteo/daily/transformer.d.ts +9 -0
  8. package/dist/types/OpenMeteo/daily/useForecastDaily.d.ts +14 -0
  9. package/dist/types/OpenMeteo/helpers.d.ts +10 -0
  10. package/dist/types/OpenMeteo/hourly/fetchParams.d.ts +1 -0
  11. package/dist/types/OpenMeteo/hourly/useForecastHourly.d.ts +15 -0
  12. package/dist/types/OpenMeteo/weatherSymbol/lib/WeatherCodesEn.d.ts +43 -0
  13. package/dist/types/OpenMeteo/weatherSymbol/lib/WeatherCodesEs.d.ts +43 -0
  14. package/dist/types/OpenMeteo/weatherSymbol/lib/getWeatherCodeEntry.d.ts +7 -0
  15. package/dist/types/OpenMeteo/weatherSymbol/weatherSymbol.d.ts +13 -0
  16. package/dist/types/astronomy/moon/MoonCalc.d.ts +63 -0
  17. package/dist/types/astronomy/moon/parseBasicData.d.ts +8 -0
  18. package/dist/types/astronomy/sun/SunCalc.d.ts +73 -0
  19. package/dist/types/astronomy/sun/helpers.d.ts +0 -0
  20. package/dist/types/astronomy/timeZoneInfo.d.ts +10 -0
  21. package/dist/types/astronomy/timehelpers.d.ts +27 -0
  22. package/dist/types/astronomy/types.d.ts +43 -0
  23. package/dist/types/geolocation/getGeolocation.d.ts +12 -0
  24. package/dist/types/geolocation/lib/geolocation.d.ts +10 -0
  25. package/dist/types/geolocation/lib/geolocationCapacitor.d.ts +10 -0
  26. package/dist/types/geolocation/lib/reversegeocoding.d.ts +19 -0
  27. package/dist/types/index.d.ts +14 -0
  28. package/dist/types/utils/degreesToCompass.d.ts +11 -0
  29. package/dist/types/utils/warning.d.ts +46 -0
  30. package/dist/types/utils/wind/WindArrow.d.ts +32 -0
  31. package/dist/types/utils/wind/windArrowTx.d.ts +9 -0
  32. package/dist/types/utils/wind/windLevel.d.ts +29 -0
  33. package/package.json +40 -0
  34. package/src/OpenMeteo/conf.js +47 -0
  35. package/src/OpenMeteo/current/fetchParams.js +21 -0
  36. package/src/OpenMeteo/current/transformer.js +37 -0
  37. package/src/OpenMeteo/current/useForecastCurrent.js +34 -0
  38. package/src/OpenMeteo/daily/fetchParams.js +9 -0
  39. package/src/OpenMeteo/daily/transformer.js +21 -0
  40. package/src/OpenMeteo/daily/useForecastDaily.js +38 -0
  41. package/src/OpenMeteo/helpers.js +19 -0
  42. package/src/OpenMeteo/hourly/fetchParams.js +12 -0
  43. package/src/OpenMeteo/hourly/useForecastHourly.js +42 -0
  44. package/src/OpenMeteo/weatherSymbol/lib/WeatherCodesEn.js +89 -0
  45. package/src/OpenMeteo/weatherSymbol/lib/WeatherCodesEs.js +81 -0
  46. package/src/OpenMeteo/weatherSymbol/lib/getWeatherCodeEntry.js +12 -0
  47. package/src/OpenMeteo/weatherSymbol/weatherSymbol.js +60 -0
  48. package/src/astronomy/moon/MoonCalc.js +171 -0
  49. package/src/astronomy/moon/parseBasicData.js +38 -0
  50. package/src/astronomy/sun/SunCalc.js +167 -0
  51. package/src/astronomy/sun/helpers.js +0 -0
  52. package/src/astronomy/timeZoneInfo.js +89 -0
  53. package/src/astronomy/timehelpers.js +69 -0
  54. package/src/astronomy/types.js +30 -0
  55. package/src/geolocation/getGeolocation.js +49 -0
  56. package/src/geolocation/lib/geolocation.js +44 -0
  57. package/src/geolocation/lib/geolocationCapacitor.js +21 -0
  58. package/src/geolocation/lib/reversegeocoding.js +109 -0
  59. package/src/index.js +38 -0
  60. package/src/utils/degreesToCompass.js +51 -0
  61. package/src/utils/warning.js +130 -0
  62. package/src/utils/wind/WindArrow.jsx +53 -0
  63. package/src/utils/wind/windArrowTx.js +24 -0
  64. package/src/utils/wind/windLevel.js +49 -0
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@angelrove/forecast-utils",
3
+ "version": "1.1.1",
4
+ "author": "Jose Angel Romero Vegas",
5
+ "license": "MIT",
6
+ "description": "Utilidades para obtener datos de previsión meteorológica (Open-Meteo API) y de astronomía (SunCalc API).",
7
+ "homepage": "https://github.com/angelrove/OpenMeteoForecast",
8
+ "type": "module",
9
+ "scripts": {
10
+ "docs:md": "bunx jsdoc2md $(cat doc-files.txt) > README.md"
11
+ },
12
+ "types": "dist/types/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "import": "./src/index.js",
16
+ "require": "./src/index.js"
17
+ }
18
+ },
19
+ "files": ["src", "dist"],
20
+ "keywords": [
21
+ "forecast",
22
+ "weather",
23
+ "open-meteo",
24
+ "astronomy",
25
+ "react",
26
+ "hooks",
27
+ "JavaScript"
28
+ ],
29
+ "peerDependencies": {
30
+ "react": "^19.1.0",
31
+ "suncalc3": "^2.0.5",
32
+ "swr": "^2.3.3",
33
+ "@capacitor/geolocation": "^7.1.2"
34
+ },
35
+ "devDependencies": {
36
+ "@biomejs/biome": "1.9.4",
37
+ "jsdoc-to-markdown": "^9.1.1"
38
+ },
39
+ "dependencies": {}
40
+ }
@@ -0,0 +1,47 @@
1
+ const ApiInfo = {
2
+ host: "https://api.open-meteo.com/v1",
3
+ pathMain: "/forecast?timezone=auto&",
4
+ };
5
+
6
+ /**
7
+ * @param {string} url
8
+ */
9
+ export async function fetcher(url) {
10
+ devLog("OpemMeteo", url);
11
+ return fetch(url).then((res) => res.json());
12
+ }
13
+
14
+ /**
15
+ * Get path for OpenMeteo API
16
+ *
17
+ * @param {number} lat
18
+ * @param {number} lon
19
+ * @param {string} path
20
+ * @returns {string}
21
+ */
22
+ export function getPath(lat, lon, path) {
23
+ return (
24
+ ApiInfo.host +
25
+ ApiInfo.pathMain +
26
+ "latitude=" +
27
+ lat +
28
+ "&longitude=" +
29
+ lon +
30
+ "&" +
31
+ path
32
+ );
33
+ }
34
+
35
+ /**
36
+ * Console log for development
37
+ *
38
+ * @param {string} title
39
+ * @param {string} url
40
+ */
41
+ function devLog(title, url) {
42
+ // @ts-ignore
43
+ if (import.meta.env.MODE === "development") {
44
+ // console.log('%c> fetch [' + title + ']:', 'color:#9e9', url);
45
+ console.log("> fetch [" + title + "]:", url);
46
+ }
47
+ }
@@ -0,0 +1,21 @@
1
+ // hourlyParams
2
+
3
+ import { fetchParams as hourlyParams } from "../hourly/fetchParams.js";
4
+
5
+ export const fetchParams =
6
+ "current=" +
7
+ "temperature_2m," +
8
+ "apparent_temperature," +
9
+ "relative_humidity_2m," +
10
+ "weather_code," +
11
+ "wind_speed_10m," +
12
+ "wind_direction_10m," +
13
+ "precipitation&" +
14
+ "&forecast_days=2" +
15
+ "&daily=" +
16
+ "temperature_2m_max," +
17
+ "temperature_2m_min," +
18
+ "precipitation_sum," +
19
+ "showers_sum" +
20
+ "&" +
21
+ hourlyParams;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Transforms the OpenMeteo API data into a more usable format.
3
+ *
4
+ * @param {{current: any, daily: any, hourly: any, latitude: number, longitude: number}} data - The data object to transform.
5
+ * @returns {Object|null} - The transformed data object or null if the input is invalid.
6
+ */
7
+ export default function transformer(data) {
8
+ if (!data) return null;
9
+
10
+ const current = data.current;
11
+ const daily = data.daily;
12
+
13
+ return {
14
+ city: null,
15
+ country: null,
16
+ time: new Date().toTimeString(),
17
+ latitude: data.latitude,
18
+ longitude: data.longitude,
19
+ weather: {
20
+ weathercode: current.weather_code,
21
+ precipitation: current.precipitation,
22
+ temperature: current.temperature_2m,
23
+ feels_like: current.apparent_temperature,
24
+ humidity: current.relative_humidity_2m,
25
+ wind: {
26
+ speed: Math.round(current.wind_speed_10m),
27
+ deg: current.wind_direction_10m,
28
+ // gust: ,
29
+ },
30
+ tem_max: daily.temperature_2m_max[0],
31
+ tem_min: daily.temperature_2m_min[0],
32
+ precipitation_sum: daily.precipitation_sum,
33
+ showers_sum: daily.showers_sum,
34
+ hourly: data.hourly,
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @module OpenMeteo:current
3
+ */
4
+
5
+ import useSWR from "swr";
6
+ import { fetcher, getPath } from "../conf.js";
7
+ import { fetchParams } from "./fetchParams.js";
8
+ import transformer from "./transformer.js";
9
+
10
+ /**
11
+ * Custom hook to fetch current weather data from OpenMeteo API.
12
+ *
13
+ * @param {number} lat
14
+ * @param {number} lon
15
+ * @param {number} refreshIntervalMin
16
+ * @returns {{ data: any, apiUrl: string, isLoading: boolean, isError: any }}
17
+ */
18
+ export function useForecastCurrent(lat, lon, refreshIntervalMin = 0) {
19
+ if (!lat || !lon) {
20
+ throw new Error("useForecastCurrent: invalid coordinates");
21
+ }
22
+
23
+ const apiUrl = getPath(lat, lon, fetchParams);
24
+ const { data, error, isLoading } = useSWR(apiUrl, fetcher, {
25
+ refreshInterval: refreshIntervalMin * 60 * 1000,
26
+ });
27
+
28
+ return {
29
+ data: data ? transformer(data) : null,
30
+ apiUrl: apiUrl,
31
+ isLoading,
32
+ isError: error,
33
+ };
34
+ }
@@ -0,0 +1,9 @@
1
+ export const fetchParams =
2
+ "forecast_days=10&" +
3
+ "daily=" +
4
+ "weather_code," +
5
+ "temperature_2m_max," +
6
+ "temperature_2m_min," +
7
+ "precipitation_sum," +
8
+ "windspeed_10m_max," +
9
+ "winddirection_10m_dominant";
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Transforms the OpenMeteo API data into a more usable format.
3
+ *
4
+ * @param {{daily: any}} data - The data object to transform.
5
+ * @returns {Object|null} - The transformed data object or null if the input is invalid.
6
+ */
7
+ export default function transformer(data) {
8
+ if (!data) return null;
9
+
10
+ const newData = {
11
+ time: data.daily.time,
12
+ weathercode: data.daily.weather_code,
13
+ tempMax: data.daily.temperature_2m_max,
14
+ tempMin: data.daily.temperature_2m_min,
15
+ windDirection: data.daily.winddirection_10m_dominant,
16
+ windSpeed: data.daily.windspeed_10m_max,
17
+ precipitation_sum: data.daily.precipitation_sum,
18
+ };
19
+
20
+ return newData;
21
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @module OpenMeteo:daily
3
+ */
4
+
5
+ import useSWR from "swr";
6
+ import { fetcher, getPath } from "../conf.js";
7
+ import { fetchParams } from "./fetchParams.js";
8
+ import transformer from "./transformer.js";
9
+
10
+ /**
11
+ * Custom hook to fetch daily forecast (10 days) data from OpenMeteo API.
12
+ * https://api.open-meteo.com/v1/forecast?timezone=auto&latitude=36.6644363&longitude=-4.5108962&forecast_days=10&daily=weathercode
13
+ *
14
+ * @param {number} lat
15
+ * @param {number} lon
16
+ * @param {number} refreshIntervalMin
17
+ * @returns {{ data: any, isLoading: boolean, isError: any }}
18
+ */
19
+ export function useForecastDaily(lat, lon, refreshIntervalMin = 0) {
20
+ // Validate --
21
+ if (!lat || !lon) {
22
+ throw new Error("useForecastDaily: invalid coordinates");
23
+ }
24
+
25
+ // Fetch --
26
+ const apiUrl = getPath(lat, lon, fetchParams);
27
+ // console.log(apiUrl);
28
+ const { data, error, isLoading } = useSWR(apiUrl, fetcher, {
29
+ refreshInterval: refreshIntervalMin * 60 * 1000,
30
+ });
31
+
32
+ // Return --
33
+ return {
34
+ data: data ? transformer(data) : null,
35
+ isLoading,
36
+ isError: error,
37
+ };
38
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Get the start and end dates based on the number of days from today.
3
+ *
4
+ * @param {number} numDay
5
+ * @returns {{startDate: string, endDate: string}} - An object containing the start and end dates in YYYY-MM-DD format.
6
+ */
7
+ export function getDatesFromNumDays(numDay) {
8
+ // Dates: Today / End ---
9
+ const startDate = new Date();
10
+ startDate.setDate(startDate.getDate() + numDay);
11
+
12
+ const endDate = new Date();
13
+ endDate.setDate(endDate.getDate() + numDay + 1);
14
+
15
+ return {
16
+ startDate: startDate.toISOString().split("T")[0],
17
+ endDate: endDate.toISOString().split("T")[0],
18
+ };
19
+ }
@@ -0,0 +1,12 @@
1
+ export const fetchParams =
2
+ "hourly=" +
3
+ "weathercode," +
4
+ "temperature_2m," +
5
+ "windspeed_10m," +
6
+ "winddirection_10m," +
7
+ "relativehumidity_2m," +
8
+ "apparent_temperature," +
9
+ "precipitation," +
10
+ "freezing_level_height," +
11
+ "is_day";
12
+ // 'cloudcover,' +
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @module OpenMeteo:hourly
3
+ */
4
+
5
+ import useSWR from "swr";
6
+ import { fetcher, getPath } from "../conf.js";
7
+ import { getDatesFromNumDays } from "../helpers.js";
8
+ import { fetchParams } from "./fetchParams.js";
9
+
10
+ /**
11
+ * Custom hook to fetch hourly forecast data for a given location and number of days from OpenMeteo API.
12
+ *
13
+ * @param {{ latitude: number, longitude: number }} location
14
+ * @param {number} dayNum - Number of days from today: -1 = 24 hours, 0 = today, 1 = tomorrow, ...
15
+ * @returns {{ data: any, isLoading: boolean, isError: any }}
16
+ */
17
+ export function useForecastHourly(location, dayNum) {
18
+ if (!location.latitude || !location.longitude) {
19
+ throw new Error("useForecastHourly: invalid coordinates");
20
+ }
21
+
22
+ // Fetch ---
23
+ const dates = getDatesFromNumDays(dayNum);
24
+
25
+ let apiUrl =
26
+ "start_date=" +
27
+ dates.startDate +
28
+ "&" +
29
+ "end_date=" +
30
+ dates.endDate +
31
+ "&" +
32
+ fetchParams;
33
+ apiUrl = getPath(location.latitude, location.longitude, apiUrl);
34
+
35
+ const { data, error, isLoading } = useSWR(apiUrl, fetcher);
36
+
37
+ return {
38
+ data: data,
39
+ isLoading,
40
+ isError: error,
41
+ };
42
+ }
@@ -0,0 +1,89 @@
1
+ /**
2
+ * WMO Weather interpretation codes (WW)
3
+ *
4
+ * @link https://open-meteo.com/en/docs?hourly=temperature_2m,weather_code&daily=weather_code#weather_variable_documentation
5
+ * @link https://www.meteomatics.com/en/api/available-parameters/derived-weather-and-convenience-parameters/general-weather-state/
6
+ *
7
+ * Code Description
8
+ * 0 Clear sky
9
+ * 1, 2, 3 Mainly clear, partly cloudy, and overcast
10
+ * 45, 48 Fog and depositing rime fog
11
+ * 51, 53, 55 Drizzle: Light, moderate, and dense intensity
12
+ * 56, 57 Freezing Drizzle: Light and dense intensity
13
+ * 61, 63, 65 Rain: Slight, moderate and heavy intensity
14
+ * 66, 67 Freezing Rain: Light and heavy intensity
15
+ * 71, 73, 75 Snow fall: Slight, moderate, and heavy intensity
16
+ * 77 Snow grains
17
+ * 80, 81, 82 Rain showers: Slight, moderate, and violent
18
+ * 85, 86 Snow showers slight and heavy
19
+ * 95 * Thunderstorm: Slight or moderate
20
+ * 96, 99 * Thunderstorm with slight and heavy hail
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} WeatherCodeEntry
25
+ * @property {number} code - WMO Weather interpretation codes (WW).
26
+ * @property {string} icon - Icon name.
27
+ * @property {string} description - Description.
28
+ */
29
+
30
+ /** @type {WeatherCodeEntry[]} */
31
+ export const weatherCodes = [
32
+ { code: 0, icon: "0", description: "Clear sky" },
33
+ { code: 1, icon: "0", description: "Mainly clear" },
34
+
35
+ { code: 2, icon: "2", description: "Partly cloudy" },
36
+ { code: 3, icon: "3", description: "Overcast" },
37
+
38
+ // Niebla
39
+ { code: 45, icon: "45", description: "Fog" },
40
+ { code: 48, icon: "48", description: "Fog and depositing rime fog" },
41
+
42
+ // Llovizna
43
+ { code: 51, icon: "51", description: "Drizzle: Light" },
44
+ { code: 53, icon: "51", description: "Drizzle: moderate" },
45
+ { code: 55, icon: "51", description: "Drizzle: dense intensity" },
46
+
47
+ // Llovizna congelante
48
+ { code: 56, icon: "51", description: "Freezing Drizzle: Light" },
49
+ { code: 57, icon: "51", description: "Freezing Drizzle: dense intensity" },
50
+
51
+ // Lluvia
52
+ { code: 61, icon: "51", description: "Rain: Slight" },
53
+ { code: 63, icon: "63", description: "Rain: moderate and heavy intensity" },
54
+ { code: 65, icon: "65", description: "Rain: heavy intensity" },
55
+
56
+ // Lluvia helada
57
+ { code: 66, icon: "63", description: "Freezing Rain: Light" },
58
+ { code: 67, icon: "65", description: "Freezing Rain: Heavy intensity" },
59
+
60
+ // Chubascos de lluvia
61
+ { code: 80, icon: "80", description: "Snow fall: slight" },
62
+ { code: 81, icon: "81", description: "Snow fall: moderate" },
63
+ { code: 82, icon: "82", description: "Snow fall: heavy intensity" },
64
+
65
+ // Tormenta
66
+ { code: 95, icon: "95", description: "Snow grains" },
67
+ { code: 96, icon: "95", description: "Rain showers: slight" },
68
+ { code: 99, icon: "99", description: "Rain showers: moderate" },
69
+
70
+ // Nieve
71
+ { code: 71, icon: "71", description: "Rain showers: violent" },
72
+ { code: 73, icon: "71", description: "Snow showers slight" },
73
+ { code: 75, icon: "75", description: "Snow showers heavy" },
74
+
75
+ // Chubascos de nieve
76
+ { code: 85, icon: "85", description: "Thunderstorm: Slight or moderate" },
77
+ {
78
+ code: 86,
79
+ icon: "86",
80
+ description: "Thunderstorm with slight and heavy hail",
81
+ },
82
+
83
+ // Granizo
84
+ {
85
+ code: 77,
86
+ icon: "77",
87
+ description: "Thunderstorm with slight and heavy hail",
88
+ },
89
+ ];
@@ -0,0 +1,81 @@
1
+ /**
2
+ * WMO Weather interpretation codes (WW)
3
+ *
4
+ * @link https://open-meteo.com/en/docs?hourly=temperature_2m,weather_code&daily=weather_code#weather_variable_documentation
5
+ * @link https://www.meteomatics.com/en/api/available-parameters/derived-weather-and-convenience-parameters/general-weather-state/
6
+ *
7
+ * Code Description
8
+ * 0 Clear sky
9
+ * 1, 2, 3 Mainly clear, partly cloudy, and overcast
10
+ * 45, 48 Fog and depositing rime fog
11
+ * 51, 53, 55 Drizzle: Light, moderate, and dense intensity
12
+ * 56, 57 Freezing Drizzle: Light and dense intensity
13
+ * 61, 63, 65 Rain: Slight, moderate and heavy intensity
14
+ * 66, 67 Freezing Rain: Light and heavy intensity
15
+ * 71, 73, 75 Snow fall: Slight, moderate, and heavy intensity
16
+ * 77 Snow grains
17
+ * 80, 81, 82 Rain showers: Slight, moderate, and violent
18
+ * 85, 86 Snow showers slight and heavy
19
+ * 95 * Thunderstorm: Slight or moderate
20
+ * 96, 99 * Thunderstorm with slight and heavy hail
21
+ */
22
+
23
+ /**
24
+ * @typedef {Object} WeatherCodeEntry
25
+ * @property {number} code - WMO Weather interpretation codes (WW).
26
+ * @property {string} icon - Icon name.
27
+ * @property {string} description - Description.
28
+ */
29
+
30
+ /** @type {WeatherCodeEntry[]} */
31
+ export const weatherCodes = [
32
+ { code: 0, icon: "0", description: "Cielo despejado" },
33
+ { code: 1, icon: "0", description: "Principalmente despejado" },
34
+
35
+ { code: 2, icon: "2", description: "Parcialmente nublado" },
36
+ { code: 3, icon: "3", description: "Cubierto" },
37
+
38
+ // Niebla
39
+ { code: 45, icon: "45", description: "Niebla" },
40
+ { code: 48, icon: "48", description: "Niebla ligera con escarcha" },
41
+
42
+ // Llovizna
43
+ { code: 51, icon: "51", description: "Llovizna débil" },
44
+ { code: 53, icon: "51", description: "Llovizna moderada" },
45
+ { code: 55, icon: "51", description: "Llovizna densa" },
46
+
47
+ // Llovizna congelante
48
+ { code: 56, icon: "51", description: "Llovizna débil, congelándose" },
49
+ { code: 57, icon: "51", description: "Llovizna densa, congelándose" },
50
+
51
+ // Lluvia
52
+ { code: 61, icon: "51", description: "Lluvia ligera" },
53
+ { code: 63, icon: "63", description: "Lluvia moderada o fuerte" },
54
+ { code: 65, icon: "65", description: "Lluvia fuerte" },
55
+
56
+ // Lluvia helada
57
+ { code: 66, icon: "63", description: "Lluvia helada ligera" },
58
+ { code: 67, icon: "65", description: "Lluvia moderada o fuerte" },
59
+
60
+ // Chubascos de lluvia
61
+ { code: 80, icon: "80", description: "Chubascos débiles" },
62
+ { code: 81, icon: "81", description: "Chubascos moderados" },
63
+ { code: 82, icon: "82", description: "Chubascos fuertes" },
64
+
65
+ // Tormenta
66
+ { code: 95, icon: "95", description: "Tormenta" },
67
+ { code: 96, icon: "95", description: "Tormenta con algo de granizo" },
68
+ { code: 99, icon: "99", description: "Tormenta fuerte, con granizo" },
69
+
70
+ // Nieve
71
+ { code: 71, icon: "71", description: "Nieve ligera" },
72
+ { code: 73, icon: "71", description: "Nevada moderada" },
73
+ { code: 75, icon: "75", description: "Fuertes nevadas" },
74
+
75
+ // Chubascos de nieve
76
+ { code: 85, icon: "85", description: "Chubascos de nieve débil" },
77
+ { code: 86, icon: "86", description: "Chubascos de nieve fuertes" },
78
+
79
+ // Granizo
80
+ { code: 77, icon: "77", description: "Granizo" },
81
+ ];
@@ -0,0 +1,12 @@
1
+ // @ts-nocheck
2
+ import { weatherCodes } from "./WeatherCodesEs.js";
3
+
4
+ /**
5
+ * Returns weather code info o undefined if not found.
6
+ *
7
+ * @param {number} code - WMO Weather interpretation code.
8
+ * @returns {WeatherCodeEntry | undefined}
9
+ */
10
+ export function getWeatherCodeEntry(code) {
11
+ return weatherCodes.find((entry) => entry.code === code);
12
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @module OpenMeteo:weatherSymbol
3
+ */
4
+
5
+ import { getWeatherCodeEntry } from "./lib/getWeatherCodeEntry.js";
6
+
7
+ /**
8
+ * Get weather symbol and description based on the weather code.
9
+ *
10
+ * @param {any} code
11
+ * @param {number} [precipitation]
12
+ * @param {boolean} night
13
+ * @param {boolean} dark
14
+ * @returns {{ icon: string, description: string }}
15
+ */
16
+ export function weatherSymbol(
17
+ code,
18
+ precipitation = undefined,
19
+ night = false,
20
+ dark = false,
21
+ ) {
22
+ // Parse code ---
23
+ let msgPlus = "";
24
+ let theCode = code;
25
+ if (precipitation && precipitation > 0.8) {
26
+ if (theCode === 63) theCode = 65;
27
+ if (theCode === 95) msgPlus = " y lluvia fuerte";
28
+ }
29
+
30
+ // Get weather entry ---
31
+ const weatherCodeEntry = getWeatherCodeEntry(theCode);
32
+ if (!weatherCodeEntry) {
33
+ return {
34
+ icon: "ws/icon_error.webp",
35
+ description: "???",
36
+ };
37
+ }
38
+
39
+ // Icon file ---
40
+ const iconKey = weatherCodeEntry.icon;
41
+ let iconFile = "icon_" + iconKey;
42
+
43
+ // Night
44
+ const nightIcons = ["0", "2", "48", "80", "85"];
45
+ if (night && nightIcons.includes(iconKey)) {
46
+ iconFile = iconFile + "_night";
47
+ }
48
+
49
+ // Light / Dark
50
+ if (dark) {
51
+ iconFile = "dark/" + iconFile;
52
+ }
53
+
54
+ // Return ---
55
+ const ext = ".webp";
56
+ return {
57
+ icon: "ws/" + iconFile + ext,
58
+ description: weatherCodeEntry.description + msgPlus,
59
+ };
60
+ }