diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml
new file mode 100644
index 0000000000..3dab691546
--- /dev/null
+++ b/.github/workflows/codeql.yaml
@@ -0,0 +1,37 @@
+name: CodeQL
+
+on:
+ push:
+ branches: [develop, master]
+ pull_request:
+ branches: [develop]
+ schedule:
+ - cron: "0 4 * * 1"
+
+jobs:
+ analyze:
+ name: Analyze (${{ matrix.language }})
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [actions, javascript-typescript]
+
+ steps:
+ - uses: actions/checkout@v6
+
+ - uses: github/codeql-action/init@v4
+ with:
+ languages: ${{ matrix.language }}
+ queries: security-and-quality
+
+ - uses: github/codeql-action/autobuild@v4
+
+ - uses: github/codeql-action/analyze@v4
+ with:
+ category: "/language:${{ matrix.language }}"
diff --git a/.github/workflows/electron-rebuild.yaml b/.github/workflows/electron-rebuild.yaml
index e9cad3346c..dd30f538c7 100644
--- a/.github/workflows/electron-rebuild.yaml
+++ b/.github/workflows/electron-rebuild.yaml
@@ -1,5 +1,8 @@
name: "Electron Rebuild Testing"
+permissions:
+ contents: read
+
on: [pull_request]
jobs:
diff --git a/.github/workflows/enforce-pullrequest-rules.yaml b/.github/workflows/enforce-pullrequest-rules.yaml
index aa4d51beb9..aa3973cfbc 100644
--- a/.github/workflows/enforce-pullrequest-rules.yaml
+++ b/.github/workflows/enforce-pullrequest-rules.yaml
@@ -3,6 +3,9 @@
name: "Enforce Pull-Request Rules"
+permissions:
+ contents: read
+
on:
pull_request:
push:
diff --git a/cspell.config.json b/cspell.config.json
index 1fa1ba6873..69c2c43ca8 100644
--- a/cspell.config.json
+++ b/cspell.config.json
@@ -13,9 +13,12 @@
"armv",
"ashishtank",
"autoplay",
+ "avghumidity",
+ "avgtemp",
"Autorestart",
"beada",
"Behaviour",
+ "Beschreibung",
"Binney",
"bluemanos",
"bnitkin",
@@ -111,6 +114,7 @@
"flopp",
"fontawesome",
"fontface",
+ "forecastday",
"forecastweather",
"fortawesome",
"frameguard",
@@ -186,14 +190,18 @@
"luxon",
"lxsession",
"magicmirror",
+ "mapbox",
"martingron",
"marvai",
"mastermerge",
"matchtype",
"maxentries",
+ "maxtemp",
+ "maxwind",
"Meteo",
"michaelteeuw",
"michmich",
+ "mintemp",
"Midori",
"mirontoli",
"MISSINGLANG",
@@ -212,7 +220,9 @@
"NEWSFEED",
"newsfeedfetcher",
"newsfetcher",
+ "newyear",
"newsitems",
+ "nextdaysrelative",
"nfogal",
"njwilliams",
"nonrepeating",
@@ -239,8 +249,10 @@
"pmin",
"Português",
"PRECIP",
+ "precips",
"Problema",
"psieg",
+ "ptype",
"pubdate",
"radokristof",
"rajniszp",
@@ -255,12 +267,14 @@
"Rosso",
"Rothfusz",
"rrule",
+ "sameorigin",
"savvadam",
"sdetweil",
"searchstr",
"sendheaders",
"serveronly",
"sexualized",
+ "showend",
"Sitecode",
"skpanagiotis",
"SMHI",
@@ -295,8 +309,11 @@
"timeformat",
"titlereplacestr",
"titlesearchstr",
+ "TOCTOU",
"todaytemp",
"tomzt",
+ "totalprecip",
+ "totalsnow",
"trunc",
"ttlms",
"ukmetoffice",
@@ -317,6 +334,7 @@
"Vorberechnung",
"vppencilsharpener",
"Wallys",
+ "weatherapi",
"Weatherbit",
"weathercode",
"WEATHERDATA",
@@ -336,6 +354,7 @@
"Woolridge",
"worktree",
"Wsymb",
+ "xhvw",
"xlarge",
"xmark",
"xrandr",
diff --git a/defaultmodules/calendar/calendar.js b/defaultmodules/calendar/calendar.js
index cfc625431a..e70cbb852d 100644
--- a/defaultmodules/calendar/calendar.js
+++ b/defaultmodules/calendar/calendar.js
@@ -167,7 +167,7 @@ Module.register("calendar", {
this.selfUpdate();
},
- notificationReceived (notification, payload, sender) {
+ notificationReceived (notification, payload) {
if (notification === "FETCH_CALENDAR") {
this.sendSocketNotification(notification, { url: payload.url, id: this.identifier });
}
diff --git a/defaultmodules/calendar/calendarfetcher.js b/defaultmodules/calendar/calendarfetcher.js
index 557f99946c..809b924cf1 100644
--- a/defaultmodules/calendar/calendarfetcher.js
+++ b/defaultmodules/calendar/calendarfetcher.js
@@ -1,6 +1,5 @@
const ical = require("node-ical");
const Log = require("logger");
-const { Agent } = require("undici");
const CalendarFetcherUtils = require("./calendarfetcherutils");
const HTTPFetcher = require("#http_fetcher");
diff --git a/defaultmodules/calendar/calendarfetcherutils.js b/defaultmodules/calendar/calendarfetcherutils.js
index 7234514d72..437c081e28 100644
--- a/defaultmodules/calendar/calendarfetcherutils.js
+++ b/defaultmodules/calendar/calendarfetcherutils.js
@@ -62,7 +62,7 @@ const CalendarFetcherUtils = {
// Subtract 1 second so that events that start on the middle of the night will not repeat.
.subtract(1, "seconds");
- Object.entries(data).forEach(([key, event]) => {
+ Object.values(data).forEach((event) => {
if (event.type !== "VEVENT") {
return;
}
diff --git a/defaultmodules/compliments/compliments.js b/defaultmodules/compliments/compliments.js
index a20810a9c8..2ded7c191b 100644
--- a/defaultmodules/compliments/compliments.js
+++ b/defaultmodules/compliments/compliments.js
@@ -308,7 +308,7 @@ Module.register("compliments", {
},
// Override notification handler.
- notificationReceived (notification, payload, sender) {
+ notificationReceived (notification, payload) {
if (notification === "CURRENTWEATHER_TYPE") {
this.currentWeatherType = payload.type;
}
diff --git a/defaultmodules/newsfeed/newsfeed.js b/defaultmodules/newsfeed/newsfeed.js
index b24906962c..cbf1aefa9e 100644
--- a/defaultmodules/newsfeed/newsfeed.js
+++ b/defaultmodules/newsfeed/newsfeed.js
@@ -411,7 +411,7 @@ Module.register("newsfeed", {
}
},
- notificationReceived (notification, payload, sender) {
+ notificationReceived (notification) {
const before = this.activeItem;
if (notification === "MODULE_DOM_CREATED" && this.config.hideLoading) {
this.hide();
diff --git a/defaultmodules/newsfeed/newsfeedfetcher.js b/defaultmodules/newsfeed/newsfeedfetcher.js
index 12febd6a35..1a5f421ab8 100644
--- a/defaultmodules/newsfeed/newsfeedfetcher.js
+++ b/defaultmodules/newsfeed/newsfeedfetcher.js
@@ -40,7 +40,7 @@ class NewsfeedFetcher {
});
// Wire up HTTPFetcher events
- this.httpFetcher.on("response", (response) => this.#handleResponse(response));
+ this.httpFetcher.on("response", (response) => void this.#handleResponse(response));
this.httpFetcher.on("error", (errorInfo) => this.fetchFailedCallback(this, errorInfo));
}
@@ -67,7 +67,7 @@ class NewsfeedFetcher {
* Handles successful HTTP response
* @param {Response} response - The fetch Response object
*/
- #handleResponse (response) {
+ async #handleResponse (response) {
this.items = [];
const parser = new FeedMe();
@@ -106,11 +106,6 @@ class NewsfeedFetcher {
parser.on("end", () => this.broadcastItems());
- parser.on("error", (error) => {
- Log.error(`${this.url} - Feed parsing failed: ${error.message}`);
- this.fetchFailedCallback(this, this.#createParseError(`Feed parsing failed: ${error.message}`, error));
- });
-
parser.on("ttl", (minutes) => {
const ttlms = Math.min(minutes * 60 * 1000, 86400000);
if (ttlms > this.httpFetcher.reloadInterval) {
@@ -123,7 +118,7 @@ class NewsfeedFetcher {
const nodeStream = response.body instanceof stream.Readable
? response.body
: stream.Readable.fromWeb(response.body);
- nodeStream.pipe(iconv.decodeStream(this.encoding)).pipe(parser);
+ await stream.promises.pipeline(nodeStream, iconv.decodeStream(this.encoding), parser);
} catch (error) {
Log.error(`${this.url} - Stream processing failed: ${error.message}`);
this.fetchFailedCallback(this, this.#createParseError(`Stream processing failed: ${error.message}`, error));
diff --git a/defaultmodules/updatenotification/git_helper.js b/defaultmodules/updatenotification/git_helper.js
index 0444c9500c..bfc51e4809 100644
--- a/defaultmodules/updatenotification/git_helper.js
+++ b/defaultmodules/updatenotification/git_helper.js
@@ -1,5 +1,5 @@
const util = require("node:util");
-const exec = util.promisify(require("node:child_process").exec);
+const execFile = util.promisify(require("node:child_process").execFile);
const fs = require("node:fs");
const path = require("node:path");
const Log = require("logger");
@@ -14,14 +14,14 @@ class GitHelper {
return new RegExp(`s*([a-z,0-9]+[.][.][a-z,0-9]+) ${branch}`, "g");
}
- async execShell (command) {
- const { stdout = "", stderr = "" } = await exec(command);
+ async execGit (moduleFolder, ...args) {
+ const { stdout = "", stderr = "" } = await execFile("git", args, { cwd: moduleFolder });
return { stdout, stderr };
}
async isGitRepo (moduleFolder) {
- const { stderr } = await this.execShell(`cd ${moduleFolder} && git remote -v`);
+ const { stderr } = await this.execGit(moduleFolder, "remote", "-v");
if (stderr) {
Log.error(`Failed to fetch git data for ${moduleFolder}: ${stderr}`);
@@ -51,7 +51,7 @@ class GitHelper {
// Folder has .git and has at least one git remote, watch this folder
this.gitRepos.push({ module: moduleName, folder: moduleFolder });
}
- } catch (err) {
+ } catch {
// Error when directory .git doesn't exist or doesn't have any remotes
// This module is not managed with git, skip
}
@@ -69,7 +69,7 @@ class GitHelper {
if (repo.module === "MagicMirror") {
// the hash is only needed for the mm repo
- const { stderr, stdout } = await this.execShell(`cd ${repo.folder} && git rev-parse HEAD`);
+ const { stderr, stdout } = await this.execGit(repo.folder, "rev-parse", "HEAD");
if (stderr) {
Log.error(`Failed to get current commit hash for ${repo.module}: ${stderr}`);
@@ -78,7 +78,7 @@ class GitHelper {
gitInfo.hash = stdout;
}
- const { stderr, stdout } = await this.execShell(`cd ${repo.folder} && git status -sb`);
+ const { stderr, stdout } = await this.execGit(repo.folder, "status", "-sb");
if (stderr) {
Log.error(`Failed to get git status for ${repo.module}: ${stderr}`);
@@ -123,7 +123,7 @@ class GitHelper {
return gitInfo;
}
- const { stderr } = await this.execShell(`cd ${repo.folder} && git fetch -n --dry-run`);
+ const { stderr } = await this.execGit(repo.folder, "fetch", "-n", "--dry-run");
// example output:
// From https://github.com/MagicMirrorOrg/MagicMirror
@@ -140,7 +140,7 @@ class GitHelper {
// get behind with refs
try {
- const { stdout } = await this.execShell(`cd ${repo.folder} && git rev-list --ancestry-path --count ${refDiff}`);
+ const { stdout } = await this.execGit(repo.folder, "rev-list", "--ancestry-path", "--count", refDiff);
gitInfo.behind = parseInt(stdout);
// for MagicMirror-Repo and "master" branch avoid getting notified when no tag is in refDiff
@@ -148,14 +148,14 @@ class GitHelper {
if (gitInfo.behind > 0 && gitInfo.module === "MagicMirror" && gitInfo.current === "master") {
let tagList = "";
try {
- const { stdout } = await this.execShell(`cd ${repo.folder} && git ls-remote -q --tags --refs`);
+ const { stdout } = await this.execGit(repo.folder, "ls-remote", "-q", "--tags", "--refs");
tagList = stdout.trim();
} catch (err) {
Log.error(`Failed to get tag list for ${repo.module}: ${err}`);
}
// check if tag is between commits and only report behind > 0 if so
try {
- const { stdout } = await this.execShell(`cd ${repo.folder} && git rev-list --ancestry-path ${refDiff}`);
+ const { stdout } = await this.execGit(repo.folder, "rev-list", "--ancestry-path", refDiff);
let cnt = 0;
for (const ref of stdout.trim().split("\n")) {
if (tagList.includes(ref)) cnt++; // tag found
@@ -193,19 +193,15 @@ class GitHelper {
return this.gitResultList;
}
- async checkUpdates () {
- var updates = [];
+ checkUpdates () {
+ const updates = [];
- const allRepos = await this.gitResultList.map((module) => {
- return new Promise((resolve) => {
- if (module.behind > 0 && module.module !== "MagicMirror") {
- Log.info(`Update found for module: ${module.module}`);
- updates.push(module);
- }
- resolve(module);
- });
- });
- await Promise.all(allRepos);
+ for (const moduleInfo of this.gitResultList) {
+ if (moduleInfo.behind > 0 && moduleInfo.module !== "MagicMirror") {
+ Log.info(`Update found for module: ${moduleInfo.module}`);
+ updates.push(moduleInfo);
+ }
+ }
return updates;
}
diff --git a/defaultmodules/updatenotification/update_helper.js b/defaultmodules/updatenotification/update_helper.js
index 34bf289c41..7fcec31ff6 100644
--- a/defaultmodules/updatenotification/update_helper.js
+++ b/defaultmodules/updatenotification/update_helper.js
@@ -113,7 +113,7 @@ class Updater {
Log.info(`Updating ${module.name}...`);
return new Promise((resolve) => {
- Exec(Command, { cwd: modulePath, timeout: this.timeout }, (error, stdout, stderr) => {
+ Exec(Command, { cwd: modulePath, timeout: this.timeout }, (error, stdout) => {
if (error) {
Log.error(`exec error: ${error}`);
Result.error = true;
@@ -143,7 +143,7 @@ class Updater {
pm2Restart () {
Log.info("[PM2] restarting MagicMirror...");
const pm2 = require("pm2");
- pm2.restart(this.PM2Id, (err, proc) => {
+ pm2.restart(this.PM2Id, (err) => {
if (err) {
Log.error("[PM2] restart Error", err);
}
diff --git a/defaultmodules/weather/current.njk b/defaultmodules/weather/current.njk
index b75966d3b1..3e66d52706 100644
--- a/defaultmodules/weather/current.njk
+++ b/defaultmodules/weather/current.njk
@@ -38,7 +38,7 @@
{% if config.showUVIndex %}
- {{ current.uv_index }}
+ {{ current.uvIndex }}
{% endif %}
@@ -78,11 +78,11 @@
{% endif %}
- {% if config.showPrecipitationAmount and current.precipitationAmount %}
+ {% if config.showPrecipitationAmount and current.precipitationAmount is defined and current.precipitationAmount is not none %}
{{ "PRECIP_AMOUNT" | translate }} {{ current.precipitationAmount | unit("precip", current.precipitationUnits) }}
{% endif %}
- {% if config.showPrecipitationProbability and current.precipitationProbability %}
+ {% if config.showPrecipitationProbability and current.precipitationProbability is defined and current.precipitationProbability is not none %}
{{ "PRECIP_POP" | translate }} {{ current.precipitationProbability }}%
{% endif %}
diff --git a/defaultmodules/weather/forecast.njk b/defaultmodules/weather/forecast.njk
index 50c6bb53d8..1b28ed2d2f 100644
--- a/defaultmodules/weather/forecast.njk
+++ b/defaultmodules/weather/forecast.njk
@@ -31,7 +31,7 @@
{% endif %}
{% if config.showUVIndex %}
- {{ f.uv_index }}
+ {{ f.uvIndex }}
{% endif %}
diff --git a/defaultmodules/weather/hourly.njk b/defaultmodules/weather/hourly.njk
index 05416de7dd..6db7cd2cd8 100644
--- a/defaultmodules/weather/hourly.njk
+++ b/defaultmodules/weather/hourly.njk
@@ -15,8 +15,8 @@
{{ hour.temperature | roundValue | unit("temperature") }}
{% if config.showUVIndex %}
- {% if hour.uv_index!=0 %}
- {{ hour.uv_index }}
+ {% if hour.uvIndex!=0 %}
+ {{ hour.uvIndex }}
{% endif %}
diff --git a/defaultmodules/weather/node_helper.js b/defaultmodules/weather/node_helper.js
index f9ea08c42a..153ab1c17c 100644
--- a/defaultmodules/weather/node_helper.js
+++ b/defaultmodules/weather/node_helper.js
@@ -4,6 +4,7 @@ const Log = require("logger");
module.exports = NodeHelper.create({
providers: {},
+ lastData: {},
start () {
Log.log(`Starting node helper for: ${this.name}`);
@@ -31,7 +32,16 @@ module.exports = NodeHelper.create({
Log.log(`Attempting to initialize provider ${identifier} for instance ${instanceId}`);
if (this.providers[instanceId]) {
- Log.log(`Weather provider ${identifier} already initialized for instance ${instanceId}`);
+ Log.log(`Weather provider ${identifier} already initialized for instance ${instanceId}, re-sending WEATHER_INITIALIZED`);
+ // Client may have restarted (e.g. page reload) - re-send so it recovers location name
+ this.sendSocketNotification("WEATHER_INITIALIZED", {
+ instanceId,
+ locationName: this.providers[instanceId].locationName
+ });
+ // Push cached data immediately so reconnecting clients don't wait for next scheduled fetch
+ if (this.lastData[instanceId]) {
+ this.sendSocketNotification("WEATHER_DATA", this.lastData[instanceId]);
+ }
return;
}
@@ -48,11 +58,9 @@ module.exports = NodeHelper.create({
provider.setCallbacks(
(data) => {
// On data received
- this.sendSocketNotification("WEATHER_DATA", {
- instanceId,
- type: config.type,
- data
- });
+ const payload = { instanceId, type: config.type, data };
+ this.lastData[instanceId] = payload;
+ this.sendSocketNotification("WEATHER_DATA", payload);
},
(errorInfo) => {
// On error
@@ -96,6 +104,7 @@ module.exports = NodeHelper.create({
Log.log(`Stopping weather provider for instance ${instanceId}`);
provider.stop();
delete this.providers[instanceId];
+ delete this.lastData[instanceId];
} else {
Log.warn(`No provider found for instance ${instanceId}`);
}
diff --git a/defaultmodules/weather/providers/openmeteo.js b/defaultmodules/weather/providers/openmeteo.js
index 7cc5f43995..ff02cc617e 100644
--- a/defaultmodules/weather/providers/openmeteo.js
+++ b/defaultmodules/weather/providers/openmeteo.js
@@ -418,46 +418,18 @@ class OpenMeteoProvider {
// Add hourly data if available
if (parsedData.hourly) {
- let h;
- const currentTime = parsedData.current_weather.time;
-
- // Handle both data shapes: object with arrays or array of objects (after transpose)
- if (Array.isArray(parsedData.hourly)) {
- // Array of objects (after transpose)
- const hourlyIndex = parsedData.hourly.findIndex((hour) => hour.time.getTime() === currentTime.getTime());
- h = hourlyIndex !== -1 ? hourlyIndex : 0;
-
- if (hourlyIndex === -1) {
- Log.debug("[openmeteo] Could not find current time in hourly data, using index 0");
- }
-
- const hourData = parsedData.hourly[h];
- if (hourData) {
- current.humidity = hourData.relativehumidity_2m;
- current.feelsLikeTemp = hourData.apparent_temperature;
- current.rain = hourData.rain;
- current.snow = hourData.snowfall ? hourData.snowfall * 10 : undefined;
- current.precipitationAmount = hourData.precipitation;
- current.precipitationProbability = hourData.precipitation_probability;
- current.uvIndex = hourData.uv_index;
- }
- } else if (parsedData.hourly.time) {
- // Object with arrays (before transpose - shouldn't happen in normal flow)
- const hourlyIndex = parsedData.hourly.time.findIndex((time) => time === currentTime);
- h = hourlyIndex !== -1 ? hourlyIndex : 0;
-
- if (hourlyIndex === -1) {
- Log.debug("[openmeteo] Could not find current time in hourly data, using index 0");
- }
-
- current.humidity = parsedData.hourly.relativehumidity_2m?.[h];
- current.feelsLikeTemp = parsedData.hourly.apparent_temperature?.[h];
- current.rain = parsedData.hourly.rain?.[h];
- current.snow = parsedData.hourly.snowfall?.[h] ? parsedData.hourly.snowfall[h] * 10 : undefined;
- current.precipitationAmount = parsedData.hourly.precipitation?.[h];
- current.precipitationProbability = parsedData.hourly.precipitation_probability?.[h];
- current.uvIndex = parsedData.hourly.uv_index?.[h];
- }
+ // Open-Meteo updates current_weather every 15 min, but hourly entries only
+ // exist at full hours — find the last entry at or before the current time.
+ const currentMs = parsedData.current_weather.time.getTime();
+ const hourlyIndex = parsedData.hourly.findLastIndex((hour) => hour.time.getTime() <= currentMs);
+ const hourData = parsedData.hourly[Math.max(0, hourlyIndex)];
+ current.humidity = hourData.relativehumidity_2m;
+ current.feelsLikeTemp = hourData.apparent_temperature;
+ current.rain = hourData.rain;
+ current.snow = hourData.snowfall != null ? hourData.snowfall * 10 : null;
+ current.precipitationAmount = hourData.precipitation;
+ current.precipitationProbability = hourData.precipitation_probability;
+ current.uvIndex = hourData.uv_index;
}
// Add daily data if available (after transpose, daily is array of objects)
diff --git a/defaultmodules/weather/providers/openweathermap.js b/defaultmodules/weather/providers/openweathermap.js
index 995855f17e..a60ade013e 100644
--- a/defaultmodules/weather/providers/openweathermap.js
+++ b/defaultmodules/weather/providers/openweathermap.js
@@ -96,28 +96,41 @@ class OpenWeatherMapProvider {
#handleResponse (data) {
try {
- // Set location name from timezone
- if (data.timezone) {
- this.locationName = data.timezone;
- }
-
let weatherData;
- const onecallData = this.#generateWeatherObjectsFromOnecall(data);
-
- switch (this.config.type) {
- case "current":
- weatherData = onecallData.current;
- break;
- case "forecast":
- case "daily":
- weatherData = onecallData.days;
- break;
- case "hourly":
- weatherData = onecallData.hours;
- break;
- default:
- Log.error(`[openweathermap] Unknown type: ${this.config.type}`);
- throw new Error(`Unknown weather type: ${this.config.type}`);
+
+ if (this.config.weatherEndpoint === "/onecall") {
+ // One Call API (v3.0)
+ if (data.timezone) {
+ this.locationName = data.timezone;
+ }
+
+ const onecallData = this.#generateWeatherObjectsFromOnecall(data);
+
+ switch (this.config.type) {
+ case "current":
+ weatherData = onecallData.current;
+ break;
+ case "forecast":
+ case "daily":
+ weatherData = onecallData.days;
+ break;
+ case "hourly":
+ weatherData = onecallData.hours;
+ break;
+ default:
+ Log.error(`[openweathermap] Unknown type: ${this.config.type}`);
+ throw new Error(`Unknown weather type: ${this.config.type}`);
+ }
+ } else if (this.config.weatherEndpoint === "/weather") {
+ // Current weather endpoint (API v2.5)
+ weatherData = this.#generateWeatherObjectFromCurrentWeather(data);
+ } else if (this.config.weatherEndpoint === "/forecast") {
+ // 3-hourly forecast endpoint (API v2.5)
+ weatherData = this.config.type === "hourly"
+ ? this.#generateHourlyWeatherObjectsFromForecast(data)
+ : this.#generateDailyWeatherObjectsFromForecast(data);
+ } else {
+ throw new Error(`Unknown weather endpoint: ${this.config.weatherEndpoint}`);
}
if (weatherData && this.onDataCallback) {
@@ -134,6 +147,123 @@ class OpenWeatherMapProvider {
}
}
+ #generateWeatherObjectFromCurrentWeather (data) {
+ const timezoneOffsetMinutes = (data.timezone ?? 0) / 60;
+
+ if (data.name && data.sys?.country) {
+ this.locationName = `${data.name}, ${data.sys.country}`;
+ } else if (data.name) {
+ this.locationName = data.name;
+ }
+
+ const weather = {};
+ weather.date = weatherUtils.applyTimezoneOffset(new Date(data.dt * 1000), timezoneOffsetMinutes);
+ weather.temperature = data.main.temp;
+ weather.feelsLikeTemp = data.main.feels_like;
+ weather.humidity = data.main.humidity;
+ weather.windSpeed = data.wind.speed;
+ weather.windFromDirection = data.wind.deg;
+ weather.weatherType = weatherUtils.convertWeatherType(data.weather[0].icon);
+ weather.sunrise = weatherUtils.applyTimezoneOffset(new Date(data.sys.sunrise * 1000), timezoneOffsetMinutes);
+ weather.sunset = weatherUtils.applyTimezoneOffset(new Date(data.sys.sunset * 1000), timezoneOffsetMinutes);
+
+ return weather;
+ }
+
+ #extractThreeHourPrecipitation (forecast) {
+ const rain = Number.parseFloat(forecast.rain?.["3h"] ?? "") || 0;
+ const snow = Number.parseFloat(forecast.snow?.["3h"] ?? "") || 0;
+ const precipitationAmount = rain + snow;
+
+ return {
+ rain,
+ snow,
+ precipitationAmount,
+ hasPrecipitation: precipitationAmount > 0
+ };
+ }
+
+ #generateHourlyWeatherObjectsFromForecast (data) {
+ const timezoneOffsetSeconds = data.city?.timezone ?? 0;
+ const timezoneOffsetMinutes = timezoneOffsetSeconds / 60;
+
+ if (data.city?.name && data.city?.country) {
+ this.locationName = `${data.city.name}, ${data.city.country}`;
+ }
+
+ return data.list.map((forecast) => {
+ const weather = {};
+ weather.date = weatherUtils.applyTimezoneOffset(new Date(forecast.dt * 1000), timezoneOffsetMinutes);
+ weather.temperature = forecast.main.temp;
+ weather.feelsLikeTemp = forecast.main.feels_like;
+ weather.humidity = forecast.main.humidity;
+ weather.windSpeed = forecast.wind.speed;
+ weather.windFromDirection = forecast.wind.deg;
+ weather.weatherType = weatherUtils.convertWeatherType(forecast.weather[0].icon);
+ weather.precipitationProbability = forecast.pop !== undefined ? forecast.pop * 100 : undefined;
+
+ const precipitation = this.#extractThreeHourPrecipitation(forecast);
+ if (precipitation.hasPrecipitation) {
+ weather.rain = precipitation.rain;
+ weather.snow = precipitation.snow;
+ weather.precipitationAmount = precipitation.precipitationAmount;
+ }
+
+ return weather;
+ });
+ }
+
+ #generateDailyWeatherObjectsFromForecast (data) {
+ const timezoneOffsetSeconds = data.city?.timezone ?? 0;
+ const timezoneOffsetMinutes = timezoneOffsetSeconds / 60;
+
+ if (data.city?.name && data.city?.country) {
+ this.locationName = `${data.city.name}, ${data.city.country}`;
+ }
+
+ const dayMap = new Map();
+
+ for (const forecast of data.list) {
+ // Shift dt by timezone offset so UTC fields represent local time
+ const localDate = new Date((forecast.dt + timezoneOffsetSeconds) * 1000);
+ const dateKey = `${localDate.getUTCFullYear()}-${String(localDate.getUTCMonth() + 1).padStart(2, "0")}-${String(localDate.getUTCDate()).padStart(2, "0")}`;
+
+ if (!dayMap.has(dateKey)) {
+ dayMap.set(dateKey, {
+ date: weatherUtils.applyTimezoneOffset(new Date(forecast.dt * 1000), timezoneOffsetMinutes),
+ minTemps: [],
+ maxTemps: [],
+ rain: 0,
+ snow: 0,
+ weatherType: weatherUtils.convertWeatherType(forecast.weather[0].icon)
+ });
+ }
+
+ const day = dayMap.get(dateKey);
+ day.minTemps.push(forecast.main.temp_min);
+ day.maxTemps.push(forecast.main.temp_max);
+
+ const hour = localDate.getUTCHours();
+ if (hour >= 8 && hour <= 17) {
+ day.weatherType = weatherUtils.convertWeatherType(forecast.weather[0].icon);
+ }
+
+ const precipitation = this.#extractThreeHourPrecipitation(forecast);
+ day.rain += precipitation.rain;
+ day.snow += precipitation.snow;
+ }
+
+ return Array.from(dayMap.values()).map((day) => ({
+ date: day.date,
+ minTemperature: Math.min(...day.minTemps),
+ maxTemperature: Math.max(...day.maxTemps),
+ weatherType: day.weatherType,
+ rain: day.rain,
+ snow: day.snow,
+ precipitationAmount: day.rain + day.snow
+ }));
+ }
+
#generateWeatherObjectsFromOnecall (data) {
let precip;
diff --git a/defaultmodules/weather/providers/smhi.js b/defaultmodules/weather/providers/smhi.js
index 163d5bafde..26b3673fb0 100644
--- a/defaultmodules/weather/providers/smhi.js
+++ b/defaultmodules/weather/providers/smhi.js
@@ -5,8 +5,32 @@ const HTTPFetcher = require("#http_fetcher");
/**
* Server-side weather provider for SMHI (Swedish Meteorological and Hydrological Institute)
* Sweden only, metric system
- * API: https://opendata.smhi.se/apidocs/metfcst/
+ *
+ * API: SNOW1gv1 — https://opendata.smhi.se/metfcst/snow1gv1
+ * Migrated from PMP3gv2 (deprecated 2026-03-31, returns HTTP 404)
+ *
+ * Version: 2.0.1 (2026-04-02)
+ *
+ * Key differences from PMP3gv2:
+ * - URL: snow1g/version/1 (was pmp3g/version/2)
+ * - Time key: "time" (was "validTime")
+ * - Data structure: flat object entry.data.X (was parameters[].find().values[0])
+ * - Parameter names: human-readable (air_temperature, wind_speed, etc.)
+ * - Coordinates: flat [lon, lat] (was nested [[lon, lat]])
+ * - Precipitation types: different value mapping (1=rain, not snow)
*/
+
+/**
+ * Maps user-facing config precipitationValue to SNOW1gv1 parameter names.
+ * Maintains backward compatibility with existing MagicMirror configs.
+ */
+const PRECIP_VALUE_MAP = {
+ pmin: "precipitation_amount_min",
+ pmean: "precipitation_amount_mean",
+ pmedian: "precipitation_amount_median",
+ pmax: "precipitation_amount_max"
+};
+
class SMHIProvider {
constructor (config) {
this.config = {
@@ -19,7 +43,7 @@ class SMHIProvider {
};
// Validate precipitationValue
- if (!["pmin", "pmean", "pmedian", "pmax"].includes(this.config.precipitationValue)) {
+ if (!Object.keys(PRECIP_VALUE_MAP).includes(this.config.precipitationValue)) {
Log.warn(`[smhi] Invalid precipitationValue: ${this.config.precipitationValue}, using pmedian`);
this.config.precipitationValue = "pmedian";
}
@@ -152,14 +176,20 @@ class SMHIProvider {
return this.#convertWeatherDataGroupedBy(filled, coordinates, "hour");
}
+ /**
+ * Find the time series entry closest to the current time.
+ * SNOW1gv1 uses "time" instead of PMP3gv2's "validTime".
+ * @param {Array} times - Array of SNOW1gv1 time series entries.
+ * @returns {object} The time series entry closest to the current time.
+ */
#getClosestToCurrentTime (times) {
const now = new Date();
let minDiff = null;
let closest = times[0];
for (const time of times) {
- const validTime = new Date(time.validTime);
- const diff = Math.abs(validTime - now);
+ const entryTime = new Date(time.time);
+ const diff = Math.abs(entryTime - now);
if (minDiff === null || diff < minDiff) {
minDiff = diff;
@@ -170,18 +200,27 @@ class SMHIProvider {
return closest;
}
+ /**
+ * Convert a single SNOW1gv1 time series entry to MagicMirror weather object.
+ *
+ * SNOW1gv1 data structure: entry.data.parameter_name (flat object)
+ * PMP3gv2 used: entry.parameters[{name, values}] (array of objects)
+ * @param {object} weatherData - A single SNOW1gv1 time series entry.
+ * @param {object} coordinates - Object with lat and lon properties.
+ * @returns {object} MagicMirror-formatted weather data object.
+ */
#convertWeatherDataToObject (weatherData, coordinates) {
- const date = new Date(weatherData.validTime);
+ const date = new Date(weatherData.time);
const { sunrise, sunset } = getSunTimes(date, coordinates.lat, coordinates.lon);
const isDay = isDayTime(date, sunrise, sunset);
const current = {
date: date,
- humidity: this.#paramValue(weatherData, "r"),
- temperature: this.#paramValue(weatherData, "t"),
- windSpeed: this.#paramValue(weatherData, "ws"),
- windFromDirection: this.#paramValue(weatherData, "wd"),
- weatherType: this.#convertWeatherType(this.#paramValue(weatherData, "Wsymb2"), isDay),
+ humidity: this.#paramValue(weatherData, "relative_humidity"),
+ temperature: this.#paramValue(weatherData, "air_temperature"),
+ windSpeed: this.#paramValue(weatherData, "wind_speed"),
+ windFromDirection: this.#paramValue(weatherData, "wind_from_direction"),
+ weatherType: this.#convertWeatherType(this.#paramValue(weatherData, "symbol_code"), isDay),
feelsLikeTemp: this.#calculateApparentTemperature(weatherData),
sunrise: sunrise,
sunset: sunset,
@@ -190,28 +229,37 @@ class SMHIProvider {
precipitationAmount: 0
};
- // Determine precipitation amount and category
- const precipitationValue = this.#paramValue(weatherData, this.config.precipitationValue);
- const pcat = this.#paramValue(weatherData, "pcat");
-
+ // Map user config (pmedian/pmean/pmin/pmax) to SNOW1gv1 parameter name
+ const precipParamName = PRECIP_VALUE_MAP[this.config.precipitationValue];
+ const precipitationValue = this.#paramValue(weatherData, precipParamName);
+ const pcat = this.#paramValue(weatherData, "predominant_precipitation_type_at_surface");
+
+ // SNOW1gv1 precipitation type mapping (differs from PMP3gv2!):
+ // 0 = no precipitation
+ // 1 = rain
+ // 2 = sleet (snow + rain mix)
+ // 5 = snow / freezing rain
+ // 6 = freezing mixed precipitation
+ // 11 = drizzle / light rain
switch (pcat) {
- case 1: // Snow
- current.snow = precipitationValue;
+ case 1: // Rain
+ case 11: // Drizzle / light rain
+ current.rain = precipitationValue;
current.precipitationAmount = precipitationValue;
break;
- case 2: // Snow and rain (50/50 split)
+ case 2: // Sleet / mixed rain and snow
current.snow = precipitationValue / 2;
current.rain = precipitationValue / 2;
current.precipitationAmount = precipitationValue;
break;
- case 3: // Rain
- case 4: // Drizzle
- case 5: // Freezing rain
- case 6: // Freezing drizzle
- current.rain = precipitationValue;
+ case 5: // Snow / freezing rain
+ case 6: // Freezing mixed precipitation
+ current.snow = precipitationValue;
current.precipitationAmount = precipitationValue;
break;
- // case 0: No precipitation - defaults already set to 0
+ case 0:
+ default:
+ break;
}
return current;
@@ -285,15 +333,22 @@ class SMHIProvider {
}
}
+ /**
+ * Fill gaps in time series data for forecast/hourly grouping.
+ * SNOW1gv1 has variable time steps: 1h (0-48h), 2h (49-72h), 6h (73-132h), 12h (133h+).
+ * Uses "time" key instead of PMP3gv2's "validTime".
+ * @param {Array} data - Array of SNOW1gv1 time series entries.
+ * @returns {Array} Time series with hourly gaps filled using previous entry data.
+ */
#fillInGaps (data) {
if (data.length === 0) return [];
const result = [];
- result.push(data[0]); // Keep first data point
+ result.push(data[0]);
for (let i = 1; i < data.length; i++) {
- const from = new Date(data[i - 1].validTime);
- const to = new Date(data[i].validTime);
+ const from = new Date(data[i - 1].time);
+ const to = new Date(data[i].time);
const hours = Math.floor((to - from) / (1000 * 60 * 60));
// Fill gaps with previous data point (start at j=1 since j=0 is already pushed)
@@ -301,7 +356,7 @@ class SMHIProvider {
const current = { ...data[i - 1] };
const newTime = new Date(from);
newTime.setHours(from.getHours() + j);
- current.validTime = newTime.toISOString();
+ current.time = newTime.toISOString();
result.push(current);
}
@@ -312,13 +367,21 @@ class SMHIProvider {
return result;
}
+ /**
+ * Extract coordinates from SNOW1gv1 response.
+ * SNOW1gv1 returns flat GeoJSON Point: { coordinates: [lon, lat] }
+ * PMP3gv2 returned nested: { coordinates: [[lon, lat]] }
+ * @param {object} data - The full SNOW1gv1 API response object.
+ * @returns {object} Object with lat and lon properties.
+ */
#resolveCoordinates (data) {
- // SMHI returns coordinates in [lon, lat] format
- // Fall back to config if response structure is unexpected
- if (data?.geometry?.coordinates?.[0] && Array.isArray(data.geometry.coordinates[0]) && data.geometry.coordinates[0].length >= 2) {
+ const coords = data?.geometry?.coordinates;
+
+ if (Array.isArray(coords) && coords.length >= 2 && typeof coords[0] === "number") {
+ // SNOW1gv1 flat format: [lon, lat]
return {
- lat: data.geometry.coordinates[0][1],
- lon: data.geometry.coordinates[0][0]
+ lat: coords[1],
+ lon: coords[0]
};
}
@@ -329,20 +392,57 @@ class SMHIProvider {
};
}
+ /**
+ * Calculate apparent (feels-like) temperature using humidity and wind.
+ * Uses SNOW1gv1 parameter names.
+ * @param {object} weatherData - A single SNOW1gv1 time series entry.
+ * @returns {number|null} Apparent temperature in °C, or raw temperature if data is missing.
+ */
#calculateApparentTemperature (weatherData) {
- const Ta = this.#paramValue(weatherData, "t");
- const rh = this.#paramValue(weatherData, "r");
- const ws = this.#paramValue(weatherData, "ws");
- const p = (rh / 100) * 6.105 * Math.exp((17.27 * Ta) / (237.7 + Ta));
+ const Ta = this.#paramValue(weatherData, "air_temperature");
+ const rh = this.#paramValue(weatherData, "relative_humidity");
+ const ws = this.#paramValue(weatherData, "wind_speed");
+ if (Ta === null || rh === null || ws === null) {
+ return Ta; // Fallback to raw temperature if data missing
+ }
+
+ const p = (rh / 100) * 6.105 * Math.exp((17.27 * Ta) / (237.7 + Ta));
return Ta + 0.33 * p - 0.7 * ws - 4;
}
+ /**
+ * Get parameter value from SNOW1gv1 flat data structure.
+ * SNOW1gv1: weatherData.data.parameter_name (direct property access)
+ * PMP3gv2 used: weatherData.parameters.find(p => p.name === name).values[0]
+ *
+ * Returns null if parameter missing or equals SMHI missing value (9999).
+ * @param {object} weatherData - A single SNOW1gv1 time series entry.
+ * @param {string} name - The SNOW1gv1 parameter name to look up.
+ * @returns {number|null} The parameter value, or null if missing.
+ */
#paramValue (weatherData, name) {
- const param = weatherData.parameters.find((p) => p.name === name);
- return param ? param.values[0] : null;
+ const value = weatherData.data?.[name];
+
+ if (value === undefined || value === null) {
+ return null;
+ }
+
+ // SMHI uses 9999 as missing value sentinel for all parameters
+ if (value === 9999) {
+ return null;
+ }
+
+ return value;
}
+ /**
+ * Convert SMHI symbol_code (1-27) to MagicMirror weather icon names.
+ * Symbol codes are identical between PMP3gv2 and SNOW1gv1.
+ * @param {number} input - SMHI symbol_code value (1-27).
+ * @param {boolean} isDayTime - Whether the current time is during daytime.
+ * @returns {string|null} MagicMirror weather icon name, or null if unknown.
+ */
#convertWeatherType (input, isDayTime) {
switch (input) {
case 1:
@@ -387,10 +487,16 @@ class SMHIProvider {
}
}
+ /**
+ * Build SNOW1gv1 forecast URL.
+ * Changed from: pmp3g/version/2
+ * Changed to: snow1g/version/1
+ * @returns {string} The full SNOW1gv1 API URL for the configured coordinates.
+ */
#getUrl () {
const lon = this.config.lon.toFixed(6);
const lat = this.config.lat.toFixed(6);
- return `https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/${lon}/lat/${lat}/data.json`;
+ return `https://opendata-download-metfcst.smhi.se/api/category/snow1g/version/1/geotype/point/lon/${lon}/lat/${lat}/data.json`;
}
}
diff --git a/defaultmodules/weather/providers/weatherapi.js b/defaultmodules/weather/providers/weatherapi.js
index 0ffb1821a2..30124b8029 100644
--- a/defaultmodules/weather/providers/weatherapi.js
+++ b/defaultmodules/weather/providers/weatherapi.js
@@ -351,7 +351,7 @@ class WeatherAPIProvider {
weather.precipitationProbability = precipitationProbability;
}
- weather.uv_index = this.#toNumber(forecastDay.day?.uv);
+ weather.uvIndex = this.#toNumber(forecastDay.day?.uv);
days.push(weather);
@@ -410,7 +410,7 @@ class WeatherAPIProvider {
const willSnow = this.#toNumber(hourData.will_it_snow) ?? 0;
weather.precipitationProbability = (willRain + willSnow) * 50;
- weather.uv_index = this.#toNumber(hourData.uv);
+ weather.uvIndex = this.#toNumber(hourData.uv);
hours.push(weather);
diff --git a/defaultmodules/weather/providers/weatherflow.js b/defaultmodules/weather/providers/weatherflow.js
index 8a4d18daa8..e94af5109f 100644
--- a/defaultmodules/weather/providers/weatherflow.js
+++ b/defaultmodules/weather/providers/weatherflow.js
@@ -145,12 +145,15 @@ class WeatherFlowProvider {
const weather = {
date: new Date(),
- humidity: current.relative_humidity || null,
- temperature: current.air_temperature || null,
- feelsLikeTemp: current.feels_like || null,
+ humidity: current.relative_humidity ?? null,
+ temperature: current.air_temperature ?? null,
+ feelsLikeTemp: current.feels_like ?? null,
windSpeed: current.wind_avg != null ? convertKmhToMs(current.wind_avg) : null,
- windFromDirection: current.wind_direction || null,
+ windFromDirection: current.wind_direction ?? null,
weatherType: this.#convertWeatherType(current.icon),
+ precipitationAmount: current.precip_accum_local_day ?? null,
+ precipitationUnits: "mm",
+ precipitationProbability: current.precip_probability ?? null,
uvIndex: current.uv || null,
sunrise: daily.sunrise ? new Date(daily.sunrise * 1000) : null,
sunset: daily.sunset ? new Date(daily.sunset * 1000) : null
@@ -175,9 +178,9 @@ class WeatherFlowProvider {
for (const forecast of data.forecast.daily) {
const weather = {
date: new Date(forecast.day_start_local * 1000),
- minTemperature: forecast.air_temp_low || null,
- maxTemperature: forecast.air_temp_high || null,
- precipitationProbability: forecast.precip_probability || null,
+ minTemperature: forecast.air_temp_low ?? null,
+ maxTemperature: forecast.air_temp_high ?? null,
+ precipitationProbability: forecast.precip_probability ?? null,
weatherType: this.#convertWeatherType(forecast.icon),
precipitationAmount: 0.0,
precipitationUnits: "mm",
@@ -193,8 +196,8 @@ class WeatherFlowProvider {
if (hourDate.getFullYear() === forecastDate.getFullYear()
&& hourDate.getMonth() === forecastDate.getMonth()
&& hourDate.getDate() === forecastDate.getDate()) {
- weather.uvIndex = Math.max(weather.uvIndex, hour.uv || 0);
- weather.precipitationAmount += hour.precip || 0;
+ weather.uvIndex = Math.max(weather.uvIndex, hour.uv ?? 0);
+ weather.precipitationAmount += hour.precip ?? 0;
} else if (hourDate > forecastDate) {
// Check if we've moved to the next day
const diffMs = hourDate - forecastDate;
@@ -224,14 +227,14 @@ class WeatherFlowProvider {
for (const hour of data.forecast.hourly) {
const weather = {
date: new Date(hour.time * 1000),
- temperature: hour.air_temperature || null,
- feelsLikeTemp: hour.feels_like || null,
- humidity: hour.relative_humidity || null,
+ temperature: hour.air_temperature ?? null,
+ feelsLikeTemp: hour.feels_like ?? null,
+ humidity: hour.relative_humidity ?? null,
windSpeed: hour.wind_avg != null ? convertKmhToMs(hour.wind_avg) : null,
- windFromDirection: hour.wind_direction || null,
+ windFromDirection: hour.wind_direction ?? null,
weatherType: this.#convertWeatherType(hour.icon),
- precipitationProbability: hour.precip_probability || null,
- precipitationAmount: hour.precip || 0,
+ precipitationProbability: hour.precip_probability ?? null,
+ precipitationAmount: hour.precip ?? 0,
precipitationUnits: "mm",
uvIndex: hour.uv || null
};
diff --git a/defaultmodules/weather/providers/yr.js b/defaultmodules/weather/providers/yr.js
index 0de8b51964..9b44571f9e 100644
--- a/defaultmodules/weather/providers/yr.js
+++ b/defaultmodules/weather/providers/yr.js
@@ -314,7 +314,7 @@ class YrProvider {
// Convert collected data to forecast objects
const days = [];
- for (const [dateStr, data] of dailyData) {
+ for (const data of dailyData.values()) {
const stellarInfo = this.#getStellarInfoForDate(data.date);
const dayData = {
diff --git a/defaultmodules/weather/weather.js b/defaultmodules/weather/weather.js
index cf0170a7b5..e40e41a4cd 100644
--- a/defaultmodules/weather/weather.js
+++ b/defaultmodules/weather/weather.js
@@ -1,11 +1,11 @@
-/* global WeatherProvider, WeatherUtils, WeatherObject, formatTime */
+/* global WeatherUtils, WeatherObject, formatTime */
Module.register("weather", {
// Default module config.
defaults: {
weatherProvider: "openweathermap",
roundTemp: false,
- type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
+ type: "current", // current, forecast, daily (equivalent to forecast), hourly
lang: config.language,
units: config.units,
tempUnits: config.units,
@@ -110,8 +110,8 @@ Module.register("weather", {
this.config.showHumidity = this.config.showHumidity ? "wind" : "none";
}
- // All providers run server-side: generate unique instance ID and initialize via node_helper
- this.instanceId = `${this.identifier}_${Date.now()}`;
+ // All providers run server-side: use stable identifier so reconnects don't spawn duplicate HTTPFetchers
+ this.instanceId = this.identifier;
if (window.initWeatherTheme) window.initWeatherTheme(this);
@@ -242,7 +242,23 @@ Module.register("weather", {
// Add all the data to the template.
getTemplateData () {
- const hourlyData = this.weatherHourlyArray?.filter((e, i) => (i + 1) % this.config.hourlyForecastIncrements === this.config.hourlyForecastIncrements - 1);
+ const now = new Date();
+ // Filter out past entries, but keep the current hour (e.g. show 0:00 at 0:10).
+ // This ensures consistent behavior across all providers, regardless of whether
+ // a provider filters past entries itself.
+ const startOfHour = new Date(now);
+ startOfHour.setMinutes(0, 0, 0);
+ const upcomingHourlyData = this.weatherHourlyArray
+ ?.filter((entry) => entry.date?.valueOf() >= startOfHour.getTime());
+ const hourlySourceData = upcomingHourlyData?.length ? upcomingHourlyData : this.weatherHourlyArray;
+
+ const increment = this.config.hourlyForecastIncrements;
+ const keepByConfiguredIncrement = (_entry, index) => {
+ // Keep the existing offset behavior of hourlyForecastIncrements.
+ return (index + 1) % increment === increment - 1;
+ };
+
+ const hourlyData = hourlySourceData?.filter(keepByConfiguredIncrement);
return {
config: this.config,
diff --git a/eslint.config.mjs b/eslint.config.mjs
index fcde3a6800..05232e45df 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -68,7 +68,6 @@ export default defineConfig([
"no-throw-literal": "error",
"no-undefined": "off",
"no-unneeded-ternary": "error",
- "no-unused-vars": "off",
"no-useless-return": "error",
"no-warning-comments": "off",
"object-shorthand": ["error", "methods"],
diff --git a/js/animateCSS.js b/js/animateCSS.js
index 8721553eee..eacb51d3a8 100644
--- a/js/animateCSS.js
+++ b/js/animateCSS.js
@@ -1,4 +1,5 @@
/* enumeration of animations in Array **/
+
const AnimateCSSIn = [
// Attention seekers
"bounce",
@@ -155,4 +156,4 @@ function removeAnimateCSS (element, animation) {
node.classList.remove("animate__animated", animationName);
node.style.removeProperty("--animate-duration");
}
-if (typeof window === "undefined") module.exports = { AnimateCSSIn, AnimateCSSOut };
+if (typeof window === "undefined") module.exports = { AnimateCSSIn, AnimateCSSOut, addAnimateCSS, removeAnimateCSS };
diff --git a/js/app.js b/js/app.js
index 04bda1221e..0e6cba45e0 100644
--- a/js/app.js
+++ b/js/app.js
@@ -84,7 +84,7 @@ function App () {
try {
fs.accessSync(moduleFile, fs.constants.R_OK);
- } catch (e) {
+ } catch {
Log.warn(`No ${moduleFile} found for module: ${moduleName}.`);
}
@@ -93,7 +93,7 @@ function App () {
let loadHelper = true;
try {
fs.accessSync(helperPath, fs.constants.R_OK);
- } catch (e) {
+ } catch {
loadHelper = false;
Log.log(`No helper found for module: ${moduleName}.`);
}
@@ -174,7 +174,8 @@ function App () {
*/
this.start = async function () {
const configObj = Utils.loadConfig();
- config = configObj.fullConf;
+ global.config = configObj.fullConf;
+ const config = global.config;
Utils.checkConfigFile(configObj);
global.defaultModulesDir = config.defaultModulesDir;
@@ -188,7 +189,7 @@ function App () {
try {
fs.renameSync(`${global.root_path}/css/custom.css`, `${global.root_path}/${env.customCss}`);
Log.warn(`WARNING! Your custom css file was moved from ${global.root_path}/css/custom.css to ${global.root_path}/${env.customCss}`);
- } catch (err) {
+ } catch {
Log.warn("WARNING! Your custom css file is currently located in the css folder. Please move it to the config folder!");
}
}
@@ -245,7 +246,7 @@ function App () {
Log.log("Sockets connected & modules started ...");
- return config;
+ return global.config;
};
/**
diff --git a/js/defaults.js b/js/defaults.js
index bd590894cb..81b5264e61 100644
--- a/js/defaults.js
+++ b/js/defaults.js
@@ -11,6 +11,8 @@ const defaults = {
basePath: "/",
electronOptions: {},
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
+ cors: "disabled", // or "allowAll" or "allowWhitelist"
+ corsDomainWhitelist: [], // example: ["api.mapbox.com"]
language: "en",
logLevel: ["INFO", "LOG", "WARN", "ERROR"],
diff --git a/js/electron.js b/js/electron.js
index 9b4465a1b9..ac48dd4b3f 100644
--- a/js/electron.js
+++ b/js/electron.js
@@ -115,7 +115,7 @@ function createWindow () {
}
// simulate mouse move to hide black cursor on start
- mainWindow.webContents.on("dom-ready", (event) => {
+ mainWindow.webContents.on("dom-ready", () => {
mainWindow.webContents.sendInputEvent({ type: "mouseMove", x: 0, y: 0 });
});
diff --git a/js/http_fetcher.js b/js/http_fetcher.js
index f72b4a3be9..b2d7b8c083 100644
--- a/js/http_fetcher.js
+++ b/js/http_fetcher.js
@@ -1,5 +1,5 @@
const { EventEmitter } = require("node:events");
-const { Agent } = require("undici");
+const { fetch: undiciFetch, Agent } = require("undici");
const Log = require("logger");
const { getUserAgent } = require("#server_functions");
@@ -183,6 +183,19 @@ class HTTPFetcher extends EventEmitter {
return null;
}
+ /**
+ * Returns a shortened version of the URL for log messages.
+ * @returns {string} Shortened URL
+ */
+ #shortenUrl () {
+ try {
+ const urlObj = new URL(this.url);
+ return `${urlObj.origin}${urlObj.pathname}${urlObj.search.length > 50 ? "?..." : urlObj.search}`;
+ } catch {
+ return this.url;
+ }
+ }
+
/**
* Determines the retry delay for a non-ok response
* @param {Response} response - The fetch Response object
@@ -198,28 +211,35 @@ class HTTPFetcher extends EventEmitter {
errorType = "AUTH_FAILURE";
delay = Math.max(this.reloadInterval * 5, THIRTY_MINUTES);
message = `Authentication failed (${status}). Check your API key. Waiting ${Math.round(delay / 60000)} minutes before retry.`;
- Log.error(`${this.logContext}${this.url} - ${message}`);
+ Log.error(`${this.logContext}${this.#shortenUrl()} - ${message}`);
} else if (status === 429) {
errorType = "RATE_LIMITED";
const retryAfter = response.headers.get("retry-after");
const parsed = retryAfter ? this.#parseRetryAfter(retryAfter) : null;
delay = parsed !== null ? Math.max(parsed, this.reloadInterval) : Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES);
message = `Rate limited (429). Retrying in ${Math.round(delay / 60000)} minutes.`;
- Log.warn(`${this.logContext}${this.url} - ${message}`);
+ Log.warn(`${this.logContext}${this.#shortenUrl()} - ${message}`);
} else if (status >= 500) {
errorType = "SERVER_ERROR";
this.serverErrorCount = Math.min(this.serverErrorCount + 1, this.maxRetries);
- delay = this.reloadInterval * Math.pow(2, this.serverErrorCount);
- message = `Server error (${status}). Retry #${this.serverErrorCount} in ${Math.round(delay / 60000)} minutes.`;
- Log.error(`${this.logContext}${this.url} - ${message}`);
+ if (this.serverErrorCount >= this.maxRetries) {
+ delay = this.reloadInterval;
+ message = `Server error (${status}). Max retries reached, retrying at configured interval (${Math.round(delay / 1000)}s).`;
+ } else {
+ delay = HTTPFetcher.calculateBackoffDelay(this.serverErrorCount, {
+ maxDelay: this.reloadInterval
+ });
+ message = `Server error (${status}). Retry #${this.serverErrorCount} in ${Math.round(delay / 1000)}s.`;
+ }
+ Log.error(`${this.logContext}${this.#shortenUrl()} - ${message}`);
} else if (status >= 400) {
errorType = "CLIENT_ERROR";
delay = Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES);
message = `Client error (${status}). Retrying in ${Math.round(delay / 60000)} minutes.`;
- Log.error(`${this.logContext}${this.url} - ${message}`);
+ Log.error(`${this.logContext}${this.#shortenUrl()} - ${message}`);
} else {
message = `Unexpected HTTP status ${status}.`;
- Log.error(`${this.logContext}${this.url} - ${message}`);
+ Log.error(`${this.logContext}${this.#shortenUrl()} - ${message}`);
}
return {
@@ -263,12 +283,19 @@ class HTTPFetcher extends EventEmitter {
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
try {
- const response = await fetch(this.url, {
- ...this.getRequestOptions(),
+ const requestOptions = this.getRequestOptions();
+ // Use undici.fetch when a custom dispatcher is present (e.g. selfSignedCert),
+ // because Node's global fetch and npm undici@8 Agents are incompatible.
+ // For regular requests, use globalThis.fetch so MSW and other interceptors work.
+ const fetchFn = requestOptions.dispatcher ? undiciFetch : globalThis.fetch;
+ const response = await fetchFn(this.url, {
+ ...requestOptions,
signal: controller.signal
});
- if (!response.ok) {
+ const isSuccessfulResponse = response.ok || response.status === 304;
+
+ if (!isSuccessfulResponse) {
const { delay, errorInfo } = this.#getDelayForResponse(response);
nextDelay = delay;
this.emit("error", errorInfo);
@@ -288,28 +315,22 @@ class HTTPFetcher extends EventEmitter {
const isTimeout = error.name === "AbortError";
const message = isTimeout ? `Request timeout after ${this.timeout}ms` : `Network error: ${error.message}`;
- // Apply exponential backoff for network errors
this.networkErrorCount = Math.min(this.networkErrorCount + 1, this.maxRetries);
- const backoffDelay = HTTPFetcher.calculateBackoffDelay(this.networkErrorCount, {
- maxDelay: this.reloadInterval
- });
- nextDelay = backoffDelay;
-
- // Truncate URL for cleaner logs
- let shortUrl = this.url;
- try {
- const urlObj = new URL(this.url);
- shortUrl = `${urlObj.origin}${urlObj.pathname}${urlObj.search.length > 50 ? "?..." : urlObj.search}`;
- } catch (urlError) {
- // If URL parsing fails, use original URL
- }
+ const exhausted = this.networkErrorCount >= this.maxRetries;
- // Gradual log-level escalation: WARN for first 2 attempts, ERROR after
- const retryMessage = `Retry #${this.networkErrorCount} in ${Math.round(nextDelay / 1000)}s.`;
- if (this.networkErrorCount <= 2) {
- Log.warn(`${this.logContext}${shortUrl} - ${message} ${retryMessage}`);
+ if (exhausted) {
+ nextDelay = this.reloadInterval;
+ Log.error(`${this.logContext}${this.#shortenUrl()} - ${message} Max retries reached, retrying at configured interval (${Math.round(nextDelay / 1000)}s).`);
} else {
- Log.error(`${this.logContext}${shortUrl} - ${message} ${retryMessage}`);
+ nextDelay = HTTPFetcher.calculateBackoffDelay(this.networkErrorCount, {
+ maxDelay: this.reloadInterval
+ });
+ const retryMsg = `${this.logContext}${this.#shortenUrl()} - ${message} Retry #${this.networkErrorCount} in ${Math.round(nextDelay / 1000)}s.`;
+ if (this.networkErrorCount <= 2) {
+ Log.warn(retryMsg);
+ } else {
+ Log.error(retryMsg);
+ }
}
const errorInfo = this.#createErrorInfo(
@@ -319,18 +340,6 @@ class HTTPFetcher extends EventEmitter {
nextDelay,
error
);
-
- /**
- * Error event - fired when fetch fails
- * @event HTTPFetcher#error
- * @type {object}
- * @property {string} message - Error description
- * @property {number|null} statusCode - HTTP status or null for network errors
- * @property {number} retryDelay - Ms until next retry
- * @property {number} retryCount - Number of consecutive server errors
- * @property {string} url - The URL that was fetched
- * @property {Error|null} originalError - The original error
- */
this.emit("error", errorInfo);
} finally {
clearTimeout(timeoutId);
diff --git a/js/ip_access_control.js b/js/ip_access_control.js
index be1f1063ef..0fef1a4e55 100644
--- a/js/ip_access_control.js
+++ b/js/ip_access_control.js
@@ -22,12 +22,12 @@ function isAllowed (clientIp, whitelist) {
// Single IP address - let ipaddr.process normalize both
const allowedAddr = ipaddr.process(entry);
return addr.toString() === allowedAddr.toString();
- } catch (err) {
+ } catch {
Log.warn(`Invalid whitelist entry: ${entry}`);
return false;
}
});
- } catch (err) {
+ } catch {
Log.warn(`Failed to parse client IP: ${clientIp}`);
return false;
}
diff --git a/js/loader.js b/js/loader.js
index 53283d59b6..31cf7cc0f4 100644
--- a/js/loader.js
+++ b/js/loader.js
@@ -1,5 +1,6 @@
/* global defaultModules, vendor */
+// eslint-disable-next-line no-unused-vars
const Loader = (function () {
/* Create helper variables */
diff --git a/js/logger.js b/js/logger.js
index b4b552288b..28d6db5227 100644
--- a/js/logger.js
+++ b/js/logger.js
@@ -29,7 +29,7 @@
return styleText("gray", parentDir === "js" ? `[${baseName}]` : `[${parentDir}]`);
}
}
- } catch (err) { /* ignore */ }
+ } catch { /* ignore */ }
return styleText("gray", "[unknown]");
};
diff --git a/js/main.js b/js/main.js
index 359f71df0e..73d6075f3b 100644
--- a/js/main.js
+++ b/js/main.js
@@ -1,4 +1,4 @@
-/* global Loader, defaults, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut, modulePositions, io */
+/* global Loader, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut, modulePositions, io */
const MM = (function () {
let modules = [];
@@ -408,7 +408,7 @@ const MM = (function () {
updateWrapperStates();
// Waiting for DOM-changes done in updateWrapperStates before we can start the animation.
- const dummy = moduleWrapper.parentElement.parentElement.offsetHeight;
+ void moduleWrapper.parentElement.parentElement.offsetHeight;
moduleWrapper.style.opacity = 1;
if (haveAnimateName) {
@@ -475,7 +475,20 @@ const MM = (function () {
const loadConfig = async function () {
try {
const res = await fetch(new URL("config/", `${location.origin}${config.basePath}`));
- config = JSON.parse(await res.text());
+
+ // The server tags functions as { __mmFunction: "" } because
+ // JSON.stringify can't serialise live functions. This reviver turns
+ // those tagged objects back into callable functions.
+ config = JSON.parse(await res.text(), (key, value) => {
+ if (value && typeof value === "object" && typeof value.__mmFunction === "string") {
+ try {
+ return new Function(`return (${value.__mmFunction})`)();
+ } catch {
+ Log.warn(`Failed to revive function for config key "${key}".`);
+ }
+ }
+ return value;
+ });
} catch (error) {
Log.error("Unable to retrieve config", error);
}
diff --git a/js/node_helper.js b/js/node_helper.js
index 8910699930..506f1d85c9 100644
--- a/js/node_helper.js
+++ b/js/node_helper.js
@@ -89,7 +89,7 @@ const NodeHelper = Class.extend({
io.of(this.name).on("connection", (socket) => {
// register catch all.
socket.onAny((notification, payload) => {
- if (config.hideConfigSecrets && payload && typeof payload === "object") {
+ if (config?.hideConfigSecrets && payload && typeof payload === "object") {
try {
const payloadStr = replaceSecretPlaceholder(JSON.stringify(payload));
this.socketNotificationReceived(notification, JSON.parse(payloadStr));
diff --git a/js/server.js b/js/server.js
index 9922958ca9..f8a51e714d 100644
--- a/js/server.js
+++ b/js/server.js
@@ -98,7 +98,7 @@ function Server (configObj) {
}
let directories = ["/config", "/css", "/favicon.svg", "/defaultmodules", "/modules", "/node_modules/animate.css", "/node_modules/@fontsource", "/node_modules/@fortawesome", "/translations", "/tests/configs", "/tests/mocks"];
- for (const [key, value] of Object.entries(vendor)) {
+ for (const value of Object.values(vendor)) {
const dirArr = value.split("/");
if (dirArr[0] === "node_modules") directories.push(`/${dirArr[0]}/${dirArr[1]}`);
}
@@ -111,12 +111,21 @@ function Server (configObj) {
const getStartup = (req, res) => res.send(startUp);
const getConfig = (req, res) => {
- if (config.hideConfigSecrets) {
- res.send(configObj.redactedConf);
- } else {
- res.send(configObj.fullConf);
- }
+ const obj = config.hideConfigSecrets ? configObj.redactedConf : configObj.fullConf;
+ // Functions can't survive JSON.stringify, so we wrap them in a
+ // tagged object { __mmFunction: "" }. The client-side
+ // JSON reviver in main.js recognises this tag and reconstructs
+ // the live function from the source string.
+ const jsonString = JSON.stringify(obj, (key, value) => {
+ if (typeof value === "function") {
+ return { __mmFunction: value.toString() };
+ }
+ return value;
+ });
+ res.set("Content-Type", "application/json");
+ res.send(jsonString);
};
+
app.get("/config", (req, res) => getConfig(req, res));
app.get("/cors", async (req, res) => await cors(req, res));
diff --git a/js/server_functions.js b/js/server_functions.js
index 063e9cfe35..2d55bc3b44 100644
--- a/js/server_functions.js
+++ b/js/server_functions.js
@@ -1,5 +1,8 @@
+const dns = require("node:dns");
const fs = require("node:fs");
const path = require("node:path");
+const ipaddr = require("ipaddr.js");
+const undici = require("undici");
const Log = require("logger");
const startUp = new Date();
@@ -19,9 +22,16 @@ function getStartup (req, res) {
* @returns {string} the input with real variable content
*/
function replaceSecretPlaceholder (input) {
- return input.replaceAll(/\*\*(SECRET_[^*]+)\*\*/g, (match, group) => {
- return process.env[group];
- });
+ if (global.config.cors !== "allowAll") {
+ return input.replaceAll(/\*\*(SECRET_[^*]+)\*\*/g, (match, group) => {
+ return process.env[group];
+ });
+ } else {
+ if (input.includes("**SECRET_")) {
+ Log.error("Replacing secrets doesn't work with CORS `allowAll`, you need to set `cors` to `disabled` or `allowWhitelist` in `config.js`");
+ }
+ return input;
+ }
}
/**
@@ -35,9 +45,13 @@ function replaceSecretPlaceholder (input) {
* @returns {Promise} A promise that resolves when the response is sent
*/
async function cors (req, res) {
+ if (global.config.cors === "disabled") {
+ Log.error("CORS is disabled, you need to enable it in `config.js` by setting `cors` to `allowAll` or `allowWhitelist`");
+ return res.status(403).json({ error: "CORS proxy is disabled" });
+ }
+ let url;
try {
const urlRegEx = "url=(.+?)$";
- let url;
const match = new RegExp(urlRegEx, "g").exec(req.url);
if (!match) {
@@ -46,17 +60,61 @@ async function cors (req, res) {
return res.status(400).send(url);
} else {
url = match[1];
- if (typeof config !== "undefined") {
+ if (typeof global.config !== "undefined") {
if (config.hideConfigSecrets) {
url = replaceSecretPlaceholder(url);
}
}
+ // Validate protocol before attempting connection (non-http/https are never allowed)
+ let parsed;
+ try {
+ parsed = new URL(url);
+ } catch {
+ Log.warn(`SSRF blocked (invalid URL): ${url}`);
+ return res.status(403).json({ error: "Forbidden: private or reserved addresses are not allowed" });
+ }
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
+ Log.warn(`SSRF blocked (protocol): ${url}`);
+ return res.status(403).json({ error: "Forbidden: private or reserved addresses are not allowed" });
+ }
+
+ // Block localhost by hostname before even creating the dispatcher (no DNS needed).
+ if (parsed.hostname.toLowerCase() === "localhost") {
+ Log.warn(`SSRF blocked (localhost): ${url}`);
+ return res.status(403).json({ error: "Forbidden: private or reserved addresses are not allowed" });
+ }
+
+ // Whitelist check: if enabled, only allow explicitly listed domains
+ if (global.config.cors === "allowWhitelist" && !global.config.corsDomainWhitelist.includes(parsed.hostname.toLowerCase())) {
+ Log.warn(`CORS blocked (not in whitelist): ${url}`);
+ return res.status(403).json({ error: "Forbidden: domain not in corsDomainWhitelist" });
+ }
+
const headersToSend = getHeadersToSend(req.url);
const expectedReceivedHeaders = geExpectedReceivedHeaders(req.url);
Log.log(`cors url: ${url}`);
- const response = await fetch(url, { headers: headersToSend });
+ // Resolve DNS once and validate the IP. The validated IP is then pinned
+ // for the actual connection so fetch() cannot re-resolve to a different
+ // address. This prevents DNS rebinding / TOCTOU attacks (GHSA-xhvw-r95j-xm4v).
+ const { address, family } = await dns.promises.lookup(parsed.hostname);
+ if (ipaddr.process(address).range() !== "unicast") {
+ Log.warn(`SSRF blocked: ${url}`);
+ return res.status(403).json({ error: "Forbidden: private or reserved addresses are not allowed" });
+ }
+
+ // Pin the validated IP — fetch() reuses it instead of doing its own DNS lookup
+ const dispatcher = new undici.Agent({
+ connect: {
+ lookup: (_h, _o, cb) => {
+ const addresses = [{ address: address, family: family }];
+ process.nextTick(() => cb(null, addresses));
+ }
+ }
+ });
+
+ const response = await undici.fetch(url, { dispatcher, headers: headersToSend });
if (response.ok) {
for (const header of expectedReceivedHeaders) {
const headerValue = response.headers.get(header);
@@ -69,7 +127,6 @@ async function cors (req, res) {
}
}
} catch (error) {
- // Only log errors in non-test environments to keep test output clean
if (process.env.mmTestMode !== "true") {
Log.error(`Error in CORS request: ${error}`);
}
@@ -144,15 +201,15 @@ function getVersion (req, res) {
function getUserAgent () {
const defaultUserAgent = `Mozilla/5.0 (Node.js ${Number(process.version.match(/^v(\d+\.\d+)/)[1])}) MagicMirror/${global.version}`;
- if (typeof config === "undefined") {
+ if (typeof global.config === "undefined") {
return defaultUserAgent;
}
- switch (typeof config.userAgent) {
+ switch (typeof global.config.userAgent) {
case "function":
- return config.userAgent();
+ return global.config.userAgent();
case "string":
- return config.userAgent;
+ return global.config.userAgent;
default:
return defaultUserAgent;
}
@@ -163,7 +220,7 @@ function getUserAgent () {
* @returns {object} environment variables key: values
*/
function getEnvVarsAsObj () {
- const obj = { modulesDir: `${config.foreignModulesDir}`, defaultModulesDir: `${config.defaultModulesDir}`, customCss: `${config.customCss}` };
+ const obj = { modulesDir: `${global.config.foreignModulesDir}`, defaultModulesDir: `${global.config.defaultModulesDir}`, customCss: `${global.config.customCss}` };
if (process.env.MM_MODULES_DIR) {
obj.modulesDir = process.env.MM_MODULES_DIR.replace(`${global.root_path}/`, "");
}
diff --git a/js/socketclient.js b/js/socketclient.js
index 73fdbf08a9..0c3a7c6691 100644
--- a/js/socketclient.js
+++ b/js/socketclient.js
@@ -1,5 +1,6 @@
/* global io */
+// eslint-disable-next-line no-unused-vars
const MMSocket = function (moduleName) {
if (typeof moduleName !== "string") {
throw new Error("Please set the module name for the MMSocket.");
diff --git a/js/translator.js b/js/translator.js
index 497c42687d..b1b52ec7de 100644
--- a/js/translator.js
+++ b/js/translator.js
@@ -17,7 +17,7 @@ const Translator = (function () {
throw new Error(`Unexpected response status: ${response.status}`);
}
return await response.json();
- } catch (exception) {
+ } catch {
Log.error(`Loading json file =${file} failed`);
return null;
}
diff --git a/js/utils.js b/js/utils.js
index f1c80ba2d0..e947bee9ba 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -55,7 +55,7 @@ const getModulePositions = () => {
try {
fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`);
}
- catch (error) {
+ catch {
Log.error("unable to write js/positions.js with the discovered module positions\nmake the MagicMirror/js folder writeable by the user starting MagicMirror");
}
}
@@ -111,7 +111,7 @@ const loadConfig = () => {
try {
fs.accessSync(templateFile, fs.constants.F_OK);
Log.warn("config.js.template files are deprecated and not used anymore. You can use variables inside config.js so copy the template file content into config.js if needed.");
- } catch (error) {
+ } catch {
// no action
}
diff --git a/package-lock.json b/package-lock.json
index 1234f28d45..5e384ba317 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,70 +1,70 @@
{
"name": "magicmirror",
- "version": "2.35.0",
+ "version": "2.36.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "magicmirror",
- "version": "2.35.0",
+ "version": "2.36.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@fontsource/roboto": "^5.2.10",
"@fontsource/roboto-condensed": "^5.2.8",
"@fortawesome/fontawesome-free": "^7.2.0",
- "ajv": "^8.18.0",
+ "ajv": "^8.20.0",
"animate.css": "^4.1.1",
"croner": "^10.0.1",
- "eslint": "^10.1.0",
+ "eslint": "^10.2.1",
"express": "^5.2.1",
"feedme": "^2.0.2",
- "globals": "^17.4.0",
+ "globals": "^17.5.0",
"helmet": "^8.1.0",
"html-to-text": "^9.0.5",
"iconv-lite": "^0.7.2",
"ipaddr.js": "^2.3.0",
"moment": "^2.30.1",
- "moment-timezone": "^0.6.1",
- "node-ical": "^0.25.6",
+ "moment-timezone": "^0.6.2",
+ "node-ical": "^0.26.0",
"nunjucks": "^3.2.4",
"pm2": "^6.0.14",
"socket.io": "^4.8.3",
"suncalc": "^1.9.0",
"systeminformation": "^5.31.5",
- "undici": "^7.24.6",
+ "undici": "^8.1.0",
"weathericons": "^2.1.0"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@stylistic/eslint-plugin": "^5.10.0",
- "@vitest/coverage-v8": "^4.1.2",
- "@vitest/eslint-plugin": "^1.6.14",
- "@vitest/ui": "^4.1.2",
- "cspell": "^9.7.0",
+ "@vitest/coverage-v8": "^4.1.5",
+ "@vitest/eslint-plugin": "^1.6.16",
+ "@vitest/ui": "^4.1.5",
+ "cspell": "^10.0.0",
"eslint-plugin-import-x": "^4.16.2",
- "eslint-plugin-jsdoc": "^62.8.1",
- "eslint-plugin-package-json": "^0.91.1",
- "eslint-plugin-playwright": "^2.10.1",
+ "eslint-plugin-jsdoc": "^62.9.0",
+ "eslint-plugin-package-json": "^0.91.2",
+ "eslint-plugin-playwright": "^2.10.2",
"express-basic-auth": "^1.2.1",
"husky": "^9.1.7",
- "jsdom": "^29.0.1",
+ "jsdom": "^29.1.0",
"lint-staged": "^16.4.0",
- "markdownlint-cli2": "^0.22.0",
- "msw": "^2.12.14",
- "playwright": "^1.58.2",
- "prettier": "^3.8.1",
+ "markdownlint-cli2": "^0.22.1",
+ "msw": "^2.13.6",
+ "playwright": "^1.59.1",
+ "prettier": "^3.8.3",
"prettier-plugin-jinja-template": "^2.1.0",
- "stylelint": "^17.6.0",
+ "stylelint": "^17.9.1",
"stylelint-config-standard": "^40.0.0",
"stylelint-prettier": "^5.0.3",
- "vitest": "^4.1.2"
+ "vitest": "^4.1.5"
},
"engines": {
"node": ">=22.21.1 <23 || >=24"
},
"optionalDependencies": {
- "electron": "^41.1.0"
+ "electron": "^41.3.0"
}
},
"node_modules/@altano/repository-tools": {
@@ -75,39 +75,49 @@
"license": "ISC"
},
"node_modules/@asamuzakjp/css-color": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.1.tgz",
- "integrity": "sha512-iGWN8E45Ws0XWx3D44Q1t6vX2LqhCKcwfmwBYCDsFrYFS6m4q/Ks61L2veETaLv+ckDC6+dTETJoaAAb7VjLiw==",
+ "version": "5.1.11",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz",
+ "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@csstools/css-calc": "^3.1.1",
- "@csstools/css-color-parser": "^4.0.2",
+ "@asamuzakjp/generational-cache": "^1.0.1",
+ "@csstools/css-calc": "^3.2.0",
+ "@csstools/css-color-parser": "^4.1.0",
"@csstools/css-parser-algorithms": "^4.0.0",
- "@csstools/css-tokenizer": "^4.0.0",
- "lru-cache": "^11.2.7"
+ "@csstools/css-tokenizer": "^4.0.0"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/@asamuzakjp/dom-selector": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.0.4.tgz",
- "integrity": "sha512-jXR6x4AcT3eIrS2fSNAwJpwirOkGcd+E7F7CP3zjdTqz9B/2huHOL8YJZBgekKwLML+u7qB/6P1LXQuMScsx0w==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz",
+ "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "@asamuzakjp/generational-cache": "^1.0.1",
"@asamuzakjp/nwsapi": "^2.3.9",
"bidi-js": "^1.0.3",
"css-tree": "^3.2.1",
- "is-potential-custom-element-name": "^1.0.1",
- "lru-cache": "^11.2.7"
+ "is-potential-custom-element-name": "^1.0.1"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
+ "node_modules/@asamuzakjp/generational-cache": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz",
+ "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+ }
+ },
"node_modules/@asamuzakjp/nwsapi": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
@@ -272,9 +282,9 @@
}
},
"node_modules/@cspell/cspell-bundled-dicts": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.7.0.tgz",
- "integrity": "sha512-s7h1vo++Q3AsfQa3cs0u/KGwm3SYInuIlC4kjlCBWjQmb4KddiZB5O1u0+3TlA7GycHb5M4CR7MDfHUICgJf+w==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-10.0.0.tgz",
+ "integrity": "sha512-ci410HEkng2582oOjlRHQtlGXwh+rUC/mVcN9dObLHpKhvPgzn2S6vT56pARstxxZpcCUG/oLhn3dCqdJlVzmA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -282,54 +292,54 @@
"@cspell/dict-al": "^1.1.1",
"@cspell/dict-aws": "^4.0.17",
"@cspell/dict-bash": "^4.2.2",
- "@cspell/dict-companies": "^3.2.10",
+ "@cspell/dict-companies": "^3.2.11",
"@cspell/dict-cpp": "^7.0.2",
"@cspell/dict-cryptocurrencies": "^5.0.5",
"@cspell/dict-csharp": "^4.0.8",
- "@cspell/dict-css": "^4.0.19",
+ "@cspell/dict-css": "^4.1.1",
"@cspell/dict-dart": "^2.3.2",
"@cspell/dict-data-science": "^2.0.13",
"@cspell/dict-django": "^4.1.6",
"@cspell/dict-docker": "^1.1.17",
- "@cspell/dict-dotnet": "^5.0.12",
+ "@cspell/dict-dotnet": "^5.0.13",
"@cspell/dict-elixir": "^4.0.8",
- "@cspell/dict-en_us": "^4.4.29",
+ "@cspell/dict-en_us": "^4.4.33",
"@cspell/dict-en-common-misspellings": "^2.1.12",
- "@cspell/dict-en-gb-mit": "^3.1.18",
- "@cspell/dict-filetypes": "^3.0.15",
+ "@cspell/dict-en-gb-mit": "^3.1.22",
+ "@cspell/dict-filetypes": "^3.0.18",
"@cspell/dict-flutter": "^1.1.1",
- "@cspell/dict-fonts": "^4.0.5",
+ "@cspell/dict-fonts": "^4.0.6",
"@cspell/dict-fsharp": "^1.1.1",
- "@cspell/dict-fullstack": "^3.2.8",
+ "@cspell/dict-fullstack": "^3.2.9",
"@cspell/dict-gaming-terms": "^1.1.2",
"@cspell/dict-git": "^3.1.0",
"@cspell/dict-golang": "^6.0.26",
"@cspell/dict-google": "^1.0.9",
"@cspell/dict-haskell": "^4.0.6",
- "@cspell/dict-html": "^4.0.14",
+ "@cspell/dict-html": "^4.0.15",
"@cspell/dict-html-symbol-entities": "^4.0.5",
"@cspell/dict-java": "^5.0.12",
"@cspell/dict-julia": "^1.1.1",
"@cspell/dict-k8s": "^1.0.12",
"@cspell/dict-kotlin": "^1.1.1",
- "@cspell/dict-latex": "^5.0.0",
+ "@cspell/dict-latex": "^5.1.0",
"@cspell/dict-lorem-ipsum": "^4.0.5",
"@cspell/dict-lua": "^4.0.8",
"@cspell/dict-makefile": "^1.0.5",
- "@cspell/dict-markdown": "^2.0.14",
+ "@cspell/dict-markdown": "^2.0.16",
"@cspell/dict-monkeyc": "^1.0.12",
"@cspell/dict-node": "^5.0.9",
- "@cspell/dict-npm": "^5.2.34",
+ "@cspell/dict-npm": "^5.2.38",
"@cspell/dict-php": "^4.1.1",
"@cspell/dict-powershell": "^5.0.15",
- "@cspell/dict-public-licenses": "^2.0.15",
- "@cspell/dict-python": "^4.2.25",
+ "@cspell/dict-public-licenses": "^2.0.16",
+ "@cspell/dict-python": "^4.2.26",
"@cspell/dict-r": "^2.1.1",
- "@cspell/dict-ruby": "^5.1.0",
+ "@cspell/dict-ruby": "^5.1.1",
"@cspell/dict-rust": "^4.1.2",
"@cspell/dict-scala": "^5.0.9",
"@cspell/dict-shell": "^1.1.2",
- "@cspell/dict-software-terms": "^5.1.21",
+ "@cspell/dict-software-terms": "^5.2.2",
"@cspell/dict-sql": "^2.2.1",
"@cspell/dict-svelte": "^1.0.7",
"@cspell/dict-swift": "^2.0.6",
@@ -339,86 +349,86 @@
"@cspell/dict-zig": "^1.0.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-json-reporter": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.7.0.tgz",
- "integrity": "sha512-6xpGXlMtQA3hV2BCAQcPkpx9eI12I0o01i9eRqSSEDKtxuAnnrejbcCpL+5OboAjTp3/BSeNYSnhuWYLkSITWQ==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-10.0.0.tgz",
+ "integrity": "sha512-hq5dui2ngYMZKbBauX7K1tkqlu81sX/uaCO49ZJLPjeZsE1auZLtHehDLfAr/ZXoj/dLYeQMSKiaJyE+qLVPHA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/cspell-types": "9.7.0"
+ "@cspell/cspell-types": "10.0.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-performance-monitor": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-9.7.0.tgz",
- "integrity": "sha512-w1PZIFXuvjnC6mQHyYAFnrsn5MzKnEcEkcK1bj4OG00bAt7WX2VUA/eNNt9c1iHozCQ+FcRYlfbGxuBmNyzSgw==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-10.0.0.tgz",
+ "integrity": "sha512-2vMh2pLt2dg/ArYvWjMP4v9HCm0pRhONsEJyc8oHdZyOYvX7trixX894I0M39+VBf3yWtPCEgYRh1UDXNIZRig==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20.18"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-pipe": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-9.7.0.tgz",
- "integrity": "sha512-iiisyRpJciU9SOHNSi0ZEK0pqbEMFRatI/R4O+trVKb+W44p4MNGClLVRWPGUmsFbZKPJL3jDtz0wPlG0/JCZA==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-10.0.0.tgz",
+ "integrity": "sha512-qcgHhQvtEX8LSwIVsWrdUgiGim52lN3jT+ghlkdp72v+nBcGKsS2frEKTmbGLug+xcqppkzs6Q6VmsFp1MGtfA==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-resolver": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-9.7.0.tgz",
- "integrity": "sha512-uiEgS238mdabDnwavo6HXt8K98jlh/jpm7NONroM9NTr9rzck2VZKD2kXEj85wDNMtRsRXNoywTjwQ8WTB6/+w==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-10.0.0.tgz",
+ "integrity": "sha512-8H+IUDB7SmrpcRugQ5f55qG81ZShk6nQRk+natLz41TEY98D8/LCmjHEkh/vhDPph9pVJmNUp7JcM2E1UHEa2g==",
"dev": true,
"license": "MIT",
"dependencies": {
"global-directory": "^5.0.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-service-bus": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-9.7.0.tgz",
- "integrity": "sha512-fkqtaCkg4jY/FotmzjhIavbXuH0AgUJxZk78Ktf4XlhqOZ4wDeUWrCf220bva4mh3TWiLx/ae9lIlpl59Vx6hA==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-10.0.0.tgz",
+ "integrity": "sha512-V7eigqg/TOoKwNK4Q18wr9KGxA8U5SFcoWVS8RyAxv4mQ+yNKHhvHEbRBifjPbQDer66afOrclb2UbqkIy2SOw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-types": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-9.7.0.tgz",
- "integrity": "sha512-Tdfx4eH2uS+gv9V9NCr3Rz+c7RSS6ntXp3Blliud18ibRUlRxO9dTaOjG4iv4x0nAmMeedP1ORkEpeXSkh2QiQ==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-10.0.0.tgz",
+ "integrity": "sha512-IQA++Idqb8fZzkCbHq3+T+9yG9WpeaBxomOrG2KcR/Pj0CgnovzuApYKL2cc35UWLePboKinMeqEPiweFpHVug==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/cspell-worker": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-9.7.0.tgz",
- "integrity": "sha512-cjEApFF0aOAa1vTUk+e7xP8ofK7iC7hsRzj1FmvvVQz8PoLWPRaq+1bT89ypPsZQvavqm5sIgb97S60/aW4TVg==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/cspell-worker/-/cspell-worker-10.0.0.tgz",
+ "integrity": "sha512-V5bjMldNksilnja3fu8muQmkW5/guyua1yNVOhoE2r7othSvjuDlGMl8g2bQSrWjp+UXu0dP/BEZ6JC/IfNwTA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "cspell-lib": "9.7.0"
+ "cspell-lib": "10.0.0"
},
"engines": {
- "node": ">=20.18"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/dict-ada": {
@@ -847,57 +857,57 @@
"license": "MIT"
},
"node_modules/@cspell/dynamic-import": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-9.7.0.tgz",
- "integrity": "sha512-Ws36IYvtS/8IN3x6K9dPLvTmaArodRJmzTn2Rkf2NaTnIYWhRuFzsP3SVVO59NN3fXswAEbmz5DSbVUe8bPZHg==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-10.0.0.tgz",
+ "integrity": "sha512-fMqu/5Ma1Q5ZCR/Par+Q4pvaTKmx5pKZzQmkwld2hNounVdk2OaIPM9MzpNn6I1mLk5J+wTnIZmfcWNAzNP9aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/url": "9.7.0",
+ "@cspell/url": "10.0.0",
"import-meta-resolve": "^4.2.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/filetypes": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-9.7.0.tgz",
- "integrity": "sha512-Ln9e/8wGOyTeL3DCCs6kwd18TSpTw3kxsANjTrzLDASrX4cNmAdvc9J5dcIuBHPaqOAnRQxuZbzUlpRh73Y24w==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-10.0.0.tgz",
+ "integrity": "sha512-UP57j9yrDtlCHpFxc/eGho1m8DP5olfu9KRWwd5fiqL9nMSE2rUJtPzQyvqmDwO5bVZt3B+fTVdo4gxuiqw25A==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/rpc": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/rpc/-/rpc-9.7.0.tgz",
- "integrity": "sha512-VnZ4ABgQeoS4RwofcePkDP7L6tf3Kh5D7LQKoyRM4R6XtfSsYefym6XKaRl3saGtthH5YyjgNJ0Tgdjen4wAAw==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/rpc/-/rpc-10.0.0.tgz",
+ "integrity": "sha512-QrpOZMwz2pAjvl6Hky2PauYoMpLCASn3osjn7uKUbgFV70sahyj6tmx4rRgRX7vHu2WQLZev+YsuO4EujiBDOg==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20.18"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/strong-weak-map": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-9.7.0.tgz",
- "integrity": "sha512-5xbvDASjklrmy88O6gmGXgYhpByCXqOj5wIgyvwZe2l83T1bE+iOfGI4pGzZJ/mN+qTn1DNKq8BPBPtDgb7Q2Q==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-10.0.0.tgz",
+ "integrity": "sha512-JRsato0s2IjYdsng+AGL6oAqgZVQgih5aWKdmxs21H6EdhMaoFDmRE5kXm/RT5a6OMdtnzQM9DqeToqBChWIOQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@cspell/url": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@cspell/url/-/url-9.7.0.tgz",
- "integrity": "sha512-ZaaBr0pTvNxmyUbIn+nVPXPr383VqJzfUDMWicgTjJIeo2+T2hOq2kNpgpvTIrWtZrsZnSP8oXms1+sKTjcvkw==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/@cspell/url/-/url-10.0.0.tgz",
+ "integrity": "sha512-q+0pHQ8DbqjemyaOn/mTtBRbCuKDqhnsVbZ6J9zkTsxPgMpccjy0s5oLXwomfrrxMRBH+UcbERwtUmE+SbnoIQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/@csstools/color-helpers": {
@@ -921,9 +931,9 @@
}
},
"node_modules/@csstools/css-calc": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.1.1.tgz",
- "integrity": "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.0.tgz",
+ "integrity": "sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==",
"dev": true,
"funding": [
{
@@ -945,9 +955,9 @@
}
},
"node_modules/@csstools/css-color-parser": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.2.tgz",
- "integrity": "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.0.tgz",
+ "integrity": "sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==",
"dev": true,
"funding": [
{
@@ -962,7 +972,7 @@
"license": "MIT",
"dependencies": {
"@csstools/color-helpers": "^6.0.2",
- "@csstools/css-calc": "^3.1.1"
+ "@csstools/css-calc": "^3.2.0"
},
"engines": {
"node": ">=20.19.0"
@@ -996,9 +1006,9 @@
}
},
"node_modules/@csstools/css-syntax-patches-for-csstree": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.2.tgz",
- "integrity": "sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.3.tgz",
+ "integrity": "sha512-SH60bMfrRCJF3morcdk57WklujF4Jr/EsQUzqkarfHXEFcAR1gg7fS/chAE922Sehgzc1/+Tz5H3Ypa1HiEKrg==",
"dev": true,
"funding": [
{
@@ -1153,14 +1163,14 @@
}
},
"node_modules/@emnapi/core": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz",
- "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
"dev": true,
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/wasi-threads": "1.2.0",
+ "@emnapi/wasi-threads": "1.2.1",
"tslib": "^2.4.0"
}
},
@@ -1173,9 +1183,9 @@
"optional": true
},
"node_modules/@emnapi/runtime": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.1.tgz",
- "integrity": "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
+ "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -1192,9 +1202,9 @@
"optional": true
},
"node_modules/@emnapi/wasi-threads": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz",
- "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz",
+ "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -1211,32 +1221,22 @@
"optional": true
},
"node_modules/@es-joy/jsdoccomment": {
- "version": "0.84.0",
- "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.84.0.tgz",
- "integrity": "sha512-0xew1CxOam0gV5OMjh2KjFQZsKL2bByX1+q4j3E73MpYIdyUxcZb/xQct9ccUb+ve5KGUYbCUxyPnYB7RbuP+w==",
+ "version": "0.86.0",
+ "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.86.0.tgz",
+ "integrity": "sha512-ukZmRQ81WiTpDWO6D/cTBM7XbrNtutHKvAVnZN/8pldAwLoJArGOvkNyxPTBGsPjsoaQBJxlH+tE2TNA/92Qgw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/estree": "^1.0.8",
- "@typescript-eslint/types": "^8.54.0",
- "comment-parser": "1.4.5",
+ "@typescript-eslint/types": "^8.58.0",
+ "comment-parser": "1.4.6",
"esquery": "^1.7.0",
- "jsdoc-type-pratt-parser": "~7.1.1"
+ "jsdoc-type-pratt-parser": "~7.2.0"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@es-joy/jsdoccomment/node_modules/comment-parser": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.5.tgz",
- "integrity": "sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 12.0.0"
- }
- },
"node_modules/@es-joy/resolve.exports": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@es-joy/resolve.exports/-/resolve.exports-1.2.0.tgz",
@@ -1287,12 +1287,12 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.23.3",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz",
- "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==",
+ "version": "0.23.5",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
+ "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^3.0.3",
+ "@eslint/object-schema": "^3.0.5",
"debug": "^4.3.1",
"minimatch": "^10.2.4"
},
@@ -1301,21 +1301,21 @@
}
},
"node_modules/@eslint/config-helpers": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz",
- "integrity": "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==",
+ "version": "0.5.5",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz",
+ "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==",
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^1.1.1"
+ "@eslint/core": "^1.2.1"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/core": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz",
- "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
+ "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
@@ -1346,21 +1346,21 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz",
- "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==",
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
+ "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
"license": "Apache-2.0",
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz",
- "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==",
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz",
+ "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==",
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^1.1.1",
+ "@eslint/core": "^1.2.1",
"levn": "^0.4.1"
},
"engines": {
@@ -1413,27 +1413,40 @@
}
},
"node_modules/@humanfs/core": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
- "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
+ "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
"license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/types": "^0.15.0"
+ },
"engines": {
"node": ">=18.18.0"
}
},
"node_modules/@humanfs/node": {
- "version": "0.16.7",
- "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
- "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
+ "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
"license": "Apache-2.0",
"dependencies": {
- "@humanfs/core": "^0.19.1",
+ "@humanfs/core": "^0.19.2",
+ "@humanfs/types": "^0.15.0",
"@humanwhocodes/retry": "^0.4.0"
},
"engines": {
"node": ">=18.18.0"
}
},
+ "node_modules/@humanfs/types": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
+ "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
"node_modules/@humanwhocodes/module-importer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@@ -1461,27 +1474,27 @@
}
},
"node_modules/@inquirer/ansi": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-1.0.2.tgz",
- "integrity": "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==",
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.5.tgz",
+ "integrity": "sha512-doc2sWgJpbFQ64UflSVd17ibMGDuxO1yKgOgLMwavzESnXjFWJqUeG8saYosqKpHp4kWiM5x1nXvEjbpx90gzw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0"
}
},
"node_modules/@inquirer/confirm": {
- "version": "5.1.21",
- "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.21.tgz",
- "integrity": "sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==",
+ "version": "6.0.12",
+ "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.0.12.tgz",
+ "integrity": "sha512-h9FgGun3QwVYNj5TWIZZ+slii73bMoBFjPfVIGtnFuL4t8gBiNDV9PcSfIzkuxvgquJKt9nr1QzszpBzTbH8Og==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@inquirer/core": "^10.3.2",
- "@inquirer/type": "^3.0.10"
+ "@inquirer/core": "^11.1.9",
+ "@inquirer/type": "^4.0.5"
},
"engines": {
- "node": ">=18"
+ "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0"
},
"peerDependencies": {
"@types/node": ">=18"
@@ -1493,23 +1506,22 @@
}
},
"node_modules/@inquirer/core": {
- "version": "10.3.2",
- "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.3.2.tgz",
- "integrity": "sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==",
+ "version": "11.1.9",
+ "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.1.9.tgz",
+ "integrity": "sha512-BDE4fG22uYh1bGSifcj7JSx119TVYNViMhMu85usp4Fswrzh6M0DV3yld64jA98uOAa2GSQ4Bg4bZRm2d2cwSg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@inquirer/ansi": "^1.0.2",
- "@inquirer/figures": "^1.0.15",
- "@inquirer/type": "^3.0.10",
+ "@inquirer/ansi": "^2.0.5",
+ "@inquirer/figures": "^2.0.5",
+ "@inquirer/type": "^4.0.5",
"cli-width": "^4.1.0",
- "mute-stream": "^2.0.0",
- "signal-exit": "^4.1.0",
- "wrap-ansi": "^6.2.0",
- "yoctocolors-cjs": "^2.1.3"
+ "fast-wrap-ansi": "^0.2.0",
+ "mute-stream": "^3.0.0",
+ "signal-exit": "^4.1.0"
},
"engines": {
- "node": ">=18"
+ "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0"
},
"peerDependencies": {
"@types/node": ">=18"
@@ -1520,103 +1532,24 @@
}
}
},
- "node_modules/@inquirer/core/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@inquirer/core/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/@inquirer/core/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@inquirer/core/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@inquirer/core/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@inquirer/core/node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/@inquirer/figures": {
- "version": "1.0.15",
- "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.15.tgz",
- "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==",
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.5.tgz",
+ "integrity": "sha512-NsSs4kzfm12lNetHwAn3GEuH317IzpwrMCbOuMIVytpjnJ90YYHNwdRgYGuKmVxwuIqSgqk3M5qqQt1cDk0tGQ==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0"
}
},
"node_modules/@inquirer/type": {
- "version": "3.0.10",
- "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.10.tgz",
- "integrity": "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==",
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.5.tgz",
+ "integrity": "sha512-aetVUNeKNc/VriqXlw1NRSW0zhMBB0W4bNbWRJgzRl/3d0QNDQFfk0GO5SDdtjMZVg6o8ZKEiadd7SCCzoOn5Q==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=18"
+ "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0"
},
"peerDependencies": {
"@types/node": ">=18"
@@ -1675,9 +1608,9 @@
"license": "MIT"
},
"node_modules/@mswjs/interceptors": {
- "version": "0.41.3",
- "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.3.tgz",
- "integrity": "sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==",
+ "version": "0.41.6",
+ "resolved": "https://registry.npmjs.org/@mswjs/interceptors/-/interceptors-0.41.6.tgz",
+ "integrity": "sha512-qmDvJIjcNsZ6tXWy2G9yuCgMPTTn35GMA3dPpSLm7QJVpbQzYdw0ALy1bKoivXnEM3U93/OrK+/M719b+fg84Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1692,6 +1625,13 @@
"node": ">=18"
}
},
+ "node_modules/@mswjs/interceptors/node_modules/@open-draft/deferred-promise": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
+ "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@napi-rs/wasm-runtime": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
@@ -1744,9 +1684,9 @@
}
},
"node_modules/@open-draft/deferred-promise": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz",
- "integrity": "sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@open-draft/deferred-promise/-/deferred-promise-3.0.0.tgz",
+ "integrity": "sha512-XW375UK8/9SqUVNVa6M0yEy8+iTi4QN5VZ7aZuRFQmy76LRwI9wy5F4YIBU6T+eTe2/DNDo8tqu8RHlwLHM6RA==",
"dev": true,
"license": "MIT"
},
@@ -1769,9 +1709,9 @@
"license": "MIT"
},
"node_modules/@oxc-project/types": {
- "version": "0.122.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.122.0.tgz",
- "integrity": "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA==",
+ "version": "0.127.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz",
+ "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==",
"dev": true,
"license": "MIT",
"funding": {
@@ -2044,9 +1984,9 @@
"license": "MIT"
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.12.tgz",
- "integrity": "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==",
"cpu": [
"arm64"
],
@@ -2061,9 +2001,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.12.tgz",
- "integrity": "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==",
"cpu": [
"arm64"
],
@@ -2078,9 +2018,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.12.tgz",
- "integrity": "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==",
"cpu": [
"x64"
],
@@ -2095,9 +2035,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.12.tgz",
- "integrity": "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==",
"cpu": [
"x64"
],
@@ -2112,9 +2052,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.12.tgz",
- "integrity": "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz",
+ "integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==",
"cpu": [
"arm"
],
@@ -2129,9 +2069,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.12.tgz",
- "integrity": "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==",
"cpu": [
"arm64"
],
@@ -2149,9 +2089,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.12.tgz",
- "integrity": "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz",
+ "integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==",
"cpu": [
"arm64"
],
@@ -2169,9 +2109,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.12.tgz",
- "integrity": "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==",
"cpu": [
"ppc64"
],
@@ -2189,9 +2129,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.12.tgz",
- "integrity": "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==",
"cpu": [
"s390x"
],
@@ -2209,9 +2149,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.12.tgz",
- "integrity": "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz",
+ "integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==",
"cpu": [
"x64"
],
@@ -2229,9 +2169,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.12.tgz",
- "integrity": "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz",
+ "integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==",
"cpu": [
"x64"
],
@@ -2249,9 +2189,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.12.tgz",
- "integrity": "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz",
+ "integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==",
"cpu": [
"arm64"
],
@@ -2266,9 +2206,9 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.12.tgz",
- "integrity": "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz",
+ "integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==",
"cpu": [
"wasm32"
],
@@ -2276,16 +2216,18 @@
"license": "MIT",
"optional": true,
"dependencies": {
- "@napi-rs/wasm-runtime": "^1.1.1"
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
},
"engines": {
- "node": ">=14.0.0"
+ "node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@rolldown/binding-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz",
- "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
+ "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
"dev": true,
"license": "MIT",
"optional": true,
@@ -2302,9 +2244,9 @@
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.12.tgz",
- "integrity": "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz",
+ "integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==",
"cpu": [
"arm64"
],
@@ -2319,9 +2261,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.12.tgz",
- "integrity": "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz",
+ "integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==",
"cpu": [
"x64"
],
@@ -2336,9 +2278,9 @@
}
},
"node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.12.tgz",
- "integrity": "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz",
+ "integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==",
"dev": true,
"license": "MIT"
},
@@ -2566,9 +2508,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "24.12.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
- "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
+ "version": "24.12.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz",
+ "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
@@ -2584,6 +2526,16 @@
"@types/node": "*"
}
},
+ "node_modules/@types/set-cookie-parser": {
+ "version": "2.4.10",
+ "resolved": "https://registry.npmjs.org/@types/set-cookie-parser/-/set-cookie-parser-2.4.10.tgz",
+ "integrity": "sha512-GGmQVGpQWUe5qglJozEjZV/5dyxbOOZ0LHe/lqyWssB88Y4svNfst0uqBVscdDeIKl5Jy5+aPSvy7mI9tYRguw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/statuses": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/statuses/-/statuses-2.0.6.tgz",
@@ -2618,14 +2570,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.58.0.tgz",
- "integrity": "sha512-8Q/wBPWLQP1j16NxoPNIKpDZFMaxl7yWIoqXWYeWO+Bbd2mjgvoF0dxP2jKZg5+x49rgKdf7Ck473M8PC3V9lg==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz",
+ "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.58.0",
- "@typescript-eslint/types": "^8.58.0",
+ "@typescript-eslint/tsconfig-utils": "^8.59.1",
+ "@typescript-eslint/types": "^8.59.1",
"debug": "^4.4.3"
},
"engines": {
@@ -2640,14 +2592,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.58.0.tgz",
- "integrity": "sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz",
+ "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.58.0",
- "@typescript-eslint/visitor-keys": "8.58.0"
+ "@typescript-eslint/types": "8.59.1",
+ "@typescript-eslint/visitor-keys": "8.59.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2658,9 +2610,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.58.0.tgz",
- "integrity": "sha512-doNSZEVJsWEu4htiVC+PR6NpM+pa+a4ClH9INRWOWCUzMst/VA9c4gXq92F8GUD1rwhNvRLkgjfYtFXegXQF7A==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz",
+ "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2675,9 +2627,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.0.tgz",
- "integrity": "sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz",
+ "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2689,16 +2641,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.58.0.tgz",
- "integrity": "sha512-7vv5UWbHqew/dvs+D3e1RvLv1v2eeZ9txRHPnEEBUgSNLx5ghdzjHa0sgLWYVKssH+lYmV0JaWdoubo0ncGYLA==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz",
+ "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/project-service": "8.58.0",
- "@typescript-eslint/tsconfig-utils": "8.58.0",
- "@typescript-eslint/types": "8.58.0",
- "@typescript-eslint/visitor-keys": "8.58.0",
+ "@typescript-eslint/project-service": "8.59.1",
+ "@typescript-eslint/tsconfig-utils": "8.59.1",
+ "@typescript-eslint/types": "8.59.1",
+ "@typescript-eslint/visitor-keys": "8.59.1",
"debug": "^4.4.3",
"minimatch": "^10.2.2",
"semver": "^7.7.3",
@@ -2717,16 +2669,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.58.0.tgz",
- "integrity": "sha512-RfeSqcFeHMHlAWzt4TBjWOAtoW9lnsAGiP3GbaX9uVgTYYrMbVnGONEfUCiSss+xMHFl+eHZiipmA8WkQ7FuNA==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz",
+ "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.58.0",
- "@typescript-eslint/types": "8.58.0",
- "@typescript-eslint/typescript-estree": "8.58.0"
+ "@typescript-eslint/scope-manager": "8.59.1",
+ "@typescript-eslint/types": "8.59.1",
+ "@typescript-eslint/typescript-estree": "8.59.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2741,13 +2693,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.58.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.58.0.tgz",
- "integrity": "sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==",
+ "version": "8.59.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz",
+ "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "8.58.0",
+ "@typescript-eslint/types": "8.59.1",
"eslint-visitor-keys": "^5.0.0"
},
"engines": {
@@ -3065,14 +3017,14 @@
]
},
"node_modules/@vitest/coverage-v8": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.2.tgz",
- "integrity": "sha512-sPK//PHO+kAkScb8XITeB1bf7fsk85Km7+rt4eeuRR3VS1/crD47cmV5wicisJmjNdfeokTZwjMk4Mj2d58Mgg==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.5.tgz",
+ "integrity": "sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^1.0.2",
- "@vitest/utils": "4.1.2",
+ "@vitest/utils": "4.1.5",
"ast-v8-to-istanbul": "^1.0.0",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
@@ -3086,8 +3038,8 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "4.1.2",
- "vitest": "4.1.2"
+ "@vitest/browser": "4.1.5",
+ "vitest": "4.1.5"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -3096,9 +3048,9 @@
}
},
"node_modules/@vitest/eslint-plugin": {
- "version": "1.6.14",
- "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.14.tgz",
- "integrity": "sha512-PXZ5ysw4eHU9h8nDtBvVcGC7Z2C/T9CFdheqSw1NNXFYqViojub0V9bgdYI67iBTOcra2mwD0EYldlY9bGPf2Q==",
+ "version": "1.6.16",
+ "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.6.16.tgz",
+ "integrity": "sha512-2pBN1F1JXq6zTSaYC58CMJa7pGxXIRsLfOioeZM4cPE3pRdSh1ySTSoHPQlOTEF5WgoVzWZQxhGQ3ygT78hOVg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3127,16 +3079,16 @@
}
},
"node_modules/@vitest/expect": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.2.tgz",
- "integrity": "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz",
+ "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.1.0",
"@types/chai": "^5.2.2",
- "@vitest/spy": "4.1.2",
- "@vitest/utils": "4.1.2",
+ "@vitest/spy": "4.1.5",
+ "@vitest/utils": "4.1.5",
"chai": "^6.2.2",
"tinyrainbow": "^3.1.0"
},
@@ -3145,13 +3097,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.2.tgz",
- "integrity": "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz",
+ "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "4.1.2",
+ "@vitest/spy": "4.1.5",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.21"
},
@@ -3172,9 +3124,9 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.2.tgz",
- "integrity": "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz",
+ "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3185,13 +3137,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.2.tgz",
- "integrity": "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz",
+ "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "4.1.2",
+ "@vitest/utils": "4.1.5",
"pathe": "^2.0.3"
},
"funding": {
@@ -3199,14 +3151,14 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.2.tgz",
- "integrity": "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz",
+ "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.1.2",
- "@vitest/utils": "4.1.2",
+ "@vitest/pretty-format": "4.1.5",
+ "@vitest/utils": "4.1.5",
"magic-string": "^0.30.21",
"pathe": "^2.0.3"
},
@@ -3215,9 +3167,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.2.tgz",
- "integrity": "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz",
+ "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==",
"dev": true,
"license": "MIT",
"funding": {
@@ -3225,13 +3177,13 @@
}
},
"node_modules/@vitest/ui": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.2.tgz",
- "integrity": "sha512-/irhyeAcKS2u6Zokagf9tqZJ0t8S6kMZq4ZG9BHZv7I+fkRrYfQX4w7geYeC2r6obThz39PDxvXQzZX+qXqGeg==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-4.1.5.tgz",
+ "integrity": "sha512-3Z9HNFiV0IF1fk0JPiK+7kE1GcaIPefQQIBYur6PM5yFIq6agys3uqP/0t966e1wXfmjbRCHDe7qW236Xjwnag==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "4.1.2",
+ "@vitest/utils": "4.1.5",
"fflate": "^0.8.2",
"flatted": "^3.4.2",
"pathe": "^2.0.3",
@@ -3243,17 +3195,17 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "vitest": "4.1.2"
+ "vitest": "4.1.5"
}
},
"node_modules/@vitest/utils": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.2.tgz",
- "integrity": "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz",
+ "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.1.2",
+ "@vitest/pretty-format": "4.1.5",
"convert-source-map": "^2.0.0",
"tinyrainbow": "^3.1.0"
},
@@ -3311,9 +3263,9 @@
}
},
"node_modules/ajv": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
- "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
@@ -3549,9 +3501,9 @@
}
},
"node_modules/basic-ftp": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz",
- "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+ "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
@@ -3890,23 +3842,6 @@
"node": ">=0.3.6"
}
},
- "node_modules/clear-module": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz",
- "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "parent-module": "^2.0.0",
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/cli-cursor": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
@@ -4166,9 +4101,9 @@
}
},
"node_modules/content-disposition": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
- "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
+ "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -4266,6 +4201,33 @@
"node": ">=6"
}
},
+ "node_modules/cosmiconfig/node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cosmiconfig/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/croner": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/croner/-/croner-10.0.1.tgz",
@@ -4300,31 +4262,31 @@
}
},
"node_modules/cspell": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell/-/cspell-9.7.0.tgz",
- "integrity": "sha512-ftxOnkd+scAI7RZ1/ksgBZRr0ouC7QRKtPQhD/PbLTKwAM62sSvRhE1bFsuW3VKBn/GilWzTjkJ40WmnDqH5iQ==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell/-/cspell-10.0.0.tgz",
+ "integrity": "sha512-R25gsSR1SLlcGyw48fwJwp0PjXrVdl7RDO/Dm5+s4DvC1uQSlyiUxsr/8ZtbyC/MPeUJFQN9B4luqLlSm0WelQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/cspell-json-reporter": "9.7.0",
- "@cspell/cspell-performance-monitor": "9.7.0",
- "@cspell/cspell-pipe": "9.7.0",
- "@cspell/cspell-types": "9.7.0",
- "@cspell/cspell-worker": "9.7.0",
- "@cspell/dynamic-import": "9.7.0",
- "@cspell/url": "9.7.0",
+ "@cspell/cspell-json-reporter": "10.0.0",
+ "@cspell/cspell-performance-monitor": "10.0.0",
+ "@cspell/cspell-pipe": "10.0.0",
+ "@cspell/cspell-types": "10.0.0",
+ "@cspell/cspell-worker": "10.0.0",
+ "@cspell/dynamic-import": "10.0.0",
+ "@cspell/url": "10.0.0",
"ansi-regex": "^6.2.2",
"chalk": "^5.6.2",
"chalk-template": "^1.1.2",
"commander": "^14.0.3",
- "cspell-config-lib": "9.7.0",
- "cspell-dictionary": "9.7.0",
- "cspell-gitignore": "9.7.0",
- "cspell-glob": "9.7.0",
- "cspell-io": "9.7.0",
- "cspell-lib": "9.7.0",
+ "cspell-config-lib": "10.0.0",
+ "cspell-dictionary": "10.0.0",
+ "cspell-gitignore": "10.0.0",
+ "cspell-glob": "10.0.0",
+ "cspell-io": "10.0.0",
+ "cspell-lib": "10.0.0",
"fast-json-stable-stringify": "^2.1.0",
- "flatted": "^3.3.3",
+ "flatted": "^3.4.2",
"semver": "^7.7.4",
"tinyglobby": "^0.2.15"
},
@@ -4333,155 +4295,154 @@
"cspell-esm": "bin.mjs"
},
"engines": {
- "node": ">=20.18"
+ "node": ">=22.18.0"
},
"funding": {
"url": "https://github.com/streetsidesoftware/cspell?sponsor=1"
}
},
"node_modules/cspell-config-lib": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-9.7.0.tgz",
- "integrity": "sha512-pguh8A3+bSJ1OOrKCiQan8bvaaY125de76OEFz7q1Pq309lIcDrkoL/W4aYbso/NjrXaIw6OjkgPMGRBI/IgGg==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-10.0.0.tgz",
+ "integrity": "sha512-HWK7SRnJ3N/kOThw/uzmXmQYCzBxu58Jkq2hHyte1voDl118BeNFoaNRWMpYdHbBi3kCj8gaZu8wGtm+Zmdhxw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/cspell-types": "9.7.0",
- "comment-json": "^4.5.1",
- "smol-toml": "^1.6.0",
- "yaml": "^2.8.2"
+ "@cspell/cspell-types": "10.0.0",
+ "comment-json": "^4.6.2",
+ "smol-toml": "^1.6.1",
+ "yaml": "^2.8.3"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-dictionary": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-9.7.0.tgz",
- "integrity": "sha512-k/Wz0so32+0QEqQe21V9m4BNXM5ZN6lz3Ix/jLCbMxFIPl6wT711ftjOWIEMFhvUOP0TWXsbzcuE9mKtS5mTig==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-10.0.0.tgz",
+ "integrity": "sha512-KubSoEAJO+77KPSSWjoLCz0+MIWVNq3joGTSyxucAZrBSJD64Y1O4BHHr1aj6XHIZwXhWWNScQlrQR3OcIulng==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/cspell-performance-monitor": "9.7.0",
- "@cspell/cspell-pipe": "9.7.0",
- "@cspell/cspell-types": "9.7.0",
- "cspell-trie-lib": "9.7.0",
+ "@cspell/cspell-performance-monitor": "10.0.0",
+ "@cspell/cspell-pipe": "10.0.0",
+ "@cspell/cspell-types": "10.0.0",
+ "cspell-trie-lib": "10.0.0",
"fast-equals": "^6.0.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-gitignore": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-9.7.0.tgz",
- "integrity": "sha512-MtoYuH4ah4K6RrmaF834npMcRsTKw0658mC6yvmBacUQOmwB/olqyuxF3fxtbb55HDb7cXDQ35t1XuwwGEQeZw==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-10.0.0.tgz",
+ "integrity": "sha512-55XLH9Y52eR7QgyV28Uaw8V9cN1YZ3PQIyrN9YBR4ndQNBKJxO9+jX1nwSspwnccCZiE/N+GGxFzRBb75JDSCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/url": "9.7.0",
- "cspell-glob": "9.7.0",
- "cspell-io": "9.7.0"
+ "@cspell/url": "10.0.0",
+ "cspell-glob": "10.0.0",
+ "cspell-io": "10.0.0"
},
"bin": {
"cspell-gitignore": "bin.mjs"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-glob": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-9.7.0.tgz",
- "integrity": "sha512-LUeAoEsoCJ+7E3TnUmWBscpVQOmdwBejMlFn0JkXy6LQzxrybxXBKf65RSdIv1o5QtrhQIMa358xXYQG0sv/tA==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-10.0.0.tgz",
+ "integrity": "sha512-bXS35fMcA9X7GEkfnWBfoPd/vTnxxfXW+YHt6tWxu5fejfs00qUbjWp1oLC9FxRaXWxIkfsYp2mi1k1jYl4RVw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/url": "9.7.0",
- "picomatch": "^4.0.3"
+ "@cspell/url": "10.0.0",
+ "picomatch": "^4.0.4"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-grammar": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-9.7.0.tgz",
- "integrity": "sha512-oEYME+7MJztfVY1C06aGcJgEYyqBS/v/ETkQGPzf/c6ObSAPRcUbVtsXZgnR72Gru9aBckc70xJcD6bELdoWCA==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-10.0.0.tgz",
+ "integrity": "sha512-49udtYzkcCYEIDJbFOb4IwiAJebOYZnYvG6o6Ep19Tq0Xwjk7i4vxUprNiFNDCWFbcbJRPE9cpwQUVwp5WFGLw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/cspell-pipe": "9.7.0",
- "@cspell/cspell-types": "9.7.0"
+ "@cspell/cspell-pipe": "10.0.0",
+ "@cspell/cspell-types": "10.0.0"
},
"bin": {
"cspell-grammar": "bin.mjs"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-io": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-9.7.0.tgz",
- "integrity": "sha512-V7x0JHAUCcJPRCH8c0MQkkaKmZD2yotxVyrNEx2SZTpvnKrYscLEnUUTWnGJIIf9znzISqw116PLnYu2c+zd6Q==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-10.0.0.tgz",
+ "integrity": "sha512-NQCAUhx9DwKApxPuFl7EK1K1XSaQEAPld45yjjwv93xF8rJkEGkgzOwjbqafwAD20eKYv1a7oj/9EC0S5jETSw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@cspell/cspell-service-bus": "9.7.0",
- "@cspell/url": "9.7.0"
+ "@cspell/cspell-service-bus": "10.0.0",
+ "@cspell/url": "10.0.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-lib": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-9.7.0.tgz",
- "integrity": "sha512-aTx/aLRpnuY1RJnYAu+A8PXfm1oIUdvAQ4W9E66bTgp1LWI+2G2++UtaPxRIgI0olxE9vcXqUnKpjOpO+5W9bQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@cspell/cspell-bundled-dicts": "9.7.0",
- "@cspell/cspell-performance-monitor": "9.7.0",
- "@cspell/cspell-pipe": "9.7.0",
- "@cspell/cspell-resolver": "9.7.0",
- "@cspell/cspell-types": "9.7.0",
- "@cspell/dynamic-import": "9.7.0",
- "@cspell/filetypes": "9.7.0",
- "@cspell/rpc": "9.7.0",
- "@cspell/strong-weak-map": "9.7.0",
- "@cspell/url": "9.7.0",
- "clear-module": "^4.1.2",
- "cspell-config-lib": "9.7.0",
- "cspell-dictionary": "9.7.0",
- "cspell-glob": "9.7.0",
- "cspell-grammar": "9.7.0",
- "cspell-io": "9.7.0",
- "cspell-trie-lib": "9.7.0",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-10.0.0.tgz",
+ "integrity": "sha512-PowW6JEjuv/F2aFEirZvBxpzHdchOnpsUJbeIcFcai0++taLTbHQObROBEBf7e0S8DnHpVD5TZkqrTME5e44wg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@cspell/cspell-bundled-dicts": "10.0.0",
+ "@cspell/cspell-performance-monitor": "10.0.0",
+ "@cspell/cspell-pipe": "10.0.0",
+ "@cspell/cspell-resolver": "10.0.0",
+ "@cspell/cspell-types": "10.0.0",
+ "@cspell/dynamic-import": "10.0.0",
+ "@cspell/filetypes": "10.0.0",
+ "@cspell/rpc": "10.0.0",
+ "@cspell/strong-weak-map": "10.0.0",
+ "@cspell/url": "10.0.0",
+ "cspell-config-lib": "10.0.0",
+ "cspell-dictionary": "10.0.0",
+ "cspell-glob": "10.0.0",
+ "cspell-grammar": "10.0.0",
+ "cspell-io": "10.0.0",
+ "cspell-trie-lib": "10.0.0",
"env-paths": "^4.0.0",
"gensequence": "^8.0.8",
- "import-fresh": "^3.3.1",
+ "import-fresh": "^4.0.0",
"resolve-from": "^5.0.0",
"vscode-languageserver-textdocument": "^1.0.12",
"vscode-uri": "^3.1.0",
"xdg-basedir": "^5.1.0"
},
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
}
},
"node_modules/cspell-trie-lib": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-9.7.0.tgz",
- "integrity": "sha512-a2YqmcraL3g6I/4gY7SYWEZfP73oLluUtxO7wxompk/kOG2K1FUXyQfZXaaR7HxVv10axT1+NrjhOmXpfbI6LA==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-10.0.0.tgz",
+ "integrity": "sha512-R8qrMx10E/bm3Lecslwxn9XYo5NzSRK1rtandEX5n9UmEYHoBXjZELkg5+TOnV8VgrVaJSK57XtcGrbKp/4kSg==",
"dev": true,
"license": "MIT",
"engines": {
- "node": ">=20"
+ "node": ">=22.18.0"
},
"peerDependencies": {
- "@cspell/cspell-types": "9.7.0"
+ "@cspell/cspell-types": "10.0.0"
}
},
"node_modules/css-functions-list": {
@@ -4850,9 +4811,9 @@
"license": "MIT"
},
"node_modules/electron": {
- "version": "41.1.0",
- "resolved": "https://registry.npmjs.org/electron/-/electron-41.1.0.tgz",
- "integrity": "sha512-0XRFyxRqetmqtkkBvV++wGbHYJ7bD++f6EgJW8y9kX4pPRagwlmKDtzqXZhKiu0DIQppm3sXxzHWK9GYP91OKQ==",
+ "version": "41.3.0",
+ "resolved": "https://registry.npmjs.org/electron/-/electron-41.3.0.tgz",
+ "integrity": "sha512-2Q5aeocmFdeheZGDUTrAvSR3t+n0c3d104AJWWEnt7syJU0tE4VdibMYaPtQ47QuXSoUf0/xSsfUUvu/uSXIfg==",
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -4895,9 +4856,9 @@
}
},
"node_modules/engine.io": {
- "version": "6.6.6",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.6.tgz",
- "integrity": "sha512-U2SN0w3OpjFRVlrc17E6TMDmH58Xl9rai1MblNjAdwWp07Kk+llmzX0hjDpQdrDGzwmvOtgM5yI+meYX6iZ2xA==",
+ "version": "6.6.7",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.7.tgz",
+ "integrity": "sha512-DgOngfDKM2EviOH3Mr9m7ks1q8roetLy/IMmYthAYzbpInMbYc/GS+fWFA3rl1gvwKVsQrVV61fo5emD1y3OJQ==",
"license": "MIT",
"dependencies": {
"@types/cors": "^2.8.12",
@@ -5070,9 +5031,9 @@
}
},
"node_modules/es-module-lexer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz",
- "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
"dev": true,
"license": "MIT"
},
@@ -5145,17 +5106,17 @@
}
},
"node_modules/eslint": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.1.0.tgz",
- "integrity": "sha512-S9jlY/ELKEUwwQnqWDO+f+m6sercqOPSqXM5Go94l7DOmxHVDgmSFGWEzeE/gwgTAr0W103BWt0QLe/7mabIvA==",
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz",
+ "integrity": "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==",
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.2",
- "@eslint/config-array": "^0.23.3",
- "@eslint/config-helpers": "^0.5.3",
- "@eslint/core": "^1.1.1",
- "@eslint/plugin-kit": "^0.6.1",
+ "@eslint/config-array": "^0.23.5",
+ "@eslint/config-helpers": "^0.5.5",
+ "@eslint/core": "^1.2.1",
+ "@eslint/plugin-kit": "^0.7.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
@@ -5282,19 +5243,19 @@
}
},
"node_modules/eslint-plugin-jsdoc": {
- "version": "62.8.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.8.1.tgz",
- "integrity": "sha512-e9358PdHgvcMF98foNd3L7hVCw70Lt+YcSL7JzlJebB8eT5oRJtW6bHMQKoAwJtw6q0q0w/fRIr2kwnHdFDI6A==",
+ "version": "62.9.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.9.0.tgz",
+ "integrity": "sha512-PY7/X4jrVgoIDncUmITlUqK546Ltmx/Pd4Hdsu4CvSjryQZJI2mEV4vrdMufyTetMiZ5taNSqvK//BTgVUlNkA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
- "@es-joy/jsdoccomment": "~0.84.0",
+ "@es-joy/jsdoccomment": "~0.86.0",
"@es-joy/resolve.exports": "1.2.0",
"are-docs-informative": "^0.0.2",
- "comment-parser": "1.4.5",
+ "comment-parser": "1.4.6",
"debug": "^4.4.3",
"escape-string-regexp": "^4.0.0",
- "espree": "^11.1.0",
+ "espree": "^11.2.0",
"esquery": "^1.7.0",
"html-entities": "^2.6.0",
"object-deep-merge": "^2.0.0",
@@ -5310,16 +5271,6 @@
"eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0"
}
},
- "node_modules/eslint-plugin-jsdoc/node_modules/comment-parser": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.5.tgz",
- "integrity": "sha512-aRDkn3uyIlCFfk5NUA+VdwMmMsh8JGhc4hapfV4yxymHGQ3BVskMQfoXGpCo5IoBuQ9tS5iiVKhCpTcB4pW4qw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 12.0.0"
- }
- },
"node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
@@ -5352,9 +5303,9 @@
}
},
"node_modules/eslint-plugin-package-json": {
- "version": "0.91.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.91.1.tgz",
- "integrity": "sha512-rxmCAcuTvDqrtywsmVHcFxEZdJUTByetAelAZiAcjMqo0BS1090KbjTeyEOiEdpEqxwa83c+xHCjFoZX9OKEcA==",
+ "version": "0.91.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-package-json/-/eslint-plugin-package-json-0.91.2.tgz",
+ "integrity": "sha512-tuPjHVYOjqEJtErmzuYiQY6o877l9Kb7+lfLhR/mAzHuy9CBqhRreIGPsQmVM/dMJ8yQVg92Bz1vBAgugELIXw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5363,7 +5314,7 @@
"detect-indent": "^7.0.2",
"detect-newline": "^4.0.1",
"eslint-fix-utils": "~0.4.1",
- "package-json-validator": "^1.3.1",
+ "package-json-validator": "^1.4.1",
"semver": "^7.7.3",
"sort-object-keys": "^2.0.0",
"sort-package-json": "^3.4.0",
@@ -5378,9 +5329,9 @@
}
},
"node_modules/eslint-plugin-playwright": {
- "version": "2.10.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.10.1.tgz",
- "integrity": "sha512-qea3UxBOb8fTwJ77FMApZKvRye5DOluDHcev0LDJwID3RELeun0JlqzrNIXAB/SXCyB/AesCW/6sZfcT9q3Edg==",
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-2.10.2.tgz",
+ "integrity": "sha512-0N+2OWc3NZbOZ0gK8mp2TK6Qu3UWcJTQ9rqU0UM2yRJXgT758pvpY0lsOLIySfbyFrLqn3TcXjixbmcK90VnuQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5425,9 +5376,9 @@
}
},
"node_modules/eslint/node_modules/ajv": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
- "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
+ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
@@ -5744,6 +5695,23 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"license": "MIT"
},
+ "node_modules/fast-string-truncated-width": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz",
+ "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-string-width": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz",
+ "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-string-truncated-width": "^3.0.2"
+ }
+ },
"node_modules/fast-uri": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz",
@@ -5760,6 +5728,16 @@
],
"license": "BSD-3-Clause"
},
+ "node_modules/fast-wrap-ansi": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.0.tgz",
+ "integrity": "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-string-width": "^3.0.2"
+ }
+ },
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
@@ -5915,9 +5893,9 @@
"license": "ISC"
},
"node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"funding": [
{
"type": "individual",
@@ -6077,9 +6055,9 @@
}
},
"node_modules/get-tsconfig": {
- "version": "4.13.7",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.7.tgz",
- "integrity": "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==",
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.14.0.tgz",
+ "integrity": "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6220,9 +6198,9 @@
}
},
"node_modules/globals": {
- "version": "17.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz",
- "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==",
+ "version": "17.5.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz",
+ "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -6249,9 +6227,9 @@
}
},
"node_modules/globby": {
- "version": "16.1.1",
- "resolved": "https://registry.npmjs.org/globby/-/globby-16.1.1.tgz",
- "integrity": "sha512-dW7vl+yiAJSp6aCekaVnVJxurRv7DCOLyXqEG3RYMYUg7AuJ2jCqPkZTA8ooqC2vtnkaMcV5WfFBMuEnTu1OQg==",
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-16.2.0.tgz",
+ "integrity": "sha512-QrJia2qDf5BB/V6HYlDTs0I0lBahyjLzpGQg3KT7FnCdTonAyPy2RtY802m2k4ALx6Dp752f82WsOczEVr3l6Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6389,9 +6367,9 @@
}
},
"node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
+ "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
@@ -6401,11 +6379,15 @@
}
},
"node_modules/headers-polyfill": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-4.0.3.tgz",
- "integrity": "sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/headers-polyfill/-/headers-polyfill-5.0.1.tgz",
+ "integrity": "sha512-1TJ6Fih/b8h5TIcv+1+Hw0PDQWJTKDKzFZzcKOiW1wJza3XoAQlkCuXLbymPYB8+ZQyw8mHvdw560e8zVFIWyA==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "dependencies": {
+ "@types/set-cookie-parser": "^2.4.10",
+ "set-cookie-parser": "^3.0.1"
+ }
},
"node_modules/helmet": {
"version": "8.1.0",
@@ -6423,6 +6405,19 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/hosted-git-info": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-9.0.2.tgz",
+ "integrity": "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^11.1.0"
+ },
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
"node_modules/html-encoding-sniffer": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
@@ -6617,45 +6612,18 @@
}
},
"node_modules/import-fresh": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
- "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-4.0.0.tgz",
+ "integrity": "sha512-Fpi660c7VPDM3fPKYovStd9IP1CPOikf6v/dGxJJMmHPcwYQIMJ4W7kO1avBYEpMqkCh+Dx3Ln6H7VYqgztLjw==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
"engines": {
- "node": ">=6"
+ "node": ">=22.15"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/import-fresh/node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/import-fresh/node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/import-meta-resolve": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz",
@@ -6693,9 +6661,9 @@
}
},
"node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.1.tgz",
+ "integrity": "sha512-1FMu8/N15Ck1BL551Jf42NYIoin2unWjLQ2Fze/DXryJRl5twqtwNHlO39qERGbIOcKYWHdgRryhOC+NG4eaLw==",
"license": "MIT",
"engines": {
"node": ">= 12"
@@ -6990,9 +6958,9 @@
"license": "Apache-2.0"
},
"node_modules/jsdoc-type-pratt-parser": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.1.1.tgz",
- "integrity": "sha512-/2uqY7x6bsrpi3i9LVU6J89352C0rpMk0as8trXxCtvd4kPk1ke/Eyif6wqfSLvoNJqcDG9Vk4UsXgygzCt2xA==",
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
+ "integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7000,28 +6968,28 @@
}
},
"node_modules/jsdom": {
- "version": "29.0.1",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.0.1.tgz",
- "integrity": "sha512-z6JOK5gRO7aMybVq/y/MlIpKh8JIi68FBKMUtKkK2KH/wMSRlCxQ682d08LB9fYXplyY/UXG8P4XXTScmdjApg==",
+ "version": "29.1.0",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.0.tgz",
+ "integrity": "sha512-YNUc7fB9QuvSSQWfrH0xF+TyABkxUwx8sswgIDaCrw4Hol8BghdZDkITtZheRJeMtzWlnTfsM3bBBusRvpO1wg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@asamuzakjp/css-color": "^5.0.1",
- "@asamuzakjp/dom-selector": "^7.0.3",
+ "@asamuzakjp/css-color": "^5.1.11",
+ "@asamuzakjp/dom-selector": "^7.1.1",
"@bramus/specificity": "^2.4.2",
- "@csstools/css-syntax-patches-for-csstree": "^1.1.1",
+ "@csstools/css-syntax-patches-for-csstree": "^1.1.3",
"@exodus/bytes": "^1.15.0",
"css-tree": "^3.2.1",
"data-urls": "^7.0.0",
"decimal.js": "^10.6.0",
"html-encoding-sniffer": "^6.0.0",
"is-potential-custom-element-name": "^1.0.1",
- "lru-cache": "^11.2.7",
- "parse5": "^8.0.0",
+ "lru-cache": "^11.3.5",
+ "parse5": "^8.0.1",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
"tough-cookie": "^6.0.1",
- "undici": "^7.24.5",
+ "undici": "^7.25.0",
"w3c-xmlserializer": "^5.0.0",
"webidl-conversions": "^8.0.1",
"whatwg-mimetype": "^5.0.0",
@@ -7040,6 +7008,16 @@
}
}
},
+ "node_modules/jsdom/node_modules/undici": {
+ "version": "7.25.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.25.0.tgz",
+ "integrity": "sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
@@ -7133,9 +7111,9 @@
}
},
"node_modules/katex": {
- "version": "0.16.44",
- "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.44.tgz",
- "integrity": "sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ==",
+ "version": "0.16.45",
+ "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz",
+ "integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==",
"dev": true,
"funding": [
"https://opencollective.com/katex",
@@ -7548,9 +7526,9 @@
}
},
"node_modules/lodash": {
- "version": "4.17.23",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
- "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"license": "MIT"
},
"node_modules/lodash.truncate": {
@@ -7608,9 +7586,9 @@
}
},
"node_modules/lru-cache": {
- "version": "11.2.7",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz",
- "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==",
+ "version": "11.3.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.3.5.tgz",
+ "integrity": "sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
@@ -7698,13 +7676,13 @@
}
},
"node_modules/markdownlint-cli2": {
- "version": "0.22.0",
- "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.22.0.tgz",
- "integrity": "sha512-mOC9BY/XGtdX3M9n3AgERd79F0+S7w18yBBTNIQ453sI87etZfp1z4eajqSMV70CYjbxKe5ktKvT2HCpvcWx9w==",
+ "version": "0.22.1",
+ "resolved": "https://registry.npmjs.org/markdownlint-cli2/-/markdownlint-cli2-0.22.1.tgz",
+ "integrity": "sha512-X14ZbytybDCXAViDmtN4DKLt9ZTrRn+oOrxTYlg3a65jS6QcYYbAkGPh/En2L/GDNbFYJ6lKaQSUNrrbN1bPrw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "globby": "16.1.1",
+ "globby": "16.2.0",
"js-yaml": "4.1.1",
"jsonc-parser": "3.3.1",
"jsonpointer": "5.0.1",
@@ -7712,7 +7690,7 @@
"markdownlint": "0.40.0",
"markdownlint-cli2-formatter-default": "0.0.6",
"micromatch": "4.0.8",
- "smol-toml": "1.6.0"
+ "smol-toml": "1.6.1"
},
"bin": {
"markdownlint-cli2": "markdownlint-cli2-bin.mjs"
@@ -7737,19 +7715,6 @@
"markdownlint-cli2": ">=0.0.4"
}
},
- "node_modules/markdownlint-cli2/node_modules/smol-toml": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz",
- "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "url": "https://github.com/sponsors/cyyynthia"
- }
- },
"node_modules/markdownlint/node_modules/string-width": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz",
@@ -8512,9 +8477,9 @@
}
},
"node_modules/moment-timezone": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.1.tgz",
- "integrity": "sha512-1B9lmAhB9D9/sHaPC1N7wLFEVUoFldxOpOO96lOD1PvJ43vCd0ozDPbu0FEL3++VvawOlDkq8YD373tJmP5JHw==",
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.2.tgz",
+ "integrity": "sha512-lDsQv8FoGdBUdf0+TjGsq2orxKuXdwFlQ6Zw6TX3xIcTwTfEpCLyKqvEauvCHJ8iu3KBV8+uPhlv70YsNGdUBQ==",
"license": "MIT",
"dependencies": {
"moment": "^2.29.4"
@@ -8540,29 +8505,29 @@
"license": "MIT"
},
"node_modules/msw": {
- "version": "2.12.14",
- "resolved": "https://registry.npmjs.org/msw/-/msw-2.12.14.tgz",
- "integrity": "sha512-4KXa4nVBIBjbDbd7vfQNuQ25eFxug0aropCQFoI0JdOBuJWamkT1yLVIWReFI8SiTRc+H1hKzaNk+cLk2N9rtQ==",
+ "version": "2.13.6",
+ "resolved": "https://registry.npmjs.org/msw/-/msw-2.13.6.tgz",
+ "integrity": "sha512-GAJbQy8Ra/Ydjt0Hb2MGT2qhzd83J3+QZMHdH85uW7r/XkKc846+Ma2PLif5hGvTm5Yqa+wkcstpim0WeLZU9g==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "@inquirer/confirm": "^5.0.0",
- "@mswjs/interceptors": "^0.41.2",
- "@open-draft/deferred-promise": "^2.2.0",
+ "@inquirer/confirm": "^6.0.11",
+ "@mswjs/interceptors": "^0.41.3",
+ "@open-draft/deferred-promise": "^3.0.0",
"@types/statuses": "^2.0.6",
- "cookie": "^1.0.2",
- "graphql": "^16.12.0",
- "headers-polyfill": "^4.0.2",
+ "cookie": "^1.1.1",
+ "graphql": "^16.13.2",
+ "headers-polyfill": "^5.0.1",
"is-node-process": "^1.2.0",
"outvariant": "^1.4.3",
"path-to-regexp": "^6.3.0",
"picocolors": "^1.1.1",
- "rettime": "^0.10.1",
+ "rettime": "^0.11.7",
"statuses": "^2.0.2",
"strict-event-emitter": "^0.5.1",
- "tough-cookie": "^6.0.0",
- "type-fest": "^5.2.0",
+ "tough-cookie": "^6.0.1",
+ "type-fest": "^5.5.0",
"until-async": "^3.0.2",
"yargs": "^17.7.2"
},
@@ -8599,13 +8564,13 @@
}
},
"node_modules/mute-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz",
- "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz",
+ "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==",
"dev": true,
"license": "ISC",
"engines": {
- "node": "^18.17.0 || >=20.5.0"
+ "node": "^20.17.0 || >=22.9.0"
}
},
"node_modules/nanoid": {
@@ -8697,25 +8662,25 @@
}
},
"node_modules/netmask": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
- "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz",
+ "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==",
"license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/node-ical": {
- "version": "0.25.6",
- "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.25.6.tgz",
- "integrity": "sha512-Wo3GSBGYUNkcxOjHhevKTGa/+eB7ZwNLCq50h/eTX/YHSDZz1nT4KzXArO455CGHLD68gc5vw3nevqWQpOjjLQ==",
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.26.0.tgz",
+ "integrity": "sha512-tJZY2fMb38Gbj0P05zHMWBr90MslhGZ1qEbOWYnokBYPPX/lYskL/0NnWoeiXTBNod+kRRcTOjxAeB20kfvKyw==",
"license": "Apache-2.0",
"dependencies": {
- "rrule-temporal": "^1.4.7",
- "temporal-polyfill": "^0.3.0"
+ "rrule-temporal": "^1.5.1",
+ "temporal-polyfill": "^0.3.2"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
}
},
"node_modules/normalize-path": {
@@ -8740,6 +8705,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/npm-package-arg": {
+ "version": "13.0.2",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-13.0.2.tgz",
+ "integrity": "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "hosted-git-info": "^9.0.0",
+ "proc-log": "^6.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^7.0.0"
+ },
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
"node_modules/nunjucks": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz",
@@ -8957,12 +8938,13 @@
}
},
"node_modules/package-json-validator": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-1.3.1.tgz",
- "integrity": "sha512-RfUMqyBoLa1qcPsKNAksnVDRuzDvLi//RqfMbf52RNMKsm+cWR/3Cfe6hvrTS/ATtEwvtm/57dPggXsau6++uA==",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-1.4.1.tgz",
+ "integrity": "sha512-kH0EKKflJOfYQeiANow4FkVn2yXVUdxPxtcSiAWSBOVXNopDBdPUShTKGVGy8Dln3n0dZZUETe0p1wGyUQGwBw==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "npm-package-arg": "^13.0.2",
"semver": "^7.7.2",
"validate-npm-package-license": "^3.0.4",
"validate-npm-package-name": "^7.0.0"
@@ -8978,16 +8960,16 @@
"license": "MIT"
},
"node_modules/parent-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz",
- "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "callsites": "^3.1.0"
+ "callsites": "^3.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=6"
}
},
"node_modules/parse-entities": {
@@ -9047,26 +9029,26 @@
"license": "MIT"
},
"node_modules/parse5": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
- "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
+ "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "entities": "^6.0.0"
+ "entities": "^8.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5/node_modules/entities": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
- "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz",
+ "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
- "node": ">=0.12"
+ "node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
@@ -9201,13 +9183,13 @@
"license": "MIT"
},
"node_modules/playwright": {
- "version": "1.58.2",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
- "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
+ "version": "1.59.1",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
+ "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.58.2"
+ "playwright-core": "1.59.1"
},
"bin": {
"playwright": "cli.js"
@@ -9220,9 +9202,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.58.2",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
- "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
+ "version": "1.59.1",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
+ "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -9403,9 +9385,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.8",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
- "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "version": "8.5.12",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz",
+ "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==",
"dev": true,
"funding": [
{
@@ -9489,9 +9471,9 @@
}
},
"node_modules/prettier": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
- "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
+ "version": "3.8.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
+ "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -9527,6 +9509,16 @@
"prettier": "^3.0.0"
}
},
+ "node_modules/proc-log": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz",
+ "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": "^20.17.0 || >=22.9.0"
+ }
+ },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -9646,16 +9638,16 @@
}
},
"node_modules/qified/node_modules/hookified": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.1.1.tgz",
- "integrity": "sha512-AHb76R16GB5EsPBE2J7Ko5kiEyXwviB9P5SMrAKcuAu4vJPZttViAbj9+tZeaQE5zjDme+1vcHP78Yj/WoAveA==",
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz",
+ "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==",
"dev": true,
"license": "MIT"
},
"node_modules/qs": {
- "version": "6.15.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
- "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
+ "version": "6.15.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
+ "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@@ -9814,11 +9806,12 @@
}
},
"node_modules/resolve": {
- "version": "1.22.11",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
- "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
"license": "MIT",
"dependencies": {
+ "es-errors": "^1.3.0",
"is-core-module": "^2.16.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
@@ -9891,9 +9884,9 @@
}
},
"node_modules/rettime": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.10.1.tgz",
- "integrity": "sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==",
+ "version": "0.11.8",
+ "resolved": "https://registry.npmjs.org/rettime/-/rettime-0.11.8.tgz",
+ "integrity": "sha512-0fERGXktJTyJ+h8fBEiPxHPEFOu0h15JY7JtwrOVqR5K+vb99ho6IyOo7ekLS3h4sJCzIDy4VWKIbZUfe9njmg==",
"dev": true,
"license": "MIT"
},
@@ -9934,14 +9927,14 @@
}
},
"node_modules/rolldown": {
- "version": "1.0.0-rc.12",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.12.tgz",
- "integrity": "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A==",
+ "version": "1.0.0-rc.17",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.17.tgz",
+ "integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.122.0",
- "@rolldown/pluginutils": "1.0.0-rc.12"
+ "@oxc-project/types": "=0.127.0",
+ "@rolldown/pluginutils": "1.0.0-rc.17"
},
"bin": {
"rolldown": "bin/cli.mjs"
@@ -9950,21 +9943,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.0.0-rc.12",
- "@rolldown/binding-darwin-arm64": "1.0.0-rc.12",
- "@rolldown/binding-darwin-x64": "1.0.0-rc.12",
- "@rolldown/binding-freebsd-x64": "1.0.0-rc.12",
- "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12",
- "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12",
- "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12",
- "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12",
- "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12",
- "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12",
- "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12",
- "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12",
- "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12",
- "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12",
- "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12"
+ "@rolldown/binding-android-arm64": "1.0.0-rc.17",
+ "@rolldown/binding-darwin-arm64": "1.0.0-rc.17",
+ "@rolldown/binding-darwin-x64": "1.0.0-rc.17",
+ "@rolldown/binding-freebsd-x64": "1.0.0-rc.17",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17",
+ "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17",
+ "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17",
+ "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17",
+ "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17",
+ "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17"
}
},
"node_modules/router": {
@@ -9984,9 +9977,9 @@
}
},
"node_modules/router/node_modules/path-to-regexp": {
- "version": "8.4.1",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.1.tgz",
- "integrity": "sha512-fvU78fIjZ+SBM9YwCknCvKOUKkLVqtWDVctl0s7xIqfmfb38t2TT4ZU2gHm+Z8xGwgW+QWEU3oQSAzIbo89Ggw==",
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
+ "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
"license": "MIT",
"funding": {
"type": "opencollective",
@@ -9994,9 +9987,9 @@
}
},
"node_modules/rrule-temporal": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.5.1.tgz",
- "integrity": "sha512-mV82lZ7OzMOXX5g+SCR8FWRMSvhTnPSznjQ2Vguezjz1nEPEv/Ap/Z/FsIZ/AxA15M9X99m05911/MCXFY+FsA==",
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/rrule-temporal/-/rrule-temporal-1.5.3.tgz",
+ "integrity": "sha512-qALnXyu4MKNUeykkkO0r6Xxl5or3rM8Cf6ibKIe/29sgmq3tGm1oNq4G1Ddp8Ku3mnKmvC3+3yFAJ3OgOu6OJw==",
"license": "MIT",
"dependencies": {
"@js-temporal/polyfill": "^0.5.1"
@@ -10187,6 +10180,13 @@
"url": "https://opencollective.com/express"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.0.tgz",
+ "integrity": "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -10240,13 +10240,13 @@
}
},
"node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
+ "object-inspect": "^1.13.4"
},
"engines": {
"node": ">= 0.4"
@@ -10486,12 +10486,12 @@
}
},
"node_modules/socks": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
- "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.8.tgz",
+ "integrity": "sha512-NlGELfPrgX2f1TAAcz0WawlLn+0r3FyhhCRpFFK2CemXenPYvzMWWZINv3eDNo9ucdwme7oCHRY0Jnbs4aIkog==",
"license": "MIT",
"dependencies": {
- "ip-address": "^10.0.1",
+ "ip-address": "^10.1.1",
"smart-buffer": "^4.2.0"
},
"engines": {
@@ -10651,9 +10651,9 @@
}
},
"node_modules/std-env": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz",
- "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz",
+ "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==",
"dev": true,
"license": "MIT"
},
@@ -10675,9 +10675,9 @@
}
},
"node_modules/string-width": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz",
- "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==",
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz",
+ "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10708,9 +10708,9 @@
}
},
"node_modules/stylelint": {
- "version": "17.6.0",
- "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.6.0.tgz",
- "integrity": "sha512-tokrsMIVAR9vAQ/q3UVEr7S0dGXCi7zkCezPRnS2kqPUulvUh5Vgfwngrk4EoAoW7wnrThqTdnTFN5Ra7CaxIg==",
+ "version": "17.9.1",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-17.9.1.tgz",
+ "integrity": "sha512-THTmnAPJTrg/JhkTWZlSyrO+HUYMx6ELthIHeMyD2WOKqXIJUFQv2Yxn91bvUrZdbBJaW2dUuQdPST2wcQ6C3g==",
"dev": true,
"funding": [
{
@@ -10724,9 +10724,9 @@
],
"license": "MIT",
"dependencies": {
- "@csstools/css-calc": "^3.1.1",
+ "@csstools/css-calc": "^3.2.0",
"@csstools/css-parser-algorithms": "^4.0.0",
- "@csstools/css-syntax-patches-for-csstree": "^1.1.1",
+ "@csstools/css-syntax-patches-for-csstree": "^1.1.3",
"@csstools/css-tokenizer": "^4.0.0",
"@csstools/media-query-list-parser": "^5.0.0",
"@csstools/selector-resolve-nested": "^4.0.0",
@@ -10740,7 +10740,7 @@
"fastest-levenshtein": "^1.0.16",
"file-entry-cache": "^11.1.2",
"global-modules": "^2.0.0",
- "globby": "^16.1.1",
+ "globby": "^16.2.0",
"globjoin": "^0.1.4",
"html-tags": "^5.1.0",
"ignore": "^7.0.5",
@@ -10751,7 +10751,7 @@
"micromatch": "^4.0.8",
"normalize-path": "^3.0.0",
"picocolors": "^1.1.1",
- "postcss": "^8.5.8",
+ "postcss": "^8.5.9",
"postcss-safe-parser": "^7.0.1",
"postcss-selector-parser": "^7.1.1",
"postcss-value-parser": "^4.2.0",
@@ -11125,9 +11125,9 @@
"license": "MIT"
},
"node_modules/tinyexec": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz",
- "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.1.1.tgz",
+ "integrity": "sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -11135,14 +11135,14 @@
}
},
"node_modules/tinyglobby": {
- "version": "0.2.15",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
- "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
- "picomatch": "^4.0.3"
+ "picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
@@ -11162,22 +11162,22 @@
}
},
"node_modules/tldts": {
- "version": "7.0.27",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.27.tgz",
- "integrity": "sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg==",
+ "version": "7.0.29",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.29.tgz",
+ "integrity": "sha512-JIXCerhudr/N6OWLwLF1HVsTTUo7ry6qHa5eWZEkiMuxsIiAACL55tGLfqfHfoH7QaMQUW8fngD7u7TxWexYQg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tldts-core": "^7.0.27"
+ "tldts-core": "^7.0.29"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
- "version": "7.0.27",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.27.tgz",
- "integrity": "sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg==",
+ "version": "7.0.29",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.29.tgz",
+ "integrity": "sha512-W99NuU7b1DcG3uJ3v9k9VztCH3WialNbBkBft5wCs8V8mexu0XQqaZEYb9l9RNNzK8+3EJ9PKWB0/RUtTQ/o+Q==",
"dev": true,
"license": "MIT"
},
@@ -11315,9 +11315,9 @@
}
},
"node_modules/type-fest": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.5.0.tgz",
- "integrity": "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.6.0.tgz",
+ "integrity": "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA==",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"dependencies": {
@@ -11345,9 +11345,9 @@
}
},
"node_modules/typescript": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz",
- "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==",
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
+ "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
@@ -11367,12 +11367,12 @@
"license": "MIT"
},
"node_modules/undici": {
- "version": "7.24.6",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.6.tgz",
- "integrity": "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.1.0.tgz",
+ "integrity": "sha512-E9MkTS4xXLnRPYqxH2e6Hr2/49e7WFDKczKcCaFH4VaZs2iNvHMqeIkyUAD9vM8kujy9TjVrRlQ5KkdEJxB2pw==",
"license": "MIT",
"engines": {
- "node": ">=20.18.1"
+ "node": ">=22.19.0"
}
},
"node_modules/undici-types": {
@@ -11516,17 +11516,17 @@
}
},
"node_modules/vite": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.3.tgz",
- "integrity": "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ==",
+ "version": "8.0.10",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz",
+ "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
- "postcss": "^8.5.8",
- "rolldown": "1.0.0-rc.12",
- "tinyglobby": "^0.2.15"
+ "postcss": "^8.5.10",
+ "rolldown": "1.0.0-rc.17",
+ "tinyglobby": "^0.2.16"
},
"bin": {
"vite": "bin/vite.js"
@@ -11543,7 +11543,7 @@
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
"@vitejs/devtools": "^0.1.0",
- "esbuild": "^0.27.0",
+ "esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
"sass": "^1.70.0",
@@ -11609,19 +11609,19 @@
}
},
"node_modules/vitest": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.2.tgz",
- "integrity": "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==",
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz",
+ "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "4.1.2",
- "@vitest/mocker": "4.1.2",
- "@vitest/pretty-format": "4.1.2",
- "@vitest/runner": "4.1.2",
- "@vitest/snapshot": "4.1.2",
- "@vitest/spy": "4.1.2",
- "@vitest/utils": "4.1.2",
+ "@vitest/expect": "4.1.5",
+ "@vitest/mocker": "4.1.5",
+ "@vitest/pretty-format": "4.1.5",
+ "@vitest/runner": "4.1.5",
+ "@vitest/snapshot": "4.1.5",
+ "@vitest/spy": "4.1.5",
+ "@vitest/utils": "4.1.5",
"es-module-lexer": "^2.0.0",
"expect-type": "^1.3.0",
"magic-string": "^0.30.21",
@@ -11649,10 +11649,12 @@
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "4.1.2",
- "@vitest/browser-preview": "4.1.2",
- "@vitest/browser-webdriverio": "4.1.2",
- "@vitest/ui": "4.1.2",
+ "@vitest/browser-playwright": "4.1.5",
+ "@vitest/browser-preview": "4.1.5",
+ "@vitest/browser-webdriverio": "4.1.5",
+ "@vitest/coverage-istanbul": "4.1.5",
+ "@vitest/coverage-v8": "4.1.5",
+ "@vitest/ui": "4.1.5",
"happy-dom": "*",
"jsdom": "*",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
@@ -11676,6 +11678,12 @@
"@vitest/browser-webdriverio": {
"optional": true
},
+ "@vitest/coverage-istanbul": {
+ "optional": true
+ },
+ "@vitest/coverage-v8": {
+ "optional": true
+ },
"@vitest/ui": {
"optional": true
},
@@ -12073,19 +12081,6 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
- },
- "node_modules/yoctocolors-cjs": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz",
- "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
}
}
}
diff --git a/package.json b/package.json
index 5cad85d4a0..b2c0eca59b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "magicmirror",
- "version": "2.35.0",
+ "version": "2.36.0",
"description": "The open source modular smart mirror platform.",
"keywords": [
"magic mirror",
@@ -90,55 +90,55 @@
"@fontsource/roboto": "^5.2.10",
"@fontsource/roboto-condensed": "^5.2.8",
"@fortawesome/fontawesome-free": "^7.2.0",
- "ajv": "^8.18.0",
+ "ajv": "^8.20.0",
"animate.css": "^4.1.1",
"croner": "^10.0.1",
- "eslint": "^10.1.0",
+ "eslint": "^10.2.1",
"express": "^5.2.1",
"feedme": "^2.0.2",
- "globals": "^17.4.0",
+ "globals": "^17.5.0",
"helmet": "^8.1.0",
"html-to-text": "^9.0.5",
"iconv-lite": "^0.7.2",
"ipaddr.js": "^2.3.0",
"moment": "^2.30.1",
- "moment-timezone": "^0.6.1",
- "node-ical": "^0.25.6",
+ "moment-timezone": "^0.6.2",
+ "node-ical": "^0.26.0",
"nunjucks": "^3.2.4",
"pm2": "^6.0.14",
"socket.io": "^4.8.3",
"suncalc": "^1.9.0",
"systeminformation": "^5.31.5",
- "undici": "^7.24.6",
+ "undici": "^8.1.0",
"weathericons": "^2.1.0"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@stylistic/eslint-plugin": "^5.10.0",
- "@vitest/coverage-v8": "^4.1.2",
- "@vitest/eslint-plugin": "^1.6.14",
- "@vitest/ui": "^4.1.2",
- "cspell": "^9.7.0",
+ "@vitest/coverage-v8": "^4.1.5",
+ "@vitest/eslint-plugin": "^1.6.16",
+ "@vitest/ui": "^4.1.5",
+ "cspell": "^10.0.0",
"eslint-plugin-import-x": "^4.16.2",
- "eslint-plugin-jsdoc": "^62.8.1",
- "eslint-plugin-package-json": "^0.91.1",
- "eslint-plugin-playwright": "^2.10.1",
+ "eslint-plugin-jsdoc": "^62.9.0",
+ "eslint-plugin-package-json": "^0.91.2",
+ "eslint-plugin-playwright": "^2.10.2",
"express-basic-auth": "^1.2.1",
"husky": "^9.1.7",
- "jsdom": "^29.0.1",
+ "jsdom": "^29.1.0",
"lint-staged": "^16.4.0",
- "markdownlint-cli2": "^0.22.0",
- "msw": "^2.12.14",
- "playwright": "^1.58.2",
- "prettier": "^3.8.1",
+ "markdownlint-cli2": "^0.22.1",
+ "msw": "^2.13.6",
+ "playwright": "^1.59.1",
+ "prettier": "^3.8.3",
"prettier-plugin-jinja-template": "^2.1.0",
- "stylelint": "^17.6.0",
+ "stylelint": "^17.9.1",
"stylelint-config-standard": "^40.0.0",
"stylelint-prettier": "^5.0.3",
- "vitest": "^4.1.2"
+ "vitest": "^4.1.5"
},
"optionalDependencies": {
- "electron": "^41.1.0"
+ "electron": "^41.3.0"
},
"engines": {
"node": ">=22.21.1 <23 || >=24"
diff --git a/serveronly/watcher.js b/serveronly/watcher.js
index c73be29415..ab8aa0a1e5 100644
--- a/serveronly/watcher.js
+++ b/serveronly/watcher.js
@@ -35,7 +35,7 @@ function getServerConfig () {
port: global.mmPort || config.port || 8080,
address: config.address || "localhost"
};
- } catch (err) {
+ } catch {
serverConfig = { port: 8080, address: "localhost" };
}
@@ -248,7 +248,7 @@ try {
Log.warn(`Watch target is not a file (directories not supported): ${targetPath}`);
}
}
-} catch (err) {
+} catch {
// Config file might not exist or be invalid, use fallback targets
Log.warn("Could not load watchTargets from config.");
}
diff --git a/tests/configs/config_functions.js b/tests/configs/config_functions.js
new file mode 100644
index 0000000000..27e265f14d
--- /dev/null
+++ b/tests/configs/config_functions.js
@@ -0,0 +1,35 @@
+/*eslint object-shorthand: ["error", "always", { "methodsIgnorePattern": "^roundToInt2$" }]*/
+
+let config = require(`${process.cwd()}/tests/configs/default.js`).configFactory({
+ modules: [
+ {
+ module: "clock",
+ position: "middle_center",
+ config: {
+ moduleFunctions: {
+ roundToInt1: (value) => {
+ try {
+ return Math.round(parseFloat(value));
+ } catch {
+ return value;
+ }
+ },
+ roundToInt2: function (value) {
+ try {
+ return Math.round(parseFloat(value));
+ } catch {
+ return value;
+ }
+ }
+ },
+ stringWithArrow: "a => b is not a function",
+ stringWithFunction: "this function keyword is just text"
+ }
+ }
+ ]
+});
+
+/*************** DO NOT EDIT THE LINE BELOW ***************/
+if (typeof module !== "undefined") {
+ module.exports = config;
+}
diff --git a/tests/e2e/config_functions_spec.js b/tests/e2e/config_functions_spec.js
new file mode 100644
index 0000000000..b40361cdcb
--- /dev/null
+++ b/tests/e2e/config_functions_spec.js
@@ -0,0 +1,21 @@
+const helpers = require("./helpers/global-setup");
+
+describe("config with module function", () => {
+ beforeAll(async () => {
+ await helpers.startApplication("tests/configs/config_functions.js");
+ });
+
+ afterAll(async () => {
+ await helpers.stopApplication();
+ });
+
+ it("config should resolve module functions", () => {
+ expect(config.modules[0].config.moduleFunctions.roundToInt1(13.3)).toBe(13);
+ expect(config.modules[0].config.moduleFunctions.roundToInt2(13.3)).toBe(13);
+ });
+
+ it("config should not revive plain strings containing arrow or function keywords", () => {
+ expect(config.modules[0].config.stringWithArrow).toBe("a => b is not a function");
+ expect(config.modules[0].config.stringWithFunction).toBe("this function keyword is just text");
+ });
+});
diff --git a/tests/e2e/translations_spec.js b/tests/e2e/translations_spec.js
index 12a364d089..42a0739115 100644
--- a/tests/e2e/translations_spec.js
+++ b/tests/e2e/translations_spec.js
@@ -76,7 +76,7 @@ describe("translations", () => {
it("should load translation file", async () => {
const { Translator, Module, config } = dom.window;
config.language = "en";
- Translator.load = vi.fn().mockImplementation((_m, _f, _fb) => null);
+ Translator.load = vi.fn().mockImplementation(() => null);
Module.register("name", { getTranslations: () => translations });
const MMM = Module.create("name");
@@ -89,7 +89,7 @@ describe("translations", () => {
it("should load translation + fallback file", async () => {
const { Translator, Module } = dom.window;
- Translator.load = vi.fn().mockImplementation((_m, _f, _fb) => null);
+ Translator.load = vi.fn().mockImplementation(() => null);
Module.register("name", { getTranslations: () => translations });
const MMM = Module.create("name");
@@ -104,7 +104,7 @@ describe("translations", () => {
it("should load translation fallback file", async () => {
const { Translator, Module, config } = dom.window;
config.language = "--";
- Translator.load = vi.fn().mockImplementation((_m, _f, _fb) => null);
+ Translator.load = vi.fn().mockImplementation(() => null);
Module.register("name", { getTranslations: () => translations });
const MMM = Module.create("name");
diff --git a/tests/electron/helpers/global-setup.js b/tests/electron/helpers/global-setup.js
index 91c542d090..8df47c4997 100644
--- a/tests/electron/helpers/global-setup.js
+++ b/tests/electron/helpers/global-setup.js
@@ -70,7 +70,7 @@ exports.stopApplication = async (timeout = 10000) => {
if (electronProcess && !electronProcess.killed) {
electronProcess.kill("SIGKILL");
}
- } catch (error) {
+ } catch {
// Ignore errors caused by Playwright already tearing down the connection
}
};
@@ -80,7 +80,7 @@ exports.stopApplication = async (timeout = 10000) => {
app.close(),
new Promise((_, reject) => setTimeout(() => reject(new Error("Electron close timeout")), timeout))
]);
- } catch (error) {
+ } catch {
killElectron();
}
};
diff --git a/tests/electron/modules/calendar_spec.js b/tests/electron/modules/calendar_spec.js
index 1be60c4d8f..c37f3a434c 100644
--- a/tests/electron/modules/calendar_spec.js
+++ b/tests/electron/modules/calendar_spec.js
@@ -26,6 +26,7 @@ describe("Calendar module", () => {
* Use this for debugging broken tests, it will console log the text of the calendar module
* @returns {Promise}
*/
+ // eslint-disable-next-line no-unused-vars
const logAllText = async () => {
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
diff --git a/tests/mocks/testNotification/testNotification.js b/tests/mocks/testNotification/testNotification.js
index 735af025a3..a18cc0261a 100644
--- a/tests/mocks/testNotification/testNotification.js
+++ b/tests/mocks/testNotification/testNotification.js
@@ -42,9 +42,9 @@ Module.register("testNotification", {
let tableRow = document.createElement("tr");
table.appendChild(tableRow);
- let tablecol1 = this.maketd(tableRow, col1);
- let tablecol2 = this.maketd(tableRow, col2);
- let tablecol3 = this.maketd(tableRow, col3);
+ this.maketd(tableRow, col1);
+ this.maketd(tableRow, col2);
+ this.maketd(tableRow, col3);
return tableRow;
},
diff --git a/tests/mocks/weather_owm_current.json b/tests/mocks/weather_owm_current.json
new file mode 100644
index 0000000000..021ae166bb
--- /dev/null
+++ b/tests/mocks/weather_owm_current.json
@@ -0,0 +1,28 @@
+{
+ "coord": { "lon": 11.58, "lat": 48.14 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "base": "stations",
+ "main": {
+ "temp": -0.27,
+ "feels_like": -3.9,
+ "temp_min": -1.0,
+ "temp_max": 0.5,
+ "pressure": 1018,
+ "humidity": 54
+ },
+ "visibility": 10000,
+ "wind": { "speed": 3.09, "deg": 220 },
+ "clouds": { "all": 100 },
+ "dt": 1744200000,
+ "sys": {
+ "type": 2,
+ "id": 2002112,
+ "country": "DE",
+ "sunrise": 1744170000,
+ "sunset": 1744218000
+ },
+ "timezone": 7200,
+ "id": 2867714,
+ "name": "Munich",
+ "cod": 200
+}
diff --git a/tests/mocks/weather_owm_forecast.json b/tests/mocks/weather_owm_forecast.json
new file mode 100644
index 0000000000..d9c3e3e075
--- /dev/null
+++ b/tests/mocks/weather_owm_forecast.json
@@ -0,0 +1,180 @@
+{
+ "cod": "200",
+ "message": 0,
+ "cnt": 16,
+ "list": [
+ {
+ "dt": 1744156800,
+ "main": { "temp": -1.0, "feels_like": -4.0, "temp_min": -1.5, "temp_max": -0.5, "pressure": 1018, "humidity": 60 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "clouds": { "all": 100 },
+ "wind": { "speed": 3.0, "deg": 210 },
+ "pop": 0.2,
+ "sys": { "pod": "n" },
+ "dt_txt": "2026-04-09 00:00:00"
+ },
+ {
+ "dt": 1744167600,
+ "main": { "temp": -1.2, "feels_like": -4.2, "temp_min": -1.5, "temp_max": -0.9, "pressure": 1018, "humidity": 62 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "clouds": { "all": 100 },
+ "wind": { "speed": 3.1, "deg": 215 },
+ "pop": 0.2,
+ "sys": { "pod": "n" },
+ "dt_txt": "2026-04-09 03:00:00"
+ },
+ {
+ "dt": 1744178400,
+ "main": { "temp": -0.5, "feels_like": -3.5, "temp_min": -1.0, "temp_max": 0.0, "pressure": 1019, "humidity": 58 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "clouds": { "all": 95 },
+ "wind": { "speed": 2.8, "deg": 220 },
+ "pop": 0.3,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-09 06:00:00"
+ },
+ {
+ "dt": 1744189200,
+ "main": { "temp": 1.0, "feels_like": -2.0, "temp_min": 0.5, "temp_max": 1.5, "pressure": 1019, "humidity": 55 },
+ "weather": [{ "id": 500, "main": "Rain", "description": "light rain", "icon": "10d" }],
+ "clouds": { "all": 90 },
+ "wind": { "speed": 2.5, "deg": 225 },
+ "pop": 0.8,
+ "rain": { "3h": 0.6 },
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-09 09:00:00"
+ },
+ {
+ "dt": 1744200000,
+ "main": { "temp": 2.0, "feels_like": -1.0, "temp_min": 1.5, "temp_max": 2.5, "pressure": 1018, "humidity": 52 },
+ "weather": [{ "id": 500, "main": "Rain", "description": "light rain", "icon": "10d" }],
+ "clouds": { "all": 88 },
+ "wind": { "speed": 2.4, "deg": 230 },
+ "pop": 0.9,
+ "rain": { "3h": 0.6 },
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-09 12:00:00"
+ },
+ {
+ "dt": 1744210800,
+ "main": { "temp": 1.5, "feels_like": -1.5, "temp_min": 1.0, "temp_max": 2.0, "pressure": 1018, "humidity": 54 },
+ "weather": [{ "id": 500, "main": "Rain", "description": "light rain", "icon": "10d" }],
+ "clouds": { "all": 90 },
+ "wind": { "speed": 2.6, "deg": 228 },
+ "pop": 0.8,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-09 15:00:00"
+ },
+ {
+ "dt": 1744221600,
+ "main": { "temp": 0.8, "feels_like": -2.2, "temp_min": 0.5, "temp_max": 1.2, "pressure": 1018, "humidity": 57 },
+ "weather": [{ "id": 500, "main": "Rain", "description": "light rain", "icon": "10d" }],
+ "clouds": { "all": 92 },
+ "wind": { "speed": 2.7, "deg": 222 },
+ "pop": 0.6,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-09 18:00:00"
+ },
+ {
+ "dt": 1744232400,
+ "main": { "temp": -0.2, "feels_like": -3.2, "temp_min": -0.5, "temp_max": 0.1, "pressure": 1019, "humidity": 60 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "clouds": { "all": 95 },
+ "wind": { "speed": 2.9, "deg": 218 },
+ "pop": 0.3,
+ "sys": { "pod": "n" },
+ "dt_txt": "2026-04-09 21:00:00"
+ },
+ {
+ "dt": 1744243200,
+ "main": { "temp": 0.5, "feels_like": -2.5, "temp_min": 0.0, "temp_max": 1.0, "pressure": 1020, "humidity": 58 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "clouds": { "all": 85 },
+ "wind": { "speed": 2.5, "deg": 200 },
+ "pop": 0.1,
+ "sys": { "pod": "n" },
+ "dt_txt": "2026-04-10 00:00:00"
+ },
+ {
+ "dt": 1744254000,
+ "main": { "temp": 1.0, "feels_like": -2.0, "temp_min": 0.5, "temp_max": 1.5, "pressure": 1021, "humidity": 56 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "clouds": { "all": 80 },
+ "wind": { "speed": 2.3, "deg": 205 },
+ "pop": 0.1,
+ "sys": { "pod": "n" },
+ "dt_txt": "2026-04-10 03:00:00"
+ },
+ {
+ "dt": 1744264800,
+ "main": { "temp": 2.0, "feels_like": -1.0, "temp_min": 1.5, "temp_max": 2.5, "pressure": 1021, "humidity": 53 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "clouds": { "all": 75 },
+ "wind": { "speed": 2.1, "deg": 210 },
+ "pop": 0.1,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-10 06:00:00"
+ },
+ {
+ "dt": 1744275600,
+ "main": { "temp": 3.5, "feels_like": 0.5, "temp_min": 3.0, "temp_max": 4.0, "pressure": 1020, "humidity": 50 },
+ "weather": [{ "id": 520, "main": "Rain", "description": "light shower rain", "icon": "09d" }],
+ "clouds": { "all": 70 },
+ "wind": { "speed": 2.0, "deg": 215 },
+ "pop": 0.5,
+ "snow": { "3h": 0.5 },
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-10 09:00:00"
+ },
+ {
+ "dt": 1744286400,
+ "main": { "temp": 5.0, "feels_like": 2.0, "temp_min": 4.5, "temp_max": 5.5, "pressure": 1019, "humidity": 48 },
+ "weather": [{ "id": 520, "main": "Rain", "description": "light shower rain", "icon": "09d" }],
+ "clouds": { "all": 65 },
+ "wind": { "speed": 1.9, "deg": 220 },
+ "pop": 0.4,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-10 12:00:00"
+ },
+ {
+ "dt": 1744297200,
+ "main": { "temp": 4.5, "feels_like": 1.5, "temp_min": 4.0, "temp_max": 5.0, "pressure": 1019, "humidity": 50 },
+ "weather": [{ "id": 520, "main": "Rain", "description": "light shower rain", "icon": "09d" }],
+ "clouds": { "all": 68 },
+ "wind": { "speed": 2.0, "deg": 218 },
+ "pop": 0.4,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-10 15:00:00"
+ },
+ {
+ "dt": 1744308000,
+ "main": { "temp": 3.0, "feels_like": 0.0, "temp_min": 2.5, "temp_max": 3.5, "pressure": 1019, "humidity": 53 },
+ "weather": [{ "id": 520, "main": "Rain", "description": "light shower rain", "icon": "09d" }],
+ "clouds": { "all": 72 },
+ "wind": { "speed": 2.1, "deg": 212 },
+ "pop": 0.3,
+ "sys": { "pod": "d" },
+ "dt_txt": "2026-04-10 18:00:00"
+ },
+ {
+ "dt": 1744318800,
+ "main": { "temp": 1.5, "feels_like": -1.5, "temp_min": 1.0, "temp_max": 2.0, "pressure": 1020, "humidity": 56 },
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "clouds": { "all": 80 },
+ "wind": { "speed": 2.2, "deg": 208 },
+ "pop": 0.2,
+ "sys": { "pod": "n" },
+ "dt_txt": "2026-04-10 21:00:00"
+ }
+ ],
+ "city": {
+ "id": 2867714,
+ "name": "Munich",
+ "coord": { "lat": 48.14, "lon": 11.58 },
+ "country": "DE",
+ "population": 1260391,
+ "timezone": 0,
+ "sunrise": 1744170000,
+ "sunset": 1744218000
+ }
+}
diff --git a/tests/mocks/weather_smhi.json b/tests/mocks/weather_smhi.json
index c08a6e85b0..6273e29791 100644
--- a/tests/mocks/weather_smhi.json
+++ b/tests/mocks/weather_smhi.json
@@ -1,1907 +1,1986 @@
{
- "approvedTime": "2026-02-06T21:31:33Z",
+ "createdTime": "2026-02-06T21:31:33Z",
"referenceTime": "2026-02-06T21:00:00Z",
- "geometry": { "type": "Point", "coordinates": [[18.089437, 59.339222]] },
+ "geometry": {
+ "type": "Point",
+ "coordinates": [18.089437, 59.339222]
+ },
"timeSeries": [
{
- "validTime": "2026-02-06T22:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.5] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [40] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1013.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-06T23:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1013.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.9] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T01:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [37] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.2] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T02:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [31] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.6] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T03:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [33] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T04:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [35] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [89] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.4] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T05:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [35] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.8] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [89] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [11.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T06:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.6] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [37] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.0] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1015.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.5] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T07:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.7] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [36] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1015.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T08:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.5] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [42] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.8] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1016.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [14.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T09:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [41] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [82] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1017.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [17.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T10:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.7] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [44] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [77] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1017.8] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [20.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T11:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [48] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [64] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [28.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [47] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [50] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [38.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T13:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.6] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [42] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [52] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T14:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.5] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.0] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [71] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.4] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [23.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T15:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [32] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [76] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T16:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [31] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.6] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1019.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T17:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.6] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.6] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1019.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T18:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [36] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.0] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1020.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T19:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [33] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.0] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1020.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.7] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T20:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.5] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [32] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.0] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.0] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.0] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [15.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [2] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T21:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [32] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [90] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.4] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [2] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T22:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [90] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [10.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [2] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-07T23:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [44] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.1] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [89] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1022.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [46] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.8] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.6] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1022.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T01:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [53] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.9] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1022.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T02:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [49] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T03:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [39] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.4] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T04:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [40] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.6] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [5.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T05:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [46] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.0] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [5.6] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T06:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [63] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.2] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T07:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [55] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [16.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T08:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [54] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.8] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [15.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T09:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [53] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [14.7] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T10:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [66] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [82] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T11:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.6] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [103] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.4] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [64] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [29.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [116] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.2] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [55] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.0] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T13:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [118] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [54] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T14:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [123] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.4] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [55] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.0] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [35.2] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T15:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [120] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.4] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [60] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.0] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.5] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T16:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [116] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [65] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.8] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T17:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [115] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.8] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [71] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [24.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T18:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.7] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [107] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.4] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [78] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [19.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T19:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.5] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [117] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.4] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [17.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T20:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [124] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T21:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [138] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.0] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T22:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [157] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.0] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.2] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-08T23:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [174] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.2] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-09T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [182] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.2] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [79] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-09T03:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.5] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [223] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.6] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.9] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [78] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [19.5] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-09T06:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [251] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [77] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1020.4] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [20.4] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
- ]
- },
- {
- "validTime": "2026-02-09T09:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [264] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.8] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [76] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1019.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [21.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-09T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [254] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.8] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1017.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [19.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-09T18:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [250] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1015.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [22.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-10T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [271] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [0.8] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.0] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1012.9] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [7.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-10T06:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-10.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [253] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1009.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [8.2] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-10T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [249] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.3] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1006.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [10.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-10T18:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-10.3] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [318] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.0] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.0] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1003.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.4] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-11T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-13.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [314] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [0.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [91] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1001.5] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-11T06:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-11.2] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [348] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.0] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [999.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [43.7] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-11T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [344] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.0] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [82] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [998.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [49.2] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-11T18:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [52] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [996.1] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [40.7] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-12T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [49] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [994.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [39.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.4] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-12T06:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.6] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [56] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.9] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.6] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [993.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [29.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-12T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.7] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [55] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.5] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [10.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [81] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [993.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.5] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.5] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-12T18:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.1] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [45] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [10.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [994.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.7] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.4] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-13T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.0] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [9.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [994.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.1] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.6] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [88] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-13T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.7] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [19] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.4] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [10.5] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [996.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [33.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.5] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-14T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-10.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [3] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.7] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [9.4] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [999.6] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [37.5] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-14T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.0] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [350] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.9] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [9.6] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [75] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1002.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [38.9] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-15T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-11.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [321] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.1] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1007.3] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [40.6] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-15T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.9] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [304] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [72] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1011.2] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [43.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.4] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-16T00:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.4] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [292] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1013.8] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [43.3] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
- },
- {
- "validTime": "2026-02-16T12:00:00Z",
- "parameters": [
- { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.8] },
- { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [295] },
- { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
- { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.3] },
- { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [78] },
- { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.7] },
- { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [45.8] },
- { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
- { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
- { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
- { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
- { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
- { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
- { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
- { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
- { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
- { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
- { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
- { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
- ]
+ "time": "2026-02-06T22:00:00Z",
+ "intervalParametersStartTime": "2026-02-06T22:00:00Z",
+ "data": {
+ "air_temperature": -5.5,
+ "wind_from_direction": 40,
+ "wind_speed": 4.3,
+ "wind_speed_of_gust": 7.8,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 1013.6,
+ "visibility_in_air": 12.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.1,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-06T23:00:00Z",
+ "intervalParametersStartTime": "2026-02-06T23:00:00Z",
+ "data": {
+ "air_temperature": -5.4,
+ "wind_from_direction": 38,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 7.7,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 1013.9,
+ "visibility_in_air": 12.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.1,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T00:00:00Z",
+ "data": {
+ "air_temperature": -5.3,
+ "wind_from_direction": 38,
+ "wind_speed": 3.9,
+ "wind_speed_of_gust": 7.7,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 1014.2,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 7,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.1,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T01:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T01:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 37,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 7.2,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 1014.2,
+ "visibility_in_air": 12.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 6,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T02:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T02:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 31,
+ "wind_speed": 3.5,
+ "wind_speed_of_gust": 6.8,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 1014.2,
+ "visibility_in_air": 12.6,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 5,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T03:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T03:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 33,
+ "wind_speed": 3.6,
+ "wind_speed_of_gust": 6.5,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 1014.1,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 6,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T04:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T04:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 35,
+ "wind_speed": 3.6,
+ "wind_speed_of_gust": 6.8,
+ "relative_humidity": 89,
+ "air_pressure_at_mean_sea_level": 1014.4,
+ "visibility_in_air": 12.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T05:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T05:00:00Z",
+ "data": {
+ "air_temperature": -5.4,
+ "wind_from_direction": 35,
+ "wind_speed": 3.8,
+ "wind_speed_of_gust": 6.9,
+ "relative_humidity": 89,
+ "air_pressure_at_mean_sea_level": 1014.7,
+ "visibility_in_air": 11.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 5,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T06:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T06:00:00Z",
+ "data": {
+ "air_temperature": -5.6,
+ "wind_from_direction": 37,
+ "wind_speed": 4.4,
+ "wind_speed_of_gust": 8.0,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 1015.3,
+ "visibility_in_air": 12.5,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 4,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T07:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T07:00:00Z",
+ "data": {
+ "air_temperature": -5.7,
+ "wind_from_direction": 36,
+ "wind_speed": 4.6,
+ "wind_speed_of_gust": 8.5,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 1015.9,
+ "visibility_in_air": 12.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T08:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T08:00:00Z",
+ "data": {
+ "air_temperature": -5.5,
+ "wind_from_direction": 42,
+ "wind_speed": 4.8,
+ "wind_speed_of_gust": 8.9,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 1016.5,
+ "visibility_in_air": 14.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 7,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T09:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T09:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 41,
+ "wind_speed": 4.3,
+ "wind_speed_of_gust": 8.7,
+ "relative_humidity": 82,
+ "air_pressure_at_mean_sea_level": 1017.3,
+ "visibility_in_air": 17.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 4,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 6,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T10:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T10:00:00Z",
+ "data": {
+ "air_temperature": -4.7,
+ "wind_from_direction": 44,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 7.9,
+ "relative_humidity": 77,
+ "air_pressure_at_mean_sea_level": 1017.8,
+ "visibility_in_air": 20.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 5,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 4,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T11:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T11:00:00Z",
+ "data": {
+ "air_temperature": -4.1,
+ "wind_from_direction": 48,
+ "wind_speed": 4.3,
+ "wind_speed_of_gust": 7.9,
+ "relative_humidity": 64,
+ "air_pressure_at_mean_sea_level": 1018.1,
+ "visibility_in_air": 28.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 6,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 3,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T12:00:00Z",
+ "data": {
+ "air_temperature": -3.9,
+ "wind_from_direction": 47,
+ "wind_speed": 4.3,
+ "wind_speed_of_gust": 7.9,
+ "relative_humidity": 50,
+ "air_pressure_at_mean_sea_level": 1018.1,
+ "visibility_in_air": 38.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 2,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T13:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T13:00:00Z",
+ "data": {
+ "air_temperature": -3.6,
+ "wind_from_direction": 42,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 7.9,
+ "relative_humidity": 52,
+ "air_pressure_at_mean_sea_level": 1018.1,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 1,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T14:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T14:00:00Z",
+ "data": {
+ "air_temperature": -3.5,
+ "wind_from_direction": 38,
+ "wind_speed": 4.0,
+ "wind_speed_of_gust": 7.7,
+ "relative_humidity": 71,
+ "air_pressure_at_mean_sea_level": 1018.4,
+ "visibility_in_air": 23.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T15:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T15:00:00Z",
+ "data": {
+ "air_temperature": -3.9,
+ "wind_from_direction": 32,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 7.3,
+ "relative_humidity": 76,
+ "air_pressure_at_mean_sea_level": 1018.9,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T16:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T16:00:00Z",
+ "data": {
+ "air_temperature": -4.2,
+ "wind_from_direction": 31,
+ "wind_speed": 3.1,
+ "wind_speed_of_gust": 6.6,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1019.2,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 6,
+ "low_type_cloud_area_fraction": 6,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T17:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T17:00:00Z",
+ "data": {
+ "air_temperature": -4.6,
+ "wind_from_direction": 38,
+ "wind_speed": 3.4,
+ "wind_speed_of_gust": 5.6,
+ "relative_humidity": 84,
+ "air_pressure_at_mean_sea_level": 1019.6,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 4,
+ "low_type_cloud_area_fraction": 4,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T18:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T18:00:00Z",
+ "data": {
+ "air_temperature": -5.4,
+ "wind_from_direction": 36,
+ "wind_speed": 3.6,
+ "wind_speed_of_gust": 7.0,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 1020.1,
+ "visibility_in_air": 13.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 1,
+ "low_type_cloud_area_fraction": 1,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 1,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T19:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T19:00:00Z",
+ "data": {
+ "air_temperature": -6.1,
+ "wind_from_direction": 33,
+ "wind_speed": 3.6,
+ "wind_speed_of_gust": 6.0,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 1020.5,
+ "visibility_in_air": 13.7,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 0,
+ "low_type_cloud_area_fraction": 0,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 1,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T20:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T20:00:00Z",
+ "data": {
+ "air_temperature": -6.5,
+ "wind_from_direction": 32,
+ "wind_speed": 4.0,
+ "wind_speed_of_gust": 7.0,
+ "relative_humidity": 84,
+ "air_pressure_at_mean_sea_level": 1021.0,
+ "visibility_in_air": 15.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 1,
+ "low_type_cloud_area_fraction": 1,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 2,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T21:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T21:00:00Z",
+ "data": {
+ "air_temperature": -6.8,
+ "wind_from_direction": 32,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 7.3,
+ "relative_humidity": 90,
+ "air_pressure_at_mean_sea_level": 1021.4,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 3,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 2,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T22:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T22:00:00Z",
+ "data": {
+ "air_temperature": -6.3,
+ "wind_from_direction": 38,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 7.3,
+ "relative_humidity": 90,
+ "air_pressure_at_mean_sea_level": 1021.9,
+ "visibility_in_air": 10.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 3,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 2,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-07T23:00:00Z",
+ "intervalParametersStartTime": "2026-02-07T23:00:00Z",
+ "data": {
+ "air_temperature": -5.9,
+ "wind_from_direction": 44,
+ "wind_speed": 4.5,
+ "wind_speed_of_gust": 8.1,
+ "relative_humidity": 89,
+ "air_pressure_at_mean_sea_level": 1022.3,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 4,
+ "low_type_cloud_area_fraction": 4,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T00:00:00Z",
+ "data": {
+ "air_temperature": -5.9,
+ "wind_from_direction": 46,
+ "wind_speed": 4.8,
+ "wind_speed_of_gust": 8.6,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 1022.5,
+ "visibility_in_air": 13.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 6,
+ "low_type_cloud_area_fraction": 6,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T01:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T01:00:00Z",
+ "data": {
+ "air_temperature": -5.8,
+ "wind_from_direction": 53,
+ "wind_speed": 4.9,
+ "wind_speed_of_gust": 8.9,
+ "relative_humidity": 84,
+ "air_pressure_at_mean_sea_level": 1022.9,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T02:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T02:00:00Z",
+ "data": {
+ "air_temperature": -5.8,
+ "wind_from_direction": 49,
+ "wind_speed": 4.6,
+ "wind_speed_of_gust": 8.9,
+ "relative_humidity": 84,
+ "air_pressure_at_mean_sea_level": 1023.2,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T03:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T03:00:00Z",
+ "data": {
+ "air_temperature": -5.9,
+ "wind_from_direction": 39,
+ "wind_speed": 4.1,
+ "wind_speed_of_gust": 8.4,
+ "relative_humidity": 85,
+ "air_pressure_at_mean_sea_level": 1023.6,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T04:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T04:00:00Z",
+ "data": {
+ "air_temperature": -6.0,
+ "wind_from_direction": 40,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 7.6,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 1023.9,
+ "visibility_in_air": 5.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T05:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T05:00:00Z",
+ "data": {
+ "air_temperature": -5.8,
+ "wind_from_direction": 46,
+ "wind_speed": 3.3,
+ "wind_speed_of_gust": 6.8,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 1024.0,
+ "visibility_in_air": 5.6,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T06:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T06:00:00Z",
+ "data": {
+ "air_temperature": -5.4,
+ "wind_from_direction": 63,
+ "wind_speed": 3.4,
+ "wind_speed_of_gust": 6.2,
+ "relative_humidity": 83,
+ "air_pressure_at_mean_sea_level": 1024.2,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T07:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T07:00:00Z",
+ "data": {
+ "air_temperature": -5.3,
+ "wind_from_direction": 55,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 6.9,
+ "relative_humidity": 83,
+ "air_pressure_at_mean_sea_level": 1024.5,
+ "visibility_in_air": 16.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T08:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T08:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 54,
+ "wind_speed": 3.4,
+ "wind_speed_of_gust": 6.7,
+ "relative_humidity": 83,
+ "air_pressure_at_mean_sea_level": 1024.8,
+ "visibility_in_air": 15.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T09:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T09:00:00Z",
+ "data": {
+ "air_temperature": -4.8,
+ "wind_from_direction": 53,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 6.8,
+ "relative_humidity": 85,
+ "air_pressure_at_mean_sea_level": 1025.1,
+ "visibility_in_air": 14.7,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T10:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T10:00:00Z",
+ "data": {
+ "air_temperature": -3.8,
+ "wind_from_direction": 66,
+ "wind_speed": 3.5,
+ "wind_speed_of_gust": 6.8,
+ "relative_humidity": 82,
+ "air_pressure_at_mean_sea_level": 1025.2,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T11:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T11:00:00Z",
+ "data": {
+ "air_temperature": -2.6,
+ "wind_from_direction": 103,
+ "wind_speed": 3.1,
+ "wind_speed_of_gust": 6.4,
+ "relative_humidity": 64,
+ "air_pressure_at_mean_sea_level": 1025.1,
+ "visibility_in_air": 29.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T12:00:00Z",
+ "data": {
+ "air_temperature": -2.2,
+ "wind_from_direction": 116,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 7.2,
+ "relative_humidity": 55,
+ "air_pressure_at_mean_sea_level": 1025.0,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T13:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T13:00:00Z",
+ "data": {
+ "air_temperature": -2.0,
+ "wind_from_direction": 118,
+ "wind_speed": 3.5,
+ "wind_speed_of_gust": 6.9,
+ "relative_humidity": 54,
+ "air_pressure_at_mean_sea_level": 1024.9,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-08T14:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T14:00:00Z",
+ "data": {
+ "air_temperature": -2.1,
+ "wind_from_direction": 123,
+ "wind_speed": 3.1,
+ "wind_speed_of_gust": 6.4,
+ "relative_humidity": 55,
+ "air_pressure_at_mean_sea_level": 1025.0,
+ "visibility_in_air": 35.2,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": -0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-08T15:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T15:00:00Z",
+ "data": {
+ "air_temperature": -2.9,
+ "wind_from_direction": 120,
+ "wind_speed": 2.5,
+ "wind_speed_of_gust": 5.4,
+ "relative_humidity": 60,
+ "air_pressure_at_mean_sea_level": 1025.0,
+ "visibility_in_air": 31.5,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-08T16:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T16:00:00Z",
+ "data": {
+ "air_temperature": -4.2,
+ "wind_from_direction": 116,
+ "wind_speed": 2.1,
+ "wind_speed_of_gust": 4.1,
+ "relative_humidity": 65,
+ "air_pressure_at_mean_sea_level": 1024.8,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 5,
+ "low_type_cloud_area_fraction": 5,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T17:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T17:00:00Z",
+ "data": {
+ "air_temperature": -5.2,
+ "wind_from_direction": 115,
+ "wind_speed": 1.8,
+ "wind_speed_of_gust": 3.1,
+ "relative_humidity": 71,
+ "air_pressure_at_mean_sea_level": 1024.6,
+ "visibility_in_air": 24.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 5,
+ "low_type_cloud_area_fraction": 5,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T18:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T18:00:00Z",
+ "data": {
+ "air_temperature": -6.7,
+ "wind_from_direction": 107,
+ "wind_speed": 1.4,
+ "wind_speed_of_gust": 2.4,
+ "relative_humidity": 78,
+ "air_pressure_at_mean_sea_level": 1024.5,
+ "visibility_in_air": 19.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 5,
+ "low_type_cloud_area_fraction": 5,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T19:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T19:00:00Z",
+ "data": {
+ "air_temperature": -7.5,
+ "wind_from_direction": 117,
+ "wind_speed": 1.3,
+ "wind_speed_of_gust": 1.9,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1024.4,
+ "visibility_in_air": 17.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 6,
+ "low_type_cloud_area_fraction": 6,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-08T20:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T20:00:00Z",
+ "data": {
+ "air_temperature": -8.1,
+ "wind_from_direction": 124,
+ "wind_speed": 1.2,
+ "wind_speed_of_gust": 1.7,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1024.3,
+ "visibility_in_air": 75.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T21:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T21:00:00Z",
+ "data": {
+ "air_temperature": -8.2,
+ "wind_from_direction": 138,
+ "wind_speed": 1.2,
+ "wind_speed_of_gust": 1.7,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1024.2,
+ "visibility_in_air": 18.0,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-08T22:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T22:00:00Z",
+ "data": {
+ "air_temperature": -8.3,
+ "wind_from_direction": 157,
+ "wind_speed": 1.4,
+ "wind_speed_of_gust": 1.8,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1024.0,
+ "visibility_in_air": 18.2,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-08T23:00:00Z",
+ "intervalParametersStartTime": "2026-02-08T23:00:00Z",
+ "data": {
+ "air_temperature": -8.3,
+ "wind_from_direction": 174,
+ "wind_speed": 1.4,
+ "wind_speed_of_gust": 1.9,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1023.6,
+ "visibility_in_air": 18.2,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-09T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-09T00:00:00Z",
+ "data": {
+ "air_temperature": -8.3,
+ "wind_from_direction": 182,
+ "wind_speed": 1.7,
+ "wind_speed_of_gust": 2.2,
+ "relative_humidity": 79,
+ "air_pressure_at_mean_sea_level": 1023.2,
+ "visibility_in_air": 18.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-09T03:00:00Z",
+ "intervalParametersStartTime": "2026-02-09T03:00:00Z",
+ "data": {
+ "air_temperature": -7.5,
+ "wind_from_direction": 223,
+ "wind_speed": 2.6,
+ "wind_speed_of_gust": 3.9,
+ "relative_humidity": 78,
+ "air_pressure_at_mean_sea_level": 1021.3,
+ "visibility_in_air": 19.5,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": -0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-09T06:00:00Z",
+ "intervalParametersStartTime": "2026-02-09T06:00:00Z",
+ "data": {
+ "air_temperature": -7.0,
+ "wind_from_direction": 251,
+ "wind_speed": 2.4,
+ "wind_speed_of_gust": 3.8,
+ "relative_humidity": 77,
+ "air_pressure_at_mean_sea_level": 1020.4,
+ "visibility_in_air": 20.4,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": -0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": -0.0
+ }
+ },
+ {
+ "time": "2026-02-09T09:00:00Z",
+ "intervalParametersStartTime": "2026-02-09T09:00:00Z",
+ "data": {
+ "air_temperature": -7.0,
+ "wind_from_direction": 264,
+ "wind_speed": 2.8,
+ "wind_speed_of_gust": 4.7,
+ "relative_humidity": 76,
+ "air_pressure_at_mean_sea_level": 1019.9,
+ "visibility_in_air": 21.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-09T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-09T12:00:00Z",
+ "data": {
+ "air_temperature": -7.0,
+ "wind_from_direction": 254,
+ "wind_speed": 3.5,
+ "wind_speed_of_gust": 7.8,
+ "relative_humidity": 84,
+ "air_pressure_at_mean_sea_level": 1017.7,
+ "visibility_in_air": 19.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-09T18:00:00Z",
+ "intervalParametersStartTime": "2026-02-09T18:00:00Z",
+ "data": {
+ "air_temperature": -9.4,
+ "wind_from_direction": 250,
+ "wind_speed": 2.3,
+ "wind_speed_of_gust": 4.5,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 1015.3,
+ "visibility_in_air": 22.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-10T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-10T00:00:00Z",
+ "data": {
+ "air_temperature": -9.9,
+ "wind_from_direction": 271,
+ "wind_speed": 0.8,
+ "wind_speed_of_gust": 2.0,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 1012.9,
+ "visibility_in_air": 7.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-10T06:00:00Z",
+ "intervalParametersStartTime": "2026-02-10T06:00:00Z",
+ "data": {
+ "air_temperature": -10.3,
+ "wind_from_direction": 253,
+ "wind_speed": 1.3,
+ "wind_speed_of_gust": 3.3,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 1009.6,
+ "visibility_in_air": 8.2,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 7,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-10T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-10T12:00:00Z",
+ "data": {
+ "air_temperature": -9.1,
+ "wind_from_direction": 249,
+ "wind_speed": 2.3,
+ "wind_speed_of_gust": 5.3,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 1006.5,
+ "visibility_in_air": 10.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": -9,
+ "predominant_precipitation_type_at_surface": 0,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-10T18:00:00Z",
+ "intervalParametersStartTime": "2026-02-10T18:00:00Z",
+ "data": {
+ "air_temperature": -10.3,
+ "wind_from_direction": 318,
+ "wind_speed": 1.0,
+ "wind_speed_of_gust": 3.0,
+ "relative_humidity": 85,
+ "air_pressure_at_mean_sea_level": 1003.7,
+ "visibility_in_air": 13.4,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.0,
+ "precipitation_amount_max": 0.0,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-11T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-11T00:00:00Z",
+ "data": {
+ "air_temperature": -13.1,
+ "wind_from_direction": 314,
+ "wind_speed": 0.5,
+ "wind_speed_of_gust": 1.5,
+ "relative_humidity": 91,
+ "air_pressure_at_mean_sea_level": 1001.5,
+ "visibility_in_air": 13.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 4,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 1,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.1,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-11T06:00:00Z",
+ "intervalParametersStartTime": "2026-02-11T06:00:00Z",
+ "data": {
+ "air_temperature": -11.2,
+ "wind_from_direction": 348,
+ "wind_speed": 1.0,
+ "wind_speed_of_gust": 2.3,
+ "relative_humidity": 88,
+ "air_pressure_at_mean_sea_level": 999.3,
+ "visibility_in_air": 43.7,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 0,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.2,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-11T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-11T12:00:00Z",
+ "data": {
+ "air_temperature": -5.1,
+ "wind_from_direction": 344,
+ "wind_speed": 2.0,
+ "wind_speed_of_gust": 4.5,
+ "relative_humidity": 82,
+ "air_pressure_at_mean_sea_level": 998.2,
+ "visibility_in_air": 49.2,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 0,
+ "high_type_cloud_area_fraction": 8,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.2,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-11T18:00:00Z",
+ "intervalParametersStartTime": "2026-02-11T18:00:00Z",
+ "data": {
+ "air_temperature": -5.8,
+ "wind_from_direction": 52,
+ "wind_speed": 3.7,
+ "wind_speed_of_gust": 6.5,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 996.1,
+ "visibility_in_air": 40.7,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 3,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.3,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-12T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-12T00:00:00Z",
+ "data": {
+ "air_temperature": -6.1,
+ "wind_from_direction": 49,
+ "wind_speed": 4.1,
+ "wind_speed_of_gust": 7.3,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 994.7,
+ "visibility_in_air": 39.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 3,
+ "high_type_cloud_area_fraction": 3,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.2,
+ "precipitation_amount_max": 0.4,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-12T06:00:00Z",
+ "intervalParametersStartTime": "2026-02-12T06:00:00Z",
+ "data": {
+ "air_temperature": -6.6,
+ "wind_from_direction": 56,
+ "wind_speed": 4.9,
+ "wind_speed_of_gust": 8.6,
+ "relative_humidity": 87,
+ "air_pressure_at_mean_sea_level": 993.3,
+ "visibility_in_air": 29.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 3,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.3,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-12T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-12T12:00:00Z",
+ "data": {
+ "air_temperature": -5.7,
+ "wind_from_direction": 55,
+ "wind_speed": 5.5,
+ "wind_speed_of_gust": 10.3,
+ "relative_humidity": 81,
+ "air_pressure_at_mean_sea_level": 993.6,
+ "visibility_in_air": 31.5,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 3,
+ "precipitation_amount_mean": 0.1,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.5,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-12T18:00:00Z",
+ "intervalParametersStartTime": "2026-02-12T18:00:00Z",
+ "data": {
+ "air_temperature": -7.1,
+ "wind_from_direction": 45,
+ "wind_speed": 5.2,
+ "wind_speed_of_gust": 10.3,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 994.2,
+ "visibility_in_air": 31.7,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 4,
+ "precipitation_amount_mean": 0.1,
+ "precipitation_amount_min": 0.2,
+ "precipitation_amount_max": 0.4,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-13T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-13T00:00:00Z",
+ "data": {
+ "air_temperature": -7.9,
+ "wind_from_direction": 38,
+ "wind_speed": 5.0,
+ "wind_speed_of_gust": 9.5,
+ "relative_humidity": 86,
+ "air_pressure_at_mean_sea_level": 994.7,
+ "visibility_in_air": 31.1,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 8,
+ "medium_type_cloud_area_fraction": 5,
+ "high_type_cloud_area_fraction": 4,
+ "precipitation_amount_mean": 0.1,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.6,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 88,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 6,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-13T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-13T12:00:00Z",
+ "data": {
+ "air_temperature": -7.7,
+ "wind_from_direction": 19,
+ "wind_speed": 5.4,
+ "wind_speed_of_gust": 10.5,
+ "relative_humidity": 80,
+ "air_pressure_at_mean_sea_level": 996.6,
+ "visibility_in_air": 33.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 8,
+ "low_type_cloud_area_fraction": 7,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 2,
+ "precipitation_amount_mean": 0.1,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.5,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-14T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-14T00:00:00Z",
+ "data": {
+ "air_temperature": -10.0,
+ "wind_from_direction": 3,
+ "wind_speed": 4.7,
+ "wind_speed_of_gust": 9.4,
+ "relative_humidity": 85,
+ "air_pressure_at_mean_sea_level": 999.6,
+ "visibility_in_air": 37.5,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 7,
+ "low_type_cloud_area_fraction": 6,
+ "medium_type_cloud_area_fraction": 4,
+ "high_type_cloud_area_fraction": 2,
+ "precipitation_amount_mean": 0.1,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.3,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-14T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-14T12:00:00Z",
+ "data": {
+ "air_temperature": -8.0,
+ "wind_from_direction": 350,
+ "wind_speed": 4.9,
+ "wind_speed_of_gust": 9.6,
+ "relative_humidity": 75,
+ "air_pressure_at_mean_sea_level": 1002.7,
+ "visibility_in_air": 38.9,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 6,
+ "low_type_cloud_area_fraction": 5,
+ "medium_type_cloud_area_fraction": 3,
+ "high_type_cloud_area_fraction": 1,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.3,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-15T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-15T00:00:00Z",
+ "data": {
+ "air_temperature": -11.4,
+ "wind_from_direction": 321,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 8.1,
+ "relative_humidity": 83,
+ "air_pressure_at_mean_sea_level": 1007.3,
+ "visibility_in_air": 40.6,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 5,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 3,
+ "high_type_cloud_area_fraction": 1,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.3,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-15T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-15T12:00:00Z",
+ "data": {
+ "air_temperature": -7.9,
+ "wind_from_direction": 304,
+ "wind_speed": 4.1,
+ "wind_speed_of_gust": 8.3,
+ "relative_humidity": 72,
+ "air_pressure_at_mean_sea_level": 1011.2,
+ "visibility_in_air": 43.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 4,
+ "low_type_cloud_area_fraction": 3,
+ "medium_type_cloud_area_fraction": 2,
+ "high_type_cloud_area_fraction": 1,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.4,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-16T00:00:00Z",
+ "intervalParametersStartTime": "2026-02-16T00:00:00Z",
+ "data": {
+ "air_temperature": -9.4,
+ "wind_from_direction": 292,
+ "wind_speed": 4.2,
+ "wind_speed_of_gust": 7.7,
+ "relative_humidity": 85,
+ "air_pressure_at_mean_sea_level": 1013.8,
+ "visibility_in_air": 43.3,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 5,
+ "low_type_cloud_area_fraction": 4,
+ "medium_type_cloud_area_fraction": 2,
+ "high_type_cloud_area_fraction": 1,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.1,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 3,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
+ },
+ {
+ "time": "2026-02-16T12:00:00Z",
+ "intervalParametersStartTime": "2026-02-16T12:00:00Z",
+ "data": {
+ "air_temperature": -4.8,
+ "wind_from_direction": 295,
+ "wind_speed": 4.1,
+ "wind_speed_of_gust": 8.3,
+ "relative_humidity": 78,
+ "air_pressure_at_mean_sea_level": 1014.7,
+ "visibility_in_air": 45.8,
+ "thunderstorm_probability": 0,
+ "cloud_area_fraction": 6,
+ "low_type_cloud_area_fraction": 4,
+ "medium_type_cloud_area_fraction": 3,
+ "high_type_cloud_area_fraction": 2,
+ "precipitation_amount_mean": 0.0,
+ "precipitation_amount_min": 0.1,
+ "precipitation_amount_max": 0.2,
+ "precipitation_amount_median": 0.0,
+ "precipitation_frozen_part": 100,
+ "predominant_precipitation_type_at_surface": 5,
+ "symbol_code": 4,
+ "precipitation_amount_mean_deterministic": 0.0
+ }
}
]
}
diff --git a/tests/unit/functions/http_fetcher_spec.js b/tests/unit/functions/http_fetcher_spec.js
index 046ddb9ca0..122025a26c 100644
--- a/tests/unit/functions/http_fetcher_spec.js
+++ b/tests/unit/functions/http_fetcher_spec.js
@@ -51,6 +51,31 @@ describe("HTTPFetcher", () => {
expect(text).toBe(responseData);
});
+ it("should treat 304 responses as successful and reset error counters", async () => {
+ server.use(
+ http.get(TEST_URL, () => {
+ return new HttpResponse(null, { status: 304 });
+ })
+ );
+
+ fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 60000 });
+ fetcher.serverErrorCount = 2;
+ fetcher.networkErrorCount = 3;
+
+ const responsePromise = new Promise((resolve) => {
+ fetcher.on("response", (response) => {
+ resolve(response);
+ });
+ });
+
+ fetcher.startPeriodicFetch();
+ const response = await responsePromise;
+
+ expect(response.status).toBe(304);
+ expect(fetcher.serverErrorCount).toBe(0);
+ expect(fetcher.networkErrorCount).toBe(0);
+ });
+
it("should emit error event on network failure", async () => {
server.use(
http.get(TEST_URL, () => {
@@ -440,3 +465,112 @@ describe("fetch() method", () => {
expect(errorInfo.errorType).toBe("NETWORK_ERROR");
});
});
+
+describe("selfSignedCert dispatcher", () => {
+ const { Agent } = require("undici");
+
+ it("should set rejectUnauthorized=false when selfSignedCert is true", () => {
+ fetcher = new HTTPFetcher(TEST_URL, {
+ reloadInterval: 60000,
+ selfSignedCert: true
+ });
+
+ const options = fetcher.getRequestOptions();
+
+ expect(options.dispatcher).toBeInstanceOf(Agent);
+ const agentOptionsSymbol = Object.getOwnPropertySymbols(options.dispatcher).find((s) => s.description === "options");
+ const dispatcherOptions = options.dispatcher[agentOptionsSymbol];
+ expect(dispatcherOptions.connect.rejectUnauthorized).toBe(false);
+ });
+
+ it("should not set a dispatcher when selfSignedCert is false", () => {
+ fetcher = new HTTPFetcher(TEST_URL, {
+ reloadInterval: 60000,
+ selfSignedCert: false
+ });
+
+ const options = fetcher.getRequestOptions();
+
+ expect(options.dispatcher).toBeUndefined();
+ });
+});
+
+describe("Retry exhaustion fallback", () => {
+ it("should fall back to reloadInterval after network retries exhausted", async () => {
+ server.use(
+ http.get(TEST_URL, () => {
+ return HttpResponse.error();
+ })
+ );
+
+ fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 300000, maxRetries: 3 });
+
+ const errors = [];
+ fetcher.on("error", (errorInfo) => errors.push(errorInfo));
+
+ // Trigger maxRetries + 1 fetches to reach exhaustion
+ for (let i = 0; i < 4; i++) {
+ await fetcher.fetch();
+ }
+
+ // First retries should use backoff (< reloadInterval)
+ expect(errors[0].retryAfter).toBe(15000);
+ expect(errors[1].retryAfter).toBe(30000);
+ // Third retry hits maxRetries, should fall back to reloadInterval
+ expect(errors[2].retryAfter).toBe(300000);
+ // Subsequent errors stay at reloadInterval
+ expect(errors[3].retryAfter).toBe(300000);
+ });
+
+ it("should fall back to reloadInterval after server error retries exhausted", async () => {
+ server.use(
+ http.get(TEST_URL, () => {
+ return new HttpResponse(null, { status: 503 });
+ })
+ );
+
+ fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 300000, maxRetries: 3 });
+
+ const errors = [];
+ fetcher.on("error", (errorInfo) => errors.push(errorInfo));
+
+ for (let i = 0; i < 4; i++) {
+ await fetcher.fetch();
+ }
+
+ // First retries should use backoff (< reloadInterval)
+ expect(errors[0].retryAfter).toBe(15000);
+ expect(errors[1].retryAfter).toBe(30000);
+ // Third retry hits maxRetries, should fall back to reloadInterval
+ expect(errors[2].retryAfter).toBe(300000);
+ // Subsequent errors stay at reloadInterval
+ expect(errors[3].retryAfter).toBe(300000);
+ });
+
+ it("should reset network error count on success", async () => {
+ let requestCount = 0;
+ server.use(
+ http.get(TEST_URL, () => {
+ requestCount++;
+ if (requestCount <= 2) return HttpResponse.error();
+ return HttpResponse.text("ok");
+ })
+ );
+
+ fetcher = new HTTPFetcher(TEST_URL, { reloadInterval: 300000, maxRetries: 3 });
+
+ const errors = [];
+ fetcher.on("error", (errorInfo) => errors.push(errorInfo));
+
+ // Two failures with backoff
+ await fetcher.fetch();
+ await fetcher.fetch();
+ expect(errors).toHaveLength(2);
+ expect(errors[0].retryAfter).toBe(15000);
+ expect(errors[1].retryAfter).toBe(30000);
+
+ // Success resets counter
+ await fetcher.fetch();
+ expect(fetcher.networkErrorCount).toBe(0);
+ });
+});
diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js
index 8fd0a01450..8c38cf9f0a 100644
--- a/tests/unit/functions/server_functions_spec.js
+++ b/tests/unit/functions/server_functions_spec.js
@@ -1,7 +1,18 @@
+// Tests use vi.spyOn on shared module objects (dns, undici).
+// vi.spyOn modifies the object property directly on the cached module instance, so it
+// is intercepted by server_functions.js regardless of the Module.prototype.require override
+// in vitest-setup.js. restoreAllMocks:true auto-restores spies, but may reuse the same
+// spy instance — mockClear() is called explicitly in beforeEach to reset call history.
+const dns = require("node:dns");
+const undici = require("undici");
const { cors, getUserAgent, replaceSecretPlaceholder } = require("#server_functions");
describe("server_functions tests", () => {
- describe("The replaceSecretPlaceholder method", () => {
+ describe("The replaceSecretPlaceholder method with cors=allowWhitelist", () => {
+ beforeEach(() => {
+ global.config = { cors: "allowWhitelist" };
+ });
+
it("Calls string without secret placeholder", () => {
const teststring = "test string without secret placeholder";
const result = replaceSecretPlaceholder(teststring);
@@ -18,29 +29,48 @@ describe("server_functions tests", () => {
});
});
+ describe("The replaceSecretPlaceholder method with cors=allowAll", () => {
+ beforeEach(() => {
+ global.config = { cors: "allowAll" };
+ });
+
+ it("Calls string without secret placeholder", () => {
+ const teststring = "test string without secret placeholder";
+ const result = replaceSecretPlaceholder(teststring);
+ expect(result).toBe(teststring);
+ });
+
+ it("Calls string with 2 secret placeholders", () => {
+ const teststring = "test string with secret1=**SECRET_ONE** and secret2=**SECRET_TWO**";
+ const result = replaceSecretPlaceholder(teststring);
+ expect(result).toBe(teststring);
+ });
+ });
+
describe("The cors method", () => {
- let fetchResponse;
+ let fetchSpy;
let fetchResponseHeadersGet;
let fetchResponseArrayBuffer;
let corsResponse;
let request;
- let fetchMock;
beforeEach(() => {
+ global.config = { cors: "allowAll" };
fetchResponseHeadersGet = vi.fn(() => {});
fetchResponseArrayBuffer = vi.fn(() => {});
- fetchResponse = {
- headers: {
- get: fetchResponseHeadersGet
- },
- arrayBuffer: fetchResponseArrayBuffer,
- ok: true
- };
- fetch = vi.fn();
- fetch.mockImplementation(() => fetchResponse);
+ // Mock DNS to return a public IP (SSRF check must pass for these tests)
+ vi.spyOn(dns.promises, "lookup").mockResolvedValue({ address: "93.184.216.34", family: 4 });
- fetchMock = fetch;
+ // vi.spyOn may return the same spy instance across tests when restoreAllMocks
+ // restores-but-reuses; mockClear() explicitly resets call history each time.
+ fetchSpy = vi.spyOn(undici, "fetch");
+ fetchSpy.mockClear();
+ fetchSpy.mockImplementation(() => Promise.resolve({
+ headers: { get: fetchResponseHeadersGet },
+ arrayBuffer: fetchResponseArrayBuffer,
+ ok: true
+ }));
corsResponse = {
set: vi.fn(() => {}),
@@ -53,7 +83,7 @@ describe("server_functions tests", () => {
};
request = {
- url: "/cors?url=www.test.com"
+ url: "/cors?url=http://www.test.com"
};
});
@@ -63,8 +93,8 @@ describe("server_functions tests", () => {
await cors(request, corsResponse);
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][0]).toBe(urlToCall);
+ expect(fetchSpy.mock.calls).toHaveLength(1);
+ expect(fetchSpy.mock.calls[0][0]).toBe(urlToCall);
});
it("Forwards Content-Type if json", async () => {
@@ -126,9 +156,9 @@ describe("server_functions tests", () => {
it("Fetches with user agent by default", async () => {
await cors(request, corsResponse);
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][1]).toHaveProperty("headers");
- expect(fetchMock.mock.calls[0][1].headers).toHaveProperty("User-Agent");
+ expect(fetchSpy.mock.calls).toHaveLength(1);
+ expect(fetchSpy.mock.calls[0][1]).toHaveProperty("headers");
+ expect(fetchSpy.mock.calls[0][1].headers).toHaveProperty("User-Agent");
});
it("Fetches with specified headers", async () => {
@@ -138,10 +168,10 @@ describe("server_functions tests", () => {
await cors(request, corsResponse);
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][1]).toHaveProperty("headers");
- expect(fetchMock.mock.calls[0][1].headers).toHaveProperty("header1", "value1");
- expect(fetchMock.mock.calls[0][1].headers).toHaveProperty("header2", "value2");
+ expect(fetchSpy.mock.calls).toHaveLength(1);
+ expect(fetchSpy.mock.calls[0][1]).toHaveProperty("headers");
+ expect(fetchSpy.mock.calls[0][1].headers).toHaveProperty("header1", "value1");
+ expect(fetchSpy.mock.calls[0][1].headers).toHaveProperty("header2", "value2");
});
it("Sends specified headers", async () => {
@@ -153,8 +183,8 @@ describe("server_functions tests", () => {
await cors(request, corsResponse);
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][1]).toHaveProperty("headers");
+ expect(fetchSpy.mock.calls).toHaveLength(1);
+ expect(fetchSpy.mock.calls[0][1]).toHaveProperty("headers");
expect(corsResponse.set.mock.calls).toHaveLength(3);
expect(corsResponse.set.mock.calls[0][0]).toBe("Content-Type");
expect(corsResponse.set.mock.calls[1][0]).toBe("header1");
@@ -182,4 +212,93 @@ describe("server_functions tests", () => {
global.config = previousConfig;
});
});
+
+ describe("The cors method blocks SSRF (DNS rebinding safe)", () => {
+ let response;
+
+ beforeEach(() => {
+ response = {
+ set: vi.fn(),
+ send: vi.fn(),
+ status: vi.fn(function () { return this; }),
+ json: vi.fn()
+ };
+ });
+
+ it("Blocks localhost hostname without DNS", async () => {
+ await cors({ url: "/cors?url=http://localhost/path" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ expect(response.json).toHaveBeenCalledWith({ error: "Forbidden: private or reserved addresses are not allowed" });
+ });
+
+ it("Blocks non-http protocols", async () => {
+ await cors({ url: "/cors?url=ftp://example.com/file" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ });
+
+ it("Blocks invalid URLs", async () => {
+ await cors({ url: "/cors?url=not_a_valid_url" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ });
+
+ it("Blocks loopback addresses (127.0.0.1)", async () => {
+ vi.spyOn(dns.promises, "lookup").mockResolvedValue({ address: "127.0.0.1", family: 4 });
+ await cors({ url: "/cors?url=http://example.com/" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ });
+
+ it("Blocks RFC 1918 private addresses (192.168.x.x)", async () => {
+ vi.spyOn(dns.promises, "lookup").mockResolvedValue({ address: "192.168.1.1", family: 4 });
+ await cors({ url: "/cors?url=http://example.com/" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ });
+
+ it("Blocks link-local / cloud metadata addresses (169.254.169.254)", async () => {
+ vi.spyOn(dns.promises, "lookup").mockResolvedValue({ address: "169.254.169.254", family: 4 });
+ await cors({ url: "/cors?url=http://example.com/" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ });
+
+ it("Allows public unicast addresses", async () => {
+ vi.spyOn(dns.promises, "lookup").mockResolvedValue({ address: "93.184.216.34", family: 4 });
+ vi.spyOn(global, "fetch").mockResolvedValue({
+ ok: true,
+ headers: { get: vi.fn() },
+ arrayBuffer: vi.fn(() => new ArrayBuffer(0))
+ });
+ await cors({ url: "/cors?url=http://example.com/" }, response);
+ expect(response.status).not.toHaveBeenCalledWith(403);
+ });
+ });
+
+ describe("cors method with allowWhitelist", () => {
+ let response;
+
+ beforeEach(() => {
+ response = {
+ set: vi.fn(),
+ send: vi.fn(),
+ status: vi.fn(function () { return this; }),
+ json: vi.fn()
+ };
+ vi.spyOn(dns.promises, "lookup").mockResolvedValue({ address: "93.184.216.34", family: 4 });
+ vi.spyOn(global, "fetch").mockResolvedValue({
+ ok: true,
+ headers: { get: vi.fn() },
+ arrayBuffer: vi.fn(() => new ArrayBuffer(0))
+ });
+ });
+
+ it("Blocks domains not in whitelist", async () => {
+ global.config = { cors: "allowWhitelist", corsDomainWhitelist: [] };
+ await cors({ url: "/cors?url=http://example.com/api" }, response);
+ expect(response.status).toHaveBeenCalledWith(403);
+ });
+
+ it("Allows domains in whitelist", async () => {
+ global.config = { cors: "allowWhitelist", corsDomainWhitelist: ["example.com"] };
+ await cors({ url: "/cors?url=http://example.com/api" }, response);
+ expect(response.status).not.toHaveBeenCalledWith(403);
+ });
+ });
});
diff --git a/tests/unit/functions/updatenotification_spec.js b/tests/unit/functions/updatenotification_spec.js
index f6617e4bf7..c5d29c570b 100644
--- a/tests/unit/functions/updatenotification_spec.js
+++ b/tests/unit/functions/updatenotification_spec.js
@@ -4,10 +4,10 @@ import { vi, describe, beforeEach, afterEach, it, expect } from "vitest";
* Creates a fresh GitHelper instance with isolated mocks for each test run.
* @param {{ current: import("vitest").Mock | null }} fsStatSyncMockRef reference to the mocked fs.statSync.
* @param {{ current: { error: import("vitest").Mock; info: import("vitest").Mock } | null }} loggerMockRef reference to logger stubs.
- * @param {{ current: import("vitest").MockInstance | null }} execShellSpyRef reference to the execShell spy.
+ * @param {{ current: import("vitest").MockInstance | null }} execGitSpyRef reference to the execGit spy.
* @returns {Promise} resolved GitHelper instance.
*/
-async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execShellSpyRef) {
+async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execGitSpyRef) {
vi.resetModules();
fsStatSyncMockRef.current = vi.fn();
@@ -20,10 +20,10 @@ async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execShellSpyRe
vi.doMock("logger", () => loggerMockRef.current);
const defaults = await import("../../../js/defaults");
- const gitHelperModule = await import(`../../../${defaults.defaultModulesDir}/updatenotification/git_helper`);
+ const gitHelperModule = await import(`../../../${defaults.defaultModulesDir}/updatenotification/git_helper.js`);
const GitHelper = gitHelperModule.default || gitHelperModule;
const instance = new GitHelper();
- execShellSpyRef.current = vi.spyOn(instance, "execShell");
+ execGitSpyRef.current = vi.spyOn(instance, "execGit");
instance.__loggerMock = loggerMockRef.current;
return instance;
}
@@ -31,7 +31,7 @@ async function createGitHelper (fsStatSyncMockRef, loggerMockRef, execShellSpyRe
describe("Updatenotification", () => {
const fsStatSyncMockRef = { current: null };
const loggerMockRef = { current: null };
- const execShellSpyRef = { current: null };
+ const execGitSpyRef = { current: null };
let gitHelper;
let gitRemoteOut;
@@ -43,10 +43,10 @@ describe("Updatenotification", () => {
let gitFetchErr;
let gitTagListOut;
- const getExecutedCommands = () => execShellSpyRef.current.mock.calls.map(([command]) => command);
+ const getExecutedCommands = () => execGitSpyRef.current.mock.calls.map((call) => call.slice(1).join(" "));
beforeEach(async () => {
- gitHelper = await createGitHelper(fsStatSyncMockRef, loggerMockRef, execShellSpyRef);
+ gitHelper = await createGitHelper(fsStatSyncMockRef, loggerMockRef, execGitSpyRef);
fsStatSyncMockRef.current.mockReturnValue({ isDirectory: () => true });
@@ -59,40 +59,42 @@ describe("Updatenotification", () => {
gitFetchErr = "";
gitTagListOut = "";
- execShellSpyRef.current.mockImplementation((command) => {
- if (command.includes("git remote -v")) {
+ execGitSpyRef.current.mockImplementation((_folder, ...args) => {
+ const command = args.join(" ");
+
+ if (command === "remote -v") {
return Promise.resolve({ stdout: gitRemoteOut, stderr: "" });
}
- if (command.includes("git rev-parse HEAD")) {
+ if (command === "rev-parse HEAD") {
return Promise.resolve({ stdout: gitRevParseOut, stderr: "" });
}
- if (command.includes("git status -sb")) {
+ if (command === "status -sb") {
return Promise.resolve({ stdout: gitStatusOut, stderr: "" });
}
- if (command.includes("git fetch -n --dry-run")) {
+ if (command === "fetch -n --dry-run") {
return Promise.resolve({ stdout: gitFetchOut, stderr: gitFetchErr });
}
- if (command.includes("git rev-list --ancestry-path --count")) {
+ if (command.startsWith("rev-list --ancestry-path --count ")) {
return Promise.resolve({ stdout: gitRevListCountOut, stderr: "" });
}
- if (command.includes("git rev-list --ancestry-path")) {
+ if (command.startsWith("rev-list --ancestry-path ")) {
return Promise.resolve({ stdout: gitRevListOut, stderr: "" });
}
- if (command.includes("git ls-remote -q --tags --refs")) {
+ if (command === "ls-remote -q --tags --refs") {
return Promise.resolve({ stdout: gitTagListOut, stderr: "" });
}
return Promise.resolve({ stdout: "", stderr: "" });
});
- if (gitHelper.execShell !== execShellSpyRef.current) {
- throw new Error("execShell spy not applied");
+ if (gitHelper.execGit !== execGitSpyRef.current) {
+ throw new Error("execGit spy not applied");
}
});
@@ -119,10 +121,10 @@ describe("Updatenotification", () => {
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
[
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 develop",
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 develop",
]
`);
});
@@ -134,20 +136,20 @@ describe("Updatenotification", () => {
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
[
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
+ "rev-parse HEAD",
+ "status -sb",
]
`);
});
it("excludes repo if status can't be retrieved", async () => {
const errorMessage = "Failed to retrieve status";
- execShellSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
+ execGitSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
expect(gitHelper.gitRepos).toHaveLength(1);
const repos = await gitHelper.getRepos();
expect(repos).toHaveLength(0);
- expect(execShellSpyRef.current.mock.calls.length).toBeGreaterThan(0);
+ expect(execGitSpyRef.current.mock.calls.length).toBeGreaterThan(0);
});
});
@@ -169,12 +171,12 @@ describe("Updatenotification", () => {
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
[
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 master",
- "cd mock-path && git ls-remote -q --tags --refs",
- "cd mock-path && git rev-list --ancestry-path 60e0377..332e429 master",
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 master",
+ "ls-remote -q --tags --refs",
+ "rev-list --ancestry-path 60e0377..332e429 master",
]
`);
});
@@ -185,20 +187,20 @@ describe("Updatenotification", () => {
const repos = await gitHelper.getRepos();
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
- [
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 master",
- "cd mock-path && git ls-remote -q --tags --refs",
- "cd mock-path && git rev-list --ancestry-path 60e0377..332e429 master",
- ]
- `);
+ [
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 master",
+ "ls-remote -q --tags --refs",
+ "rev-list --ancestry-path 60e0377..332e429 master",
+ ]
+ `);
});
it("excludes repo if status can't be retrieved", async () => {
const errorMessage = "Failed to retrieve status";
- execShellSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
+ execGitSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
const repos = await gitHelper.getRepos();
expect(repos).toHaveLength(0);
@@ -224,15 +226,15 @@ describe("Updatenotification", () => {
const repos = await gitHelper.getRepos();
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
- [
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 master",
- "cd mock-path && git ls-remote -q --tags --refs",
- "cd mock-path && git rev-list --ancestry-path 60e0377..332e429 master",
- ]
- `);
+ [
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 master",
+ "ls-remote -q --tags --refs",
+ "rev-list --ancestry-path 60e0377..332e429 master",
+ ]
+ `);
});
it("returns status information early if isBehindInStatus", async () => {
@@ -241,20 +243,20 @@ describe("Updatenotification", () => {
const repos = await gitHelper.getRepos();
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
- [
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 master",
- "cd mock-path && git ls-remote -q --tags --refs",
- "cd mock-path && git rev-list --ancestry-path 60e0377..332e429 master",
- ]
- `);
+ [
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 master",
+ "ls-remote -q --tags --refs",
+ "rev-list --ancestry-path 60e0377..332e429 master",
+ ]
+ `);
});
it("excludes repo if status can't be retrieved", async () => {
const errorMessage = "Failed to retrieve status";
- execShellSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
+ execGitSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
const repos = await gitHelper.getRepos();
expect(repos).toHaveLength(0);
@@ -280,15 +282,15 @@ describe("Updatenotification", () => {
const repos = await gitHelper.getRepos();
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
- [
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 master",
- "cd mock-path && git ls-remote -q --tags --refs",
- "cd mock-path && git rev-list --ancestry-path 60e0377..332e429 master",
- ]
- `);
+ [
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 master",
+ "ls-remote -q --tags --refs",
+ "rev-list --ancestry-path 60e0377..332e429 master",
+ ]
+ `);
});
it("returns status information early if isBehindInStatus", async () => {
@@ -297,20 +299,20 @@ describe("Updatenotification", () => {
const repos = await gitHelper.getRepos();
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
- [
- "cd mock-path && git rev-parse HEAD",
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 60e0377..332e429 master",
- "cd mock-path && git ls-remote -q --tags --refs",
- "cd mock-path && git rev-list --ancestry-path 60e0377..332e429 master",
- ]
- `);
+ [
+ "rev-parse HEAD",
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 60e0377..332e429 master",
+ "ls-remote -q --tags --refs",
+ "rev-list --ancestry-path 60e0377..332e429 master",
+ ]
+ `);
});
it("excludes repo if status can't be retrieved", async () => {
const errorMessage = "Failed to retrieve status";
- execShellSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
+ execGitSpyRef.current.mockImplementationOnce(() => Promise.reject(new Error(errorMessage)));
const repos = await gitHelper.getRepos();
expect(repos).toHaveLength(0);
@@ -334,12 +336,12 @@ describe("Updatenotification", () => {
const repos = await gitHelper.getRepos();
expect(repos[0]).toMatchSnapshot();
expect(getExecutedCommands()).toMatchInlineSnapshot(`
- [
- "cd mock-path && git status -sb",
- "cd mock-path && git fetch -n --dry-run",
- "cd mock-path && git rev-list --ancestry-path --count 19f7faf..9d83101 master",
- ]
- `);
+ [
+ "status -sb",
+ "fetch -n --dry-run",
+ "rev-list --ancestry-path --count 19f7faf..9d83101 master",
+ ]
+ `);
});
});
});
diff --git a/tests/unit/modules/default/weather/node_helper_spec.js b/tests/unit/modules/default/weather/node_helper_spec.js
new file mode 100644
index 0000000000..2f18e9654a
--- /dev/null
+++ b/tests/unit/modules/default/weather/node_helper_spec.js
@@ -0,0 +1,116 @@
+import Module from "node:module";
+import { afterEach, describe, expect, it, vi } from "vitest";
+
+/**
+ * Creates a fresh weather node helper instance with isolated mocks.
+ * @returns {Promise} The mocked weather node helper.
+ */
+async function loadWeatherNodeHelper () {
+ vi.resetModules();
+
+ const loggerMock = {
+ log: vi.fn(),
+ warn: vi.fn(),
+ error: vi.fn()
+ };
+ const originalRequire = Module.prototype.require;
+
+ Module.prototype.require = function (id) {
+ if (id === "node_helper") {
+ return {
+ create: vi.fn((definition) => definition)
+ };
+ }
+
+ if (id === "logger") {
+ return loggerMock;
+ }
+
+ return originalRequire.apply(this, arguments);
+ };
+
+ let helper;
+ try {
+ const helperModule = await import("../../../../../defaultmodules/weather/node_helper");
+ helper = helperModule.default || helperModule;
+ } finally {
+ Module.prototype.require = originalRequire;
+ }
+
+ helper.providers = {};
+ helper.lastData = {};
+ helper.sendSocketNotification = vi.fn();
+
+ return helper;
+}
+
+afterEach(() => {
+ vi.resetAllMocks();
+ vi.resetModules();
+});
+
+describe("weather node_helper reconnect handling", () => {
+ it("re-sends cached weather data when a client reconnects", async () => {
+ const helper = await loadWeatherNodeHelper();
+ const instanceId = "weather-current";
+ const cachedPayload = {
+ instanceId,
+ type: "current",
+ data: { temperature: 8.5 }
+ };
+
+ helper.providers[instanceId] = { locationName: "Munich, BY" };
+ helper.lastData[instanceId] = cachedPayload;
+
+ await helper.initWeatherProvider({
+ weatherProvider: "openmeteo",
+ instanceId,
+ type: "current"
+ });
+
+ expect(helper.sendSocketNotification).toHaveBeenNthCalledWith(1, "WEATHER_INITIALIZED", {
+ instanceId,
+ locationName: "Munich, BY"
+ });
+ expect(helper.sendSocketNotification).toHaveBeenNthCalledWith(2, "WEATHER_DATA", cachedPayload);
+ expect(helper.sendSocketNotification).toHaveBeenCalledTimes(2);
+ });
+
+ it("does not send WEATHER_DATA on reconnect when no cached payload exists", async () => {
+ const helper = await loadWeatherNodeHelper();
+ const instanceId = "weather-current";
+
+ helper.providers[instanceId] = { locationName: "Munich, BY" };
+
+ await helper.initWeatherProvider({
+ weatherProvider: "openmeteo",
+ instanceId,
+ type: "current"
+ });
+
+ expect(helper.sendSocketNotification).toHaveBeenCalledWith("WEATHER_INITIALIZED", {
+ instanceId,
+ locationName: "Munich, BY"
+ });
+ expect(helper.sendSocketNotification).toHaveBeenCalledTimes(1);
+ });
+
+ it("cleans up provider and cached data when stopping an instance", async () => {
+ const helper = await loadWeatherNodeHelper();
+ const instanceId = "weather-current";
+ const stop = vi.fn();
+
+ helper.providers[instanceId] = { stop };
+ helper.lastData[instanceId] = {
+ instanceId,
+ type: "current",
+ data: { temperature: 8.5 }
+ };
+
+ helper.stopWeatherProvider(instanceId);
+
+ expect(stop).toHaveBeenCalledTimes(1);
+ expect(helper.providers[instanceId]).toBeUndefined();
+ expect(helper.lastData[instanceId]).toBeUndefined();
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/openmeteo_spec.js b/tests/unit/modules/default/weather/providers/openmeteo_spec.js
index 0377a99013..225a970c88 100644
--- a/tests/unit/modules/default/weather/providers/openmeteo_spec.js
+++ b/tests/unit/modules/default/weather/providers/openmeteo_spec.js
@@ -144,12 +144,15 @@ describe("OpenMeteoProvider", () => {
provider.start();
const result = await dataPromise;
+ const currentHourUnix = Math.floor(currentData.current_weather.time / 3600) * 3600;
+ const currentHourIndex = currentData.hourly.time.findIndex((time) => time === currentHourUnix);
expect(result).toBeDefined();
expect(result.temperature).toBe(8.5);
expect(result.windSpeed).toBeCloseTo(4.7, 1);
expect(result.windFromDirection).toBe(9);
- expect(result.humidity).toBe(83);
+ expect(result.humidity).toBe(currentData.hourly.relativehumidity_2m[currentHourIndex]);
+ expect(result.humidity).not.toBe(currentData.hourly.relativehumidity_2m[0]);
});
it("should include sunrise and sunset from daily data", async () => {
diff --git a/tests/unit/modules/default/weather/providers/openweathermap_spec.js b/tests/unit/modules/default/weather/providers/openweathermap_spec.js
index 7b27fd711f..d5b92ed6d6 100644
--- a/tests/unit/modules/default/weather/providers/openweathermap_spec.js
+++ b/tests/unit/modules/default/weather/providers/openweathermap_spec.js
@@ -8,6 +8,8 @@ import { setupServer } from "msw/node";
import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
import onecallData from "../../../../../mocks/weather_owm_onecall.json" with { type: "json" };
+import currentData from "../../../../../mocks/weather_owm_current.json" with { type: "json" };
+import forecastData from "../../../../../mocks/weather_owm_forecast.json" with { type: "json" };
let server;
@@ -232,4 +234,321 @@ describe("OpenWeatherMapProvider", () => {
expect(provider.locationName).toBe("America/New_York");
});
});
+
+ describe("API v2.5 - Current Weather (/weather endpoint)", () => {
+ it("should parse current weather from /weather endpoint", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/weather",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/weather", () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.temperature).toBe(-0.27);
+ expect(result.feelsLikeTemp).toBe(-3.9);
+ expect(result.humidity).toBe(54);
+ expect(result.windSpeed).toBe(3.09);
+ expect(result.windFromDirection).toBe(220);
+ expect(result.weatherType).toBe("cloudy-windy");
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should set location name from city name and country", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/weather",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/weather", () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ await dataPromise;
+
+ expect(provider.locationName).toBe("Munich, DE");
+ });
+ });
+
+ describe("API v2.5 - Forecast (/forecast endpoint)", () => {
+ it("should parse /forecast endpoint into daily grouped forecast", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(2);
+ });
+
+ it("should correctly aggregate min/max temperatures per day", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Day 1: temp_min values: -1.5, -1.5, -1.0, 0.5, 1.5, 1.0, 0.5, -0.5 → min=-1.5
+ expect(result[0].minTemperature).toBe(-1.5);
+ // Day 1: temp_max values: -0.5, -0.9, 0.0, 1.5, 2.5, 2.0, 1.2, 0.1 → max=2.5
+ expect(result[0].maxTemperature).toBe(2.5);
+ // Day 2: temp_min values: 0.0, 0.5, 1.5, 3.0, 4.5, 4.0, 2.5, 1.0 → min=0.0
+ expect(result[1].minTemperature).toBe(0.0);
+ // Day 2: temp_max values: 1.0, 1.5, 2.5, 4.0, 5.5, 5.0, 3.5, 2.0 → max=5.5
+ expect(result[1].maxTemperature).toBe(5.5);
+ });
+
+ it("should pick daytime weather type (8-17h)", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Day 1 daytime entries have icon "10d" → "rain"
+ expect(result[0].weatherType).toBe("rain");
+ // Day 2 daytime entries have icon "09d" → "showers"
+ expect(result[1].weatherType).toBe("showers");
+ });
+
+ it("should accumulate precipitation per day", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Day 1: two rain entries of 0.6 each = 1.2
+ expect(result[0].rain).toBeCloseTo(1.2);
+ expect(result[0].precipitationAmount).toBeCloseTo(1.2);
+ // Day 2: one snow entry of 0.5
+ expect(result[1].snow).toBeCloseTo(0.5);
+ expect(result[1].precipitationAmount).toBeCloseTo(0.5);
+ });
+
+ it("should set location name from city in forecast response", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ await dataPromise;
+
+ expect(provider.locationName).toBe("Munich, DE");
+ });
+ });
+
+ describe("API v2.5 - Hourly (/forecast endpoint with type hourly)", () => {
+ it("should return individual 3h entries instead of aggregating", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(forecastData.list.length);
+ });
+
+ it("should map temperature and wind from each 3h slot", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result[0].temperature).toBe(forecastData.list[0].main.temp);
+ expect(result[0].windSpeed).toBe(forecastData.list[0].wind.speed);
+ expect(result[0].precipitationProbability).toBe(forecastData.list[0].pop * 100);
+ });
+
+ it("should include precipitation when present in a slot", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ apiVersion: "2.5",
+ weatherEndpoint: "/forecast",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/2.5/forecast", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Entry at index 3 has rain: { "3h": 0.6 }
+ expect(result[3].rain).toBe(0.6);
+ expect(result[3].precipitationAmount).toBe(0.6);
+ // Entry at index 11 has snow: { "3h": 0.5 }
+ expect(result[11].snow).toBe(0.5);
+ expect(result[11].precipitationAmount).toBe(0.5);
+ });
+ });
});
diff --git a/tests/unit/modules/default/weather/providers/smhi_spec.js b/tests/unit/modules/default/weather/providers/smhi_spec.js
index b7e1211785..de5eb04ea4 100644
--- a/tests/unit/modules/default/weather/providers/smhi_spec.js
+++ b/tests/unit/modules/default/weather/providers/smhi_spec.js
@@ -3,6 +3,8 @@
*
* Tests data parsing for current, forecast, and hourly weather types.
* SMHI provides data only for Sweden, uses metric system.
+ *
+ * Fixture: weather_smhi.json uses SNOW1gv1 format (replaced PMP3gv2 2026-03-31)
*/
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
@@ -123,11 +125,10 @@ describe("SMHIProvider", () => {
provider.setCallbacks(resolve, vi.fn());
});
- // Use data with rain (pcat=3 at index 2)
+ // Use entry at index 2 which has ptype=5 (snow) but pmedian=0.0
const rainData = JSON.parse(JSON.stringify(smhiData));
- // Make the rain entry the closest to "now"
rainData.timeSeries = [rainData.timeSeries[2]];
- rainData.timeSeries[0].validTime = new Date().toISOString();
+ rainData.timeSeries[0].time = new Date().toISOString();
server.use(
http.get("https://opendata-download-metfcst.smhi.se/*", () => {
@@ -140,7 +141,8 @@ describe("SMHIProvider", () => {
const result = await dataPromise;
- expect(result.rain).toBe(0.0); // pmedian value with pcat=3 (rain)
+ // pmedian is 0.0 at this entry, so all precipitation amounts are 0
+ expect(result.rain).toBe(0);
expect(result.precipitationAmount).toBe(0.0);
expect(result.snow).toBe(0);
});
diff --git a/tests/unit/modules/default/weather/providers/weatherapi_spec.js b/tests/unit/modules/default/weather/providers/weatherapi_spec.js
index 413360f61c..e53713cc65 100644
--- a/tests/unit/modules/default/weather/providers/weatherapi_spec.js
+++ b/tests/unit/modules/default/weather/providers/weatherapi_spec.js
@@ -240,6 +240,7 @@ describe("WeatherAPIProvider", () => {
expect(result[0].minTemperature).toBe(-8);
expect(result[0].maxTemperature).toBe(-1);
expect(result[0].weatherType).toBe("day-sprinkle");
+ expect(result[0].uvIndex).toBe(1);
expect(result[0].sunrise).toBeInstanceOf(Date);
expect(result[0].sunset).toBeInstanceOf(Date);
});
@@ -275,6 +276,7 @@ describe("WeatherAPIProvider", () => {
expect(result[0].humidity).toBe(85);
expect(result[0].windFromDirection).toBe(210);
expect(result[0].weatherType).toBe("night-sprinkle");
+ expect(result[0].uvIndex).toBe(0);
expect(result[0].precipitationProbability).toBe(50);
});
});
diff --git a/tests/unit/modules/default/weather/providers/weatherflow_spec.js b/tests/unit/modules/default/weather/providers/weatherflow_spec.js
index 2eb2fdb4a4..f6b28cadcb 100644
--- a/tests/unit/modules/default/weather/providers/weatherflow_spec.js
+++ b/tests/unit/modules/default/weather/providers/weatherflow_spec.js
@@ -85,6 +85,9 @@ describe("WeatherFlowProvider", () => {
expect(result).toBeDefined();
expect(result.temperature).toBe(16);
expect(result.humidity).toBe(28);
+ expect(result.precipitationAmount).toBe(0);
+ expect(result.precipitationUnits).toBe("mm");
+ expect(result.precipitationProbability).toBe(0);
expect(result.weatherType).not.toBeNull();
});
diff --git a/tests/unit/modules/default/weather/providers/yr_spec.js b/tests/unit/modules/default/weather/providers/yr_spec.js
index 4602a8d840..64598f2503 100644
--- a/tests/unit/modules/default/weather/providers/yr_spec.js
+++ b/tests/unit/modules/default/weather/providers/yr_spec.js
@@ -15,7 +15,6 @@ import { describe, it, expect, vi, beforeAll, beforeEach, afterAll, afterEach }
import yrData from "../../../../../mocks/weather_yr.json" with { type: "json" };
const YR_FORECAST_URL = "https://api.met.no/weatherapi/locationforecast/**";
-const YR_SUNRISE_URL = "https://api.met.no/weatherapi/sunrise/**";
// Fixed time: 30 minutes after the first timeseries entry (2026-02-06T21:00:00Z)
// This ensures timeseries[0] is always chosen as the closest past entry.